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"