Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove a secret-dependent branch in Montgomery multiplication #3398

Merged
Merged
69 changes: 45 additions & 24 deletions library/bignum.c
Original file line number Diff line number Diff line change
Expand Up @@ -1328,9 +1328,12 @@ int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi
}

/*
* Helper for mbedtls_mpi subtraction
* Helper for mbedtls_mpi subtraction:
* d -= s where d and s have the same size and d >= s.
gilles-peskine-arm marked this conversation as resolved.
Show resolved Hide resolved
*/
static void mpi_sub_hlp( size_t n, mbedtls_mpi_uint *s, mbedtls_mpi_uint *d )
static void mpi_sub_hlp( size_t n,
const mbedtls_mpi_uint *s,
gilles-peskine-arm marked this conversation as resolved.
Show resolved Hide resolved
mbedtls_mpi_uint *d )
{
size_t i;
mbedtls_mpi_uint c, z;
Expand Down Expand Up @@ -1975,18 +1978,34 @@ static void mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N )
*mm = ~x + 1;
}

/*
* Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
*/
static int mpi_montmul( mbedtls_mpi *A, const mbedtls_mpi *B, const mbedtls_mpi *N, mbedtls_mpi_uint mm,
/** Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
yanesca marked this conversation as resolved.
Show resolved Hide resolved
*
* \param[in,out] A One of the numbers to multiply.
* It must have at least one more limb than N
* (A->n >= N->n + 1).
* On successful completion, A contains the result of
* the multiplication A * B * R^-1 mod N where
* R = (2^ciL)^n.
* \param[in] B One of the numbers to multiply.
* It must be nonzero and must not have more limbs than N
* (B->n <= N->n).
* \param[in] N The modulo. N must be odd.
* \param mm The value calculated by `mpi_montg_init(&mm, N)`.
* This is -N^-1 mod 2^ciL.
* \param[in,out] T A bignum for temporary storage.
* It must be at least twice the limb size of N plus 2
* (T->n >= 2 * (N->n + 1)).
* Its initial content is unused and
* its final content is indeterminate.
* Note that unlike the usual convention in the library
* for `const mbedtls_mpi*`, the content of T can change.
yanesca marked this conversation as resolved.
Show resolved Hide resolved
*/
static void mpi_montmul( mbedtls_mpi *A, const mbedtls_mpi *B, const mbedtls_mpi *N, mbedtls_mpi_uint mm,
const mbedtls_mpi *T )
{
size_t i, n, m;
mbedtls_mpi_uint u0, u1, *d;

if( T->n < N->n + 1 || T->p == NULL )
return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );

memset( T->p, 0, T->n * ciL );

d = T->p;
Expand All @@ -2009,28 +2028,30 @@ static int mpi_montmul( mbedtls_mpi *A, const mbedtls_mpi *B, const mbedtls_mpi

memcpy( A->p, d, ( n + 1 ) * ciL );

/* If A >= N then A -= N. Do the subtraction unconditionally to prevent
* timing attacks. Modify T as a side effect. */
if( mbedtls_mpi_cmp_abs( A, N ) >= 0 )
mpi_sub_hlp( n, N->p, A->p );
else
/* prevent timing attacks */
mpi_sub_hlp( n, A->p, T->p );

return( 0 );
}

/*
* Montgomery reduction: A = A * R^-1 mod N
*
* See mpi_montmul() regarding constraints and guarantees on the parameters.
*/
static int mpi_montred( mbedtls_mpi *A, const mbedtls_mpi *N,
mbedtls_mpi_uint mm, const mbedtls_mpi *T )
static void mpi_montred( mbedtls_mpi *A, const mbedtls_mpi *N,
mbedtls_mpi_uint mm, const mbedtls_mpi *T )
{
mbedtls_mpi_uint z = 1;
mbedtls_mpi U;

U.n = U.s = (int) z;
U.p = &z;

return( mpi_montmul( A, &U, N, mm, T ) );
mpi_montmul( A, &U, N, mm, T );
}

/*
Expand Down Expand Up @@ -2116,13 +2137,13 @@ int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A,
else
MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[1], A ) );

MBEDTLS_MPI_CHK( mpi_montmul( &W[1], &RR, N, mm, &T ) );
mpi_montmul( &W[1], &RR, N, mm, &T );

/*
* X = R^2 * R^-1 mod N = R mod N
*/
MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &RR ) );
MBEDTLS_MPI_CHK( mpi_montred( X, N, mm, &T ) );
mpi_montred( X, N, mm, &T );

if( wsize > 1 )
{
Expand All @@ -2135,7 +2156,7 @@ int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A,
MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[j], &W[1] ) );

for( i = 0; i < wsize - 1; i++ )
MBEDTLS_MPI_CHK( mpi_montmul( &W[j], &W[j], N, mm, &T ) );
mpi_montmul( &W[j], &W[j], N, mm, &T );

/*
* W[i] = W[i - 1] * W[1]
Expand All @@ -2145,7 +2166,7 @@ int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A,
MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[i], N->n + 1 ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[i], &W[i - 1] ) );

MBEDTLS_MPI_CHK( mpi_montmul( &W[i], &W[1], N, mm, &T ) );
mpi_montmul( &W[i], &W[1], N, mm, &T );
}
}

Expand Down Expand Up @@ -2182,7 +2203,7 @@ int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A,
/*
* out of window, square X
*/
MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
mpi_montmul( X, X, N, mm, &T );
continue;
}

Expand All @@ -2200,12 +2221,12 @@ int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A,
* X = X^wsize R^-1 mod N
*/
for( i = 0; i < wsize; i++ )
MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
mpi_montmul( X, X, N, mm, &T );

/*
* X = X * W[wbits] R^-1 mod N
*/
MBEDTLS_MPI_CHK( mpi_montmul( X, &W[wbits], N, mm, &T ) );
mpi_montmul( X, &W[wbits], N, mm, &T );

state--;
nbits = 0;
Expand All @@ -2218,18 +2239,18 @@ int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A,
*/
for( i = 0; i < nbits; i++ )
{
MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
mpi_montmul( X, X, N, mm, &T );

wbits <<= 1;

if( ( wbits & ( one << wsize ) ) != 0 )
MBEDTLS_MPI_CHK( mpi_montmul( X, &W[1], N, mm, &T ) );
mpi_montmul( X, &W[1], N, mm, &T );
}

/*
* X = A^E * R * R^-1 mod N = A^E mod N
*/
MBEDTLS_MPI_CHK( mpi_montred( X, N, mm, &T ) );
mpi_montred( X, N, mm, &T );

if( neg && E->n != 0 && ( E->p[0] & 1 ) != 0 )
{
Expand Down