From e1b6b7c0ac6b1862ec745f7b514a54b50e99d501 Mon Sep 17 00:00:00 2001 From: Werner Lewis Date: Tue, 29 Nov 2022 12:25:05 +0000 Subject: [PATCH 1/7] Implement mbedtls_mpi_mod_add() Signed-off-by: Werner Lewis --- library/bignum_mod.c | 11 ++ library/bignum_mod.h | 30 +++++- scripts/mbedtls_dev/bignum_mod.py | 14 +++ tests/suites/test_suite_bignum_mod.data | 19 ++++ tests/suites/test_suite_bignum_mod.function | 111 ++++++++++++++++++++ 5 files changed, 184 insertions(+), 1 deletion(-) diff --git a/library/bignum_mod.c b/library/bignum_mod.c index 7cf2fb22c9..0057ebae21 100644 --- a/library/bignum_mod.c +++ b/library/bignum_mod.c @@ -198,7 +198,18 @@ int mbedtls_mpi_mod_sub( mbedtls_mpi_mod_residue *X, /* 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 0a8f4d3d0c..26d31d4c53 100644 --- a/library/bignum_mod.h +++ b/library/bignum_mod.h @@ -199,7 +199,35 @@ int mbedtls_mpi_mod_sub( mbedtls_mpi_mod_residue *X, /* 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 aa06fe8634..9086c2eb51 100644 --- a/scripts/mbedtls_dev/bignum_mod.py +++ b/scripts/mbedtls_dev/bignum_mod.py @@ -55,6 +55,20 @@ class BignumModSub(bignum_common.ModOperationCommon, BignumModTarget): # 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 501d9d7d8b..7b1c85fb06 100644 --- a/tests/suites/test_suite_bignum_mod.data +++ b/tests/suites/test_suite_bignum_mod.data @@ -45,7 +45,26 @@ mpi_mod_sub:"014320a022ccb75bdf470ddf25":"000000025a55a46e5da99c71c7":"e8000f93" # 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 0d2e232f91..0676fbb50c 100644 --- a/tests/suites/test_suite_bignum_mod.function +++ b/tests/suites/test_suite_bignum_mod.function @@ -210,7 +210,118 @@ exit: /* 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 */ From 93a31c9efd1857b20aeeb2b5cbc69acb2b7d3c0f Mon Sep 17 00:00:00 2001 From: Werner Lewis Date: Tue, 6 Dec 2022 10:14:57 +0000 Subject: [PATCH 2/7] Re-enable pylint unused warnings Signed-off-by: Werner Lewis --- scripts/mbedtls_dev/bignum_mod.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/mbedtls_dev/bignum_mod.py b/scripts/mbedtls_dev/bignum_mod.py index 9086c2eb51..a16699a642 100644 --- a/scripts/mbedtls_dev/bignum_mod.py +++ b/scripts/mbedtls_dev/bignum_mod.py @@ -14,10 +14,10 @@ # See the License for the specific language governing permissions and # limitations under the License. -from typing import Dict, List # pylint: disable=unused-import +from typing import Dict, List from . import test_data_generation -from . import bignum_common # pylint: disable=unused-import +from . import bignum_common class BignumModTarget(test_data_generation.BaseTarget): #pylint: disable=abstract-method, too-few-public-methods From 3f2999ad256a022e7c6fdc1cd031bc6dece7c911 Mon Sep 17 00:00:00 2001 From: Werner Lewis Date: Tue, 6 Dec 2022 10:17:58 +0000 Subject: [PATCH 3/7] Rename test_suite_bignum_mod.data for consistency Use the same naming convention as bignum and bignum_core now that test data is generated. Signed-off-by: Werner Lewis --- ...test_suite_bignum_mod.data => test_suite_bignum_mod.misc.data} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename tests/suites/{test_suite_bignum_mod.data => test_suite_bignum_mod.misc.data} (100%) diff --git a/tests/suites/test_suite_bignum_mod.data b/tests/suites/test_suite_bignum_mod.misc.data similarity index 100% rename from tests/suites/test_suite_bignum_mod.data rename to tests/suites/test_suite_bignum_mod.misc.data From 25690a98f08ce3bc1ba8f4d0675ab2e7fb876598 Mon Sep 17 00:00:00 2001 From: Werner Lewis Date: Tue, 13 Dec 2022 17:17:34 +0000 Subject: [PATCH 4/7] Rename oret to expected_ret Signed-off-by: Werner Lewis --- tests/suites/test_suite_bignum_mod.function | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tests/suites/test_suite_bignum_mod.function b/tests/suites/test_suite_bignum_mod.function index 0676fbb50c..d65bb6e2db 100644 --- a/tests/suites/test_suite_bignum_mod.function +++ b/tests/suites/test_suite_bignum_mod.function @@ -213,7 +213,7 @@ exit: /* BEGIN_CASE */ void mpi_mod_add( char * input_N, char * input_A, char * input_B, - char * input_S, int oret ) + char * input_S, int expected_ret ) { mbedtls_mpi_mod_residue a = { NULL, 0 }; mbedtls_mpi_mod_residue b = { NULL, 0 }; @@ -230,9 +230,9 @@ void mpi_mod_add( char * 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 ) ); + TEST_EQUAL( 0, test_read_residue( &a, &m, input_A, expected_ret != 0 ) ); + TEST_EQUAL( 0, test_read_residue( &b, &m, input_B, expected_ret != 0 ) ); + TEST_EQUAL( 0, test_read_residue( &s, &m, input_S, expected_ret != 0 ) ); size_t limbs = m.limbs; size_t bytes = limbs * sizeof( *X_raw ); @@ -240,7 +240,7 @@ void mpi_mod_add( char * input_N, /* One spare limb for negative testing */ ASSERT_ALLOC( X_raw, limbs + 1 ); - if( oret == 0 ) + if( expected_ret == 0 ) { /* Negative test with too many limbs in output */ x.p = X_raw; @@ -264,8 +264,8 @@ void mpi_mod_add( char * input_N, 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 ) + TEST_EQUAL( expected_ret, mbedtls_mpi_mod_add( &x, &a, &b, &m ) ); + if( expected_ret != 0 ) goto exit; TEST_COMPARE_MPI_RESIDUES( x, s ); From eed01aabd388aeec102ac3e4847152d47c695e07 Mon Sep 17 00:00:00 2001 From: Werner Lewis Date: Tue, 13 Dec 2022 17:18:17 +0000 Subject: [PATCH 5/7] Clarify wording in documentation Signed-off-by: Werner Lewis --- library/bignum_mod.h | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/library/bignum_mod.h b/library/bignum_mod.h index 26d31d4c53..11b4e980f0 100644 --- a/library/bignum_mod.h +++ b/library/bignum_mod.h @@ -204,7 +204,8 @@ int mbedtls_mpi_mod_sub( mbedtls_mpi_mod_residue *X, * * Calculate `A + B modulo N`. * - * \p A, \p B and \p X must all have the same number of limbs as \p N. + * \p A, \p B and \p X must all be associated with the modulus \p N and 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. @@ -213,10 +214,10 @@ int mbedtls_mpi_mod_sub( mbedtls_mpi_mod_residue *X, * 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. + * \param[out] X The address of the result residue. 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] A The address of the first input residue. + * \param[in] B The address of the second input residue. * \param[in] N The address of the modulus. Used to perform a modulo * operation on the result of the addition. * From 79341a4e7ec46858096cc601fd51dc617e9e24f3 Mon Sep 17 00:00:00 2001 From: Werner Lewis Date: Tue, 13 Dec 2022 17:19:01 +0000 Subject: [PATCH 6/7] Reallocate X_raw to enforce no overflow Signed-off-by: Werner Lewis --- tests/suites/test_suite_bignum_mod.function | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/tests/suites/test_suite_bignum_mod.function b/tests/suites/test_suite_bignum_mod.function index d65bb6e2db..abe4dee40f 100644 --- a/tests/suites/test_suite_bignum_mod.function +++ b/tests/suites/test_suite_bignum_mod.function @@ -237,30 +237,40 @@ void mpi_mod_add( char * input_N, 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( expected_ret == 0 ) { /* Negative test with too many limbs in output */ + ASSERT_ALLOC( X_raw, 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 ) ); + mbedtls_free( X_raw ); + X_raw = NULL; + /* Negative test with too few limbs in output */ if( limbs > 1 ) { + ASSERT_ALLOC( X_raw, 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 ) ); + + mbedtls_free( X_raw ); + X_raw = NULL; } /* Negative testing with too many/too few limbs in a and b is covered by * manually-written test cases with oret != 0. */ } + /* Allocate correct number of limbs for X_raw */ + ASSERT_ALLOC( X_raw, limbs ); + TEST_EQUAL( 0, mbedtls_mpi_mod_residue_setup( &x, &m, X_raw, limbs ) ); /* A + B => Correct result or expected error */ From ca906e9dd73e0caafa2ae2b34127b3a92d44aa4b Mon Sep 17 00:00:00 2001 From: Werner Lewis Date: Tue, 13 Dec 2022 17:19:57 +0000 Subject: [PATCH 7/7] Remove B + A tests Signed-off-by: Werner Lewis --- tests/suites/test_suite_bignum_mod.function | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/tests/suites/test_suite_bignum_mod.function b/tests/suites/test_suite_bignum_mod.function index abe4dee40f..507920afd3 100644 --- a/tests/suites/test_suite_bignum_mod.function +++ b/tests/suites/test_suite_bignum_mod.function @@ -303,24 +303,6 @@ void mpi_mod_add( char * input_N, 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 */