diff --git a/library/bignum_mod_raw.c b/library/bignum_mod_raw.c index 6c694b0c58..2f49ea2d9e 100644 --- a/library/bignum_mod_raw.c +++ b/library/bignum_mod_raw.c @@ -129,7 +129,16 @@ void mbedtls_mpi_mod_raw_sub( mbedtls_mpi_uint *X, /* END MERGE SLOT 4 */ /* BEGIN MERGE SLOT 5 */ - +void mbedtls_mpi_mod_raw_add( mbedtls_mpi_uint *X, + const mbedtls_mpi_uint *A, + const mbedtls_mpi_uint *B, + const mbedtls_mpi_mod_modulus *N ) +{ + mbedtls_mpi_uint carry, borrow; + carry = mbedtls_mpi_core_add( X, A, B, N->limbs ); + borrow = mbedtls_mpi_core_sub( X, X, N->p, N->limbs ); + (void) mbedtls_mpi_core_add_if( X, N->p, N->limbs, (unsigned) ( carry ^ borrow ) ); +} /* END MERGE SLOT 5 */ /* BEGIN MERGE SLOT 6 */ diff --git a/library/bignum_mod_raw.h b/library/bignum_mod_raw.h index 05fa9d6ac8..f6c6ebd8f2 100644 --- a/library/bignum_mod_raw.h +++ b/library/bignum_mod_raw.h @@ -177,7 +177,28 @@ void mbedtls_mpi_mod_raw_sub( mbedtls_mpi_uint *X, /* END MERGE SLOT 4 */ /* BEGIN MERGE SLOT 5 */ - +/** + * \brief Perform a known-size modular addition. + * + * Calculate `A + B modulo N`. + * + * The number of limbs in each operand, and the result, is given by the + * modulus \p N. + * + * \p X may be aliased to \p A or \p B, or even both, but may not overlap + * either otherwise. + * + * \param[out] X The result of the modular addition. + * \param[in] A Little-endian presentation of the left operand. This + * must be smaller than \p N. + * \param[in] B Little-endian presentation of the right operand. This + * must be smaller than \p N. + * \param[in] N The address of the modulus. + */ +void mbedtls_mpi_mod_raw_add( mbedtls_mpi_uint *X, + const mbedtls_mpi_uint *A, + const mbedtls_mpi_uint *B, + const mbedtls_mpi_mod_modulus *N ); /* END MERGE SLOT 5 */ /* BEGIN MERGE SLOT 6 */ diff --git a/scripts/mbedtls_dev/bignum_mod_raw.py b/scripts/mbedtls_dev/bignum_mod_raw.py index c271048548..0bbad5dd90 100644 --- a/scripts/mbedtls_dev/bignum_mod_raw.py +++ b/scripts/mbedtls_dev/bignum_mod_raw.py @@ -61,6 +61,19 @@ class BignumModRawSub(bignum_common.ModOperationCommon, # BEGIN MERGE SLOT 5 +class BignumModRawAdd(bignum_common.ModOperationCommon, + BignumModRawTarget): + """Test cases for bignum mpi_mod_raw_add().""" + symbol = "+" + test_function = "mpi_mod_raw_add" + test_name = "mbedtls_mpi_mod_raw_add" + input_style = "fixed" + arity = 2 + + def result(self) -> List[str]: + result = (self.int_a + self.int_b) % self.int_n + return [self.format_result(result)] + # END MERGE SLOT 5 # BEGIN MERGE SLOT 6 diff --git a/tests/suites/test_suite_bignum_mod_raw.function b/tests/suites/test_suite_bignum_mod_raw.function index 2d9e412280..00ed005f50 100644 --- a/tests/suites/test_suite_bignum_mod_raw.function +++ b/tests/suites/test_suite_bignum_mod_raw.function @@ -360,6 +360,98 @@ exit: /* BEGIN MERGE SLOT 5 */ +/* BEGIN_CASE */ +void mpi_mod_raw_add( char * input_N, + char * input_A, char * input_B, + char * input_S ) +{ + mbedtls_mpi_uint *A = NULL; + mbedtls_mpi_uint *B = NULL; + mbedtls_mpi_uint *S = NULL; + mbedtls_mpi_uint *N = NULL; + mbedtls_mpi_uint *X = NULL; + size_t A_limbs, B_limbs, N_limbs, S_limbs; + + mbedtls_mpi_mod_modulus m; + mbedtls_mpi_mod_modulus_init( &m ); + + TEST_EQUAL( 0, mbedtls_test_read_mpi_core( &A, &A_limbs, input_A ) ); + TEST_EQUAL( 0, mbedtls_test_read_mpi_core( &B, &B_limbs, input_B ) ); + TEST_EQUAL( 0, mbedtls_test_read_mpi_core( &N, &N_limbs, input_N ) ); + TEST_EQUAL( 0, mbedtls_test_read_mpi_core( &S, &S_limbs, input_S ) ); + + /* Modulus gives the number of limbs; all inputs must have the same. */ + size_t limbs = N_limbs; + size_t bytes = limbs * sizeof( *A ); + + TEST_EQUAL( A_limbs, limbs ); + TEST_EQUAL( B_limbs, limbs ); + TEST_EQUAL( S_limbs, limbs ); + + ASSERT_ALLOC( X, limbs ); + + TEST_EQUAL( mbedtls_mpi_mod_modulus_setup( + &m, N, limbs, + MBEDTLS_MPI_MOD_EXT_REP_BE, + MBEDTLS_MPI_MOD_REP_MONTGOMERY + ), 0 ); + + /* A + B => Correct result */ + mbedtls_mpi_mod_raw_add( X, A, B, &m ); + ASSERT_COMPARE( X, bytes, S, bytes ); + + /* A + B: alias X to A => Correct result */ + memcpy( X, A, bytes ); + mbedtls_mpi_mod_raw_add( X, X, B, &m ); + ASSERT_COMPARE( X, bytes, S, bytes ); + + /* A + B: alias X to B => Correct result */ + memcpy( X, B, bytes ); + mbedtls_mpi_mod_raw_add( X, A, X, &m ); + ASSERT_COMPARE( X, bytes, S, bytes ); + + if ( memcmp(A, B, bytes ) == 0 ) + { + /* A == B: alias A and B */ + + /* A + A => Correct result */ + mbedtls_mpi_mod_raw_add( X, A, A, &m ); + ASSERT_COMPARE( X, bytes, S, bytes ); + + /* A + A: X, A, B all aliased together => Correct result */ + memcpy( X, A, bytes ); + mbedtls_mpi_mod_raw_add( X, X, X, &m ); + ASSERT_COMPARE( X, bytes, S, bytes ); + } + else + { + /* A != B: test B + A */ + + /* B + A => Correct result */ + mbedtls_mpi_mod_raw_add( X, B, A, &m ); + ASSERT_COMPARE( X, bytes, S, bytes ); + + /* B + A: alias X to A => Correct result */ + memcpy( X, A, bytes ); + mbedtls_mpi_mod_raw_add( X, B, X, &m ); + ASSERT_COMPARE( X, bytes, S, bytes ); + + /* B + A: alias X to B => Correct result */ + memcpy( X, B, bytes ); + mbedtls_mpi_mod_raw_add( X, X, A, &m ); + ASSERT_COMPARE( X, bytes, S, bytes ); + } + +exit: + mbedtls_mpi_mod_modulus_free( &m ); + + mbedtls_free( A ); + mbedtls_free( B ); + mbedtls_free( S ); + mbedtls_free( N ); + mbedtls_free( X ); +} +/* END_CASE */ /* END MERGE SLOT 5 */ /* BEGIN MERGE SLOT 6 */