Unit-test mpi_core_div2_mod_odd()
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 <manuel.pegourie-gonnard@arm.com>
diff --git a/library/bignum_core.c b/library/bignum_core.c
index e020da1..3490f7d 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 @@
* 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 @@
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 167099d..a9d447f 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 61660c4..cad9c1c 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 @@
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 67164e2..d4cf00f 100644
--- a/tests/suites/test_suite_bignum_core.misc.data
+++ b/tests/suites/test_suite_bignum_core.misc.data
@@ -529,3 +529,15 @@
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"