From 37e230c0226f435f4029f0aa5702c164326a07f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Wed, 28 Aug 2013 13:50:42 +0200 Subject: [PATCH 01/23] Add arc4 support in the cipher layer --- include/polarssl/cipher.h | 4 + library/cipher.c | 29 ++++++ library/cipher_wrap.c | 35 ++++++-- tests/CMakeLists.txt | 1 + tests/Makefile | 9 ++ tests/suites/test_suite_cipher.arc4.data | 110 +++++++++++++++++++++++ 6 files changed, 183 insertions(+), 5 deletions(-) create mode 100644 tests/suites/test_suite_cipher.arc4.data diff --git a/include/polarssl/cipher.h b/include/polarssl/cipher.h index 0ab2b563b..3164a9a63 100644 --- a/include/polarssl/cipher.h +++ b/include/polarssl/cipher.h @@ -151,6 +151,10 @@ typedef struct { int (*ctr_func)( void *ctx, size_t length, size_t *nc_off, unsigned char *nonce_counter, unsigned char *stream_block, const unsigned char *input, unsigned char *output ); + /** Encrypt using STREAM */ + int (*stream_func)( void *ctx, size_t length, + const unsigned char *input, unsigned char *output ); + /** Set key for encryption purposes */ int (*setkey_enc_func)( void *ctx, const unsigned char *key, unsigned int key_length); diff --git a/library/cipher.c b/library/cipher.c index 826d8fcd2..5a260a0bc 100644 --- a/library/cipher.c +++ b/library/cipher.c @@ -36,6 +36,10 @@ #include +#if defined(POLARSSL_ARC4_C) +#define POLARSSL_CIPHER_MODE_STREAM +#endif + #if defined _MSC_VER && !defined strcasecmp #define strcasecmp _stricmp #endif @@ -61,6 +65,10 @@ static const int supported_ciphers[] = { #endif /* defined(POLARSSL_AES_C) */ +#if defined(POLARSSL_ARC4_C) + POLARSSL_CIPHER_ARC4_128, +#endif + #if defined(POLARSSL_CAMELLIA_C) POLARSSL_CIPHER_CAMELLIA_128_CBC, POLARSSL_CIPHER_CAMELLIA_192_CBC, @@ -279,6 +287,11 @@ const cipher_info_t *cipher_info_from_string( const char *cipher_name ) #endif /* defined(POLARSSL_CIPHER_MODE_CTR) */ #endif +#if defined(POLARSSL_ARC4_C) + if( !strcasecmp( "ARC4-128", cipher_name ) ) + return( cipher_info_from_type( POLARSSL_CIPHER_ARC4_128 ) ); +#endif + #if defined(POLARSSL_DES_C) if( !strcasecmp( "DES-CBC", cipher_name ) ) return cipher_info_from_type( POLARSSL_CIPHER_DES_CBC ); @@ -527,6 +540,21 @@ int cipher_update( cipher_context_t *ctx, const unsigned char *input, size_t ile } #endif +#if defined(POLARSSL_CIPHER_MODE_STREAM) + if( ctx->cipher_info->mode == POLARSSL_MODE_STREAM ) + { + if( 0 != ( ret = ctx->cipher_info->base->stream_func( ctx->cipher_ctx, + ilen, input, output ) ) ) + { + return ret; + } + + *olen = ilen; + + return 0; + } +#endif + return POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE; } @@ -697,6 +725,7 @@ int cipher_finish( cipher_context_t *ctx, unsigned char *output, size_t *olen) if( POLARSSL_MODE_CFB == ctx->cipher_info->mode || POLARSSL_MODE_CTR == ctx->cipher_info->mode || + POLARSSL_MODE_STREAM == ctx->cipher_info->mode || POLARSSL_MODE_NULL == ctx->cipher_info->mode ) { return 0; diff --git a/library/cipher_wrap.c b/library/cipher_wrap.c index baff2aac3..7a4ff753b 100644 --- a/library/cipher_wrap.c +++ b/library/cipher_wrap.c @@ -37,6 +37,10 @@ #include "polarssl/aes.h" #endif +#if defined(POLARSSL_ARC4_C) +#include "polarssl/arc4.h" +#endif + #if defined(POLARSSL_CAMELLIA_C) #include "polarssl/camellia.h" #endif @@ -129,6 +133,7 @@ const cipher_base_t aes_info = { aes_crypt_cbc_wrap, aes_crypt_cfb128_wrap, aes_crypt_ctr_wrap, + NULL, aes_setkey_enc_wrap, aes_setkey_dec_wrap, aes_ctx_alloc, @@ -324,6 +329,7 @@ const cipher_base_t camellia_info = { camellia_crypt_cbc_wrap, camellia_crypt_cfb128_wrap, camellia_crypt_ctr_wrap, + NULL, camellia_setkey_enc_wrap, camellia_setkey_dec_wrap, camellia_ctx_alloc, @@ -531,6 +537,7 @@ const cipher_base_t des_info = { des_crypt_cbc_wrap, des_crypt_cfb128_wrap, des_crypt_ctr_wrap, + NULL, des_setkey_enc_wrap, des_setkey_dec_wrap, des_ctx_alloc, @@ -552,6 +559,7 @@ const cipher_base_t des_ede_info = { des3_crypt_cbc_wrap, des_crypt_cfb128_wrap, des_crypt_ctr_wrap, + NULL, des3_set2key_enc_wrap, des3_set2key_dec_wrap, des3_ctx_alloc, @@ -573,6 +581,7 @@ const cipher_base_t des_ede3_info = { des3_crypt_cbc_wrap, des_crypt_cfb128_wrap, des_crypt_ctr_wrap, + NULL, des3_set3key_enc_wrap, des3_set3key_dec_wrap, des3_ctx_alloc, @@ -661,6 +670,7 @@ const cipher_base_t blowfish_info = { blowfish_crypt_cbc_wrap, blowfish_crypt_cfb64_wrap, blowfish_crypt_ctr_wrap, + NULL, blowfish_setkey_enc_wrap, blowfish_setkey_dec_wrap, blowfish_ctx_alloc, @@ -703,15 +713,28 @@ const cipher_info_t blowfish_ctr_info = { #endif /* POLARSSL_BLOWFISH_C */ #if defined(POLARSSL_ARC4_C) -static void * arc4_ctx_alloc( void ) +static int arc4_crypt_stream_wrap( void *ctx, size_t length, + const unsigned char *input, + unsigned char *output ) { - return (void *) 1; + return( arc4_crypt( (arc4_context *) ctx, length, input, output ) ); } +static int arc4_setkey_wrap( void *ctx, const unsigned char *key, + unsigned int key_length ) +{ + arc4_setup( (arc4_context *) ctx, key, key_length ); + return( 0 ); +} + +static void * arc4_ctx_alloc( void ) +{ + return polarssl_malloc( sizeof( arc4_context ) ); +} static void arc4_ctx_free( void *ctx ) { - ((void) ctx); + polarssl_free( ctx ); } const cipher_base_t arc4_base_info = { @@ -719,8 +742,9 @@ const cipher_base_t arc4_base_info = { NULL, NULL, NULL, - NULL, - NULL, + arc4_crypt_stream_wrap, + arc4_setkey_wrap, + arc4_setkey_wrap, arc4_ctx_alloc, arc4_ctx_free }; @@ -755,6 +779,7 @@ const cipher_base_t null_base_info = { NULL, NULL, NULL, + NULL, null_ctx_alloc, null_ctx_free }; diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 2bd41c0af..cac80a4c9 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -40,6 +40,7 @@ add_test_suite(base64) add_test_suite(blowfish) add_test_suite(camellia) add_test_suite(cipher cipher.aes) +add_test_suite(cipher cipher.arc4) add_test_suite(cipher cipher.blowfish) add_test_suite(cipher cipher.camellia) add_test_suite(cipher cipher.des) diff --git a/tests/Makefile b/tests/Makefile index 4d70858e8..ad678ea76 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -27,6 +27,7 @@ APPS = test_suite_aes.ecb test_suite_aes.cbc \ test_suite_arc4 \ test_suite_base64 test_suite_blowfish \ test_suite_camellia test_suite_cipher.aes \ + test_suite_cipher.arc4 \ test_suite_cipher.blowfish \ test_suite_cipher.camellia \ test_suite_cipher.des test_suite_cipher.null \ @@ -74,6 +75,10 @@ test_suite_cipher.aes.c : suites/test_suite_cipher.function suites/test_suite_ci echo " Generate $@" scripts/generate_code.pl suites test_suite_cipher test_suite_cipher.aes +test_suite_cipher.arc4.c : suites/test_suite_cipher.function suites/test_suite_cipher.arc4.data scripts/generate_code.pl suites/helpers.function suites/main_test.function + echo " Generate $@" + scripts/generate_code.pl suites test_suite_cipher test_suite_cipher.arc4 + test_suite_cipher.blowfish.c : suites/test_suite_cipher.function suites/test_suite_cipher.blowfish.data scripts/generate_code.pl suites/helpers.function suites/main_test.function echo " Generate $@" scripts/generate_code.pl suites test_suite_cipher test_suite_cipher.blowfish @@ -158,6 +163,10 @@ test_suite_cipher.aes: test_suite_cipher.aes.c ../library/libpolarssl.a echo " CC $@.c" $(CC) $(CFLAGS) $(OFLAGS) $@.c $(LDFLAGS) -o $@ +test_suite_cipher.arc4: test_suite_cipher.arc4.c ../library/libpolarssl.a + echo " CC $@.c" + $(CC) $(CFLAGS) $(OFLAGS) $@.c $(LDFLAGS) -o $@ + test_suite_cipher.blowfish: test_suite_cipher.blowfish.c ../library/libpolarssl.a echo " CC $@.c" $(CC) $(CFLAGS) $(OFLAGS) $@.c $(LDFLAGS) -o $@ diff --git a/tests/suites/test_suite_cipher.arc4.data b/tests/suites/test_suite_cipher.arc4.data new file mode 100644 index 000000000..93d35b35d --- /dev/null +++ b/tests/suites/test_suite_cipher.arc4.data @@ -0,0 +1,110 @@ +Cipher Selftest +depends_on:POLARSSL_SELF_TEST +cipher_selftest: + +Decrypt empty buffer +dec_empty_buf: + +ARC4 Encrypt and decrypt 0 bytes +depends_on:POLARSSL_ARC4_C +enc_dec_buf:POLARSSL_CIPHER_ARC4_128:"ARC4-128":128:0:-1 + +ARC4 Encrypt and decrypt 1 byte +depends_on:POLARSSL_ARC4_C +enc_dec_buf:POLARSSL_CIPHER_ARC4_128:"ARC4-128":128:1:-1 + +ARC4 Encrypt and decrypt 2 bytes +depends_on:POLARSSL_ARC4_C +enc_dec_buf:POLARSSL_CIPHER_ARC4_128:"ARC4-128":128:2:-1 + +ARC4 Encrypt and decrypt 7 bytes +depends_on:POLARSSL_ARC4_C +enc_dec_buf:POLARSSL_CIPHER_ARC4_128:"ARC4-128":128:7:-1 + +ARC4 Encrypt and decrypt 8 bytes +depends_on:POLARSSL_ARC4_C +enc_dec_buf:POLARSSL_CIPHER_ARC4_128:"ARC4-128":128:8:-1 + +ARC4 Encrypt and decrypt 9 bytes +depends_on:POLARSSL_ARC4_C +enc_dec_buf:POLARSSL_CIPHER_ARC4_128:"ARC4-128":128:9:-1 + +ARC4 Encrypt and decrypt 15 bytes +depends_on:POLARSSL_ARC4_C +enc_dec_buf:POLARSSL_CIPHER_ARC4_128:"ARC4-128":128:15:-1 + +ARC4 Encrypt and decrypt 16 bytes +depends_on:POLARSSL_ARC4_C +enc_dec_buf:POLARSSL_CIPHER_ARC4_128:"ARC4-128":128:16:-1 + +ARC4 Encrypt and decrypt 17 bytes +depends_on:POLARSSL_ARC4_C +enc_dec_buf:POLARSSL_CIPHER_ARC4_128:"ARC4-128":128:17:-1 + +ARC4 Encrypt and decrypt 31 bytes +depends_on:POLARSSL_ARC4_C +enc_dec_buf:POLARSSL_CIPHER_ARC4_128:"ARC4-128":128:31:-1 + +ARC4 Encrypt and decrypt 32 bytes +depends_on:POLARSSL_ARC4_C +enc_dec_buf:POLARSSL_CIPHER_ARC4_128:"ARC4-128":128:32:-1 + +ARC4 Encrypt and decrypt 32 bytes +depends_on:POLARSSL_ARC4_C +enc_dec_buf:POLARSSL_CIPHER_ARC4_128:"ARC4-128":128:33:-1 + +ARC4 Encrypt and decrypt 47 bytes +depends_on:POLARSSL_ARC4_C +enc_dec_buf:POLARSSL_CIPHER_ARC4_128:"ARC4-128":128:47:-1 + +ARC4 Encrypt and decrypt 48 bytes +depends_on:POLARSSL_ARC4_C +enc_dec_buf:POLARSSL_CIPHER_ARC4_128:"ARC4-128":128:48:-1 + +ARC4 Encrypt and decrypt 49 bytes +depends_on:POLARSSL_ARC4_C +enc_dec_buf:POLARSSL_CIPHER_ARC4_128:"ARC4-128":128:49:-1 + +ARC4 Encrypt and decrypt 0 bytes in multiple parts +depends_on:POLARSSL_ARC4_C +enc_dec_buf_multipart:POLARSSL_CIPHER_ARC4_128:128:0:0: + +ARC4 Encrypt and decrypt 1 bytes in multiple parts 1 +depends_on:POLARSSL_ARC4_C +enc_dec_buf_multipart:POLARSSL_CIPHER_ARC4_128:128:1:0: + +ARC4 Encrypt and decrypt 1 bytes in multiple parts 2 +depends_on:POLARSSL_ARC4_C +enc_dec_buf_multipart:POLARSSL_CIPHER_ARC4_128:128:0:1: + +ARC4 Encrypt and decrypt 16 bytes in multiple parts 1 +depends_on:POLARSSL_ARC4_C +enc_dec_buf_multipart:POLARSSL_CIPHER_ARC4_128:128:16:0: + +ARC4 Encrypt and decrypt 16 bytes in multiple parts 2 +depends_on:POLARSSL_ARC4_C +enc_dec_buf_multipart:POLARSSL_CIPHER_ARC4_128:128:0:16: + +ARC4 Encrypt and decrypt 16 bytes in multiple parts 3 +depends_on:POLARSSL_ARC4_C +enc_dec_buf_multipart:POLARSSL_CIPHER_ARC4_128:128:1:15: + +ARC4 Encrypt and decrypt 16 bytes in multiple parts 4 +depends_on:POLARSSL_ARC4_C +enc_dec_buf_multipart:POLARSSL_CIPHER_ARC4_128:128:15:1: + +ARC4 Encrypt and decrypt 22 bytes in multiple parts 1 +depends_on:POLARSSL_ARC4_C +enc_dec_buf_multipart:POLARSSL_CIPHER_ARC4_128:128:15:7: + +ARC4 Encrypt and decrypt 22 bytes in multiple parts 1 +depends_on:POLARSSL_ARC4_C +enc_dec_buf_multipart:POLARSSL_CIPHER_ARC4_128:128:16:6: + +ARC4 Encrypt and decrypt 22 bytes in multiple parts 1 +depends_on:POLARSSL_ARC4_C +enc_dec_buf_multipart:POLARSSL_CIPHER_ARC4_128:128:17:6: + +ARC4 Encrypt and decrypt 32 bytes in multiple parts 1 +depends_on:POLARSSL_ARC4_C +enc_dec_buf_multipart:POLARSSL_CIPHER_ARC4_128:128:16:16: From b5e85885de37f8368f293db0d343a8fca0410487 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Wed, 28 Aug 2013 16:36:14 +0200 Subject: [PATCH 02/23] Handle NULL as a stream cipher for more uniformity --- include/polarssl/cipher.h | 1 - library/cipher.c | 23 ++------------ library/cipher_wrap.c | 39 ++++++++++++++++-------- tests/suites/test_suite_cipher.null.data | 28 ++++++++--------- 4 files changed, 42 insertions(+), 49 deletions(-) diff --git a/include/polarssl/cipher.h b/include/polarssl/cipher.h index 3164a9a63..67ca28ccf 100644 --- a/include/polarssl/cipher.h +++ b/include/polarssl/cipher.h @@ -95,7 +95,6 @@ typedef enum { typedef enum { POLARSSL_MODE_NONE = 0, - POLARSSL_MODE_NULL, POLARSSL_MODE_CBC, POLARSSL_MODE_CFB, POLARSSL_MODE_OFB, diff --git a/library/cipher.c b/library/cipher.c index 5a260a0bc..60e1d911e 100644 --- a/library/cipher.c +++ b/library/cipher.c @@ -36,7 +36,7 @@ #include -#if defined(POLARSSL_ARC4_C) +#if defined(POLARSSL_ARC4_C) || defined(POLARSSL_CIPHER_NULL_CIPHER) #define POLARSSL_CIPHER_MODE_STREAM #endif @@ -367,11 +367,6 @@ int cipher_setkey( cipher_context_t *ctx, const unsigned char *key, ctx->key_length = key_length; ctx->operation = operation; -#if defined(POLARSSL_CIPHER_NULL_CIPHER) - if( ctx->cipher_info->mode == POLARSSL_MODE_NULL ) - return 0; -#endif /* defined(POLARSSL_CIPHER_NULL_CIPHER) */ - /* * For CFB and CTR mode always use the encryption key schedule */ @@ -421,19 +416,6 @@ int cipher_update( cipher_context_t *ctx, const unsigned char *input, size_t ile return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA; } -#if defined(POLARSSL_CIPHER_NULL_CIPHER) - if( ctx->cipher_info->mode == POLARSSL_MODE_NULL ) - { - *olen = ilen; - - if( output == input ) - return( 0 ); - - memcpy( output, input, ilen ); - return 0; - } -#endif /* defined(POLARSSL_CIPHER_NULL_CIPHER) */ - if( ctx->cipher_info->mode == POLARSSL_MODE_CBC ) { /* @@ -725,8 +707,7 @@ int cipher_finish( cipher_context_t *ctx, unsigned char *output, size_t *olen) if( POLARSSL_MODE_CFB == ctx->cipher_info->mode || POLARSSL_MODE_CTR == ctx->cipher_info->mode || - POLARSSL_MODE_STREAM == ctx->cipher_info->mode || - POLARSSL_MODE_NULL == ctx->cipher_info->mode ) + POLARSSL_MODE_STREAM == ctx->cipher_info->mode ) { return 0; } diff --git a/library/cipher_wrap.c b/library/cipher_wrap.c index 7a4ff753b..562f8b34b 100644 --- a/library/cipher_wrap.c +++ b/library/cipher_wrap.c @@ -645,12 +645,7 @@ static int blowfish_crypt_ctr_wrap( void *ctx, size_t length, #endif } -static int blowfish_setkey_dec_wrap( void *ctx, const unsigned char *key, unsigned int key_length ) -{ - return blowfish_setkey( (blowfish_context *) ctx, key, key_length ); -} - -static int blowfish_setkey_enc_wrap( void *ctx, const unsigned char *key, unsigned int key_length ) +static int blowfish_setkey_wrap( void *ctx, const unsigned char *key, unsigned int key_length ) { return blowfish_setkey( (blowfish_context *) ctx, key, key_length ); } @@ -671,8 +666,8 @@ const cipher_base_t blowfish_info = { blowfish_crypt_cfb64_wrap, blowfish_crypt_ctr_wrap, NULL, - blowfish_setkey_enc_wrap, - blowfish_setkey_dec_wrap, + blowfish_setkey_wrap, + blowfish_setkey_wrap, blowfish_ctx_alloc, blowfish_ctx_free }; @@ -761,12 +756,30 @@ const cipher_info_t arc4_128_info = { #endif /* POLARSSL_ARC4_C */ #if defined(POLARSSL_CIPHER_NULL_CIPHER) +static int null_crypt_stream( void *ctx, size_t length, + const unsigned char *input, + unsigned char *output ) +{ + ((void) ctx); + memmove( output, input, length ); + return( 0 ); +} + +static int null_setkey( void *ctx, const unsigned char *key, + unsigned int key_length ) +{ + ((void) ctx); + ((void) key); + ((void) key_length); + + return( 0 ); +} + static void * null_ctx_alloc( void ) { return (void *) 1; } - static void null_ctx_free( void *ctx ) { ((void) ctx); @@ -777,16 +790,16 @@ const cipher_base_t null_base_info = { NULL, NULL, NULL, - NULL, - NULL, - NULL, + null_crypt_stream, + null_setkey, + null_setkey, null_ctx_alloc, null_ctx_free }; const cipher_info_t null_cipher_info = { POLARSSL_CIPHER_NULL, - POLARSSL_MODE_NULL, + POLARSSL_MODE_STREAM, 0, "NULL", 0, diff --git a/tests/suites/test_suite_cipher.null.data b/tests/suites/test_suite_cipher.null.data index 96aa36a9d..dd6827715 100644 --- a/tests/suites/test_suite_cipher.null.data +++ b/tests/suites/test_suite_cipher.null.data @@ -7,59 +7,59 @@ dec_empty_buf: NULL Encrypt and decrypt 0 bytes depends_on:POLARSSL_CIPHER_NULL_CIPHER -enc_dec_buf:POLARSSL_CIPHER_NULL:NULL:0:0 +enc_dec_buf:POLARSSL_CIPHER_NULL:"NULL":0:0:-1 NULL Encrypt and decrypt 1 bytes depends_on:POLARSSL_CIPHER_NULL_CIPHER -enc_dec_buf:POLARSSL_CIPHER_NULL:NULL:0:1 +enc_dec_buf:POLARSSL_CIPHER_NULL:"NULL":0:1:-1 NULL Encrypt and decrypt 2 bytes depends_on:POLARSSL_CIPHER_NULL_CIPHER -enc_dec_buf:POLARSSL_CIPHER_NULL:NULL:0:2 +enc_dec_buf:POLARSSL_CIPHER_NULL:"NULL":0:2:-1 NULL Encrypt and decrypt 7 bytes depends_on:POLARSSL_CIPHER_NULL_CIPHER -enc_dec_buf:POLARSSL_CIPHER_NULL:NULL:0:7 +enc_dec_buf:POLARSSL_CIPHER_NULL:"NULL":0:7:-1 NULL Encrypt and decrypt 8 bytes depends_on:POLARSSL_CIPHER_NULL_CIPHER -enc_dec_buf:POLARSSL_CIPHER_NULL:NULL:0:8 +enc_dec_buf:POLARSSL_CIPHER_NULL:"NULL":0:8:-1 NULL Encrypt and decrypt 9 bytes depends_on:POLARSSL_CIPHER_NULL_CIPHER -enc_dec_buf:POLARSSL_CIPHER_NULL:NULL:0:9 +enc_dec_buf:POLARSSL_CIPHER_NULL:"NULL":0:9:-1 NULL Encrypt and decrypt 15 bytes depends_on:POLARSSL_CIPHER_NULL_CIPHER -enc_dec_buf:POLARSSL_CIPHER_NULL:NULL:0:15 +enc_dec_buf:POLARSSL_CIPHER_NULL:"NULL":0:15:-1 NULL Encrypt and decrypt 16 bytes depends_on:POLARSSL_CIPHER_NULL_CIPHER -enc_dec_buf:POLARSSL_CIPHER_NULL:NULL:0:16 +enc_dec_buf:POLARSSL_CIPHER_NULL:"NULL":0:16:-1 NULL Encrypt and decrypt 31 bytes depends_on:POLARSSL_CIPHER_NULL_CIPHER -enc_dec_buf:POLARSSL_CIPHER_NULL:NULL:0:31 +enc_dec_buf:POLARSSL_CIPHER_NULL:"NULL":0:31:-1 NULL Encrypt and decrypt 32 bytes depends_on:POLARSSL_CIPHER_NULL_CIPHER -enc_dec_buf:POLARSSL_CIPHER_NULL:NULL:0:32 +enc_dec_buf:POLARSSL_CIPHER_NULL:"NULL":0:32:-1 NULL Encrypt and decrypt 33 bytes depends_on:POLARSSL_CIPHER_NULL_CIPHER -enc_dec_buf:POLARSSL_CIPHER_NULL:NULL:0:33 +enc_dec_buf:POLARSSL_CIPHER_NULL:"NULL":0:33:-1 NULL Encrypt and decrypt 47 bytes depends_on:POLARSSL_CIPHER_NULL_CIPHER -enc_dec_buf:POLARSSL_CIPHER_NULL:NULL:0:47 +enc_dec_buf:POLARSSL_CIPHER_NULL:"NULL":0:47:-1 NULL Encrypt and decrypt 48 bytes depends_on:POLARSSL_CIPHER_NULL_CIPHER -enc_dec_buf:POLARSSL_CIPHER_NULL:NULL:0:48 +enc_dec_buf:POLARSSL_CIPHER_NULL:"NULL":0:48:-1 NULL Encrypt and decrypt 49 bytes depends_on:POLARSSL_CIPHER_NULL_CIPHER -enc_dec_buf:POLARSSL_CIPHER_NULL:NULL:0:49 +enc_dec_buf:POLARSSL_CIPHER_NULL:"NULL":0:49:-1 NULL Encrypt and decrypt 1 bytes in multiple parts 1 depends_on:POLARSSL_CIPHER_NULL_CIPHER From 07f8fa5a69f09bf2bba24a0c93fc3333e4d42a3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Fri, 30 Aug 2013 18:34:08 +0200 Subject: [PATCH 03/23] GCM in the cipher layer, step 1 - no support for additional data - no support for tag --- library/cipher.c | 70 ++++++++++++++- library/cipher_wrap.c | 35 +++++++- library/gcm.c | 4 +- tests/CMakeLists.txt | 1 + tests/Makefile | 10 ++- tests/suites/test_suite_cipher.function | 2 +- tests/suites/test_suite_cipher.gcm.data | 110 ++++++++++++++++++++++++ 7 files changed, 225 insertions(+), 7 deletions(-) create mode 100644 tests/suites/test_suite_cipher.gcm.data diff --git a/library/cipher.c b/library/cipher.c index 60e1d911e..733f6e5f9 100644 --- a/library/cipher.c +++ b/library/cipher.c @@ -34,6 +34,10 @@ #include "polarssl/cipher.h" #include "polarssl/cipher_wrap.h" +#if defined(POLARSSL_GCM_C) +#include "polarssl/gcm.h" +#endif + #include #if defined(POLARSSL_ARC4_C) || defined(POLARSSL_CIPHER_NULL_CIPHER) @@ -285,7 +289,14 @@ const cipher_info_t *cipher_info_from_string( const char *cipher_name ) if( !strcasecmp( "AES-256-CTR", cipher_name ) ) return cipher_info_from_type( POLARSSL_CIPHER_AES_256_CTR ); #endif /* defined(POLARSSL_CIPHER_MODE_CTR) */ + +#if defined(POLARSSL_GCM_C) + if( !strcasecmp( "AES-128-GCM", cipher_name ) ) + return cipher_info_from_type( POLARSSL_CIPHER_AES_128_GCM ); + if( !strcasecmp( "AES-256-GCM", cipher_name ) ) + return cipher_info_from_type( POLARSSL_CIPHER_AES_256_GCM ); #endif +#endif /* POLARSSL_AES_C */ #if defined(POLARSSL_ARC4_C) if( !strcasecmp( "ARC4-128", cipher_name ) ) @@ -392,6 +403,16 @@ int cipher_reset( cipher_context_t *ctx, const unsigned char *iv ) ctx->unprocessed_len = 0; +#if defined(POLARSSL_GCM_C) + if( POLARSSL_MODE_GCM == ctx->cipher_info->mode ) + { + // TODO: allow other IV length + // TODO: allow additional data + return gcm_starts( ctx->cipher_ctx, ctx->operation, + iv, 12, (unsigned char *) "", 0 ); + } +#endif + memcpy( ctx->iv, iv, cipher_get_iv_size( ctx ) ); return 0; @@ -416,7 +437,8 @@ int cipher_update( cipher_context_t *ctx, const unsigned char *input, size_t ile return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA; } - if( ctx->cipher_info->mode == POLARSSL_MODE_CBC ) + if( ctx->cipher_info->mode == POLARSSL_MODE_CBC || + ctx->cipher_info->mode == POLARSSL_MODE_GCM ) { /* * If there is not enough data for a full block, cache it. @@ -443,6 +465,18 @@ int cipher_update( cipher_context_t *ctx, const unsigned char *input, size_t ile memcpy( &( ctx->unprocessed_data[ctx->unprocessed_len] ), input, copy_len ); +#if defined(POLARSSL_GCM_C) + if( ctx->cipher_info->mode == POLARSSL_MODE_GCM ) + { + if( 0 != ( ret = gcm_update( ctx->cipher_ctx, + cipher_get_block_size( ctx ), + ctx->unprocessed_data, output ) ) ) + { + return ret; + } + } + else +#endif if( 0 != ( ret = ctx->cipher_info->base->cbc_func( ctx->cipher_ctx, ctx->operation, cipher_get_block_size( ctx ), ctx->iv, ctx->unprocessed_data, output ) ) ) @@ -479,11 +513,23 @@ int cipher_update( cipher_context_t *ctx, const unsigned char *input, size_t ile */ if( ilen ) { +#if defined(POLARSSL_GCM_C) + if( ctx->cipher_info->mode == POLARSSL_MODE_GCM ) + { + if( 0 != ( ret = gcm_update( ctx->cipher_ctx, + ilen, input, output ) ) ) + { + return ret; + } + } + else +#endif if( 0 != ( ret = ctx->cipher_info->base->cbc_func( ctx->cipher_ctx, ctx->operation, ilen, ctx->iv, input, output ) ) ) { return ret; } + *olen += ilen; } @@ -712,6 +758,28 @@ int cipher_finish( cipher_context_t *ctx, unsigned char *output, size_t *olen) return 0; } +#if defined(POLARSSL_GCM_C) + if( POLARSSL_MODE_GCM == ctx->cipher_info->mode ) + { + size_t tag_len = 0; // TODO + unsigned char tag[16]; + + if( 0 != ( ret = gcm_update( ctx->cipher_ctx, + ctx->unprocessed_len, ctx->unprocessed_data, + output ) ) ) + { + return( ret ); + } + + *olen += ctx->unprocessed_len; + + if( 0 != ( ret = gcm_finish( ctx->cipher_ctx, tag, tag_len ) ) ) + return( ret ); + + return( 0 ); + } +#endif + if( POLARSSL_MODE_CBC == ctx->cipher_info->mode ) { if( POLARSSL_ENCRYPT == ctx->operation ) diff --git a/library/cipher_wrap.c b/library/cipher_wrap.c index 562f8b34b..c8eee5432 100644 --- a/library/cipher_wrap.c +++ b/library/cipher_wrap.c @@ -53,6 +53,10 @@ #include "polarssl/blowfish.h" #endif +#if defined(POLARSSL_GCM_C) +#include "polarssl/gcm.h" +#endif + #if defined(POLARSSL_MEMORY_C) #include "polarssl/memory.h" #else @@ -235,6 +239,33 @@ const cipher_info_t aes_256_ctr_info = { #endif /* POLARSSL_CIPHER_MODE_CTR */ #if defined(POLARSSL_GCM_C) +static void *gcm_ctx_alloc( void ) +{ + return polarssl_malloc( sizeof( gcm_context ) ); +} + +static void gcm_ctx_free( void *ctx ) +{ + polarssl_free( ctx ); +} + +static int gcm_setkey_wrap( void *ctx, const unsigned char *key, unsigned int key_length ) +{ + return gcm_init( (gcm_context *) ctx, key, key_length ); +} + +const cipher_base_t gcm_aes_info = { + POLARSSL_CIPHER_ID_AES, + NULL, + NULL, + NULL, + NULL, + gcm_setkey_wrap, + gcm_setkey_wrap, + gcm_ctx_alloc, + gcm_ctx_free, +}; + const cipher_info_t aes_128_gcm_info = { POLARSSL_CIPHER_AES_128_GCM, POLARSSL_MODE_GCM, @@ -242,7 +273,7 @@ const cipher_info_t aes_128_gcm_info = { "AES-128-GCM", 16, 16, - &aes_info + &gcm_aes_info }; const cipher_info_t aes_256_gcm_info = { @@ -252,7 +283,7 @@ const cipher_info_t aes_256_gcm_info = { "AES-256-GCM", 16, 16, - &aes_info + &gcm_aes_info }; #endif /* POLARSSL_GCM_C */ diff --git a/library/gcm.c b/library/gcm.c index 3e9969d3b..9c079bddd 100644 --- a/library/gcm.c +++ b/library/gcm.c @@ -293,11 +293,11 @@ int gcm_finish( gcm_context *ctx, uint64_t orig_len = ctx->len * 8; uint64_t orig_add_len = ctx->add_len * 8; - memcpy( tag, ctx->base_ectr, tag_len ); - if( tag_len > 16 ) return( POLARSSL_ERR_GCM_BAD_INPUT ); + memcpy( tag, ctx->base_ectr, tag_len ); + if( orig_len || orig_add_len ) { memset( work_buf, 0x00, 16 ); diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index cac80a4c9..20f3c8d94 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -44,6 +44,7 @@ add_test_suite(cipher cipher.arc4) add_test_suite(cipher cipher.blowfish) add_test_suite(cipher cipher.camellia) add_test_suite(cipher cipher.des) +add_test_suite(cipher cipher.gcm) add_test_suite(cipher cipher.null) add_test_suite(cipher cipher.padding) add_test_suite(ctr_drbg) diff --git a/tests/Makefile b/tests/Makefile index ad678ea76..4d2bcba61 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -27,7 +27,7 @@ APPS = test_suite_aes.ecb test_suite_aes.cbc \ test_suite_arc4 \ test_suite_base64 test_suite_blowfish \ test_suite_camellia test_suite_cipher.aes \ - test_suite_cipher.arc4 \ + test_suite_cipher.arc4 test_suite_cipher.gcm \ test_suite_cipher.blowfish \ test_suite_cipher.camellia \ test_suite_cipher.des test_suite_cipher.null \ @@ -79,6 +79,10 @@ test_suite_cipher.arc4.c : suites/test_suite_cipher.function suites/test_suite_c echo " Generate $@" scripts/generate_code.pl suites test_suite_cipher test_suite_cipher.arc4 +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 " Generate $@" + scripts/generate_code.pl suites test_suite_cipher test_suite_cipher.gcm + test_suite_cipher.blowfish.c : suites/test_suite_cipher.function suites/test_suite_cipher.blowfish.data scripts/generate_code.pl suites/helpers.function suites/main_test.function echo " Generate $@" scripts/generate_code.pl suites test_suite_cipher test_suite_cipher.blowfish @@ -167,6 +171,10 @@ test_suite_cipher.arc4: test_suite_cipher.arc4.c ../library/libpolarssl.a echo " CC $@.c" $(CC) $(CFLAGS) $(OFLAGS) $@.c $(LDFLAGS) -o $@ +test_suite_cipher.gcm: test_suite_cipher.gcm.c ../library/libpolarssl.a + echo " CC $@.c" + $(CC) $(CFLAGS) $(OFLAGS) $@.c $(LDFLAGS) -o $@ + test_suite_cipher.blowfish: test_suite_cipher.blowfish.c ../library/libpolarssl.a echo " CC $@.c" $(CC) $(CFLAGS) $(OFLAGS) $@.c $(LDFLAGS) -o $@ diff --git a/tests/suites/test_suite_cipher.function b/tests/suites/test_suite_cipher.function index 1f7943a44..537720872 100644 --- a/tests/suites/test_suite_cipher.function +++ b/tests/suites/test_suite_cipher.function @@ -248,7 +248,7 @@ void enc_dec_buf_multipart( int cipher_id, int key_len, int first_length_val, TEST_ASSERT( totaloutlen == length || ( totaloutlen % cipher_get_block_size( &ctx_dec ) == 0 && totaloutlen < length && - totaloutlen + cipher_get_block_size( &ctx_dec ) > length ) ); + totaloutlen + cipher_get_block_size( &ctx_dec ) >= length ) ); TEST_ASSERT( 0 == cipher_finish( &ctx_dec, decbuf + outlen, &outlen ) ); totaloutlen += outlen; diff --git a/tests/suites/test_suite_cipher.gcm.data b/tests/suites/test_suite_cipher.gcm.data new file mode 100644 index 000000000..aacdca8eb --- /dev/null +++ b/tests/suites/test_suite_cipher.gcm.data @@ -0,0 +1,110 @@ +Cipher Selftest +depends_on:POLARSSL_SELF_TEST +cipher_selftest: + +Decrypt empty buffer +dec_empty_buf: + +AES-GCM Encrypt and decrypt 0 bytes +depends_on:POLARSSL_AES_C:POLARSSL_GCM_C +enc_dec_buf:POLARSSL_CIPHER_AES_128_GCM:"AES-128-GCM":128:0:-1 + +AES 128 GCM Encrypt and decrypt 1 byte +depends_on:POLARSSL_AES_C:POLARSSL_GCM_C +enc_dec_buf:POLARSSL_CIPHER_AES_128_GCM:"AES-128-GCM":128:1:-1 + +AES 128 GCM Encrypt and decrypt 2 bytes +depends_on:POLARSSL_AES_C:POLARSSL_GCM_C +enc_dec_buf:POLARSSL_CIPHER_AES_128_GCM:"AES-128-GCM":128:2:-1 + +AES 128 GCM Encrypt and decrypt 7 bytes +depends_on:POLARSSL_AES_C:POLARSSL_GCM_C +enc_dec_buf:POLARSSL_CIPHER_AES_128_GCM:"AES-128-GCM":128:7:-1 + +AES 128 GCM Encrypt and decrypt 8 bytes +depends_on:POLARSSL_AES_C:POLARSSL_GCM_C +enc_dec_buf:POLARSSL_CIPHER_AES_128_GCM:"AES-128-GCM":128:8:-1 + +AES 128 GCM Encrypt and decrypt 9 bytes +depends_on:POLARSSL_AES_C:POLARSSL_GCM_C +enc_dec_buf:POLARSSL_CIPHER_AES_128_GCM:"AES-128-GCM":128:9:-1 + +AES 128 GCM Encrypt and decrypt 15 bytes +depends_on:POLARSSL_AES_C:POLARSSL_GCM_C +enc_dec_buf:POLARSSL_CIPHER_AES_128_GCM:"AES-128-GCM":128:15:-1 + +AES 128 GCM Encrypt and decrypt 16 bytes +depends_on:POLARSSL_AES_C:POLARSSL_GCM_C +enc_dec_buf:POLARSSL_CIPHER_AES_128_GCM:"AES-128-GCM":128:16:-1 + +AES 128 GCM Encrypt and decrypt 17 bytes +depends_on:POLARSSL_AES_C:POLARSSL_GCM_C +enc_dec_buf:POLARSSL_CIPHER_AES_128_GCM:"AES-128-GCM":128:17:-1 + +AES 128 GCM Encrypt and decrypt 31 bytes +depends_on:POLARSSL_AES_C:POLARSSL_GCM_C +enc_dec_buf:POLARSSL_CIPHER_AES_128_GCM:"AES-128-GCM":128:31:-1 + +AES 128 GCM Encrypt and decrypt 32 bytes +depends_on:POLARSSL_AES_C:POLARSSL_GCM_C +enc_dec_buf:POLARSSL_CIPHER_AES_128_GCM:"AES-128-GCM":128:32:-1 + +AES 128 GCM Encrypt and decrypt 32 bytes +depends_on:POLARSSL_AES_C:POLARSSL_GCM_C +enc_dec_buf:POLARSSL_CIPHER_AES_128_GCM:"AES-128-GCM":128:33:-1 + +AES 128 GCM Encrypt and decrypt 47 bytes +depends_on:POLARSSL_AES_C:POLARSSL_GCM_C +enc_dec_buf:POLARSSL_CIPHER_AES_128_GCM:"AES-128-GCM":128:47:-1 + +AES 128 GCM Encrypt and decrypt 48 bytes +depends_on:POLARSSL_AES_C:POLARSSL_GCM_C +enc_dec_buf:POLARSSL_CIPHER_AES_128_GCM:"AES-128-GCM":128:48:-1 + +AES 128 GCM Encrypt and decrypt 49 bytes +depends_on:POLARSSL_AES_C:POLARSSL_GCM_C +enc_dec_buf:POLARSSL_CIPHER_AES_128_GCM:"AES-128-GCM":128:49:-1 + +AES 128 GCM Encrypt and decrypt 0 bytes in multiple parts +depends_on:POLARSSL_AES_C:POLARSSL_GCM_C +enc_dec_buf_multipart:POLARSSL_CIPHER_AES_128_GCM:128:0:0 + +AES 128 GCM Encrypt and decrypt 1 bytes in multiple parts 1 +depends_on:POLARSSL_AES_C:POLARSSL_GCM_C +enc_dec_buf_multipart:POLARSSL_CIPHER_AES_128_GCM:128:1:0 + +AES 128 GCM Encrypt and decrypt 1 bytes in multiple parts 2 +depends_on:POLARSSL_AES_C:POLARSSL_GCM_C +enc_dec_buf_multipart:POLARSSL_CIPHER_AES_128_GCM:128:0:1 + +AES 128 GCM Encrypt and decrypt 16 bytes in multiple parts 1 +depends_on:POLARSSL_AES_C:POLARSSL_GCM_C +enc_dec_buf_multipart:POLARSSL_CIPHER_AES_128_GCM:128:16:0 + +AES 128 GCM Encrypt and decrypt 16 bytes in multiple parts 2 +depends_on:POLARSSL_AES_C:POLARSSL_GCM_C +enc_dec_buf_multipart:POLARSSL_CIPHER_AES_128_GCM:128:0:16 + +AES 128 GCM Encrypt and decrypt 16 bytes in multiple parts 3 +depends_on:POLARSSL_AES_C:POLARSSL_GCM_C +enc_dec_buf_multipart:POLARSSL_CIPHER_AES_128_GCM:128:1:15 + +AES 128 GCM Encrypt and decrypt 16 bytes in multiple parts 4 +depends_on:POLARSSL_AES_C:POLARSSL_GCM_C +enc_dec_buf_multipart:POLARSSL_CIPHER_AES_128_GCM:128:15:1 + +AES 128 GCM Encrypt and decrypt 22 bytes in multiple parts 1 +depends_on:POLARSSL_AES_C:POLARSSL_GCM_C +enc_dec_buf_multipart:POLARSSL_CIPHER_AES_128_GCM:128:15:7 + +AES 128 GCM Encrypt and decrypt 22 bytes in multiple parts 1 +depends_on:POLARSSL_AES_C:POLARSSL_GCM_C +enc_dec_buf_multipart:POLARSSL_CIPHER_AES_128_GCM:128:16:6 + +AES 128 GCM Encrypt and decrypt 22 bytes in multiple parts 1 +depends_on:POLARSSL_AES_C:POLARSSL_GCM_C +enc_dec_buf_multipart:POLARSSL_CIPHER_AES_128_GCM:128:17:6 + +AES 128 GCM Encrypt and decrypt 32 bytes in multiple parts 1 +depends_on:POLARSSL_AES_C:POLARSSL_GCM_C +enc_dec_buf_multipart:POLARSSL_CIPHER_AES_128_GCM:128:16:16 From 20d6a17af99ad538db902dbebf16879c0b3de687 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Sat, 31 Aug 2013 16:37:46 +0200 Subject: [PATCH 04/23] Make GCM tag check "constant-time" --- library/gcm.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/library/gcm.c b/library/gcm.c index 9c079bddd..104fda3a4 100644 --- a/library/gcm.c +++ b/library/gcm.c @@ -357,15 +357,22 @@ int gcm_auth_decrypt( gcm_context *ctx, unsigned char *output ) { unsigned char check_tag[16]; + size_t i; + int diff; gcm_crypt_and_tag( ctx, GCM_DECRYPT, length, iv, iv_len, add, add_len, input, output, tag_len, check_tag ); - if( memcmp( check_tag, tag, tag_len ) == 0 ) - return( 0 ); + /* Check tag in "constant-time" */ + for( diff = 0, i = 0; i < tag_len; i++ ) + diff |= tag[i] ^ check_tag[i]; - memset( output, 0, length ); + if( diff != 0 ) + { + memset( output, 0, length ); + return( POLARSSL_ERR_GCM_AUTH_FAILED ); + } - return( POLARSSL_ERR_GCM_AUTH_FAILED ); + return( 0 ); } #if defined(POLARSSL_SELF_TEST) From da02a7f45e55f9e1394cf4cab118b78ac299dec2 Mon Sep 17 00:00:00 2001 From: Paul Bakker Date: Sat, 31 Aug 2013 17:25:14 +0200 Subject: [PATCH 05/23] AES_CBC ciphersuites now run purely via cipher layer --- include/polarssl/ssl.h | 3 + library/ssl_tls.c | 136 ++++++++++++++++++++++++++++++++++++----- 2 files changed, 123 insertions(+), 16 deletions(-) diff --git a/include/polarssl/ssl.h b/include/polarssl/ssl.h index 354c6c2fc..aafbfb687 100644 --- a/include/polarssl/ssl.h +++ b/include/polarssl/ssl.h @@ -504,6 +504,9 @@ struct _ssl_transform md_context_t md_ctx_enc; /*!< MAC (encryption) */ md_context_t md_ctx_dec; /*!< MAC (decryption) */ + cipher_context_t cipher_ctx_enc; /*!< encryption context */ + cipher_context_t cipher_ctx_dec; /*!< decryption context */ + uint32_t ctx_enc[SSL_CTX_MAX / 4]; /*!< encryption context */ uint32_t ctx_dec[SSL_CTX_MAX / 4]; /*!< decryption context */ diff --git a/library/ssl_tls.c b/library/ssl_tls.c index ed95d3e03..5e2e7725b 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -355,6 +355,7 @@ static void ssl_calc_finished_tls_sha384(ssl_context *,unsigned char *,int); int ssl_derive_keys( ssl_context *ssl ) { + int ret = 0; unsigned char tmp[64]; unsigned char keyblk[256]; unsigned char *key1; @@ -648,15 +649,46 @@ int ssl_derive_keys( ssl_context *ssl ) break; #endif -#if defined(POLARSSL_AES_C) case POLARSSL_CIPHER_AES_128_CBC: case POLARSSL_CIPHER_AES_256_CBC: - aes_setkey_enc( (aes_context*) transform->ctx_enc, key1, - cipher_info->key_length ); - aes_setkey_dec( (aes_context*) transform->ctx_dec, key2, - cipher_info->key_length ); + if( ( ret = cipher_init_ctx( &transform->cipher_ctx_enc, + cipher_info ) ) != 0 ) + { + return( ret ); + } + + if( ( ret = cipher_setkey( &transform->cipher_ctx_enc, key1, + cipher_info->key_length, + POLARSSL_ENCRYPT ) ) != 0 ) + { + return( ret ); + } + + if( ( ret = cipher_set_padding_mode( &transform->cipher_ctx_enc, + POLARSSL_PADDING_NONE ) ) != 0 ) + { + return( ret ); + } + + if( ( ret = cipher_init_ctx( &transform->cipher_ctx_dec, + cipher_info ) ) != 0 ) + { + return( ret ); + } + + if( ( ret = cipher_setkey( &transform->cipher_ctx_dec, key2, + cipher_info->key_length, + POLARSSL_DECRYPT ) ) != 0 ) + { + return( ret ); + } + + if( ( ret = cipher_set_padding_mode( &transform->cipher_ctx_dec, + POLARSSL_PADDING_NONE ) ) != 0 ) + { + return( ret ); + } break; -#endif #if defined(POLARSSL_CAMELLIA_C) case POLARSSL_CIPHER_CAMELLIA_128_CBC: @@ -999,8 +1031,10 @@ static int ssl_encrypt_buf( ssl_context *ssl ) else #endif /* POLARSSL_GCM_C */ { + int ret; unsigned char *enc_msg; size_t enc_msglen; + size_t olen = 0; padlen = ssl->transform_out->ivlen - ( ssl->out_msglen + 1 ) % ssl->transform_out->ivlen; @@ -1065,14 +1099,49 @@ static int ssl_encrypt_buf( ssl_context *ssl ) break; #endif -#if defined(POLARSSL_AES_C) case POLARSSL_CIPHER_AES_128_CBC: case POLARSSL_CIPHER_AES_256_CBC: - aes_crypt_cbc( (aes_context *) ssl->transform_out->ctx_enc, - AES_ENCRYPT, enc_msglen, - ssl->transform_out->iv_enc, enc_msg, enc_msg ); - break; + if( ( ret = cipher_reset( &ssl->transform_out->cipher_ctx_enc, + ssl->transform_out->iv_enc ) ) != 0 ) + { + return( ret ); + } + + if( ( ret = cipher_update( &ssl->transform_out->cipher_ctx_enc, + enc_msg, enc_msglen, enc_msg, + &olen ) ) != 0 ) + { + return( ret ); + } + + enc_msglen -= olen; + + if( ( ret = cipher_finish( &ssl->transform_out->cipher_ctx_enc, + enc_msg + olen, &olen ) ) != 0 ) + { + return( ret ); + } + + if( enc_msglen != olen ) + { + SSL_DEBUG_MSG( 1, ( "total encrypted length incorrect %d %d", + enc_msglen, olen ) ); + // TODO Real error number + return( -1 ); + } + +#if defined(POLARSSL_SSL_PROTO_SSL3) || defined(POLARSSL_SSL_PROTO_TLS1) + if( ssl->minor_ver < SSL_MINOR_VERSION_2 ) + { + /* + * Save IV in SSL3 and TLS1 + */ + memcpy( ssl->transform_out->iv_enc, + ssl->transform_out->cipher_ctx_enc.iv, + ssl->transform_out->ivlen ); + } #endif + break; #if defined(POLARSSL_CAMELLIA_C) case POLARSSL_CIPHER_CAMELLIA_128_CBC: @@ -1190,10 +1259,12 @@ static int ssl_decrypt_buf( ssl_context *ssl ) /* * Decrypt and check the padding */ + int ret; unsigned char *dec_msg; unsigned char *dec_msg_result; size_t dec_msglen; size_t minlen = 0; + size_t olen = 0; /* * Check immediate ciphertext sanity @@ -1252,14 +1323,47 @@ static int ssl_decrypt_buf( ssl_context *ssl ) break; #endif -#if defined(POLARSSL_AES_C) case POLARSSL_CIPHER_AES_128_CBC: case POLARSSL_CIPHER_AES_256_CBC: - aes_crypt_cbc( (aes_context *) ssl->transform_in->ctx_dec, - AES_DECRYPT, dec_msglen, - ssl->transform_in->iv_dec, dec_msg, dec_msg_result ); - break; + if( ( ret = cipher_reset( &ssl->transform_in->cipher_ctx_dec, + ssl->transform_in->iv_dec ) ) != 0 ) + { + return( ret ); + } + + if( ( ret = cipher_update( &ssl->transform_in->cipher_ctx_dec, + dec_msg, dec_msglen, dec_msg_result, + &olen ) ) != 0 ) + { + return( ret ); + } + + dec_msglen -= olen; + if( ( ret = cipher_finish( &ssl->transform_in->cipher_ctx_dec, + dec_msg_result + olen, &olen ) ) != 0 ) + { + return( ret ); + } + + if( dec_msglen != olen ) + { + SSL_DEBUG_MSG( 1, ( "total encrypted length incorrect" ) ); + // TODO Real error number + return( -1 ); + } + +#if defined(POLARSSL_SSL_PROTO_SSL3) || defined(POLARSSL_SSL_PROTO_TLS1) + if( ssl->minor_ver < SSL_MINOR_VERSION_2 ) + { + /* + * Save IV in SSL3 and TLS1 + */ + memcpy( ssl->transform_in->iv_dec, + ssl->transform_in->cipher_ctx_dec.iv, + ssl->transform_in->ivlen ); + } #endif + break; #if defined(POLARSSL_CAMELLIA_C) case POLARSSL_CIPHER_CAMELLIA_128_CBC: From cca5b81d18f7eb8d31a843b072848a1220dbeca7 Mon Sep 17 00:00:00 2001 From: Paul Bakker Date: Sat, 31 Aug 2013 17:40:26 +0200 Subject: [PATCH 06/23] All CBC ciphersuites via the cipher layer --- library/ssl_tls.c | 216 ++++++++++++++-------------------------------- 1 file changed, 66 insertions(+), 150 deletions(-) diff --git a/library/ssl_tls.c b/library/ssl_tls.c index 5e2e7725b..bb939cbd8 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -642,15 +642,12 @@ int ssl_derive_keys( ssl_context *ssl ) break; #endif -#if defined(POLARSSL_DES_C) case POLARSSL_CIPHER_DES_EDE3_CBC: - des3_set3key_enc( (des3_context *) transform->ctx_enc, key1 ); - des3_set3key_dec( (des3_context *) transform->ctx_dec, key2 ); - break; -#endif - + case POLARSSL_CIPHER_CAMELLIA_128_CBC: + case POLARSSL_CIPHER_CAMELLIA_256_CBC: case POLARSSL_CIPHER_AES_128_CBC: case POLARSSL_CIPHER_AES_256_CBC: + case POLARSSL_CIPHER_DES_CBC: if( ( ret = cipher_init_ctx( &transform->cipher_ctx_enc, cipher_info ) ) != 0 ) { @@ -690,23 +687,6 @@ int ssl_derive_keys( ssl_context *ssl ) } break; -#if defined(POLARSSL_CAMELLIA_C) - case POLARSSL_CIPHER_CAMELLIA_128_CBC: - case POLARSSL_CIPHER_CAMELLIA_256_CBC: - camellia_setkey_enc( (camellia_context*) transform->ctx_enc, key1, - cipher_info->key_length ); - camellia_setkey_dec( (camellia_context*) transform->ctx_dec, key2, - cipher_info->key_length ); - break; -#endif - -#if defined(POLARSSL_DES_C) - case POLARSSL_CIPHER_DES_CBC: - des_setkey_enc( (des_context *) transform->ctx_enc, key1 ); - des_setkey_dec( (des_context *) transform->ctx_dec, key2 ); - break; -#endif - #if defined(POLARSSL_GCM_C) case POLARSSL_CIPHER_AES_128_GCM: case POLARSSL_CIPHER_AES_256_GCM: @@ -1083,78 +1063,46 @@ static int ssl_encrypt_buf( ssl_context *ssl ) SSL_DEBUG_BUF( 4, "before encrypt: output payload", ssl->out_iv, ssl->out_msglen ); - switch( ssl->transform_out->ciphersuite_info->cipher ) + if( ( ret = cipher_reset( &ssl->transform_out->cipher_ctx_enc, + ssl->transform_out->iv_enc ) ) != 0 ) { -#if defined(POLARSSL_DES_C) - case POLARSSL_CIPHER_DES_CBC: - des_crypt_cbc( (des_context *) ssl->transform_out->ctx_enc, - DES_ENCRYPT, enc_msglen, - ssl->transform_out->iv_enc, enc_msg, enc_msg ); - break; + return( ret ); + } - case POLARSSL_CIPHER_DES_EDE3_CBC: - des3_crypt_cbc( (des3_context *) ssl->transform_out->ctx_enc, - DES_ENCRYPT, enc_msglen, - ssl->transform_out->iv_enc, enc_msg, enc_msg ); - break; -#endif + if( ( ret = cipher_update( &ssl->transform_out->cipher_ctx_enc, + enc_msg, enc_msglen, enc_msg, + &olen ) ) != 0 ) + { + return( ret ); + } - case POLARSSL_CIPHER_AES_128_CBC: - case POLARSSL_CIPHER_AES_256_CBC: - if( ( ret = cipher_reset( &ssl->transform_out->cipher_ctx_enc, - ssl->transform_out->iv_enc ) ) != 0 ) - { - return( ret ); - } + enc_msglen -= olen; - if( ( ret = cipher_update( &ssl->transform_out->cipher_ctx_enc, - enc_msg, enc_msglen, enc_msg, - &olen ) ) != 0 ) - { - return( ret ); - } + if( ( ret = cipher_finish( &ssl->transform_out->cipher_ctx_enc, + enc_msg + olen, &olen ) ) != 0 ) + { + return( ret ); + } - enc_msglen -= olen; - - if( ( ret = cipher_finish( &ssl->transform_out->cipher_ctx_enc, - enc_msg + olen, &olen ) ) != 0 ) - { - return( ret ); - } - - if( enc_msglen != olen ) - { - SSL_DEBUG_MSG( 1, ( "total encrypted length incorrect %d %d", - enc_msglen, olen ) ); - // TODO Real error number - return( -1 ); - } + if( enc_msglen != olen ) + { + SSL_DEBUG_MSG( 1, ( "total encrypted length incorrect %d %d", + enc_msglen, olen ) ); + // TODO Real error number + return( -1 ); + } #if defined(POLARSSL_SSL_PROTO_SSL3) || defined(POLARSSL_SSL_PROTO_TLS1) - if( ssl->minor_ver < SSL_MINOR_VERSION_2 ) - { - /* - * Save IV in SSL3 and TLS1 - */ - memcpy( ssl->transform_out->iv_enc, - ssl->transform_out->cipher_ctx_enc.iv, - ssl->transform_out->ivlen ); - } -#endif - break; - -#if defined(POLARSSL_CAMELLIA_C) - case POLARSSL_CIPHER_CAMELLIA_128_CBC: - case POLARSSL_CIPHER_CAMELLIA_256_CBC: - camellia_crypt_cbc( (camellia_context *) ssl->transform_out->ctx_enc, - CAMELLIA_ENCRYPT, enc_msglen, - ssl->transform_out->iv_enc, enc_msg, enc_msg ); - break; -#endif - - default: - return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE ); + if( ssl->minor_ver < SSL_MINOR_VERSION_2 ) + { + /* + * Save IV in SSL3 and TLS1 + */ + memcpy( ssl->transform_out->iv_enc, + ssl->transform_out->cipher_ctx_enc.iv, + ssl->transform_out->ivlen ); } +#endif } for( i = 8; i > 0; i-- ) @@ -1307,76 +1255,44 @@ static int ssl_decrypt_buf( ssl_context *ssl ) } #endif /* POLARSSL_SSL_PROTO_TLS1_1 || POLARSSL_SSL_PROTO_TLS1_2 */ - switch( ssl->transform_in->ciphersuite_info->cipher ) + if( ( ret = cipher_reset( &ssl->transform_in->cipher_ctx_dec, + ssl->transform_in->iv_dec ) ) != 0 ) { -#if defined(POLARSSL_DES_C) - case POLARSSL_CIPHER_DES_CBC: - des_crypt_cbc( (des_context *) ssl->transform_in->ctx_dec, - DES_DECRYPT, dec_msglen, - ssl->transform_in->iv_dec, dec_msg, dec_msg_result ); - break; + return( ret ); + } - case POLARSSL_CIPHER_DES_EDE3_CBC: - des3_crypt_cbc( (des3_context *) ssl->transform_in->ctx_dec, - DES_DECRYPT, dec_msglen, - ssl->transform_in->iv_dec, dec_msg, dec_msg_result ); - break; -#endif + if( ( ret = cipher_update( &ssl->transform_in->cipher_ctx_dec, + dec_msg, dec_msglen, dec_msg_result, + &olen ) ) != 0 ) + { + return( ret ); + } - case POLARSSL_CIPHER_AES_128_CBC: - case POLARSSL_CIPHER_AES_256_CBC: - if( ( ret = cipher_reset( &ssl->transform_in->cipher_ctx_dec, - ssl->transform_in->iv_dec ) ) != 0 ) - { - return( ret ); - } + dec_msglen -= olen; + if( ( ret = cipher_finish( &ssl->transform_in->cipher_ctx_dec, + dec_msg_result + olen, &olen ) ) != 0 ) + { + return( ret ); + } - if( ( ret = cipher_update( &ssl->transform_in->cipher_ctx_dec, - dec_msg, dec_msglen, dec_msg_result, - &olen ) ) != 0 ) - { - return( ret ); - } - - dec_msglen -= olen; - if( ( ret = cipher_finish( &ssl->transform_in->cipher_ctx_dec, - dec_msg_result + olen, &olen ) ) != 0 ) - { - return( ret ); - } - - if( dec_msglen != olen ) - { - SSL_DEBUG_MSG( 1, ( "total encrypted length incorrect" ) ); - // TODO Real error number - return( -1 ); - } + if( dec_msglen != olen ) + { + SSL_DEBUG_MSG( 1, ( "total encrypted length incorrect" ) ); + // TODO Real error number + return( -1 ); + } #if defined(POLARSSL_SSL_PROTO_SSL3) || defined(POLARSSL_SSL_PROTO_TLS1) - if( ssl->minor_ver < SSL_MINOR_VERSION_2 ) - { - /* - * Save IV in SSL3 and TLS1 - */ - memcpy( ssl->transform_in->iv_dec, - ssl->transform_in->cipher_ctx_dec.iv, - ssl->transform_in->ivlen ); - } -#endif - break; - -#if defined(POLARSSL_CAMELLIA_C) - case POLARSSL_CIPHER_CAMELLIA_128_CBC: - case POLARSSL_CIPHER_CAMELLIA_256_CBC: - camellia_crypt_cbc( (camellia_context *) ssl->transform_in->ctx_dec, - CAMELLIA_DECRYPT, dec_msglen, - ssl->transform_in->iv_dec, dec_msg, dec_msg_result ); - break; -#endif - - default: - return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE ); + if( ssl->minor_ver < SSL_MINOR_VERSION_2 ) + { + /* + * Save IV in SSL3 and TLS1 + */ + memcpy( ssl->transform_in->iv_dec, + ssl->transform_in->cipher_ctx_dec.iv, + ssl->transform_in->ivlen ); } +#endif padlen = 1 + ssl->in_msg[ssl->in_msglen - 1]; From 9241be7ac56cf5bf76487e77f710961eaddc762b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Sat, 31 Aug 2013 17:31:03 +0200 Subject: [PATCH 07/23] Change cipher prototypes for GCM --- include/polarssl/cipher.h | 22 ++++++++++--- include/polarssl/gcm.h | 8 ++--- library/cipher.c | 41 ++++++++++++++++++++----- library/cipher_wrap.c | 4 +-- library/gcm.c | 3 +- library/pkcs12.c | 7 +++-- library/pkcs5.c | 7 +++-- programs/aes/crypt_and_hash.c | 8 ++--- tests/suites/test_suite_cipher.function | 33 ++++++++++++-------- 9 files changed, 94 insertions(+), 39 deletions(-) diff --git a/include/polarssl/cipher.h b/include/polarssl/cipher.h index 67ca28ccf..ef037be5d 100644 --- a/include/polarssl/cipher.h +++ b/include/polarssl/cipher.h @@ -320,7 +320,7 @@ static inline cipher_mode_t cipher_get_cipher_mode( const cipher_context_t *ctx * \param ctx cipher's context. Must have been initialised. * * \return size of the cipher's IV, or 0 if ctx has not been - * initialised. + * initialised or accepts IV of various sizes. */ static inline int cipher_get_iv_size( const cipher_context_t *ctx ) { @@ -432,11 +432,18 @@ int cipher_set_padding_mode( cipher_context_t *ctx, cipher_padding_t mode ); * * \param ctx generic cipher context * \param iv IV to use or NONCE_COUNTER in the case of a CTR-mode cipher + * \param iv_len IV length for ciphers with variable-size IV, + * Discared by ciphers with fixed-size IV. + * \param ad Additional data for AEAD ciphers, or discarded. + * May be NULL only if ad_len is 0. + * \param ad_len Length of ad for AEAD ciphers, or discarded. * * \returns 0 on success, POLARSSL_ERR_CIPHER_BAD_INPUT_DATA * if parameter verification fails. */ -int cipher_reset( cipher_context_t *ctx, const unsigned char *iv ); +int cipher_reset( cipher_context_t *ctx, + const unsigned char *iv, size_t iv_len, + const unsigned char *ad, size_t ad_len ); /** * \brief Generic cipher update function. Encrypts/decrypts @@ -471,8 +478,13 @@ int cipher_update( cipher_context_t *ctx, const unsigned char *input, size_t ile * the last block, and written to the output buffer. * * \param ctx Generic cipher context - * \param output buffer to write data to. Needs block_size data available. + * \param output buffer to write data to. Needs block_size available. * \param olen length of the data written to the output buffer. + * \param tag Ignore by non-AEAD ciphers. For AEAD ciphers: + * - on encryption: buffer to write the tag; + * - on decryption: tag to verify. + * May be NULL if tag_len is zero. + * \param tag_len Length of the tag to write/check for AEAD ciphers. * * \returns 0 on success, POLARSSL_ERR_CIPHER_BAD_INPUT_DATA if * parameter verification fails, @@ -481,7 +493,9 @@ int cipher_update( cipher_context_t *ctx, const unsigned char *input, size_t ile * POLARSSL_ERR_CIPHER_INVALID_PADDING on invalid padding * while decrypting or a cipher specific error code. */ -int cipher_finish( cipher_context_t *ctx, unsigned char *output, size_t *olen); +int cipher_finish( cipher_context_t *ctx, + unsigned char *output, size_t *olen, + unsigned char *tag, size_t tag_len ); /** * \brief Checkup routine diff --git a/include/polarssl/gcm.h b/include/polarssl/gcm.h index 2bed34288..dc058dcd7 100644 --- a/include/polarssl/gcm.h +++ b/include/polarssl/gcm.h @@ -146,7 +146,7 @@ int gcm_auth_decrypt( gcm_context *ctx, * \param mode GCM_ENCRYPT or GCM_DECRYPT * \param iv initialization vector * \param iv_len length of IV - * \param add additional data + * \param add additional data (or NULL if length is 0) * \param add_len length of additional data * * \return 0 if successful @@ -182,14 +182,14 @@ int gcm_update( gcm_context *ctx, /** * \brief Generic GCM finalisation function. Wraps up the GCM stream - * and generated the tag. The tag can have a maximum length of + * and generates the tag. The tag can have a maximum length of * 16 bytes. * * \param ctx GCM context - * \param tag buffer for holding the tag + * \param tag buffer for holding the tag (may be NULL if tag_len is 0) * \param tag_len length of the tag to generate * - * \return 0 if successful or POLARSSL_ERR_GCM_BAD_INPUT + * \return 0 if successful or POLARSSL_ERR_GCM_BAD_INPUT */ int gcm_finish( gcm_context *ctx, unsigned char *tag, diff --git a/library/cipher.c b/library/cipher.c index 733f6e5f9..d7cac05f0 100644 --- a/library/cipher.c +++ b/library/cipher.c @@ -396,7 +396,9 @@ int cipher_setkey( cipher_context_t *ctx, const unsigned char *key, return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA; } -int cipher_reset( cipher_context_t *ctx, const unsigned char *iv ) +int cipher_reset( cipher_context_t *ctx, + const unsigned char *iv, size_t iv_len, + const unsigned char *ad, size_t ad_len ) { if( NULL == ctx || NULL == ctx->cipher_info || NULL == iv ) return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA; @@ -406,11 +408,13 @@ int cipher_reset( cipher_context_t *ctx, const unsigned char *iv ) #if defined(POLARSSL_GCM_C) if( POLARSSL_MODE_GCM == ctx->cipher_info->mode ) { - // TODO: allow other IV length - // TODO: allow additional data return gcm_starts( ctx->cipher_ctx, ctx->operation, - iv, 12, (unsigned char *) "", 0 ); + iv, iv_len, ad, ad_len ); } +#else + ((void) ad); + ((void) ad_len); + ((void) iv_len); #endif memcpy( ctx->iv, iv, cipher_get_iv_size( ctx ) ); @@ -742,7 +746,9 @@ static int get_no_padding( unsigned char *input, size_t input_len, return 0; } -int cipher_finish( cipher_context_t *ctx, unsigned char *output, size_t *olen) +int cipher_finish( cipher_context_t *ctx, + unsigned char *output, size_t *olen, + unsigned char *tag, size_t tag_len ) { int ret = 0; @@ -761,8 +767,9 @@ int cipher_finish( cipher_context_t *ctx, unsigned char *output, size_t *olen) #if defined(POLARSSL_GCM_C) if( POLARSSL_MODE_GCM == ctx->cipher_info->mode ) { - size_t tag_len = 0; // TODO - unsigned char tag[16]; + unsigned char check_tag[16]; + size_t i; + int diff; if( 0 != ( ret = gcm_update( ctx->cipher_ctx, ctx->unprocessed_len, ctx->unprocessed_data, @@ -773,11 +780,29 @@ int cipher_finish( cipher_context_t *ctx, unsigned char *output, size_t *olen) *olen += ctx->unprocessed_len; - if( 0 != ( ret = gcm_finish( ctx->cipher_ctx, tag, tag_len ) ) ) + if( 0 != ( ret = gcm_finish( ctx->cipher_ctx, check_tag, tag_len ) ) ) return( ret ); + /* On encryption, write the tag */ + if( POLARSSL_ENCRYPT == ctx->operation ) + { + if( tag_len != 0 ) + memcpy( tag, check_tag, tag_len ); + return( 0 ); + } + + /* On decryption, check the tag (in "constant-time") */ + for( diff = 0, i = 0; i < tag_len; i++ ) + diff |= tag[i] ^ check_tag[i]; + + if( diff != 0 ) + return( POLARSSL_ERR_GCM_AUTH_FAILED ); + return( 0 ); } +#else + ((void) tag); + ((void) tag_len); #endif if( POLARSSL_MODE_CBC == ctx->cipher_info->mode ) diff --git a/library/cipher_wrap.c b/library/cipher_wrap.c index c8eee5432..5c9810056 100644 --- a/library/cipher_wrap.c +++ b/library/cipher_wrap.c @@ -271,7 +271,7 @@ const cipher_info_t aes_128_gcm_info = { POLARSSL_MODE_GCM, 128, "AES-128-GCM", - 16, + 0, 16, &gcm_aes_info }; @@ -281,7 +281,7 @@ const cipher_info_t aes_256_gcm_info = { POLARSSL_MODE_GCM, 256, "AES-256-GCM", - 16, + 0, 16, &gcm_aes_info }; diff --git a/library/gcm.c b/library/gcm.c index 104fda3a4..99036a05c 100644 --- a/library/gcm.c +++ b/library/gcm.c @@ -296,7 +296,8 @@ int gcm_finish( gcm_context *ctx, if( tag_len > 16 ) return( POLARSSL_ERR_GCM_BAD_INPUT ); - memcpy( tag, ctx->base_ectr, tag_len ); + if( tag_len != 0 ) + memcpy( tag, ctx->base_ectr, tag_len ); if( orig_len || orig_add_len ) { diff --git a/library/pkcs12.c b/library/pkcs12.c index e0d7207ce..9ccb60ab7 100644 --- a/library/pkcs12.c +++ b/library/pkcs12.c @@ -184,7 +184,7 @@ int pkcs12_pbe( asn1_buf *pbe_params, int mode, if( ( ret = cipher_setkey( &cipher_ctx, key, keylen, mode ) ) != 0 ) goto exit; - if( ( ret = cipher_reset( &cipher_ctx, iv ) ) != 0 ) + if( ( ret = cipher_reset( &cipher_ctx, iv, 0, NULL, 0 ) ) != 0 ) goto exit; if( ( ret = cipher_update( &cipher_ctx, data, len, @@ -193,8 +193,11 @@ int pkcs12_pbe( asn1_buf *pbe_params, int mode, goto exit; } - if( ( ret = cipher_finish( &cipher_ctx, output + olen, &olen ) ) != 0 ) + if( ( ret = cipher_finish( &cipher_ctx, output + olen, &olen, NULL, 0 ) ) + != 0 ) + { ret = POLARSSL_ERR_PKCS12_PASSWORD_MISMATCH; + } exit: cipher_free_ctx( &cipher_ctx ); diff --git a/library/pkcs5.c b/library/pkcs5.c index 9e3ce9332..2b6a75a92 100644 --- a/library/pkcs5.c +++ b/library/pkcs5.c @@ -187,7 +187,7 @@ int pkcs5_pbes2( asn1_buf *pbe_params, int mode, if( ( ret = cipher_setkey( &cipher_ctx, key, keylen, mode ) ) != 0 ) goto exit; - if( ( ret = cipher_reset( &cipher_ctx, iv ) ) != 0 ) + if( ( ret = cipher_reset( &cipher_ctx, iv, 0, NULL, 0 ) ) != 0 ) goto exit; if( ( ret = cipher_update( &cipher_ctx, data, datalen, @@ -196,8 +196,11 @@ int pkcs5_pbes2( asn1_buf *pbe_params, int mode, goto exit; } - if( ( ret = cipher_finish( &cipher_ctx, output + olen, &olen ) ) != 0 ) + if( ( ret = cipher_finish( &cipher_ctx, output + olen, &olen, NULL, 0 ) ) + != 0 ) + { ret = POLARSSL_ERR_PKCS5_PASSWORD_MISMATCH; + } exit: md_free_ctx( &md_ctx ); diff --git a/programs/aes/crypt_and_hash.c b/programs/aes/crypt_and_hash.c index 47b17d523..a9b862e7a 100644 --- a/programs/aes/crypt_and_hash.c +++ b/programs/aes/crypt_and_hash.c @@ -306,7 +306,7 @@ int main( int argc, char *argv[] ) fprintf( stderr, "cipher_setkey() returned error\n"); goto exit; } - if( cipher_reset( &cipher_ctx, IV ) != 0 ) + if( cipher_reset( &cipher_ctx, IV, 16, NULL, 0 ) != 0 ) { fprintf( stderr, "cipher_reset() returned error\n"); goto exit; @@ -338,7 +338,7 @@ int main( int argc, char *argv[] ) } } - if( cipher_finish( &cipher_ctx, output, &olen ) != 0 ) + if( cipher_finish( &cipher_ctx, output, &olen, NULL, 0 ) != 0 ) { fprintf( stderr, "cipher_finish() returned error\n" ); goto exit; @@ -424,7 +424,7 @@ int main( int argc, char *argv[] ) cipher_setkey( &cipher_ctx, digest, cipher_info->key_length, POLARSSL_DECRYPT ); - cipher_reset( &cipher_ctx, IV); + cipher_reset( &cipher_ctx, IV, 16, NULL, 0 ); md_hmac_starts( &md_ctx, digest, 32 ); @@ -455,7 +455,7 @@ int main( int argc, char *argv[] ) /* * Write the final block of data */ - cipher_finish( &cipher_ctx, output, &olen ); + cipher_finish( &cipher_ctx, output, &olen, NULL, 0 ); if( fwrite( output, 1, olen, fout ) != olen ) { diff --git a/tests/suites/test_suite_cipher.function b/tests/suites/test_suite_cipher.function index 537720872..b1814fab0 100644 --- a/tests/suites/test_suite_cipher.function +++ b/tests/suites/test_suite_cipher.function @@ -14,6 +14,8 @@ void enc_dec_buf( int cipher_id, char *cipher_string, int key_len, size_t length = length_val; unsigned char key[32]; unsigned char iv[16]; + unsigned char ad[13]; + unsigned char tag[16]; const cipher_info_t *cipher_info; cipher_context_t ctx_dec; @@ -35,6 +37,8 @@ void enc_dec_buf( int cipher_id, char *cipher_string, int key_len, memset( inbuf, 5, 64 ); memset( encbuf, 0, 64 ); memset( decbuf, 0, 64 ); + memset( tag, 0, 16 ); + memset( ad, 0x2a, 13 ); /* Check and get info structures */ cipher_info = cipher_info_from_type( cipher_id ); @@ -54,8 +58,8 @@ void enc_dec_buf( int cipher_id, char *cipher_string, int key_len, TEST_ASSERT( 0 == cipher_set_padding_mode( &ctx_enc, pad_mode ) ); } - TEST_ASSERT( 0 == cipher_reset( &ctx_dec, iv ) ); - TEST_ASSERT( 0 == cipher_reset( &ctx_enc, iv ) ); + TEST_ASSERT( 0 == cipher_reset( &ctx_dec, iv, 16, ad, 13 ) ); + TEST_ASSERT( 0 == cipher_reset( &ctx_enc, iv, 16, ad, 13 ) ); /* encode length number of bytes from inbuf */ TEST_ASSERT( 0 == cipher_update( &ctx_enc, inbuf, length, encbuf, &outlen ) ); @@ -66,7 +70,8 @@ void enc_dec_buf( int cipher_id, char *cipher_string, int key_len, total_len < length && total_len + cipher_get_block_size( &ctx_enc ) > length ) ); - TEST_ASSERT( 0 == cipher_finish( &ctx_enc, encbuf + outlen, &outlen ) ); + TEST_ASSERT( 0 == cipher_finish( &ctx_enc, encbuf + outlen, &outlen, + tag, 16 ) ); total_len += outlen; TEST_ASSERT( total_len == length || @@ -83,7 +88,8 @@ void enc_dec_buf( int cipher_id, char *cipher_string, int key_len, total_len < length && total_len + cipher_get_block_size( &ctx_dec ) >= length ) ); - TEST_ASSERT( 0 == cipher_finish( &ctx_dec, decbuf + outlen, &outlen ) ); + TEST_ASSERT( 0 == cipher_finish( &ctx_dec, decbuf + outlen, &outlen, + tag, 16 ) ); total_len += outlen; TEST_ASSERT( total_len == length ); @@ -127,11 +133,11 @@ void enc_fail( int cipher_id, int pad_mode, int key_len, TEST_ASSERT( 0 == cipher_init_ctx( &ctx, cipher_info ) ); TEST_ASSERT( 0 == cipher_setkey( &ctx, key, key_len, POLARSSL_ENCRYPT ) ); TEST_ASSERT( 0 == cipher_set_padding_mode( &ctx, pad_mode ) ); - TEST_ASSERT( 0 == cipher_reset( &ctx, iv ) ); + TEST_ASSERT( 0 == cipher_reset( &ctx, iv, 16, NULL, 0 ) ); /* encode length number of bytes from inbuf */ TEST_ASSERT( 0 == cipher_update( &ctx, inbuf, length, encbuf, &outlen ) ); - TEST_ASSERT( ret == cipher_finish( &ctx, encbuf + outlen, &outlen ) ); + TEST_ASSERT( ret == cipher_finish( &ctx, encbuf + outlen, &outlen, NULL, 0 ) ); /* done */ TEST_ASSERT( 0 == cipher_free_ctx( &ctx ) ); @@ -168,12 +174,13 @@ void dec_empty_buf() TEST_ASSERT( 0 == cipher_setkey( &ctx_dec, key, 128, POLARSSL_DECRYPT ) ); - TEST_ASSERT( 0 == cipher_reset( &ctx_dec, iv ) ); + TEST_ASSERT( 0 == cipher_reset( &ctx_dec, iv, 16, NULL, 0 ) ); /* decode 0-byte string */ TEST_ASSERT( 0 == cipher_update( &ctx_dec, encbuf, 0, decbuf, &outlen ) ); TEST_ASSERT( 0 == outlen ); - TEST_ASSERT( POLARSSL_ERR_CIPHER_FULL_BLOCK_EXPECTED == cipher_finish( &ctx_dec, decbuf + outlen, &outlen ) ); + TEST_ASSERT( POLARSSL_ERR_CIPHER_FULL_BLOCK_EXPECTED == cipher_finish( + &ctx_dec, decbuf + outlen, &outlen, NULL, 0 ) ); TEST_ASSERT( 0 == outlen ); TEST_ASSERT( 0 == cipher_free_ctx( &ctx_dec ) ); @@ -221,8 +228,8 @@ void enc_dec_buf_multipart( int cipher_id, int key_len, int first_length_val, TEST_ASSERT( 0 == cipher_setkey( &ctx_dec, key, key_len, POLARSSL_DECRYPT ) ); TEST_ASSERT( 0 == cipher_setkey( &ctx_enc, key, key_len, POLARSSL_ENCRYPT ) ); - TEST_ASSERT( 0 == cipher_reset( &ctx_dec, iv ) ); - TEST_ASSERT( 0 == cipher_reset( &ctx_enc, iv ) ); + TEST_ASSERT( 0 == cipher_reset( &ctx_dec, iv, 16, NULL, 0 ) ); + TEST_ASSERT( 0 == cipher_reset( &ctx_enc, iv, 16, NULL, 0 ) ); /* encode length number of bytes from inbuf */ TEST_ASSERT( 0 == cipher_update( &ctx_enc, inbuf, first_length, encbuf, &outlen ) ); @@ -234,7 +241,8 @@ void enc_dec_buf_multipart( int cipher_id, int key_len, int first_length_val, totaloutlen < length && totaloutlen + cipher_get_block_size( &ctx_enc ) > length ) ); - TEST_ASSERT( 0 == cipher_finish( &ctx_enc, encbuf + totaloutlen, &outlen ) ); + TEST_ASSERT( 0 == cipher_finish( &ctx_enc, encbuf + totaloutlen, &outlen, + NULL, 0 ) ); totaloutlen += outlen; TEST_ASSERT( totaloutlen == length || ( totaloutlen % cipher_get_block_size( &ctx_enc ) == 0 && @@ -250,7 +258,8 @@ void enc_dec_buf_multipart( int cipher_id, int key_len, int first_length_val, totaloutlen < length && totaloutlen + cipher_get_block_size( &ctx_dec ) >= length ) ); - TEST_ASSERT( 0 == cipher_finish( &ctx_dec, decbuf + outlen, &outlen ) ); + TEST_ASSERT( 0 == cipher_finish( &ctx_dec, decbuf + outlen, &outlen, + NULL, 0 ) ); totaloutlen += outlen; TEST_ASSERT( totaloutlen == length ); From ea6ad3f6e5f358ca9a9a82471ba0a77b7f1781a3 Mon Sep 17 00:00:00 2001 From: Paul Bakker Date: Mon, 2 Sep 2013 14:57:01 +0200 Subject: [PATCH 08/23] ARC4 ciphersuites using only cipher layer --- library/ssl_tls.c | 162 ++++++++++++++++++++++++++++++++++------------ 1 file changed, 122 insertions(+), 40 deletions(-) diff --git a/library/ssl_tls.c b/library/ssl_tls.c index bb939cbd8..52d4b33cd 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -633,15 +633,7 @@ int ssl_derive_keys( ssl_context *ssl ) switch( cipher_info->type ) { -#if defined(POLARSSL_ARC4_C) case POLARSSL_CIPHER_ARC4_128: - arc4_setup( (arc4_context *) transform->ctx_enc, key1, - transform->keylen ); - arc4_setup( (arc4_context *) transform->ctx_dec, key2, - transform->keylen ); - break; -#endif - case POLARSSL_CIPHER_DES_EDE3_CBC: case POLARSSL_CIPHER_CAMELLIA_128_CBC: case POLARSSL_CIPHER_CAMELLIA_256_CBC: @@ -654,36 +646,58 @@ int ssl_derive_keys( ssl_context *ssl ) return( ret ); } - if( ( ret = cipher_setkey( &transform->cipher_ctx_enc, key1, - cipher_info->key_length, - POLARSSL_ENCRYPT ) ) != 0 ) - { - return( ret ); - } - - if( ( ret = cipher_set_padding_mode( &transform->cipher_ctx_enc, - POLARSSL_PADDING_NONE ) ) != 0 ) - { - return( ret ); - } - if( ( ret = cipher_init_ctx( &transform->cipher_ctx_dec, cipher_info ) ) != 0 ) { return( ret ); } - if( ( ret = cipher_setkey( &transform->cipher_ctx_dec, key2, - cipher_info->key_length, - POLARSSL_DECRYPT ) ) != 0 ) + if( cipher_info->type == POLARSSL_CIPHER_ARC4_128 ) { - return( ret ); + if( ( ret = cipher_setkey( &transform->cipher_ctx_enc, key1, + cipher_info->key_length / 8, + POLARSSL_ENCRYPT ) ) != 0 ) + { + return( ret ); + } + + if( ( ret = cipher_setkey( &transform->cipher_ctx_dec, key2, + cipher_info->key_length / 8, + POLARSSL_DECRYPT ) ) != 0 ) + { + return( ret ); + } + } + else + { + if( ( ret = cipher_setkey( &transform->cipher_ctx_enc, key1, + cipher_info->key_length, + POLARSSL_ENCRYPT ) ) != 0 ) + { + return( ret ); + } + + if( ( ret = cipher_setkey( &transform->cipher_ctx_dec, key2, + cipher_info->key_length, + POLARSSL_DECRYPT ) ) != 0 ) + { + return( ret ); + } } - if( ( ret = cipher_set_padding_mode( &transform->cipher_ctx_dec, - POLARSSL_PADDING_NONE ) ) != 0 ) + if( cipher_info->mode == POLARSSL_MODE_CBC ) { - return( ret ); + if( ( ret = cipher_set_padding_mode( &transform->cipher_ctx_enc, + POLARSSL_PADDING_NONE ) ) != 0 ) + { + return( ret ); + } + + if( ( ret = cipher_set_padding_mode( &transform->cipher_ctx_dec, + POLARSSL_PADDING_NONE ) ) != 0 ) + { + return( ret ); + } } break; @@ -925,9 +939,11 @@ static int ssl_encrypt_buf( ssl_context *ssl ) } else #endif /* POLARSSL_CIPHER_NULL_CIPHER */ -#if defined(POLARSSL_ARC4_C) if( ssl->transform_out->ciphersuite_info->cipher == POLARSSL_CIPHER_ARC4_128 ) { + int ret; + size_t olen = 0; + padlen = 0; SSL_DEBUG_MSG( 3, ( "before encrypt: msglen = %d, " @@ -937,12 +953,43 @@ static int ssl_encrypt_buf( ssl_context *ssl ) SSL_DEBUG_BUF( 4, "before encrypt: output payload", ssl->out_msg, ssl->out_msglen ); - arc4_crypt( (arc4_context *) ssl->transform_out->ctx_enc, - ssl->out_msglen, ssl->out_msg, - ssl->out_msg ); + if( ( ret = cipher_reset( &ssl->transform_out->cipher_ctx_enc, + ssl->transform_out->iv_enc, + ssl->transform_out->ivlen, NULL, 0 ) ) != 0 ) + { + return( ret ); + } + + if( ( ret = cipher_update( &ssl->transform_out->cipher_ctx_enc, + ssl->out_msg, ssl->out_msglen, ssl->out_msg, + &olen ) ) != 0 ) + { + return( ret ); + } + + if( ssl->out_msglen != olen ) + { + SSL_DEBUG_MSG( 1, ( "total encrypted length incorrect %d %d", + ssl->out_msglen, olen ) ); + // TODO Real error number + return( -1 ); + } + + if( ( ret = cipher_finish( &ssl->transform_out->cipher_ctx_enc, + ssl->out_msg + olen, &olen, NULL, 0 ) ) != 0 ) + { + return( ret ); + } + + if( 0 != olen ) + { + SSL_DEBUG_MSG( 1, ( "total encrypted length incorrect %d %d", + 0, olen ) ); + // TODO Real error number + return( -1 ); + } } else -#endif /* POLARSSL_ARC4_C */ #if defined(POLARSSL_GCM_C) if( ssl->transform_out->ciphersuite_info->cipher == POLARSSL_CIPHER_AES_128_GCM || ssl->transform_out->ciphersuite_info->cipher == POLARSSL_CIPHER_AES_256_GCM ) @@ -1064,7 +1111,8 @@ static int ssl_encrypt_buf( ssl_context *ssl ) ssl->out_iv, ssl->out_msglen ); if( ( ret = cipher_reset( &ssl->transform_out->cipher_ctx_enc, - ssl->transform_out->iv_enc ) ) != 0 ) + ssl->transform_out->iv_enc, + ssl->transform_out->ivlen, NULL, 0 ) ) != 0 ) { return( ret ); } @@ -1079,7 +1127,7 @@ static int ssl_encrypt_buf( ssl_context *ssl ) enc_msglen -= olen; if( ( ret = cipher_finish( &ssl->transform_out->cipher_ctx_enc, - enc_msg + olen, &olen ) ) != 0 ) + enc_msg + olen, &olen, NULL, 0 ) ) != 0 ) { return( ret ); } @@ -1140,11 +1188,44 @@ static int ssl_decrypt_buf( ssl_context *ssl ) #if defined(POLARSSL_ARC4_C) if( ssl->transform_in->ciphersuite_info->cipher == POLARSSL_CIPHER_ARC4_128 ) { + int ret; + size_t olen = 0; + padlen = 0; - arc4_crypt( (arc4_context *) ssl->transform_in->ctx_dec, - ssl->in_msglen, ssl->in_msg, - ssl->in_msg ); + if( ( ret = cipher_reset( &ssl->transform_in->cipher_ctx_dec, + ssl->transform_in->iv_dec, + ssl->transform_in->ivlen, NULL, 0 ) ) != 0 ) + { + return( ret ); + } + + if( ( ret = cipher_update( &ssl->transform_in->cipher_ctx_dec, + ssl->in_msg, ssl->in_msglen, ssl->in_msg, + &olen ) ) != 0 ) + { + return( ret ); + } + + if( ssl->in_msglen != olen ) + { + SSL_DEBUG_MSG( 1, ( "total encrypted length incorrect" ) ); + // TODO Real error number + return( -1 ); + } + + if( ( ret = cipher_finish( &ssl->transform_in->cipher_ctx_dec, + ssl->in_msg + olen, &olen, NULL, 0 ) ) != 0 ) + { + return( ret ); + } + + if( 0 != olen ) + { + SSL_DEBUG_MSG( 1, ( "total encrypted length incorrect" ) ); + // TODO Real error number + return( -1 ); + } } else #endif /* POLARSSL_ARC4_C */ @@ -1256,7 +1337,8 @@ static int ssl_decrypt_buf( ssl_context *ssl ) #endif /* POLARSSL_SSL_PROTO_TLS1_1 || POLARSSL_SSL_PROTO_TLS1_2 */ if( ( ret = cipher_reset( &ssl->transform_in->cipher_ctx_dec, - ssl->transform_in->iv_dec ) ) != 0 ) + ssl->transform_in->iv_dec, + ssl->transform_in->ivlen, NULL, 0 ) ) != 0 ) { return( ret ); } @@ -1270,7 +1352,7 @@ static int ssl_decrypt_buf( ssl_context *ssl ) dec_msglen -= olen; if( ( ret = cipher_finish( &ssl->transform_in->cipher_ctx_dec, - dec_msg_result + olen, &olen ) ) != 0 ) + dec_msg_result + olen, &olen, NULL, 0 ) ) != 0 ) { return( ret ); } From 9c853b910c612775b4ad0db578ad76d8c7ba8b45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Tue, 3 Sep 2013 13:04:44 +0200 Subject: [PATCH 09/23] Split cipher_set_iv() out of cipher_reset() --- include/polarssl/cipher.h | 35 +++++++++++++++++++------ library/cipher.c | 27 ++++++++++++++----- library/pkcs12.c | 5 +++- library/pkcs5.c | 5 +++- programs/aes/crypt_and_hash.c | 10 +++++-- tests/suites/test_suite_cipher.function | 23 +++++++++++----- 6 files changed, 79 insertions(+), 26 deletions(-) diff --git a/include/polarssl/cipher.h b/include/polarssl/cipher.h index ef037be5d..e540c925f 100644 --- a/include/polarssl/cipher.h +++ b/include/polarssl/cipher.h @@ -185,7 +185,8 @@ typedef struct { /** Name of the cipher */ const char * name; - /** IV size, in bytes */ + /** IV/NONCE size, in bytes, for ciphers with fixed-length IVs), or + * 0 for ciphers with variable-length IVs or not using IVs */ unsigned int iv_size; /** block size, in bytes */ @@ -222,6 +223,9 @@ typedef struct { /** Current IV or NONCE_COUNTER for CTR-mode */ unsigned char iv[POLARSSL_MAX_IV_LENGTH]; + /** IV size in bytes (for ciphers with variable-length IVs) */ + size_t iv_size; + /** Cipher-specific context */ void *cipher_ctx; } cipher_context_t; @@ -315,18 +319,22 @@ static inline cipher_mode_t cipher_get_cipher_mode( const cipher_context_t *ctx } /** - * \brief Returns the size of the cipher's IV. + * \brief Returns the size of the cipher's IV/NONCE in bytes. * * \param ctx cipher's context. Must have been initialised. * - * \return size of the cipher's IV, or 0 if ctx has not been - * initialised or accepts IV of various sizes. + * \return If IV has not been set yet: desired size for ciphers + * with fixed-size IVs, 0 for other ciphers. + * If IV has already been set: actual size. */ static inline int cipher_get_iv_size( const cipher_context_t *ctx ) { if( NULL == ctx || NULL == ctx->cipher_info ) return 0; + if( ctx->iv_size != 0 ) + return ctx->iv_size; + return ctx->cipher_info->iv_size; } @@ -427,13 +435,25 @@ int cipher_setkey( cipher_context_t *ctx, const unsigned char *key, int key_leng */ int cipher_set_padding_mode( cipher_context_t *ctx, cipher_padding_t mode ); +/** + * \brief Set the initialization vector (IV) or nonce + * + * \param iv IV to use (or NONCE_COUNTER for CTR-mode ciphers) + * \param iv_len IV length for ciphers with variable-size IV, + * Discarded by ciphers with fixed-size IV. + * + * \returns O on success, or POLARSSL_ERR_CIPHER_BAD_INPUT_DATA + * + * \note Some ciphers don't use IVs nor NONCE. For these + * ciphers, this function has no effect. + */ +int cipher_set_iv( cipher_context_t *ctx, + const unsigned char *iv, size_t iv_len ); + /** * \brief Reset the given context, setting the IV to iv * * \param ctx generic cipher context - * \param iv IV to use or NONCE_COUNTER in the case of a CTR-mode cipher - * \param iv_len IV length for ciphers with variable-size IV, - * Discared by ciphers with fixed-size IV. * \param ad Additional data for AEAD ciphers, or discarded. * May be NULL only if ad_len is 0. * \param ad_len Length of ad for AEAD ciphers, or discarded. @@ -442,7 +462,6 @@ int cipher_set_padding_mode( cipher_context_t *ctx, cipher_padding_t mode ); * if parameter verification fails. */ int cipher_reset( cipher_context_t *ctx, - const unsigned char *iv, size_t iv_len, const unsigned char *ad, size_t ad_len ); /** diff --git a/library/cipher.c b/library/cipher.c index d7cac05f0..d90abe1ab 100644 --- a/library/cipher.c +++ b/library/cipher.c @@ -396,29 +396,42 @@ int cipher_setkey( cipher_context_t *ctx, const unsigned char *key, return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA; } -int cipher_reset( cipher_context_t *ctx, - const unsigned char *iv, size_t iv_len, - const unsigned char *ad, size_t ad_len ) +int cipher_set_iv( cipher_context_t *ctx, + const unsigned char *iv, size_t iv_len ) { + size_t fixed_iv_size; + if( NULL == ctx || NULL == ctx->cipher_info || NULL == iv ) return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA; + fixed_iv_size = cipher_get_iv_size( ctx ); + + /* 0 means variable size (or no IV): use given len */ + if( fixed_iv_size == 0 ) + fixed_iv_size = iv_len; + + memcpy( ctx->iv, iv, fixed_iv_size ); + ctx->iv_size = fixed_iv_size; + + return 0; +} + +int cipher_reset( cipher_context_t *ctx, + const unsigned char *ad, size_t ad_len ) +{ ctx->unprocessed_len = 0; #if defined(POLARSSL_GCM_C) if( POLARSSL_MODE_GCM == ctx->cipher_info->mode ) { return gcm_starts( ctx->cipher_ctx, ctx->operation, - iv, iv_len, ad, ad_len ); + ctx->iv, ctx->iv_size, ad, ad_len ); } #else ((void) ad); ((void) ad_len); - ((void) iv_len); #endif - memcpy( ctx->iv, iv, cipher_get_iv_size( ctx ) ); - return 0; } diff --git a/library/pkcs12.c b/library/pkcs12.c index 9ccb60ab7..3634ce139 100644 --- a/library/pkcs12.c +++ b/library/pkcs12.c @@ -184,7 +184,10 @@ int pkcs12_pbe( asn1_buf *pbe_params, int mode, if( ( ret = cipher_setkey( &cipher_ctx, key, keylen, mode ) ) != 0 ) goto exit; - if( ( ret = cipher_reset( &cipher_ctx, iv, 0, NULL, 0 ) ) != 0 ) + if( ( ret = cipher_set_iv( &cipher_ctx, iv, 0 ) ) != 0 ) + goto exit; + + if( ( ret = cipher_reset( &cipher_ctx, iv, 0 ) ) != 0 ) goto exit; if( ( ret = cipher_update( &cipher_ctx, data, len, diff --git a/library/pkcs5.c b/library/pkcs5.c index 2b6a75a92..6582fd05f 100644 --- a/library/pkcs5.c +++ b/library/pkcs5.c @@ -187,7 +187,10 @@ int pkcs5_pbes2( asn1_buf *pbe_params, int mode, if( ( ret = cipher_setkey( &cipher_ctx, key, keylen, mode ) ) != 0 ) goto exit; - if( ( ret = cipher_reset( &cipher_ctx, iv, 0, NULL, 0 ) ) != 0 ) + if( ( ret = cipher_set_iv( &cipher_ctx, iv, 0 ) ) != 0 ) + goto exit; + + if( ( ret = cipher_reset( &cipher_ctx, NULL, 0 ) ) != 0 ) goto exit; if( ( ret = cipher_update( &cipher_ctx, data, datalen, diff --git a/programs/aes/crypt_and_hash.c b/programs/aes/crypt_and_hash.c index a9b862e7a..8ffdb9f94 100644 --- a/programs/aes/crypt_and_hash.c +++ b/programs/aes/crypt_and_hash.c @@ -306,7 +306,12 @@ int main( int argc, char *argv[] ) fprintf( stderr, "cipher_setkey() returned error\n"); goto exit; } - if( cipher_reset( &cipher_ctx, IV, 16, NULL, 0 ) != 0 ) + if( cipher_set_iv( &cipher_ctx, IV, 16 ) != 0 ) + { + fprintf( stderr, "cipher_set_iv() returned error\n"); + goto exit; + } + if( cipher_reset( &cipher_ctx, NULL, 0 ) != 0 ) { fprintf( stderr, "cipher_reset() returned error\n"); goto exit; @@ -424,7 +429,8 @@ int main( int argc, char *argv[] ) cipher_setkey( &cipher_ctx, digest, cipher_info->key_length, POLARSSL_DECRYPT ); - cipher_reset( &cipher_ctx, IV, 16, NULL, 0 ); + cipher_set_iv( &cipher_ctx, IV, 16 ); + cipher_reset( &cipher_ctx, NULL, 0 ); md_hmac_starts( &md_ctx, digest, 32 ); diff --git a/tests/suites/test_suite_cipher.function b/tests/suites/test_suite_cipher.function index b1814fab0..d247bab2a 100644 --- a/tests/suites/test_suite_cipher.function +++ b/tests/suites/test_suite_cipher.function @@ -58,8 +58,11 @@ void enc_dec_buf( int cipher_id, char *cipher_string, int key_len, TEST_ASSERT( 0 == cipher_set_padding_mode( &ctx_enc, pad_mode ) ); } - TEST_ASSERT( 0 == cipher_reset( &ctx_dec, iv, 16, ad, 13 ) ); - TEST_ASSERT( 0 == cipher_reset( &ctx_enc, iv, 16, ad, 13 ) ); + TEST_ASSERT( 0 == cipher_set_iv( &ctx_dec, iv, 16 ) ); + TEST_ASSERT( 0 == cipher_set_iv( &ctx_enc, iv, 16 ) ); + + TEST_ASSERT( 0 == cipher_reset( &ctx_dec, ad, 13 ) ); + TEST_ASSERT( 0 == cipher_reset( &ctx_enc, ad, 13 ) ); /* encode length number of bytes from inbuf */ TEST_ASSERT( 0 == cipher_update( &ctx_enc, inbuf, length, encbuf, &outlen ) ); @@ -133,7 +136,8 @@ void enc_fail( int cipher_id, int pad_mode, int key_len, TEST_ASSERT( 0 == cipher_init_ctx( &ctx, cipher_info ) ); TEST_ASSERT( 0 == cipher_setkey( &ctx, key, key_len, POLARSSL_ENCRYPT ) ); TEST_ASSERT( 0 == cipher_set_padding_mode( &ctx, pad_mode ) ); - TEST_ASSERT( 0 == cipher_reset( &ctx, iv, 16, NULL, 0 ) ); + TEST_ASSERT( 0 == cipher_set_iv( &ctx, iv, 16 ) ); + TEST_ASSERT( 0 == cipher_reset( &ctx, NULL, 0 ) ); /* encode length number of bytes from inbuf */ TEST_ASSERT( 0 == cipher_update( &ctx, inbuf, length, encbuf, &outlen ) ); @@ -166,7 +170,7 @@ void dec_empty_buf() memset( encbuf, 0, 64 ); memset( decbuf, 0, 64 ); - /* Initialise enc and dec contexts */ + /* Initialise context */ cipher_info = cipher_info_from_type( POLARSSL_CIPHER_AES_128_CBC ); TEST_ASSERT( NULL != cipher_info); @@ -174,7 +178,9 @@ void dec_empty_buf() TEST_ASSERT( 0 == cipher_setkey( &ctx_dec, key, 128, POLARSSL_DECRYPT ) ); - TEST_ASSERT( 0 == cipher_reset( &ctx_dec, iv, 16, NULL, 0 ) ); + TEST_ASSERT( 0 == cipher_set_iv( &ctx_dec, iv, 16 ) ); + + TEST_ASSERT( 0 == cipher_reset( &ctx_dec, NULL, 0 ) ); /* decode 0-byte string */ TEST_ASSERT( 0 == cipher_update( &ctx_dec, encbuf, 0, decbuf, &outlen ) ); @@ -228,8 +234,11 @@ void enc_dec_buf_multipart( int cipher_id, int key_len, int first_length_val, TEST_ASSERT( 0 == cipher_setkey( &ctx_dec, key, key_len, POLARSSL_DECRYPT ) ); TEST_ASSERT( 0 == cipher_setkey( &ctx_enc, key, key_len, POLARSSL_ENCRYPT ) ); - TEST_ASSERT( 0 == cipher_reset( &ctx_dec, iv, 16, NULL, 0 ) ); - TEST_ASSERT( 0 == cipher_reset( &ctx_enc, iv, 16, NULL, 0 ) ); + TEST_ASSERT( 0 == cipher_set_iv( &ctx_dec, iv, 16 ) ); + TEST_ASSERT( 0 == cipher_set_iv( &ctx_enc, iv, 16 ) ); + + TEST_ASSERT( 0 == cipher_reset( &ctx_dec, NULL, 0 ) ); + TEST_ASSERT( 0 == cipher_reset( &ctx_enc, NULL, 0 ) ); /* encode length number of bytes from inbuf */ TEST_ASSERT( 0 == cipher_update( &ctx_enc, inbuf, first_length, encbuf, &outlen ) ); From a235b5b5bd551172e0e41598c0b909119f3e2628 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Tue, 3 Sep 2013 13:25:52 +0200 Subject: [PATCH 10/23] Fix iv_len interface. cipher_info->iv_size == 0 is no longer ambiguous, and cipher_get_iv_size() always returns something useful to generate an IV. --- include/polarssl/cipher.h | 15 +++++++++------ library/cipher.c | 15 +++++++-------- library/cipher_wrap.c | 32 ++++++++++++++++++++++++++++++-- library/pkcs12.c | 4 ++-- library/pkcs5.c | 2 +- 5 files changed, 49 insertions(+), 19 deletions(-) diff --git a/include/polarssl/cipher.h b/include/polarssl/cipher.h index e540c925f..93a0015d7 100644 --- a/include/polarssl/cipher.h +++ b/include/polarssl/cipher.h @@ -185,10 +185,13 @@ typedef struct { /** Name of the cipher */ const char * name; - /** IV/NONCE size, in bytes, for ciphers with fixed-length IVs), or - * 0 for ciphers with variable-length IVs or not using IVs */ + /** IV/NONCE size, in bytes. + * For cipher that accept many sizes: recommended size */ unsigned int iv_size; + /** Flag for ciphers that accept many sizes of IV/NONCE */ + int accepts_variable_iv_size; + /** block size, in bytes */ unsigned int block_size; @@ -323,8 +326,8 @@ static inline cipher_mode_t cipher_get_cipher_mode( const cipher_context_t *ctx * * \param ctx cipher's context. Must have been initialised. * - * \return If IV has not been set yet: desired size for ciphers - * with fixed-size IVs, 0 for other ciphers. + * \return If IV has not been set yet: (recommended) IV size + * (0 for ciphers not using IV/NONCE). * If IV has already been set: actual size. */ static inline int cipher_get_iv_size( const cipher_context_t *ctx ) @@ -439,8 +442,8 @@ int cipher_set_padding_mode( cipher_context_t *ctx, cipher_padding_t mode ); * \brief Set the initialization vector (IV) or nonce * * \param iv IV to use (or NONCE_COUNTER for CTR-mode ciphers) - * \param iv_len IV length for ciphers with variable-size IV, - * Discarded by ciphers with fixed-size IV. + * \param iv_len IV length for ciphers with variable-size IV; + * discarded by ciphers with fixed-size IV. * * \returns O on success, or POLARSSL_ERR_CIPHER_BAD_INPUT_DATA * diff --git a/library/cipher.c b/library/cipher.c index d90abe1ab..a5f6e1186 100644 --- a/library/cipher.c +++ b/library/cipher.c @@ -399,19 +399,18 @@ int cipher_setkey( cipher_context_t *ctx, const unsigned char *key, int cipher_set_iv( cipher_context_t *ctx, const unsigned char *iv, size_t iv_len ) { - size_t fixed_iv_size; + size_t actual_iv_size; if( NULL == ctx || NULL == ctx->cipher_info || NULL == iv ) return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA; - fixed_iv_size = cipher_get_iv_size( ctx ); + if( ctx->cipher_info->accepts_variable_iv_size ) + actual_iv_size = iv_len; + else + actual_iv_size = ctx->cipher_info->iv_size; - /* 0 means variable size (or no IV): use given len */ - if( fixed_iv_size == 0 ) - fixed_iv_size = iv_len; - - memcpy( ctx->iv, iv, fixed_iv_size ); - ctx->iv_size = fixed_iv_size; + memcpy( ctx->iv, iv, actual_iv_size ); + ctx->iv_size = actual_iv_size; return 0; } diff --git a/library/cipher_wrap.c b/library/cipher_wrap.c index 5c9810056..ebe60cf20 100644 --- a/library/cipher_wrap.c +++ b/library/cipher_wrap.c @@ -150,6 +150,7 @@ const cipher_info_t aes_128_cbc_info = { 128, "AES-128-CBC", 16, + 0, 16, &aes_info }; @@ -160,6 +161,7 @@ const cipher_info_t aes_192_cbc_info = { 192, "AES-192-CBC", 16, + 0, 16, &aes_info }; @@ -170,6 +172,7 @@ const cipher_info_t aes_256_cbc_info = { 256, "AES-256-CBC", 16, + 0, 16, &aes_info }; @@ -181,6 +184,7 @@ const cipher_info_t aes_128_cfb128_info = { 128, "AES-128-CFB128", 16, + 0, 16, &aes_info }; @@ -191,6 +195,7 @@ const cipher_info_t aes_192_cfb128_info = { 192, "AES-192-CFB128", 16, + 0, 16, &aes_info }; @@ -201,6 +206,7 @@ const cipher_info_t aes_256_cfb128_info = { 256, "AES-256-CFB128", 16, + 0, 16, &aes_info }; @@ -213,6 +219,7 @@ const cipher_info_t aes_128_ctr_info = { 128, "AES-128-CTR", 16, + 0, 16, &aes_info }; @@ -223,6 +230,7 @@ const cipher_info_t aes_192_ctr_info = { 192, "AES-192-CTR", 16, + 0, 16, &aes_info }; @@ -233,6 +241,7 @@ const cipher_info_t aes_256_ctr_info = { 256, "AES-256-CTR", 16, + 0, 16, &aes_info }; @@ -271,7 +280,8 @@ const cipher_info_t aes_128_gcm_info = { POLARSSL_MODE_GCM, 128, "AES-128-GCM", - 0, + 12, + 1, 16, &gcm_aes_info }; @@ -281,7 +291,8 @@ const cipher_info_t aes_256_gcm_info = { POLARSSL_MODE_GCM, 256, "AES-256-GCM", - 0, + 12, + 1, 16, &gcm_aes_info }; @@ -373,6 +384,7 @@ const cipher_info_t camellia_128_cbc_info = { 128, "CAMELLIA-128-CBC", 16, + 0, 16, &camellia_info }; @@ -383,6 +395,7 @@ const cipher_info_t camellia_192_cbc_info = { 192, "CAMELLIA-192-CBC", 16, + 0, 16, &camellia_info }; @@ -393,6 +406,7 @@ const cipher_info_t camellia_256_cbc_info = { 256, "CAMELLIA-256-CBC", 16, + 0, 16, &camellia_info }; @@ -404,6 +418,7 @@ const cipher_info_t camellia_128_cfb128_info = { 128, "CAMELLIA-128-CFB128", 16, + 0, 16, &camellia_info }; @@ -414,6 +429,7 @@ const cipher_info_t camellia_192_cfb128_info = { 192, "CAMELLIA-192-CFB128", 16, + 0, 16, &camellia_info }; @@ -424,6 +440,7 @@ const cipher_info_t camellia_256_cfb128_info = { 256, "CAMELLIA-256-CFB128", 16, + 0, 16, &camellia_info }; @@ -436,6 +453,7 @@ const cipher_info_t camellia_128_ctr_info = { 128, "CAMELLIA-128-CTR", 16, + 0, 16, &camellia_info }; @@ -446,6 +464,7 @@ const cipher_info_t camellia_192_ctr_info = { 192, "CAMELLIA-192-CTR", 16, + 0, 16, &camellia_info }; @@ -456,6 +475,7 @@ const cipher_info_t camellia_256_ctr_info = { 256, "CAMELLIA-256-CTR", 16, + 0, 16, &camellia_info }; @@ -581,6 +601,7 @@ const cipher_info_t des_cbc_info = { POLARSSL_KEY_LENGTH_DES, "DES-CBC", 8, + 0, 8, &des_info }; @@ -603,6 +624,7 @@ const cipher_info_t des_ede_cbc_info = { POLARSSL_KEY_LENGTH_DES_EDE, "DES-EDE-CBC", 8, + 0, 8, &des_ede_info }; @@ -625,6 +647,7 @@ const cipher_info_t des_ede3_cbc_info = { POLARSSL_KEY_LENGTH_DES_EDE3, "DES-EDE3-CBC", 8, + 0, 8, &des_ede3_info }; @@ -709,6 +732,7 @@ const cipher_info_t blowfish_cbc_info = { 128, "BLOWFISH-CBC", 8, + 0, 8, &blowfish_info }; @@ -720,6 +744,7 @@ const cipher_info_t blowfish_cfb64_info = { 128, "BLOWFISH-CFB64", 8, + 0, 8, &blowfish_info }; @@ -732,6 +757,7 @@ const cipher_info_t blowfish_ctr_info = { 128, "BLOWFISH-CTR", 8, + 0, 8, &blowfish_info }; @@ -781,6 +807,7 @@ const cipher_info_t arc4_128_info = { 128, "ARC4-128", 0, + 0, 1, &arc4_base_info }; @@ -834,6 +861,7 @@ const cipher_info_t null_cipher_info = { 0, "NULL", 0, + 0, 1, &null_base_info }; diff --git a/library/pkcs12.c b/library/pkcs12.c index 3634ce139..cc59d6845 100644 --- a/library/pkcs12.c +++ b/library/pkcs12.c @@ -184,10 +184,10 @@ int pkcs12_pbe( asn1_buf *pbe_params, int mode, if( ( ret = cipher_setkey( &cipher_ctx, key, keylen, mode ) ) != 0 ) goto exit; - if( ( ret = cipher_set_iv( &cipher_ctx, iv, 0 ) ) != 0 ) + if( ( ret = cipher_set_iv( &cipher_ctx, iv, cipher_info->iv_size ) ) != 0 ) goto exit; - if( ( ret = cipher_reset( &cipher_ctx, iv, 0 ) ) != 0 ) + if( ( ret = cipher_reset( &cipher_ctx, NULL, 0 ) ) != 0 ) goto exit; if( ( ret = cipher_update( &cipher_ctx, data, len, diff --git a/library/pkcs5.c b/library/pkcs5.c index 6582fd05f..10adbb49e 100644 --- a/library/pkcs5.c +++ b/library/pkcs5.c @@ -187,7 +187,7 @@ int pkcs5_pbes2( asn1_buf *pbe_params, int mode, if( ( ret = cipher_setkey( &cipher_ctx, key, keylen, mode ) ) != 0 ) goto exit; - if( ( ret = cipher_set_iv( &cipher_ctx, iv, 0 ) ) != 0 ) + if( ( ret = cipher_set_iv( &cipher_ctx, iv, enc_scheme_params.len ) ) != 0 ) goto exit; if( ( ret = cipher_reset( &cipher_ctx, NULL, 0 ) ) != 0 ) From 2adc40c346344d490713a497743bc63a93eecd5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Tue, 3 Sep 2013 13:54:12 +0200 Subject: [PATCH 11/23] Split cipher_update_ad() out or cipher_reset() --- include/polarssl/cipher.h | 23 ++++++++++++++++++++--- library/cipher.c | 22 ++++++++++++++++++++-- library/pkcs12.c | 2 +- library/pkcs5.c | 2 +- programs/aes/crypt_and_hash.c | 4 ++-- tests/suites/test_suite_cipher.function | 21 +++++++++++++++------ 6 files changed, 59 insertions(+), 15 deletions(-) diff --git a/include/polarssl/cipher.h b/include/polarssl/cipher.h index 93a0015d7..7dea1e214 100644 --- a/include/polarssl/cipher.h +++ b/include/polarssl/cipher.h @@ -454,7 +454,7 @@ int cipher_set_iv( cipher_context_t *ctx, const unsigned char *iv, size_t iv_len ); /** - * \brief Reset the given context, setting the IV to iv + * \brief Finish preparation of the given context * * \param ctx generic cipher context * \param ad Additional data for AEAD ciphers, or discarded. @@ -464,8 +464,25 @@ int cipher_set_iv( cipher_context_t *ctx, * \returns 0 on success, POLARSSL_ERR_CIPHER_BAD_INPUT_DATA * if parameter verification fails. */ -int cipher_reset( cipher_context_t *ctx, - const unsigned char *ad, size_t ad_len ); +int cipher_reset( cipher_context_t *ctx ); + +/** + * \brief Add additional data (for AEAD ciphers). + * This function has no effect for non-AEAD ciphers. + * For AEAD ciphers, it may or may not be called + * repeatedly, and/or interleaved with calls to + * cipher_udpate(), depending on the cipher. + * E.g. for GCM is must be called exactly once, right + * after cipher_reset(). + * + * \param ctx generic cipher context + * \param ad Additional data to use. + * \param ad_len Length of ad. + * + * \returns 0 on success, or a specific error code. + */ +int cipher_update_ad( cipher_context_t *ctx, + const unsigned char *ad, size_t ad_len ); /** * \brief Generic cipher update function. Encrypts/decrypts diff --git a/library/cipher.c b/library/cipher.c index a5f6e1186..f8e2841d2 100644 --- a/library/cipher.c +++ b/library/cipher.c @@ -415,14 +415,32 @@ int cipher_set_iv( cipher_context_t *ctx, return 0; } -int cipher_reset( cipher_context_t *ctx, - const unsigned char *ad, size_t ad_len ) +int cipher_reset( cipher_context_t *ctx ) { + if( NULL == ctx || NULL == ctx->cipher_info ) + return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA; + ctx->unprocessed_len = 0; + return 0; +} + +int cipher_update_ad( cipher_context_t *ctx, + const unsigned char *ad, size_t ad_len ) +{ + if( NULL == ctx || NULL == ctx->cipher_info ) + return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA; + #if defined(POLARSSL_GCM_C) if( POLARSSL_MODE_GCM == ctx->cipher_info->mode ) { + /* Make sure we're called right after cipher_reset() */ + if( ((gcm_context *) ctx->cipher_ctx)->len != 0 || + ((gcm_context *) ctx->cipher_ctx)->add_len != 0 ) + { + return POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE; + } + return gcm_starts( ctx->cipher_ctx, ctx->operation, ctx->iv, ctx->iv_size, ad, ad_len ); } diff --git a/library/pkcs12.c b/library/pkcs12.c index cc59d6845..98ebd8876 100644 --- a/library/pkcs12.c +++ b/library/pkcs12.c @@ -187,7 +187,7 @@ int pkcs12_pbe( asn1_buf *pbe_params, int mode, if( ( ret = cipher_set_iv( &cipher_ctx, iv, cipher_info->iv_size ) ) != 0 ) goto exit; - if( ( ret = cipher_reset( &cipher_ctx, NULL, 0 ) ) != 0 ) + if( ( ret = cipher_reset( &cipher_ctx ) ) != 0 ) goto exit; if( ( ret = cipher_update( &cipher_ctx, data, len, diff --git a/library/pkcs5.c b/library/pkcs5.c index 10adbb49e..a27d4fb04 100644 --- a/library/pkcs5.c +++ b/library/pkcs5.c @@ -190,7 +190,7 @@ int pkcs5_pbes2( asn1_buf *pbe_params, int mode, if( ( ret = cipher_set_iv( &cipher_ctx, iv, enc_scheme_params.len ) ) != 0 ) goto exit; - if( ( ret = cipher_reset( &cipher_ctx, NULL, 0 ) ) != 0 ) + if( ( ret = cipher_reset( &cipher_ctx ) ) != 0 ) goto exit; if( ( ret = cipher_update( &cipher_ctx, data, datalen, diff --git a/programs/aes/crypt_and_hash.c b/programs/aes/crypt_and_hash.c index 8ffdb9f94..c46713d15 100644 --- a/programs/aes/crypt_and_hash.c +++ b/programs/aes/crypt_and_hash.c @@ -311,7 +311,7 @@ int main( int argc, char *argv[] ) fprintf( stderr, "cipher_set_iv() returned error\n"); goto exit; } - if( cipher_reset( &cipher_ctx, NULL, 0 ) != 0 ) + if( cipher_reset( &cipher_ctx ) != 0 ) { fprintf( stderr, "cipher_reset() returned error\n"); goto exit; @@ -430,7 +430,7 @@ int main( int argc, char *argv[] ) cipher_setkey( &cipher_ctx, digest, cipher_info->key_length, POLARSSL_DECRYPT ); cipher_set_iv( &cipher_ctx, IV, 16 ); - cipher_reset( &cipher_ctx, NULL, 0 ); + cipher_reset( &cipher_ctx ); md_hmac_starts( &md_ctx, digest, 32 ); diff --git a/tests/suites/test_suite_cipher.function b/tests/suites/test_suite_cipher.function index d247bab2a..aa82daae9 100644 --- a/tests/suites/test_suite_cipher.function +++ b/tests/suites/test_suite_cipher.function @@ -61,8 +61,11 @@ void enc_dec_buf( int cipher_id, char *cipher_string, int key_len, TEST_ASSERT( 0 == cipher_set_iv( &ctx_dec, iv, 16 ) ); TEST_ASSERT( 0 == cipher_set_iv( &ctx_enc, iv, 16 ) ); - TEST_ASSERT( 0 == cipher_reset( &ctx_dec, ad, 13 ) ); - TEST_ASSERT( 0 == cipher_reset( &ctx_enc, ad, 13 ) ); + TEST_ASSERT( 0 == cipher_reset( &ctx_dec ) ); + TEST_ASSERT( 0 == cipher_reset( &ctx_enc ) ); + + TEST_ASSERT( 0 == cipher_update_ad( &ctx_dec, ad, 13 ) ); + TEST_ASSERT( 0 == cipher_update_ad( &ctx_enc, ad, 13 ) ); /* encode length number of bytes from inbuf */ TEST_ASSERT( 0 == cipher_update( &ctx_enc, inbuf, length, encbuf, &outlen ) ); @@ -137,7 +140,8 @@ void enc_fail( int cipher_id, int pad_mode, int key_len, TEST_ASSERT( 0 == cipher_setkey( &ctx, key, key_len, POLARSSL_ENCRYPT ) ); TEST_ASSERT( 0 == cipher_set_padding_mode( &ctx, pad_mode ) ); TEST_ASSERT( 0 == cipher_set_iv( &ctx, iv, 16 ) ); - TEST_ASSERT( 0 == cipher_reset( &ctx, NULL, 0 ) ); + TEST_ASSERT( 0 == cipher_reset( &ctx ) ); + TEST_ASSERT( 0 == cipher_update_ad( &ctx, NULL, 0 ) ); /* encode length number of bytes from inbuf */ TEST_ASSERT( 0 == cipher_update( &ctx, inbuf, length, encbuf, &outlen ) ); @@ -180,7 +184,9 @@ void dec_empty_buf() TEST_ASSERT( 0 == cipher_set_iv( &ctx_dec, iv, 16 ) ); - TEST_ASSERT( 0 == cipher_reset( &ctx_dec, NULL, 0 ) ); + TEST_ASSERT( 0 == cipher_reset( &ctx_dec ) ); + + TEST_ASSERT( 0 == cipher_update_ad( &ctx_dec, NULL, 0 ) ); /* decode 0-byte string */ TEST_ASSERT( 0 == cipher_update( &ctx_dec, encbuf, 0, decbuf, &outlen ) ); @@ -237,8 +243,11 @@ void enc_dec_buf_multipart( int cipher_id, int key_len, int first_length_val, TEST_ASSERT( 0 == cipher_set_iv( &ctx_dec, iv, 16 ) ); TEST_ASSERT( 0 == cipher_set_iv( &ctx_enc, iv, 16 ) ); - TEST_ASSERT( 0 == cipher_reset( &ctx_dec, NULL, 0 ) ); - TEST_ASSERT( 0 == cipher_reset( &ctx_enc, NULL, 0 ) ); + TEST_ASSERT( 0 == cipher_reset( &ctx_dec ) ); + TEST_ASSERT( 0 == cipher_reset( &ctx_enc ) ); + + TEST_ASSERT( 0 == cipher_update_ad( &ctx_dec, NULL, 0 ) ); + TEST_ASSERT( 0 == cipher_update_ad( &ctx_enc, NULL, 0 ) ); /* encode length number of bytes from inbuf */ TEST_ASSERT( 0 == cipher_update( &ctx_enc, inbuf, first_length, encbuf, &outlen ) ); From aa9ffc5e98f1c375efb6787e12d6537da2e99327 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Tue, 3 Sep 2013 16:19:22 +0200 Subject: [PATCH 12/23] Split tag handling out of cipher_finish() --- include/polarssl/cipher.h | 35 +++++++++--- library/cipher.c | 73 ++++++++++++++++--------- library/pkcs12.c | 5 +- library/pkcs5.c | 5 +- programs/aes/crypt_and_hash.c | 4 +- tests/suites/test_suite_cipher.function | 20 +++---- 6 files changed, 88 insertions(+), 54 deletions(-) diff --git a/include/polarssl/cipher.h b/include/polarssl/cipher.h index 7dea1e214..dc5a41ca3 100644 --- a/include/polarssl/cipher.h +++ b/include/polarssl/cipher.h @@ -519,11 +519,6 @@ int cipher_update( cipher_context_t *ctx, const unsigned char *input, size_t ile * \param ctx Generic cipher context * \param output buffer to write data to. Needs block_size available. * \param olen length of the data written to the output buffer. - * \param tag Ignore by non-AEAD ciphers. For AEAD ciphers: - * - on encryption: buffer to write the tag; - * - on decryption: tag to verify. - * May be NULL if tag_len is zero. - * \param tag_len Length of the tag to write/check for AEAD ciphers. * * \returns 0 on success, POLARSSL_ERR_CIPHER_BAD_INPUT_DATA if * parameter verification fails, @@ -533,8 +528,34 @@ int cipher_update( cipher_context_t *ctx, const unsigned char *input, size_t ile * while decrypting or a cipher specific error code. */ int cipher_finish( cipher_context_t *ctx, - unsigned char *output, size_t *olen, - unsigned char *tag, size_t tag_len ); + unsigned char *output, size_t *olen ); + +/** + * \brief Write tag for AEAD ciphers. + * No effect for other ciphers. + * Must be called after cipher_finish(). + * + * \param tag buffer to write the tag + * \param tag_len Length of the tag to write + * + * \return 0 on success, or a specific error code. + */ +int cipher_write_tag( cipher_context_t *ctx, + unsigned char *tag, size_t tag_len ); + +/** + * \brief Check tag for AEAD ciphers. + * No effect for other ciphers. + * Calling time depends on the cipher: + * for GCM, must be called after cipher_finish(). + * + * \param tag Buffer holding the tag + * \param tag_len Length of the tag to check + * + * \return 0 on success, or a specific error code. + */ +int cipher_check_tag( cipher_context_t *ctx, + const unsigned char *tag, size_t tag_len ); /** * \brief Checkup routine diff --git a/library/cipher.c b/library/cipher.c index f8e2841d2..a90e2dcd9 100644 --- a/library/cipher.c +++ b/library/cipher.c @@ -777,8 +777,7 @@ static int get_no_padding( unsigned char *input, size_t input_len, } int cipher_finish( cipher_context_t *ctx, - unsigned char *output, size_t *olen, - unsigned char *tag, size_t tag_len ) + unsigned char *output, size_t *olen ) { int ret = 0; @@ -797,10 +796,6 @@ int cipher_finish( cipher_context_t *ctx, #if defined(POLARSSL_GCM_C) if( POLARSSL_MODE_GCM == ctx->cipher_info->mode ) { - unsigned char check_tag[16]; - size_t i; - int diff; - if( 0 != ( ret = gcm_update( ctx->cipher_ctx, ctx->unprocessed_len, ctx->unprocessed_data, output ) ) ) @@ -810,29 +805,8 @@ int cipher_finish( cipher_context_t *ctx, *olen += ctx->unprocessed_len; - if( 0 != ( ret = gcm_finish( ctx->cipher_ctx, check_tag, tag_len ) ) ) - return( ret ); - - /* On encryption, write the tag */ - if( POLARSSL_ENCRYPT == ctx->operation ) - { - if( tag_len != 0 ) - memcpy( tag, check_tag, tag_len ); - return( 0 ); - } - - /* On decryption, check the tag (in "constant-time") */ - for( diff = 0, i = 0; i < tag_len; i++ ) - diff |= tag[i] ^ check_tag[i]; - - if( diff != 0 ) - return( POLARSSL_ERR_GCM_AUTH_FAILED ); - return( 0 ); } -#else - ((void) tag); - ((void) tag_len); #endif if( POLARSSL_MODE_CBC == ctx->cipher_info->mode ) @@ -930,6 +904,51 @@ int cipher_set_padding_mode( cipher_context_t *ctx, cipher_padding_t mode ) return 0; } +int cipher_write_tag( cipher_context_t *ctx, + unsigned char *tag, size_t tag_len ) +{ + if( NULL == ctx || NULL == ctx->cipher_info || NULL == tag ) + return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA; + + if( POLARSSL_MODE_GCM != ctx->cipher_info->mode ) + return( 0 ); + + if( POLARSSL_ENCRYPT != ctx->operation ) + return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA; + + return gcm_finish( ctx->cipher_ctx, tag, tag_len ); +} + +int cipher_check_tag( cipher_context_t *ctx, + const unsigned char *tag, size_t tag_len ) +{ + int ret; + unsigned char check_tag[16]; + size_t i; + int diff; + + if( NULL == ctx || NULL == ctx->cipher_info ) + return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA; + + if( POLARSSL_MODE_GCM != ctx->cipher_info->mode ) + return( 0 ); + + if( POLARSSL_DECRYPT != ctx->operation || tag_len > sizeof( check_tag ) ) + return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA; + + if( 0 != ( ret = gcm_finish( ctx->cipher_ctx, check_tag, tag_len ) ) ) + return( ret ); + + /* On decryption, check the tag (in "constant-time") */ + for( diff = 0, i = 0; i < tag_len; i++ ) + diff |= tag[i] ^ check_tag[i]; + + if( diff != 0 ) + return( POLARSSL_ERR_GCM_AUTH_FAILED ); + + return( 0 ); +} + #if defined(POLARSSL_SELF_TEST) #include diff --git a/library/pkcs12.c b/library/pkcs12.c index 98ebd8876..335af7ebf 100644 --- a/library/pkcs12.c +++ b/library/pkcs12.c @@ -196,11 +196,8 @@ int pkcs12_pbe( asn1_buf *pbe_params, int mode, goto exit; } - if( ( ret = cipher_finish( &cipher_ctx, output + olen, &olen, NULL, 0 ) ) - != 0 ) - { + if( ( ret = cipher_finish( &cipher_ctx, output + olen, &olen ) ) != 0 ) ret = POLARSSL_ERR_PKCS12_PASSWORD_MISMATCH; - } exit: cipher_free_ctx( &cipher_ctx ); diff --git a/library/pkcs5.c b/library/pkcs5.c index a27d4fb04..0b9830dc6 100644 --- a/library/pkcs5.c +++ b/library/pkcs5.c @@ -199,11 +199,8 @@ int pkcs5_pbes2( asn1_buf *pbe_params, int mode, goto exit; } - if( ( ret = cipher_finish( &cipher_ctx, output + olen, &olen, NULL, 0 ) ) - != 0 ) - { + if( ( ret = cipher_finish( &cipher_ctx, output + olen, &olen ) ) != 0 ) ret = POLARSSL_ERR_PKCS5_PASSWORD_MISMATCH; - } exit: md_free_ctx( &md_ctx ); diff --git a/programs/aes/crypt_and_hash.c b/programs/aes/crypt_and_hash.c index c46713d15..6caaad872 100644 --- a/programs/aes/crypt_and_hash.c +++ b/programs/aes/crypt_and_hash.c @@ -343,7 +343,7 @@ int main( int argc, char *argv[] ) } } - if( cipher_finish( &cipher_ctx, output, &olen, NULL, 0 ) != 0 ) + if( cipher_finish( &cipher_ctx, output, &olen ) != 0 ) { fprintf( stderr, "cipher_finish() returned error\n" ); goto exit; @@ -461,7 +461,7 @@ int main( int argc, char *argv[] ) /* * Write the final block of data */ - cipher_finish( &cipher_ctx, output, &olen, NULL, 0 ); + cipher_finish( &cipher_ctx, output, &olen ); if( fwrite( output, 1, olen, fout ) != olen ) { diff --git a/tests/suites/test_suite_cipher.function b/tests/suites/test_suite_cipher.function index aa82daae9..5d32bc3d1 100644 --- a/tests/suites/test_suite_cipher.function +++ b/tests/suites/test_suite_cipher.function @@ -76,10 +76,11 @@ void enc_dec_buf( int cipher_id, char *cipher_string, int key_len, total_len < length && total_len + cipher_get_block_size( &ctx_enc ) > length ) ); - TEST_ASSERT( 0 == cipher_finish( &ctx_enc, encbuf + outlen, &outlen, - tag, 16 ) ); + TEST_ASSERT( 0 == cipher_finish( &ctx_enc, encbuf + outlen, &outlen ) ); total_len += outlen; + TEST_ASSERT( 0 == cipher_write_tag( &ctx_enc, tag, 16 ) ); + TEST_ASSERT( total_len == length || ( total_len % cipher_get_block_size( &ctx_enc ) == 0 && total_len > length && @@ -94,10 +95,11 @@ void enc_dec_buf( int cipher_id, char *cipher_string, int key_len, total_len < length && total_len + cipher_get_block_size( &ctx_dec ) >= length ) ); - TEST_ASSERT( 0 == cipher_finish( &ctx_dec, decbuf + outlen, &outlen, - tag, 16 ) ); + TEST_ASSERT( 0 == cipher_finish( &ctx_dec, decbuf + outlen, &outlen ) ); total_len += outlen; + TEST_ASSERT( 0 == cipher_check_tag( &ctx_dec, tag, 16 ) ); + TEST_ASSERT( total_len == length ); TEST_ASSERT( 0 == memcmp(inbuf, decbuf, length) ); @@ -145,7 +147,7 @@ void enc_fail( int cipher_id, int pad_mode, int key_len, /* encode length number of bytes from inbuf */ TEST_ASSERT( 0 == cipher_update( &ctx, inbuf, length, encbuf, &outlen ) ); - TEST_ASSERT( ret == cipher_finish( &ctx, encbuf + outlen, &outlen, NULL, 0 ) ); + TEST_ASSERT( ret == cipher_finish( &ctx, encbuf + outlen, &outlen ) ); /* done */ TEST_ASSERT( 0 == cipher_free_ctx( &ctx ) ); @@ -192,7 +194,7 @@ void dec_empty_buf() TEST_ASSERT( 0 == cipher_update( &ctx_dec, encbuf, 0, decbuf, &outlen ) ); TEST_ASSERT( 0 == outlen ); TEST_ASSERT( POLARSSL_ERR_CIPHER_FULL_BLOCK_EXPECTED == cipher_finish( - &ctx_dec, decbuf + outlen, &outlen, NULL, 0 ) ); + &ctx_dec, decbuf + outlen, &outlen ) ); TEST_ASSERT( 0 == outlen ); TEST_ASSERT( 0 == cipher_free_ctx( &ctx_dec ) ); @@ -259,8 +261,7 @@ void enc_dec_buf_multipart( int cipher_id, int key_len, int first_length_val, totaloutlen < length && totaloutlen + cipher_get_block_size( &ctx_enc ) > length ) ); - TEST_ASSERT( 0 == cipher_finish( &ctx_enc, encbuf + totaloutlen, &outlen, - NULL, 0 ) ); + TEST_ASSERT( 0 == cipher_finish( &ctx_enc, encbuf + totaloutlen, &outlen ) ); totaloutlen += outlen; TEST_ASSERT( totaloutlen == length || ( totaloutlen % cipher_get_block_size( &ctx_enc ) == 0 && @@ -276,8 +277,7 @@ void enc_dec_buf_multipart( int cipher_id, int key_len, int first_length_val, totaloutlen < length && totaloutlen + cipher_get_block_size( &ctx_dec ) >= length ) ); - TEST_ASSERT( 0 == cipher_finish( &ctx_dec, decbuf + outlen, &outlen, - NULL, 0 ) ); + TEST_ASSERT( 0 == cipher_finish( &ctx_dec, decbuf + outlen, &outlen ) ); totaloutlen += outlen; TEST_ASSERT( totaloutlen == length ); From 43a4780b03b802818f379fccd0dde924bd7d0447 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Tue, 3 Sep 2013 16:35:53 +0200 Subject: [PATCH 13/23] Ommit AEAD functions if GCM not defined --- include/polarssl/cipher.h | 13 ++++-- library/cipher.c | 61 +++++++++++++++---------- tests/suites/test_suite_cipher.function | 12 +++++ 3 files changed, 58 insertions(+), 28 deletions(-) diff --git a/include/polarssl/cipher.h b/include/polarssl/cipher.h index dc5a41ca3..b7d449210 100644 --- a/include/polarssl/cipher.h +++ b/include/polarssl/cipher.h @@ -30,6 +30,12 @@ #ifndef POLARSSL_CIPHER_H #define POLARSSL_CIPHER_H +#include "config.h" + +#if defined(POLARSSL_GCM_C) +#define POLARSSL_CIPHER_MODE_AEAD +#endif + #include #if defined(_MSC_VER) && !defined(inline) @@ -457,15 +463,13 @@ int cipher_set_iv( cipher_context_t *ctx, * \brief Finish preparation of the given context * * \param ctx generic cipher context - * \param ad Additional data for AEAD ciphers, or discarded. - * May be NULL only if ad_len is 0. - * \param ad_len Length of ad for AEAD ciphers, or discarded. * * \returns 0 on success, POLARSSL_ERR_CIPHER_BAD_INPUT_DATA * if parameter verification fails. */ int cipher_reset( cipher_context_t *ctx ); +#if defined(POLARSSL_CIPHER_MODE_AEAD) /** * \brief Add additional data (for AEAD ciphers). * This function has no effect for non-AEAD ciphers. @@ -483,6 +487,7 @@ int cipher_reset( cipher_context_t *ctx ); */ int cipher_update_ad( cipher_context_t *ctx, const unsigned char *ad, size_t ad_len ); +#endif /* POLARSSL_CIPHER_MODE_AEAD */ /** * \brief Generic cipher update function. Encrypts/decrypts @@ -530,6 +535,7 @@ int cipher_update( cipher_context_t *ctx, const unsigned char *input, size_t ile int cipher_finish( cipher_context_t *ctx, unsigned char *output, size_t *olen ); +#if defined(POLARSSL_CIPHER_MODE_AEAD) /** * \brief Write tag for AEAD ciphers. * No effect for other ciphers. @@ -556,6 +562,7 @@ int cipher_write_tag( cipher_context_t *ctx, */ int cipher_check_tag( cipher_context_t *ctx, const unsigned char *tag, size_t tag_len ); +#endif /* POLARSSL_CIPHER_MODE_AEAD */ /** * \brief Checkup routine diff --git a/library/cipher.c b/library/cipher.c index a90e2dcd9..160f4bcad 100644 --- a/library/cipher.c +++ b/library/cipher.c @@ -425,6 +425,7 @@ int cipher_reset( cipher_context_t *ctx ) return 0; } +#if defined(POLARSSL_CIPHER_MODE_AEAD) int cipher_update_ad( cipher_context_t *ctx, const unsigned char *ad, size_t ad_len ) { @@ -444,13 +445,11 @@ int cipher_update_ad( cipher_context_t *ctx, return gcm_starts( ctx->cipher_ctx, ctx->operation, ctx->iv, ctx->iv_size, ad, ad_len ); } -#else - ((void) ad); - ((void) ad_len); #endif return 0; } +#endif /* POLARSSL_CIPHER_MODE_AEAD */ int cipher_update( cipher_context_t *ctx, const unsigned char *input, size_t ilen, unsigned char *output, size_t *olen ) @@ -904,50 +903,62 @@ int cipher_set_padding_mode( cipher_context_t *ctx, cipher_padding_t mode ) return 0; } +#if defined(POLARSSL_CIPHER_MODE_AEAD) int cipher_write_tag( cipher_context_t *ctx, unsigned char *tag, size_t tag_len ) { if( NULL == ctx || NULL == ctx->cipher_info || NULL == tag ) return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA; - if( POLARSSL_MODE_GCM != ctx->cipher_info->mode ) - return( 0 ); - if( POLARSSL_ENCRYPT != ctx->operation ) return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA; - return gcm_finish( ctx->cipher_ctx, tag, tag_len ); +#if defined(POLARSSL_GCM_C) + if( POLARSSL_MODE_GCM == ctx->cipher_info->mode ) + return gcm_finish( ctx->cipher_ctx, tag, tag_len ); +#endif + + return 0; } int cipher_check_tag( cipher_context_t *ctx, const unsigned char *tag, size_t tag_len ) { int ret; - unsigned char check_tag[16]; - size_t i; - int diff; - if( NULL == ctx || NULL == ctx->cipher_info ) + if( NULL == ctx || NULL == ctx->cipher_info || + POLARSSL_DECRYPT != ctx->operation ) + { return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA; + } + +#if defined(POLARSSL_GCM_C) + if( POLARSSL_MODE_GCM == ctx->cipher_info->mode ) + { + unsigned char check_tag[16]; + size_t i; + int diff; + + if( tag_len > sizeof( check_tag ) ) + return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA; + + if( 0 != ( ret = gcm_finish( ctx->cipher_ctx, check_tag, tag_len ) ) ) + return( ret ); + + /* Check the tag in "constant-time" */ + for( diff = 0, i = 0; i < tag_len; i++ ) + diff |= tag[i] ^ check_tag[i]; + + if( diff != 0 ) + return( POLARSSL_ERR_GCM_AUTH_FAILED ); - if( POLARSSL_MODE_GCM != ctx->cipher_info->mode ) return( 0 ); - - if( POLARSSL_DECRYPT != ctx->operation || tag_len > sizeof( check_tag ) ) - return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA; - - if( 0 != ( ret = gcm_finish( ctx->cipher_ctx, check_tag, tag_len ) ) ) - return( ret ); - - /* On decryption, check the tag (in "constant-time") */ - for( diff = 0, i = 0; i < tag_len; i++ ) - diff |= tag[i] ^ check_tag[i]; - - if( diff != 0 ) - return( POLARSSL_ERR_GCM_AUTH_FAILED ); + } +#endif return( 0 ); } +#endif /* POLARSSL_CIPHER_MODE_AEAD */ #if defined(POLARSSL_SELF_TEST) diff --git a/tests/suites/test_suite_cipher.function b/tests/suites/test_suite_cipher.function index 5d32bc3d1..63de2db4d 100644 --- a/tests/suites/test_suite_cipher.function +++ b/tests/suites/test_suite_cipher.function @@ -64,8 +64,10 @@ void enc_dec_buf( int cipher_id, char *cipher_string, int key_len, TEST_ASSERT( 0 == cipher_reset( &ctx_dec ) ); TEST_ASSERT( 0 == cipher_reset( &ctx_enc ) ); +#if defined(POLARSSL_CIPHER_MODE_AEAD) TEST_ASSERT( 0 == cipher_update_ad( &ctx_dec, ad, 13 ) ); TEST_ASSERT( 0 == cipher_update_ad( &ctx_enc, ad, 13 ) ); +#endif /* POLARSSL_CIPHER_MODE_AEAD */ /* encode length number of bytes from inbuf */ TEST_ASSERT( 0 == cipher_update( &ctx_enc, inbuf, length, encbuf, &outlen ) ); @@ -79,7 +81,9 @@ void enc_dec_buf( int cipher_id, char *cipher_string, int key_len, TEST_ASSERT( 0 == cipher_finish( &ctx_enc, encbuf + outlen, &outlen ) ); total_len += outlen; +#if defined(POLARSSL_CIPHER_MODE_AEAD) TEST_ASSERT( 0 == cipher_write_tag( &ctx_enc, tag, 16 ) ); +#endif /* POLARSSL_CIPHER_MODE_AEAD */ TEST_ASSERT( total_len == length || ( total_len % cipher_get_block_size( &ctx_enc ) == 0 && @@ -98,7 +102,9 @@ void enc_dec_buf( int cipher_id, char *cipher_string, int key_len, TEST_ASSERT( 0 == cipher_finish( &ctx_dec, decbuf + outlen, &outlen ) ); total_len += outlen; +#if defined(POLARSSL_CIPHER_MODE_AEAD) TEST_ASSERT( 0 == cipher_check_tag( &ctx_dec, tag, 16 ) ); +#endif /* POLARSSL_CIPHER_MODE_AEAD */ TEST_ASSERT( total_len == length ); @@ -143,7 +149,9 @@ void enc_fail( int cipher_id, int pad_mode, int key_len, TEST_ASSERT( 0 == cipher_set_padding_mode( &ctx, pad_mode ) ); TEST_ASSERT( 0 == cipher_set_iv( &ctx, iv, 16 ) ); TEST_ASSERT( 0 == cipher_reset( &ctx ) ); +#if defined(POLARSSL_CIPHER_MODE_AEAD) TEST_ASSERT( 0 == cipher_update_ad( &ctx, NULL, 0 ) ); +#endif /* POLARSSL_CIPHER_MODE_AEAD */ /* encode length number of bytes from inbuf */ TEST_ASSERT( 0 == cipher_update( &ctx, inbuf, length, encbuf, &outlen ) ); @@ -188,7 +196,9 @@ void dec_empty_buf() TEST_ASSERT( 0 == cipher_reset( &ctx_dec ) ); +#if defined(POLARSSL_CIPHER_MODE_AEAD) TEST_ASSERT( 0 == cipher_update_ad( &ctx_dec, NULL, 0 ) ); +#endif /* POLARSSL_CIPHER_MODE_AEAD */ /* decode 0-byte string */ TEST_ASSERT( 0 == cipher_update( &ctx_dec, encbuf, 0, decbuf, &outlen ) ); @@ -248,8 +258,10 @@ void enc_dec_buf_multipart( int cipher_id, int key_len, int first_length_val, TEST_ASSERT( 0 == cipher_reset( &ctx_dec ) ); TEST_ASSERT( 0 == cipher_reset( &ctx_enc ) ); +#if defined(POLARSSL_CIPHER_MODE_AEAD) TEST_ASSERT( 0 == cipher_update_ad( &ctx_dec, NULL, 0 ) ); TEST_ASSERT( 0 == cipher_update_ad( &ctx_enc, NULL, 0 ) ); +#endif /* POLARSSL_CIPHER_MODE_AEAD */ /* encode length number of bytes from inbuf */ TEST_ASSERT( 0 == cipher_update( &ctx_enc, inbuf, first_length, encbuf, &outlen ) ); From 8eccab50779a5ce63b2a1178a4056dcfdc2b6510 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Tue, 3 Sep 2013 18:31:25 +0200 Subject: [PATCH 14/23] Add test vectors to the cipher test suite Ensures the selected cipher/mode/padding is actually used and padding and tag are actually checked. --- tests/suites/test_suite_cipher.aes.data | 28 +++++++++++ tests/suites/test_suite_cipher.function | 67 +++++++++++++++++++++++++ tests/suites/test_suite_cipher.gcm.data | 4 ++ 3 files changed, 99 insertions(+) diff --git a/tests/suites/test_suite_cipher.aes.data b/tests/suites/test_suite_cipher.aes.data index 2e45ae461..fc0beac67 100644 --- a/tests/suites/test_suite_cipher.aes.data +++ b/tests/suites/test_suite_cipher.aes.data @@ -764,3 +764,31 @@ enc_dec_buf_multipart:POLARSSL_CIPHER_AES_256_CBC:256:17:6: AES Encrypt and decrypt 32 bytes in multiple parts 1 depends_on:POLARSSL_AES_C enc_dec_buf_multipart:POLARSSL_CIPHER_AES_256_CBC:256:16:16: + +AES Decrypt test vector #0 +depends_on:POLARSSL_AES_C:POLARSSL_CIPHER_PADDING_PKCS7 +decrypt_test_vec:POLARSSL_CIPHER_AES_128_CBC:POLARSSL_PADDING_PKCS7:"ffffffffe00000000000000000000000":"00000000000000000000000000000000":"23f710842b9bb9c32f26648c786807ca":"00000000000000000000000000000000":"":"":POLARSSL_ERR_CIPHER_INVALID_PADDING:0 + +AES Decrypt test vector #1 +depends_on:POLARSSL_AES_C +decrypt_test_vec:POLARSSL_CIPHER_AES_128_CBC:POLARSSL_PADDING_NONE:"ffffffffe00000000000000000000000":"00000000000000000000000000000000":"23f710842b9bb9c32f26648c786807ca":"00000000000000000000000000000000":"":"":0:0 + +AES Decrypt test vector #2 +depends_on:POLARSSL_AES_C +decrypt_test_vec:POLARSSL_CIPHER_AES_192_CBC:POLARSSL_PADDING_NONE:"000000000000000000000000000000000000000000000000":"00000000000000000000000000000000":"707b1dbb0ffa40ef7d95def421233fae":"fffffffff80000000000000000000000":"":"":0:0 + +AES Decrypt test vector #3 +depends_on:POLARSSL_AES_C +decrypt_test_vec:POLARSSL_CIPHER_AES_256_CBC:POLARSSL_PADDING_NONE:"0000000000000000000000000000000000000000000000000000000000000000":"00000000000000000000000000000000":"49af6b372135acef10132e548f217b17":"ff000000000000000000000000000000":"":"":0:0 + +AES Decrypt test vector #4 +depends_on:POLARSSL_AES_C:POLARSSL_CIPHER_MODE_CFB +decrypt_test_vec:POLARSSL_CIPHER_AES_128_CFB128:-1:"fffffffe000000000000000000000000":"00000000000000000000000000000000":"1114bc2028009b923f0b01915ce5e7c4":"00000000000000000000000000000000":"":"":0:0: + +AES Decrypt test vector #5 +depends_on:POLARSSL_AES_C:POLARSSL_CIPHER_MODE_CFB +decrypt_test_vec:POLARSSL_CIPHER_AES_192_CFB128:-1:"ffffffffffffffffffffffffffffffffffffffffffe00000":"00000000000000000000000000000000":"60136703374f64e860b48ce31f930716":"00000000000000000000000000000000":"":"":0:0 + +AES Decrypt test vector #6 +depends_on:POLARSSL_AES_C:POLARSSL_CIPHER_MODE_CFB +decrypt_test_vec:POLARSSL_CIPHER_AES_128_CFB128:-1:"ffffffffff800000000000000000000000000000000000000000000000000000":"00000000000000000000000000000000":"be66cfea2fecd6bf0ec7b4352c99bcaa":"00000000000000000000000000000000":"":"":0:0 diff --git a/tests/suites/test_suite_cipher.function b/tests/suites/test_suite_cipher.function index 63de2db4d..9dad06c72 100644 --- a/tests/suites/test_suite_cipher.function +++ b/tests/suites/test_suite_cipher.function @@ -301,6 +301,73 @@ void enc_dec_buf_multipart( int cipher_id, int key_len, int first_length_val, } /* END_CASE */ +/* BEGIN_CASE */ +void decrypt_test_vec( int cipher_id, int pad_mode, + char *hex_key, char *hex_iv, + char *hex_cipher, char *hex_clear, + char *hex_ad, char *hex_tag, + int finish_result, int tag_result ) +{ + unsigned char key[100]; + unsigned char iv[100]; + unsigned char cipher[100]; + unsigned char clear[100]; + unsigned char ad[100]; + unsigned char tag[100]; + size_t key_len, iv_len, cipher_len, clear_len, ad_len, tag_len; + cipher_context_t ctx; + unsigned char output[100]; + size_t outlen, total_len; + + memset( key, 0x00, sizeof( key ) ); + memset( iv, 0x00, sizeof( iv ) ); + memset( cipher, 0x00, sizeof( cipher ) ); + memset( clear, 0x00, sizeof( clear ) ); + memset( ad, 0x00, sizeof( ad ) ); + memset( tag, 0x00, sizeof( tag ) ); + memset( output, 0x00, sizeof( output ) ); + + key_len = unhexify( key, hex_key ); + iv_len = unhexify( iv, hex_iv ); + cipher_len = unhexify( cipher, hex_cipher ); + clear_len = unhexify( clear, hex_clear ); + ad_len = unhexify( ad, hex_ad ); + tag_len = unhexify( tag, hex_tag ); + + /* Prepare context */ + TEST_ASSERT( 0 == cipher_init_ctx( &ctx, + cipher_info_from_type( cipher_id ) ) ); + TEST_ASSERT( 0 == cipher_setkey( &ctx, key, 8 * key_len, POLARSSL_DECRYPT ) ); + if( pad_mode != -1 ) + TEST_ASSERT( 0 == cipher_set_padding_mode( &ctx, pad_mode ) ); + TEST_ASSERT( 0 == cipher_set_iv( &ctx, iv, iv_len ) ); + TEST_ASSERT( 0 == cipher_reset( &ctx ) ); +#if defined(POLARSSL_CIPHER_MODE_AEAD) + TEST_ASSERT( 0 == cipher_update_ad( &ctx, ad, ad_len ) ); +#endif /* POLARSSL_CIPHER_MODE_AEAD */ + + /* decode buffer and check tag */ + total_len = 0; + TEST_ASSERT( 0 == cipher_update( &ctx, cipher, cipher_len, output, &outlen ) ); + total_len += outlen; + TEST_ASSERT( finish_result == cipher_finish( &ctx, output + outlen, + &outlen ) ); + total_len += outlen; +#if defined(POLARSSL_CIPHER_MODE_AEAD) + TEST_ASSERT( tag_result == cipher_check_tag( &ctx, tag, tag_len ) ); +#endif /* POLARSSL_CIPHER_MODE_AEAD */ + + /* check plaintext only if everything went fine */ + if( 0 == finish_result && 0 == tag_result ) + { + TEST_ASSERT( total_len == clear_len ); + TEST_ASSERT( 0 == memcmp( output, clear, clear_len ) ); + } + + cipher_free_ctx( &ctx ); +} +/* END_CASE */ + /* BEGIN_CASE */ void set_padding( int cipher_id, int pad_mode, int ret ) { diff --git a/tests/suites/test_suite_cipher.gcm.data b/tests/suites/test_suite_cipher.gcm.data index aacdca8eb..100afddf8 100644 --- a/tests/suites/test_suite_cipher.gcm.data +++ b/tests/suites/test_suite_cipher.gcm.data @@ -108,3 +108,7 @@ enc_dec_buf_multipart:POLARSSL_CIPHER_AES_128_GCM:128:17:6 AES 128 GCM Encrypt and decrypt 32 bytes in multiple parts 1 depends_on:POLARSSL_AES_C:POLARSSL_GCM_C enc_dec_buf_multipart:POLARSSL_CIPHER_AES_128_GCM:128:16:16 + +AES 128 GCM Decrypt test vector #1 +depends_on:POLARSSL_AES_C:POLARSSL_GCM_C +decrypt_test_vec:POLARSSL_CIPHER_AES_128_CBC:-1:"d785dafea3e966731ef6fc6202262584":"d91a46205ee94058b3b8403997592dd2":"":"":"3b92a17c1b9c3578a68cffea5a5b6245":0:0 From f7ce67f0d2322f218347f43e172f1f9a055a54b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Tue, 3 Sep 2013 20:17:35 +0200 Subject: [PATCH 15/23] Add tests for gcm via cipher --- tests/suites/test_suite_cipher.function | 18 ++++++++----- tests/suites/test_suite_cipher.gcm.data | 34 ++++++++++++++++++++++++- tests/suites/test_suite_gcm.function | 1 + 3 files changed, 45 insertions(+), 8 deletions(-) diff --git a/tests/suites/test_suite_cipher.function b/tests/suites/test_suite_cipher.function index 9dad06c72..c556a2e56 100644 --- a/tests/suites/test_suite_cipher.function +++ b/tests/suites/test_suite_cipher.function @@ -1,5 +1,9 @@ /* BEGIN_HEADER */ #include + +#if defined(POLARSSL_GCM_C) +#include +#endif /* END_HEADER */ /* BEGIN_DEPENDENCIES @@ -308,15 +312,15 @@ void decrypt_test_vec( int cipher_id, int pad_mode, char *hex_ad, char *hex_tag, int finish_result, int tag_result ) { - unsigned char key[100]; - unsigned char iv[100]; - unsigned char cipher[100]; - unsigned char clear[100]; - unsigned char ad[100]; - unsigned char tag[100]; + unsigned char key[50]; + unsigned char iv[50]; + unsigned char cipher[200]; + unsigned char clear[200]; + unsigned char ad[200]; + unsigned char tag[20]; size_t key_len, iv_len, cipher_len, clear_len, ad_len, tag_len; cipher_context_t ctx; - unsigned char output[100]; + unsigned char output[200]; size_t outlen, total_len; memset( key, 0x00, sizeof( key ) ); diff --git a/tests/suites/test_suite_cipher.gcm.data b/tests/suites/test_suite_cipher.gcm.data index 100afddf8..7a83dc5dd 100644 --- a/tests/suites/test_suite_cipher.gcm.data +++ b/tests/suites/test_suite_cipher.gcm.data @@ -111,4 +111,36 @@ enc_dec_buf_multipart:POLARSSL_CIPHER_AES_128_GCM:128:16:16 AES 128 GCM Decrypt test vector #1 depends_on:POLARSSL_AES_C:POLARSSL_GCM_C -decrypt_test_vec:POLARSSL_CIPHER_AES_128_CBC:-1:"d785dafea3e966731ef6fc6202262584":"d91a46205ee94058b3b8403997592dd2":"":"":"3b92a17c1b9c3578a68cffea5a5b6245":0:0 +decrypt_test_vec:POLARSSL_CIPHER_AES_128_GCM:-1:"d785dafea3e966731ef6fc6202262584":"d91a46205ee94058b3b8403997592dd2":"":"":"":"3b92a17c1b9c3578a68cffea5a5b6245":0:0 + +AES 128 GCM Decrypt test vector #2 +depends_on:POLARSSL_AES_C:POLARSSL_GCM_C +decrypt_test_vec:POLARSSL_CIPHER_AES_128_GCM:-1:"9ab5c8ca905b5fe50461f4a68941144b":"96dd3927a96e16123f2e9d6b367d303f":"":"":"":"6e0c53ef":0:0 + +AES 128 GCM Decrypt test vector #3 +depends_on:POLARSSL_AES_C:POLARSSL_GCM_C +decrypt_test_vec:POLARSSL_CIPHER_AES_128_GCM:-1:"b5fc7af605721a9cfe61c1ee6a4b3e22":"6b757d4055823d1035d01077666037d6":"":"":"":"e8c09ddd":0:POLARSSL_ERR_GCM_AUTH_FAILED + +AES 128 GCM Decrypt test vector #4 +depends_on:POLARSSL_AES_C:POLARSSL_GCM_C +decrypt_test_vec:POLARSSL_CIPHER_AES_128_GCM:-1:"03c0b4a6e508a8490db0d086a82c9db7":"ac52f6c1a05030321fa39f87e89fdb5e":"":"":"33316ca79d10a79f4fd038593e8eef09625089dc4e0ffe4bc1f2871554fa6666ab3e7fe7885edef694b410456f3ec0e513bb25f1b48d95e4820c5972c1aabb25c84c08566002dadc36df334c1ce86847964a122016d389ac873bca8c335a7a99bcef91e1b985ae5d488a2d7f78b4bf14e0c2dc715e814f4e24276057cf668172":"756292d8b4653887edef51679b161812":0:POLARSSL_ERR_GCM_AUTH_FAILED + +AES 128 GCM Decrypt test vector #5 +depends_on:POLARSSL_AES_C:POLARSSL_GCM_C +decrypt_test_vec:POLARSSL_CIPHER_AES_128_GCM:-1:"2bc73fba942ff105823b5dccf6befb1c":"902c3e3b69b1ef8395d7281ff74cce38":"":"":"4adec0b4ac00325a860044d9f9519daa4f7c163229a75819b0fd7d8e23319f030e61dfa8eadabff42ea27bc36bdb6cad249e801ca631b656836448b7172c11126bad2781e6a1aa4f62c4eda53409408b008c057e0b81215cc13ddabbb8f1915f4bbab854f8b00763a530ad5055d265778cd3080d0bd35b76a329bdd5b5a2d268":"ebdd7c8e87fe733138a433543542d1":0:0 + +AES 128 GCM Decrypt test vector #6 +depends_on:POLARSSL_AES_C:POLARSSL_GCM_C +decrypt_test_vec:POLARSSL_CIPHER_AES_128_GCM:-1:"0dd358bc3f992f26e81e3a2f3aa2d517":"d8c750bb443ee1a169dfe97cfe4d855b":"87cc4fd75788c9d5cc83bae5d764dd249d178ab23224049795d4288b5ed9ea3f317068a39a7574b300c8544226e87b08e008fbe241d094545c211d56ac44437d41491a438272738968c8d371aa7787b5f606c8549a9d868d8a71380e9657d3c0337979feb01de5991fc1470dfc59eb02511efbbff3fcb479a862ba3844a25aaa":"77949b29f085bb3abb71a5386003811233056d3296eb093370f7777dadd306d93d59dcb9754d3857cf2758091ba661f845ef0582f6ae0e134328106f0d5d16b541cd74fdc756dc7b53f4f8a194daeea9369ebb1630c01ccb307b848e9527da20a39898d748fd59206f0b79d0ed946a8958033a45bd9ae673518b32606748eb65":"":"a81d13973baa22a751833d7d3f94b3b1":0:0 + +AES 128 GCM Decrypt test vector #7 +depends_on:POLARSSL_AES_C:POLARSSL_GCM_C +decrypt_test_vec:POLARSSL_CIPHER_AES_128_GCM:-1:"9a433c612d7e1bdff881e4d63ba8b141":"8b670cf31f470f79a6c0b79e73863ca1":"ce10758332f423228b5e4ae31efda7677586934a1d8f05d9b7a0dc4e2010ec3eaacb71a527a5fff8e787d75ebd24ad163394c891b33477ed9e2a2d853c364cb1c5d0bc317fcaf4010817dbe5f1fd1037c701b291b3a66b164bc818bf5c00a4c210a1671faa574d74c7f3543f6c09aaf117e12e2eb3dae55edb1cc5b4086b617d":"":"":"8526fd25daf890e79946a205b698f287":0:POLARSSL_ERR_GCM_AUTH_FAILED + +AES 128 GCM Decrypt test vector #8 +depends_on:POLARSSL_AES_C:POLARSSL_GCM_C +decrypt_test_vec:POLARSSL_CIPHER_AES_128_GCM:-1:"69eedf3777e594c30e94e9c5e2bce467":"a3330638a809ba358d6c098e4342b81e":"5114e9983c96fecec3f7304ca42f52aa16cb7c6aadfb62ad537c93a3188835ca0703dad34c73cf96435b668b68a7a1d056931959316e8d3ab956bf64c4e07479c7767f9d488b0c0c351333ccf400b7e0be19a0fd173e3f2a1ae313f27e516952260fd2da9ab9daca478ebb93cd07d0b7503b32364d8e308d904d966c58f226bb":"208e6321238bf5c6e2ef55a4b8f531cbbfb0d77374fe32df6dd663486cf79beeed39bb6910c3c78dd0cc30707a0a12b226b2d06024db25dcd8a4e620f009cafa5242121e864c7f3f4360aaf1e9d4e548d99615156f156008418c1c41ff2bbc007cecf8f209c73203e6df89b32871de637b3d6af2e277d146ae03f3404d387b77":"df4e3f2b47cf0e8590228fcf9913fb8a5eb9751bba318fd2d57be68c7e788e04fabf303699b99f26313d1c4956105cd2817aad21b91c28f3b9251e9c0b354490fa5abfcea0065aa3cc9b96772eb8af06a1a9054bf12d3ae698dfb01a13f989f8b8a4bb61686cf3adf58f05873a24d403a62a092290c2481e4159588fea6b9a09":"5de3068e1e20eed469265000077b1db9":0:0 + +AES 128 GCM Decrypt test vector #9 +depends_on:POLARSSL_AES_C:POLARSSL_GCM_C +decrypt_test_vec:POLARSSL_CIPHER_AES_128_GCM:-1:"45cc35311eedf0ba093bf901931a7036":"fed5084de3c348f5a0adf4c2fd4e848a":"5dc8d7525eaad035c19714ae1b1e538cb66a4089027245351e0ad9297410fb3a0c1155407c10a8bb95a9ca624a9c9925dac003ee78926c6e90ff4ccdba10e8a78bda1c4478162a0e302de5ff05fb0f94c89c3c7429fb94828bdcd97d21333c2ee72963ee6f056ce272b8bab007e653a42b01d1d2041ba627f169c8c0d32e6dae":"":"6e210914e4aed188d576f5ad7fc7e4cf7dd8d82f34ea3bcbdb7267cfd9045f806978dbff3460c4e8ff8c4edb6ad2edba405a8d915729d89aab2116b36a70b54f5920a97f5a571977e0329eda6c696749be940eabfc6d8b0bbd6fbdb87657b3a7695da9f5d3a7384257f20e0becd8512d3705cc246ee6ca1e610921cf92603d79":"266a895fc21da5176b44b446d7d1921d":0:POLARSSL_ERR_GCM_AUTH_FAILED diff --git a/tests/suites/test_suite_gcm.function b/tests/suites/test_suite_gcm.function index c00ec0b10..2b870d1e3 100644 --- a/tests/suites/test_suite_gcm.function +++ b/tests/suites/test_suite_gcm.function @@ -95,6 +95,7 @@ void gcm_decrypt_and_verify( char *hex_key_string, char *hex_src_string, } else { + TEST_ASSERT( ret == 0 ); hexify( dst_str, output, pt_len ); TEST_ASSERT( strcmp( (char *) dst_str, pt_result ) == 0 ); From 83f3fc0d772d1137b225a9c9bacec084177f2e70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Wed, 4 Sep 2013 12:07:24 +0200 Subject: [PATCH 16/23] Add AES-192-GCM --- include/polarssl/cipher.h | 1 + include/polarssl/cipher_wrap.h | 1 + library/cipher.c | 10 ++++++++++ library/cipher_wrap.c | 11 +++++++++++ 4 files changed, 23 insertions(+) diff --git a/include/polarssl/cipher.h b/include/polarssl/cipher.h index b7d449210..cc692089a 100644 --- a/include/polarssl/cipher.h +++ b/include/polarssl/cipher.h @@ -80,6 +80,7 @@ typedef enum { POLARSSL_CIPHER_AES_192_CTR, POLARSSL_CIPHER_AES_256_CTR, POLARSSL_CIPHER_AES_128_GCM, + POLARSSL_CIPHER_AES_192_GCM, POLARSSL_CIPHER_AES_256_GCM, POLARSSL_CIPHER_CAMELLIA_128_CBC, POLARSSL_CIPHER_CAMELLIA_192_CBC, diff --git a/include/polarssl/cipher_wrap.h b/include/polarssl/cipher_wrap.h index 4dabb44ee..84852561f 100644 --- a/include/polarssl/cipher_wrap.h +++ b/include/polarssl/cipher_wrap.h @@ -56,6 +56,7 @@ extern const cipher_info_t aes_256_ctr_info; #if defined(POLARSSL_GCM_C) extern const cipher_info_t aes_128_gcm_info; +extern const cipher_info_t aes_192_gcm_info; extern const cipher_info_t aes_256_gcm_info; #endif /* POLARSSL_GCM_C */ diff --git a/library/cipher.c b/library/cipher.c index 160f4bcad..a014eca5e 100644 --- a/library/cipher.c +++ b/library/cipher.c @@ -67,6 +67,12 @@ static const int supported_ciphers[] = { POLARSSL_CIPHER_AES_256_CTR, #endif /* defined(POLARSSL_CIPHER_MODE_CTR) */ +#if defined(POLARSSL_GCM_C) + POLARSSL_CIPHER_AES_128_GCM, + POLARSSL_CIPHER_AES_192_GCM, + POLARSSL_CIPHER_AES_256_GCM, +#endif /* defined(POLARSSL_GCM_C) */ + #endif /* defined(POLARSSL_AES_C) */ #if defined(POLARSSL_ARC4_C) @@ -157,6 +163,8 @@ const cipher_info_t *cipher_info_from_type( const cipher_type_t cipher_type ) #if defined(POLARSSL_GCM_C) case POLARSSL_CIPHER_AES_128_GCM: return &aes_128_gcm_info; + case POLARSSL_CIPHER_AES_192_GCM: + return &aes_192_gcm_info; case POLARSSL_CIPHER_AES_256_GCM: return &aes_256_gcm_info; #endif /* defined(POLARSSL_GCM_C) */ @@ -293,6 +301,8 @@ const cipher_info_t *cipher_info_from_string( const char *cipher_name ) #if defined(POLARSSL_GCM_C) if( !strcasecmp( "AES-128-GCM", cipher_name ) ) return cipher_info_from_type( POLARSSL_CIPHER_AES_128_GCM ); + if( !strcasecmp( "AES-192-GCM", cipher_name ) ) + return cipher_info_from_type( POLARSSL_CIPHER_AES_192_GCM ); if( !strcasecmp( "AES-256-GCM", cipher_name ) ) return cipher_info_from_type( POLARSSL_CIPHER_AES_256_GCM ); #endif diff --git a/library/cipher_wrap.c b/library/cipher_wrap.c index ebe60cf20..79daaf987 100644 --- a/library/cipher_wrap.c +++ b/library/cipher_wrap.c @@ -286,6 +286,17 @@ const cipher_info_t aes_128_gcm_info = { &gcm_aes_info }; +const cipher_info_t aes_192_gcm_info = { + POLARSSL_CIPHER_AES_192_GCM, + POLARSSL_MODE_GCM, + 192, + "AES-192-GCM", + 12, + 1, + 16, + &gcm_aes_info +}; + const cipher_info_t aes_256_gcm_info = { POLARSSL_CIPHER_AES_256_GCM, POLARSSL_MODE_GCM, From ce4112538c5d5710ab24063f033847ee77332b61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Wed, 4 Sep 2013 12:28:37 +0200 Subject: [PATCH 17/23] Fix RC4 key length in cipher --- include/polarssl/arc4.h | 2 +- library/cipher_wrap.c | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/include/polarssl/arc4.h b/include/polarssl/arc4.h index aa8feaaf7..9333265d3 100644 --- a/include/polarssl/arc4.h +++ b/include/polarssl/arc4.h @@ -55,7 +55,7 @@ arc4_context; * * \param ctx ARC4 context to be initialized * \param key the secret key - * \param keylen length of the key + * \param keylen length of the key, in bytes */ void arc4_setup( arc4_context *ctx, const unsigned char *key, unsigned int keylen ); diff --git a/library/cipher_wrap.c b/library/cipher_wrap.c index 79daaf987..f09823ac7 100644 --- a/library/cipher_wrap.c +++ b/library/cipher_wrap.c @@ -786,7 +786,11 @@ static int arc4_crypt_stream_wrap( void *ctx, size_t length, static int arc4_setkey_wrap( void *ctx, const unsigned char *key, unsigned int key_length ) { - arc4_setup( (arc4_context *) ctx, key, key_length ); + /* we get key_length in bits, arc4 expects it in bytes */ + if( key_length % 8 != 0) + return( POLARSSL_ERR_CIPHER_BAD_INPUT_DATA ); + + arc4_setup( (arc4_context *) ctx, key, key_length / 8 ); return( 0 ); } From 45125bc160b1c120cb3b70d233162dc8bb107a5e Mon Sep 17 00:00:00 2001 From: Paul Bakker Date: Wed, 4 Sep 2013 16:47:11 +0200 Subject: [PATCH 18/23] Changes to handle merged enhancements --- library/ssl_tls.c | 111 ++++++++++++++++++++++++++++------------------ 1 file changed, 67 insertions(+), 44 deletions(-) diff --git a/library/ssl_tls.c b/library/ssl_tls.c index 52d4b33cd..399d6ba75 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -643,46 +643,31 @@ int ssl_derive_keys( ssl_context *ssl ) if( ( ret = cipher_init_ctx( &transform->cipher_ctx_enc, cipher_info ) ) != 0 ) { + SSL_DEBUG_RET( 1, "cipher_init_ctx", ret ); return( ret ); } if( ( ret = cipher_init_ctx( &transform->cipher_ctx_dec, cipher_info ) ) != 0 ) { + SSL_DEBUG_RET( 1, "cipher_init_ctx", ret ); return( ret ); } - if( cipher_info->type == POLARSSL_CIPHER_ARC4_128 ) + if( ( ret = cipher_setkey( &transform->cipher_ctx_enc, key1, + cipher_info->key_length, + POLARSSL_ENCRYPT ) ) != 0 ) { - if( ( ret = cipher_setkey( &transform->cipher_ctx_enc, key1, - cipher_info->key_length / 8, - POLARSSL_ENCRYPT ) ) != 0 ) - { - return( ret ); - } - - if( ( ret = cipher_setkey( &transform->cipher_ctx_dec, key2, - cipher_info->key_length / 8, - POLARSSL_DECRYPT ) ) != 0 ) - { - return( ret ); - } + SSL_DEBUG_RET( 1, "cipher_setkey", ret ); + return( ret ); } - else - { - if( ( ret = cipher_setkey( &transform->cipher_ctx_enc, key1, - cipher_info->key_length, - POLARSSL_ENCRYPT ) ) != 0 ) - { - return( ret ); - } - if( ( ret = cipher_setkey( &transform->cipher_ctx_dec, key2, - cipher_info->key_length, - POLARSSL_DECRYPT ) ) != 0 ) - { - return( ret ); - } + if( ( ret = cipher_setkey( &transform->cipher_ctx_dec, key2, + cipher_info->key_length, + POLARSSL_DECRYPT ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "cipher_setkey", ret ); + return( ret ); } if( cipher_info->mode == POLARSSL_MODE_CBC ) @@ -690,12 +675,14 @@ int ssl_derive_keys( ssl_context *ssl ) if( ( ret = cipher_set_padding_mode( &transform->cipher_ctx_enc, POLARSSL_PADDING_NONE ) ) != 0 ) { + SSL_DEBUG_RET( 1, "cipher_set_padding_mode", ret ); return( ret ); } if( ( ret = cipher_set_padding_mode( &transform->cipher_ctx_dec, POLARSSL_PADDING_NONE ) ) != 0 ) { + SSL_DEBUG_RET( 1, "cipher_set_padding_mode", ret ); return( ret ); } } @@ -953,10 +940,17 @@ static int ssl_encrypt_buf( ssl_context *ssl ) SSL_DEBUG_BUF( 4, "before encrypt: output payload", ssl->out_msg, ssl->out_msglen ); - if( ( ret = cipher_reset( &ssl->transform_out->cipher_ctx_enc, - ssl->transform_out->iv_enc, - ssl->transform_out->ivlen, NULL, 0 ) ) != 0 ) + if( ( ret = cipher_reset( &ssl->transform_out->cipher_ctx_enc ) ) != 0 ) { + SSL_DEBUG_RET( 1, "cipher_reset", ret ); + return( ret ); + } + + if( ( ret = cipher_set_iv( &ssl->transform_out->cipher_ctx_enc, + ssl->transform_out->iv_enc, + ssl->transform_out->ivlen ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "cipher_set_iv", ret ); return( ret ); } @@ -964,6 +958,7 @@ static int ssl_encrypt_buf( ssl_context *ssl ) ssl->out_msg, ssl->out_msglen, ssl->out_msg, &olen ) ) != 0 ) { + SSL_DEBUG_RET( 1, "cipher_update", ret ); return( ret ); } @@ -976,8 +971,9 @@ static int ssl_encrypt_buf( ssl_context *ssl ) } if( ( ret = cipher_finish( &ssl->transform_out->cipher_ctx_enc, - ssl->out_msg + olen, &olen, NULL, 0 ) ) != 0 ) + ssl->out_msg + olen, &olen ) ) != 0 ) { + SSL_DEBUG_RET( 1, "cipher_finish", ret ); return( ret ); } @@ -1110,10 +1106,17 @@ static int ssl_encrypt_buf( ssl_context *ssl ) SSL_DEBUG_BUF( 4, "before encrypt: output payload", ssl->out_iv, ssl->out_msglen ); - if( ( ret = cipher_reset( &ssl->transform_out->cipher_ctx_enc, - ssl->transform_out->iv_enc, - ssl->transform_out->ivlen, NULL, 0 ) ) != 0 ) + if( ( ret = cipher_reset( &ssl->transform_out->cipher_ctx_enc ) ) != 0 ) { + SSL_DEBUG_RET( 1, "cipher_reset", ret ); + return( ret ); + } + + if( ( ret = cipher_set_iv( &ssl->transform_out->cipher_ctx_enc, + ssl->transform_out->iv_enc, + ssl->transform_out->ivlen ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "cipher_set_iv", ret ); return( ret ); } @@ -1121,14 +1124,16 @@ static int ssl_encrypt_buf( ssl_context *ssl ) enc_msg, enc_msglen, enc_msg, &olen ) ) != 0 ) { + SSL_DEBUG_RET( 1, "cipher_update", ret ); return( ret ); } enc_msglen -= olen; if( ( ret = cipher_finish( &ssl->transform_out->cipher_ctx_enc, - enc_msg + olen, &olen, NULL, 0 ) ) != 0 ) + enc_msg + olen, &olen ) ) != 0 ) { + SSL_DEBUG_RET( 1, "cipher_finish", ret ); return( ret ); } @@ -1193,10 +1198,17 @@ static int ssl_decrypt_buf( ssl_context *ssl ) padlen = 0; - if( ( ret = cipher_reset( &ssl->transform_in->cipher_ctx_dec, - ssl->transform_in->iv_dec, - ssl->transform_in->ivlen, NULL, 0 ) ) != 0 ) + if( ( ret = cipher_reset( &ssl->transform_in->cipher_ctx_dec ) ) != 0 ) { + SSL_DEBUG_RET( 1, "cipher_reset", ret ); + return( ret ); + } + + if( ( ret = cipher_set_iv( &ssl->transform_in->cipher_ctx_dec, + ssl->transform_in->iv_dec, + ssl->transform_in->ivlen ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "cipher_set_iv", ret ); return( ret ); } @@ -1204,6 +1216,7 @@ static int ssl_decrypt_buf( ssl_context *ssl ) ssl->in_msg, ssl->in_msglen, ssl->in_msg, &olen ) ) != 0 ) { + SSL_DEBUG_RET( 1, "cipher_update", ret ); return( ret ); } @@ -1215,8 +1228,9 @@ static int ssl_decrypt_buf( ssl_context *ssl ) } if( ( ret = cipher_finish( &ssl->transform_in->cipher_ctx_dec, - ssl->in_msg + olen, &olen, NULL, 0 ) ) != 0 ) + ssl->in_msg + olen, &olen ) ) != 0 ) { + SSL_DEBUG_RET( 1, "cipher_finish", ret ); return( ret ); } @@ -1336,10 +1350,17 @@ static int ssl_decrypt_buf( ssl_context *ssl ) } #endif /* POLARSSL_SSL_PROTO_TLS1_1 || POLARSSL_SSL_PROTO_TLS1_2 */ - if( ( ret = cipher_reset( &ssl->transform_in->cipher_ctx_dec, - ssl->transform_in->iv_dec, - ssl->transform_in->ivlen, NULL, 0 ) ) != 0 ) + if( ( ret = cipher_reset( &ssl->transform_in->cipher_ctx_dec ) ) != 0 ) { + SSL_DEBUG_RET( 1, "cipher_reset", ret ); + return( ret ); + } + + if( ( ret = cipher_set_iv( &ssl->transform_in->cipher_ctx_dec, + ssl->transform_in->iv_dec, + ssl->transform_in->ivlen ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "cipher_set_iv", ret ); return( ret ); } @@ -1347,13 +1368,15 @@ static int ssl_decrypt_buf( ssl_context *ssl ) dec_msg, dec_msglen, dec_msg_result, &olen ) ) != 0 ) { + SSL_DEBUG_RET( 1, "cipher_update", ret ); return( ret ); } dec_msglen -= olen; if( ( ret = cipher_finish( &ssl->transform_in->cipher_ctx_dec, - dec_msg_result + olen, &olen, NULL, 0 ) ) != 0 ) + dec_msg_result + olen, &olen ) ) != 0 ) { + SSL_DEBUG_RET( 1, "cipher_finish", ret ); return( ret ); } From 1af50a240bb9609e9b8faee90781bfec792ee058 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Thu, 5 Sep 2013 10:30:32 +0200 Subject: [PATCH 19/23] Cipher: test multiple cycles GCM-cipher: just trust the user to call update_ad at the right time --- library/cipher.c | 7 --- tests/suites/test_suite_cipher.function | 59 ++++++++++++++----------- 2 files changed, 34 insertions(+), 32 deletions(-) diff --git a/library/cipher.c b/library/cipher.c index a014eca5e..280124d6d 100644 --- a/library/cipher.c +++ b/library/cipher.c @@ -445,13 +445,6 @@ int cipher_update_ad( cipher_context_t *ctx, #if defined(POLARSSL_GCM_C) if( POLARSSL_MODE_GCM == ctx->cipher_info->mode ) { - /* Make sure we're called right after cipher_reset() */ - if( ((gcm_context *) ctx->cipher_ctx)->len != 0 || - ((gcm_context *) ctx->cipher_ctx)->add_len != 0 ) - { - return POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE; - } - return gcm_starts( ctx->cipher_ctx, ctx->operation, ctx->iv, ctx->iv_size, ad, ad_len ); } diff --git a/tests/suites/test_suite_cipher.function b/tests/suites/test_suite_cipher.function index c556a2e56..3cd1768f6 100644 --- a/tests/suites/test_suite_cipher.function +++ b/tests/suites/test_suite_cipher.function @@ -15,34 +15,26 @@ void enc_dec_buf( int cipher_id, char *cipher_string, int key_len, int length_val, int pad_mode ) { - size_t length = length_val; + size_t length = length_val, outlen, total_len, i; unsigned char key[32]; unsigned char iv[16]; unsigned char ad[13]; unsigned char tag[16]; + unsigned char inbuf[64]; + unsigned char encbuf[64]; + unsigned char decbuf[64]; const cipher_info_t *cipher_info; cipher_context_t ctx_dec; cipher_context_t ctx_enc; - unsigned char inbuf[64]; - unsigned char encbuf[64]; - unsigned char decbuf[64]; - - size_t outlen = 0; - size_t total_len = 0; - - memset( key, 0, 32 ); - memset( iv , 0, 16 ); - + /* + * Prepare contexts + */ memset( &ctx_dec, 0, sizeof( ctx_dec ) ); memset( &ctx_enc, 0, sizeof( ctx_enc ) ); - - memset( inbuf, 5, 64 ); - memset( encbuf, 0, 64 ); - memset( decbuf, 0, 64 ); - memset( tag, 0, 16 ); - memset( ad, 0x2a, 13 ); + + memset( key, 0x2a, sizeof( key ) ); /* Check and get info structures */ cipher_info = cipher_info_from_type( cipher_id ); @@ -52,7 +44,7 @@ void enc_dec_buf( int cipher_id, char *cipher_string, int key_len, /* Initialise enc and dec contexts */ TEST_ASSERT( 0 == cipher_init_ctx( &ctx_dec, cipher_info ) ); TEST_ASSERT( 0 == cipher_init_ctx( &ctx_enc, cipher_info ) ); - + TEST_ASSERT( 0 == cipher_setkey( &ctx_dec, key, key_len, POLARSSL_DECRYPT ) ); TEST_ASSERT( 0 == cipher_setkey( &ctx_enc, key, key_len, POLARSSL_ENCRYPT ) ); @@ -62,15 +54,28 @@ void enc_dec_buf( int cipher_id, char *cipher_string, int key_len, TEST_ASSERT( 0 == cipher_set_padding_mode( &ctx_enc, pad_mode ) ); } - TEST_ASSERT( 0 == cipher_set_iv( &ctx_dec, iv, 16 ) ); - TEST_ASSERT( 0 == cipher_set_iv( &ctx_enc, iv, 16 ) ); + /* + * Do a few encode/decode cycles + */ + for( i = 0; i < 3; i++ ) + { + memset( iv , 0x00 + i, sizeof( iv ) ); + memset( ad, 0x10 + i, sizeof( ad ) ); + memset( inbuf, 0x20 + i, sizeof( inbuf ) ); + + memset( encbuf, 0, sizeof( encbuf ) ); + memset( decbuf, 0, sizeof( decbuf ) ); + memset( tag, 0, sizeof( tag ) ); + + TEST_ASSERT( 0 == cipher_set_iv( &ctx_dec, iv, sizeof( iv ) ) ); + TEST_ASSERT( 0 == cipher_set_iv( &ctx_enc, iv, sizeof( iv ) ) ); TEST_ASSERT( 0 == cipher_reset( &ctx_dec ) ); TEST_ASSERT( 0 == cipher_reset( &ctx_enc ) ); #if defined(POLARSSL_CIPHER_MODE_AEAD) - TEST_ASSERT( 0 == cipher_update_ad( &ctx_dec, ad, 13 ) ); - TEST_ASSERT( 0 == cipher_update_ad( &ctx_enc, ad, 13 ) ); + TEST_ASSERT( 0 == cipher_update_ad( &ctx_dec, ad, sizeof( ad ) - i ) ); + TEST_ASSERT( 0 == cipher_update_ad( &ctx_enc, ad, sizeof( ad ) - i ) ); #endif /* POLARSSL_CIPHER_MODE_AEAD */ /* encode length number of bytes from inbuf */ @@ -86,7 +91,7 @@ void enc_dec_buf( int cipher_id, char *cipher_string, int key_len, total_len += outlen; #if defined(POLARSSL_CIPHER_MODE_AEAD) - TEST_ASSERT( 0 == cipher_write_tag( &ctx_enc, tag, 16 ) ); + TEST_ASSERT( 0 == cipher_write_tag( &ctx_enc, tag, sizeof( tag ) ) ); #endif /* POLARSSL_CIPHER_MODE_AEAD */ TEST_ASSERT( total_len == length || @@ -107,13 +112,17 @@ void enc_dec_buf( int cipher_id, char *cipher_string, int key_len, total_len += outlen; #if defined(POLARSSL_CIPHER_MODE_AEAD) - TEST_ASSERT( 0 == cipher_check_tag( &ctx_dec, tag, 16 ) ); + TEST_ASSERT( 0 == cipher_check_tag( &ctx_dec, tag, sizeof( tag ) ) ); #endif /* POLARSSL_CIPHER_MODE_AEAD */ + /* check result */ TEST_ASSERT( total_len == length ); - TEST_ASSERT( 0 == memcmp(inbuf, decbuf, length) ); + } + /* + * Done + */ TEST_ASSERT( 0 == cipher_free_ctx( &ctx_dec ) ); TEST_ASSERT( 0 == cipher_free_ctx( &ctx_enc ) ); } From 226d5da1fc6b21448a9d37bccafd0b7ba1445738 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Thu, 5 Sep 2013 13:19:22 +0200 Subject: [PATCH 20/23] GCM ciphersuites partially using cipher layer --- include/polarssl/ssl.h | 48 ------------------------------------------ library/ssl_tls.c | 10 +++++++-- 2 files changed, 8 insertions(+), 50 deletions(-) diff --git a/include/polarssl/ssl.h b/include/polarssl/ssl.h index aafbfb687..52ec2168d 100644 --- a/include/polarssl/ssl.h +++ b/include/polarssl/ssl.h @@ -441,40 +441,6 @@ struct _ssl_session #endif /* POLARSSL_SSL_TRUNCATED_HMAC */ }; -/* - * Helpers to find the correct size of the context in _ssl_transform - * (in the long run, we'll use the cipher layer, but for now...) - */ -#define SSL_MAX(a, b) ( a > b ? a : b ) -#define SSL_CTX_MAX_0 0 -#if defined(POLARSSL_AES_C) -#define SSL_CTX_MAX_1 SSL_MAX( SSL_CTX_MAX_0, sizeof( aes_context ) ) -#else -#define SSL_CTX_MAX_1 SSL_CTX_MAX_0 -#endif -#if defined(POLARSSL_ARC4_C) -#define SSL_CTX_MAX_2 SSL_MAX( SSL_CTX_MAX_1, sizeof( arc4_context ) ) -#else -#define SSL_CTX_MAX_2 SSL_CTX_MAX_1 -#endif -#if defined(POLARSSL_DES_C) -#define SSL_CTX_MAX_3 SSL_MAX( SSL_CTX_MAX_2, sizeof( des_context ) ) -#define SSL_CTX_MAX_4 SSL_MAX( SSL_CTX_MAX_3, sizeof( des3_context ) ) -#else -#define SSL_CTX_MAX_4 SSL_CTX_MAX_2 -#endif -#if defined(POLARSSL_CAMELLIA_C) -#define SSL_CTX_MAX_5 SSL_MAX( SSL_CTX_MAX_4, sizeof( camellia_context ) ) -#else -#define SSL_CTX_MAX_5 SSL_CTX_MAX_4 -#endif -#if defined(POLARSSL_GCM_C) -#define SSL_CTX_MAX_6 SSL_MAX( SSL_CTX_MAX_5, sizeof( gcm_context ) ) -#else -#define SSL_CTX_MAX_6 SSL_CTX_MAX_5 -#endif -#define SSL_CTX_MAX SSL_CTX_MAX_6 - /* * This structure contains a full set of runtime transform parameters * either in negotiation or active. @@ -507,9 +473,6 @@ struct _ssl_transform cipher_context_t cipher_ctx_enc; /*!< encryption context */ cipher_context_t cipher_ctx_dec; /*!< decryption context */ - uint32_t ctx_enc[SSL_CTX_MAX / 4]; /*!< encryption context */ - uint32_t ctx_dec[SSL_CTX_MAX / 4]; /*!< decryption context */ - /* * Session specific compression layer */ @@ -519,17 +482,6 @@ struct _ssl_transform #endif }; -/* Not needed any more */ -#undef SSL_MAX -#undef SSL_CTX_MAX_0 -#undef SSL_CTX_MAX_1 -#undef SSL_CTX_MAX_2 -#undef SSL_CTX_MAX_3 -#undef SSL_CTX_MAX_4 -#undef SSL_CTX_MAX_5 -#undef SSL_CTX_MAX_6 -#undef SSL_CTX_MAX - /* * This structure contains the parameters only needed during handshake. */ diff --git a/library/ssl_tls.c b/library/ssl_tls.c index 399d6ba75..cddaec668 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -640,6 +640,8 @@ int ssl_derive_keys( ssl_context *ssl ) case POLARSSL_CIPHER_AES_128_CBC: case POLARSSL_CIPHER_AES_256_CBC: case POLARSSL_CIPHER_DES_CBC: + case POLARSSL_CIPHER_AES_128_GCM: + case POLARSSL_CIPHER_AES_256_GCM: if( ( ret = cipher_init_ctx( &transform->cipher_ctx_enc, cipher_info ) ) != 0 ) { @@ -1021,6 +1023,9 @@ static int ssl_encrypt_buf( ssl_context *ssl ) ssl->transform_out->iv_enc + ssl->transform_out->fixed_ivlen, ssl->transform_out->ivlen - ssl->transform_out->fixed_ivlen ); + SSL_DEBUG_BUF( 4, "IV used", ssl->out_iv, + ssl->transform_out->ivlen - ssl->transform_out->fixed_ivlen ); + /* * Fix pointer positions and message length with added IV */ @@ -1041,7 +1046,7 @@ static int ssl_encrypt_buf( ssl_context *ssl ) */ ssl->out_msglen += 16; - gcm_crypt_and_tag( (gcm_context *) ssl->transform_out->ctx_enc, + gcm_crypt_and_tag( ssl->transform_out->cipher_ctx_enc->cipher_ctx, GCM_ENCRYPT, enc_msglen, ssl->transform_out->iv_enc, ssl->transform_out->ivlen, add_data, 13, @@ -1280,7 +1285,7 @@ static int ssl_decrypt_buf( ssl_context *ssl ) ssl->transform_in->ivlen ); SSL_DEBUG_BUF( 4, "TAG used", dec_msg + dec_msglen, 16 ); - ret = gcm_auth_decrypt( (gcm_context *) ssl->transform_in->ctx_dec, + ret = gcm_auth_decrypt( ssl->transform_in->cipher_ctx_dec->cipher_ctx, dec_msglen, ssl->transform_in->iv_dec, ssl->transform_in->ivlen, @@ -1295,6 +1300,7 @@ static int ssl_decrypt_buf( ssl_context *ssl ) return( POLARSSL_ERR_SSL_INVALID_MAC ); } + } else #endif /* POLARSSL_GCM_C */ From b8bd5937417eccc88a9a1e28c8722e7918e5a78b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Thu, 5 Sep 2013 13:38:15 +0200 Subject: [PATCH 21/23] Restrict cipher_update() for GCM --- include/polarssl/cipher.h | 4 ++ library/cipher.c | 51 +++++-------------------- library/ssl_tls.c | 14 +------ tests/suites/test_suite_cipher.gcm.data | 16 +------- 4 files changed, 18 insertions(+), 67 deletions(-) diff --git a/include/polarssl/cipher.h b/include/polarssl/cipher.h index cc692089a..aad488fc8 100644 --- a/include/polarssl/cipher.h +++ b/include/polarssl/cipher.h @@ -512,6 +512,10 @@ int cipher_update_ad( cipher_context_t *ctx, * POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE on an * unsupported mode for a cipher or a cipher specific * error code. + * + * \note If the underlying cipher is GCM, all calls to this + * function, except the last one before cipher_finish(), + * must have ilen a multiple of the block size. */ int cipher_update( cipher_context_t *ctx, const unsigned char *input, size_t ilen, unsigned char *output, size_t *olen ); diff --git a/library/cipher.c b/library/cipher.c index 280124d6d..8d90a646b 100644 --- a/library/cipher.c +++ b/library/cipher.c @@ -467,14 +467,21 @@ int cipher_update( cipher_context_t *ctx, const unsigned char *input, size_t ile return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA; } +#if defined(POLARSSL_GCM_C) + if( ctx->cipher_info->mode == POLARSSL_MODE_GCM) + { + *olen = ilen; + return gcm_update( ctx->cipher_ctx, ilen, input, output ); + } +#endif + if( input == output && ( ctx->unprocessed_len != 0 || ilen % cipher_get_block_size( ctx ) ) ) { return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA; } - if( ctx->cipher_info->mode == POLARSSL_MODE_CBC || - ctx->cipher_info->mode == POLARSSL_MODE_GCM ) + if( ctx->cipher_info->mode == POLARSSL_MODE_CBC ) { /* * If there is not enough data for a full block, cache it. @@ -501,18 +508,6 @@ int cipher_update( cipher_context_t *ctx, const unsigned char *input, size_t ile memcpy( &( ctx->unprocessed_data[ctx->unprocessed_len] ), input, copy_len ); -#if defined(POLARSSL_GCM_C) - if( ctx->cipher_info->mode == POLARSSL_MODE_GCM ) - { - if( 0 != ( ret = gcm_update( ctx->cipher_ctx, - cipher_get_block_size( ctx ), - ctx->unprocessed_data, output ) ) ) - { - return ret; - } - } - else -#endif if( 0 != ( ret = ctx->cipher_info->base->cbc_func( ctx->cipher_ctx, ctx->operation, cipher_get_block_size( ctx ), ctx->iv, ctx->unprocessed_data, output ) ) ) @@ -549,17 +544,6 @@ int cipher_update( cipher_context_t *ctx, const unsigned char *input, size_t ile */ if( ilen ) { -#if defined(POLARSSL_GCM_C) - if( ctx->cipher_info->mode == POLARSSL_MODE_GCM ) - { - if( 0 != ( ret = gcm_update( ctx->cipher_ctx, - ilen, input, output ) ) ) - { - return ret; - } - } - else -#endif if( 0 != ( ret = ctx->cipher_info->base->cbc_func( ctx->cipher_ctx, ctx->operation, ilen, ctx->iv, input, output ) ) ) { @@ -790,27 +774,12 @@ int cipher_finish( cipher_context_t *ctx, if( POLARSSL_MODE_CFB == ctx->cipher_info->mode || POLARSSL_MODE_CTR == ctx->cipher_info->mode || + POLARSSL_MODE_GCM == ctx->cipher_info->mode || POLARSSL_MODE_STREAM == ctx->cipher_info->mode ) { return 0; } -#if defined(POLARSSL_GCM_C) - if( POLARSSL_MODE_GCM == ctx->cipher_info->mode ) - { - if( 0 != ( ret = gcm_update( ctx->cipher_ctx, - ctx->unprocessed_len, ctx->unprocessed_data, - output ) ) ) - { - return( ret ); - } - - *olen += ctx->unprocessed_len; - - return( 0 ); - } -#endif - if( POLARSSL_MODE_CBC == ctx->cipher_info->mode ) { if( POLARSSL_ENCRYPT == ctx->operation ) diff --git a/library/ssl_tls.c b/library/ssl_tls.c index cddaec668..7e7ddd713 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -690,16 +690,6 @@ int ssl_derive_keys( ssl_context *ssl ) } break; -#if defined(POLARSSL_GCM_C) - case POLARSSL_CIPHER_AES_128_GCM: - case POLARSSL_CIPHER_AES_256_GCM: - gcm_init( (gcm_context *) transform->ctx_enc, key1, - cipher_info->key_length ); - gcm_init( (gcm_context *) transform->ctx_dec, key2, - cipher_info->key_length ); - break; -#endif - case POLARSSL_CIPHER_NULL: break; @@ -1046,7 +1036,7 @@ static int ssl_encrypt_buf( ssl_context *ssl ) */ ssl->out_msglen += 16; - gcm_crypt_and_tag( ssl->transform_out->cipher_ctx_enc->cipher_ctx, + gcm_crypt_and_tag( ssl->transform_out->cipher_ctx_enc.cipher_ctx, GCM_ENCRYPT, enc_msglen, ssl->transform_out->iv_enc, ssl->transform_out->ivlen, add_data, 13, @@ -1285,7 +1275,7 @@ static int ssl_decrypt_buf( ssl_context *ssl ) ssl->transform_in->ivlen ); SSL_DEBUG_BUF( 4, "TAG used", dec_msg + dec_msglen, 16 ); - ret = gcm_auth_decrypt( ssl->transform_in->cipher_ctx_dec->cipher_ctx, + ret = gcm_auth_decrypt( ssl->transform_in->cipher_ctx_dec.cipher_ctx, dec_msglen, ssl->transform_in->iv_dec, ssl->transform_in->ivlen, diff --git a/tests/suites/test_suite_cipher.gcm.data b/tests/suites/test_suite_cipher.gcm.data index 7a83dc5dd..7681d1878 100644 --- a/tests/suites/test_suite_cipher.gcm.data +++ b/tests/suites/test_suite_cipher.gcm.data @@ -85,25 +85,13 @@ AES 128 GCM Encrypt and decrypt 16 bytes in multiple parts 2 depends_on:POLARSSL_AES_C:POLARSSL_GCM_C enc_dec_buf_multipart:POLARSSL_CIPHER_AES_128_GCM:128:0:16 -AES 128 GCM Encrypt and decrypt 16 bytes in multiple parts 3 -depends_on:POLARSSL_AES_C:POLARSSL_GCM_C -enc_dec_buf_multipart:POLARSSL_CIPHER_AES_128_GCM:128:1:15 - -AES 128 GCM Encrypt and decrypt 16 bytes in multiple parts 4 -depends_on:POLARSSL_AES_C:POLARSSL_GCM_C -enc_dec_buf_multipart:POLARSSL_CIPHER_AES_128_GCM:128:15:1 - -AES 128 GCM Encrypt and decrypt 22 bytes in multiple parts 1 -depends_on:POLARSSL_AES_C:POLARSSL_GCM_C -enc_dec_buf_multipart:POLARSSL_CIPHER_AES_128_GCM:128:15:7 - AES 128 GCM Encrypt and decrypt 22 bytes in multiple parts 1 depends_on:POLARSSL_AES_C:POLARSSL_GCM_C enc_dec_buf_multipart:POLARSSL_CIPHER_AES_128_GCM:128:16:6 -AES 128 GCM Encrypt and decrypt 22 bytes in multiple parts 1 +AES 128 GCM Encrypt and decrypt 22 bytes in multiple parts 2 depends_on:POLARSSL_AES_C:POLARSSL_GCM_C -enc_dec_buf_multipart:POLARSSL_CIPHER_AES_128_GCM:128:17:6 +enc_dec_buf_multipart:POLARSSL_CIPHER_AES_128_GCM:128:0:22 AES 128 GCM Encrypt and decrypt 32 bytes in multiple parts 1 depends_on:POLARSSL_AES_C:POLARSSL_GCM_C From d13a4099dd8e48c38603784bdb8c7c0af1b1ee6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Thu, 5 Sep 2013 16:10:41 +0200 Subject: [PATCH 22/23] GCM ciphersuites using only cipher layer --- library/ssl_tls.c | 112 +++++++++++++++++++++++++++++++++++++--------- 1 file changed, 90 insertions(+), 22 deletions(-) diff --git a/library/ssl_tls.c b/library/ssl_tls.c index 7e7ddd713..2095424f0 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -982,7 +982,7 @@ static int ssl_encrypt_buf( ssl_context *ssl ) if( ssl->transform_out->ciphersuite_info->cipher == POLARSSL_CIPHER_AES_128_GCM || ssl->transform_out->ciphersuite_info->cipher == POLARSSL_CIPHER_AES_256_GCM ) { - size_t enc_msglen; + size_t enc_msglen, olen, totlen; unsigned char *enc_msg; unsigned char add_data[13]; int ret = POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE; @@ -1032,19 +1032,55 @@ static int ssl_encrypt_buf( ssl_context *ssl ) ssl->out_msg, ssl->out_msglen ); /* - * Adjust for tag + * Encrypt + */ + if( ( ret = cipher_set_iv( &ssl->transform_out->cipher_ctx_enc, + ssl->transform_out->iv_enc, + ssl->transform_out->ivlen ) ) != 0 || + ( ret = cipher_reset( &ssl->transform_out->cipher_ctx_enc ) ) != 0 ) + { + return( ret ); + } + + if( ( ret = cipher_update_ad( &ssl->transform_out->cipher_ctx_enc, + add_data, 13 ) ) != 0 ) + { + return( ret ); + } + + if( ( ret = cipher_update( &ssl->transform_out->cipher_ctx_enc, + enc_msg, enc_msglen, + enc_msg, &olen ) ) != 0 ) + { + return( ret ); + } + totlen = olen; + + if( ( ret = cipher_finish( &ssl->transform_out->cipher_ctx_enc, + enc_msg + olen, &olen ) ) != 0 ) + { + return( ret ); + } + totlen += olen; + + if( totlen != enc_msglen ) + { + SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( -1 ); + } + + /* + * Authenticate */ ssl->out_msglen += 16; - gcm_crypt_and_tag( ssl->transform_out->cipher_ctx_enc.cipher_ctx, - GCM_ENCRYPT, enc_msglen, - ssl->transform_out->iv_enc, ssl->transform_out->ivlen, - add_data, 13, - enc_msg, enc_msg, - 16, enc_msg + enc_msglen ); + if( ( ret = cipher_write_tag( &ssl->transform_out->cipher_ctx_enc, + enc_msg + enc_msglen, 16 ) ) != 0 ) + { + return( ret ); + } - SSL_DEBUG_BUF( 4, "after encrypt: tag", - enc_msg + enc_msglen, 16 ); + SSL_DEBUG_BUF( 4, "after encrypt: tag", enc_msg + enc_msglen, 16 ); } else #endif /* POLARSSL_GCM_C */ @@ -1244,7 +1280,7 @@ static int ssl_decrypt_buf( ssl_context *ssl ) { unsigned char *dec_msg; unsigned char *dec_msg_result; - size_t dec_msglen; + size_t dec_msglen, olen, totlen; unsigned char add_data[13]; int ret = POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE; @@ -1275,19 +1311,51 @@ static int ssl_decrypt_buf( ssl_context *ssl ) ssl->transform_in->ivlen ); SSL_DEBUG_BUF( 4, "TAG used", dec_msg + dec_msglen, 16 ); - ret = gcm_auth_decrypt( ssl->transform_in->cipher_ctx_dec.cipher_ctx, - dec_msglen, - ssl->transform_in->iv_dec, - ssl->transform_in->ivlen, - add_data, 13, - dec_msg + dec_msglen, 16, - dec_msg, dec_msg_result ); - - if( ret != 0 ) + /* + * Decrypt + */ + if( ( ret = cipher_set_iv( &ssl->transform_in->cipher_ctx_dec, + ssl->transform_in->iv_dec, + ssl->transform_in->ivlen ) ) != 0 || + ( ret = cipher_reset( &ssl->transform_in->cipher_ctx_dec ) ) != 0 ) { - SSL_DEBUG_MSG( 1, ( "AEAD decrypt failed on validation (ret = -0x%02x)", - -ret ) ); + return( ret ); + } + if( ( ret = cipher_update_ad( &ssl->transform_in->cipher_ctx_dec, + add_data, 13 ) ) != 0 ) + { + return( ret ); + } + + if( ( ret = cipher_update( &ssl->transform_in->cipher_ctx_dec, + dec_msg, dec_msglen, + dec_msg_result, &olen ) ) != 0 ) + { + return( ret ); + } + totlen = olen; + + if( ( ret = cipher_finish( &ssl->transform_in->cipher_ctx_dec, + dec_msg_result + olen, &olen ) ) != 0 ) + { + return( ret ); + } + totlen += olen; + + if( totlen != dec_msglen ) + { + SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( -1 ); + } + + /* + * Authenticate + */ + if( ( ret = cipher_check_tag( &ssl->transform_in->cipher_ctx_dec, + dec_msg + dec_msglen, 16 ) ) != 0 ) + { + SSL_DEBUG_RET( 1, "cipher_check_tag", ret ); return( POLARSSL_ERR_SSL_INVALID_MAC ); } From 7da0a38d430f6b426e2c8502f1af812c0d653950 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Thu, 5 Sep 2013 16:56:03 +0200 Subject: [PATCH 23/23] Rm some includes that are now useless --- include/polarssl/ssl.h | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/include/polarssl/ssl.h b/include/polarssl/ssl.h index 52ec2168d..eaebd6a72 100644 --- a/include/polarssl/ssl.h +++ b/include/polarssl/ssl.h @@ -49,30 +49,15 @@ #include "sha512.h" #endif +// for session tickets #if defined(POLARSSL_AES_C) #include "aes.h" #endif -#if defined(POLARSSL_ARC4_C) -#include "arc4.h" -#endif -#if defined(POLARSSL_DES_C) -#include "des.h" -#endif -#if defined(POLARSSL_CAMELLIA_C) -#include "camellia.h" -#endif -#if defined(POLARSSL_GCM_C) -#include "gcm.h" -#endif #if defined(POLARSSL_X509_PARSE_C) #include "x509.h" #endif -#if defined(POLARSSL_RSA_C) -#include "rsa.h" -#endif - #if defined(POLARSSL_DHM_C) #include "dhm.h" #endif