Merge pull request #2894 from gilles-peskine-arm/drbg-set_entropy_len-2.16

Backport 2.16: Allow xxx_drbg_set_entropy_len before xxx_drbg_seed
This commit is contained in:
Jaeden Amero 2019-11-29 16:17:34 +00:00 committed by GitHub
commit c0546439c4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 108 additions and 105 deletions

View File

@ -6,6 +6,10 @@ Bugfix
* Remove redundant line for getting the bitlen of a bignum, since the variable * Remove redundant line for getting the bitlen of a bignum, since the variable
holding the returned value is overwritten a line after. holding the returned value is overwritten a line after.
Found by irwir in #2377. Found by irwir in #2377.
* 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 Changes
* Add unit tests for AES-GCM when called through mbedtls_cipher_auth_xxx() * Add unit tests for AES-GCM when called through mbedtls_cipher_auth_xxx()

View File

@ -214,11 +214,8 @@ void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context *ctx );
* with mbedtls_entropy_init() (which registers the platform's default * with mbedtls_entropy_init() (which registers the platform's default
* entropy sources). * entropy sources).
* *
* \p f_entropy is always called with a buffer size equal to the entropy * The entropy length is #MBEDTLS_CTR_DRBG_ENTROPY_LEN by default.
* length. The entropy length is initially #MBEDTLS_CTR_DRBG_ENTROPY_LEN * You can override it by calling mbedtls_ctr_drbg_set_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.
* *
* You can provide a personalization string in addition to the * You can provide a personalization string in addition to the
* entropy source, to make this instantiation as unique as possible. * entropy source, to make this instantiation as unique as possible.
@ -252,9 +249,18 @@ void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context *ctx );
#endif #endif
/** /**
* \param ctx The CTR_DRBG context to seed. * \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 * \param f_entropy The entropy callback, taking as arguments the
* \p p_entropy context, the buffer to fill, and the * \p p_entropy context, the buffer to fill, and the
* length of the buffer. * 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 p_entropy The entropy context to pass to \p f_entropy.
* \param custom The personalization string. * \param custom The personalization string.
* This can be \c NULL, in which case the personalization * This can be \c NULL, in which case the personalization
@ -298,15 +304,10 @@ void mbedtls_ctr_drbg_set_prediction_resistance( mbedtls_ctr_drbg_context *ctx,
/** /**
* \brief This function sets the amount of entropy grabbed on each * \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. * 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 * \note The security strength of CTR_DRBG is bounded by the
* entropy length. Thus: * entropy length. Thus:
* - When using AES-256 * - When using AES-256

View File

@ -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. * Note that SHA-256 is just as efficient as SHA-224.
* The security strength can be reduced if a smaller * The security strength can be reduced if a smaller
* entropy length is set with * 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 * \note The default entropy length is the security strength
* the security strength (converted from bits to bytes). * (converted from bits to bytes). You can override
* You can set a different entropy length for subsequent * it by calling mbedtls_hmac_drbg_set_entropy_len().
* seeding by calling mbedtls_hmac_drbg_set_entropy_len()
* after this function.
* *
* \note During the initial seeding, this function calls * \note During the initial seeding, this function calls
* the entropy source to obtain a nonce * 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 * \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(). * See the documentation of mbedtls_hmac_drbg_seed() for the default value.
*
* \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().
* *
* \param ctx The HMAC_DRBG context. * \param ctx The HMAC_DRBG context.
* \param len The amount of entropy to grab, in bytes. * \param len The amount of entropy to grab, in bytes.

View File

@ -62,68 +62,6 @@ void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context *ctx )
#endif #endif
} }
/*
* 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)
* 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
* 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 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 ) void mbedtls_ctr_drbg_free( mbedtls_ctr_drbg_context *ctx )
{ {
if( ctx == NULL ) if( ctx == NULL )
@ -427,6 +365,63 @@ exit:
return( ret ); return( ret );
} }
/* CTR_DRBG_Instantiate with derivation function (SP 800-90A §10.2.1.3.2)
* 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 ctx->entropy_len bytes
* and with outputs
* ctx = initial_working_state
*/
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 ) );
}
/* CTR_DRBG_Generate with derivation function (SP 800-90A §10.2.1.5.2) /* CTR_DRBG_Generate with derivation function (SP 800-90A §10.2.1.5.2)
* mbedtls_ctr_drbg_random_with_add(ctx, output, output_len, additional, add_len) * mbedtls_ctr_drbg_random_with_add(ctx, output, output_len, additional, add_len)
* implements * implements
@ -678,8 +673,11 @@ int mbedtls_ctr_drbg_self_test( int verbose )
mbedtls_printf( " CTR_DRBG (PR = TRUE) : " ); mbedtls_printf( " CTR_DRBG (PR = TRUE) : " );
test_offset = 0; test_offset = 0;
CHK( mbedtls_ctr_drbg_seed_entropy_len( &ctx, ctr_drbg_self_test_entropy, mbedtls_ctr_drbg_set_entropy_len( &ctx, 32 );
(void *) entropy_source_pr, nonce_pers_pr, 16, 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 ); 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 ) );
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 ); mbedtls_ctr_drbg_init( &ctx );
test_offset = 0; test_offset = 0;
CHK( mbedtls_ctr_drbg_seed_entropy_len( &ctx, ctr_drbg_self_test_entropy, mbedtls_ctr_drbg_set_entropy_len( &ctx, 32 );
(void *) entropy_source_nopr, nonce_pers_nopr, 16, 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_random( &ctx, buf, 16 ) );
CHK( mbedtls_ctr_drbg_reseed( &ctx, NULL, 0 ) ); CHK( mbedtls_ctr_drbg_reseed( &ctx, NULL, 0 ) );
CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) ); CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );

View File

@ -273,16 +273,19 @@ int mbedtls_hmac_drbg_seed( mbedtls_hmac_drbg_context *ctx,
ctx->reseed_interval = MBEDTLS_HMAC_DRBG_RESEED_INTERVAL; ctx->reseed_interval = MBEDTLS_HMAC_DRBG_RESEED_INTERVAL;
/* 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. * 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,
* (This also matches the sizes used in the NIST test vectors.) * min_entropy_len (in bits) is security_strength.
*/ *
ctx->entropy_len = md_size <= 20 ? 16 : /* 160-bits hash -> 128 bits */ * (This also matches the sizes used in the NIST test vectors.)
md_size <= 28 ? 24 : /* 224-bits hash -> 192 bits */ */
32; /* better (256+) -> 256 bits */ 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, if( ( ret = hmac_drbg_reseed_core( ctx, custom, len,
1 /* add nonce */ ) ) != 0 ) 1 /* add nonce */ ) ) != 0 )
@ -303,7 +306,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 ) void mbedtls_hmac_drbg_set_entropy_len( mbedtls_hmac_drbg_context *ctx, size_t len )
{ {

View File

@ -674,12 +674,13 @@ int main( int argc, char *argv[] )
mbedtls_ctr_drbg_context ctr_drbg; mbedtls_ctr_drbg_context ctr_drbg;
mbedtls_ctr_drbg_init( &ctr_drbg ); mbedtls_ctr_drbg_init( &ctr_drbg );
if( mbedtls_ctr_drbg_seed( &ctr_drbg, myrand, NULL, NULL, 0 ) != 0 ) if( mbedtls_ctr_drbg_seed( &ctr_drbg, myrand, NULL, NULL, 0 ) != 0 )
mbedtls_exit(1); mbedtls_exit(1);
TIME_AND_TSC( "CTR_DRBG (NOPR)", TIME_AND_TSC( "CTR_DRBG (NOPR)",
mbedtls_ctr_drbg_random( &ctr_drbg, buf, BUFSIZE ) ); mbedtls_ctr_drbg_random( &ctr_drbg, buf, BUFSIZE ) );
mbedtls_ctr_drbg_free( &ctr_drbg );
mbedtls_ctr_drbg_init( &ctr_drbg );
if( mbedtls_ctr_drbg_seed( &ctr_drbg, myrand, NULL, NULL, 0 ) != 0 ) if( mbedtls_ctr_drbg_seed( &ctr_drbg, myrand, NULL, NULL, 0 ) != 0 )
mbedtls_exit(1); mbedtls_exit(1);
mbedtls_ctr_drbg_set_prediction_resistance( &ctr_drbg, MBEDTLS_CTR_DRBG_PR_ON ); mbedtls_ctr_drbg_set_prediction_resistance( &ctr_drbg, MBEDTLS_CTR_DRBG_PR_ON );

View File

@ -44,11 +44,11 @@ static void ctr_drbg_validate_internal( int reseed_mode, data_t * nonce,
/* CTR_DRBG_Instantiate(entropy[:entropy->len], nonce, perso, <ignored>) /* CTR_DRBG_Instantiate(entropy[:entropy->len], nonce, perso, <ignored>)
* where nonce||perso = nonce[nonce->len] */ * 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, &ctx,
mbedtls_test_entropy_func, entropy->x, mbedtls_test_entropy_func, entropy->x,
nonce->x, nonce->len, nonce->x, nonce->len ) == 0 );
entropy_chunk_len ) == 0 );
if( reseed_mode == RESEED_ALWAYS ) if( reseed_mode == RESEED_ALWAYS )
mbedtls_ctr_drbg_set_prediction_resistance( mbedtls_ctr_drbg_set_prediction_resistance(
&ctx, &ctx,