CTR_DRBG: define a constant for the default entropy nonce length

The default entropy nonce length is either zero or nonzero depending
on the desired security strength and the entropy length.

The implementation calculates the actual entropy nonce length from the
actual entropy length, and therefore it doesn't need a constant that
indicates the default entropy nonce length. A portable application may
be interested in this constant, however. And our test code could
definitely use it.

Define a constant MBEDTLS_CTR_DRBG_ENTROPY_NONCE_LEN and use it in
test code. Previously, test_suite_ctr_drbg had knowledge about the
default entropy nonce length built in and test_suite_psa_crypto_init
failed. Now both use MBEDTLS_CTR_DRBG_ENTROPY_NONCE_LEN.

This change means that the test ctr_drbg_entropy_usage no longer
validates that the default entropy nonce length is sensible. So add a
new test that checks that the default entropy length and the default
entropy nonce length are sufficient to ensure the expected security
strength.
This commit is contained in:
Gilles Peskine 2019-10-23 19:39:36 +02:00
parent e9a3454e09
commit 69971662bf
5 changed files with 78 additions and 34 deletions

View File

@ -147,6 +147,24 @@
extern "C" { extern "C" {
#endif #endif
#if MBEDTLS_CTR_DRBG_ENTROPY_LEN >= MBEDTLS_CTR_DRBG_KEYSIZE * 3 / 2
/** The default length of the nonce read from the entropy source.
*
* This is \c 0 because a single read from the entropy source is sufficient
* to include a nonce.
* See the documentation of mbedtls_ctr_drbg_seed() for more information.
*/
#define MBEDTLS_CTR_DRBG_ENTROPY_NONCE_LEN 0
#else
/** The default length of the nonce read from the entropy source.
*
* This is half of the default entropy length because a single read from
* the entropy source does not provide enough material to form a nonce.
* See the documentation of mbedtls_ctr_drbg_seed() for more information.
*/
#define MBEDTLS_CTR_DRBG_ENTROPY_NONCE_LEN ( MBEDTLS_CTR_DRBG_ENTROPY_LEN + 1 ) / 2
#endif
/** /**
* \brief The CTR_DRBG context structure. * \brief The CTR_DRBG context structure.
*/ */
@ -216,20 +234,9 @@ void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context *ctx );
* by the key size and entropy length according to NIST SP 800-90A §10.2.1; * by the key size and entropy length according to NIST SP 800-90A §10.2.1;
* - Half the entropy length otherwise. * - Half the entropy length otherwise.
* You can override it by calling mbedtls_ctr_drbg_set_nonce_len(). * You can override it by calling mbedtls_ctr_drbg_set_nonce_len().
*/ * With the default entropy length, the entropy nonce length is
#if MBEDTLS_CTR_DRBG_ENTROPY_LEN >= MBEDTLS_CTR_DRBG_KEYSIZE * 3 / 2 * #MBEDTLS_CTR_DRBG_ENTROPY_NONCE_LEN.
/** 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 * You can provide a nonce and 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.
* See SP 800-90A §8.6.7 for more details about nonces. * See SP 800-90A §8.6.7 for more details about nonces.
@ -240,7 +247,7 @@ void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context *ctx );
* - A string obtained by calling \p f_entropy function for the entropy * - A string obtained by calling \p f_entropy function for the entropy
* length. * length.
*/ */
#if MBEDTLS_CTR_DRBG_ENTROPY_LEN >= MBEDTLS_CTR_DRBG_KEYSIZE * 3 / 2 #if MBEDTLS_CTR_DRBG_ENTROPY_NONCE_LEN == 0
/** /**
* - If mbedtls_ctr_drbg_set_nonce_len() has been called, a string * - If mbedtls_ctr_drbg_set_nonce_len() has been called, a string
* obtained by calling \p f_entropy function for the specified length. * obtained by calling \p f_entropy function for the specified length.

View File

@ -1070,12 +1070,7 @@ CTR_DRBG CAVS 14.3 (AES-128 use df,True,128,64,0,0) #0
depends_on:MBEDTLS_CTR_DRBG_USE_128_BIT_KEY depends_on:MBEDTLS_CTR_DRBG_USE_128_BIT_KEY
ctr_drbg_validate_pr:"d4f1f4ae08bcb3e1":"5d4041942bcf68864a4997d8171f1f9fef55a769b7eaf03fe082029bb32a2b9d8239e865c0a42e14b964b9c09de85a20":"":"":"4155320287eedcf7d484c2c2a1e2eb64b9c9ce77c87202a1ae1616c7a5cfd1c687c7a0bfcc85bda48fdd4629fd330c22d0a76076f88fc7cd04037ee06b7af602" ctr_drbg_validate_pr:"d4f1f4ae08bcb3e1":"5d4041942bcf68864a4997d8171f1f9fef55a769b7eaf03fe082029bb32a2b9d8239e865c0a42e14b964b9c09de85a20":"":"":"4155320287eedcf7d484c2c2a1e2eb64b9c9ce77c87202a1ae1616c7a5cfd1c687c7a0bfcc85bda48fdd4629fd330c22d0a76076f88fc7cd04037ee06b7af602"
CTR_DRBG entropy usage (entropy_nonce_len=0 by default) CTR_DRBG entropy usage (default entropy_nonce_len)
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:-1
CTR_DRBG entropy usage (entropy_nonce_len=0) CTR_DRBG entropy usage (entropy_nonce_len=0)
@ -1084,6 +1079,14 @@ ctr_drbg_entropy_usage:0
CTR_DRBG entropy usage (entropy_nonce_len=7) CTR_DRBG entropy usage (entropy_nonce_len=7)
ctr_drbg_entropy_usage:7 ctr_drbg_entropy_usage:7
CTR_DRBG entropy strength: 128 bits
depends_on:MBEDTLS_CTR_DRBG_USE_128_BIT_KEY
ctr_drbg_entropy_strength:128
CTR_DRBG entropy strength: 256 bits
depends_on:!MBEDTLS_CTR_DRBG_USE_128_BIT_KEY
ctr_drbg_entropy_strength:256
CTR_DRBG write/update seed file [#1] CTR_DRBG write/update seed file [#1]
ctr_drbg_seed_file:"data_files/ctr_drbg_seed":0 ctr_drbg_seed_file:"data_files/ctr_drbg_seed":0

View File

@ -3,14 +3,6 @@
#include "mbedtls/ctr_drbg.h" #include "mbedtls/ctr_drbg.h"
#include "string.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 */ /* Modes for ctr_drbg_validate */
enum reseed_mode enum reseed_mode
{ {
@ -196,7 +188,37 @@ void ctr_drbg_validate_reseed_first( data_t * add_init, data_t * entropy,
} }
/* END_CASE */ /* END_CASE */
/* BEGIN_CASE */
void ctr_drbg_entropy_strength( int expected_bit_strength )
{
unsigned char entropy[/*initial entropy*/ MBEDTLS_CTR_DRBG_ENTROPY_LEN +
/*nonce*/ MBEDTLS_CTR_DRBG_ENTROPY_NONCE_LEN +
/*reseed*/ MBEDTLS_CTR_DRBG_ENTROPY_LEN];
mbedtls_ctr_drbg_context ctx;
size_t last_idx;
size_t byte_strength = expected_bit_strength / 8;
mbedtls_ctr_drbg_init( &ctx );
test_offset_idx = 0;
test_max_idx = sizeof( entropy );
memset( entropy, 0, sizeof( entropy ) );
/* The initial seeding must grab at least byte_strength bytes of entropy
* for the entropy input and byte_strength/2 bytes for a nonce. */
TEST_ASSERT( mbedtls_ctr_drbg_seed( &ctx,
mbedtls_test_entropy_func, entropy,
NULL, 0 ) == 0 );
TEST_ASSERT( test_offset_idx >= ( byte_strength * 3 + 1 ) / 2 );
last_idx = test_offset_idx;
/* A reseed must grab at least byte_strength bytes of entropy. */
TEST_ASSERT( mbedtls_ctr_drbg_reseed( &ctx, NULL, 0 ) == 0 );
TEST_ASSERT( test_offset_idx - last_idx >= byte_strength );
exit:
mbedtls_ctr_drbg_free( &ctx );
}
/* END_CASE */
/* BEGIN_CASE */ /* BEGIN_CASE */
void ctr_drbg_entropy_usage( int entropy_nonce_len ) void ctr_drbg_entropy_usage( int entropy_nonce_len )
@ -224,11 +246,7 @@ void ctr_drbg_entropy_usage( int entropy_nonce_len )
if( entropy_nonce_len >= 0 ) if( entropy_nonce_len >= 0 )
expected_idx += entropy_nonce_len; expected_idx += entropy_nonce_len;
else else
{ expected_idx += MBEDTLS_CTR_DRBG_ENTROPY_NONCE_LEN;
#if defined(DEFAULT_ENTROPY_NONCE)
expected_idx += ( MBEDTLS_CTR_DRBG_ENTROPY_LEN + 1 ) / 2;
#endif
}
TEST_EQUAL( test_offset_idx, expected_idx ); TEST_EQUAL( test_offset_idx, expected_idx );
/* By default, PR is off and reseed_interval is large, /* By default, PR is off and reseed_interval is large,

View File

@ -34,15 +34,25 @@ fake_entropy_source:MBEDTLS_ENTROPY_BLOCK_SIZE:0:0:0:0:PSA_ERROR_INSUFFICIENT_EN
Fake entropy: less than the block size Fake entropy: less than the block size
fake_entropy_source:MBEDTLS_ENTROPY_BLOCK_SIZE:MBEDTLS_ENTROPY_BLOCK_SIZE - 1:-1:-1:-1:PSA_ERROR_INSUFFICIENT_ENTROPY fake_entropy_source:MBEDTLS_ENTROPY_BLOCK_SIZE:MBEDTLS_ENTROPY_BLOCK_SIZE - 1:-1:-1:-1:PSA_ERROR_INSUFFICIENT_ENTROPY
Fake entropy: not enough for a nonce
depends_on:ENTROPY_NONCE_LEN != 0
fake_entropy_source:MBEDTLS_ENTROPY_BLOCK_SIZE:ENTROPY_NONCE_LEN - 1:-1:-1:-1:PSA_ERROR_INSUFFICIENT_ENTROPY
Fake entropy: one block eventually Fake entropy: one block eventually
depends_on:ENTROPY_NONCE_LEN == 0
fake_entropy_source:MBEDTLS_ENTROPY_BLOCK_SIZE:0:0:0:MBEDTLS_ENTROPY_BLOCK_SIZE:PSA_SUCCESS fake_entropy_source:MBEDTLS_ENTROPY_BLOCK_SIZE:0:0:0:MBEDTLS_ENTROPY_BLOCK_SIZE:PSA_SUCCESS
Fake entropy: one block in two steps Fake entropy: one block in two steps
depends_on:ENTROPY_NONCE_LEN == 0
fake_entropy_source:MBEDTLS_ENTROPY_BLOCK_SIZE:MBEDTLS_ENTROPY_BLOCK_SIZE - 1:1:-1:-1:PSA_SUCCESS fake_entropy_source:MBEDTLS_ENTROPY_BLOCK_SIZE:MBEDTLS_ENTROPY_BLOCK_SIZE - 1:1:-1:-1:PSA_SUCCESS
Fake entropy: more than one block in two steps Fake entropy: more than one block in two steps
depends_on:ENTROPY_NONCE_LEN == 0
fake_entropy_source:MBEDTLS_ENTROPY_BLOCK_SIZE:MBEDTLS_ENTROPY_BLOCK_SIZE - 1:MBEDTLS_ENTROPY_BLOCK_SIZE - 1:-1:-1:PSA_SUCCESS fake_entropy_source:MBEDTLS_ENTROPY_BLOCK_SIZE:MBEDTLS_ENTROPY_BLOCK_SIZE - 1:MBEDTLS_ENTROPY_BLOCK_SIZE - 1:-1:-1:PSA_SUCCESS
Fake entropy: two blocks eventually
fake_entropy_source:MBEDTLS_ENTROPY_BLOCK_SIZE:0:MBEDTLS_ENTROPY_BLOCK_SIZE:0:MBEDTLS_ENTROPY_BLOCK_SIZE:PSA_SUCCESS
NV seed only: less than minimum NV seed only: less than minimum
entropy_from_nv_seed:MBEDTLS_ENTROPY_MIN_PLATFORM - 1:PSA_ERROR_INSUFFICIENT_ENTROPY entropy_from_nv_seed:MBEDTLS_ENTROPY_MIN_PLATFORM - 1:PSA_ERROR_INSUFFICIENT_ENTROPY

View File

@ -11,6 +11,12 @@
#define ENTROPY_MIN_NV_SEED_SIZE \ #define ENTROPY_MIN_NV_SEED_SIZE \
MAX(MBEDTLS_ENTROPY_MIN_PLATFORM, MBEDTLS_ENTROPY_BLOCK_SIZE) MAX(MBEDTLS_ENTROPY_MIN_PLATFORM, MBEDTLS_ENTROPY_BLOCK_SIZE)
/* PSA crypto uses the CTR_DRBG module. In some configurations, it needs
* to read from the entropy source twice: once for the initial entropy
* and once for a nonce. */
#include "mbedtls/ctr_drbg.h"
#define ENTROPY_NONCE_LEN MBEDTLS_CTR_DRBG_ENTROPY_NONCE_LEN
typedef struct typedef struct
{ {
size_t threshold; /* Minimum bytes to make mbedtls_entropy_func happy */ size_t threshold; /* Minimum bytes to make mbedtls_entropy_func happy */