mirror of
https://github.com/Mbed-TLS/mbedtls.git
synced 2025-07-28 00:21:48 +03:00
Merge pull request #4644 from gilles-peskine-arm/mpi_montmul-null-2.x
Backport 2.x: Fix several bugs with the value 0 in bignum
This commit is contained in:
111
library/bignum.c
111
library/bignum.c
@ -203,7 +203,13 @@ static int mbedtls_mpi_resize_clear( mbedtls_mpi *X, size_t limbs )
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy the contents of Y into X
|
||||
* Copy the contents of Y into X.
|
||||
*
|
||||
* This function is not constant-time. Leading zeros in Y may be removed.
|
||||
*
|
||||
* Ensure that X does not shrink. This is not guaranteed by the public API,
|
||||
* but some code in the bignum module relies on this property, for example
|
||||
* in mbedtls_mpi_exp_mod().
|
||||
*/
|
||||
int mbedtls_mpi_copy( mbedtls_mpi *X, const mbedtls_mpi *Y )
|
||||
{
|
||||
@ -217,7 +223,11 @@ int mbedtls_mpi_copy( mbedtls_mpi *X, const mbedtls_mpi *Y )
|
||||
|
||||
if( Y->n == 0 )
|
||||
{
|
||||
mbedtls_mpi_free( X );
|
||||
if( X->n != 0 )
|
||||
{
|
||||
X->s = 1;
|
||||
memset( X->p, 0, X->n * ciL );
|
||||
}
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
@ -502,6 +512,12 @@ int mbedtls_mpi_read_string( mbedtls_mpi *X, int radix, const char *s )
|
||||
|
||||
mbedtls_mpi_init( &T );
|
||||
|
||||
if( s[0] == 0 )
|
||||
{
|
||||
mbedtls_mpi_free( X );
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
if( s[0] == '-' )
|
||||
{
|
||||
++s;
|
||||
@ -1625,6 +1641,7 @@ int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi
|
||||
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
|
||||
size_t i, j;
|
||||
mbedtls_mpi TA, TB;
|
||||
int result_is_zero = 0;
|
||||
MPI_VALIDATE_RET( X != NULL );
|
||||
MPI_VALIDATE_RET( A != NULL );
|
||||
MPI_VALIDATE_RET( B != NULL );
|
||||
@ -1637,10 +1654,14 @@ int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi
|
||||
for( i = A->n; i > 0; i-- )
|
||||
if( A->p[i - 1] != 0 )
|
||||
break;
|
||||
if( i == 0 )
|
||||
result_is_zero = 1;
|
||||
|
||||
for( j = B->n; j > 0; j-- )
|
||||
if( B->p[j - 1] != 0 )
|
||||
break;
|
||||
if( j == 0 )
|
||||
result_is_zero = 1;
|
||||
|
||||
MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + j ) );
|
||||
MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
|
||||
@ -1648,7 +1669,14 @@ int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi
|
||||
for( ; j > 0; j-- )
|
||||
mpi_mul_hlp( i, A->p, X->p + j - 1, B->p[j - 1] );
|
||||
|
||||
X->s = A->s * B->s;
|
||||
/* If the result is 0, we don't shortcut the operation, which reduces
|
||||
* but does not eliminate side channels leaking the zero-ness. We do
|
||||
* need to take care to set the sign bit properly since the library does
|
||||
* not fully support an MPI object with a value of 0 and s == -1. */
|
||||
if( result_is_zero )
|
||||
X->s = 1;
|
||||
else
|
||||
X->s = A->s * B->s;
|
||||
|
||||
cleanup:
|
||||
|
||||
@ -2175,6 +2203,11 @@ int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A,
|
||||
#endif
|
||||
|
||||
j = N->n + 1;
|
||||
/* All W[i] and X must have at least N->n limbs for the mpi_montmul()
|
||||
* and mpi_montred() calls later. Here we ensure that W[1] and X are
|
||||
* large enough, and later we'll grow other W[i] to the same length.
|
||||
* They must not be shrunk midway through this function!
|
||||
*/
|
||||
MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
|
||||
MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], j ) );
|
||||
MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T, j * 2 ) );
|
||||
@ -2209,10 +2242,18 @@ int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A,
|
||||
* W[1] = A * R^2 * R^-1 mod N = A * R mod N
|
||||
*/
|
||||
if( mbedtls_mpi_cmp_mpi( A, N ) >= 0 )
|
||||
{
|
||||
MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &W[1], A, N ) );
|
||||
/* This should be a no-op because W[1] is already that large before
|
||||
* mbedtls_mpi_mod_mpi(), but it's necessary to avoid an overflow
|
||||
* in mpi_montmul() below, so let's make sure. */
|
||||
MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], N->n + 1 ) );
|
||||
}
|
||||
else
|
||||
MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[1], A ) );
|
||||
|
||||
/* Note that this is safe because W[1] always has at least N->n limbs
|
||||
* (it grew above and was preserved by mbedtls_mpi_copy()). */
|
||||
mpi_montmul( &W[1], &RR, N, mm, &T );
|
||||
|
||||
/*
|
||||
@ -2368,19 +2409,67 @@ int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B
|
||||
lz = mbedtls_mpi_lsb( &TA );
|
||||
lzt = mbedtls_mpi_lsb( &TB );
|
||||
|
||||
/* The loop below gives the correct result when A==0 but not when B==0.
|
||||
* So have a special case for B==0. Leverage the fact that we just
|
||||
* calculated the lsb and lsb(B)==0 iff B is odd or 0 to make the test
|
||||
* slightly more efficient than cmp_int(). */
|
||||
if( lzt == 0 && mbedtls_mpi_get_bit( &TB, 0 ) == 0 )
|
||||
{
|
||||
ret = mbedtls_mpi_copy( G, A );
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if( lzt < lz )
|
||||
lz = lzt;
|
||||
|
||||
MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, lz ) );
|
||||
MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, lz ) );
|
||||
|
||||
TA.s = TB.s = 1;
|
||||
|
||||
/* We mostly follow the procedure described in HAC 14.54, but with some
|
||||
* minor differences:
|
||||
* - Sequences of multiplications or divisions by 2 are grouped into a
|
||||
* single shift operation.
|
||||
* - The procedure in HAC assumes that 0 < TB <= TA.
|
||||
* - The condition TB <= TA is not actually necessary for correctness.
|
||||
* TA and TB have symmetric roles except for the loop termination
|
||||
* condition, and the shifts at the beginning of the loop body
|
||||
* remove any significance from the ordering of TA vs TB before
|
||||
* the shifts.
|
||||
* - If TA = 0, the loop goes through 0 iterations and the result is
|
||||
* correctly TB.
|
||||
* - The case TB = 0 was short-circuited above.
|
||||
*
|
||||
* For the correctness proof below, decompose the original values of
|
||||
* A and B as
|
||||
* A = sa * 2^a * A' with A'=0 or A' odd, and sa = +-1
|
||||
* B = sb * 2^b * B' with B'=0 or B' odd, and sb = +-1
|
||||
* Then gcd(A, B) = 2^{min(a,b)} * gcd(A',B'),
|
||||
* and gcd(A',B') is odd or 0.
|
||||
*
|
||||
* At the beginning, we have TA = |A| and TB = |B| so gcd(A,B) = gcd(TA,TB).
|
||||
* The code maintains the following invariant:
|
||||
* gcd(A,B) = 2^k * gcd(TA,TB) for some k (I)
|
||||
*/
|
||||
|
||||
/* Proof that the loop terminates:
|
||||
* At each iteration, either the right-shift by 1 is made on a nonzero
|
||||
* value and the nonnegative integer bitlen(TA) + bitlen(TB) decreases
|
||||
* by at least 1, or the right-shift by 1 is made on zero and then
|
||||
* TA becomes 0 which ends the loop (TB cannot be 0 if it is right-shifted
|
||||
* since in that case TB is calculated from TB-TA with the condition TB>TA).
|
||||
*/
|
||||
while( mbedtls_mpi_cmp_int( &TA, 0 ) != 0 )
|
||||
{
|
||||
/* Divisions by 2 preserve the invariant (I). */
|
||||
MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, mbedtls_mpi_lsb( &TA ) ) );
|
||||
MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, mbedtls_mpi_lsb( &TB ) ) );
|
||||
|
||||
/* Set either TA or TB to |TA-TB|/2. Since TA and TB are both odd,
|
||||
* TA-TB is even so the division by 2 has an integer result.
|
||||
* Invariant (I) is preserved since any odd divisor of both TA and TB
|
||||
* also divides |TA-TB|/2, and any odd divisor of both TA and |TA-TB|/2
|
||||
* also divides TB, and any odd divisior of both TB and |TA-TB|/2 also
|
||||
* divides TA.
|
||||
*/
|
||||
if( mbedtls_mpi_cmp_mpi( &TA, &TB ) >= 0 )
|
||||
{
|
||||
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TA, &TA, &TB ) );
|
||||
@ -2391,8 +2480,18 @@ int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B
|
||||
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TB, &TB, &TA ) );
|
||||
MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, 1 ) );
|
||||
}
|
||||
/* Note that one of TA or TB is still odd. */
|
||||
}
|
||||
|
||||
/* By invariant (I), gcd(A,B) = 2^k * gcd(TA,TB) for some k.
|
||||
* At the loop exit, TA = 0, so gcd(TA,TB) = TB.
|
||||
* - If there was at least one loop iteration, then one of TA or TB is odd,
|
||||
* and TA = 0, so TB is odd and gcd(TA,TB) = gcd(A',B'). In this case,
|
||||
* lz = min(a,b) so gcd(A,B) = 2^lz * TB.
|
||||
* - If there was no loop iteration, then A was 0, and gcd(A,B) = B.
|
||||
* In this case, lz = 0 and B = TB so gcd(A,B) = B = 2^lz * TB as well.
|
||||
*/
|
||||
|
||||
MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &TB, lz ) );
|
||||
MBEDTLS_MPI_CHK( mbedtls_mpi_copy( G, &TB ) );
|
||||
|
||||
|
Reference in New Issue
Block a user