From 7fba4668264bfbf8fd3bc8e4bfc7e48d7d6525c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Thu, 17 Jul 2025 09:17:12 +0200 Subject: [PATCH] Unit-test mpi_core_div2_mod_odd() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This function has specific code to handle carries and it's not clear how to exercises that code through the modinv function, so well, that's what unit tests are for. Signed-off-by: Manuel Pégourié-Gonnard --- library/bignum_core.c | 10 +++--- library/bignum_core_invasive.h | 19 +++++++++-- tests/suites/test_suite_bignum_core.function | 34 +++++++++++++++++++ tests/suites/test_suite_bignum_core.misc.data | 12 +++++++ 4 files changed, 69 insertions(+), 6 deletions(-) diff --git a/library/bignum_core.c b/library/bignum_core.c index e020da100e..3490f7d885 100644 --- a/library/bignum_core.c +++ b/library/bignum_core.c @@ -18,6 +18,7 @@ #include "mbedtls/platform.h" #include "bignum_core.h" +#include "bignum_core_invasive.h" #include "bn_mul.h" #include "constant_time_internal.h" @@ -1037,9 +1038,10 @@ static void mpi_core_sub_mod(mbedtls_mpi_uint *X, * Divide X by 2 mod N in place, assuming N is odd. * The input must be in [0, N) and so will the output. */ -static void mpi_core_div2_mod_odd(mbedtls_mpi_uint *X, - const mbedtls_mpi_uint *N, - size_t limbs) +MBEDTLS_STATIC_TESTABLE +void mbedtls_mpi_core_div2_mod_odd(mbedtls_mpi_uint *X, + const mbedtls_mpi_uint *N, + size_t limbs) { /* If X is odd, add N to make it even before shifting. */ unsigned odd = (unsigned) X[0] & 1; @@ -1200,7 +1202,7 @@ void mbedtls_mpi_core_gcd_modinv_odd(mbedtls_mpi_uint *G, mbedtls_mpi_core_cond_assign(t2, q, N_limbs, u_odd_v_even); mbedtls_mpi_core_cond_assign(t2, d, N_limbs, u_odd_v_odd); - mpi_core_div2_mod_odd(t2, N, N_limbs); + mbedtls_mpi_core_div2_mod_odd(t2, N, N_limbs); /* Update and possibly swap */ memcpy(r, t1, N_limbs * ciL); diff --git a/library/bignum_core_invasive.h b/library/bignum_core_invasive.h index 167099dc91..a9d447f792 100644 --- a/library/bignum_core_invasive.h +++ b/library/bignum_core_invasive.h @@ -13,11 +13,26 @@ #include "bignum_core.h" -#if defined(MBEDTLS_TEST_HOOKS) && !defined(MBEDTLS_THREADING_C) +#if defined(MBEDTLS_TEST_HOOKS) + +#if !defined(MBEDTLS_THREADING_C) extern void (*mbedtls_safe_codepath_hook)(void); extern void (*mbedtls_unsafe_codepath_hook)(void); -#endif /* MBEDTLS_TEST_HOOKS && !MBEDTLS_THREADING_C */ +#endif /* !MBEDTLS_THREADING_C */ + +/** Divide X by 2 mod N in place, assuming N is odd. + * + * \param[in,out] X The value to divide by 2 mod \p N. + * \param[in] N The modulus. Must be odd. + * \param[in] limbs The number of limbs in \p X and \p N. + */ +MBEDTLS_STATIC_TESTABLE +void mbedtls_mpi_core_div2_mod_odd(mbedtls_mpi_uint *X, + const mbedtls_mpi_uint *N, + size_t limbs); + +#endif /* MBEDTLS_TEST_HOOKS */ #endif /* MBEDTLS_BIGNUM_CORE_INVASIVE_H */ diff --git a/tests/suites/test_suite_bignum_core.function b/tests/suites/test_suite_bignum_core.function index 61660c4851..cad9c1c0dc 100644 --- a/tests/suites/test_suite_bignum_core.function +++ b/tests/suites/test_suite_bignum_core.function @@ -2,6 +2,7 @@ #include "mbedtls/bignum.h" #include "mbedtls/entropy.h" #include "bignum_core.h" +#include "bignum_core_invasive.h" #include "constant_time_internal.h" #include "test/constant_flow.h" #include "test/bignum_codepath_check.h" @@ -1529,3 +1530,36 @@ exit: 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) +{ + mbedtls_mpi_uint *X = NULL; + size_t X_limbs = 0; + mbedtls_mpi_uint *N = NULL; + size_t N_limbs = 0; + mbedtls_mpi_uint *exp_X = NULL; + size_t exp_X_limbs = 0; + + /* Read test parameters into MPI structures */ + TEST_EQUAL(0, mbedtls_test_read_mpi_core(&X, &X_limbs, input_X)); + TEST_EQUAL(0, mbedtls_test_read_mpi_core(&N, &N_limbs, input_N)); + TEST_EQUAL(0, mbedtls_test_read_mpi_core(&exp_X, &exp_X_limbs, input_exp_X)); + + /* The function under test requires this */ + TEST_EQUAL(X_limbs, N_limbs); + + TEST_CF_SECRET(X, X_limbs * sizeof(mbedtls_mpi_uint)); + TEST_CF_SECRET(N, N_limbs * sizeof(mbedtls_mpi_uint)); + + mbedtls_mpi_core_div2_mod_odd(X, N, N_limbs); + + TEST_CF_PUBLIC(X, X_limbs * sizeof(mbedtls_mpi_uint)); + TEST_EQUAL(0, mpi_core_cmp(X, X_limbs, exp_X, exp_X_limbs)); + +exit: + mbedtls_free(X); + mbedtls_free(N); + mbedtls_free(exp_X); +} +/* END_CASE */ diff --git a/tests/suites/test_suite_bignum_core.misc.data b/tests/suites/test_suite_bignum_core.misc.data index 67164e2f90..d4cf00f893 100644 --- a/tests/suites/test_suite_bignum_core.misc.data +++ b/tests/suites/test_suite_bignum_core.misc.data @@ -529,3 +529,15 @@ mpi_core_gcd_modinv_odd:"e4518a1900fce698fa3":"1a84113636607520200d":"3":"" GCD-modinv random 80-bit, trivial GCD -> inverse mpi_core_gcd_modinv_odd:"7f2405d6de7db80a7bc":"1a84113636607520200d":"1":"15f158844a59cd7a3ed2" + +Div2 mod odd: even value +mpi_core_div2_mod_odd:"4":"7":"2" + +Div2 mod odd: odd value, no carry +mpi_core_div2_mod_odd:"5":"7":"6" + +Div2 mod odd: odd value with carry +mpi_core_div2_mod_odd:"8000000000000001":"8000000000000003":"8000000000000002" + +Div2 mod odd: even value with top bit set +mpi_core_div2_mod_odd:"8000000000000002":"8000000000000003":"4000000000000001"