Add mpi_safe_cond_assign()
diff --git a/include/polarssl/bignum.h b/include/polarssl/bignum.h
index 1052c5a..6e2afac 100644
--- a/include/polarssl/bignum.h
+++ b/include/polarssl/bignum.h
@@ -232,6 +232,25 @@
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
*
* \param X MPI to set
diff --git a/library/bignum.c b/library/bignum.c
index 55f7463..663d924 100644
--- a/library/bignum.c
+++ b/library/bignum.c
@@ -205,6 +205,31 @@
}
/*
+ * 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
*/
int mpi_lset( mpi *X, t_sint z )
diff --git a/tests/suites/test_suite_mpi.data b/tests/suites/test_suite_mpi.data
index e763374..8755fa2 100644
--- a/tests/suites/test_suite_mpi.data
+++ b/tests/suites/test_suite_mpi.data
@@ -205,6 +205,15 @@
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 d3a0d48..ee9b94a 100644
--- a/tests/suites/test_suite_mpi.function
+++ b/tests/suites/test_suite_mpi.function
@@ -309,6 +309,26 @@
/* 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 )
{
mpi X, Y, A;