diff --git a/library/constant_time.c b/library/constant_time.c index 47e9b02d6b..cd3ec10647 100644 --- a/library/constant_time.c +++ b/library/constant_time.c @@ -741,6 +741,50 @@ cleanup: return( ret ); } +/* + * Compare unsigned values in constant time + */ +unsigned mbedtls_mpi_core_lt_ct( const mbedtls_mpi_uint *X, + const mbedtls_mpi_uint *Y, + size_t len ) +{ + size_t i; + /* The value of any of these variables is either 0 or 1 at all times. */ + unsigned ret, cond, done; + + ret = cond = done = 0; + + for( i = len; i > 0; i-- ) + { + /* + * If Y[i - 1] < X[i - 1] then X < Y is false and the result must + * remain 0. + * + * Again even if we can make a decision, we just mark the result and + * the fact that we are done and continue looping. + */ + cond = mbedtls_ct_mpi_uint_lt( Y[i - 1], X[i - 1] ); + done |= cond; + + /* + * If X[i - 1] < Y[i - 1] then X < Y is true. + * + * Again even if we can make a decision, we just mark the result and + * the fact that we are done and continue looping. + */ + cond = mbedtls_ct_mpi_uint_lt( X[i - 1], Y[i - 1] ); + ret |= cond & ( 1 - done ); + done |= cond; + } + + /* + * If all the limbs were equal, then the numbers are equal, X < Y is false + * and leaving the result 0 is correct. + */ + + return( ret ); +} + /* * Compare signed values in constant time */ diff --git a/library/constant_time_internal.h b/library/constant_time_internal.h index 9466bc3789..7255b2a857 100644 --- a/library/constant_time_internal.h +++ b/library/constant_time_internal.h @@ -129,6 +129,22 @@ unsigned mbedtls_ct_size_bool_eq( size_t x, unsigned mbedtls_ct_mpi_uint_lt( const mbedtls_mpi_uint x, const mbedtls_mpi_uint y ); +/** + * \brief Check if an MPI is less than the other in constant time. + * + * \param X The left-hand MPI. This must point to an array of limbs + * with the same allocated length as Y. + * \param Y The right-hand MPI. This must point to an array of limbs + * with the same allocated length as X. + * \param len The number of limbs in X and Y. + * + * \return The result of the comparison: + * \c 1 if \p X is less than \p Y. + * \c 0 if \p X is greater than or equal to \p Y. + */ +unsigned mbedtls_mpi_core_lt_ct( const mbedtls_mpi_uint *X, + const mbedtls_mpi_uint *Y, + size_t len ); #endif /* MBEDTLS_BIGNUM_C */ /** Choose between two integer values without branches. diff --git a/tests/suites/test_suite_mpi.data b/tests/suites/test_suite_mpi.data index 1974e3fc38..e52953c7ff 100644 --- a/tests/suites/test_suite_mpi.data +++ b/tests/suites/test_suite_mpi.data @@ -409,6 +409,63 @@ mbedtls_mpi_cmp_mpi:"-1230000000000000000":"":-1 Test mbedtls_mpi_cmp_mpi: large negative < 0 (1 limb) mbedtls_mpi_cmp_mpi:"-1230000000000000000":"0":-1 +Base test mbedtls_mpi_core_lt_ct #1 +mbedtls_mpi_core_lt_ct:"02B5":"02B5":0 + +Base test mbedtls_mpi_core_lt_ct #2 +mbedtls_mpi_core_lt_ct:"02B5":"02B4":0 + +Base test mbedtls_mpi_core_lt_ct #3 +mbedtls_mpi_core_lt_ct:"02B5":"02B6":1 + +Base test mbedtls_mpi_core_lt_ct (length=0) +mbedtls_mpi_core_lt_ct:"":"":0 + +Base test mbedtls_mpi_core_lt_ct (corner case - 64 bit) #1 +mbedtls_mpi_core_lt_ct:"7FFFFFFFFFFFFFFF":"FF":0 + +Base test mbedtls_mpi_core_lt_ct (corner case - 64 bit) #2 +mbedtls_mpi_core_lt_ct:"8000000000000000":"7FFFFFFFFFFFFFFF":0 + +Base test mbedtls_mpi_core_lt_ct (corner case - 64 bit) #3 +mbedtls_mpi_core_lt_ct:"8000000000000000":"01":0 + +Base test mbedtls_mpi_core_lt_ct (corner case - 64 bit) #4 +mbedtls_mpi_core_lt_ct:"8000000000000000":"00":0 + +Base test mbedtls_mpi_core_lt_ct (corner case - 64 bit) #5 +mbedtls_mpi_core_lt_ct:"FFFFFFFFFFFFFFFF":"FF":0 + +Base test mbedtls_mpi_core_lt_ct (corner case - 32 bit) #1 +mbedtls_mpi_core_lt_ct:"7FFFFFFF":"FF":0 + +Base test mbedtls_mpi_core_lt_ct (corner case - 32 bit) #2 +mbedtls_mpi_core_lt_ct:"80000000":"7FFFFFFF":0 + +Base test mbedtls_mpi_core_lt_ct (corner case - 32 bit) #3 +mbedtls_mpi_core_lt_ct:"80000000":"01":0 + +Base test mbedtls_mpi_core_lt_ct (corner case - 32 bit) #4 +mbedtls_mpi_core_lt_ct:"80000000":"00":0 + +Base test mbedtls_mpi_core_lt_ct (corner case - 32 bit) #5 +mbedtls_mpi_core_lt_ct:"FFFFFFFF":"FF":0 + +Multi-limb mbedtls_mpi_core_lt_ct (XY, equal MS limbs) +mbedtls_mpi_core_lt_ct:"EEFFFFFFFFFFFFFFFF":"EEFFFFFFFFFFFFFFF1":0 + +Multi-limb mbedtls_mpi_core_lt_ct (X=Y) +mbedtls_mpi_core_lt_ct:"EEFFFFFFFFFFFFFFFF":"EEFFFFFFFFFFFFFFFF":0 + +Multi-limb mbedtls_mpi_core_lt_ct (Alternating limbs) #1 +mbedtls_mpi_core_lt_ct:"11FFFFFFFFFFFFFFFF":"FF1111111111111111":1 + +Multi-limb mbedtls_mpi_core_lt_ct (Alternating limbs) #2 +mbedtls_mpi_core_lt_ct:"FF1111111111111111":"11FFFFFFFFFFFFFFFF":0 + Base test mbedtls_mpi_lt_mpi_ct #1 mbedtls_mpi_lt_mpi_ct:1:"2B5":1:"2B5":0:0 diff --git a/tests/suites/test_suite_mpi.function b/tests/suites/test_suite_mpi.function index b0d947c9db..ff87ea44ac 100644 --- a/tests/suites/test_suite_mpi.function +++ b/tests/suites/test_suite_mpi.function @@ -2,6 +2,8 @@ #include "mbedtls/bignum.h" #include "mbedtls/entropy.h" #include "bignum_core.h" +#include "constant_time_internal.h" +#include "test/constant_flow.h" #if MBEDTLS_MPI_MAX_BITS > 792 #define MPI_MAX_BITS_LARGER_THAN_792 @@ -607,6 +609,42 @@ exit: } /* END_CASE */ +/* BEGIN_CASE */ +void mbedtls_mpi_core_lt_ct( data_t * input_X, data_t * input_Y, int input_ret ) +{ + #define MAX_LEN 64 + mbedtls_mpi_uint X[MAX_LEN]; + mbedtls_mpi_uint Y[MAX_LEN]; + unsigned exp_ret = input_ret; + unsigned ret; + size_t len = CHARS_TO_LIMBS( + input_X->len > input_Y->len ? input_X->len : input_Y->len ); + + TEST_ASSERT( len <= MAX_LEN ); + + TEST_ASSERT( mbedtls_mpi_core_read_be( X, len, input_X->x, input_X->len ) + == 0 ); + TEST_ASSERT( mbedtls_mpi_core_read_be( Y, len, input_Y->x, input_Y->len ) + == 0 ); + + TEST_CF_SECRET( X, len * sizeof( mbedtls_mpi_uint ) ); + TEST_CF_SECRET( Y, len * sizeof( mbedtls_mpi_uint ) ); + + ret = mbedtls_mpi_core_lt_ct( X, Y, len ); + + TEST_CF_PUBLIC( X, len * sizeof( mbedtls_mpi_uint ) ); + TEST_CF_PUBLIC( Y, len * sizeof( mbedtls_mpi_uint ) ); + TEST_CF_PUBLIC( &ret, sizeof( ret ) ); + + TEST_ASSERT( ret == exp_ret ); + +exit: + ; + + #undef MAX_LEN +} +/* END_CASE */ + /* BEGIN_CASE */ void mbedtls_mpi_lt_mpi_ct( int size_X, char * input_X, int size_Y, char * input_Y,