diff --git a/ChangeLog.d/bugfix-2927.txt b/ChangeLog.d/bugfix-2927.txt new file mode 100644 index 0000000000..2213c6ee45 --- /dev/null +++ b/ChangeLog.d/bugfix-2927.txt @@ -0,0 +1,3 @@ +Bugfix + * In CTR_DRBG and HMAC_DRBG, don't reset the reseed interval in seed(). + Fixes #2927. diff --git a/include/mbedtls/ctr_drbg.h b/include/mbedtls/ctr_drbg.h index 6c48ec1edd..7f1d23253c 100644 --- a/include/mbedtls/ctr_drbg.h +++ b/include/mbedtls/ctr_drbg.h @@ -210,6 +210,11 @@ mbedtls_ctr_drbg_context; * and prepares it for mbedtls_ctr_drbg_seed() * or mbedtls_ctr_drbg_free(). * + * \note The reseed interval is + * #MBEDTLS_CTR_DRBG_RESEED_INTERVAL by default. + * You can override it by calling + * mbedtls_ctr_drbg_set_reseed_interval(). + * * \param ctx The CTR_DRBG context to initialize. */ void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context *ctx ); @@ -309,7 +314,8 @@ int mbedtls_ctr_drbg_seed( mbedtls_ctr_drbg_context *ctx, size_t len ); /** - * \brief This function clears CTR_CRBG context data. + * \brief This function resets CTR_DRBG context to the state immediately + * after initial call of mbedtls_ctr_drbg_init(). * * \param ctx The CTR_DRBG context to clear. */ diff --git a/include/mbedtls/hmac_drbg.h b/include/mbedtls/hmac_drbg.h index 57ce9d98f4..91165415fb 100644 --- a/include/mbedtls/hmac_drbg.h +++ b/include/mbedtls/hmac_drbg.h @@ -111,6 +111,10 @@ typedef struct mbedtls_hmac_drbg_context * This function makes the context ready for mbedtls_hmac_drbg_seed(), * mbedtls_hmac_drbg_seed_buf() or mbedtls_hmac_drbg_free(). * + * \note The reseed interval is #MBEDTLS_HMAC_DRBG_RESEED_INTERVAL + * by default. Override this value by calling + * mbedtls_hmac_drbg_set_reseed_interval(). + * * \param ctx HMAC_DRBG context to be initialized. */ void mbedtls_hmac_drbg_init( mbedtls_hmac_drbg_context *ctx ); @@ -334,7 +338,8 @@ int mbedtls_hmac_drbg_random_with_add( void *p_rng, int mbedtls_hmac_drbg_random( void *p_rng, unsigned char *output, size_t out_len ); /** - * \brief Free an HMAC_DRBG context + * \brief This function resets HMAC_DRBG context to the state immediately + * after initial call of mbedtls_hmac_drbg_init(). * * \param ctx The HMAC_DRBG context to free. */ diff --git a/library/ctr_drbg.c b/library/ctr_drbg.c index 54843a7be6..023aac51a3 100644 --- a/library/ctr_drbg.c +++ b/library/ctr_drbg.c @@ -55,11 +55,17 @@ void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context *ctx ) * See mbedtls_ctr_drbg_set_nonce_len(). */ ctx->reseed_counter = -1; + ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL; + #if defined(MBEDTLS_THREADING_C) mbedtls_mutex_init( &ctx->mutex ); #endif } +/* + * This function resets CTR_DRBG context to the state immediately + * after initial call of mbedtls_ctr_drbg_init(). + */ void mbedtls_ctr_drbg_free( mbedtls_ctr_drbg_context *ctx ) { if( ctx == NULL ) @@ -70,6 +76,11 @@ void mbedtls_ctr_drbg_free( mbedtls_ctr_drbg_context *ctx ) #endif mbedtls_aes_free( &ctx->aes_ctx ); mbedtls_platform_zeroize( ctx, sizeof( mbedtls_ctr_drbg_context ) ); + ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL; + ctx->reseed_counter = -1; +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_init( &ctx->mutex ); +#endif } void mbedtls_ctr_drbg_set_prediction_resistance( mbedtls_ctr_drbg_context *ctx, @@ -468,8 +479,6 @@ int mbedtls_ctr_drbg_seed( mbedtls_ctr_drbg_context *ctx, (size_t) ctx->reseed_counter : good_nonce_len( ctx->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 ) diff --git a/library/hmac_drbg.c b/library/hmac_drbg.c index aa3e251040..25a0225835 100644 --- a/library/hmac_drbg.c +++ b/library/hmac_drbg.c @@ -53,6 +53,8 @@ void mbedtls_hmac_drbg_init( mbedtls_hmac_drbg_context *ctx ) { memset( ctx, 0, sizeof( mbedtls_hmac_drbg_context ) ); + ctx->reseed_interval = MBEDTLS_HMAC_DRBG_RESEED_INTERVAL; + #if defined(MBEDTLS_THREADING_C) mbedtls_mutex_init( &ctx->mutex ); #endif @@ -266,8 +268,6 @@ int mbedtls_hmac_drbg_seed( mbedtls_hmac_drbg_context *ctx, ctx->f_entropy = f_entropy; ctx->p_entropy = p_entropy; - ctx->reseed_interval = MBEDTLS_HMAC_DRBG_RESEED_INTERVAL; - if( ctx->entropy_len == 0 ) { /* @@ -412,7 +412,8 @@ int mbedtls_hmac_drbg_random( void *p_rng, unsigned char *output, size_t out_len } /* - * Free an HMAC_DRBG context + * This function resets HMAC_DRBG context to the state immediately + * after initial call of mbedtls_hmac_drbg_init(). */ void mbedtls_hmac_drbg_free( mbedtls_hmac_drbg_context *ctx ) { @@ -424,6 +425,10 @@ void mbedtls_hmac_drbg_free( mbedtls_hmac_drbg_context *ctx ) #endif mbedtls_md_free( &ctx->md_ctx ); mbedtls_platform_zeroize( ctx, sizeof( mbedtls_hmac_drbg_context ) ); + ctx->reseed_interval = MBEDTLS_HMAC_DRBG_RESEED_INTERVAL; +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_init( &ctx->mutex ); +#endif } #if defined(MBEDTLS_FS_IO) diff --git a/tests/suites/test_suite_ctr_drbg.function b/tests/suites/test_suite_ctr_drbg.function index 5e4cd26b60..c3ffe3b47b 100644 --- a/tests/suites/test_suite_ctr_drbg.function +++ b/tests/suites/test_suite_ctr_drbg.function @@ -240,6 +240,9 @@ void ctr_drbg_entropy_usage( int entropy_nonce_len ) if( entropy_nonce_len >= 0 ) TEST_ASSERT( mbedtls_ctr_drbg_set_nonce_len( &ctx, entropy_nonce_len ) == 0 ); + /* Set reseed interval before seed */ + mbedtls_ctr_drbg_set_reseed_interval( &ctx, 2 * reps ); + /* Init must use entropy */ TEST_ASSERT( mbedtls_ctr_drbg_seed( &ctx, mbedtls_test_entropy_func, entropy, NULL, 0 ) == 0 ); expected_idx += MBEDTLS_CTR_DRBG_ENTROPY_LEN; @@ -249,8 +252,8 @@ void ctr_drbg_entropy_usage( int entropy_nonce_len ) expected_idx += MBEDTLS_CTR_DRBG_ENTROPY_NONCE_LEN; TEST_EQUAL( test_offset_idx, expected_idx ); - /* By default, PR is off and reseed_interval is large, - * so the next few calls should not use entropy */ + /* By default, PR is off, and reseed interval was set to + * 2 * reps so the next few calls should not use entropy */ for( i = 0; i < reps; i++ ) { TEST_ASSERT( mbedtls_ctr_drbg_random( &ctx, out, sizeof( out ) - 4 ) == 0 ); @@ -265,15 +268,16 @@ void ctr_drbg_entropy_usage( int entropy_nonce_len ) TEST_ASSERT( out[sizeof( out ) - 2] == 0 ); TEST_ASSERT( out[sizeof( out ) - 1] == 0 ); - /* Set reseed_interval to the number of calls done, - * so the next call should reseed */ - mbedtls_ctr_drbg_set_reseed_interval( &ctx, 2 * reps ); + /* There have been 2 * reps calls to random. The next call should reseed */ TEST_ASSERT( mbedtls_ctr_drbg_random( &ctx, out, sizeof( out ) ) == 0 ); expected_idx += MBEDTLS_CTR_DRBG_ENTROPY_LEN; TEST_EQUAL( test_offset_idx, expected_idx ); - /* The new few calls should not reseed */ - for( i = 0; i < reps / 2; i++ ) + /* Set reseed interval after seed */ + mbedtls_ctr_drbg_set_reseed_interval( &ctx, 4 * reps + 1 ); + + /* The next few calls should not reseed */ + for( i = 0; i < (2 * reps); i++ ) { TEST_ASSERT( mbedtls_ctr_drbg_random( &ctx, out, sizeof( out ) ) == 0 ); TEST_ASSERT( mbedtls_ctr_drbg_random_with_add( &ctx, out, sizeof( out ) , diff --git a/tests/suites/test_suite_hmac_drbg.function b/tests/suites/test_suite_hmac_drbg.function index 512eeb89ca..b83d760d22 100644 --- a/tests/suites/test_suite_hmac_drbg.function +++ b/tests/suites/test_suite_hmac_drbg.function @@ -57,6 +57,9 @@ void hmac_drbg_entropy_usage( int md_alg ) else default_entropy_len = 32; + /* Set reseed interval before seed */ + mbedtls_hmac_drbg_set_reseed_interval( &ctx, 2 * reps ); + /* Init must use entropy */ TEST_ASSERT( mbedtls_hmac_drbg_seed( &ctx, md_info, mbedtls_test_entropy_func, &entropy, NULL, 0 ) == 0 ); @@ -64,8 +67,8 @@ void hmac_drbg_entropy_usage( int md_alg ) expected_consumed_entropy += default_entropy_len * 3 / 2; TEST_EQUAL( sizeof( buf ) - entropy.len, expected_consumed_entropy ); - /* By default, PR is off and reseed_interval is large, - * so the next few calls should not use entropy */ + /* By default, PR is off, and reseed interval was set to + * 2 * reps so the next few calls should not use entropy */ for( i = 0; i < reps; i++ ) { TEST_ASSERT( mbedtls_hmac_drbg_random( &ctx, out, sizeof( out ) - 4 ) == 0 ); @@ -80,15 +83,16 @@ void hmac_drbg_entropy_usage( int md_alg ) TEST_ASSERT( out[sizeof( out ) - 2] == 0 ); TEST_ASSERT( out[sizeof( out ) - 1] == 0 ); - /* Set reseed_interval to the number of calls done, - * so the next call should reseed */ - mbedtls_hmac_drbg_set_reseed_interval( &ctx, 2 * reps ); + /* There have been 2 * reps calls to random. The next call should reseed */ TEST_ASSERT( mbedtls_hmac_drbg_random( &ctx, out, sizeof( out ) ) == 0 ); expected_consumed_entropy += default_entropy_len; TEST_EQUAL( sizeof( buf ) - entropy.len, expected_consumed_entropy ); + /* Set reseed interval after seed */ + mbedtls_hmac_drbg_set_reseed_interval( &ctx, 4 * reps + 1); + /* The new few calls should not reseed */ - for( i = 0; i < reps / 2; i++ ) + for( i = 0; i < (2 * reps); i++ ) { TEST_ASSERT( mbedtls_hmac_drbg_random( &ctx, out, sizeof( out ) ) == 0 ); TEST_ASSERT( mbedtls_hmac_drbg_random_with_add( &ctx, out, sizeof( out ) , @@ -199,7 +203,7 @@ void hmac_drbg_no_reseed( int md_alg, data_t * entropy, TEST_ASSERT( mbedtls_hmac_drbg_random_with_add( &ctx, my_output, output->len, add2->x, add2->len ) == 0 ); - /* clear for second run */ + /* Reset context for second run */ mbedtls_hmac_drbg_free( &ctx ); TEST_ASSERT( memcmp( my_output, output->x, output->len ) == 0 );