Skip to content

Commit 204e45f

Browse files
CTR_DRBG: grab a nonce from the entropy source if needed
Change the default entropy nonce length to be nonzero in some cases. Specifically, the default nonce length is now set in such a way that the entropy input during the initial seeding always contains enough entropy to achieve the maximum possible security strength per NIST SP 800-90A given the key size and entropy length. If MBEDTLS_CTR_DRBG_ENTROPY_LEN is kept to its default value, mbedtls_ctr_drbg_seed() now grabs extra entropy for a nonce if MBEDTLS_CTR_DRBG_USE_128_BIT_KEY is disabled and either MBEDTLS_ENTROPY_FORCE_SHA256 is enabled or MBEDTLS_SHA512_C is disabled. If MBEDTLS_CTR_DRBG_USE_128_BIT_KEY is enabled, or if the entropy module uses SHA-512, then the default value of MBEDTLS_CTR_DRBG_ENTROPY_LEN does not require a second call to the entropy function to achieve the maximum security strength. This choice of default nonce size guarantees NIST compliance with the maximum security strength while keeping backward compatibility and performance high: in configurations that do not require grabbing more entropy, the code will not grab more entropy than before.
1 parent db34203 commit 204e45f

File tree

4 files changed

+87
-43
lines changed

4 files changed

+87
-43
lines changed

include/mbedtls/ctr_drbg.h

Lines changed: 41 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -12,36 +12,14 @@
1212
* The Mbed TLS implementation of CTR_DRBG uses AES-256 (default) or AES-128
1313
* (if \c MBEDTLS_CTR_DRBG_USE_128_BIT_KEY is enabled at compile time)
1414
* as the underlying block cipher, with a derivation function.
15-
* The initial seeding grabs #MBEDTLS_CTR_DRBG_ENTROPY_LEN bytes of entropy.
16-
* See the documentation of mbedtls_ctr_drbg_seed() for more details.
17-
*
18-
* Based on NIST SP 800-90A §10.2.1 table 3 and NIST SP 800-57 part 1 table 2,
19-
* here are the security strengths achieved in typical configuration:
20-
* - 256 bits under the default configuration of the library, with AES-256
21-
* and with #MBEDTLS_CTR_DRBG_ENTROPY_LEN set to 48 or more.
22-
* - 256 bits if AES-256 is used, #MBEDTLS_CTR_DRBG_ENTROPY_LEN is set
23-
* to 32 or more, and the DRBG is initialized with an explicit
24-
* nonce in the \c custom parameter to mbedtls_ctr_drbg_seed().
25-
* - 256 bits if AES-256 is used, #MBEDTLS_CTR_DRBG_ENTROPY_LEN is set
26-
* to 32 or more, and mbedtls_ctr_drbg_set_nonce_len() is called to set
27-
* an entropy nonce length of 16 bytes or more.
28-
* - 128 bits if AES-256 is used but #MBEDTLS_CTR_DRBG_ENTROPY_LEN is
29-
* between 24 and 47 and the DRBG is not initialized with an explicit
30-
* nonce (see mbedtls_ctr_drbg_seed()).
31-
* - 128 bits if AES-128 is used (\c MBEDTLS_CTR_DRBG_USE_128_BIT_KEY enabled)
32-
* and #MBEDTLS_CTR_DRBG_ENTROPY_LEN is set to 24 or more (which is
33-
* always the case unless it is explicitly set to a different value
34-
* in config.h).
35-
* - 128 bits if AES-128 is used (\c MBEDTLS_CTR_DRBG_USE_128_BIT_KEY enabled)
36-
* to 16 or more, and mbedtls_ctr_drbg_set_nonce_len() is called to set
37-
* an entropy nonce length of 8 bytes or more.
38-
*
39-
* Note that the value of #MBEDTLS_CTR_DRBG_ENTROPY_LEN defaults to:
40-
* - \c 48 if the module \c MBEDTLS_SHA512_C is enabled and the symbol
41-
* \c MBEDTLS_ENTROPY_FORCE_SHA256 is disabled at compile time.
42-
* This is the default configuration of the library.
43-
* - \c 32 if the module \c MBEDTLS_SHA512_C is disabled at compile time.
44-
* - \c 32 if \c MBEDTLS_ENTROPY_FORCE_SHA256 is enabled at compile time.
15+
*
16+
* The security strength as defined in NIST SP 800-90A is
17+
* 128 bits when AES-128 is used (\c MBEDTLS_CTR_DRBG_USE_128_BIT_KEY enabled)
18+
* and 256 bits otherwise, provided that #MBEDTLS_CTR_DRBG_ENTROPY_LEN is
19+
* kept at its default value (and not overridden in config.h) and that the
20+
* DRBG instance is set up with default parameters.
21+
* See the documentation of mbedtls_ctr_drbg_seed() for more
22+
* information.
4523
*/
4624
/*
4725
* Copyright (C) 2006-2019, Arm Limited (or its affiliates), All Rights Reserved
@@ -232,6 +210,26 @@ void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context *ctx );
232210
* The entropy length is #MBEDTLS_CTR_DRBG_ENTROPY_LEN by default.
233211
* You can override it by calling mbedtls_ctr_drbg_set_entropy_len().
234212
*
213+
* The entropy nonce length is:
214+
* - \c 0 if the entropy length is at least 3/2 times the entropy length,
215+
* which guarantees that the security strength is the maximum permitted
216+
* by the key size and entropy length according to NIST SP 800-90A §10.2.1;
217+
* - Half the entropy length otherwise.
218+
* You can override it by calling mbedtls_ctr_drbg_set_nonce_len().
219+
*/
220+
#if MBEDTLS_CTR_DRBG_ENTROPY_LEN >= MBEDTLS_CTR_DRBG_KEYSIZE * 3 / 2
221+
/** With the default entropy length, the entropy nonce length is \c 0.
222+
*/
223+
#elif MBEDTLS_CTR_DRBG_ENTROPY_LEN & 1
224+
/** With the default entropy length, the entropy nonce length is
225+
* (#MBEDTLS_CTR_DRBG_ENTROPY_LEN + 1) / 2.
226+
*/
227+
#else
228+
/** With the default entropy length, the entropy nonce length is
229+
* #MBEDTLS_CTR_DRBG_ENTROPY_LEN / 2.
230+
*/
231+
#endif
232+
/*
235233
* You can provide a nonce and personalization string in addition to the
236234
* entropy source, to make this instantiation as unique as possible.
237235
* See SP 800-90A §8.6.7 for more details about nonces.
@@ -241,11 +239,18 @@ void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context *ctx );
241239
* is the concatenation of the following strings:
242240
* - A string obtained by calling \p f_entropy function for the entropy
243241
* length.
244-
* - A string obtained by calling \p f_entropy function for the nonce
245-
* length set with mbedtls_ctr_drbg_set_nonce_len(). If the entropy
246-
* nonce length is \c 0, this function does not make a second call
247-
* to \p f_entropy.
248-
* - The \p custom string.
242+
*/
243+
#if MBEDTLS_CTR_DRBG_ENTROPY_LEN >= MBEDTLS_CTR_DRBG_KEYSIZE * 3 / 2
244+
/* - If mbedtls_ctr_drbg_set_nonce_len() has been called, a string
245+
* obtained by calling \p f_entropy function for the specified length.
246+
*/
247+
#else
248+
/* - A string obtained by calling \p f_entropy function for the entropy nonce
249+
* length. If the entropy nonce length is \c 0, this function does not
250+
* make a second call to \p f_entropy.
251+
*/
252+
#endif
253+
/* - The \p custom string.
249254
*
250255
* \note To achieve the nominal security strength permitted
251256
* by CTR_DRBG, the entropy length must be:
@@ -256,10 +261,7 @@ void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context *ctx );
256261
*
257262
* In addition, if you do not pass a nonce in \p custom,
258263
* the sum of the entropy length
259-
* (#MBEDTLS_CTR_DRBG_ENTROPY_LEN unless overridden with
260-
* mbedtls_ctr_drbg_set_entropy_len())
261-
* and the entropy nonce length (\c 0 unless overridden
262-
* with mbedtls_ctr_drbg_set_nonce_len()) must be:
264+
* and the entropy nonce length must be:
263265
* - at least 24 bytes for a 128-bit strength
264266
* (maximum achievable strength when using AES-128);
265267
* - at least 48 bytes for a 256-bit strength

library/ctr_drbg.c

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,9 @@
5656
void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context *ctx )
5757
{
5858
memset( ctx, 0, sizeof( mbedtls_ctr_drbg_context ) );
59+
/* Indicate that the entropy nonce length is not set explicitly.
60+
* See mbedtls_ctr_drbg_set_nonce_len(). */
61+
ctx->reseed_counter = -1;
5962

6063
#if defined(MBEDTLS_THREADING_C)
6164
mbedtls_mutex_init( &ctx->mutex );
@@ -419,6 +422,19 @@ int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx,
419422
return( mbedtls_ctr_drbg_reseed_internal( ctx, additional, len, 0 ) );
420423
}
421424

425+
/* Return a "good" nonce length for CTR_DRBG. The chosen nonce length
426+
* is sufficient to achieve the maximum security strength given the key
427+
* size and entropy length. If there is enough entropy in the initial
428+
* call to the entropy function to serve as both the entropy input and
429+
* the nonce, don't make a second call to get a nonce. */
430+
static size_t good_nonce_len( size_t entropy_len )
431+
{
432+
if( entropy_len >= MBEDTLS_CTR_DRBG_KEYSIZE * 3 / 2 )
433+
return( 0 );
434+
else
435+
return( ( entropy_len + 1 ) / 2 );
436+
}
437+
422438
/* CTR_DRBG_Instantiate with derivation function (SP 800-90A §10.2.1.3.2)
423439
* mbedtls_ctr_drbg_seed(ctx, f_entropy, p_entropy, custom, len)
424440
* implements
@@ -438,6 +454,7 @@ int mbedtls_ctr_drbg_seed( mbedtls_ctr_drbg_context *ctx,
438454
{
439455
int ret;
440456
unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
457+
size_t nonce_len;
441458

442459
memset( key, 0, MBEDTLS_CTR_DRBG_KEYSIZE );
443460

@@ -448,6 +465,14 @@ int mbedtls_ctr_drbg_seed( mbedtls_ctr_drbg_context *ctx,
448465

449466
if( ctx->entropy_len == 0 )
450467
ctx->entropy_len = MBEDTLS_CTR_DRBG_ENTROPY_LEN;
468+
/* ctx->reseed_counter contains the desired amount of entropy to
469+
* grab for a nonce (see mbedtls_ctr_drbg_set_nonce_len()).
470+
* If it's -1, indicating that the entropy nonce length was not set
471+
* explicitly, use a sufficiently large nonce for security. */
472+
nonce_len = ( ctx->reseed_counter >= 0 ?
473+
(size_t) ctx->reseed_counter :
474+
good_nonce_len( ctx->entropy_len ) );
475+
451476
ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;
452477

453478
/* Initialize with an empty key. */
@@ -457,11 +482,9 @@ int mbedtls_ctr_drbg_seed( mbedtls_ctr_drbg_context *ctx,
457482
return( ret );
458483
}
459484

460-
/* Do the initial seeding.
461-
* ctx->reseed_counter contains the desired amount of entropy to
462-
* grab for a nonce (see mbedtls_ctr_drbg_set_nonce_len()). */
485+
/* Do the initial seeding. */
463486
if( ( ret = mbedtls_ctr_drbg_reseed_internal( ctx, custom, len,
464-
ctx->reseed_counter ) ) != 0 )
487+
nonce_len ) ) != 0 )
465488
{
466489
return( ret );
467490
}

tests/suites/test_suite_ctr_drbg.data

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1071,6 +1071,11 @@ depends_on:MBEDTLS_CTR_DRBG_USE_128_BIT_KEY
10711071
ctr_drbg_validate_pr:"d4f1f4ae08bcb3e1":"5d4041942bcf68864a4997d8171f1f9fef55a769b7eaf03fe082029bb32a2b9d8239e865c0a42e14b964b9c09de85a20":"":"":"4155320287eedcf7d484c2c2a1e2eb64b9c9ce77c87202a1ae1616c7a5cfd1c687c7a0bfcc85bda48fdd4629fd330c22d0a76076f88fc7cd04037ee06b7af602"
10721072

10731073
CTR_DRBG entropy usage (entropy_nonce_len=0 by default)
1074+
depends_on:!DEFAULT_ENTROPY_NONCE
1075+
ctr_drbg_entropy_usage:-1
1076+
1077+
CTR_DRBG entropy usage (entropy_nonce_len=entropy_len/2 by default)
1078+
depends_on:DEFAULT_ENTROPY_NONCE
10741079
ctr_drbg_entropy_usage:-1
10751080

10761081
CTR_DRBG entropy usage (entropy_nonce_len=0)

tests/suites/test_suite_ctr_drbg.function

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,14 @@
33
#include "mbedtls/ctr_drbg.h"
44
#include "string.h"
55

6+
/* mbedtls_ctr_drbg_seed() grabs a nonce by default if the entropy
7+
* length is smaller than 3/2 times the maximum security strength. */
8+
#if MBEDTLS_CTR_DRBG_ENTROPY_LEN >= MBEDTLS_CTR_DRBG_KEYSIZE * 3 / 2
9+
#undef DEFAULT_ENTROPY_NONCE
10+
#else
11+
#define DEFAULT_ENTROPY_NONCE
12+
#endif
13+
614
/* Modes for ctr_drbg_validate */
715
enum reseed_mode
816
{
@@ -215,6 +223,12 @@ void ctr_drbg_entropy_usage( int entropy_nonce_len )
215223
expected_idx += MBEDTLS_CTR_DRBG_ENTROPY_LEN;
216224
if( entropy_nonce_len >= 0 )
217225
expected_idx += entropy_nonce_len;
226+
else
227+
{
228+
#if defined(DEFAULT_ENTROPY_NONCE)
229+
expected_idx += ( MBEDTLS_CTR_DRBG_ENTROPY_LEN + 1 ) / 2;
230+
#endif
231+
}
218232
TEST_EQUAL( test_offset_idx, expected_idx );
219233

220234
/* By default, PR is off and reseed_interval is large,

0 commit comments

Comments
 (0)