Merge remote-tracking branch 'restricted/pr/538' into mbedtls-2.14-restricted

This commit is contained in:
Simon Butcher 2018-11-29 17:09:42 +00:00
commit ee66bcfc87
6 changed files with 179 additions and 74 deletions

View file

@ -16,6 +16,15 @@ Security
plaintexts and forge RSA signatures. Other asymmetric algorithms may plaintexts and forge RSA signatures. Other asymmetric algorithms may
have been similarly vulnerable. Reported by Eyal Ronen, Robert Gillham, have been similarly vulnerable. Reported by Eyal Ronen, Robert Gillham,
Daniel Genkin, Adi Shamir, David Wong and Yuval Yarom. 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.14.0 branch released 2018-11-19 = mbed TLS 2.14.0 branch released 2018-11-19

View file

@ -239,6 +239,27 @@ int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx,
/** /**
* \brief This function updates the state of the CTR_DRBG context. * \brief This function updates the state of the CTR_DRBG context.
* *
* \param ctx The CTR_DRBG context.
* \param additional The data to update the state with.
* \param add_len Length of \p additional in bytes. This must be at
* most #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT.
*
* \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 * \note If \p add_len is greater than
* #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT, only the first * #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT, only the first
* #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT Bytes are used. * #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT Bytes are used.
@ -247,10 +268,10 @@ int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx,
* \param ctx The CTR_DRBG context. * \param ctx The CTR_DRBG context.
* \param additional The data to update the state with. * \param additional The data to update the state with.
* \param add_len Length of \p additional data. * \param add_len Length of \p additional data.
*
*/ */
void mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context *ctx, 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 * \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 additional Additional data to update state with, or NULL
* \param add_len Length of additional data, or 0 * \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 * \note Additional data is optional, pass NULL and 0 as second
* third argument if no additional data is being used. * third argument if no additional data is being used.
*/ */
void mbedtls_hmac_drbg_update( mbedtls_hmac_drbg_context *ctx, 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) * \brief HMAC_DRBG reseeding (extracts data from entropy source)

View file

@ -299,9 +299,7 @@ static int ctr_drbg_update_internal( mbedtls_ctr_drbg_context *ctx,
* Crypt counter block * Crypt counter block
*/ */
if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, ctx->counter, p ) ) != 0 ) if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, ctx->counter, p ) ) != 0 )
{ goto exit;
return( ret );
}
p += MBEDTLS_CTR_DRBG_BLOCKSIZE; p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
} }
@ -313,12 +311,12 @@ static int ctr_drbg_update_internal( mbedtls_ctr_drbg_context *ctx,
* Update key and counter * Update key and counter
*/ */
if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, tmp, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 ) if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, tmp, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
{ goto exit;
return( ret );
}
memcpy( ctx->counter, tmp + MBEDTLS_CTR_DRBG_KEYSIZE, MBEDTLS_CTR_DRBG_BLOCKSIZE ); memcpy( ctx->counter, tmp + MBEDTLS_CTR_DRBG_KEYSIZE, MBEDTLS_CTR_DRBG_BLOCKSIZE );
return( 0 ); exit:
mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
return( ret );
} }
/* CTR_DRBG_Instantiate with derivation function (SP 800-90A §10.2.1.3.2) /* CTR_DRBG_Instantiate with derivation function (SP 800-90A §10.2.1.3.2)
@ -333,21 +331,36 @@ static int ctr_drbg_update_internal( mbedtls_ctr_drbg_context *ctx,
* and with outputs * and with outputs
* ctx = initial_working_state * ctx = initial_working_state
*/ */
void mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context *ctx, int mbedtls_ctr_drbg_update_ret( mbedtls_ctr_drbg_context *ctx,
const unsigned char *additional, size_t add_len ) const unsigned char *additional,
size_t add_len )
{ {
unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN]; 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_platform_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 /* MAX_INPUT would be more logical here, but we have to match
* block_cipher_df()'s limits since we can't propagate errors */ * block_cipher_df()'s limits since we can't propagate errors */
if( add_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT ) if( add_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
add_len = MBEDTLS_CTR_DRBG_MAX_SEED_INPUT; add_len = MBEDTLS_CTR_DRBG_MAX_SEED_INPUT;
(void) mbedtls_ctr_drbg_update_ret( ctx, additional, add_len );
block_cipher_df( add_input, additional, add_len );
ctr_drbg_update_internal( ctx, add_input );
}
} }
/* CTR_DRBG_Reseed with derivation function (SP 800-90A §10.2.1.4.2) /* CTR_DRBG_Reseed with derivation function (SP 800-90A §10.2.1.4.2)
@ -399,20 +412,18 @@ int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx,
* Reduce to 384 bits * Reduce to 384 bits
*/ */
if( ( ret = block_cipher_df( seed, seed, seedlen ) ) != 0 ) if( ( ret = block_cipher_df( seed, seed, seedlen ) ) != 0 )
{ goto exit;
return( ret );
}
/* /*
* Update state * Update state
*/ */
if( ( ret = ctr_drbg_update_internal( ctx, seed ) ) != 0 ) if( ( ret = ctr_drbg_update_internal( ctx, seed ) ) != 0 )
{ goto exit;
return( ret );
}
ctx->reseed_counter = 1; ctx->reseed_counter = 1;
return( 0 ); exit:
mbedtls_platform_zeroize( seed, sizeof( seed ) );
return( ret );
} }
/* CTR_DRBG_Generate with derivation function (SP 800-90A §10.2.1.5.2) /* CTR_DRBG_Generate with derivation function (SP 800-90A §10.2.1.5.2)
@ -467,13 +478,9 @@ int mbedtls_ctr_drbg_random_with_add( void *p_rng,
if( add_len > 0 ) if( add_len > 0 )
{ {
if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 ) if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 )
{ goto exit;
return( ret );
}
if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 ) if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
{ goto exit;
return( ret );
}
} }
while( output_len > 0 ) while( output_len > 0 )
@ -489,9 +496,7 @@ int mbedtls_ctr_drbg_random_with_add( void *p_rng,
* Crypt counter block * Crypt counter block
*/ */
if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, ctx->counter, tmp ) ) != 0 ) if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, ctx->counter, tmp ) ) != 0 )
{ goto exit;
return( ret );
}
use_len = ( output_len > MBEDTLS_CTR_DRBG_BLOCKSIZE ) ? MBEDTLS_CTR_DRBG_BLOCKSIZE : use_len = ( output_len > MBEDTLS_CTR_DRBG_BLOCKSIZE ) ? MBEDTLS_CTR_DRBG_BLOCKSIZE :
output_len; output_len;
@ -504,12 +509,13 @@ int mbedtls_ctr_drbg_random_with_add( void *p_rng,
} }
if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 ) if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
{ goto exit;
return( ret );
}
ctx->reseed_counter++; ctx->reseed_counter++;
exit:
mbedtls_platform_zeroize( add_input, sizeof( add_input ) );
mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
return( 0 ); return( 0 );
} }
@ -581,7 +587,7 @@ int mbedtls_ctr_drbg_update_seed_file( mbedtls_ctr_drbg_context *ctx, const char
if( fread( buf, 1, n, f ) != n ) if( fread( buf, 1, n, f ) != n )
ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR; ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
else else
mbedtls_ctr_drbg_update( ctx, buf, n ); ret = mbedtls_ctr_drbg_update_ret( ctx, buf, n );
fclose( f ); fclose( f );

View file

@ -66,29 +66,56 @@ void mbedtls_hmac_drbg_init( mbedtls_hmac_drbg_context *ctx )
/* /*
* HMAC_DRBG update, using optional additional data (10.1.2.2) * HMAC_DRBG update, using optional additional data (10.1.2.2)
*/ */
void mbedtls_hmac_drbg_update( mbedtls_hmac_drbg_context *ctx, int mbedtls_hmac_drbg_update_ret( mbedtls_hmac_drbg_context *ctx,
const unsigned char *additional, size_t add_len ) const unsigned char *additional,
size_t add_len )
{ {
size_t md_len = mbedtls_md_get_size( ctx->md_ctx.md_info ); 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 rounds = ( additional != NULL && add_len != 0 ) ? 2 : 1;
unsigned char sep[1]; unsigned char sep[1];
unsigned char K[MBEDTLS_MD_MAX_SIZE]; unsigned char K[MBEDTLS_MD_MAX_SIZE];
int ret;
for( sep[0] = 0; sep[0] < rounds; sep[0]++ ) for( sep[0] = 0; sep[0] < rounds; sep[0]++ )
{ {
/* Step 1 or 4 */ /* Step 1 or 4 */
mbedtls_md_hmac_reset( &ctx->md_ctx ); if( ( ret = mbedtls_md_hmac_reset( &ctx->md_ctx ) ) != 0 )
mbedtls_md_hmac_update( &ctx->md_ctx, ctx->V, md_len ); goto exit;
mbedtls_md_hmac_update( &ctx->md_ctx, sep, 1 ); 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 ) 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 */ /* Step 2 or 5 */
mbedtls_md_hmac_starts( &ctx->md_ctx, K, md_len ); if( ( ret = mbedtls_md_hmac_starts( &ctx->md_ctx, K, md_len ) ) != 0 )
mbedtls_md_hmac_update( &ctx->md_ctx, ctx->V, md_len ); goto exit;
mbedtls_md_hmac_finish( &ctx->md_ctx, ctx->V ); 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_platform_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 );
} }
/* /*
@ -108,10 +135,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 * 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. * 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 ) ); 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 ); return( 0 );
} }
@ -124,6 +154,7 @@ int mbedtls_hmac_drbg_reseed( mbedtls_hmac_drbg_context *ctx,
{ {
unsigned char seed[MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT]; unsigned char seed[MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT];
size_t seedlen; size_t seedlen;
int ret;
/* III. Check input length */ /* III. Check input length */
if( len > MBEDTLS_HMAC_DRBG_MAX_INPUT || if( len > MBEDTLS_HMAC_DRBG_MAX_INPUT ||
@ -135,7 +166,8 @@ int mbedtls_hmac_drbg_reseed( mbedtls_hmac_drbg_context *ctx,
memset( seed, 0, MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT ); memset( seed, 0, MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT );
/* IV. Gather entropy_len bytes of entropy for the seed */ /* 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 ); return( MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED );
seedlen = ctx->entropy_len; seedlen = ctx->entropy_len;
@ -148,13 +180,16 @@ int mbedtls_hmac_drbg_reseed( mbedtls_hmac_drbg_context *ctx,
} }
/* 2. Update state */ /* 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 */ /* 3. Reset reseed_counter */
ctx->reseed_counter = 1; ctx->reseed_counter = 1;
exit:
/* 4. Done */ /* 4. Done */
return( 0 ); mbedtls_platform_zeroize( seed, seedlen );
return( ret );
} }
/* /*
@ -180,7 +215,8 @@ int mbedtls_hmac_drbg_seed( mbedtls_hmac_drbg_context *ctx,
* Use the V memory location, which is currently all 0, to initialize the * 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. * 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 ); memset( ctx->V, 0x01, md_size );
ctx->f_entropy = f_entropy; ctx->f_entropy = f_entropy;
@ -273,16 +309,24 @@ int mbedtls_hmac_drbg_random_with_add( void *p_rng,
/* 2. Use additional data if any */ /* 2. Use additional data if any */
if( additional != NULL && add_len != 0 ) 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 */ /* 3, 4, 5. Generate bytes */
while( left != 0 ) while( left != 0 )
{ {
size_t use_len = left > md_len ? md_len : left; size_t use_len = left > md_len ? md_len : left;
mbedtls_md_hmac_reset( &ctx->md_ctx ); if( ( ret = mbedtls_md_hmac_reset( &ctx->md_ctx ) ) != 0 )
mbedtls_md_hmac_update( &ctx->md_ctx, ctx->V, md_len ); goto exit;
mbedtls_md_hmac_finish( &ctx->md_ctx, ctx->V ); 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 ); memcpy( out, ctx->V, use_len );
out += use_len; out += use_len;
@ -290,13 +334,16 @@ int mbedtls_hmac_drbg_random_with_add( void *p_rng,
} }
/* 6. Update */ /* 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 */ /* 7. Update reseed counter */
ctx->reseed_counter++; ctx->reseed_counter++;
exit:
/* 8. Done */ /* 8. Done */
return( 0 ); return( ret );
} }
/* /*
@ -388,7 +435,7 @@ int mbedtls_hmac_drbg_update_seed_file( mbedtls_hmac_drbg_context *ctx, const ch
if( fread( buf, 1, n, f ) != n ) if( fread( buf, 1, n, f ) != n )
ret = MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR; ret = MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR;
else else
mbedtls_hmac_drbg_update( ctx, buf, n ); ret = mbedtls_hmac_drbg_update_ret( ctx, buf, n );
fclose( f ); fclose( f );

View file

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