From efd242a0e5e79759a98e99c1959987f8b5fa890a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Thu, 24 Jul 2025 11:10:59 +0200 Subject: [PATCH] Gracefully handle A_limbs > N_limbs and test it MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Manuel Pégourié-Gonnard --- library/bignum_core.c | 7 +- library/bignum_core.h | 2 +- tests/suites/test_suite_bignum_core.function | 104 ++++++++++++++++++ tests/suites/test_suite_bignum_core.misc.data | 3 + 4 files changed, 113 insertions(+), 3 deletions(-) diff --git a/library/bignum_core.c b/library/bignum_core.c index 49a966fb3f..8ac65e2202 100644 --- a/library/bignum_core.c +++ b/library/bignum_core.c @@ -1123,12 +1123,15 @@ void mbedtls_mpi_core_gcd_modinv_odd(mbedtls_mpi_uint *G, * We only write to G (aka v) after reading from inputs (A and N), which * allows aliasing, except with N when I != NULL, as then we'll be operating * mod N on q and r later - see the public documentation. - * - * Also avoid possible UB with memcpy when src == dst. */ + if (A_limbs > N_limbs) { + /* Violating this precondition should not result in memory errors. */ + A_limbs = N_limbs; + } memcpy(u, A, A_limbs * ciL); memset((char *) u + A_limbs * ciL, 0, (N_limbs - A_limbs) * ciL); + /* Avoid possible UB with memcpy when src == dst. */ if (v != N) { memcpy(v, N, N_limbs * ciL); } diff --git a/library/bignum_core.h b/library/bignum_core.h index cd78e723f1..f044b33f93 100644 --- a/library/bignum_core.h +++ b/library/bignum_core.h @@ -832,7 +832,7 @@ void mbedtls_mpi_core_from_mont_rep(mbedtls_mpi_uint *X, * When I != NULL (computing the modular inverse), G or I may alias A * but none of them may alias N (the modulus). * - * If any precondition is not met, output values are unspecified. + * If any of the above preconditions is not met, output values are unspecified. * * \param[out] G The GCD of \p A and \p N. * Must have the same number of limbs as \p N. diff --git a/tests/suites/test_suite_bignum_core.function b/tests/suites/test_suite_bignum_core.function index cad9c1c0dc..8ae1931cbc 100644 --- a/tests/suites/test_suite_bignum_core.function +++ b/tests/suites/test_suite_bignum_core.function @@ -1531,6 +1531,110 @@ exit: } /* END_CASE */ +/* BEGIN_CASE */ +void mpi_core_gcd_modinv_odd_preconditions() +{ + /* + * The purpose of this test function is to ensure that the function doesn't + * crash (but just outputs garbage) when preconditions are not met. + */ + + mbedtls_mpi_uint two_limbs[2]; + mbedtls_mpi_uint one_limb[1]; + mbedtls_mpi_uint *G = NULL, *I = NULL, *T = NULL; + + /* Large enough for all calls below */ + TEST_CALLOC(G, 2); + TEST_CALLOC(I, 2); + TEST_CALLOC(T, 5 * 2); + + /* + * Input values + */ + + /* N is not odd */ + two_limbs[0] = 2; // N = 2^n + 2 + two_limbs[1] = 1; + one_limb[0] = 42; // A = 42 + mbedtls_mpi_core_gcd_modinv_odd(G, NULL, one_limb, 1, two_limbs, 2, T); + mbedtls_mpi_core_gcd_modinv_odd(G, I, one_limb, 1, two_limbs, 2, T); + + /* A > N */ + two_limbs[0] = 3; // N = 3 + two_limbs[1] = 0; + one_limb[0] = 42; // A = 42 + mbedtls_mpi_core_gcd_modinv_odd(G, NULL, one_limb, 1, two_limbs, 2, T); + mbedtls_mpi_core_gcd_modinv_odd(G, I, one_limb, 1, two_limbs, 2, T); + + /* A_limbs > N_limbs (but A <= N) */ + one_limb[0] = 5; // N = 5 + two_limbs[0] = 3; // A = 3 + two_limbs[1] = 0; + mbedtls_mpi_core_gcd_modinv_odd(G, NULL, two_limbs, 2, one_limb, 1, T); + mbedtls_mpi_core_gcd_modinv_odd(G, I, two_limbs, 2, one_limb, 1, T); + + /* A_limbs > N_limbs (and A > N) */ + one_limb[0] = 5; // N = 5 + two_limbs[0] = 7; // A = 7 + two_limbs[1] = 0; + mbedtls_mpi_core_gcd_modinv_odd(G, NULL, two_limbs, 2, one_limb, 1, T); + mbedtls_mpi_core_gcd_modinv_odd(G, I, two_limbs, 2, one_limb, 1, T); + + /* I != NULL but N is 1 */ + two_limbs[0] = 1; // N = 1 + two_limbs[1] = 0; + one_limb[0] = 1; // A = 1 + mbedtls_mpi_core_gcd_modinv_odd(G, I, two_limbs, 2, one_limb, 1, T); + + /* + * Aliasing + */ + + /* Now use valid values for remaining tests */ + two_limbs[0] = 1; // N = 2^n + 1 + two_limbs[1] = 1; + one_limb[0] = 42; // A = 42 + + /* A aliased to N */ + mbedtls_mpi_core_gcd_modinv_odd(G, NULL, two_limbs, 2, two_limbs, 2, T); + mbedtls_mpi_core_gcd_modinv_odd(G, I, two_limbs, 2, two_limbs, 2, T); + + /* G aliased to A and N */ + memcpy(G, two_limbs, 2 * sizeof(mbedtls_mpi_uint)); + mbedtls_mpi_core_gcd_modinv_odd(G, NULL, G, 2, G, 2, T); + mbedtls_mpi_core_gcd_modinv_odd(G, I, G, 2, G, 2, T); + + /* I != NULL, G aliased to N */ + memcpy(G, two_limbs, 2 * sizeof(mbedtls_mpi_uint)); + mbedtls_mpi_core_gcd_modinv_odd(G, I, two_limbs, 2, G, 2, T); + + /* I != NULL, I aliased to N */ + memcpy(I, two_limbs, 2 * sizeof(mbedtls_mpi_uint)); + mbedtls_mpi_core_gcd_modinv_odd(G, I, two_limbs, 2, I, 2, T); + + /* I aliased to A and N */ + memcpy(I, two_limbs, 2 * sizeof(mbedtls_mpi_uint)); + mbedtls_mpi_core_gcd_modinv_odd(G, I, I, 2, I, 2, T); + + /* + * Not specific to this function + */ + + /* A_limbs = 0 */ + mbedtls_mpi_core_gcd_modinv_odd(G, NULL, one_limb, 0, two_limbs, 2, T); + mbedtls_mpi_core_gcd_modinv_odd(G, I, one_limb, 0, two_limbs, 2, T); + + /* A_limbs = N_limbs = 0 */ + mbedtls_mpi_core_gcd_modinv_odd(G, NULL, one_limb, 0, two_limbs, 0, T); + mbedtls_mpi_core_gcd_modinv_odd(G, I, one_limb, 0, two_limbs, 0, T); + +exit: + mbedtls_free(G); + mbedtls_free(I); + mbedtls_free(T); +} +/* END_CASE */ + /* BEGIN_CASE depends_on:MBEDTLS_TEST_HOOKS */ void mpi_core_div2_mod_odd(char *input_X, char *input_N, char *input_exp_X) { diff --git a/tests/suites/test_suite_bignum_core.misc.data b/tests/suites/test_suite_bignum_core.misc.data index 5d3c6753ce..e2ba5a61f7 100644 --- a/tests/suites/test_suite_bignum_core.misc.data +++ b/tests/suites/test_suite_bignum_core.misc.data @@ -535,6 +535,9 @@ mpi_core_gcd_modinv_odd:"7f2405d6de7db80a7bc":"1a84113636607520200d":"1":"15f158 GCD-modinv (almost) max iterations mpi_core_gcd_modinv_odd:"8000000000000000":"b26eb5721a2cb24c36acb4550b176671":"1":"77e1dd63583a6b3c8deefe7737862c89" +GCD-modinv preconditions not met +mpi_core_gcd_modinv_odd_preconditions: + Div2 mod odd: even value mpi_core_div2_mod_odd:"4":"7":"2"