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