From 912ffe414e62a13f1b1cb25d3e051b776e459fa5 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Fri, 4 Oct 2019 12:15:55 +0200 Subject: [PATCH] CTR_DRBG: support set_entropy_len() before seed() mbedtls_ctr_drbg_seed() always set the entropy length to the default, so a call to mbedtls_ctr_drbg_set_entropy_len() before seed() had no effect. Change this to the more intuitive behavior that set_entropy_len() sets the entropy length and seed() respects that and only uses the default entropy length if there was no call to set_entropy_len(). The former test-only function mbedtls_ctr_drbg_seed_entropy_len() is no longer used, but keep it for strict ABI compatibility. --- include/mbedtls/ctr_drbg.h | 16 +++---- library/ctr_drbg.c | 53 ++++++++++++----------- tests/suites/test_suite_ctr_drbg.function | 6 +-- 3 files changed, 35 insertions(+), 40 deletions(-) diff --git a/include/mbedtls/ctr_drbg.h b/include/mbedtls/ctr_drbg.h index 766e64701..c14507ff6 100644 --- a/include/mbedtls/ctr_drbg.h +++ b/include/mbedtls/ctr_drbg.h @@ -214,11 +214,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. @@ -255,6 +252,8 @@ void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context *ctx ); * \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 @@ -298,15 +297,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: * - When using AES-256 diff --git a/library/ctr_drbg.c b/library/ctr_drbg.c index 80544dfb8..32b34e462 100644 --- a/library/ctr_drbg.c +++ b/library/ctr_drbg.c @@ -365,29 +365,22 @@ exit: return( ret ); } -/* - * Non-public function wrapped by mbedtls_ctr_drbg_seed(). Necessary to allow - * NIST tests to succeed (which require known length fixed entropy) - */ /* CTR_DRBG_Instantiate with derivation function (SP 800-90A §10.2.1.3.2) - * mbedtls_ctr_drbg_seed_entropy_len(ctx, f_entropy, p_entropy, - * custom, len, entropy_len) + * mbedtls_ctr_drbg_seed(ctx, f_entropy, p_entropy, custom, len) * implements * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string, * security_strength) -> initial_working_state * with inputs * custom[:len] = nonce || personalization_string - * where entropy_input comes from f_entropy for entropy_len bytes + * where entropy_input comes from f_entropy for ctx->entropy_len bytes * and with outputs * ctx = initial_working_state */ -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 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]; @@ -399,7 +392,8 @@ int mbedtls_ctr_drbg_seed_entropy_len( ctx->f_entropy = f_entropy; ctx->p_entropy = p_entropy; - ctx->entropy_len = entropy_len; + if( ctx->entropy_len == 0 ) + ctx->entropy_len = MBEDTLS_CTR_DRBG_ENTROPY_LEN; ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL; /* @@ -417,14 +411,15 @@ int mbedtls_ctr_drbg_seed_entropy_len( 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 ) +/* 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 ) { - return( mbedtls_ctr_drbg_seed_entropy_len( ctx, f_entropy, p_entropy, custom, len, - MBEDTLS_CTR_DRBG_ENTROPY_LEN ) ); + mbedtls_ctr_drbg_set_entropy_len( ctx, entropy_len ); + return( mbedtls_ctr_drbg_seed( ctx, f_entropy, p_entropy, custom, len ) ); } /* CTR_DRBG_Generate with derivation function (SP 800-90A §10.2.1.5.2) @@ -678,8 +673,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 ) ); @@ -699,8 +697,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/tests/suites/test_suite_ctr_drbg.function b/tests/suites/test_suite_ctr_drbg.function index 4a97826f6..01050d92d 100644 --- a/tests/suites/test_suite_ctr_drbg.function +++ b/tests/suites/test_suite_ctr_drbg.function @@ -44,11 +44,11 @@ static void ctr_drbg_validate_internal( int reseed_mode, data_t * nonce, /* CTR_DRBG_Instantiate(entropy[:entropy->len], nonce, perso, ) * where nonce||perso = nonce[nonce->len] */ - TEST_ASSERT( mbedtls_ctr_drbg_seed_entropy_len( + mbedtls_ctr_drbg_set_entropy_len( &ctx, entropy_chunk_len ); + TEST_ASSERT( mbedtls_ctr_drbg_seed( &ctx, mbedtls_test_entropy_func, entropy->x, - nonce->x, nonce->len, - entropy_chunk_len ) == 0 ); + nonce->x, nonce->len ) == 0 ); if( reseed_mode == RESEED_ALWAYS ) mbedtls_ctr_drbg_set_prediction_resistance( &ctx,