diff --git a/include/mbedtls/ctr_drbg.h b/include/mbedtls/ctr_drbg.h index 2b0c61712..09f4e620e 100644 --- a/include/mbedtls/ctr_drbg.h +++ b/include/mbedtls/ctr_drbg.h @@ -12,36 +12,14 @@ * The Mbed TLS implementation of CTR_DRBG uses AES-256 (default) or AES-128 * (if \c MBEDTLS_CTR_DRBG_USE_128_BIT_KEY is enabled at compile time) * as the underlying block cipher, with a derivation function. - * The initial seeding grabs #MBEDTLS_CTR_DRBG_ENTROPY_LEN bytes of entropy. - * See the documentation of mbedtls_ctr_drbg_seed() for more details. * - * Based on NIST SP 800-90A §10.2.1 table 3 and NIST SP 800-57 part 1 table 2, - * here are the security strengths achieved in typical configuration: - * - 256 bits under the default configuration of the library, with AES-256 - * and with #MBEDTLS_CTR_DRBG_ENTROPY_LEN set to 48 or more. - * - 256 bits if AES-256 is used, #MBEDTLS_CTR_DRBG_ENTROPY_LEN is set - * to 32 or more, and the DRBG is initialized with an explicit - * nonce in the \c custom parameter to mbedtls_ctr_drbg_seed(). - * - 256 bits if AES-256 is used, #MBEDTLS_CTR_DRBG_ENTROPY_LEN is set - * to 32 or more, and mbedtls_ctr_drbg_set_nonce_len() is called to set - * an entropy nonce length of 16 bytes or more. - * - 128 bits if AES-256 is used but #MBEDTLS_CTR_DRBG_ENTROPY_LEN is - * between 24 and 47 and the DRBG is not initialized with an explicit - * nonce (see mbedtls_ctr_drbg_seed()). - * - 128 bits if AES-128 is used (\c MBEDTLS_CTR_DRBG_USE_128_BIT_KEY enabled) - * and #MBEDTLS_CTR_DRBG_ENTROPY_LEN is set to 24 or more (which is - * always the case unless it is explicitly set to a different value - * in config.h). - * - 128 bits if AES-128 is used (\c MBEDTLS_CTR_DRBG_USE_128_BIT_KEY enabled) - * to 16 or more, and mbedtls_ctr_drbg_set_nonce_len() is called to set - * an entropy nonce length of 8 bytes or more. - * - * Note that the value of #MBEDTLS_CTR_DRBG_ENTROPY_LEN defaults to: - * - \c 48 if the module \c MBEDTLS_SHA512_C is enabled and the symbol - * \c MBEDTLS_ENTROPY_FORCE_SHA256 is disabled at compile time. - * This is the default configuration of the library. - * - \c 32 if the module \c MBEDTLS_SHA512_C is disabled at compile time. - * - \c 32 if \c MBEDTLS_ENTROPY_FORCE_SHA256 is enabled at compile time. + * The security strength as defined in NIST SP 800-90A is + * 128 bits when AES-128 is used (\c MBEDTLS_CTR_DRBG_USE_128_BIT_KEY enabled) + * and 256 bits otherwise, provided that #MBEDTLS_CTR_DRBG_ENTROPY_LEN is + * kept at its default value (and not overridden in config.h) and that the + * DRBG instance is set up with default parameters. + * See the documentation of mbedtls_ctr_drbg_seed() for more + * information. */ /* * 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 ); * The entropy length is #MBEDTLS_CTR_DRBG_ENTROPY_LEN by default. * You can override it by calling mbedtls_ctr_drbg_set_entropy_len(). * + * The entropy nonce length is: + * - \c 0 if the entropy length is at least 3/2 times the entropy length, + * which guarantees that the security strength is the maximum permitted + * by the key size and entropy length according to NIST SP 800-90A §10.2.1; + * - Half the entropy length otherwise. + * You can override it by calling mbedtls_ctr_drbg_set_nonce_len(). + */ +#if MBEDTLS_CTR_DRBG_ENTROPY_LEN >= MBEDTLS_CTR_DRBG_KEYSIZE * 3 / 2 +/** With the default entropy length, the entropy nonce length is \c 0. + */ +#elif MBEDTLS_CTR_DRBG_ENTROPY_LEN & 1 +/** With the default entropy length, the entropy nonce length is + * (#MBEDTLS_CTR_DRBG_ENTROPY_LEN + 1) / 2. + */ +#else +/** With the default entropy length, the entropy nonce length is + * #MBEDTLS_CTR_DRBG_ENTROPY_LEN / 2. + */ +#endif +/** * You can provide a nonce and personalization string in addition to the * entropy source, to make this instantiation as unique as possible. * See SP 800-90A §8.6.7 for more details about nonces. @@ -241,10 +239,20 @@ void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context *ctx ); * is the concatenation of the following strings: * - A string obtained by calling \p f_entropy function for the entropy * length. - * - A string obtained by calling \p f_entropy function for the nonce - * length set with mbedtls_ctr_drbg_set_nonce_len(). If the entropy - * nonce length is \c 0, this function does not make a second call - * to \p f_entropy. + */ +#if MBEDTLS_CTR_DRBG_ENTROPY_LEN >= MBEDTLS_CTR_DRBG_KEYSIZE * 3 / 2 +/** + * - If mbedtls_ctr_drbg_set_nonce_len() has been called, a string + * obtained by calling \p f_entropy function for the specified length. + */ +#else +/** + * - A string obtained by calling \p f_entropy function for the entropy nonce + * length. If the entropy nonce length is \c 0, this function does not + * make a second call to \p f_entropy. + */ +#endif +/** * - The \p custom string. * * \note To achieve the nominal security strength permitted @@ -256,10 +264,7 @@ void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context *ctx ); * * In addition, if you do not pass a nonce in \p custom, * the sum of the entropy length - * (#MBEDTLS_CTR_DRBG_ENTROPY_LEN unless overridden with - * mbedtls_ctr_drbg_set_entropy_len()) - * and the entropy nonce length (\c 0 unless overridden - * with mbedtls_ctr_drbg_set_nonce_len()) must be: + * and the entropy nonce length must be: * - at least 24 bytes for a 128-bit strength * (maximum achievable strength when using AES-128); * - at least 48 bytes for a 256-bit strength diff --git a/library/ctr_drbg.c b/library/ctr_drbg.c index 8c6ee59d5..047bb2a3e 100644 --- a/library/ctr_drbg.c +++ b/library/ctr_drbg.c @@ -56,6 +56,9 @@ void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context *ctx ) { memset( ctx, 0, sizeof( mbedtls_ctr_drbg_context ) ); + /* Indicate that the entropy nonce length is not set explicitly. + * See mbedtls_ctr_drbg_set_nonce_len(). */ + ctx->reseed_counter = -1; #if defined(MBEDTLS_THREADING_C) mbedtls_mutex_init( &ctx->mutex ); @@ -419,6 +422,19 @@ int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx, return( mbedtls_ctr_drbg_reseed_internal( ctx, additional, len, 0 ) ); } +/* Return a "good" nonce length for CTR_DRBG. The chosen nonce length + * is sufficient to achieve the maximum security strength given the key + * size and entropy length. If there is enough entropy in the initial + * call to the entropy function to serve as both the entropy input and + * the nonce, don't make a second call to get a nonce. */ +static size_t good_nonce_len( size_t entropy_len ) +{ + if( entropy_len >= MBEDTLS_CTR_DRBG_KEYSIZE * 3 / 2 ) + return( 0 ); + else + return( ( entropy_len + 1 ) / 2 ); +} + /* 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 @@ -438,6 +454,7 @@ int mbedtls_ctr_drbg_seed( mbedtls_ctr_drbg_context *ctx, { int ret; unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE]; + size_t nonce_len; memset( key, 0, MBEDTLS_CTR_DRBG_KEYSIZE ); @@ -448,6 +465,14 @@ int mbedtls_ctr_drbg_seed( mbedtls_ctr_drbg_context *ctx, if( ctx->entropy_len == 0 ) ctx->entropy_len = MBEDTLS_CTR_DRBG_ENTROPY_LEN; + /* ctx->reseed_counter contains the desired amount of entropy to + * grab for a nonce (see mbedtls_ctr_drbg_set_nonce_len()). + * If it's -1, indicating that the entropy nonce length was not set + * explicitly, use a sufficiently large nonce for security. */ + nonce_len = ( ctx->reseed_counter >= 0 ? + (size_t) ctx->reseed_counter : + good_nonce_len( ctx->entropy_len ) ); + ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL; /* Initialize with an empty key. */ @@ -457,11 +482,9 @@ int mbedtls_ctr_drbg_seed( mbedtls_ctr_drbg_context *ctx, return( ret ); } - /* Do the initial seeding. - * ctx->reseed_counter contains the desired amount of entropy to - * grab for a nonce (see mbedtls_ctr_drbg_set_nonce_len()). */ + /* Do the initial seeding. */ if( ( ret = mbedtls_ctr_drbg_reseed_internal( ctx, custom, len, - ctx->reseed_counter ) ) != 0 ) + nonce_len ) ) != 0 ) { return( ret ); } diff --git a/tests/suites/test_suite_ctr_drbg.data b/tests/suites/test_suite_ctr_drbg.data index 5f198a4ee..461e50255 100644 --- a/tests/suites/test_suite_ctr_drbg.data +++ b/tests/suites/test_suite_ctr_drbg.data @@ -1071,6 +1071,11 @@ depends_on:MBEDTLS_CTR_DRBG_USE_128_BIT_KEY ctr_drbg_validate_pr:"d4f1f4ae08bcb3e1":"5d4041942bcf68864a4997d8171f1f9fef55a769b7eaf03fe082029bb32a2b9d8239e865c0a42e14b964b9c09de85a20":"":"":"4155320287eedcf7d484c2c2a1e2eb64b9c9ce77c87202a1ae1616c7a5cfd1c687c7a0bfcc85bda48fdd4629fd330c22d0a76076f88fc7cd04037ee06b7af602" CTR_DRBG entropy usage (entropy_nonce_len=0 by default) +depends_on:!DEFAULT_ENTROPY_NONCE +ctr_drbg_entropy_usage:-1 + +CTR_DRBG entropy usage (entropy_nonce_len=entropy_len/2 by default) +depends_on:DEFAULT_ENTROPY_NONCE ctr_drbg_entropy_usage:-1 CTR_DRBG entropy usage (entropy_nonce_len=0) diff --git a/tests/suites/test_suite_ctr_drbg.function b/tests/suites/test_suite_ctr_drbg.function index c79b6e2aa..c28438587 100644 --- a/tests/suites/test_suite_ctr_drbg.function +++ b/tests/suites/test_suite_ctr_drbg.function @@ -3,6 +3,14 @@ #include "mbedtls/ctr_drbg.h" #include "string.h" +/* mbedtls_ctr_drbg_seed() grabs a nonce by default if the entropy + * length is smaller than 3/2 times the maximum security strength. */ +#if MBEDTLS_CTR_DRBG_ENTROPY_LEN >= MBEDTLS_CTR_DRBG_KEYSIZE * 3 / 2 +#undef DEFAULT_ENTROPY_NONCE +#else +#define DEFAULT_ENTROPY_NONCE +#endif + /* Modes for ctr_drbg_validate */ enum reseed_mode { @@ -215,6 +223,12 @@ void ctr_drbg_entropy_usage( int entropy_nonce_len ) expected_idx += MBEDTLS_CTR_DRBG_ENTROPY_LEN; if( entropy_nonce_len >= 0 ) expected_idx += entropy_nonce_len; + else + { +#if defined(DEFAULT_ENTROPY_NONCE) + expected_idx += ( MBEDTLS_CTR_DRBG_ENTROPY_LEN + 1 ) / 2; +#endif + } TEST_EQUAL( test_offset_idx, expected_idx ); /* By default, PR is off and reseed_interval is large,