Implement mbedtls_mpi_mod_add()
Signed-off-by: Werner Lewis <werner.lewis@arm.com>
diff --git a/library/bignum_mod.c b/library/bignum_mod.c
index 7cf2fb2..0057eba 100644
--- a/library/bignum_mod.c
+++ b/library/bignum_mod.c
@@ -198,7 +198,18 @@
/* END MERGE SLOT 4 */
/* BEGIN MERGE SLOT 5 */
+int mbedtls_mpi_mod_add( mbedtls_mpi_mod_residue *X,
+ const mbedtls_mpi_mod_residue *A,
+ const mbedtls_mpi_mod_residue *B,
+ const mbedtls_mpi_mod_modulus *N )
+{
+ if( X->limbs != N->limbs || A->limbs != N->limbs || B->limbs != N->limbs )
+ return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
+ mbedtls_mpi_mod_raw_add(X->p, A->p, B->p, N);
+
+ return( 0 );
+}
/* END MERGE SLOT 5 */
/* BEGIN MERGE SLOT 6 */
diff --git a/library/bignum_mod.h b/library/bignum_mod.h
index 0a8f4d3..26d31d4 100644
--- a/library/bignum_mod.h
+++ b/library/bignum_mod.h
@@ -199,7 +199,35 @@
/* END MERGE SLOT 4 */
/* BEGIN MERGE SLOT 5 */
-
+/**
+ * \brief Perform a fixed-size modular addition.
+ *
+ * Calculate `A + B modulo N`.
+ *
+ * \p A, \p B and \p X must all have the same number of limbs as \p N.
+ *
+ * \p X may be aliased to \p A or \p B, or even both, but may not overlap
+ * either otherwise.
+ *
+ * \note This function does not check that \p A or \p B are in canonical
+ * form (that is, are < \p N) - that will have been done by
+ * mbedtls_mpi_mod_residue_setup().
+ *
+ * \param[out] X The address of the result MPI. Must be initialized.
+ * Must have the same number of limbs as the modulus \p N.
+ * \param[in] A The address of the first MPI.
+ * \param[in] B The address of the second MPI.
+ * \param[in] N The address of the modulus. Used to perform a modulo
+ * operation on the result of the addition.
+ *
+ * \return \c 0 if successful.
+ * \return #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if the given MPIs do not
+ * have the correct number of limbs.
+ */
+int mbedtls_mpi_mod_add( mbedtls_mpi_mod_residue *X,
+ const mbedtls_mpi_mod_residue *A,
+ const mbedtls_mpi_mod_residue *B,
+ const mbedtls_mpi_mod_modulus *N );
/* END MERGE SLOT 5 */
/* BEGIN MERGE SLOT 6 */
diff --git a/scripts/mbedtls_dev/bignum_mod.py b/scripts/mbedtls_dev/bignum_mod.py
index aa06fe8..9086c2e 100644
--- a/scripts/mbedtls_dev/bignum_mod.py
+++ b/scripts/mbedtls_dev/bignum_mod.py
@@ -55,6 +55,20 @@
# END MERGE SLOT 4
# BEGIN MERGE SLOT 5
+class BignumModAdd(bignum_common.ModOperationCommon, BignumModTarget):
+ """Test cases for bignum mpi_mod_add()."""
+ count = 0
+ symbol = "+"
+ test_function = "mpi_mod_add"
+ test_name = "mbedtls_mpi_mod_add"
+ input_style = "fixed"
+
+ def result(self) -> List[str]:
+ result = (self.int_a + self.int_b) % self.int_n
+ # To make negative tests easier, append "0" for success to the
+ # generated cases
+ return [self.format_result(result), "0"]
+
# END MERGE SLOT 5
diff --git a/tests/suites/test_suite_bignum_mod.data b/tests/suites/test_suite_bignum_mod.data
index 501d9d7..7b1c85f 100644
--- a/tests/suites/test_suite_bignum_mod.data
+++ b/tests/suites/test_suite_bignum_mod.data
@@ -45,7 +45,26 @@
# END MERGE SLOT 4
# BEGIN MERGE SLOT 5
+mpi_mod_add base case for negative testing (N, a, b all >= 1 limb)
+mpi_mod_add:"014320a022ccb75bdf470ddf25":"000000025a55a46e5da99c71c7":"00033b2e3c9fd0803ce8000f93":"00033b3096f574ee9a919c815a":0
+mpi_mod_add with modulus too long/both inputs too short
+mpi_mod_add:"0000000014320a022ccb75bdf470ddf25":"000000025a55a46e5da99c71c7":"00033b2e3c9fd0803ce8000f93":"00":MBEDTLS_ERR_MPI_BAD_INPUT_DATA
+
+mpi_mod_add with first input too long
+mpi_mod_add:"014320a022ccb75bdf470ddf25":"0000000000000025a55a46e5da99c71c7":"00033b2e3c9fd0803ce8000f93":"00":MBEDTLS_ERR_MPI_BAD_INPUT_DATA
+
+mpi_mod_add with second input too long
+mpi_mod_add:"014320a022ccb75bdf470ddf25":"000000025a55a46e5da99c71c7":"000000000033b2e3c9fd0803ce8000f93":"00":MBEDTLS_ERR_MPI_BAD_INPUT_DATA
+
+mpi_mod_add with both inputs too long
+mpi_mod_add:"014320a022ccb75bdf470ddf25":"0000000000000025a55a46e5da99c71c7":"000000000033b2e3c9fd0803ce8000f93":"00":MBEDTLS_ERR_MPI_BAD_INPUT_DATA
+
+mpi_mod_add with first input too short
+mpi_mod_add:"014320a022ccb75bdf470ddf25":"a99c71c7":"00033b2e3c9fd0803ce8000f93":"00":MBEDTLS_ERR_MPI_BAD_INPUT_DATA
+
+mpi_mod_add with second input too short
+mpi_mod_add:"014320a022ccb75bdf470ddf25":"000000025a55a46e5da99c71c7":"e8000f93":"00":MBEDTLS_ERR_MPI_BAD_INPUT_DATA
# END MERGE SLOT 5
# BEGIN MERGE SLOT 6
diff --git a/tests/suites/test_suite_bignum_mod.function b/tests/suites/test_suite_bignum_mod.function
index 0d2e232..0676fbb 100644
--- a/tests/suites/test_suite_bignum_mod.function
+++ b/tests/suites/test_suite_bignum_mod.function
@@ -210,7 +210,118 @@
/* END MERGE SLOT 4 */
/* BEGIN MERGE SLOT 5 */
+/* BEGIN_CASE */
+void mpi_mod_add( char * input_N,
+ char * input_A, char * input_B,
+ char * input_S, int oret )
+{
+ mbedtls_mpi_mod_residue a = { NULL, 0 };
+ mbedtls_mpi_mod_residue b = { NULL, 0 };
+ mbedtls_mpi_mod_residue s = { NULL, 0 };
+ mbedtls_mpi_mod_residue x = { NULL, 0 };
+ mbedtls_mpi_uint *X_raw = NULL;
+ mbedtls_mpi_mod_modulus m;
+ mbedtls_mpi_mod_modulus_init( &m );
+
+ TEST_EQUAL( 0,
+ test_read_modulus( &m, MBEDTLS_MPI_MOD_REP_MONTGOMERY, input_N ) );
+
+ /* test_read_residue() normally checks that inputs have the same number of
+ * limbs as the modulus. For negative testing we can ask it to skip this
+ * with a non-zero final parameter. */
+ TEST_EQUAL( 0, test_read_residue( &a, &m, input_A, oret != 0 ) );
+ TEST_EQUAL( 0, test_read_residue( &b, &m, input_B, oret != 0 ) );
+ TEST_EQUAL( 0, test_read_residue( &s, &m, input_S, oret != 0 ) );
+
+ size_t limbs = m.limbs;
+ size_t bytes = limbs * sizeof( *X_raw );
+
+ /* One spare limb for negative testing */
+ ASSERT_ALLOC( X_raw, limbs + 1 );
+
+ if( oret == 0 )
+ {
+ /* Negative test with too many limbs in output */
+ x.p = X_raw;
+ x.limbs = limbs + 1;
+ TEST_EQUAL( MBEDTLS_ERR_MPI_BAD_INPUT_DATA,
+ mbedtls_mpi_mod_add( &x, &a, &b, &m ) );
+
+ /* Negative test with too few limbs in output */
+ if( limbs > 1 )
+ {
+ x.p = X_raw;
+ x.limbs = limbs - 1;
+ TEST_EQUAL( MBEDTLS_ERR_MPI_BAD_INPUT_DATA,
+ mbedtls_mpi_mod_add( &x, &a, &b, &m ) );
+ }
+
+ /* Negative testing with too many/too few limbs in a and b is covered by
+ * manually-written test cases with oret != 0. */
+ }
+
+ TEST_EQUAL( 0, mbedtls_mpi_mod_residue_setup( &x, &m, X_raw, limbs ) );
+
+ /* A + B => Correct result or expected error */
+ TEST_EQUAL( oret, mbedtls_mpi_mod_add( &x, &a, &b, &m ) );
+ if( oret != 0 )
+ goto exit;
+
+ TEST_COMPARE_MPI_RESIDUES( x, s );
+
+ /* a + b: alias x to a => Correct result */
+ memcpy( x.p, a.p, bytes );
+ TEST_EQUAL( 0, mbedtls_mpi_mod_add( &x, &x, &b, &m ) );
+ TEST_COMPARE_MPI_RESIDUES( x, s );
+
+ /* a + b: alias x to b => Correct result */
+ memcpy( x.p, b.p, bytes );
+ TEST_EQUAL( 0, mbedtls_mpi_mod_add( &x, &a, &x, &m ) );
+ TEST_COMPARE_MPI_RESIDUES( x, s );
+
+ if ( memcmp( a.p, b.p, bytes ) == 0 )
+ {
+ /* a == b: alias a and b */
+
+ /* a + a => Correct result */
+ TEST_EQUAL( 0, mbedtls_mpi_mod_add( &x, &a, &a, &m ) );
+ TEST_COMPARE_MPI_RESIDUES( x, s );
+
+ /* a + a: x, a, b all aliased together => Correct result */
+ memcpy( x.p, a.p, bytes );
+ TEST_EQUAL( 0, mbedtls_mpi_mod_add( &x, &x, &x, &m ) );
+ TEST_COMPARE_MPI_RESIDUES( x, s );
+ }
+ else
+ {
+ /* a != b: test b + a */
+
+ /* b + a => Correct result */
+ mbedtls_mpi_mod_add( &x, &b, &a, &m );
+ TEST_COMPARE_MPI_RESIDUES( x, s );
+
+ /* b + a: alias x to a => Correct result */
+ memcpy( x.p, a.p, bytes );
+ TEST_EQUAL( 0, mbedtls_mpi_mod_add( &x, &b, &x, &m ) );
+ TEST_COMPARE_MPI_RESIDUES( x, s );
+
+ /* b + a: alias x to b => Correct result */
+ memcpy( x.p, b.p, bytes );
+ TEST_EQUAL( 0, mbedtls_mpi_mod_add( &x, &x, &a, &m ) );
+ TEST_COMPARE_MPI_RESIDUES( x, s );
+ }
+
+exit:
+ mbedtls_free( (void *)m.p ); /* mbedtls_mpi_mod_modulus_free() sets m.p = NULL */
+ mbedtls_mpi_mod_modulus_free( &m );
+
+ mbedtls_free( a.p );
+ mbedtls_free( b.p );
+ mbedtls_free( s.p );
+ mbedtls_free( X_raw );
+}
+/* END_CASE */
/* END MERGE SLOT 5 */
/* BEGIN MERGE SLOT 6 */