diff --git a/library/bignum_core.c b/library/bignum_core.c index d0728e7ab..89fd4043e 100644 --- a/library/bignum_core.c +++ b/library/bignum_core.c @@ -25,6 +25,7 @@ #include "mbedtls/error.h" #include "mbedtls/platform_util.h" +#include "constant_time_internal.h" #include "mbedtls/platform.h" @@ -153,6 +154,36 @@ void mbedtls_mpi_core_bigendian_to_host( mbedtls_mpi_uint *A, } } +void mbedtls_mpi_core_cond_assign( mbedtls_mpi_uint *X, + const mbedtls_mpi_uint *A, + size_t limbs, + unsigned char assign ) +{ + if( X == A ) + return; + + mbedtls_ct_mpi_uint_cond_assign( limbs, X, A, assign ); +} + +void mbedtls_mpi_core_cond_swap( mbedtls_mpi_uint *X, + mbedtls_mpi_uint *Y, + size_t limbs, + unsigned char swap ) +{ + if( X == Y ) + return; + + /* all-bits 1 if swap is 1, all-bits 0 if swap is 0 */ + mbedtls_mpi_uint limb_mask = mbedtls_ct_mpi_uint_mask( swap ); + + for( size_t i = 0; i < limbs; i++ ) + { + mbedtls_mpi_uint tmp = X[i]; + X[i] = ( X[i] & ~limb_mask ) | ( Y[i] & limb_mask ); + Y[i] = ( Y[i] & ~limb_mask ) | ( tmp & limb_mask ); + } +} + int mbedtls_mpi_core_read_le( mbedtls_mpi_uint *X, size_t X_limbs, const unsigned char *input, diff --git a/library/bignum_core.h b/library/bignum_core.h index 8e227f8d8..b626fab6e 100644 --- a/library/bignum_core.h +++ b/library/bignum_core.h @@ -74,6 +74,58 @@ size_t mbedtls_mpi_core_bitlen( const mbedtls_mpi_uint *A, size_t A_limbs ); void mbedtls_mpi_core_bigendian_to_host( mbedtls_mpi_uint *A, size_t A_limbs ); +/** + * \brief Perform a safe conditional copy of an MPI which doesn't reveal + * whether assignment was done or not. + * + * \param[out] X The address of the destination MPI. + * This must be initialized. Must have enough limbs to + * store the full value of \p A. + * \param[in] A The address of the source MPI. This must be initialized. + * \param limbs The number of limbs of \p A. + * \param assign The condition deciding whether to perform the + * assignment or not. Must be either 0 or 1: + * * \c 1: Perform the assignment `X = A`. + * * \c 0: Keep the original value of \p X. + * + * \note This function avoids leaking any information about whether + * the assignment was done or not. + * + * \warning If \p assign is neither 0 nor 1, the result of this function + * is indeterminate, and the resulting value in \p X might be + * neither its original value nor the value in \p A. + */ +void mbedtls_mpi_core_cond_assign( mbedtls_mpi_uint *X, + const mbedtls_mpi_uint *A, + size_t limbs, + unsigned char assign ); + +/** + * \brief Perform a safe conditional swap of two MPIs which doesn't reveal + * whether the swap was done or not. + * + * \param[in,out] X The address of the first MPI. + * This must be initialized. + * \param[in,out] Y The address of the second MPI. + * This must be initialized. + * \param limbs The number of limbs of \p X and \p Y. + * \param swap The condition deciding whether to perform + * the swap or not. Must be either 0 or 1: + * * \c 1: Swap the values of \p X and \p Y. + * * \c 0: Keep the original values of \p X and \p Y. + * + * \note This function avoids leaking any information about whether + * the swap was done or not. + * + * \warning If \p swap is neither 0 nor 1, the result of this function + * is indeterminate, and both \p X and \p Y might end up with + * values different to either of the original ones. + */ +void mbedtls_mpi_core_cond_swap( mbedtls_mpi_uint *X, + mbedtls_mpi_uint *Y, + size_t limbs, + unsigned char swap ); + /** Import X from unsigned binary data, little-endian. * * The MPI needs to have enough limbs to store the full value (including any diff --git a/library/bignum_mod_raw.c b/library/bignum_mod_raw.c index e1c96d612..4b8a69800 100644 --- a/library/bignum_mod_raw.c +++ b/library/bignum_mod_raw.c @@ -33,6 +33,22 @@ #include "bignum_mod.h" #include "constant_time_internal.h" +void mbedtls_mpi_mod_raw_cond_assign( mbedtls_mpi_uint *X, + const mbedtls_mpi_uint *A, + const mbedtls_mpi_mod_modulus *N, + unsigned char assign ) +{ + mbedtls_mpi_core_cond_assign( X, A, N->limbs, assign ); +} + +void mbedtls_mpi_mod_raw_cond_swap( mbedtls_mpi_uint *X, + mbedtls_mpi_uint *Y, + const mbedtls_mpi_mod_modulus *N, + unsigned char swap ) +{ + mbedtls_mpi_core_cond_swap( X, Y, N->limbs, swap ); +} + int mbedtls_mpi_mod_raw_read( mbedtls_mpi_uint *X, const mbedtls_mpi_mod_modulus *m, const unsigned char *input, diff --git a/library/bignum_mod_raw.h b/library/bignum_mod_raw.h index 7b3a0c177..f698a9a62 100644 --- a/library/bignum_mod_raw.h +++ b/library/bignum_mod_raw.h @@ -33,6 +33,60 @@ #include "bignum_mod.h" +/** + * \brief Perform a safe conditional copy of an MPI which doesn't reveal + * whether the assignment was done or not. + * + * The size to copy is determined by \p N. + * + * \param[out] X The address of the destination MPI. + * This must be initialized. Must have enough limbs to + * store the full value of \p A. + * \param[in] A The address of the source MPI. This must be initialized. + * \param[in] N The address of the modulus related to \p X and \p A. + * \param assign The condition deciding whether to perform the + * assignment or not. Must be either 0 or 1: + * * \c 1: Perform the assignment `X = A`. + * * \c 0: Keep the original value of \p X. + * + * \note This function avoids leaking any information about whether + * the assignment was done or not. + * + * \warning If \p assign is neither 0 nor 1, the result of this function + * is indeterminate, and the resulting value in \p X might be + * neither its original value nor the value in \p A. + */ +void mbedtls_mpi_mod_raw_cond_assign( mbedtls_mpi_uint *X, + const mbedtls_mpi_uint *A, + const mbedtls_mpi_mod_modulus *N, + unsigned char assign ); + +/** + * \brief Perform a safe conditional swap of two MPIs which doesn't reveal + * whether the swap was done or not. + * + * The size to swap is determined by \p N. + * + * \param[in,out] X The address of the first MPI. This must be initialized. + * \param[in,out] Y The address of the second MPI. This must be initialized. + * \param[in] N The address of the modulus related to \p X and \p Y. + * \param swap The condition deciding whether to perform + * the swap or not. Must be either 0 or 1: + * * \c 1: Swap the values of \p X and \p Y. + * * \c 0: Keep the original values of \p X and \p Y. + * + * \note This function avoids leaking any information about whether + * the swap was done or not. + * + * \warning If \p swap is neither 0 nor 1, the result of this function + * is indeterminate, and both \p X and \p Y might end up with + * values different to either of the original ones. + */ +void mbedtls_mpi_mod_raw_cond_swap( mbedtls_mpi_uint *X, + mbedtls_mpi_uint *Y, + const mbedtls_mpi_mod_modulus *N, + unsigned char swap ); + /** Import X from unsigned binary data. * * The MPI needs to have enough limbs to store the full value (including any diff --git a/library/constant_time.c b/library/constant_time.c index 01a6976d8..510304e32 100644 --- a/library/constant_time.c +++ b/library/constant_time.c @@ -30,6 +30,7 @@ #if defined(MBEDTLS_BIGNUM_C) #include "mbedtls/bignum.h" +#include "bignum_core.h" #endif #if defined(MBEDTLS_SSL_TLS_C) @@ -678,21 +679,19 @@ int mbedtls_mpi_safe_cond_assign( mbedtls_mpi *X, unsigned char assign ) { int ret = 0; - size_t i; - mbedtls_mpi_uint limb_mask; MPI_VALIDATE_RET( X != NULL ); MPI_VALIDATE_RET( Y != NULL ); /* all-bits 1 if assign is 1, all-bits 0 if assign is 0 */ - limb_mask = mbedtls_ct_mpi_uint_mask( assign );; + mbedtls_mpi_uint limb_mask = mbedtls_ct_mpi_uint_mask( assign ); MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) ); X->s = mbedtls_ct_cond_select_sign( assign, Y->s, X->s ); - mbedtls_ct_mpi_uint_cond_assign( Y->n, X->p, Y->p, assign ); + mbedtls_mpi_core_cond_assign( X->p, Y->p, Y->n, assign ); - for( i = Y->n; i < X->n; i++ ) + for( size_t i = Y->n; i < X->n; i++ ) X->p[i] &= ~limb_mask; cleanup: @@ -709,19 +708,14 @@ int mbedtls_mpi_safe_cond_swap( mbedtls_mpi *X, mbedtls_mpi *Y, unsigned char swap ) { - int ret, s; - size_t i; - mbedtls_mpi_uint limb_mask; - mbedtls_mpi_uint tmp; + int ret = 0; + int s; MPI_VALIDATE_RET( X != NULL ); MPI_VALIDATE_RET( Y != NULL ); if( X == Y ) return( 0 ); - /* all-bits 1 if swap is 1, all-bits 0 if swap is 0 */ - limb_mask = mbedtls_ct_mpi_uint_mask( swap ); - MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_grow( Y, X->n ) ); @@ -729,13 +723,7 @@ int mbedtls_mpi_safe_cond_swap( mbedtls_mpi *X, X->s = mbedtls_ct_cond_select_sign( swap, Y->s, X->s ); Y->s = mbedtls_ct_cond_select_sign( swap, s, Y->s ); - - for( i = 0; i < X->n; i++ ) - { - tmp = X->p[i]; - X->p[i] = ( X->p[i] & ~limb_mask ) | ( Y->p[i] & limb_mask ); - Y->p[i] = ( Y->p[i] & ~limb_mask ) | ( tmp & limb_mask ); - } + mbedtls_mpi_core_cond_swap( X->p, Y->p, X->n, swap ); cleanup: return( ret ); diff --git a/tests/suites/test_suite_mpi.data b/tests/suites/test_suite_mpi.data index 95e0d3199..22d99a928 100644 --- a/tests/suites/test_suite_mpi.data +++ b/tests/suites/test_suite_mpi.data @@ -717,6 +717,84 @@ mpi_core_lt_ct:"11FFFFFFFFFFFFFFFF":"FF1111111111111111":1 mbedtls_mpi_core_lt_ct: x>y (alternating limbs) mpi_core_lt_ct:"FF1111111111111111":"11FFFFFFFFFFFFFFFF":0 +mbedtls_mpi_core_cond_assign: 1 limb +mpi_core_cond_assign:"FFFFFFFF":"11111111":4 + +mbedtls_mpi_core_cond_assign: more limbs #1 +mpi_core_cond_assign:"00000000FFFFFFFF55555555AAAAAAAA":"0123456789ABCDEF0123456789ABCDEF":16 + +mbedtls_mpi_core_cond_assign: more limbs #2 +mpi_core_cond_assign:"11111111EEEEEEEE77777777CCCCCCCC":"FEDCBA9876543210FEDCBA9876543210":16 + +mbedtls_mpi_core_cond_assign: more limbs #3 +mpi_core_cond_assign:"562D2B7E83BDC6FF783CEC0D6F46EAE7":"4C314E3B5CEB009C25F3300D5ECF670A":16 + +mbedtls_mpi_core_cond_assign: copy 256 bytes of limbs +mpi_core_cond_assign:"00000000111111112222222233333333444444445555555566666666777777778888888899999999AAAAAAAABBBBBBBBCCCCCCCCDDDDDDDDEEEEEEEEFFFFFFFF00000000111111112222222233333333444444445555555566666666777777778888888899999999AAAAAAAABBBBBBBBCCCCCCCCDDDDDDDDEEEEEEEEFFFFFFFF00000000111111112222222233333333444444445555555566666666777777778888888899999999AAAAAAAABBBBBBBBCCCCCCCCDDDDDDDDEEEEEEEEFFFFFFFF00000000111111112222222233333333444444445555555566666666777777778888888899999999AAAAAAAABBBBBBBBCCCCCCCCDDDDDDDDEEEEEEEEFFFFFFFF":"6E3173EEAC8D68A5AB53D259F32D9E9C298FD2C4FAD3BEE9151DC103EA2382F5480C7D11F451C060A1E3D887E05A620EF6395763CB7A40FC473DD0771456A018E18635EA971C36DCAD09D60E8BD0E2E0CCD1AECB8BE0ABA881DBE60163F6C45947EC0B05FDAAA3DF944627DD4FACBAD3FF2AB4B99D91E548C06A4AF320A9CA0D2FD0CB19B90B9D6A8BF59CB631DD925B6DEA621FE962099D3D0BED6B13C0C546DC6B563A7FC63B1B77D277897DD7B9DF28C4C9213A183B83D982964C6AD8192CE7354B11ED727EDEF85074C46E4E2E6C1728FB7980385CDB36512F927847C6A14A118624ABC12B09DBEE60D651B5431AAD982228C61655EABB80C263871AE1CF":256 + +mbedtls_mpi_core_cond_assign: copy half of the limbs +mpi_core_cond_assign:"00000000FFFFFFFF55555555AAAAAAAA":"FEDCBA9876543210FEDCBA9876543210":8 + +mbedtls_mpi_core_cond_swap: same value +mpi_core_cond_swap:"FFFFFFFF":"FFFFFFFF":4 + +mbedtls_mpi_core_cond_swap: 1 limb +mpi_core_cond_swap:"FFFFFFFF":"11111111":4 + +mbedtls_mpi_core_cond_swap: more limbs #1 +mpi_core_cond_swap:"00000000FFFFFFFF55555555AAAAAAAA":"0123456789ABCDEF0123456789ABCDEF":16 + +mbedtls_mpi_core_cond_swap: more limbs #2 +mpi_core_cond_swap:"11111111EEEEEEEE77777777CCCCCCCC":"FEDCBA9876543210FEDCBA9876543210":16 + +mbedtls_mpi_core_cond_swap: more limbs #3 +mpi_core_cond_swap:"562D2B7E83BDC6FF783CEC0D6F46EAE7":"4C314E3B5CEB009C25F3300D5ECF670A":16 + +mbedtls_mpi_core_cond_swap: copy 256 bytes of limbs +mpi_core_cond_swap:"00000000111111112222222233333333444444445555555566666666777777778888888899999999AAAAAAAABBBBBBBBCCCCCCCCDDDDDDDDEEEEEEEEFFFFFFFF00000000111111112222222233333333444444445555555566666666777777778888888899999999AAAAAAAABBBBBBBBCCCCCCCCDDDDDDDDEEEEEEEEFFFFFFFF00000000111111112222222233333333444444445555555566666666777777778888888899999999AAAAAAAABBBBBBBBCCCCCCCCDDDDDDDDEEEEEEEEFFFFFFFF00000000111111112222222233333333444444445555555566666666777777778888888899999999AAAAAAAABBBBBBBBCCCCCCCCDDDDDDDDEEEEEEEEFFFFFFFF":"9FBBA284460D8EAB5E0D66B634BD18FBA58C0C25417DD637526A7622C6425B46E09AEFBB8C2340AC823DFE990A62C85DB23BCDBEA734134606CEEB4BCF7444569D5EC4E32341ED09D7A5D0BB8B11D7B726BAECCF37D4FC1BEBD892CADD7BE9E093343C1A68D7A188DFE145C1EDBD8048B24E20A076F981D75ABE44318ADC40ED316C444774B6A90D3EE49557315AA6FAB162A498C0B2E2C15BD94186A665E12DDC39211583FA5F21218A3B46999FEBA4DFF454FB6ED35B8F3AE5F8EA840838BD76006DA112F85EDAA2CC07518FFC9724D5695BAF74F16C8D1A3A06029D2F5C1023D9E8A84D1267BD9AF82D1F5F77092D34BE4E8C4D1EA8C58F90B094DCFD6920":256 + +mbedtls_mpi_core_cond_swap: copy half of the limbs +mpi_core_cond_swap:"00000000FFFFFFFF55555555AAAAAAAA":"FEDCBA9876543210FEDCBA9876543210":8 + +mbedtls_mpi_mod_raw_cond_assign: 1 limb +mpi_mod_raw_cond_assign:"FFFFFFFF":"11111111":4 + +mbedtls_mpi_mod_raw_cond_assign: more limbs #1 +mpi_mod_raw_cond_assign:"00000000FFFFFFFF55555555AAAAAAAA":"0123456789ABCDEF0123456789ABCDEF":16 + +mbedtls_mpi_mod_raw_cond_assign: more limbs #2 +mpi_mod_raw_cond_assign:"11111111EEEEEEEE77777777CCCCCCCC":"FEDCBA9876543210FEDCBA9876543210":16 + +mbedtls_mpi_mod_raw_cond_assign: more limbs #3 +mpi_mod_raw_cond_assign:"562D2B7E83BDC6FF783CEC0D6F46EAE7":"4C314E3B5CEB009C25F3300D5ECF670A":16 + +mbedtls_mpi_mod_raw_cond_assign: copy 256 bytes of limbs +mpi_mod_raw_cond_assign:"00000000111111112222222233333333444444445555555566666666777777778888888899999999AAAAAAAABBBBBBBBCCCCCCCCDDDDDDDDEEEEEEEEFFFFFFFF00000000111111112222222233333333444444445555555566666666777777778888888899999999AAAAAAAABBBBBBBBCCCCCCCCDDDDDDDDEEEEEEEEFFFFFFFF00000000111111112222222233333333444444445555555566666666777777778888888899999999AAAAAAAABBBBBBBBCCCCCCCCDDDDDDDDEEEEEEEEFFFFFFFF00000000111111112222222233333333444444445555555566666666777777778888888899999999AAAAAAAABBBBBBBBCCCCCCCCDDDDDDDDEEEEEEEEFFFFFFFF":"38AAE958A11CCE9F4B4D0EDF64D31DF6FEA451D56B3BAB3DB796739B96C5C9C619DAE2AD5394D41FC3746A4F35BA186F02D908E900A2BA5AC95D494378A6A6FC619801DA3F3B4C5BAAA49B16DD3B2EF9AFB4B82449F90628E1438405D321ACA8476EA3E7124D46D5F25CD57143F2C6A022F7D6EBF7C726AEF56D97E3944EACD627A814D2F546F5A659DD316AE57584BC46F0D976D537E78AB09D2599BB0F073366C541CEF4B6D76FE72D000A01167FCE506B805B295C12BFCAA3B768D8E6AA50D939BDB519A94000B7B18B2D36AE888EDC33DC933E9612D112BB7A95D0748F175E69F00B9D8470C64E27B4FF39551B09FF046F864E9FC22A3E1F73570DF31214":256 + +mbedtls_mpi_mod_raw_cond_assign: copy half of the limbs +mpi_mod_raw_cond_assign:"00000000FFFFFFFF55555555AAAAAAAA":"FEDCBA9876543210FEDCBA9876543210":8 + +mbedtls_mpi_mod_raw_cond_swap: same value +mpi_mod_raw_cond_swap:"FFFFFFFF":"FFFFFFFF":4 + +mbedtls_mpi_mod_raw_cond_swap: 1 limb +mpi_mod_raw_cond_swap:"FFFFFFFF":"11111111":4 + +mbedtls_mpi_mod_raw_cond_swap: more limbs #1 +mpi_mod_raw_cond_swap:"00000000FFFFFFFF55555555AAAAAAAA":"0123456789ABCDEF0123456789ABCDEF":16 + +mbedtls_mpi_mod_raw_cond_swap: more limbs #2 +mpi_mod_raw_cond_swap:"11111111EEEEEEEE77777777CCCCCCCC":"FEDCBA9876543210FEDCBA9876543210":16 + +mbedtls_mpi_mod_raw_cond_swap: more limbs #3 +mpi_mod_raw_cond_swap:"562D2B7E83BDC6FF783CEC0D6F46EAE7":"4C314E3B5CEB009C25F3300D5ECF670A":16 + +mbedtls_mpi_mod_raw_cond_swap: copy 256 bytes of limbs +mpi_mod_raw_cond_swap:"00000000111111112222222233333333444444445555555566666666777777778888888899999999AAAAAAAABBBBBBBBCCCCCCCCDDDDDDDDEEEEEEEEFFFFFFFF00000000111111112222222233333333444444445555555566666666777777778888888899999999AAAAAAAABBBBBBBBCCCCCCCCDDDDDDDDEEEEEEEEFFFFFFFF00000000111111112222222233333333444444445555555566666666777777778888888899999999AAAAAAAABBBBBBBBCCCCCCCCDDDDDDDDEEEEEEEEFFFFFFFF00000000111111112222222233333333444444445555555566666666777777778888888899999999AAAAAAAABBBBBBBBCCCCCCCCDDDDDDDDEEEEEEEEFFFFFFFF":"A6154F6146E5AE06C705EF228DB022B4C0C908D9FF11E83CB0836A37DD11D72B5AE0D053B6D0B376B015E3B09DCC04644F12CBCBD0407300DEDA1D817E99A030BA128A57494F6C6BC650A840B70B3A1CDF8A75A387184C93DEF02DD538C60E8764AD2E4600952E09D24DC5524AB34070D25D204174D23B2BFDACBC67F8973C47FAF01CE9810130934AB6A94C5E6D223EDEAE904FD18368231AC3113C2CD73E879124CE21FC379C695C41D6861F5FB957570C3E6EF61F4FBA5D9945FB42931FC8E68370177DB313BEB7AF79B1F0F872368946FF35BD059E60677342EB3A0431714044AD508CD244B7CE200C5DC75B3BC7846A4CF0436C9288F2153124C9283171":256 + +mbedtls_mpi_mod_raw_cond_swap: copy half of the limbs +mpi_mod_raw_cond_swap:"00000000FFFFFFFF55555555AAAAAAAA":"FEDCBA9876543210FEDCBA9876543210":8 + Base test mbedtls_mpi_lt_mpi_ct #1 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 9812c56b5..b699f9c04 100644 --- a/tests/suites/test_suite_mpi.function +++ b/tests/suites/test_suite_mpi.function @@ -768,6 +768,316 @@ exit: } /* END_CASE */ +/* BEGIN_CASE */ +void mpi_core_cond_assign( data_t * input_X, + data_t * input_Y, + int input_bytes ) +{ + mbedtls_mpi_uint *X = NULL; + mbedtls_mpi_uint *Y = NULL; + size_t limbs_X = CHARS_TO_LIMBS( input_X->len ); + size_t limbs_Y = CHARS_TO_LIMBS( input_Y->len ); + size_t limbs = limbs_X; + size_t copy_limbs = CHARS_TO_LIMBS( input_bytes ); + size_t bytes = limbs * sizeof( mbedtls_mpi_uint ); + size_t copy_bytes = copy_limbs * sizeof( mbedtls_mpi_uint ); + + TEST_EQUAL( limbs_X, limbs_Y ); + TEST_ASSERT( copy_limbs <= limbs ); + + ASSERT_ALLOC( X, limbs ); + ASSERT_ALLOC( Y, limbs ); + + TEST_ASSERT( mbedtls_mpi_core_read_be( X, limbs, input_X->x, input_X->len ) + == 0 ); + + TEST_ASSERT( mbedtls_mpi_core_read_be( Y, limbs, input_Y->x, input_Y->len ) + == 0 ); + + /* condition is false */ + TEST_CF_SECRET( X, bytes ); + TEST_CF_SECRET( Y, bytes ); + + mbedtls_mpi_core_cond_assign( X, Y, copy_limbs, 0 ); + + TEST_CF_PUBLIC( X, bytes ); + TEST_CF_PUBLIC( Y, bytes ); + + TEST_ASSERT( memcmp( X, Y, bytes ) != 0 ); + + /* condition is true */ + TEST_CF_SECRET( X, bytes ); + TEST_CF_SECRET( Y, bytes ); + + mbedtls_mpi_core_cond_assign( X, Y, copy_limbs, 1 ); + + TEST_CF_PUBLIC( X, bytes ); + TEST_CF_PUBLIC( Y, bytes ); + + /* Check if the given length is copied even it is smaller + than the length of the given MPIs. */ + if( copy_limbs < limbs ) + { + ASSERT_COMPARE( X, copy_bytes, Y, copy_bytes ); + TEST_ASSERT( memcmp( X, Y, bytes ) != 0 ); + } + else + ASSERT_COMPARE( X, bytes, Y, bytes ); + +exit: + mbedtls_free( X ); + mbedtls_free( Y ); +} +/* END_CASE */ + +/* BEGIN_CASE */ +void mpi_core_cond_swap( data_t * input_X, + data_t * input_Y, + int input_bytes ) +{ + mbedtls_mpi_uint *tmp_X = NULL; + mbedtls_mpi_uint *tmp_Y = NULL; + mbedtls_mpi_uint *X = NULL; + mbedtls_mpi_uint *Y = NULL; + size_t limbs_X = CHARS_TO_LIMBS( input_X->len ); + size_t limbs_Y = CHARS_TO_LIMBS( input_Y->len ); + size_t limbs = limbs_X; + size_t copy_limbs = CHARS_TO_LIMBS( input_bytes ); + size_t bytes = limbs * sizeof( mbedtls_mpi_uint ); + size_t copy_bytes = copy_limbs * sizeof( mbedtls_mpi_uint ); + + TEST_EQUAL( limbs_X, limbs_Y ); + TEST_ASSERT( copy_limbs <= limbs ); + + ASSERT_ALLOC( tmp_X, limbs ); + ASSERT_ALLOC( tmp_Y, limbs ); + + TEST_ASSERT( mbedtls_mpi_core_read_be( tmp_X, limbs, + input_X->x, input_X->len ) + == 0 ); + ASSERT_ALLOC( X, limbs ); + memcpy( X, tmp_X, bytes ); + + TEST_ASSERT( mbedtls_mpi_core_read_be( tmp_Y, limbs, + input_Y->x, input_Y->len ) + == 0 ); + ASSERT_ALLOC( Y, limbs ); + memcpy( Y, tmp_Y, bytes ); + + /* condition is false */ + TEST_CF_SECRET( X, bytes ); + TEST_CF_SECRET( Y, bytes ); + + mbedtls_mpi_core_cond_swap( X, Y, copy_limbs, 0 ); + + TEST_CF_PUBLIC( X, bytes ); + TEST_CF_PUBLIC( Y, bytes ); + + ASSERT_COMPARE( X, bytes, tmp_X, bytes ); + ASSERT_COMPARE( Y, bytes, tmp_Y, bytes ); + + /* condition is true */ + TEST_CF_SECRET( X, bytes ); + TEST_CF_SECRET( Y, bytes ); + + mbedtls_mpi_core_cond_swap( X, Y, copy_limbs, 1 ); + + TEST_CF_PUBLIC( X, bytes ); + TEST_CF_PUBLIC( Y, bytes ); + + /* Check if the given length is copied even it is smaller + than the length of the given MPIs. */ + if( copy_limbs < limbs ) + { + ASSERT_COMPARE( X, copy_bytes, tmp_Y, copy_bytes ); + ASSERT_COMPARE( Y, copy_bytes, tmp_X, copy_bytes ); + TEST_ASSERT( memcmp( X, tmp_X, bytes ) != 0 ); + TEST_ASSERT( memcmp( X, tmp_Y, bytes ) != 0 ); + TEST_ASSERT( memcmp( Y, tmp_X, bytes ) != 0 ); + TEST_ASSERT( memcmp( Y, tmp_Y, bytes ) != 0 ); + } + else + { + ASSERT_COMPARE( X, bytes, tmp_Y, bytes ); + ASSERT_COMPARE( Y, bytes, tmp_X, bytes ); + } + +exit: + mbedtls_free( tmp_X ); + mbedtls_free( tmp_Y ); + mbedtls_free( X ); + mbedtls_free( Y ); +} +/* END_CASE */ + +/* BEGIN_CASE */ +void mpi_mod_raw_cond_assign( data_t * input_X, + data_t * input_Y, + int input_bytes ) +{ + mbedtls_mpi_uint *X = NULL; + mbedtls_mpi_uint *Y = NULL; + mbedtls_mpi_uint *buff_m = NULL; + mbedtls_mpi_mod_modulus m; + size_t limbs_X = CHARS_TO_LIMBS( input_X->len ); + size_t limbs_Y = CHARS_TO_LIMBS( input_Y->len ); + size_t limbs = limbs_X; + size_t copy_limbs = CHARS_TO_LIMBS( input_bytes ); + size_t bytes = limbs * sizeof( mbedtls_mpi_uint ); + size_t copy_bytes = copy_limbs * sizeof( mbedtls_mpi_uint ); + + TEST_EQUAL( limbs_X, limbs_Y ); + TEST_ASSERT( copy_limbs <= limbs ); + + ASSERT_ALLOC( X, limbs ); + ASSERT_ALLOC( Y, limbs ); + + ASSERT_ALLOC( buff_m, limbs ); + mbedtls_mpi_mod_modulus_init( &m ); + TEST_ASSERT( mbedtls_mpi_mod_modulus_setup( + &m, buff_m, copy_limbs, + MBEDTLS_MPI_MOD_EXT_REP_BE, + MBEDTLS_MPI_MOD_REP_MONTGOMERY ) + == 0 ); + + TEST_ASSERT( mbedtls_mpi_core_read_be( X, limbs, + input_X->x, input_X->len ) + == 0 ); + + TEST_ASSERT( mbedtls_mpi_core_read_be( Y, limbs, + input_Y->x, input_Y->len ) + == 0 ); + + /* condition is false */ + TEST_CF_SECRET( X, bytes ); + TEST_CF_SECRET( Y, bytes ); + + mbedtls_mpi_mod_raw_cond_assign( X, Y, &m, 0 ); + + TEST_CF_PUBLIC( X, bytes ); + TEST_CF_PUBLIC( Y, bytes ); + + TEST_ASSERT( memcmp( X, Y, bytes ) != 0 ); + + /* condition is true */ + TEST_CF_SECRET( X, bytes ); + TEST_CF_SECRET( Y, bytes ); + + mbedtls_mpi_mod_raw_cond_assign( X, Y, &m, 1 ); + + TEST_CF_PUBLIC( X, bytes ); + TEST_CF_PUBLIC( Y, bytes ); + + /* Check if the given length is copied even it is smaller + than the length of the given MPIs. */ + if( copy_limbs len ); + size_t limbs_Y = CHARS_TO_LIMBS( input_Y->len ); + size_t limbs = limbs_X; + size_t copy_limbs = CHARS_TO_LIMBS( input_bytes ); + size_t bytes = limbs * sizeof( mbedtls_mpi_uint ); + size_t copy_bytes = copy_limbs * sizeof( mbedtls_mpi_uint ); + + TEST_EQUAL( limbs_X, limbs_Y ); + TEST_ASSERT( copy_limbs <= limbs ); + + ASSERT_ALLOC( tmp_X, limbs ); + ASSERT_ALLOC( tmp_Y, limbs ); + + ASSERT_ALLOC( buff_m, copy_limbs ); + mbedtls_mpi_mod_modulus_init( &m ); + TEST_ASSERT( mbedtls_mpi_mod_modulus_setup( + &m, buff_m, copy_limbs, + MBEDTLS_MPI_MOD_EXT_REP_BE, + MBEDTLS_MPI_MOD_REP_MONTGOMERY ) + == 0 ); + + TEST_ASSERT( mbedtls_mpi_core_read_be( tmp_X, limbs, input_X->x, input_X->len ) + == 0 ); + ASSERT_ALLOC( X, limbs ); + memcpy( X, tmp_X, bytes ); + + TEST_ASSERT( mbedtls_mpi_core_read_be( tmp_Y, limbs, input_Y->x, input_Y->len ) + == 0 ); + ASSERT_ALLOC( Y, bytes ); + memcpy( Y, tmp_Y, bytes ); + + /* condition is false */ + TEST_CF_SECRET( X, bytes ); + TEST_CF_SECRET( Y, bytes ); + + mbedtls_mpi_mod_raw_cond_swap( X, Y, &m, 0 ); + + TEST_CF_PUBLIC( X, bytes ); + TEST_CF_PUBLIC( Y, bytes ); + + ASSERT_COMPARE( X, bytes, tmp_X, bytes ); + ASSERT_COMPARE( Y, bytes, tmp_Y, bytes ); + + /* condition is true */ + TEST_CF_SECRET( X, bytes ); + TEST_CF_SECRET( Y, bytes ); + + mbedtls_mpi_mod_raw_cond_swap( X, Y, &m, 1 ); + + TEST_CF_PUBLIC( X, bytes ); + TEST_CF_PUBLIC( Y, bytes ); + + /* Check if the given length is copied even it is smaller + than the length of the given MPIs. */ + if( copy_limbs < limbs ) + { + ASSERT_COMPARE( X, copy_bytes, tmp_Y, copy_bytes ); + ASSERT_COMPARE( Y, copy_bytes, tmp_X, copy_bytes ); + TEST_ASSERT( memcmp( X, tmp_X, bytes ) != 0 ); + TEST_ASSERT( memcmp( X, tmp_Y, bytes ) != 0 ); + TEST_ASSERT( memcmp( Y, tmp_X, bytes ) != 0 ); + TEST_ASSERT( memcmp( Y, tmp_Y, bytes ) != 0 ); + } + else + { + ASSERT_COMPARE( X, bytes, tmp_Y, bytes ); + ASSERT_COMPARE( Y, bytes, tmp_X, bytes ); + } + +exit: + mbedtls_free( tmp_X ); + mbedtls_free( tmp_Y ); + mbedtls_free( X ); + mbedtls_free( Y ); + + mbedtls_mpi_mod_modulus_free( &m ); + mbedtls_free( buff_m ); +} +/* END_CASE */ + /* BEGIN_CASE */ void mpi_lt_mpi_ct( int size_X, char * input_X, int size_Y, char * input_Y,