mirror of
https://github.com/yuzu-emu/mbedtls.git
synced 2025-01-07 06:15:37 +00:00
Bignum: Fix prime validation vulnerability
The input distribution to primality testing functions is completely different when used for generating primes and when for validating primes. The constants used in the library are geared towards the prime generation use case and are weak when used for validation. (Maliciously constructed composite numbers can pass the test with high probability) The mbedtls_mpi_is_prime() function is in the public API and although it is not documented, it is reasonable to assume that the primary use case is validating primes. The RSA module too uses it for validating key material.
This commit is contained in:
parent
02a8b0e232
commit
9dc5b7a27b
|
@ -2043,12 +2043,12 @@ cleanup:
|
|||
/*
|
||||
* Miller-Rabin pseudo-primality test (HAC 4.24)
|
||||
*/
|
||||
static int mpi_miller_rabin( const mbedtls_mpi *X,
|
||||
static int mpi_miller_rabin( const mbedtls_mpi *X, size_t rounds,
|
||||
int (*f_rng)(void *, unsigned char *, size_t),
|
||||
void *p_rng )
|
||||
{
|
||||
int ret, count;
|
||||
size_t i, j, k, n, s;
|
||||
size_t i, j, k, s;
|
||||
mbedtls_mpi W, R, T, A, RR;
|
||||
|
||||
mbedtls_mpi_init( &W ); mbedtls_mpi_init( &R ); mbedtls_mpi_init( &T ); mbedtls_mpi_init( &A );
|
||||
|
@ -2064,14 +2064,8 @@ static int mpi_miller_rabin( const mbedtls_mpi *X,
|
|||
MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &R, s ) );
|
||||
|
||||
i = mbedtls_mpi_bitlen( X );
|
||||
/*
|
||||
* HAC, table 4.4
|
||||
*/
|
||||
n = ( ( i >= 1300 ) ? 2 : ( i >= 850 ) ? 3 :
|
||||
( i >= 650 ) ? 4 : ( i >= 350 ) ? 8 :
|
||||
( i >= 250 ) ? 12 : ( i >= 150 ) ? 18 : 27 );
|
||||
|
||||
for( i = 0; i < n; i++ )
|
||||
for( i = 0; i < rounds; i++ )
|
||||
{
|
||||
/*
|
||||
* pick a random A, 1 < A < |X| - 1
|
||||
|
@ -2138,7 +2132,7 @@ cleanup:
|
|||
/*
|
||||
* Pseudo-primality test: small factors, then Miller-Rabin
|
||||
*/
|
||||
int mbedtls_mpi_is_prime( const mbedtls_mpi *X,
|
||||
int mpi_is_prime_internal( const mbedtls_mpi *X, int rounds,
|
||||
int (*f_rng)(void *, unsigned char *, size_t),
|
||||
void *p_rng )
|
||||
{
|
||||
|
@ -2164,7 +2158,17 @@ int mbedtls_mpi_is_prime( const mbedtls_mpi *X,
|
|||
return( ret );
|
||||
}
|
||||
|
||||
return( mpi_miller_rabin( &XX, f_rng, p_rng ) );
|
||||
return( mpi_miller_rabin( &XX, rounds, f_rng, p_rng ) );
|
||||
}
|
||||
|
||||
/*
|
||||
* Pseudo-primality test, error probability 2^-80
|
||||
*/
|
||||
int mbedtls_mpi_is_prime( const mbedtls_mpi *X,
|
||||
int (*f_rng)(void *, unsigned char *, size_t),
|
||||
void *p_rng )
|
||||
{
|
||||
return mpi_is_prime_internal( X, 40, f_rng, p_rng );
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -2176,6 +2180,7 @@ int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int dh_flag,
|
|||
{
|
||||
int ret;
|
||||
size_t k, n;
|
||||
int rounds;
|
||||
mbedtls_mpi_uint r;
|
||||
mbedtls_mpi Y;
|
||||
|
||||
|
@ -2186,6 +2191,13 @@ int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int dh_flag,
|
|||
|
||||
n = BITS_TO_LIMBS( nbits );
|
||||
|
||||
/*
|
||||
* 2^-80 error probability, number of rounds chosen per HAC, table 4.4
|
||||
*/
|
||||
rounds = ( ( nbits >= 1300 ) ? 2 : ( nbits >= 850 ) ? 3 :
|
||||
( nbits >= 650 ) ? 4 : ( nbits >= 350 ) ? 8 :
|
||||
( nbits >= 250 ) ? 12 : ( nbits >= 150 ) ? 18 : 27 );
|
||||
|
||||
MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
|
||||
|
||||
k = mbedtls_mpi_bitlen( X );
|
||||
|
@ -2197,7 +2209,7 @@ int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int dh_flag,
|
|||
|
||||
if( dh_flag == 0 )
|
||||
{
|
||||
while( ( ret = mbedtls_mpi_is_prime( X, f_rng, p_rng ) ) != 0 )
|
||||
while( ( ret = mpi_is_prime_internal( X, rounds, f_rng, p_rng ) ) != 0 )
|
||||
{
|
||||
if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
|
||||
goto cleanup;
|
||||
|
@ -2233,8 +2245,10 @@ int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int dh_flag,
|
|||
*/
|
||||
if( ( ret = mpi_check_small_factors( X ) ) == 0 &&
|
||||
( ret = mpi_check_small_factors( &Y ) ) == 0 &&
|
||||
( ret = mpi_miller_rabin( X, f_rng, p_rng ) ) == 0 &&
|
||||
( ret = mpi_miller_rabin( &Y, f_rng, p_rng ) ) == 0 )
|
||||
( ret = mpi_miller_rabin( X, rounds, f_rng, p_rng ) )
|
||||
== 0 &&
|
||||
( ret = mpi_miller_rabin( &Y, rounds, f_rng, p_rng ) )
|
||||
== 0 )
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue