Skip to content

Commit c054643

Browse files
authored
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
2 parents 269d414 + b02a233 commit c054643

File tree

7 files changed

+108
-105
lines changed

7 files changed

+108
-105
lines changed

ChangeLog

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ Bugfix
66
* Remove redundant line for getting the bitlen of a bignum, since the variable
77
holding the returned value is overwritten a line after.
88
Found by irwir in #2377.
9+
* Support mbedtls_hmac_drbg_set_entropy_len() and
10+
mbedtls_ctr_drbg_set_entropy_len() before the DRBG is seeded. Before,
11+
the initial seeding always reset the entropy length to the compile-time
12+
default.
913

1014
Changes
1115
* Add unit tests for AES-GCM when called through mbedtls_cipher_auth_xxx()

include/mbedtls/ctr_drbg.h

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -214,11 +214,8 @@ void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context *ctx );
214214
* with mbedtls_entropy_init() (which registers the platform's default
215215
* entropy sources).
216216
*
217-
* \p f_entropy is always called with a buffer size equal to the entropy
218-
* length. The entropy length is initially #MBEDTLS_CTR_DRBG_ENTROPY_LEN
219-
* and this value is always used for the initial seeding. You can change
220-
* the entropy length for subsequent seeding by calling
221-
* mbedtls_ctr_drbg_set_entropy_len() after this function.
217+
* The entropy length is #MBEDTLS_CTR_DRBG_ENTROPY_LEN by default.
218+
* You can override it by calling mbedtls_ctr_drbg_set_entropy_len().
222219
*
223220
* You can provide a personalization string in addition to the
224221
* entropy source, to make this instantiation as unique as possible.
@@ -252,9 +249,18 @@ void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context *ctx );
252249
#endif
253250
/**
254251
* \param ctx The CTR_DRBG context to seed.
252+
* It must have been initialized with
253+
* mbedtls_ctr_drbg_init().
254+
* After a successful call to mbedtls_ctr_drbg_seed(),
255+
* you may not call mbedtls_ctr_drbg_seed() again on
256+
* the same context unless you call
257+
* mbedtls_ctr_drbg_free() and mbedtls_ctr_drbg_init()
258+
* again first.
255259
* \param f_entropy The entropy callback, taking as arguments the
256260
* \p p_entropy context, the buffer to fill, and the
257261
* length of the buffer.
262+
* \p f_entropy is always called with a buffer size
263+
* equal to the entropy length.
258264
* \param p_entropy The entropy context to pass to \p f_entropy.
259265
* \param custom The personalization string.
260266
* 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,
298304

299305
/**
300306
* \brief This function sets the amount of entropy grabbed on each
301-
* subsequent reseed.
307+
* seed or reseed.
302308
*
303309
* The default value is #MBEDTLS_CTR_DRBG_ENTROPY_LEN.
304310
*
305-
* \note mbedtls_ctr_drbg_seed() always sets the entropy length
306-
* to #MBEDTLS_CTR_DRBG_ENTROPY_LEN, so this function
307-
* only has an effect when it is called after
308-
* mbedtls_ctr_drbg_seed().
309-
*
310311
* \note The security strength of CTR_DRBG is bounded by the
311312
* entropy length. Thus:
312313
* - When using AES-256

include/mbedtls/hmac_drbg.h

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -139,13 +139,11 @@ void mbedtls_hmac_drbg_init( mbedtls_hmac_drbg_context *ctx );
139139
* Note that SHA-256 is just as efficient as SHA-224.
140140
* The security strength can be reduced if a smaller
141141
* entropy length is set with
142-
* mbedtls_hmac_drbg_set_entropy_len() afterwards.
142+
* mbedtls_hmac_drbg_set_entropy_len().
143143
*
144-
* \note The entropy length for the initial seeding is
145-
* the security strength (converted from bits to bytes).
146-
* You can set a different entropy length for subsequent
147-
* seeding by calling mbedtls_hmac_drbg_set_entropy_len()
148-
* after this function.
144+
* \note The default entropy length is the security strength
145+
* (converted from bits to bytes). You can override
146+
* it by calling mbedtls_hmac_drbg_set_entropy_len().
149147
*
150148
* \note During the initial seeding, this function calls
151149
* the entropy source to obtain a nonce
@@ -224,14 +222,9 @@ void mbedtls_hmac_drbg_set_prediction_resistance( mbedtls_hmac_drbg_context *ctx
224222

225223
/**
226224
* \brief This function sets the amount of entropy grabbed on each
227-
* reseed.
225+
* seed or reseed.
228226
*
229-
* The default value is set by mbedtls_hmac_drbg_seed().
230-
*
231-
* \note mbedtls_hmac_drbg_seed() always sets the entropy length
232-
* to the default value based on the chosen MD algorithm,
233-
* so this function only has an effect if it is called
234-
* after mbedtls_hmac_drbg_seed().
227+
* See the documentation of mbedtls_hmac_drbg_seed() for the default value.
235228
*
236229
* \param ctx The HMAC_DRBG context.
237230
* \param len The amount of entropy to grab, in bytes.

library/ctr_drbg.c

Lines changed: 67 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -62,68 +62,6 @@ void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context *ctx )
6262
#endif
6363
}
6464

65-
/*
66-
* Non-public function wrapped by mbedtls_ctr_drbg_seed(). Necessary to allow
67-
* NIST tests to succeed (which require known length fixed entropy)
68-
*/
69-
/* CTR_DRBG_Instantiate with derivation function (SP 800-90A §10.2.1.3.2)
70-
* mbedtls_ctr_drbg_seed_entropy_len(ctx, f_entropy, p_entropy,
71-
* custom, len, entropy_len)
72-
* implements
73-
* CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string,
74-
* security_strength) -> initial_working_state
75-
* with inputs
76-
* custom[:len] = nonce || personalization_string
77-
* where entropy_input comes from f_entropy for entropy_len bytes
78-
* and with outputs
79-
* ctx = initial_working_state
80-
*/
81-
int mbedtls_ctr_drbg_seed_entropy_len(
82-
mbedtls_ctr_drbg_context *ctx,
83-
int (*f_entropy)(void *, unsigned char *, size_t),
84-
void *p_entropy,
85-
const unsigned char *custom,
86-
size_t len,
87-
size_t entropy_len )
88-
{
89-
int ret;
90-
unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
91-
92-
memset( key, 0, MBEDTLS_CTR_DRBG_KEYSIZE );
93-
94-
mbedtls_aes_init( &ctx->aes_ctx );
95-
96-
ctx->f_entropy = f_entropy;
97-
ctx->p_entropy = p_entropy;
98-
99-
ctx->entropy_len = entropy_len;
100-
ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;
101-
102-
/*
103-
* Initialize with an empty key
104-
*/
105-
if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, key, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
106-
{
107-
return( ret );
108-
}
109-
110-
if( ( ret = mbedtls_ctr_drbg_reseed( ctx, custom, len ) ) != 0 )
111-
{
112-
return( ret );
113-
}
114-
return( 0 );
115-
}
116-
117-
int mbedtls_ctr_drbg_seed( mbedtls_ctr_drbg_context *ctx,
118-
int (*f_entropy)(void *, unsigned char *, size_t),
119-
void *p_entropy,
120-
const unsigned char *custom,
121-
size_t len )
122-
{
123-
return( mbedtls_ctr_drbg_seed_entropy_len( ctx, f_entropy, p_entropy, custom, len,
124-
MBEDTLS_CTR_DRBG_ENTROPY_LEN ) );
125-
}
126-
12765
void mbedtls_ctr_drbg_free( mbedtls_ctr_drbg_context *ctx )
12866
{
12967
if( ctx == NULL )
@@ -427,6 +365,63 @@ int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx,
427365
return( ret );
428366
}
429367

368+
/* CTR_DRBG_Instantiate with derivation function (SP 800-90A §10.2.1.3.2)
369+
* mbedtls_ctr_drbg_seed(ctx, f_entropy, p_entropy, custom, len)
370+
* implements
371+
* CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string,
372+
* security_strength) -> initial_working_state
373+
* with inputs
374+
* custom[:len] = nonce || personalization_string
375+
* where entropy_input comes from f_entropy for ctx->entropy_len bytes
376+
* and with outputs
377+
* ctx = initial_working_state
378+
*/
379+
int mbedtls_ctr_drbg_seed( mbedtls_ctr_drbg_context *ctx,
380+
int (*f_entropy)(void *, unsigned char *, size_t),
381+
void *p_entropy,
382+
const unsigned char *custom,
383+
size_t len )
384+
{
385+
int ret;
386+
unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
387+
388+
memset( key, 0, MBEDTLS_CTR_DRBG_KEYSIZE );
389+
390+
mbedtls_aes_init( &ctx->aes_ctx );
391+
392+
ctx->f_entropy = f_entropy;
393+
ctx->p_entropy = p_entropy;
394+
395+
if( ctx->entropy_len == 0 )
396+
ctx->entropy_len = MBEDTLS_CTR_DRBG_ENTROPY_LEN;
397+
ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;
398+
399+
/*
400+
* Initialize with an empty key
401+
*/
402+
if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, key, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
403+
{
404+
return( ret );
405+
}
406+
407+
if( ( ret = mbedtls_ctr_drbg_reseed( ctx, custom, len ) ) != 0 )
408+
{
409+
return( ret );
410+
}
411+
return( 0 );
412+
}
413+
414+
/* Backward compatibility wrapper */
415+
int mbedtls_ctr_drbg_seed_entropy_len(
416+
mbedtls_ctr_drbg_context *ctx,
417+
int (*f_entropy)(void *, unsigned char *, size_t), void *p_entropy,
418+
const unsigned char *custom, size_t len,
419+
size_t entropy_len )
420+
{
421+
mbedtls_ctr_drbg_set_entropy_len( ctx, entropy_len );
422+
return( mbedtls_ctr_drbg_seed( ctx, f_entropy, p_entropy, custom, len ) );
423+
}
424+
430425
/* CTR_DRBG_Generate with derivation function (SP 800-90A §10.2.1.5.2)
431426
* mbedtls_ctr_drbg_random_with_add(ctx, output, output_len, additional, add_len)
432427
* implements
@@ -678,8 +673,11 @@ int mbedtls_ctr_drbg_self_test( int verbose )
678673
mbedtls_printf( " CTR_DRBG (PR = TRUE) : " );
679674

680675
test_offset = 0;
681-
CHK( mbedtls_ctr_drbg_seed_entropy_len( &ctx, ctr_drbg_self_test_entropy,
682-
(void *) entropy_source_pr, nonce_pers_pr, 16, 32 ) );
676+
mbedtls_ctr_drbg_set_entropy_len( &ctx, 32 );
677+
CHK( mbedtls_ctr_drbg_seed( &ctx,
678+
ctr_drbg_self_test_entropy,
679+
(void *) entropy_source_pr,
680+
nonce_pers_pr, 16 ) );
683681
mbedtls_ctr_drbg_set_prediction_resistance( &ctx, MBEDTLS_CTR_DRBG_PR_ON );
684682
CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
685683
CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
@@ -699,8 +697,11 @@ int mbedtls_ctr_drbg_self_test( int verbose )
699697
mbedtls_ctr_drbg_init( &ctx );
700698

701699
test_offset = 0;
702-
CHK( mbedtls_ctr_drbg_seed_entropy_len( &ctx, ctr_drbg_self_test_entropy,
703-
(void *) entropy_source_nopr, nonce_pers_nopr, 16, 32 ) );
700+
mbedtls_ctr_drbg_set_entropy_len( &ctx, 32 );
701+
CHK( mbedtls_ctr_drbg_seed( &ctx,
702+
ctr_drbg_self_test_entropy,
703+
(void *) entropy_source_nopr,
704+
nonce_pers_nopr, 16 ) );
704705
CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );
705706
CHK( mbedtls_ctr_drbg_reseed( &ctx, NULL, 0 ) );
706707
CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );

library/hmac_drbg.c

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -273,16 +273,19 @@ int mbedtls_hmac_drbg_seed( mbedtls_hmac_drbg_context *ctx,
273273

274274
ctx->reseed_interval = MBEDTLS_HMAC_DRBG_RESEED_INTERVAL;
275275

276-
/*
277-
* See SP800-57 5.6.1 (p. 65-66) for the security strength provided by
278-
* each hash function, then according to SP800-90A rev1 10.1 table 2,
279-
* min_entropy_len (in bits) is security_strength.
280-
*
281-
* (This also matches the sizes used in the NIST test vectors.)
282-
*/
283-
ctx->entropy_len = md_size <= 20 ? 16 : /* 160-bits hash -> 128 bits */
284-
md_size <= 28 ? 24 : /* 224-bits hash -> 192 bits */
285-
32; /* better (256+) -> 256 bits */
276+
if( ctx->entropy_len == 0 )
277+
{
278+
/*
279+
* See SP800-57 5.6.1 (p. 65-66) for the security strength provided by
280+
* each hash function, then according to SP800-90A rev1 10.1 table 2,
281+
* min_entropy_len (in bits) is security_strength.
282+
*
283+
* (This also matches the sizes used in the NIST test vectors.)
284+
*/
285+
ctx->entropy_len = md_size <= 20 ? 16 : /* 160-bits hash -> 128 bits */
286+
md_size <= 28 ? 24 : /* 224-bits hash -> 192 bits */
287+
32; /* better (256+) -> 256 bits */
288+
}
286289

287290
if( ( ret = hmac_drbg_reseed_core( ctx, custom, len,
288291
1 /* add nonce */ ) ) != 0 )
@@ -303,7 +306,7 @@ void mbedtls_hmac_drbg_set_prediction_resistance( mbedtls_hmac_drbg_context *ctx
303306
}
304307

305308
/*
306-
* Set entropy length grabbed for reseeds
309+
* Set entropy length grabbed for seeding
307310
*/
308311
void mbedtls_hmac_drbg_set_entropy_len( mbedtls_hmac_drbg_context *ctx, size_t len )
309312
{

programs/test/benchmark.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -674,12 +674,13 @@ int main( int argc, char *argv[] )
674674
mbedtls_ctr_drbg_context ctr_drbg;
675675

676676
mbedtls_ctr_drbg_init( &ctr_drbg );
677-
678677
if( mbedtls_ctr_drbg_seed( &ctr_drbg, myrand, NULL, NULL, 0 ) != 0 )
679678
mbedtls_exit(1);
680679
TIME_AND_TSC( "CTR_DRBG (NOPR)",
681680
mbedtls_ctr_drbg_random( &ctr_drbg, buf, BUFSIZE ) );
681+
mbedtls_ctr_drbg_free( &ctr_drbg );
682682

683+
mbedtls_ctr_drbg_init( &ctr_drbg );
683684
if( mbedtls_ctr_drbg_seed( &ctr_drbg, myrand, NULL, NULL, 0 ) != 0 )
684685
mbedtls_exit(1);
685686
mbedtls_ctr_drbg_set_prediction_resistance( &ctr_drbg, MBEDTLS_CTR_DRBG_PR_ON );

tests/suites/test_suite_ctr_drbg.function

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,11 +44,11 @@ static void ctr_drbg_validate_internal( int reseed_mode, data_t * nonce,
4444

4545
/* CTR_DRBG_Instantiate(entropy[:entropy->len], nonce, perso, <ignored>)
4646
* where nonce||perso = nonce[nonce->len] */
47-
TEST_ASSERT( mbedtls_ctr_drbg_seed_entropy_len(
47+
mbedtls_ctr_drbg_set_entropy_len( &ctx, entropy_chunk_len );
48+
TEST_ASSERT( mbedtls_ctr_drbg_seed(
4849
&ctx,
4950
mbedtls_test_entropy_func, entropy->x,
50-
nonce->x, nonce->len,
51-
entropy_chunk_len ) == 0 );
51+
nonce->x, nonce->len ) == 0 );
5252
if( reseed_mode == RESEED_ALWAYS )
5353
mbedtls_ctr_drbg_set_prediction_resistance(
5454
&ctx,

0 commit comments

Comments
 (0)