mirror of
https://github.com/yuzu-emu/mbedtls.git
synced 2025-01-11 04:55:41 +00:00
Merge pull request #305 from gilles-peskine-arm/ctr_drbg-grab_nonce_from_entropy-set_nonce_length
CTR_DRBG: grab a nonce from the entropy source if needed
This commit is contained in:
commit
22589f0a72
|
@ -12,30 +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().
|
||||
* - 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).
|
||||
*
|
||||
* 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
|
||||
|
@ -163,20 +147,47 @@
|
|||
extern "C" {
|
||||
#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.
|
||||
*/
|
||||
typedef struct mbedtls_ctr_drbg_context
|
||||
{
|
||||
unsigned char counter[16]; /*!< The counter (V). */
|
||||
int reseed_counter; /*!< The reseed counter. */
|
||||
int reseed_counter; /*!< The reseed counter.
|
||||
* This is the number of requests that have
|
||||
* been made since the last (re)seeding,
|
||||
* minus one.
|
||||
* Before the initial seeding, this field
|
||||
* contains the amount of entropy in bytes
|
||||
* to use as a nonce for the initial seeding.
|
||||
*/
|
||||
int prediction_resistance; /*!< This determines whether prediction
|
||||
resistance is enabled, that is
|
||||
whether to systematically reseed before
|
||||
each random generation. */
|
||||
size_t entropy_len; /*!< The amount of entropy grabbed on each
|
||||
seed or reseed operation. */
|
||||
int reseed_interval; /*!< The reseed interval. */
|
||||
seed or reseed operation, in bytes. */
|
||||
int reseed_interval; /*!< The reseed interval.
|
||||
* This is the maximum number of requests
|
||||
* that can be made between reseedings. */
|
||||
|
||||
mbedtls_aes_context aes_ctx; /*!< The AES context. */
|
||||
|
||||
|
@ -217,43 +228,68 @@ 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().
|
||||
*
|
||||
* You can provide a personalization string in addition to the
|
||||
* entropy source, to make this instantiation as unique as possible.
|
||||
* 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().
|
||||
* With the default entropy length, the entropy nonce length is
|
||||
* #MBEDTLS_CTR_DRBG_ENTROPY_NONCE_LEN.
|
||||
*
|
||||
* \note The _seed_material_ value passed to the derivation
|
||||
* function in the CTR_DRBG Instantiate Process
|
||||
* described in NIST SP 800-90A §10.2.1.3.2
|
||||
* is the concatenation of the string obtained from
|
||||
* calling \p f_entropy and the \p custom string.
|
||||
* The origin of the nonce depends on the value of
|
||||
* the entropy length relative to the security strength.
|
||||
* - If the entropy length is at least 1.5 times the
|
||||
* security strength then the nonce is taken from the
|
||||
* string obtained with \p f_entropy.
|
||||
* - If the entropy length is less than the security
|
||||
* strength, then the nonce is taken from \p custom.
|
||||
* In this case, for compliance with SP 800-90A,
|
||||
* you must pass a unique value of \p custom at
|
||||
* each invocation. See SP 800-90A §8.6.7 for more
|
||||
* details.
|
||||
* 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.
|
||||
*
|
||||
* The _seed_material_ value passed to the derivation function in
|
||||
* the CTR_DRBG Instantiate Process described in NIST SP 800-90A §10.2.1.3.2
|
||||
* is the concatenation of the following strings:
|
||||
* - A string obtained by calling \p f_entropy function for the entropy
|
||||
* length.
|
||||
*/
|
||||
#if MBEDTLS_CTR_DRBG_ENTROPY_LEN < MBEDTLS_CTR_DRBG_KEYSIZE * 3 / 2
|
||||
/** \warning When #MBEDTLS_CTR_DRBG_ENTROPY_LEN is less than
|
||||
* #MBEDTLS_CTR_DRBG_KEYSIZE * 3 / 2, to achieve the
|
||||
* maximum security strength permitted by CTR_DRBG,
|
||||
* you must pass a value of \p custom that is a nonce:
|
||||
* this value must never be repeated in subsequent
|
||||
* runs of the same application or on a different
|
||||
* device.
|
||||
#if MBEDTLS_CTR_DRBG_ENTROPY_NONCE_LEN == 0
|
||||
/**
|
||||
* - 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
|
||||
* by CTR_DRBG, the entropy length must be:
|
||||
* - at least 16 bytes for a 128-bit strength
|
||||
* (maximum achievable strength when using AES-128);
|
||||
* - at least 32 bytes for a 256-bit strength
|
||||
* (maximum achievable strength when using AES-256).
|
||||
*
|
||||
* In addition, if you do not pass a nonce in \p custom,
|
||||
* the sum of the entropy length
|
||||
* 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
|
||||
* (maximum achievable strength when using AES-256).
|
||||
*
|
||||
* \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
|
||||
* \p p_entropy context, the buffer to fill, and the
|
||||
* length of the buffer.
|
||||
* \p f_entropy is always called with a buffer size
|
||||
* equal to the entropy length.
|
||||
* less than or equal to the entropy length.
|
||||
* \param p_entropy The entropy context to pass to \p f_entropy.
|
||||
* \param custom The personalization string.
|
||||
* This can be \c NULL, in which case the personalization
|
||||
|
@ -301,11 +337,6 @@ void mbedtls_ctr_drbg_set_prediction_resistance( mbedtls_ctr_drbg_context *ctx,
|
|||
*
|
||||
* 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
|
||||
* entropy length. Thus:
|
||||
* - When using AES-256
|
||||
|
@ -320,11 +351,35 @@ void mbedtls_ctr_drbg_set_prediction_resistance( mbedtls_ctr_drbg_context *ctx,
|
|||
*
|
||||
* \param ctx The CTR_DRBG context.
|
||||
* \param len The amount of entropy to grab, in bytes.
|
||||
* This must be at most #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT.
|
||||
* This must be at most #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT
|
||||
* and at most the maximum length accepted by the
|
||||
* entropy function that is set in the context.
|
||||
*/
|
||||
void mbedtls_ctr_drbg_set_entropy_len( mbedtls_ctr_drbg_context *ctx,
|
||||
size_t len );
|
||||
|
||||
/**
|
||||
* \brief This function sets the amount of entropy grabbed
|
||||
* as a nonce for the initial seeding.
|
||||
*
|
||||
* Call this function before calling mbedtls_ctr_drbg_seed() to read
|
||||
* a nonce from the entropy source during the initial seeding.
|
||||
*
|
||||
* \param ctx The CTR_DRBG context.
|
||||
* \param len The amount of entropy to grab for the nonce, in bytes.
|
||||
* This must be at most #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT
|
||||
* and at most the maximum length accepted by the
|
||||
* entropy function that is set in the context.
|
||||
*
|
||||
* \return \c 0 on success.
|
||||
* \return #MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG if \p len is
|
||||
* more than #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT.
|
||||
* \return #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED
|
||||
* if the initial seeding has already taken place.
|
||||
*/
|
||||
int mbedtls_ctr_drbg_set_nonce_len( mbedtls_ctr_drbg_context *ctx,
|
||||
size_t len );
|
||||
|
||||
/**
|
||||
* \brief This function sets the reseed interval.
|
||||
*
|
||||
|
|
|
@ -139,7 +139,7 @@ void mbedtls_hmac_drbg_init( mbedtls_hmac_drbg_context *ctx );
|
|||
* Note that SHA-256 is just as efficient as SHA-224.
|
||||
* The security strength can be reduced if a smaller
|
||||
* entropy length is set with
|
||||
* mbedtls_hmac_drbg_set_entropy_len() afterwards.
|
||||
* mbedtls_hmac_drbg_set_entropy_len().
|
||||
*
|
||||
* \note The default entropy length is the security strength
|
||||
* (converted from bits to bytes). You can override
|
||||
|
@ -222,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
|
||||
* reseed.
|
||||
* seed or reseed.
|
||||
*
|
||||
* The default value is set by mbedtls_hmac_drbg_seed().
|
||||
*
|
||||
* \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().
|
||||
* See the documentation of mbedtls_hmac_drbg_seed() for the default value.
|
||||
*
|
||||
* \param ctx The HMAC_DRBG context.
|
||||
* \param len The amount of entropy to grab, in bytes.
|
||||
|
|
|
@ -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 );
|
||||
|
@ -86,6 +89,32 @@ void mbedtls_ctr_drbg_set_entropy_len( mbedtls_ctr_drbg_context *ctx,
|
|||
ctx->entropy_len = len;
|
||||
}
|
||||
|
||||
int mbedtls_ctr_drbg_set_nonce_len( mbedtls_ctr_drbg_context *ctx,
|
||||
size_t len )
|
||||
{
|
||||
/* If mbedtls_ctr_drbg_seed() has already been called, it's
|
||||
* too late. Return the error code that's closest to making sense. */
|
||||
if( ctx->f_entropy != NULL )
|
||||
return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
|
||||
|
||||
if( len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
|
||||
return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
|
||||
#if SIZE_MAX > INT_MAX
|
||||
/* This shouldn't be an issue because
|
||||
* MBEDTLS_CTR_DRBG_MAX_SEED_INPUT < INT_MAX in any sensible
|
||||
* configuration, but make sure anyway. */
|
||||
if( len > INT_MAX )
|
||||
return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
|
||||
#endif
|
||||
|
||||
/* For backward compatibility with Mbed TLS <= 2.19, store the
|
||||
* entropy nonce length in a field that already exists, but isn't
|
||||
* used until after the initial seeding. */
|
||||
/* Due to the capping of len above, the value fits in an int. */
|
||||
ctx->reseed_counter = (int) len;
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
void mbedtls_ctr_drbg_set_reseed_interval( mbedtls_ctr_drbg_context *ctx,
|
||||
int interval )
|
||||
{
|
||||
|
@ -319,7 +348,7 @@ void mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context *ctx,
|
|||
#endif /* MBEDTLS_DEPRECATED_REMOVED */
|
||||
|
||||
/* CTR_DRBG_Reseed with derivation function (SP 800-90A §10.2.1.4.2)
|
||||
* mbedtls_ctr_drbg_reseed(ctx, additional, len)
|
||||
* mbedtls_ctr_drbg_reseed(ctx, additional, len, nonce_len)
|
||||
* implements
|
||||
* CTR_DRBG_Reseed(working_state, entropy_input, additional_input)
|
||||
* -> new_working_state
|
||||
|
@ -327,51 +356,57 @@ void mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context *ctx,
|
|||
* ctx contains working_state
|
||||
* additional[:len] = additional_input
|
||||
* and entropy_input comes from calling ctx->f_entropy
|
||||
* for (ctx->entropy_len + nonce_len) bytes
|
||||
* and with output
|
||||
* ctx contains new_working_state
|
||||
*/
|
||||
int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx,
|
||||
const unsigned char *additional, size_t len )
|
||||
static int mbedtls_ctr_drbg_reseed_internal( mbedtls_ctr_drbg_context *ctx,
|
||||
const unsigned char *additional,
|
||||
size_t len,
|
||||
size_t nonce_len )
|
||||
{
|
||||
unsigned char seed[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT];
|
||||
size_t seedlen = 0;
|
||||
int ret;
|
||||
|
||||
if( ctx->entropy_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT ||
|
||||
len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len )
|
||||
if( ctx->entropy_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
|
||||
return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
|
||||
if( nonce_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len )
|
||||
return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
|
||||
if( len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len - nonce_len )
|
||||
return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
|
||||
|
||||
memset( seed, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT );
|
||||
|
||||
/*
|
||||
* Gather entropy_len bytes of entropy to seed state
|
||||
*/
|
||||
if( 0 != ctx->f_entropy( ctx->p_entropy, seed,
|
||||
ctx->entropy_len ) )
|
||||
/* Gather entropy_len bytes of entropy to seed state. */
|
||||
if( 0 != ctx->f_entropy( ctx->p_entropy, seed, ctx->entropy_len ) )
|
||||
{
|
||||
return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
|
||||
}
|
||||
|
||||
seedlen += ctx->entropy_len;
|
||||
|
||||
/*
|
||||
* Add additional data
|
||||
*/
|
||||
if( additional && len )
|
||||
/* Gather entropy for a nonce if requested. */
|
||||
if( nonce_len != 0 )
|
||||
{
|
||||
if( 0 != ctx->f_entropy( ctx->p_entropy, seed, nonce_len ) )
|
||||
{
|
||||
return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
|
||||
}
|
||||
seedlen += nonce_len;
|
||||
}
|
||||
|
||||
/* Add additional data if provided. */
|
||||
if( additional != NULL && len != 0 )
|
||||
{
|
||||
memcpy( seed + seedlen, additional, len );
|
||||
seedlen += len;
|
||||
}
|
||||
|
||||
/*
|
||||
* Reduce to 384 bits
|
||||
*/
|
||||
/* Reduce to 384 bits. */
|
||||
if( ( ret = block_cipher_df( seed, seed, seedlen ) ) != 0 )
|
||||
goto exit;
|
||||
|
||||
/*
|
||||
* Update state
|
||||
*/
|
||||
/* Update state. */
|
||||
if( ( ret = ctr_drbg_update_internal( ctx, seed ) ) != 0 )
|
||||
goto exit;
|
||||
ctx->reseed_counter = 1;
|
||||
|
@ -381,15 +416,33 @@ exit:
|
|||
return( ret );
|
||||
}
|
||||
|
||||
int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx,
|
||||
const unsigned char *additional, size_t len )
|
||||
{
|
||||
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_entropy_len(ctx, f_entropy, p_entropy,
|
||||
* custom, len, entropy_len)
|
||||
* 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 entropy_len bytes
|
||||
* where entropy_input comes from f_entropy for ctx->entropy_len bytes
|
||||
* and with outputs
|
||||
* ctx = initial_working_state
|
||||
*/
|
||||
|
@ -401,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 );
|
||||
|
||||
|
@ -411,18 +465,26 @@ 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
|
||||
*/
|
||||
/* 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 )
|
||||
/* Do the initial seeding. */
|
||||
if( ( ret = mbedtls_ctr_drbg_reseed_internal( ctx, custom, len,
|
||||
nonce_len ) ) != 0 )
|
||||
{
|
||||
return( ret );
|
||||
}
|
||||
|
@ -693,6 +755,7 @@ int mbedtls_ctr_drbg_self_test( int verbose )
|
|||
|
||||
test_offset = 0;
|
||||
mbedtls_ctr_drbg_set_entropy_len( &ctx, 32 );
|
||||
mbedtls_ctr_drbg_set_nonce_len( &ctx, 0 );
|
||||
CHK( mbedtls_ctr_drbg_seed( &ctx,
|
||||
ctr_drbg_self_test_entropy,
|
||||
(void *) entropy_source_pr,
|
||||
|
@ -717,6 +780,7 @@ int mbedtls_ctr_drbg_self_test( int verbose )
|
|||
|
||||
test_offset = 0;
|
||||
mbedtls_ctr_drbg_set_entropy_len( &ctx, 32 );
|
||||
mbedtls_ctr_drbg_set_nonce_len( &ctx, 0 );
|
||||
CHK( mbedtls_ctr_drbg_seed( &ctx,
|
||||
ctr_drbg_self_test_entropy,
|
||||
(void *) entropy_source_nopr,
|
||||
|
|
|
@ -686,12 +686,13 @@ int main( int argc, char *argv[] )
|
|||
mbedtls_ctr_drbg_context ctr_drbg;
|
||||
|
||||
mbedtls_ctr_drbg_init( &ctr_drbg );
|
||||
|
||||
if( mbedtls_ctr_drbg_seed( &ctr_drbg, myrand, NULL, NULL, 0 ) != 0 )
|
||||
mbedtls_exit(1);
|
||||
TIME_AND_TSC( "CTR_DRBG (NOPR)",
|
||||
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 )
|
||||
mbedtls_exit(1);
|
||||
mbedtls_ctr_drbg_set_prediction_resistance( &ctr_drbg, MBEDTLS_CTR_DRBG_PR_ON );
|
||||
|
|
|
@ -1070,8 +1070,22 @@ CTR_DRBG CAVS 14.3 (AES-128 use df,True,128,64,0,0) #0
|
|||
depends_on:MBEDTLS_CTR_DRBG_USE_128_BIT_KEY
|
||||
ctr_drbg_validate_pr:"d4f1f4ae08bcb3e1":"5d4041942bcf68864a4997d8171f1f9fef55a769b7eaf03fe082029bb32a2b9d8239e865c0a42e14b964b9c09de85a20":"":"":"4155320287eedcf7d484c2c2a1e2eb64b9c9ce77c87202a1ae1616c7a5cfd1c687c7a0bfcc85bda48fdd4629fd330c22d0a76076f88fc7cd04037ee06b7af602"
|
||||
|
||||
CTR_DRBG entropy usage
|
||||
ctr_drbg_entropy_usage:
|
||||
CTR_DRBG entropy usage (default entropy_nonce_len)
|
||||
ctr_drbg_entropy_usage:-1
|
||||
|
||||
CTR_DRBG entropy usage (entropy_nonce_len=0)
|
||||
ctr_drbg_entropy_usage:0
|
||||
|
||||
CTR_DRBG entropy usage (entropy_nonce_len=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_seed_file:"data_files/ctr_drbg_seed":0
|
||||
|
|
|
@ -45,6 +45,7 @@ static void ctr_drbg_validate_internal( int reseed_mode, data_t * nonce,
|
|||
/* CTR_DRBG_Instantiate(entropy[:entropy->len], nonce, perso, <ignored>)
|
||||
* where nonce||perso = nonce[nonce->len] */
|
||||
mbedtls_ctr_drbg_set_entropy_len( &ctx, entropy_chunk_len );
|
||||
mbedtls_ctr_drbg_set_nonce_len( &ctx, 0 );
|
||||
TEST_ASSERT( mbedtls_ctr_drbg_seed(
|
||||
&ctx,
|
||||
mbedtls_test_entropy_func, entropy->x,
|
||||
|
@ -187,17 +188,47 @@ void ctr_drbg_validate_reseed_first( data_t * add_init, data_t * entropy,
|
|||
}
|
||||
/* 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 */
|
||||
void ctr_drbg_entropy_usage( )
|
||||
void ctr_drbg_entropy_usage( int entropy_nonce_len )
|
||||
{
|
||||
unsigned char out[16];
|
||||
unsigned char add[16];
|
||||
unsigned char entropy[1024];
|
||||
mbedtls_ctr_drbg_context ctx;
|
||||
size_t i, reps = 10;
|
||||
size_t last_idx;
|
||||
size_t expected_idx = 0;
|
||||
|
||||
mbedtls_ctr_drbg_init( &ctx );
|
||||
test_offset_idx = 0;
|
||||
|
@ -206,21 +237,27 @@ void ctr_drbg_entropy_usage( )
|
|||
memset( out, 0, sizeof( out ) );
|
||||
memset( add, 0, sizeof( add ) );
|
||||
|
||||
if( entropy_nonce_len >= 0 )
|
||||
TEST_ASSERT( mbedtls_ctr_drbg_set_nonce_len( &ctx, entropy_nonce_len ) == 0 );
|
||||
|
||||
/* Init must use entropy */
|
||||
last_idx = test_offset_idx;
|
||||
TEST_ASSERT( mbedtls_ctr_drbg_seed( &ctx, mbedtls_test_entropy_func, entropy, NULL, 0 ) == 0 );
|
||||
TEST_ASSERT( last_idx < test_offset_idx );
|
||||
expected_idx += MBEDTLS_CTR_DRBG_ENTROPY_LEN;
|
||||
if( entropy_nonce_len >= 0 )
|
||||
expected_idx += entropy_nonce_len;
|
||||
else
|
||||
expected_idx += MBEDTLS_CTR_DRBG_ENTROPY_NONCE_LEN;
|
||||
TEST_EQUAL( test_offset_idx, expected_idx );
|
||||
|
||||
/* By default, PR is off and reseed_interval is large,
|
||||
* so the next few calls should not use entropy */
|
||||
last_idx = test_offset_idx;
|
||||
for( i = 0; i < reps; i++ )
|
||||
{
|
||||
TEST_ASSERT( mbedtls_ctr_drbg_random( &ctx, out, sizeof( out ) - 4 ) == 0 );
|
||||
TEST_ASSERT( mbedtls_ctr_drbg_random_with_add( &ctx, out, sizeof( out ) - 4,
|
||||
add, sizeof( add ) ) == 0 );
|
||||
}
|
||||
TEST_ASSERT( last_idx == test_offset_idx );
|
||||
TEST_EQUAL( test_offset_idx, expected_idx );
|
||||
|
||||
/* While at it, make sure we didn't write past the requested length */
|
||||
TEST_ASSERT( out[sizeof( out ) - 4] == 0 );
|
||||
|
@ -232,17 +269,17 @@ void ctr_drbg_entropy_usage( )
|
|||
* so the next call should reseed */
|
||||
mbedtls_ctr_drbg_set_reseed_interval( &ctx, 2 * reps );
|
||||
TEST_ASSERT( mbedtls_ctr_drbg_random( &ctx, out, sizeof( out ) ) == 0 );
|
||||
TEST_ASSERT( last_idx < test_offset_idx );
|
||||
expected_idx += MBEDTLS_CTR_DRBG_ENTROPY_LEN;
|
||||
TEST_EQUAL( test_offset_idx, expected_idx );
|
||||
|
||||
/* The new few calls should not reseed */
|
||||
last_idx = test_offset_idx;
|
||||
for( i = 0; i < reps / 2; i++ )
|
||||
{
|
||||
TEST_ASSERT( mbedtls_ctr_drbg_random( &ctx, out, sizeof( out ) ) == 0 );
|
||||
TEST_ASSERT( mbedtls_ctr_drbg_random_with_add( &ctx, out, sizeof( out ) ,
|
||||
add, sizeof( add ) ) == 0 );
|
||||
}
|
||||
TEST_ASSERT( last_idx == test_offset_idx );
|
||||
TEST_EQUAL( test_offset_idx, expected_idx );
|
||||
|
||||
/* Call update with too much data (sizeof entropy > MAX(_SEED)_INPUT).
|
||||
* Make sure it's detected as an error and doesn't cause memory
|
||||
|
@ -253,18 +290,19 @@ void ctr_drbg_entropy_usage( )
|
|||
/* Now enable PR, so the next few calls should all reseed */
|
||||
mbedtls_ctr_drbg_set_prediction_resistance( &ctx, MBEDTLS_CTR_DRBG_PR_ON );
|
||||
TEST_ASSERT( mbedtls_ctr_drbg_random( &ctx, out, sizeof( out ) ) == 0 );
|
||||
TEST_ASSERT( last_idx < test_offset_idx );
|
||||
expected_idx += MBEDTLS_CTR_DRBG_ENTROPY_LEN;
|
||||
TEST_EQUAL( test_offset_idx, expected_idx );
|
||||
|
||||
/* Finally, check setting entropy_len */
|
||||
mbedtls_ctr_drbg_set_entropy_len( &ctx, 42 );
|
||||
last_idx = test_offset_idx;
|
||||
TEST_ASSERT( mbedtls_ctr_drbg_random( &ctx, out, sizeof( out ) ) == 0 );
|
||||
TEST_ASSERT( test_offset_idx - last_idx == 42 );
|
||||
expected_idx += 42;
|
||||
TEST_EQUAL( test_offset_idx, expected_idx );
|
||||
|
||||
mbedtls_ctr_drbg_set_entropy_len( &ctx, 13 );
|
||||
last_idx = test_offset_idx;
|
||||
TEST_ASSERT( mbedtls_ctr_drbg_random( &ctx, out, sizeof( out ) ) == 0 );
|
||||
TEST_ASSERT( test_offset_idx - last_idx == 13 );
|
||||
expected_idx += 13;
|
||||
TEST_EQUAL( test_offset_idx, expected_idx );
|
||||
|
||||
exit:
|
||||
mbedtls_ctr_drbg_free( &ctx );
|
||||
|
|
|
@ -37,7 +37,9 @@ void hmac_drbg_entropy_usage( int md_alg )
|
|||
const mbedtls_md_info_t *md_info;
|
||||
mbedtls_hmac_drbg_context ctx;
|
||||
entropy_ctx entropy;
|
||||
size_t last_len, i, reps = 10;
|
||||
size_t i, reps = 10;
|
||||
size_t default_entropy_len;
|
||||
size_t expected_consumed_entropy = 0;
|
||||
|
||||
mbedtls_hmac_drbg_init( &ctx );
|
||||
memset( buf, 0, sizeof( buf ) );
|
||||
|
@ -48,23 +50,29 @@ void hmac_drbg_entropy_usage( int md_alg )
|
|||
|
||||
md_info = mbedtls_md_info_from_type( md_alg );
|
||||
TEST_ASSERT( md_info != NULL );
|
||||
if( mbedtls_md_get_size( md_info ) <= 20 )
|
||||
default_entropy_len = 16;
|
||||
else if( mbedtls_md_get_size( md_info ) <= 28 )
|
||||
default_entropy_len = 24;
|
||||
else
|
||||
default_entropy_len = 32;
|
||||
|
||||
/* Init must use entropy */
|
||||
last_len = entropy.len;
|
||||
TEST_ASSERT( mbedtls_hmac_drbg_seed( &ctx, md_info, mbedtls_test_entropy_func, &entropy,
|
||||
NULL, 0 ) == 0 );
|
||||
TEST_ASSERT( entropy.len < last_len );
|
||||
/* default_entropy_len of entropy, plus half as much for the nonce */
|
||||
expected_consumed_entropy += default_entropy_len * 3 / 2;
|
||||
TEST_EQUAL( sizeof( buf ) - entropy.len, expected_consumed_entropy );
|
||||
|
||||
/* By default, PR is off and reseed_interval is large,
|
||||
* so the next few calls should not use entropy */
|
||||
last_len = entropy.len;
|
||||
for( i = 0; i < reps; i++ )
|
||||
{
|
||||
TEST_ASSERT( mbedtls_hmac_drbg_random( &ctx, out, sizeof( out ) - 4 ) == 0 );
|
||||
TEST_ASSERT( mbedtls_hmac_drbg_random_with_add( &ctx, out, sizeof( out ) - 4,
|
||||
buf, 16 ) == 0 );
|
||||
}
|
||||
TEST_ASSERT( entropy.len == last_len );
|
||||
TEST_EQUAL( sizeof( buf ) - entropy.len, expected_consumed_entropy );
|
||||
|
||||
/* While at it, make sure we didn't write past the requested length */
|
||||
TEST_ASSERT( out[sizeof( out ) - 4] == 0 );
|
||||
|
@ -76,33 +84,34 @@ void hmac_drbg_entropy_usage( int md_alg )
|
|||
* so the next call should reseed */
|
||||
mbedtls_hmac_drbg_set_reseed_interval( &ctx, 2 * reps );
|
||||
TEST_ASSERT( mbedtls_hmac_drbg_random( &ctx, out, sizeof( out ) ) == 0 );
|
||||
TEST_ASSERT( entropy.len < last_len );
|
||||
expected_consumed_entropy += default_entropy_len;
|
||||
TEST_EQUAL( sizeof( buf ) - entropy.len, expected_consumed_entropy );
|
||||
|
||||
/* The new few calls should not reseed */
|
||||
last_len = entropy.len;
|
||||
for( i = 0; i < reps / 2; i++ )
|
||||
{
|
||||
TEST_ASSERT( mbedtls_hmac_drbg_random( &ctx, out, sizeof( out ) ) == 0 );
|
||||
TEST_ASSERT( mbedtls_hmac_drbg_random_with_add( &ctx, out, sizeof( out ) ,
|
||||
buf, 16 ) == 0 );
|
||||
}
|
||||
TEST_ASSERT( entropy.len == last_len );
|
||||
TEST_EQUAL( sizeof( buf ) - entropy.len, expected_consumed_entropy );
|
||||
|
||||
/* Now enable PR, so the next few calls should all reseed */
|
||||
mbedtls_hmac_drbg_set_prediction_resistance( &ctx, MBEDTLS_HMAC_DRBG_PR_ON );
|
||||
TEST_ASSERT( mbedtls_hmac_drbg_random( &ctx, out, sizeof( out ) ) == 0 );
|
||||
TEST_ASSERT( entropy.len < last_len );
|
||||
expected_consumed_entropy += default_entropy_len;
|
||||
TEST_EQUAL( sizeof( buf ) - entropy.len, expected_consumed_entropy );
|
||||
|
||||
/* Finally, check setting entropy_len */
|
||||
mbedtls_hmac_drbg_set_entropy_len( &ctx, 42 );
|
||||
last_len = entropy.len;
|
||||
TEST_ASSERT( mbedtls_hmac_drbg_random( &ctx, out, sizeof( out ) ) == 0 );
|
||||
TEST_ASSERT( (int) last_len - entropy.len == 42 );
|
||||
expected_consumed_entropy += 42;
|
||||
TEST_EQUAL( sizeof( buf ) - entropy.len, expected_consumed_entropy );
|
||||
|
||||
mbedtls_hmac_drbg_set_entropy_len( &ctx, 13 );
|
||||
last_len = entropy.len;
|
||||
TEST_ASSERT( mbedtls_hmac_drbg_random( &ctx, out, sizeof( out ) ) == 0 );
|
||||
TEST_ASSERT( (int) last_len - entropy.len == 13 );
|
||||
expected_consumed_entropy += 13;
|
||||
TEST_EQUAL( sizeof( buf ) - entropy.len, expected_consumed_entropy );
|
||||
|
||||
exit:
|
||||
mbedtls_hmac_drbg_free( &ctx );
|
||||
|
|
|
@ -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_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
|
||||
depends_on:ENTROPY_NONCE_LEN == 0
|
||||
fake_entropy_source:MBEDTLS_ENTROPY_BLOCK_SIZE:0:0:0:MBEDTLS_ENTROPY_BLOCK_SIZE:PSA_SUCCESS
|
||||
|
||||
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: 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: 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
|
||||
entropy_from_nv_seed:MBEDTLS_ENTROPY_MIN_PLATFORM - 1:PSA_ERROR_INSUFFICIENT_ENTROPY
|
||||
|
||||
|
|
|
@ -11,6 +11,12 @@
|
|||
#define ENTROPY_MIN_NV_SEED_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
|
||||
{
|
||||
size_t threshold; /* Minimum bytes to make mbedtls_entropy_func happy */
|
||||
|
|
Loading…
Reference in a new issue