From 71c2c2160182495d019369432d5daa94a801c7c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Thu, 21 Nov 2013 16:56:39 +0100 Subject: [PATCH] Add mpi_safe_cond_assign() --- include/polarssl/bignum.h | 19 +++++++++++++++++++ library/bignum.c | 25 +++++++++++++++++++++++++ tests/suites/test_suite_mpi.data | 9 +++++++++ tests/suites/test_suite_mpi.function | 20 ++++++++++++++++++++ 4 files changed, 73 insertions(+) diff --git a/include/polarssl/bignum.h b/include/polarssl/bignum.h index 1052c5aa0..6e2afac72 100644 --- a/include/polarssl/bignum.h +++ b/include/polarssl/bignum.h @@ -231,6 +231,25 @@ int mpi_copy( mpi *X, const mpi *Y ); */ void mpi_swap( mpi *X, mpi *Y ); +/** + * \brief Safe conditional assignement X = Y if assign is 1 + * + * \param X MPI to conditionally assign to + * \param Y Value to be assigned + * \param assign 1: perform the assignment, 0: leave X untouched + * + * \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 ); + * except that it avoids leaking any information about whether + * the assignment was done or not (the above code may leak + * information through branch prediction analysis). + */ +int mpi_safe_cond_assign( mpi *X, mpi *Y, unsigned char assign ); + /** * \brief Set value from integer * diff --git a/library/bignum.c b/library/bignum.c index 55f7463a9..663d9240e 100644 --- a/library/bignum.c +++ b/library/bignum.c @@ -204,6 +204,31 @@ void mpi_swap( mpi *X, mpi *Y ) memcpy( Y, &T, sizeof( mpi ) ); } +/* + * Conditionally assign X = Y, without leaking information + */ +int mpi_safe_cond_assign( mpi *X, 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 both MPIs have the same size */ + if( X->n > Y->n ) + MPI_CHK( mpi_grow( Y, X->n ) ); + if( Y->n > X->n ) + MPI_CHK( mpi_grow( X, Y->n ) ); + + /* Do the conditional assign safely */ + for( i = 0; i < X->n; i++ ) + X->p[i] = X->p[i] * (1 - assign) + Y->p[i] * assign; + +cleanup: + return( ret ); +} + /* * Set value from integer */ diff --git a/tests/suites/test_suite_mpi.data b/tests/suites/test_suite_mpi.data index e763374ae..8755fa29a 100644 --- a/tests/suites/test_suite_mpi.data +++ b/tests/suites/test_suite_mpi.data @@ -205,6 +205,15 @@ mpi_shrink:4:1:0:1 Test mpi_shrink #8 mpi_shrink:4:0:0:1 +Test mpi_safe_cond_assign #1 +mpi_safe_cond_assign:"01":"02" + +Test mpi_safe_cond_assign #2 +mpi_safe_cond_assign:"FF000000000000000001":"02" + +Test mpi_safe_cond_assign #3 +mpi_safe_cond_assign:"01":"FF000000000000000002" + 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 d3a0d4898..ee9b94a5b 100644 --- a/tests/suites/test_suite_mpi.function +++ b/tests/suites/test_suite_mpi.function @@ -308,6 +308,26 @@ void mpi_shrink( int before, int used, int min, int after ) } /* END_CASE */ +/* BEGIN_CASE */ +void mpi_safe_cond_assign( char *x_str, char *y_str ) +{ + mpi X, Y, XX; + mpi_init( &X ); mpi_init( &Y ); mpi_init( &XX ); + + TEST_ASSERT( mpi_read_string( &X, 16, x_str ) == 0 ); + TEST_ASSERT( mpi_read_string( &Y, 16, y_str ) == 0 ); + TEST_ASSERT( mpi_copy( &XX, &X ) == 0 ); + + TEST_ASSERT( mpi_safe_cond_assign( &X, &Y, 0 ) == 0 ); + TEST_ASSERT( mpi_cmp_mpi( &X, &XX ) == 0 ); + + TEST_ASSERT( mpi_safe_cond_assign( &X, &Y, 1 ) == 0 ); + TEST_ASSERT( mpi_cmp_mpi( &X, &Y ) == 0 ); + + mpi_free( &X ); mpi_free( &Y ); mpi_free( &XX ); +} +/* END_CASE */ + /* BEGIN_CASE */ void mpi_swap( int input_X, int input_Y ) {