Merge pull request #820 from gilles-peskine-arm/mpi_fill_random-constant_time_comparison-development-restricted
Fix small timing side channel in ECDSA ephemeral key generation
This commit is contained in:
commit
6f1dbe615c
2 changed files with 17 additions and 3 deletions
7
ChangeLog.d/ecdsa-random-leading-zeros.txt
Normal file
7
ChangeLog.d/ecdsa-random-leading-zeros.txt
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
Security
|
||||||
|
* Fix a potential side channel vulnerability in ECDSA ephemeral key generation.
|
||||||
|
An adversary who is capable of very precise timing measurements could
|
||||||
|
learn partial information about the leading bits of the nonce used for the
|
||||||
|
signature, allowing the recovery of the private key after observing a
|
||||||
|
large number of signature operations. This completes a partial fix in
|
||||||
|
Mbed TLS 2.20.0.
|
|
@ -2466,9 +2466,10 @@ int mbedtls_mpi_random( mbedtls_mpi *X,
|
||||||
{
|
{
|
||||||
int ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
|
int ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
|
||||||
int count;
|
int count;
|
||||||
unsigned cmp = 0;
|
unsigned lt_lower = 1, lt_upper = 0;
|
||||||
size_t n_bits = mbedtls_mpi_bitlen( N );
|
size_t n_bits = mbedtls_mpi_bitlen( N );
|
||||||
size_t n_bytes = ( n_bits + 7 ) / 8;
|
size_t n_bytes = ( n_bits + 7 ) / 8;
|
||||||
|
mbedtls_mpi lower_bound;
|
||||||
|
|
||||||
if( min < 0 )
|
if( min < 0 )
|
||||||
return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
|
return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
|
||||||
|
@ -2494,10 +2495,14 @@ int mbedtls_mpi_random( mbedtls_mpi *X,
|
||||||
*/
|
*/
|
||||||
count = ( n_bytes > 4 ? 30 : 250 );
|
count = ( n_bytes > 4 ? 30 : 250 );
|
||||||
|
|
||||||
|
mbedtls_mpi_init( &lower_bound );
|
||||||
|
|
||||||
/* Ensure that target MPI has exactly the same number of limbs
|
/* Ensure that target MPI has exactly the same number of limbs
|
||||||
* as the upper bound, even if the upper bound has leading zeros.
|
* as the upper bound, even if the upper bound has leading zeros.
|
||||||
* This is necessary for the mbedtls_mpi_lt_mpi_ct() check. */
|
* This is necessary for the mbedtls_mpi_lt_mpi_ct() check. */
|
||||||
MBEDTLS_MPI_CHK( mbedtls_mpi_resize_clear( X, N->n ) );
|
MBEDTLS_MPI_CHK( mbedtls_mpi_resize_clear( X, N->n ) );
|
||||||
|
MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &lower_bound, N->n ) );
|
||||||
|
MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &lower_bound, min ) );
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Match the procedure given in RFC 6979 §3.3 (deterministic ECDSA)
|
* Match the procedure given in RFC 6979 §3.3 (deterministic ECDSA)
|
||||||
|
@ -2518,11 +2523,13 @@ int mbedtls_mpi_random( mbedtls_mpi *X,
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
MBEDTLS_MPI_CHK( mbedtls_mpi_lt_mpi_ct( X, N, &cmp ) );
|
MBEDTLS_MPI_CHK( mbedtls_mpi_lt_mpi_ct( X, &lower_bound, <_lower ) );
|
||||||
|
MBEDTLS_MPI_CHK( mbedtls_mpi_lt_mpi_ct( X, N, <_upper ) );
|
||||||
}
|
}
|
||||||
while( mbedtls_mpi_cmp_int( X, min ) < 0 || cmp != 1 );
|
while( lt_lower != 0 || lt_upper == 0 );
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
|
mbedtls_mpi_free( &lower_bound );
|
||||||
return( ret );
|
return( ret );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue