From 43aff2aec4993e16bb5008affaae7058d370672c Mon Sep 17 00:00:00 2001 From: Paul Bakker Date: Mon, 9 Sep 2013 00:10:27 +0200 Subject: [PATCH] Moved GCM to use cipher layer instead of AES directly --- include/polarssl/gcm.h | 16 ++++---- library/cipher_wrap.c | 9 +++-- library/gcm.c | 56 +++++++++++++++++++++------- tests/suites/test_suite_gcm.function | 4 +- 4 files changed, 58 insertions(+), 27 deletions(-) diff --git a/include/polarssl/gcm.h b/include/polarssl/gcm.h index dc058dcd7..1997c4bb1 100644 --- a/include/polarssl/gcm.h +++ b/include/polarssl/gcm.h @@ -1,7 +1,7 @@ /** * \file gcm.h * - * \brief Galois/Counter mode for AES + * \brief Galois/Counter mode for 128-bit block ciphers * * Copyright (C) 2006-2013, Brainspark B.V. * @@ -27,7 +27,7 @@ #ifndef POLARSSL_GCM_H #define POLARSSL_GCM_H -#include "aes.h" +#include "cipher.h" #ifdef _MSC_VER #include @@ -50,7 +50,7 @@ extern "C" { * \brief GCM context structure */ typedef struct { - aes_context aes_ctx; /*!< AES context used */ + cipher_context_t cipher_ctx;/*!< cipher context used */ uint64_t HL[16]; /*!< Precalculated HTable */ uint64_t HH[16]; /*!< Precalculated HTable */ uint64_t len; /*!< Total data length */ @@ -66,15 +66,17 @@ gcm_context; * \brief GCM initialization (encryption) * * \param ctx GCM context to be initialized + * \param cipher cipher to use (a 128-bit block cipher) * \param key encryption key * \param keysize must be 128, 192 or 256 * - * \return 0 if successful, or POLARSSL_ERR_AES_INVALID_KEY_LENGTH + * \return 0 if successful, or a cipher specific error code */ -int gcm_init( gcm_context *ctx, const unsigned char *key, unsigned int keysize ); +int gcm_init( gcm_context *ctx, cipher_id_t cipher, const unsigned char *key, + unsigned int keysize ); /** - * \brief GCM buffer encryption/decryption using AES + * \brief GCM buffer encryption/decryption using a block cipher * * \note On encryption, the output buffer can be the same as the input buffer. * On decryption, the output buffer cannot be the same as input buffer. @@ -108,7 +110,7 @@ int gcm_crypt_and_tag( gcm_context *ctx, unsigned char *tag ); /** - * \brief GCM buffer authenticated decryption using AES + * \brief GCM buffer authenticated decryption using a block cipher * * \note On decryption, the output buffer cannot be the same as input buffer. * If buffers overlap, the output buffer must trail at least 8 bytes diff --git a/library/cipher_wrap.c b/library/cipher_wrap.c index 253fcdce1..862328f69 100644 --- a/library/cipher_wrap.c +++ b/library/cipher_wrap.c @@ -298,9 +298,10 @@ 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 ) +static int gcm_aes_setkey_wrap( void *ctx, const unsigned char *key, unsigned int key_length ) { - return gcm_init( (gcm_context *) ctx, key, key_length ); + return gcm_init( (gcm_context *) ctx, POLARSSL_CIPHER_ID_AES, + key, key_length ); } const cipher_base_t gcm_aes_info = { @@ -310,8 +311,8 @@ const cipher_base_t gcm_aes_info = { NULL, NULL, NULL, - gcm_setkey_wrap, - gcm_setkey_wrap, + gcm_aes_setkey_wrap, + gcm_aes_setkey_wrap, gcm_ctx_alloc, gcm_ctx_free, }; diff --git a/library/gcm.c b/library/gcm.c index 99036a05c..e041647d3 100644 --- a/library/gcm.c +++ b/library/gcm.c @@ -54,15 +54,17 @@ } #endif -static void gcm_gen_table( gcm_context *ctx ) +static int gcm_gen_table( gcm_context *ctx ) { - int i, j; + int ret, i, j; uint64_t hi, lo; uint64_t vl, vh; unsigned char h[16]; + size_t olen = 0; memset( h, 0, 16 ); - aes_crypt_ecb( &ctx->aes_ctx, AES_ENCRYPT, h, h ); + if( ( ret = cipher_update( &ctx->cipher_ctx, h, 16, h, &olen ) ) != 0 ) + return( ret ); ctx->HH[0] = 0; ctx->HL[0] = 0; @@ -99,18 +101,33 @@ static void gcm_gen_table( gcm_context *ctx ) HiL[j] = vl ^ ctx->HL[j]; } } + + return( 0 ); } -int gcm_init( gcm_context *ctx, const unsigned char *key, unsigned int keysize ) +int gcm_init( gcm_context *ctx, cipher_id_t cipher, const unsigned char *key, + unsigned int keysize ) { int ret; + const cipher_info_t *cipher_info; memset( ctx, 0, sizeof(gcm_context) ); - if( ( ret = aes_setkey_enc( &ctx->aes_ctx, key, keysize ) ) != 0 ) + cipher_info = cipher_info_from_values( cipher, keysize, POLARSSL_MODE_ECB ); + if( cipher_info == NULL ) + return( POLARSSL_ERR_GCM_BAD_INPUT ); + + if( ( ret = cipher_init_ctx( &ctx->cipher_ctx, cipher_info ) ) != 0 ) return( ret ); - gcm_gen_table( ctx ); + if( ( ret = cipher_setkey( &ctx->cipher_ctx, key, keysize, + POLARSSL_ENCRYPT ) ) != 0 ) + { + return( ret ); + } + + if( ( ret = gcm_gen_table( ctx ) ) != 0 ) + return( ret ); return( 0 ); } @@ -176,10 +193,11 @@ int gcm_starts( gcm_context *ctx, const unsigned char *add, size_t add_len ) { + int ret; unsigned char work_buf[16]; size_t i; const unsigned char *p; - size_t use_len; + size_t use_len, olen = 0; memset( ctx->y, 0x00, sizeof(ctx->y) ); memset( ctx->buf, 0x00, sizeof(ctx->buf) ); @@ -218,7 +236,11 @@ int gcm_starts( gcm_context *ctx, gcm_mult( ctx, ctx->y, ctx->y ); } - aes_crypt_ecb( &ctx->aes_ctx, AES_ENCRYPT, ctx->y, ctx->base_ectr ); + if( ( ret = cipher_update( &ctx->cipher_ctx, ctx->y, 16, ctx->base_ectr, + &olen ) ) != 0 ) + { + return( ret ); + } ctx->add_len = add_len; p = add; @@ -243,11 +265,12 @@ int gcm_update( gcm_context *ctx, const unsigned char *input, unsigned char *output ) { + int ret; unsigned char ectr[16]; size_t i; const unsigned char *p; unsigned char *out_p = output; - size_t use_len; + size_t use_len, olen = 0; if( output > input && (size_t) ( output - input ) < length ) return( POLARSSL_ERR_GCM_BAD_INPUT ); @@ -263,7 +286,11 @@ int gcm_update( gcm_context *ctx, if( ++ctx->y[i - 1] != 0 ) break; - aes_crypt_ecb( &ctx->aes_ctx, AES_ENCRYPT, ctx->y, ectr ); + if( ( ret = cipher_update( &ctx->cipher_ctx, ctx->y, 16, ectr, + &olen ) ) != 0 ) + { + return( ret ); + } for( i = 0; i < use_len; i++ ) { @@ -613,6 +640,7 @@ int gcm_self_test( int verbose ) unsigned char buf[64]; unsigned char tag_buf[16]; int i, j, ret; + cipher_id_t cipher = POLARSSL_CIPHER_ID_AES; for( j = 0; j < 3; j++ ) { @@ -623,7 +651,7 @@ int gcm_self_test( int verbose ) if( verbose != 0 ) printf( " AES-GCM-%3d #%d (%s): ", key_len, i, "enc" ); - gcm_init( &ctx, key[key_index[i]], key_len ); + gcm_init( &ctx, cipher, key[key_index[i]], key_len ); ret = gcm_crypt_and_tag( &ctx, GCM_ENCRYPT, pt_len[i], @@ -647,7 +675,7 @@ int gcm_self_test( int verbose ) if( verbose != 0 ) printf( " AES-GCM-%3d #%d (%s): ", key_len, i, "dec" ); - gcm_init( &ctx, key[key_index[i]], key_len ); + gcm_init( &ctx, cipher, key[key_index[i]], key_len ); ret = gcm_crypt_and_tag( &ctx, GCM_DECRYPT, pt_len[i], @@ -671,7 +699,7 @@ int gcm_self_test( int verbose ) if( verbose != 0 ) printf( " AES-GCM-%3d #%d split (%s): ", key_len, i, "enc" ); - gcm_init( &ctx, key[key_index[i]], key_len ); + gcm_init( &ctx, cipher, key[key_index[i]], key_len ); ret = gcm_starts( &ctx, GCM_ENCRYPT, iv[iv_index[i]], iv_len[i], @@ -734,7 +762,7 @@ int gcm_self_test( int verbose ) if( verbose != 0 ) printf( " AES-GCM-%3d #%d split (%s): ", key_len, i, "dec" ); - gcm_init( &ctx, key[key_index[i]], key_len ); + gcm_init( &ctx, cipher, key[key_index[i]], key_len ); ret = gcm_starts( &ctx, GCM_DECRYPT, iv[iv_index[i]], iv_len[i], diff --git a/tests/suites/test_suite_gcm.function b/tests/suites/test_suite_gcm.function index 2b870d1e3..c9cc1774e 100644 --- a/tests/suites/test_suite_gcm.function +++ b/tests/suites/test_suite_gcm.function @@ -39,7 +39,7 @@ void gcm_encrypt_and_tag( char *hex_key_string, char *hex_src_string, iv_len = unhexify( iv_str, hex_iv_string ); add_len = unhexify( add_str, hex_add_string ); - TEST_ASSERT( gcm_init( &ctx, key_str, key_len * 8 ) == init_result ); + TEST_ASSERT( gcm_init( &ctx, POLARSSL_CIPHER_ID_AES, key_str, key_len * 8 ) == init_result ); if( init_result == 0 ) { TEST_ASSERT( gcm_crypt_and_tag( &ctx, GCM_ENCRYPT, pt_len, iv_str, iv_len, add_str, add_len, src_str, output, tag_len, tag_output ) == 0 ); @@ -84,7 +84,7 @@ void gcm_decrypt_and_verify( char *hex_key_string, char *hex_src_string, add_len = unhexify( add_str, hex_add_string ); unhexify( tag_str, hex_tag_string ); - TEST_ASSERT( gcm_init( &ctx, key_str, key_len * 8 ) == init_result ); + TEST_ASSERT( gcm_init( &ctx, POLARSSL_CIPHER_ID_AES, key_str, key_len * 8 ) == init_result ); if( init_result == 0 ) { ret = gcm_auth_decrypt( &ctx, pt_len, iv_str, iv_len, add_str, add_len, tag_str, tag_len, src_str, output );