diff --git a/ChangeLog b/ChangeLog index 16982a0e0..47f639748 100644 --- a/ChangeLog +++ b/ChangeLog @@ -2,6 +2,12 @@ mbed TLS ChangeLog (Sorted per branch, date) = mbed TLS 2.7.x branch released xxxx-xx-xx +Bugfix + * Support mbedtls_hmac_drbg_set_entropy_len() and + mbedtls_ctr_drbg_set_entropy_len() before the DRBG is seeded. Before, + the initial seeding always reset the entropy length to the compile-time + default. + Changes * Add unit tests for AES-GCM when called through mbedtls_cipher_auth_xxx() from the cipher abstraction layer. Fixes #2198. diff --git a/include/mbedtls/ctr_drbg.h b/include/mbedtls/ctr_drbg.h index 8963c7423..340886264 100644 --- a/include/mbedtls/ctr_drbg.h +++ b/include/mbedtls/ctr_drbg.h @@ -190,11 +190,8 @@ void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context *ctx ); * with mbedtls_entropy_init() (which registers the platform's default * entropy sources). * - * \p f_entropy is always called with a buffer size equal to the entropy - * length. The entropy length is initially #MBEDTLS_CTR_DRBG_ENTROPY_LEN - * and this value is always used for the initial seeding. You can change - * the entropy length for subsequent seeding by calling - * mbedtls_ctr_drbg_set_entropy_len() after this function. + * The entropy length is #MBEDTLS_CTR_DRBG_ENTROPY_LEN by default. + * You can override it by calling mbedtls_ctr_drbg_set_entropy_len(). * * You can provide a personalization string in addition to the * entropy source, to make this instantiation as unique as possible. @@ -227,9 +224,18 @@ void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context *ctx ); #endif /** * \param ctx The CTR_DRBG context to seed. + * It must have been initialized with + * mbedtls_ctr_drbg_init(). + * After a successful call to mbedtls_ctr_drbg_seed(), + * you may not call mbedtls_ctr_drbg_seed() again on + * the same context unless you call + * mbedtls_ctr_drbg_free() and mbedtls_ctr_drbg_init() + * again first. * \param f_entropy The entropy callback, taking as arguments the * \p p_entropy context, the buffer to fill, and the * length of the buffer. + * \p f_entropy is always called with a buffer size + * equal to the entropy length. * \param p_entropy The entropy context to pass to \p f_entropy. * \param custom The personalization string. * This can be \c NULL, in which case the personalization @@ -273,15 +279,10 @@ void mbedtls_ctr_drbg_set_prediction_resistance( mbedtls_ctr_drbg_context *ctx, /** * \brief This function sets the amount of entropy grabbed on each - * subsequent reseed. + * seed or reseed. * * The default value is #MBEDTLS_CTR_DRBG_ENTROPY_LEN. * - * \note mbedtls_ctr_drbg_seed() always sets the entropy length - * to #MBEDTLS_CTR_DRBG_ENTROPY_LEN, so this function - * only has an effect when it is called after - * mbedtls_ctr_drbg_seed(). - * * \note The security strength of CTR_DRBG is bounded by the * entropy length. Thus \p len must be at least * 32 (in bytes) to achieve a 256-bit strength. diff --git a/include/mbedtls/hmac_drbg.h b/include/mbedtls/hmac_drbg.h index a46b28726..2e4e23bc0 100644 --- a/include/mbedtls/hmac_drbg.h +++ b/include/mbedtls/hmac_drbg.h @@ -139,13 +139,11 @@ void mbedtls_hmac_drbg_init( mbedtls_hmac_drbg_context *ctx ); * Note that SHA-256 is just as efficient as SHA-224. * The security strength can be reduced if a smaller * entropy length is set with - * mbedtls_hmac_drbg_set_entropy_len() afterwards. + * mbedtls_hmac_drbg_set_entropy_len(). * - * \note The entropy length for the initial seeding is - * the security strength (converted from bits to bytes). - * You can set a different entropy length for subsequent - * seeding by calling mbedtls_hmac_drbg_set_entropy_len() - * after this function. + * \note The default entropy length is the security strength + * (converted from bits to bytes). You can override + * it by calling mbedtls_hmac_drbg_set_entropy_len(). * * \note During the initial seeding, this function calls * the entropy source to obtain a nonce @@ -224,14 +222,9 @@ void mbedtls_hmac_drbg_set_prediction_resistance( mbedtls_hmac_drbg_context *ctx /** * \brief This function sets the amount of entropy grabbed on each - * reseed. + * seed or reseed. * - * The default value is set by mbedtls_hmac_drbg_seed(). - * - * \note mbedtls_hmac_drbg_seed() always sets the entropy length - * to the default value based on the chosen MD algorithm, - * so this function only has an effect if it is called - * after mbedtls_hmac_drbg_seed(). + * See the documentation of mbedtls_hmac_drbg_seed() for the default value. * * \param ctx The HMAC_DRBG context. * \param len The amount of entropy to grab, in bytes. diff --git a/library/ctr_drbg.c b/library/ctr_drbg.c index d7a94840c..c318e6afe 100644 --- a/library/ctr_drbg.c +++ b/library/ctr_drbg.c @@ -66,56 +66,6 @@ void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context *ctx ) #endif } -/* - * Non-public function wrapped by mbedtls_ctr_drbg_seed(). Necessary to allow - * NIST tests to succeed (which require known length fixed entropy) - */ -int mbedtls_ctr_drbg_seed_entropy_len( - mbedtls_ctr_drbg_context *ctx, - int (*f_entropy)(void *, unsigned char *, size_t), - void *p_entropy, - const unsigned char *custom, - size_t len, - size_t entropy_len ) -{ - int ret; - unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE]; - - memset( key, 0, MBEDTLS_CTR_DRBG_KEYSIZE ); - - mbedtls_aes_init( &ctx->aes_ctx ); - - ctx->f_entropy = f_entropy; - ctx->p_entropy = p_entropy; - - ctx->entropy_len = entropy_len; - ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL; - - /* - * Initialize with an empty key - */ - if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, key, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 ) - { - return( ret ); - } - - if( ( ret = mbedtls_ctr_drbg_reseed( ctx, custom, len ) ) != 0 ) - { - return( ret ); - } - return( 0 ); -} - -int mbedtls_ctr_drbg_seed( mbedtls_ctr_drbg_context *ctx, - int (*f_entropy)(void *, unsigned char *, size_t), - void *p_entropy, - const unsigned char *custom, - size_t len ) -{ - return( mbedtls_ctr_drbg_seed_entropy_len( ctx, f_entropy, p_entropy, custom, len, - MBEDTLS_CTR_DRBG_ENTROPY_LEN ) ); -} - void mbedtls_ctr_drbg_free( mbedtls_ctr_drbg_context *ctx ) { if( ctx == NULL ) @@ -386,6 +336,52 @@ exit: return( ret ); } +int mbedtls_ctr_drbg_seed( mbedtls_ctr_drbg_context *ctx, + int (*f_entropy)(void *, unsigned char *, size_t), + void *p_entropy, + const unsigned char *custom, + size_t len ) +{ + int ret; + unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE]; + + memset( key, 0, MBEDTLS_CTR_DRBG_KEYSIZE ); + + mbedtls_aes_init( &ctx->aes_ctx ); + + ctx->f_entropy = f_entropy; + ctx->p_entropy = p_entropy; + + if( ctx->entropy_len == 0 ) + ctx->entropy_len = MBEDTLS_CTR_DRBG_ENTROPY_LEN; + ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL; + + /* + * Initialize with an empty key + */ + if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, key, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 ) + { + return( ret ); + } + + if( ( ret = mbedtls_ctr_drbg_reseed( ctx, custom, len ) ) != 0 ) + { + return( ret ); + } + return( 0 ); +} + +/* Backward compatibility wrapper */ +int mbedtls_ctr_drbg_seed_entropy_len( + mbedtls_ctr_drbg_context *ctx, + int (*f_entropy)(void *, unsigned char *, size_t), void *p_entropy, + const unsigned char *custom, size_t len, + size_t entropy_len ) +{ + mbedtls_ctr_drbg_set_entropy_len( ctx, entropy_len ); + return( mbedtls_ctr_drbg_seed( ctx, f_entropy, p_entropy, custom, len ) ); +} + int mbedtls_ctr_drbg_random_with_add( void *p_rng, unsigned char *output, size_t output_len, const unsigned char *additional, size_t add_len ) @@ -617,8 +613,11 @@ int mbedtls_ctr_drbg_self_test( int verbose ) mbedtls_printf( " CTR_DRBG (PR = TRUE) : " ); test_offset = 0; - CHK( mbedtls_ctr_drbg_seed_entropy_len( &ctx, ctr_drbg_self_test_entropy, - (void *) entropy_source_pr, nonce_pers_pr, 16, 32 ) ); + mbedtls_ctr_drbg_set_entropy_len( &ctx, 32 ); + CHK( mbedtls_ctr_drbg_seed( &ctx, + ctr_drbg_self_test_entropy, + (void *) entropy_source_pr, + nonce_pers_pr, 16 ) ); mbedtls_ctr_drbg_set_prediction_resistance( &ctx, MBEDTLS_CTR_DRBG_PR_ON ); CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) ); CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) ); @@ -638,8 +637,11 @@ int mbedtls_ctr_drbg_self_test( int verbose ) mbedtls_ctr_drbg_init( &ctx ); test_offset = 0; - CHK( mbedtls_ctr_drbg_seed_entropy_len( &ctx, ctr_drbg_self_test_entropy, - (void *) entropy_source_nopr, nonce_pers_nopr, 16, 32 ) ); + mbedtls_ctr_drbg_set_entropy_len( &ctx, 32 ); + CHK( mbedtls_ctr_drbg_seed( &ctx, + ctr_drbg_self_test_entropy, + (void *) entropy_source_nopr, + nonce_pers_nopr, 16 ) ); CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) ); CHK( mbedtls_ctr_drbg_reseed( &ctx, NULL, 0 ) ); CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) ); diff --git a/library/hmac_drbg.c b/library/hmac_drbg.c index 886f44a80..346c26321 100644 --- a/library/hmac_drbg.c +++ b/library/hmac_drbg.c @@ -275,16 +275,19 @@ int mbedtls_hmac_drbg_seed( mbedtls_hmac_drbg_context *ctx, ctx->reseed_interval = MBEDTLS_HMAC_DRBG_RESEED_INTERVAL; - /* - * See SP800-57 5.6.1 (p. 65-66) for the security strength provided by - * each hash function, then according to SP800-90A rev1 10.1 table 2, - * min_entropy_len (in bits) is security_strength. - * - * (This also matches the sizes used in the NIST test vectors.) - */ - ctx->entropy_len = md_size <= 20 ? 16 : /* 160-bits hash -> 128 bits */ - md_size <= 28 ? 24 : /* 224-bits hash -> 192 bits */ - 32; /* better (256+) -> 256 bits */ + if( ctx->entropy_len == 0 ) + { + /* + * See SP800-57 5.6.1 (p. 65-66) for the security strength provided by + * each hash function, then according to SP800-90A rev1 10.1 table 2, + * min_entropy_len (in bits) is security_strength. + * + * (This also matches the sizes used in the NIST test vectors.) + */ + ctx->entropy_len = md_size <= 20 ? 16 : /* 160-bits hash -> 128 bits */ + md_size <= 28 ? 24 : /* 224-bits hash -> 192 bits */ + 32; /* better (256+) -> 256 bits */ + } if( ( ret = hmac_drbg_reseed_core( ctx, custom, len, 1 /* add nonce */ ) ) != 0 ) @@ -305,7 +308,7 @@ void mbedtls_hmac_drbg_set_prediction_resistance( mbedtls_hmac_drbg_context *ctx } /* - * Set entropy length grabbed for reseeds + * Set entropy length grabbed for seeding */ void mbedtls_hmac_drbg_set_entropy_len( mbedtls_hmac_drbg_context *ctx, size_t len ) { diff --git a/programs/test/benchmark.c b/programs/test/benchmark.c index 20e3c2e39..a63a30ec8 100644 --- a/programs/test/benchmark.c +++ b/programs/test/benchmark.c @@ -560,13 +560,14 @@ int main( int argc, char *argv[] ) mbedtls_ctr_drbg_context ctr_drbg; mbedtls_ctr_drbg_init( &ctr_drbg ); - if( mbedtls_ctr_drbg_seed( &ctr_drbg, myrand, NULL, NULL, 0 ) != 0 ) mbedtls_exit(1); TIME_AND_TSC( "CTR_DRBG (NOPR)", if( mbedtls_ctr_drbg_random( &ctr_drbg, buf, BUFSIZE ) != 0 ) mbedtls_exit(1) ); + mbedtls_ctr_drbg_free( &ctr_drbg ); + mbedtls_ctr_drbg_init( &ctr_drbg ); if( mbedtls_ctr_drbg_seed( &ctr_drbg, myrand, NULL, NULL, 0 ) != 0 ) mbedtls_exit(1); mbedtls_ctr_drbg_set_prediction_resistance( &ctr_drbg, MBEDTLS_CTR_DRBG_PR_ON ); diff --git a/tests/suites/test_suite_ctr_drbg.function b/tests/suites/test_suite_ctr_drbg.function index f17bd3be0..134ba9c85 100644 --- a/tests/suites/test_suite_ctr_drbg.function +++ b/tests/suites/test_suite_ctr_drbg.function @@ -72,7 +72,10 @@ void ctr_drbg_validate_pr( char *add_init_string, char *entropy_string, add2_len = unhexify( add2, add2_string ); test_offset_idx = 0; - TEST_ASSERT( mbedtls_ctr_drbg_seed_entropy_len( &ctx, mbedtls_test_entropy_func, entropy, add_init, add_init_len, 32 ) == 0 ); + mbedtls_ctr_drbg_set_entropy_len( &ctx, 32 ); + TEST_ASSERT( mbedtls_ctr_drbg_seed( &ctx, + mbedtls_test_entropy_func, entropy, + add_init, add_init_len ) == 0 ); mbedtls_ctr_drbg_set_prediction_resistance( &ctx, MBEDTLS_CTR_DRBG_PR_ON ); TEST_ASSERT( mbedtls_ctr_drbg_random_with_add( &ctx, buf, 16, add1, add1_len ) == 0 ); @@ -110,7 +113,10 @@ void ctr_drbg_validate_nopr( char *add_init_string, char *entropy_string, add2_len = unhexify( add2, add2_string ); test_offset_idx = 0; - TEST_ASSERT( mbedtls_ctr_drbg_seed_entropy_len( &ctx, mbedtls_test_entropy_func, entropy, add_init, add_init_len, 32 ) == 0 ); + mbedtls_ctr_drbg_set_entropy_len( &ctx, 32 ); + TEST_ASSERT( mbedtls_ctr_drbg_seed( &ctx, + mbedtls_test_entropy_func, entropy, + add_init, add_init_len ) == 0 ); TEST_ASSERT( mbedtls_ctr_drbg_random_with_add( &ctx, buf, 16, add1, add1_len ) == 0 ); TEST_ASSERT( mbedtls_ctr_drbg_reseed( &ctx, add_reseed, add_reseed_len ) == 0 );