diff --git a/include/polarssl/bignum.h b/include/polarssl/bignum.h index d98dce9c4..df17b129b 100644 --- a/include/polarssl/bignum.h +++ b/include/polarssl/bignum.h @@ -236,11 +236,10 @@ void mpi_swap( mpi *X, mpi *Y ); * * \param X MPI to conditionally assign to * \param Y Value to be assigned - * \param assign 1: perform the assignment, 0: leave X untouched + * \param assign 1: perform the assignment, 0: keep X's original value * * \return 0 if successful, * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed, - * POLARSSL_ERR_MPI_BAD_INPUT_DATA if assing is not 0 or 1 * * \note This function is equivalent to * if( assign ) mpi_copy( X, Y ); @@ -251,6 +250,25 @@ void mpi_swap( mpi *X, mpi *Y ); */ int mpi_safe_cond_assign( mpi *X, const mpi *Y, unsigned char assign ); +/** + * \brief Safe conditional swap X <-> Y if swap is 1 + * + * \param X First mpi value + * \param Y Second mpi value + * \param assign 1: perform the swap, 0: keep X and Y's original values + * + * \return 0 if successful, + * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed, + * + * \note This function is equivalent to + * if( assign ) mpi_swap( X, Y ); + * except that it avoids leaking any information about whether + * the assignment was done or not (the above code may leak + * information through branch prediction and/or memory access + * patterns analysis). + */ +int mpi_safe_cond_swap( mpi *X, mpi *Y, unsigned char assign ); + /** * \brief Set value from integer * diff --git a/library/bignum.c b/library/bignum.c index 98d534a5a..dd5c0bfdd 100644 --- a/library/bignum.c +++ b/library/bignum.c @@ -214,16 +214,16 @@ int mpi_safe_cond_assign( mpi *X, const mpi *Y, unsigned char assign ) int ret = 0; size_t i; - if( assign * ( 1 - assign ) != 0 ) - return( POLARSSL_ERR_MPI_BAD_INPUT_DATA ); + /* make sure assign is 0 or 1 */ + assign = ( assign != 0 ); - if( Y->n > X->n ) - MPI_CHK( mpi_grow( X, Y->n ) ); + MPI_CHK( mpi_grow( X, Y->n ) ); - /* Do the conditional assign safely */ X->s = X->s * (1 - assign) + Y->s * assign; + for( i = 0; i < Y->n; i++ ) X->p[i] = X->p[i] * (1 - assign) + Y->p[i] * assign; + for( ; i < X->n; i++ ) X->p[i] *= (1 - assign); @@ -231,6 +231,43 @@ cleanup: return( ret ); } +/* + * Conditionally swap X and Y, without leaking information + * about whether the swap was made or not. + * Here it is not ok to simply swap the pointers, which whould lead to + * different memory access patterns when X and Y are used afterwards. + */ +int mpi_safe_cond_swap( mpi *X, mpi *Y, unsigned char swap ) +{ + int ret, s; + size_t i; + t_uint tmp; + + if( X == Y ) + return( 0 ); + + /* make sure swap is 0 or 1 */ + swap = ( swap != 0 ); + + MPI_CHK( mpi_grow( X, Y->n ) ); + MPI_CHK( mpi_grow( Y, X->n ) ); + + s = X->s; + X->s = X->s * (1 - swap) + Y->s * swap; + Y->s = Y->s * (1 - swap) + s * swap; + + + for( i = 0; i < X->n; i++ ) + { + tmp = X->p[i]; + X->p[i] = X->p[i] * (1 - swap) + Y->p[i] * swap; + Y->p[i] = Y->p[i] * (1 - swap) + tmp * swap; + } + +cleanup: + return( ret ); +} + /* * Set value from integer */ diff --git a/tests/suites/test_suite_mpi.data b/tests/suites/test_suite_mpi.data index 36ae8d6a8..fdbef02cc 100644 --- a/tests/suites/test_suite_mpi.data +++ b/tests/suites/test_suite_mpi.data @@ -223,6 +223,24 @@ mpi_safe_cond_assign:-1:"01":+1:"02" Test mpi_safe_cond_assign #6 mpi_safe_cond_assign:-1:"01":-1:"02" +Test mpi_safe_cond_swap #1 +mpi_safe_cond_swap:+1:"01":+1:"02" + +Test mpi_safe_cond_swap #2 +mpi_safe_cond_swap:+1:"FF000000000000000001":+1:"02" + +Test mpi_safe_cond_swap #3 +mpi_safe_cond_swap:+1:"01":+1:"FF000000000000000002" + +Test mpi_safe_cond_swap #4 +mpi_safe_cond_swap:+1:"01":-1:"02" + +Test mpi_safe_cond_swap #5 +mpi_safe_cond_swap:-1:"01":+1:"02" + +Test mpi_safe_cond_swap #6 +mpi_safe_cond_swap:-1:"01":-1:"02" + Base test mpi_add_abs #1 mpi_add_abs:10:"12345678":10:"642531":10:"12988209" diff --git a/tests/suites/test_suite_mpi.function b/tests/suites/test_suite_mpi.function index 394cd339b..620c36851 100644 --- a/tests/suites/test_suite_mpi.function +++ b/tests/suites/test_suite_mpi.function @@ -331,6 +331,36 @@ void mpi_safe_cond_assign( int x_sign, char *x_str, } /* END_CASE */ +/* BEGIN_CASE */ +void mpi_safe_cond_swap( int x_sign, char *x_str, + int y_sign, char *y_str ) +{ + mpi X, Y, XX, YY; + + mpi_init( &X ); mpi_init( &Y ); + mpi_init( &XX ); mpi_init( &YY ); + + TEST_ASSERT( mpi_read_string( &X, 16, x_str ) == 0 ); + X.s = x_sign; + TEST_ASSERT( mpi_read_string( &Y, 16, y_str ) == 0 ); + Y.s = y_sign; + + TEST_ASSERT( mpi_copy( &XX, &X ) == 0 ); + TEST_ASSERT( mpi_copy( &YY, &Y ) == 0 ); + + TEST_ASSERT( mpi_safe_cond_swap( &X, &Y, 0 ) == 0 ); + TEST_ASSERT( mpi_cmp_mpi( &X, &XX ) == 0 ); + TEST_ASSERT( mpi_cmp_mpi( &Y, &YY ) == 0 ); + + TEST_ASSERT( mpi_safe_cond_swap( &X, &Y, 1 ) == 0 ); + TEST_ASSERT( mpi_cmp_mpi( &Y, &XX ) == 0 ); + TEST_ASSERT( mpi_cmp_mpi( &X, &YY ) == 0 ); + + mpi_free( &X ); mpi_free( &Y ); + mpi_free( &XX ); mpi_free( &YY ); +} +/* END_CASE */ + /* BEGIN_CASE */ void mpi_swap( int input_X, int input_Y ) {