Merge pull request #7725 from minosgalanakis/ecp/7268_add_optimised_reduction_setup_3

[Bignum] Add optimised reduction setup
diff --git a/library/bignum_mod.c b/library/bignum_mod.c
index acf45e9..84f3896 100644
--- a/library/bignum_mod.c
+++ b/library/bignum_mod.c
@@ -88,7 +88,7 @@
             N->rep.mont.mm = 0;
             break;
         case MBEDTLS_MPI_MOD_REP_OPT_RED:
-            mbedtls_free(N->rep.ored);
+            N->rep.ored.modp = NULL;
             break;
         case MBEDTLS_MPI_MOD_REP_INVALID:
             break;
@@ -136,33 +136,25 @@
     return ret;
 }
 
-int mbedtls_mpi_mod_modulus_setup(mbedtls_mpi_mod_modulus *N,
-                                  const mbedtls_mpi_uint *p,
-                                  size_t p_limbs,
-                                  mbedtls_mpi_mod_rep_selector int_rep)
+static inline void standard_modulus_setup(mbedtls_mpi_mod_modulus *N,
+                                          const mbedtls_mpi_uint *p,
+                                          size_t p_limbs,
+                                          mbedtls_mpi_mod_rep_selector int_rep)
 {
-    int ret = 0;
-
     N->p = p;
     N->limbs = p_limbs;
     N->bits = mbedtls_mpi_core_bitlen(p, p_limbs);
+    N->int_rep = int_rep;
+}
 
-    switch (int_rep) {
-        case MBEDTLS_MPI_MOD_REP_MONTGOMERY:
-            N->int_rep = int_rep;
-            N->rep.mont.mm = mbedtls_mpi_core_montmul_init(N->p);
-            ret = set_mont_const_square(&N->rep.mont.rr, N->p, N->limbs);
-            break;
-        case MBEDTLS_MPI_MOD_REP_OPT_RED:
-            N->int_rep = int_rep;
-            N->rep.ored = NULL;
-            break;
-        default:
-            ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
-            goto exit;
-    }
-
-exit:
+int mbedtls_mpi_mod_modulus_setup(mbedtls_mpi_mod_modulus *N,
+                                  const mbedtls_mpi_uint *p,
+                                  size_t p_limbs)
+{
+    int ret = 0;
+    standard_modulus_setup(N, p, p_limbs, MBEDTLS_MPI_MOD_REP_MONTGOMERY);
+    N->rep.mont.mm = mbedtls_mpi_core_montmul_init(N->p);
+    ret = set_mont_const_square(&N->rep.mont.rr, N->p, N->limbs);
 
     if (ret != 0) {
         mbedtls_mpi_mod_modulus_free(N);
@@ -171,6 +163,16 @@
     return ret;
 }
 
+int mbedtls_mpi_mod_optred_modulus_setup(mbedtls_mpi_mod_modulus *N,
+                                         const mbedtls_mpi_uint *p,
+                                         size_t p_limbs,
+                                         mbedtls_mpi_modp_fn modp)
+{
+    standard_modulus_setup(N, p, p_limbs, MBEDTLS_MPI_MOD_REP_OPT_RED);
+    N->rep.ored.modp = modp;
+    return 0;
+}
+
 int mbedtls_mpi_mod_mul(mbedtls_mpi_mod_residue *X,
                         const mbedtls_mpi_mod_residue *A,
                         const mbedtls_mpi_mod_residue *B,
@@ -235,8 +237,7 @@
     mbedtls_mpi_mod_modulus Nmont;
     mbedtls_mpi_mod_modulus_init(&Nmont);
 
-    MBEDTLS_MPI_CHK(mbedtls_mpi_mod_modulus_setup(&Nmont, N->p, N->limbs,
-                                                  MBEDTLS_MPI_MOD_REP_MONTGOMERY));
+    MBEDTLS_MPI_CHK(mbedtls_mpi_mod_modulus_setup(&Nmont, N->p, N->limbs));
 
     /* We'll use X->p to hold the Montgomery form of the input A->p */
     mbedtls_mpi_core_to_mont_rep(X->p, A->p, Nmont.p, Nmont.limbs,
diff --git a/library/bignum_mod.h b/library/bignum_mod.h
index db177ed..39e8fd2 100644
--- a/library/bignum_mod.h
+++ b/library/bignum_mod.h
@@ -98,10 +98,11 @@
     /* Skip 1 as it is slightly easier to accidentally pass to functions. */
     /** Montgomery representation. */
     MBEDTLS_MPI_MOD_REP_MONTGOMERY = 2,
-    /** TODO: document this.
-     *
-     * Residues are in canonical representation.
-     */
+    /* Optimised reduction available. This indicates a coordinate modulus (P)
+     * and one or more of the following have been configured:
+     * - A nist curve (MBEDTLS_ECP_DP_SECPXXXR1_ENABLED) & MBEDTLS_ECP_NIST_OPTIM.
+     * - A Kobliz Curve.
+     * - A Fast Reduction Curve CURVE25519 or CURVE448. */
     MBEDTLS_MPI_MOD_REP_OPT_RED,
 } mbedtls_mpi_mod_rep_selector;
 
@@ -123,7 +124,11 @@
     mbedtls_mpi_uint mm;         /* Montgomery const for -N^{-1} mod 2^{ciL} */
 } mbedtls_mpi_mont_struct;
 
-typedef void *mbedtls_mpi_opt_red_struct;
+typedef int (*mbedtls_mpi_modp_fn)(mbedtls_mpi_uint *X, size_t X_limbs);
+
+typedef struct {
+    mbedtls_mpi_modp_fn modp;    /* The optimised reduction function pointer */
+} mbedtls_mpi_opt_red_struct;
 
 typedef struct {
     const mbedtls_mpi_uint *p;
@@ -197,16 +202,29 @@
  *                  not be modified in any way until after
  *                  mbedtls_mpi_mod_modulus_free() is called.
  * \param p_limbs   The number of limbs of \p p.
- * \param int_rep   The internal representation to be used for residues
- *                  associated with \p N (see #mbedtls_mpi_mod_rep_selector).
  *
  * \return      \c 0 if successful.
- * \return      #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if \p int_rep is invalid.
  */
 int mbedtls_mpi_mod_modulus_setup(mbedtls_mpi_mod_modulus *N,
                                   const mbedtls_mpi_uint *p,
-                                  size_t p_limbs,
-                                  mbedtls_mpi_mod_rep_selector int_rep);
+                                  size_t p_limbs);
+
+/** Setup an optimised-reduction compatible modulus structure.
+ *
+ * \param[out] N    The address of the modulus structure to populate.
+ * \param[in] p     The address of the limb array storing the value of \p N.
+ *                  The memory pointed to by \p p will be used by \p N and must
+ *                  not be modified in any way until after
+ *                  mbedtls_mpi_mod_modulus_free() is called.
+ * \param p_limbs   The number of limbs of \p p.
+ * \param modp      A pointer to the optimised reduction function to use. \p p.
+ *
+ * \return      \c 0 if successful.
+ */
+int mbedtls_mpi_mod_optred_modulus_setup(mbedtls_mpi_mod_modulus *N,
+                                         const mbedtls_mpi_uint *p,
+                                         size_t p_limbs,
+                                         mbedtls_mpi_modp_fn modp);
 
 /** Free elements of a modulus structure.
  *
diff --git a/library/ecp_curves.c b/library/ecp_curves.c
index 96013b3..4a8f891 100644
--- a/library/ecp_curves.c
+++ b/library/ecp_curves.c
@@ -5831,20 +5831,24 @@
 MBEDTLS_STATIC_TESTABLE
 int mbedtls_ecp_modulus_setup(mbedtls_mpi_mod_modulus *N,
                               const mbedtls_ecp_group_id id,
-                              const mbedtls_ecp_curve_type ctype)
+                              const mbedtls_ecp_modulus_type ctype)
 {
+    mbedtls_mpi_modp_fn modp = NULL;
     mbedtls_mpi_uint *p = NULL;
     size_t p_limbs;
 
-    if (!(ctype == (mbedtls_ecp_curve_type) MBEDTLS_ECP_MOD_COORDINATE || \
-          ctype == (mbedtls_ecp_curve_type) MBEDTLS_ECP_MOD_SCALAR)) {
+    if (!(ctype == (mbedtls_ecp_modulus_type) MBEDTLS_ECP_MOD_COORDINATE || \
+          ctype == (mbedtls_ecp_modulus_type) MBEDTLS_ECP_MOD_SCALAR)) {
         return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
     }
 
     switch (id) {
 #if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED)
         case MBEDTLS_ECP_DP_SECP192R1:
-            if (ctype == (mbedtls_ecp_curve_type) MBEDTLS_ECP_MOD_COORDINATE) {
+            if (ctype == (mbedtls_ecp_modulus_type) MBEDTLS_ECP_MOD_COORDINATE) {
+#if defined(MBEDTLS_ECP_NIST_OPTIM)
+                modp = &mbedtls_ecp_mod_p192_raw;
+#endif
                 p = (mbedtls_mpi_uint *) secp192r1_p;
                 p_limbs = CHARS_TO_LIMBS(sizeof(secp192r1_p));
             } else {
@@ -5856,7 +5860,10 @@
 
 #if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED)
         case MBEDTLS_ECP_DP_SECP224R1:
-            if (ctype == (mbedtls_ecp_curve_type) MBEDTLS_ECP_MOD_COORDINATE) {
+            if (ctype == (mbedtls_ecp_modulus_type) MBEDTLS_ECP_MOD_COORDINATE) {
+#if defined(MBEDTLS_ECP_NIST_OPTIM)
+                modp = &mbedtls_ecp_mod_p224_raw;
+#endif
                 p = (mbedtls_mpi_uint *) secp224r1_p;
                 p_limbs = CHARS_TO_LIMBS(sizeof(secp224r1_p));
             } else {
@@ -5868,7 +5875,10 @@
 
 #if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED)
         case MBEDTLS_ECP_DP_SECP256R1:
-            if (ctype == (mbedtls_ecp_curve_type) MBEDTLS_ECP_MOD_COORDINATE) {
+            if (ctype == (mbedtls_ecp_modulus_type) MBEDTLS_ECP_MOD_COORDINATE) {
+#if defined(MBEDTLS_ECP_NIST_OPTIM)
+                modp = &mbedtls_ecp_mod_p256_raw;
+#endif
                 p = (mbedtls_mpi_uint *) secp256r1_p;
                 p_limbs = CHARS_TO_LIMBS(sizeof(secp256r1_p));
             } else {
@@ -5880,7 +5890,10 @@
 
 #if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED)
         case MBEDTLS_ECP_DP_SECP384R1:
-            if (ctype == (mbedtls_ecp_curve_type) MBEDTLS_ECP_MOD_COORDINATE) {
+            if (ctype == (mbedtls_ecp_modulus_type) MBEDTLS_ECP_MOD_COORDINATE) {
+#if defined(MBEDTLS_ECP_NIST_OPTIM)
+                modp = &mbedtls_ecp_mod_p384_raw;
+#endif
                 p = (mbedtls_mpi_uint *) secp384r1_p;
                 p_limbs = CHARS_TO_LIMBS(sizeof(secp384r1_p));
             } else {
@@ -5892,7 +5905,10 @@
 
 #if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED)
         case MBEDTLS_ECP_DP_SECP521R1:
-            if (ctype == (mbedtls_ecp_curve_type) MBEDTLS_ECP_MOD_COORDINATE) {
+            if (ctype == (mbedtls_ecp_modulus_type) MBEDTLS_ECP_MOD_COORDINATE) {
+#if defined(MBEDTLS_ECP_NIST_OPTIM)
+                modp = &mbedtls_ecp_mod_p521_raw;
+#endif
                 p = (mbedtls_mpi_uint *) secp521r1_p;
                 p_limbs = CHARS_TO_LIMBS(sizeof(secp521r1_p));
             } else {
@@ -5904,7 +5920,7 @@
 
 #if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED)
         case MBEDTLS_ECP_DP_BP256R1:
-            if (ctype == (mbedtls_ecp_curve_type) MBEDTLS_ECP_MOD_COORDINATE) {
+            if (ctype == (mbedtls_ecp_modulus_type) MBEDTLS_ECP_MOD_COORDINATE) {
                 p = (mbedtls_mpi_uint *) brainpoolP256r1_p;
                 p_limbs = CHARS_TO_LIMBS(sizeof(brainpoolP256r1_p));
             } else {
@@ -5916,7 +5932,7 @@
 
 #if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED)
         case MBEDTLS_ECP_DP_BP384R1:
-            if (ctype == (mbedtls_ecp_curve_type) MBEDTLS_ECP_MOD_COORDINATE) {
+            if (ctype == (mbedtls_ecp_modulus_type) MBEDTLS_ECP_MOD_COORDINATE) {
                 p = (mbedtls_mpi_uint *) brainpoolP384r1_p;
                 p_limbs = CHARS_TO_LIMBS(sizeof(brainpoolP384r1_p));
             } else {
@@ -5928,7 +5944,7 @@
 
 #if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED)
         case MBEDTLS_ECP_DP_BP512R1:
-            if (ctype == (mbedtls_ecp_curve_type) MBEDTLS_ECP_MOD_COORDINATE) {
+            if (ctype == (mbedtls_ecp_modulus_type) MBEDTLS_ECP_MOD_COORDINATE) {
                 p = (mbedtls_mpi_uint *) brainpoolP512r1_p;
                 p_limbs = CHARS_TO_LIMBS(sizeof(brainpoolP512r1_p));
             } else {
@@ -5940,7 +5956,8 @@
 
 #if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED)
         case MBEDTLS_ECP_DP_CURVE25519:
-            if (ctype == (mbedtls_ecp_curve_type) MBEDTLS_ECP_MOD_COORDINATE) {
+            if (ctype == (mbedtls_ecp_modulus_type) MBEDTLS_ECP_MOD_COORDINATE) {
+                modp = &mbedtls_ecp_mod_p255_raw;
                 p = (mbedtls_mpi_uint *) curve25519_p;
                 p_limbs = CHARS_TO_LIMBS(sizeof(curve25519_p));
             } else {
@@ -5952,7 +5969,8 @@
 
 #if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED)
         case MBEDTLS_ECP_DP_SECP192K1:
-            if (ctype == (mbedtls_ecp_curve_type) MBEDTLS_ECP_MOD_COORDINATE) {
+            if (ctype == (mbedtls_ecp_modulus_type) MBEDTLS_ECP_MOD_COORDINATE) {
+                modp = &mbedtls_ecp_mod_p192_raw;
                 p = (mbedtls_mpi_uint *) secp192k1_p;
                 p_limbs = CHARS_TO_LIMBS(sizeof(secp192k1_p));
             } else {
@@ -5964,7 +5982,8 @@
 
 #if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED)
         case MBEDTLS_ECP_DP_SECP224K1:
-            if (ctype == (mbedtls_ecp_curve_type) MBEDTLS_ECP_MOD_COORDINATE) {
+            if (ctype == (mbedtls_ecp_modulus_type) MBEDTLS_ECP_MOD_COORDINATE) {
+                modp = &mbedtls_ecp_mod_p224_raw;
                 p = (mbedtls_mpi_uint *) secp224k1_p;
                 p_limbs = CHARS_TO_LIMBS(sizeof(secp224k1_p));
             } else {
@@ -5976,7 +5995,8 @@
 
 #if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED)
         case MBEDTLS_ECP_DP_SECP256K1:
-            if (ctype == (mbedtls_ecp_curve_type) MBEDTLS_ECP_MOD_COORDINATE) {
+            if (ctype == (mbedtls_ecp_modulus_type) MBEDTLS_ECP_MOD_COORDINATE) {
+                modp = &mbedtls_ecp_mod_p256_raw;
                 p = (mbedtls_mpi_uint *) secp256k1_p;
                 p_limbs = CHARS_TO_LIMBS(sizeof(secp256k1_p));
             } else {
@@ -5988,7 +6008,8 @@
 
 #if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED)
         case MBEDTLS_ECP_DP_CURVE448:
-            if (ctype == (mbedtls_ecp_curve_type) MBEDTLS_ECP_MOD_COORDINATE) {
+            if (ctype == (mbedtls_ecp_modulus_type) MBEDTLS_ECP_MOD_COORDINATE) {
+                modp = &mbedtls_ecp_mod_p448_raw;
                 p = (mbedtls_mpi_uint *) curve448_p;
                 p_limbs = CHARS_TO_LIMBS(sizeof(curve448_p));
             } else {
@@ -6003,9 +6024,14 @@
             return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
     }
 
-    if (mbedtls_mpi_mod_modulus_setup(N, p, p_limbs,
-                                      MBEDTLS_MPI_MOD_REP_MONTGOMERY)) {
-        return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    if (modp != NULL) {
+        if (mbedtls_mpi_mod_optred_modulus_setup(N, p, p_limbs, modp)) {
+            return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+        }
+    } else {
+        if (mbedtls_mpi_mod_modulus_setup(N, p, p_limbs)) {
+            return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+        }
     }
     return 0;
 }
diff --git a/library/ecp_invasive.h b/library/ecp_invasive.h
index 1dc5567..94867b9 100644
--- a/library/ecp_invasive.h
+++ b/library/ecp_invasive.h
@@ -306,7 +306,7 @@
  * \param[in,out] N The address of the modulus structure to populate.
  *                  Must be initialized.
  * \param[in] id    The mbedtls_ecp_group_id for which to initialise the modulus.
- * \param[in] ctype The mbedtls_ecp_curve_type identifier for a coordinate modulus (P)
+ * \param[in] ctype The mbedtls_ecp_modulus_type identifier for a coordinate modulus (P)
  *                  or a scalar modulus (N).
  *
  * \return          \c 0 if successful.
@@ -317,7 +317,7 @@
 MBEDTLS_STATIC_TESTABLE
 int mbedtls_ecp_modulus_setup(mbedtls_mpi_mod_modulus *N,
                               const mbedtls_ecp_group_id id,
-                              const mbedtls_ecp_curve_type ctype);
+                              const mbedtls_ecp_modulus_type ctype);
 
 #endif /* MBEDTLS_TEST_HOOKS && MBEDTLS_ECP_C */
 
diff --git a/scripts/mbedtls_dev/ecp.py b/scripts/mbedtls_dev/ecp.py
index e5dd4d9..8a3ab28 100644
--- a/scripts/mbedtls_dev/ecp.py
+++ b/scripts/mbedtls_dev/ecp.py
@@ -34,7 +34,8 @@
     test_name = "ecp_mod_p192_raw"
     input_style = "fixed"
     arity = 1
-    dependencies = ["MBEDTLS_ECP_DP_SECP192R1_ENABLED"]
+    dependencies = ["MBEDTLS_ECP_DP_SECP192R1_ENABLED",
+                    "MBEDTLS_ECP_NIST_OPTIM"]
 
     moduli = ["fffffffffffffffffffffffffffffffeffffffffffffffff"] # type: List[str]
 
@@ -110,7 +111,8 @@
     test_name = "ecp_mod_p224_raw"
     input_style = "arch_split"
     arity = 1
-    dependencies = ["MBEDTLS_ECP_DP_SECP224R1_ENABLED"]
+    dependencies = ["MBEDTLS_ECP_DP_SECP224R1_ENABLED",
+                    "MBEDTLS_ECP_NIST_OPTIM"]
 
     moduli = ["ffffffffffffffffffffffffffffffff000000000000000000000001"] # type: List[str]
 
@@ -187,7 +189,8 @@
     test_name = "ecp_mod_p256_raw"
     input_style = "fixed"
     arity = 1
-    dependencies = ["MBEDTLS_ECP_DP_SECP256R1_ENABLED"]
+    dependencies = ["MBEDTLS_ECP_DP_SECP256R1_ENABLED",
+                    "MBEDTLS_ECP_NIST_OPTIM"]
 
     moduli = ["ffffffff00000001000000000000000000000000ffffffffffffffffffffffff"] # type: List[str]
 
@@ -270,7 +273,8 @@
     test_name = "ecp_mod_p384_raw"
     input_style = "fixed"
     arity = 1
-    dependencies = ["MBEDTLS_ECP_DP_SECP384R1_ENABLED"]
+    dependencies = ["MBEDTLS_ECP_DP_SECP384R1_ENABLED",
+                    "MBEDTLS_ECP_NIST_OPTIM"]
 
     moduli = [("ffffffffffffffffffffffffffffffffffffffffffffffff"
                "fffffffffffffffeffffffff0000000000000000ffffffff")
@@ -392,7 +396,8 @@
     test_name = "ecp_mod_p521_raw"
     input_style = "arch_split"
     arity = 1
-    dependencies = ["MBEDTLS_ECP_DP_SECP521R1_ENABLED"]
+    dependencies = ["MBEDTLS_ECP_DP_SECP521R1_ENABLED",
+                    "MBEDTLS_ECP_NIST_OPTIM"]
 
     moduli = [("01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
                "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")
diff --git a/tests/src/bignum_helpers.c b/tests/src/bignum_helpers.c
index 4dd3791..efb2eca 100644
--- a/tests/src/bignum_helpers.c
+++ b/tests/src/bignum_helpers.c
@@ -99,7 +99,18 @@
     if (ret != 0) {
         return ret;
     }
-    ret = mbedtls_mpi_mod_modulus_setup(N, p, limbs, int_rep);
+
+    switch (int_rep) {
+        case MBEDTLS_MPI_MOD_REP_MONTGOMERY:
+            ret = mbedtls_mpi_mod_modulus_setup(N, p, limbs);
+            break;
+        case MBEDTLS_MPI_MOD_REP_OPT_RED:
+            ret = mbedtls_mpi_mod_optred_modulus_setup(N, p, limbs, NULL);
+            break;
+        default:
+            ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
+            break;
+    }
     if (ret != 0) {
         mbedtls_free(p);
     }
diff --git a/tests/suites/test_suite_bignum_mod.function b/tests/suites/test_suite_bignum_mod.function
index 233d3a9..4edc0b9 100644
--- a/tests/suites/test_suite_bignum_mod.function
+++ b/tests/suites/test_suite_bignum_mod.function
@@ -10,21 +10,6 @@
     ASSERT_COMPARE((a).p, (a).limbs * sizeof(mbedtls_mpi_uint), \
                    (b).p, (b).limbs * sizeof(mbedtls_mpi_uint))
 
-static int test_read_modulus(mbedtls_mpi_mod_modulus *m,
-                             mbedtls_mpi_mod_rep_selector int_rep,
-                             char *input)
-{
-    mbedtls_mpi_uint *p = NULL;
-    size_t limbs;
-
-    int ret = mbedtls_test_read_mpi_core(&p, &limbs, input);
-    if (ret != 0) {
-        return ret;
-    }
-
-    return mbedtls_mpi_mod_modulus_setup(m, p, limbs, int_rep);
-}
-
 static int test_read_residue(mbedtls_mpi_mod_residue *r,
                              const mbedtls_mpi_mod_modulus *m,
                              char *input,
@@ -65,7 +50,19 @@
     memset(mp, 0xFF, sizeof(mp));
 
     mbedtls_mpi_mod_modulus_init(&m);
-    ret = mbedtls_mpi_mod_modulus_setup(&m, mp, MLIMBS, int_rep);
+
+    switch (int_rep) {
+        case MBEDTLS_MPI_MOD_REP_MONTGOMERY:
+            ret = mbedtls_mpi_mod_modulus_setup(&m, mp, MLIMBS);
+            break;
+        case MBEDTLS_MPI_MOD_REP_OPT_RED:
+            ret = mbedtls_mpi_mod_optred_modulus_setup(&m, mp, MLIMBS, NULL);
+            break;
+        default:
+            ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
+            break;
+    }
+
     TEST_EQUAL(ret, iret);
 
     /* Only test if the constants have been set-up  */
@@ -112,8 +109,8 @@
     mbedtls_mpi_mod_modulus m;
     mbedtls_mpi_mod_modulus_init(&m);
 
-    TEST_EQUAL(test_read_modulus(&m, MBEDTLS_MPI_MOD_REP_MONTGOMERY, input_N),
-               0);
+    TEST_EQUAL(mbedtls_test_read_mpi_modulus(&m, input_N,
+                                             MBEDTLS_MPI_MOD_REP_MONTGOMERY), 0);
 
     TEST_EQUAL(test_read_residue(&rA, &m, input_A, 0), 0);
     TEST_EQUAL(test_read_residue(&rB, &m, input_B, 0), 0);
@@ -200,8 +197,8 @@
     mbedtls_mpi_mod_modulus fake_m;
     mbedtls_mpi_mod_modulus_init(&fake_m);
 
-    TEST_EQUAL(test_read_modulus(&m, MBEDTLS_MPI_MOD_REP_MONTGOMERY, input_N),
-               0);
+    TEST_EQUAL(mbedtls_test_read_mpi_modulus(&m, input_N,
+                                             MBEDTLS_MPI_MOD_REP_MONTGOMERY), 0);
 
     TEST_EQUAL(test_read_residue(&rA, &m, input_A, 1), 0);
     TEST_EQUAL(test_read_residue(&rB, &m, input_B, 1), 0);
@@ -247,7 +244,8 @@
     mbedtls_mpi_mod_modulus_init(&m);
 
     TEST_EQUAL(0,
-               test_read_modulus(&m, MBEDTLS_MPI_MOD_REP_MONTGOMERY, input_N));
+               mbedtls_test_read_mpi_modulus(&m, input_N,
+                                             MBEDTLS_MPI_MOD_REP_MONTGOMERY));
 
     /* 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
@@ -348,7 +346,8 @@
     mbedtls_mpi_mod_modulus_init(&N);
 
     TEST_EQUAL(0,
-               test_read_modulus(&N, MBEDTLS_MPI_MOD_REP_MONTGOMERY, input_N));
+               mbedtls_test_read_mpi_modulus(&N, input_N,
+                                             MBEDTLS_MPI_MOD_REP_MONTGOMERY));
 
     /* 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
@@ -397,7 +396,8 @@
     mbedtls_mpi_mod_modulus_init(&N);
 
     TEST_EQUAL(0,
-               test_read_modulus(&N, MBEDTLS_MPI_MOD_REP_OPT_RED, input_N));
+               mbedtls_test_read_mpi_modulus(&N, input_N,
+                                             MBEDTLS_MPI_MOD_REP_OPT_RED));
 
     /* 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
@@ -447,7 +447,8 @@
     mbedtls_mpi_mod_modulus_init(&m);
 
     TEST_EQUAL(0,
-               test_read_modulus(&m, MBEDTLS_MPI_MOD_REP_MONTGOMERY, input_N));
+               mbedtls_test_read_mpi_modulus(&m, input_N,
+                                             MBEDTLS_MPI_MOD_REP_MONTGOMERY));
 
     /* 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
@@ -550,8 +551,7 @@
     TEST_EQUAL(0, mbedtls_test_read_mpi_core(&N, &n_limbs, input_N));
     TEST_EQUAL(0, mbedtls_test_read_mpi_core(&R, &r_limbs, input_R));
 
-    TEST_EQUAL(0, mbedtls_mpi_mod_modulus_setup(&m, N, n_limbs,
-                                                MBEDTLS_MPI_MOD_REP_MONTGOMERY));
+    TEST_EQUAL(0, mbedtls_mpi_mod_modulus_setup(&m, N, n_limbs));
 
     TEST_EQUAL(ret, mbedtls_mpi_mod_residue_setup(&r, &m, R, r_limbs));
 
@@ -592,8 +592,7 @@
                mbedtls_mpi_mod_write(&r, &m, buf->x, buf->len, endian));
 
     /* Set up modulus and test with residue->p == NULL */
-    TEST_EQUAL(0, mbedtls_mpi_mod_modulus_setup(&m, N, n_limbs,
-                                                MBEDTLS_MPI_MOD_REP_MONTGOMERY));
+    TEST_EQUAL(0, mbedtls_mpi_mod_modulus_setup(&m, N, n_limbs));
 
     TEST_EQUAL(MBEDTLS_ERR_MPI_BAD_INPUT_DATA,
                mbedtls_mpi_mod_read(&r, &m, buf->x, buf->len, endian));
@@ -666,8 +665,7 @@
     TEST_LE_U(a_bytes, n_bytes);
 
     /* Init Structures */
-    TEST_EQUAL(0, mbedtls_mpi_mod_modulus_setup(&m, N, n_limbs,
-                                                MBEDTLS_MPI_MOD_REP_MONTGOMERY));
+    TEST_EQUAL(0, mbedtls_mpi_mod_modulus_setup(&m, N, n_limbs));
 
     /* Enforcing p_limbs >= m->limbs */
     TEST_EQUAL(0, mbedtls_mpi_mod_residue_setup(&r, &m, R, n_limbs));
diff --git a/tests/suites/test_suite_bignum_mod_raw.function b/tests/suites/test_suite_bignum_mod_raw.function
index bd5eea7..b67ac51 100644
--- a/tests/suites/test_suite_bignum_mod_raw.function
+++ b/tests/suites/test_suite_bignum_mod_raw.function
@@ -54,8 +54,7 @@
 
     mbedtls_mpi_uint init[sizeof(X) / sizeof(X[0])];
     memset(init, 0xFF, sizeof(init));
-    int ret = mbedtls_mpi_mod_modulus_setup(&m, init, nx,
-                                            MBEDTLS_MPI_MOD_REP_MONTGOMERY);
+    int ret = mbedtls_mpi_mod_modulus_setup(&m, init, nx);
     TEST_EQUAL(ret, 0);
 
     if (iendian == MBEDTLS_MPI_MOD_EXT_REP_INVALID && iret != 0) {
@@ -137,8 +136,7 @@
     ASSERT_ALLOC(buff_m, copy_limbs);
     memset(buff_m, 0xFF, copy_limbs);
     TEST_EQUAL(mbedtls_mpi_mod_modulus_setup(
-                   &m, buff_m, copy_limbs,
-                   MBEDTLS_MPI_MOD_REP_MONTGOMERY), 0);
+                   &m, buff_m, copy_limbs), 0);
 
     /* condition is false */
     TEST_CF_SECRET(X, bytes);
@@ -208,8 +206,7 @@
     ASSERT_ALLOC(buff_m, copy_limbs);
     memset(buff_m, 0xFF, copy_limbs);
     TEST_EQUAL(mbedtls_mpi_mod_modulus_setup(
-                   &m, buff_m, copy_limbs,
-                   MBEDTLS_MPI_MOD_REP_MONTGOMERY), 0);
+                   &m, buff_m, copy_limbs), 0);
 
     ASSERT_ALLOC(X, limbs);
     memcpy(X, tmp_X, bytes);
@@ -297,8 +294,7 @@
     ASSERT_ALLOC(X, limbs);
 
     TEST_EQUAL(mbedtls_mpi_mod_modulus_setup(
-                   &m, N, limbs,
-                   MBEDTLS_MPI_MOD_REP_MONTGOMERY), 0);
+                   &m, N, limbs), 0);
 
     mbedtls_mpi_mod_raw_sub(X, A, B, &m);
     ASSERT_COMPARE(X, bytes, res, bytes);
@@ -368,8 +364,7 @@
     TEST_ASSERT(c || mbedtls_mpi_core_lt_ct(tmp, N, limbs));
 
     TEST_EQUAL(mbedtls_mpi_mod_modulus_setup(
-                   &m, N, limbs,
-                   MBEDTLS_MPI_MOD_REP_MONTGOMERY), 0);
+                   &m, N, limbs), 0);
 
     mbedtls_mpi_mod_raw_fix_quasi_reduction(X, &m);
     ASSERT_COMPARE(X, bytes, res, bytes);
@@ -419,8 +414,7 @@
     ASSERT_ALLOC(X, limbs);
 
     TEST_EQUAL(mbedtls_mpi_mod_modulus_setup(
-                   &m, N, limbs,
-                   MBEDTLS_MPI_MOD_REP_MONTGOMERY), 0);
+                   &m, N, limbs), 0);
 
     const size_t limbs_T = limbs * 2 + 1;
     ASSERT_ALLOC(T, limbs_T);
@@ -580,9 +574,7 @@
     ASSERT_ALLOC(X, limbs);
 
     TEST_EQUAL(mbedtls_mpi_mod_modulus_setup(
-                   &m, N, limbs,
-                   MBEDTLS_MPI_MOD_REP_MONTGOMERY
-                   ), 0);
+                   &m, N, limbs), 0);
 
     /* A + B => Correct result */
     mbedtls_mpi_mod_raw_add(X, A, B, &m);
@@ -720,8 +712,7 @@
     size_t limbs = n_limbs;
     size_t bytes = limbs * sizeof(mbedtls_mpi_uint);
 
-    TEST_EQUAL(0, mbedtls_mpi_mod_modulus_setup(&m, N, n_limbs,
-                                                MBEDTLS_MPI_MOD_REP_MONTGOMERY));
+    TEST_EQUAL(0, mbedtls_mpi_mod_modulus_setup(&m, N, n_limbs));
 
     /* 1. Test low-level function first */
 
@@ -785,8 +776,7 @@
     size_t limbs = n_limbs;
     size_t bytes = limbs * sizeof(mbedtls_mpi_uint);
 
-    TEST_EQUAL(0, mbedtls_mpi_mod_modulus_setup(&m, N, n_limbs,
-                                                MBEDTLS_MPI_MOD_REP_MONTGOMERY));
+    TEST_EQUAL(0, mbedtls_mpi_mod_modulus_setup(&m, N, n_limbs));
 
     /* 1. Test low-level function first */
 
@@ -847,8 +837,7 @@
     ASSERT_ALLOC(R, n_limbs);
     ASSERT_ALLOC(Z, n_limbs);
 
-    TEST_EQUAL(0, mbedtls_mpi_mod_modulus_setup(&m, N, n_limbs,
-                                                MBEDTLS_MPI_MOD_REP_MONTGOMERY));
+    TEST_EQUAL(0, mbedtls_mpi_mod_modulus_setup(&m, N, n_limbs));
 
     /* Neg( A == 0 ) => Zero result */
     mbedtls_mpi_mod_raw_neg(R, Z, &m);
diff --git a/tests/suites/test_suite_ecp.function b/tests/suites/test_suite_ecp.function
index 9ef35d8..55ded45 100644
--- a/tests/suites/test_suite_ecp.function
+++ b/tests/suites/test_suite_ecp.function
@@ -1294,35 +1294,35 @@
     bytes = limbs_N * sizeof(mbedtls_mpi_uint);
 
     switch (curve_id) {
-#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED)
+#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) && defined(MBEDTLS_ECP_NIST_OPTIM)
         case MBEDTLS_ECP_DP_SECP192R1:
             limbs = 2 * limbs_N;
             curve_bits = 192;
             curve_func = &mbedtls_ecp_mod_p192_raw;
             break;
 #endif
-#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED)
+#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) && defined(MBEDTLS_ECP_NIST_OPTIM)
         case MBEDTLS_ECP_DP_SECP224R1:
             limbs = 448 / biL;
             curve_bits = 224;
             curve_func = &mbedtls_ecp_mod_p224_raw;
             break;
 #endif
-#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED)
+#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) && defined(MBEDTLS_ECP_NIST_OPTIM)
         case MBEDTLS_ECP_DP_SECP256R1:
             limbs = 2 * limbs_N;
             curve_bits = 256;
             curve_func = &mbedtls_ecp_mod_p256_raw;
             break;
 #endif
-#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED)
+#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) && defined(MBEDTLS_ECP_NIST_OPTIM)
         case MBEDTLS_ECP_DP_SECP384R1:
             limbs = 2 * limbs_N;
             curve_bits = 384;
             curve_func = &mbedtls_ecp_mod_p384_raw;
             break;
 #endif
-#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED)
+#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) && defined(MBEDTLS_ECP_NIST_OPTIM)
         case MBEDTLS_ECP_DP_SECP521R1:
             limbs = 2 * limbs_N;
             curve_bits = 522;
@@ -1373,8 +1373,7 @@
     TEST_EQUAL(limbs_res, limbs_N);
 
     TEST_EQUAL(mbedtls_mpi_mod_modulus_setup(
-                   &m, N, limbs_N,
-                   MBEDTLS_MPI_MOD_REP_OPT_RED), 0);
+                   &m, N, limbs_N), 0);
 
     TEST_EQUAL((*curve_func)(X, limbs_X), 0);
 
@@ -1407,16 +1406,18 @@
     TEST_EQUAL(ret, iret);
 
     if (ret == 0) {
-
+        TEST_ASSERT(m.int_rep != MBEDTLS_MPI_MOD_REP_INVALID);
         /* Test for limb sizes */
         TEST_EQUAL(m.limbs, p_limbs);
         bytes = p_limbs * sizeof(mbedtls_mpi_uint);
 
-        /* Test for validity of moduli by the presence of Montgomery consts */
-
-        TEST_ASSERT(m.rep.mont.mm != 0);
-        TEST_ASSERT(m.rep.mont.rr != NULL);
-
+        if (m.int_rep == MBEDTLS_MPI_MOD_REP_MONTGOMERY) {
+            /* Test for validity of moduli by the presence of Montgomery consts */
+            TEST_ASSERT(m.rep.mont.mm != 0);
+            TEST_ASSERT(m.rep.mont.rr != NULL);
+        } else {
+            TEST_ASSERT(m.rep.ored.modp != NULL);
+        }
 
         /* Compare output byte-by-byte */
         ASSERT_COMPARE(p, bytes, m.p, bytes);