Merge remote-tracking branch 'restricted/pr/513' into mbedtls-2.7-restricted

This commit is contained in:
Simon Butcher 2018-11-29 17:27:35 +00:00
commit 4303f7619e
6 changed files with 177 additions and 70 deletions

View File

@ -16,6 +16,15 @@ Security
plaintexts and forge RSA signatures. Other asymmetric algorithms may
have been similarly vulnerable. Reported by Eyal Ronen, Robert Gillham,
Daniel Genkin, Adi Shamir, David Wong and Yuval Yarom.
* Wipe sensitive buffers on the stack in the CTR_DRBG and HMAC_DRBG
modules.
API Changes
* The new functions mbedtls_ctr_drbg_update_ret() and
mbedtls_hmac_drbg_update_ret() are similar to mbedtls_ctr_drbg_update()
and mbedtls_hmac_drbg_update() respectively, but the new functions
report errors whereas the old functions return void. We recommend that
applications use the new functions.
= mbed TLS 2.7.7 branch released 2018-11-19

View File

@ -227,14 +227,37 @@ int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx,
*
* \param ctx The CTR_DRBG context.
* \param additional The data to update the state with.
* \param add_len Length of \p additional data.
* \param add_len Length of \p additional in bytes. This must be at
* most #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT.
*
* \note If \p add_len is greater than #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT,
* only the first #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT Bytes are used.
* \return \c 0 on success.
* \return #MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG if
* \p add_len is more than
* #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT.
* \return An error from the underlying AES cipher on failure.
*/
int mbedtls_ctr_drbg_update_ret( mbedtls_ctr_drbg_context *ctx,
const unsigned char *additional,
size_t add_len );
/**
* \brief This function updates the state of the CTR_DRBG context.
*
* \warning This function cannot report errors. You should use
* mbedtls_ctr_drbg_update_ret() instead.
*
* \note If \p add_len is greater than
* #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT, only the first
* #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT Bytes are used.
* The remaining Bytes are silently discarded.
*
* \param ctx The CTR_DRBG context.
* \param additional The data to update the state with.
* \param add_len Length of \p additional data.
*/
void mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context *ctx,
const unsigned char *additional, size_t add_len );
const unsigned char *additional,
size_t add_len );
/**
* \brief This function updates a CTR_DRBG instance with additional

View File

@ -195,11 +195,31 @@ void mbedtls_hmac_drbg_set_reseed_interval( mbedtls_hmac_drbg_context *ctx,
* \param additional Additional data to update state with, or NULL
* \param add_len Length of additional data, or 0
*
* \return \c 0 on success, or an error from the underlying
* hash calculation.
*
* \note Additional data is optional, pass NULL and 0 as second
* third argument if no additional data is being used.
*/
int mbedtls_hmac_drbg_update_ret( mbedtls_hmac_drbg_context *ctx,
const unsigned char *additional, size_t add_len );
/**
* \brief HMAC_DRBG update state
*
* \warning This function cannot report errors. You should use
* mbedtls_hmac_drbg_update_ret() instead.
*
* \param ctx HMAC_DRBG context
* \param additional Additional data to update state with, or NULL
* \param add_len Length of additional data, or 0
*
* \note Additional data is optional, pass NULL and 0 as second
* third argument if no additional data is being used.
*/
void mbedtls_hmac_drbg_update( mbedtls_hmac_drbg_context *ctx,
const unsigned char *additional, size_t add_len );
const unsigned char *additional,
size_t add_len );
/**
* \brief HMAC_DRBG reseeding (extracts data from entropy source)

View File

@ -283,9 +283,7 @@ static int ctr_drbg_update_internal( mbedtls_ctr_drbg_context *ctx,
* Crypt counter block
*/
if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, ctx->counter, p ) ) != 0 )
{
return( ret );
}
goto exit;
p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
}
@ -297,29 +295,44 @@ static int ctr_drbg_update_internal( mbedtls_ctr_drbg_context *ctx,
* Update key and counter
*/
if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, tmp, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
{
return( ret );
}
goto exit;
memcpy( ctx->counter, tmp + MBEDTLS_CTR_DRBG_KEYSIZE, MBEDTLS_CTR_DRBG_BLOCKSIZE );
return( 0 );
exit:
mbedtls_zeroize( tmp, sizeof( tmp ) );
return( ret );
}
void mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context *ctx,
const unsigned char *additional, size_t add_len )
int mbedtls_ctr_drbg_update_ret( mbedtls_ctr_drbg_context *ctx,
const unsigned char *additional,
size_t add_len )
{
unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
int ret;
if( add_len > 0 )
{
if( add_len == 0 )
return( 0 );
if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 )
goto exit;
if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
goto exit;
exit:
mbedtls_zeroize( add_input, sizeof( add_input ) );
return( ret );
}
/* Deprecated function, kept for backward compatibility. */
void mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context *ctx,
const unsigned char *additional,
size_t add_len )
{
/* MAX_INPUT would be more logical here, but we have to match
* block_cipher_df()'s limits since we can't propagate errors */
if( add_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
add_len = MBEDTLS_CTR_DRBG_MAX_SEED_INPUT;
block_cipher_df( add_input, additional, add_len );
ctr_drbg_update_internal( ctx, add_input );
}
(void) mbedtls_ctr_drbg_update_ret( ctx, additional, add_len );
}
int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx,
@ -359,20 +372,18 @@ int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx,
* Reduce to 384 bits
*/
if( ( ret = block_cipher_df( seed, seed, seedlen ) ) != 0 )
{
return( ret );
}
goto exit;
/*
* Update state
*/
if( ( ret = ctr_drbg_update_internal( ctx, seed ) ) != 0 )
{
return( ret );
}
goto exit;
ctx->reseed_counter = 1;
return( 0 );
exit:
mbedtls_zeroize( seed, sizeof( seed ) );
return( ret );
}
int mbedtls_ctr_drbg_random_with_add( void *p_rng,
@ -408,13 +419,9 @@ int mbedtls_ctr_drbg_random_with_add( void *p_rng,
if( add_len > 0 )
{
if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 )
{
return( ret );
}
goto exit;
if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
{
return( ret );
}
goto exit;
}
while( output_len > 0 )
@ -430,9 +437,7 @@ int mbedtls_ctr_drbg_random_with_add( void *p_rng,
* Crypt counter block
*/
if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, ctx->counter, tmp ) ) != 0 )
{
return( ret );
}
goto exit;
use_len = ( output_len > MBEDTLS_CTR_DRBG_BLOCKSIZE ) ? MBEDTLS_CTR_DRBG_BLOCKSIZE :
output_len;
@ -445,12 +450,13 @@ int mbedtls_ctr_drbg_random_with_add( void *p_rng,
}
if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
{
return( ret );
}
goto exit;
ctx->reseed_counter++;
exit:
mbedtls_zeroize( add_input, sizeof( add_input ) );
mbedtls_zeroize( tmp, sizeof( tmp ) );
return( 0 );
}
@ -522,7 +528,7 @@ int mbedtls_ctr_drbg_update_seed_file( mbedtls_ctr_drbg_context *ctx, const char
if( fread( buf, 1, n, f ) != n )
ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
else
mbedtls_ctr_drbg_update( ctx, buf, n );
ret = mbedtls_ctr_drbg_update_ret( ctx, buf, n );
fclose( f );

View File

@ -70,29 +70,56 @@ void mbedtls_hmac_drbg_init( mbedtls_hmac_drbg_context *ctx )
/*
* HMAC_DRBG update, using optional additional data (10.1.2.2)
*/
void mbedtls_hmac_drbg_update( mbedtls_hmac_drbg_context *ctx,
const unsigned char *additional, size_t add_len )
int mbedtls_hmac_drbg_update_ret( mbedtls_hmac_drbg_context *ctx,
const unsigned char *additional,
size_t add_len )
{
size_t md_len = mbedtls_md_get_size( ctx->md_ctx.md_info );
unsigned char rounds = ( additional != NULL && add_len != 0 ) ? 2 : 1;
unsigned char sep[1];
unsigned char K[MBEDTLS_MD_MAX_SIZE];
int ret;
for( sep[0] = 0; sep[0] < rounds; sep[0]++ )
{
/* Step 1 or 4 */
mbedtls_md_hmac_reset( &ctx->md_ctx );
mbedtls_md_hmac_update( &ctx->md_ctx, ctx->V, md_len );
mbedtls_md_hmac_update( &ctx->md_ctx, sep, 1 );
if( ( ret = mbedtls_md_hmac_reset( &ctx->md_ctx ) ) != 0 )
goto exit;
if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx,
ctx->V, md_len ) ) != 0 )
goto exit;
if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx,
sep, 1 ) ) != 0 )
goto exit;
if( rounds == 2 )
mbedtls_md_hmac_update( &ctx->md_ctx, additional, add_len );
mbedtls_md_hmac_finish( &ctx->md_ctx, K );
{
if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx,
additional, add_len ) ) != 0 )
goto exit;
}
if( ( ret = mbedtls_md_hmac_finish( &ctx->md_ctx, K ) ) != 0 )
goto exit;
/* Step 2 or 5 */
mbedtls_md_hmac_starts( &ctx->md_ctx, K, md_len );
mbedtls_md_hmac_update( &ctx->md_ctx, ctx->V, md_len );
mbedtls_md_hmac_finish( &ctx->md_ctx, ctx->V );
if( ( ret = mbedtls_md_hmac_starts( &ctx->md_ctx, K, md_len ) ) != 0 )
goto exit;
if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx,
ctx->V, md_len ) ) != 0 )
goto exit;
if( ( ret = mbedtls_md_hmac_finish( &ctx->md_ctx, ctx->V ) ) != 0 )
goto exit;
}
exit:
mbedtls_zeroize( K, sizeof( K ) );
return( ret );
}
void mbedtls_hmac_drbg_update( mbedtls_hmac_drbg_context *ctx,
const unsigned char *additional,
size_t add_len )
{
(void) mbedtls_hmac_drbg_update_ret( ctx, additional, add_len );
}
/*
@ -112,10 +139,13 @@ int mbedtls_hmac_drbg_seed_buf( mbedtls_hmac_drbg_context *ctx,
* Use the V memory location, which is currently all 0, to initialize the
* MD context with an all-zero key. Then set V to its initial value.
*/
mbedtls_md_hmac_starts( &ctx->md_ctx, ctx->V, mbedtls_md_get_size( md_info ) );
if( ( ret = mbedtls_md_hmac_starts( &ctx->md_ctx, ctx->V,
mbedtls_md_get_size( md_info ) ) ) != 0 )
return( ret );
memset( ctx->V, 0x01, mbedtls_md_get_size( md_info ) );
mbedtls_hmac_drbg_update( ctx, data, data_len );
if( ( ret = mbedtls_hmac_drbg_update_ret( ctx, data, data_len ) ) != 0 )
return( ret );
return( 0 );
}
@ -128,6 +158,7 @@ int mbedtls_hmac_drbg_reseed( mbedtls_hmac_drbg_context *ctx,
{
unsigned char seed[MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT];
size_t seedlen;
int ret;
/* III. Check input length */
if( len > MBEDTLS_HMAC_DRBG_MAX_INPUT ||
@ -139,7 +170,8 @@ int mbedtls_hmac_drbg_reseed( mbedtls_hmac_drbg_context *ctx,
memset( seed, 0, MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT );
/* IV. Gather entropy_len bytes of entropy for the seed */
if( ctx->f_entropy( ctx->p_entropy, seed, ctx->entropy_len ) != 0 )
if( ( ret = ctx->f_entropy( ctx->p_entropy,
seed, ctx->entropy_len ) ) != 0 )
return( MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED );
seedlen = ctx->entropy_len;
@ -152,13 +184,16 @@ int mbedtls_hmac_drbg_reseed( mbedtls_hmac_drbg_context *ctx,
}
/* 2. Update state */
mbedtls_hmac_drbg_update( ctx, seed, seedlen );
if( ( ret = mbedtls_hmac_drbg_update_ret( ctx, seed, seedlen ) ) != 0 )
goto exit;
/* 3. Reset reseed_counter */
ctx->reseed_counter = 1;
exit:
/* 4. Done */
return( 0 );
mbedtls_zeroize( seed, seedlen );
return( ret );
}
/*
@ -184,7 +219,8 @@ int mbedtls_hmac_drbg_seed( mbedtls_hmac_drbg_context *ctx,
* Use the V memory location, which is currently all 0, to initialize the
* MD context with an all-zero key. Then set V to its initial value.
*/
mbedtls_md_hmac_starts( &ctx->md_ctx, ctx->V, md_size );
if( ( ret = mbedtls_md_hmac_starts( &ctx->md_ctx, ctx->V, md_size ) ) != 0 )
return( ret );
memset( ctx->V, 0x01, md_size );
ctx->f_entropy = f_entropy;
@ -277,16 +313,24 @@ int mbedtls_hmac_drbg_random_with_add( void *p_rng,
/* 2. Use additional data if any */
if( additional != NULL && add_len != 0 )
mbedtls_hmac_drbg_update( ctx, additional, add_len );
{
if( ( ret = mbedtls_hmac_drbg_update_ret( ctx,
additional, add_len ) ) != 0 )
goto exit;
}
/* 3, 4, 5. Generate bytes */
while( left != 0 )
{
size_t use_len = left > md_len ? md_len : left;
mbedtls_md_hmac_reset( &ctx->md_ctx );
mbedtls_md_hmac_update( &ctx->md_ctx, ctx->V, md_len );
mbedtls_md_hmac_finish( &ctx->md_ctx, ctx->V );
if( ( ret = mbedtls_md_hmac_reset( &ctx->md_ctx ) ) != 0 )
goto exit;
if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx,
ctx->V, md_len ) ) != 0 )
goto exit;
if( ( ret = mbedtls_md_hmac_finish( &ctx->md_ctx, ctx->V ) ) != 0 )
goto exit;
memcpy( out, ctx->V, use_len );
out += use_len;
@ -294,13 +338,16 @@ int mbedtls_hmac_drbg_random_with_add( void *p_rng,
}
/* 6. Update */
mbedtls_hmac_drbg_update( ctx, additional, add_len );
if( ( ret = mbedtls_hmac_drbg_update_ret( ctx,
additional, add_len ) ) != 0 )
goto exit;
/* 7. Update reseed counter */
ctx->reseed_counter++;
exit:
/* 8. Done */
return( 0 );
return( ret );
}
/*
@ -392,7 +439,7 @@ int mbedtls_hmac_drbg_update_seed_file( mbedtls_hmac_drbg_context *ctx, const ch
if( fread( buf, 1, n, f ) != n )
ret = MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR;
else
mbedtls_hmac_drbg_update( ctx, buf, n );
ret = mbedtls_hmac_drbg_update_ret( ctx, buf, n );
fclose( f );

View File

@ -177,9 +177,11 @@ void ctr_drbg_entropy_usage( )
}
TEST_ASSERT( last_idx == test_offset_idx );
/* Call update with too much data (sizeof entropy > MAX(_SEED)_INPUT)
* (just make sure it doesn't cause memory corruption) */
mbedtls_ctr_drbg_update( &ctx, entropy, sizeof( entropy ) );
/* Call update with too much data (sizeof entropy > MAX(_SEED)_INPUT).
* Make sure it's detected as an error and doesn't cause memory
* corruption. */
TEST_ASSERT( mbedtls_ctr_drbg_update_ret(
&ctx, entropy, sizeof( entropy ) ) != 0 );
/* Now enable PR, so the next few calls should all reseed */
mbedtls_ctr_drbg_set_prediction_resistance( &ctx, MBEDTLS_CTR_DRBG_PR_ON );