mirror of
https://github.com/yuzu-emu/mbedtls.git
synced 2024-11-27 05:24:15 +01:00
Correct deterministic ECDSA behavior
We were still reusing the internal HMAC-DRBG of the deterministic ECDSA for blinding. This meant that with cryptographically low likelyhood the result was not the same signature as the one the deterministic ECDSA algorithm has to produce (however it is still a valid ECDSA signature). To correct this we seed a second HMAC-DRBG with the same seed to restore correct behavior. We also apply a label to avoid reusing the bits of the ephemeral key for a different purpose and reduce the chance that they leak. This workaround can't be implemented in the restartable case without penalising the case where external RNG is available or completely defeating the purpose of the restartable feature, therefore in this case the small chance of incorrect behavior remains.
This commit is contained in:
parent
ba66faf167
commit
7b774483bf
@ -195,12 +195,16 @@ static int ecdsa_sign_det_internal( mbedtls_ecp_group *grp, mbedtls_mpi *r,
|
||||
size_t grp_len = ( grp->nbits + 7 ) / 8;
|
||||
const mbedtls_md_info_t *md_info;
|
||||
mbedtls_mpi h;
|
||||
/* Variables for deterministic blinding fallback */
|
||||
const char* blind_label = "BLINDING CONTEXT";
|
||||
mbedtls_hmac_drbg_context rng_ctx_blind;
|
||||
|
||||
if( ( md_info = mbedtls_md_info_from_type( md_alg ) ) == NULL )
|
||||
return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
|
||||
|
||||
mbedtls_mpi_init( &h );
|
||||
mbedtls_hmac_drbg_init( &rng_ctx );
|
||||
mbedtls_hmac_drbg_init( &rng_ctx_blind );
|
||||
|
||||
/* Use private key and message hash (reduced) to initialize HMAC_DRBG */
|
||||
MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( d, data, grp_len ) );
|
||||
@ -213,18 +217,38 @@ static int ecdsa_sign_det_internal( mbedtls_ecp_group *grp, mbedtls_mpi *r,
|
||||
mbedtls_hmac_drbg_random, &rng_ctx,
|
||||
f_rng_blind, p_rng_blind );
|
||||
else
|
||||
{
|
||||
/*
|
||||
* Use the same RNG for both blinding and ephemeral key generation.
|
||||
* Since the RNG output is always the same for the same key and message,
|
||||
* this limits the efficiency of blinding and leaks information through
|
||||
* side channels.
|
||||
* To avoid reusing rng_ctx and risking incorrect behavior we seed a
|
||||
* second HMAC-DRBG with the same seed. We also apply a label to avoid
|
||||
* reusing the bits of the ephemeral key for blinding and eliminate the
|
||||
* risk that they leak this way.
|
||||
*/
|
||||
|
||||
mbedtls_hmac_drbg_seed_buf( &rng_ctx_blind, md_info,
|
||||
data, 2 * grp_len );
|
||||
ret = mbedtls_hmac_drbg_update_ret( &rng_ctx_blind,
|
||||
(const unsigned char*) blind_label,
|
||||
strlen( blind_label ) );
|
||||
if( ret != 0 )
|
||||
goto cleanup;
|
||||
|
||||
/*
|
||||
* Since the output of the RNGs is always the same for the same key and
|
||||
* message, this limits the efficiency of blinding and leaks information
|
||||
* through side channels. After mbedtls_ecdsa_sign_det() is removed NULL
|
||||
* won't be a valid value for f_rng_blind anymore. Therefore it should
|
||||
* be checked by the caller and this branch and check can be removed.
|
||||
*/
|
||||
ret = ecdsa_sign_internal( grp, r, s, d, buf, blen,
|
||||
mbedtls_hmac_drbg_random, &rng_ctx,
|
||||
mbedtls_hmac_drbg_random, &rng_ctx );
|
||||
mbedtls_hmac_drbg_random, &rng_ctx_blind );
|
||||
|
||||
}
|
||||
|
||||
cleanup:
|
||||
mbedtls_hmac_drbg_free( &rng_ctx );
|
||||
mbedtls_hmac_drbg_free( &rng_ctx_blind );
|
||||
mbedtls_mpi_free( &h );
|
||||
|
||||
return( ret );
|
||||
|
Loading…
Reference in New Issue
Block a user