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 ) );