From bd92062269997a882e6214360da21307fc0bae9b Mon Sep 17 00:00:00 2001 From: Daniel King Date: Sun, 15 May 2016 19:56:20 -0300 Subject: [PATCH] Add ChaCha20 to the Cipher module --- include/mbedtls/chacha20.h | 2 +- include/mbedtls/cipher.h | 4 +- library/chacha20.c | 4 +- library/cipher.c | 31 ++++++ library/cipher_wrap.c | 73 ++++++++++++ tests/CMakeLists.txt | 1 + tests/Makefile | 9 ++ tests/suites/test_suite_cipher.chacha20.data | 111 +++++++++++++++++++ 8 files changed, 231 insertions(+), 4 deletions(-) create mode 100644 tests/suites/test_suite_cipher.chacha20.data diff --git a/include/mbedtls/chacha20.h b/include/mbedtls/chacha20.h index ab10a96a8..d23618ee0 100644 --- a/include/mbedtls/chacha20.h +++ b/include/mbedtls/chacha20.h @@ -121,7 +121,7 @@ int mbedtls_chacha20_starts( mbedtls_chacha20_context* ctx, * output pointers are NULL. * Otherwise, 0 is returned to indicate success. */ -int mbedtls_chacha20_process( mbedtls_chacha20_context *ctx, +int mbedtls_chacha20_update( mbedtls_chacha20_context *ctx, size_t size, const unsigned char *input, unsigned char *output ); diff --git a/include/mbedtls/cipher.h b/include/mbedtls/cipher.h index 3ee2ab7db..c5a50c0d2 100644 --- a/include/mbedtls/cipher.h +++ b/include/mbedtls/cipher.h @@ -86,6 +86,7 @@ typedef enum { MBEDTLS_CIPHER_ID_CAMELLIA, /**< The Camellia cipher. */ MBEDTLS_CIPHER_ID_BLOWFISH, /**< The Blowfish cipher. */ MBEDTLS_CIPHER_ID_ARC4, /**< The RC4 cipher. */ + MBEDTLS_CIPHER_ID_CHACHA20, /**< The Chacha20 cipher. */ } mbedtls_cipher_id_t; /** @@ -145,6 +146,7 @@ typedef enum { MBEDTLS_CIPHER_CAMELLIA_128_CCM, /**< Camellia cipher with 128-bit CCM mode. */ MBEDTLS_CIPHER_CAMELLIA_192_CCM, /**< Camellia cipher with 192-bit CCM mode. */ MBEDTLS_CIPHER_CAMELLIA_256_CCM, /**< Camellia cipher with 256-bit CCM mode. */ + MBEDTLS_CIPHER_CHACHA20, /**< Chacha20 stream cipher. */ } mbedtls_cipher_type_t; /** Supported cipher modes. */ @@ -190,7 +192,7 @@ enum { /** Maximum length of any IV, in Bytes. */ #define MBEDTLS_MAX_IV_LENGTH 16 /** Maximum block size of any cipher, in Bytes. */ -#define MBEDTLS_MAX_BLOCK_LENGTH 16 +#define MBEDTLS_MAX_BLOCK_LENGTH 64 /** * Base cipher information (opaque struct). diff --git a/library/chacha20.c b/library/chacha20.c index 75fd9e915..8206a3bf0 100644 --- a/library/chacha20.c +++ b/library/chacha20.c @@ -245,7 +245,7 @@ int mbedtls_chacha20_starts( mbedtls_chacha20_context* ctx, return( 0 ); } -int mbedtls_chacha20_process( mbedtls_chacha20_context *ctx, +int mbedtls_chacha20_update( mbedtls_chacha20_context *ctx, size_t size, const unsigned char *input, unsigned char *output ) @@ -333,7 +333,7 @@ int mbedtls_chacha20_crypt( const unsigned char key[32], if ( result != 0 ) goto cleanup; - result = mbedtls_chacha20_process( &ctx, data_len, input, output ); + result = mbedtls_chacha20_update( &ctx, data_len, input, output ); cleanup: mbedtls_chacha20_free( &ctx ); diff --git a/library/cipher.c b/library/cipher.c index a5cd61cdf..68d0c10ff 100644 --- a/library/cipher.c +++ b/library/cipher.c @@ -46,6 +46,10 @@ #include "mbedtls/ccm.h" #endif +#if defined(MBEDTLS_CHACHA20_C) +#include "mbedtls/chacha20.h" +#endif + #if defined(MBEDTLS_CMAC_C) #include "mbedtls/cmac.h" #endif @@ -231,6 +235,18 @@ int mbedtls_cipher_set_iv( mbedtls_cipher_context_t *ctx, return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); } +#if defined(MBEDTLS_CHACHA20_C) + if ( ctx->cipher_info->type == MBEDTLS_CIPHER_CHACHA20 ) + { + if ( 0 != mbedtls_chacha20_starts( (mbedtls_chacha20_context*)ctx->cipher_ctx, + iv, + 0U ) ) /* Initial counter value */ + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + } +#endif + memcpy( ctx->iv, iv, actual_iv_size ); ctx->iv_size = actual_iv_size; @@ -314,6 +330,16 @@ int mbedtls_cipher_update( mbedtls_cipher_context_t *ctx, const unsigned char *i return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); } + +#if defined(MBEDTLS_CHACHA20_C) + if ( ctx->cipher_info->type == MBEDTLS_CIPHER_CHACHA20 ) + { + *olen = ilen; + return mbedtls_chacha20_update( (mbedtls_chacha20_context*) ctx->cipher_ctx, + ilen, input, output ); + } +#endif + #if defined(MBEDTLS_CIPHER_MODE_CBC) if( ctx->cipher_info->mode == MBEDTLS_MODE_CBC ) { @@ -646,6 +672,11 @@ int mbedtls_cipher_finish( mbedtls_cipher_context_t *ctx, return( 0 ); } + if ( MBEDTLS_CIPHER_CHACHA20 == ctx->cipher_info->type ) + { + return( 0 ); + } + if( MBEDTLS_MODE_ECB == ctx->cipher_info->mode ) { if( ctx->unprocessed_len != 0 ) diff --git a/library/cipher_wrap.c b/library/cipher_wrap.c index dc76af8ff..f4e7964df 100644 --- a/library/cipher_wrap.c +++ b/library/cipher_wrap.c @@ -53,6 +53,10 @@ #include "mbedtls/blowfish.h" #endif +#if defined(MBEDTLS_CHACHA20_C) +#include "mbedtls/chacha20.h" +#endif + #if defined(MBEDTLS_GCM_C) #include "mbedtls/gcm.h" #endif @@ -1283,6 +1287,71 @@ static const mbedtls_cipher_info_t arc4_128_info = { }; #endif /* MBEDTLS_ARC4_C */ +#if defined(MBEDTLS_CHACHA20_C) + +static int chacha20_setkey_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + if( key_bitlen != 256U ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + if ( 0 != mbedtls_chacha20_setkey( (mbedtls_chacha20_context*)ctx, key ) ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + return( 0 ); +} + +static void * chacha20_ctx_alloc( void ) +{ + mbedtls_chacha20_context *ctx; + ctx = mbedtls_calloc( 1, sizeof( mbedtls_chacha20_context ) ); + + if( ctx == NULL ) + return( NULL ); + + mbedtls_chacha20_init( ctx ); + + return( ctx ); +} + +static void chacha20_ctx_free( void *ctx ) +{ + mbedtls_chacha20_free( (mbedtls_chacha20_context *) ctx ); + mbedtls_free( ctx ); +} + +static const mbedtls_cipher_base_t chacha20_base_info = { + MBEDTLS_CIPHER_ID_CHACHA20, + NULL, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + NULL, +#endif + chacha20_setkey_wrap, + chacha20_setkey_wrap, + chacha20_ctx_alloc, + chacha20_ctx_free +}; +static const mbedtls_cipher_info_t chacha20_info = { + MBEDTLS_CIPHER_CHACHA20, + MBEDTLS_MODE_NONE, + 256, + "CHACHA20", + 12, + 0, + 64, + &chacha20_base_info +}; +#endif /* MBEDTLS_CHACHA20_C */ + #if defined(MBEDTLS_CIPHER_NULL_CIPHER) static int null_crypt_stream( void *ctx, size_t length, const unsigned char *input, @@ -1438,6 +1507,10 @@ const mbedtls_cipher_definition_t mbedtls_cipher_definitions[] = #endif #endif /* MBEDTLS_DES_C */ +#if defined(MBEDTLS_CHACHA20_C) + { MBEDTLS_CIPHER_CHACHA20, &chacha20_info }, +#endif + #if defined(MBEDTLS_CIPHER_NULL_CIPHER) { MBEDTLS_CIPHER_NULL, &null_cipher_info }, #endif /* MBEDTLS_CIPHER_NULL_CIPHER */ diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 1525bc2a3..3821657ae 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -60,6 +60,7 @@ add_test_suite(cipher cipher.arc4) add_test_suite(cipher cipher.blowfish) add_test_suite(cipher cipher.camellia) add_test_suite(cipher cipher.ccm) +add_test_suite(cipher cipher.chacha20) add_test_suite(cipher cipher.des) add_test_suite(cipher cipher.gcm) add_test_suite(cipher cipher.null) diff --git a/tests/Makefile b/tests/Makefile index 233259b7a..34a0a8915 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -53,6 +53,7 @@ APPS = test_suite_aes.ecb$(EXEXT) test_suite_aes.cbc$(EXEXT) \ test_suite_chacha20$(EXEXT) test_suite_cmac$(EXEXT) \ test_suite_cipher.aes$(EXEXT) \ test_suite_cipher.arc4$(EXEXT) test_suite_cipher.ccm$(EXEXT) \ + test_suite_cipher.chacha20$(EXEXT) \ test_suite_cipher.gcm$(EXEXT) \ test_suite_cipher.blowfish$(EXEXT) \ test_suite_cipher.camellia$(EXEXT) \ @@ -125,6 +126,10 @@ test_suite_cipher.ccm.c : suites/test_suite_cipher.function suites/test_suite_ci echo " Gen $@" perl scripts/generate_code.pl suites test_suite_cipher test_suite_cipher.ccm +test_suite_cipher.chacha20.c : suites/test_suite_cipher.function suites/test_suite_cipher.chacha20.data scripts/generate_code.pl suites/helpers.function suites/main_test.function + echo " Gen $@" + perl scripts/generate_code.pl suites test_suite_cipher test_suite_cipher.chacha20 + test_suite_cipher.gcm.c : suites/test_suite_cipher.function suites/test_suite_cipher.gcm.data scripts/generate_code.pl suites/helpers.function suites/main_test.function echo " Gen $@" perl scripts/generate_code.pl suites test_suite_cipher test_suite_cipher.gcm @@ -257,6 +262,10 @@ test_suite_cipher.ccm$(EXEXT): test_suite_cipher.ccm.c $(DEP) echo " CC $<" $(CC) $(LOCAL_CFLAGS) $(CFLAGS) $< $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ +test_suite_cipher.chacha20$(EXEXT): test_suite_cipher.chacha20.c $(DEP) + echo " CC $<" + $(CC) $(LOCAL_CFLAGS) $(CFLAGS) $< $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ + test_suite_cipher.gcm$(EXEXT): test_suite_cipher.gcm.c $(DEP) echo " CC $<" $(CC) $(LOCAL_CFLAGS) $(CFLAGS) $< $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ diff --git a/tests/suites/test_suite_cipher.chacha20.data b/tests/suites/test_suite_cipher.chacha20.data new file mode 100644 index 000000000..5f3e07d0b --- /dev/null +++ b/tests/suites/test_suite_cipher.chacha20.data @@ -0,0 +1,111 @@ +Decrypt empty buffer +depends_on:MBEDTLS_CHACHA20_C: +dec_empty_buf: + +ChaCha20 Encrypt and decrypt 0 bytes +depends_on:MBEDTLS_CHACHA20_C +enc_dec_buf:MBEDTLS_CIPHER_CHACHA20:"CHACHA20":256:0:-1 + +ChaCha20 Encrypt and decrypt 1 bytes +depends_on:MBEDTLS_CHACHA20_C +enc_dec_buf:MBEDTLS_CIPHER_CHACHA20:"CHACHA20":256:1:-1 + +ChaCha20 Encrypt and decrypt 2 bytes +depends_on:MBEDTLS_CHACHA20_C +enc_dec_buf:MBEDTLS_CIPHER_CHACHA20:"CHACHA20":256:2:-1 + +ChaCha20 Encrypt and decrypt 7 bytes +depends_on:MBEDTLS_CHACHA20_C +enc_dec_buf:MBEDTLS_CIPHER_CHACHA20:"CHACHA20":256:7:-1 + +ChaCha20 Encrypt and decrypt 8 bytes +depends_on:MBEDTLS_CHACHA20_C +enc_dec_buf:MBEDTLS_CIPHER_CHACHA20:"CHACHA20":256:8:-1 + +ChaCha20 Encrypt and decrypt 9 bytes +depends_on:MBEDTLS_CHACHA20_C +enc_dec_buf:MBEDTLS_CIPHER_CHACHA20:"CHACHA20":256:9:-1 + +ChaCha20 Encrypt and decrypt 15 bytes +depends_on:MBEDTLS_CHACHA20_C +enc_dec_buf:MBEDTLS_CIPHER_CHACHA20:"CHACHA20":256:15:-1 + +ChaCha20 Encrypt and decrypt 16 bytes +depends_on:MBEDTLS_CHACHA20_C +enc_dec_buf:MBEDTLS_CIPHER_CHACHA20:"CHACHA20":256:16:-1 + +ChaCha20 Encrypt and decrypt 17 bytes +depends_on:MBEDTLS_CHACHA20_C +enc_dec_buf:MBEDTLS_CIPHER_CHACHA20:"CHACHA20":256:17:-1 + +ChaCha20 Encrypt and decrypt 31 bytes +depends_on:MBEDTLS_CHACHA20_C +enc_dec_buf:MBEDTLS_CIPHER_CHACHA20:"CHACHA20":256:31:-1 + +ChaCha20 Encrypt and decrypt 32 bytes +depends_on:MBEDTLS_CHACHA20_C +enc_dec_buf:MBEDTLS_CIPHER_CHACHA20:"CHACHA20":256:32:-1 + +ChaCha20 Encrypt and decrypt 33 bytes +depends_on:MBEDTLS_CHACHA20_C +enc_dec_buf:MBEDTLS_CIPHER_CHACHA20:"CHACHA20":256:33:-1 + +ChaCha20 Encrypt and decrypt 47 bytes +depends_on:MBEDTLS_CHACHA20_C +enc_dec_buf:MBEDTLS_CIPHER_CHACHA20:"CHACHA20":256:47:-1 + +ChaCha20 Encrypt and decrypt 48 bytes +depends_on:MBEDTLS_CHACHA20_C +enc_dec_buf:MBEDTLS_CIPHER_CHACHA20:"CHACHA20":256:48:-1 + +ChaCha20 Encrypt and decrypt 49 bytes +depends_on:MBEDTLS_CHACHA20_C +enc_dec_buf:MBEDTLS_CIPHER_CHACHA20:"CHACHA20":256:49:-1 + +ChaCha20 Encrypt and decrypt 0 bytes in multiple parts 1 +depends_on:MBEDTLS_CHACHA20_C +enc_dec_buf_multipart:MBEDTLS_CIPHER_CHACHA20:256:0:0:-1:0:0:0:0 + +ChaCha20 Encrypt and decrypt 1 bytes in multiple parts 1 +depends_on:MBEDTLS_CHACHA20_C +enc_dec_buf_multipart:MBEDTLS_CIPHER_CHACHA20:256:1:0:-1:1:0:1:0 + +ChaCha20 Encrypt and decrypt 1 bytes in multiple parts 2 +depends_on:MBEDTLS_CHACHA20_C +enc_dec_buf_multipart:MBEDTLS_CIPHER_CHACHA20:256:0:1:-1:0:1:0:1 + +ChaCha20 Encrypt and decrypt 16 bytes in multiple parts 1 +depends_on:MBEDTLS_CHACHA20_C +enc_dec_buf_multipart:MBEDTLS_CIPHER_CHACHA20:256:16:0:-1:16:0:16:0 + +ChaCha20 Encrypt and decrypt 16 bytes in multiple parts 2 +depends_on:MBEDTLS_CHACHA20_C +enc_dec_buf_multipart:MBEDTLS_CIPHER_CHACHA20:256:0:16:-1:0:16:0:16 + +ChaCha20 Encrypt and decrypt 16 bytes in multiple parts 3 +depends_on:MBEDTLS_CHACHA20_C +enc_dec_buf_multipart:MBEDTLS_CIPHER_CHACHA20:256:1:15:-1:1:15:1:15 + +ChaCha20 Encrypt and decrypt 16 bytes in multiple parts 4 +depends_on:MBEDTLS_CHACHA20_C +enc_dec_buf_multipart:MBEDTLS_CIPHER_CHACHA20:256:15:1:-1:15:1:15:1 + +ChaCha20 Encrypt and decrypt 22 bytes in multiple parts 1 +depends_on:MBEDTLS_CHACHA20_C +enc_dec_buf_multipart:MBEDTLS_CIPHER_CHACHA20:256:15:7:-1:15:7:15:7 + +ChaCha20 Encrypt and decrypt 22 bytes in multiple parts 2 +depends_on:MBEDTLS_CHACHA20_C +enc_dec_buf_multipart:MBEDTLS_CIPHER_CHACHA20:256:7:15:-1:7:15:7:15 + +ChaCha20 Encrypt and decrypt 22 bytes in multiple parts 3 +depends_on:MBEDTLS_CHACHA20_C +enc_dec_buf_multipart:MBEDTLS_CIPHER_CHACHA20:256:16:6:-1:16:6:16:6 + +ChaCha20 Encrypt and decrypt 22 bytes in multiple parts 4 +depends_on:MBEDTLS_CHACHA20_C +enc_dec_buf_multipart:MBEDTLS_CIPHER_CHACHA20:256:6:16:-1:6:16:6:16 + +ChaCha20 Encrypt and decrypt 32 bytes in multiple parts +depends_on:MBEDTLS_CHACHA20_C +enc_dec_buf_multipart:MBEDTLS_CIPHER_CHACHA20:256:16:16:-1:16:16:16:16