Extract Secp224r1 from the prototype

Signed-off-by: Gabor Mezei <gabor.mezei@arm.com>
diff --git a/library/ecp_curves.c b/library/ecp_curves.c
index 1a027d6..d42f093 100644
--- a/library/ecp_curves.c
+++ b/library/ecp_curves.c
@@ -4575,6 +4575,7 @@
 #endif
 #if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED)
 static int ecp_mod_p224(mbedtls_mpi *);
+static int ecp_mod_p224_raw(mbedtls_mpi_uint *Np, size_t Nn);
 #endif
 #if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED)
 static int ecp_mod_p256(mbedtls_mpi *);
@@ -4951,6 +4952,176 @@
 #if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) ||   \
     defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) ||   \
     defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED)
+
+/*
+ * The reader is advised to first understand ecp_mod_p192() since the same
+ * general structure is used here, but with additional complications:
+ * (1) chunks of 32 bits, and (2) subtractions.
+ */
+
+/*
+ * For these primes, we need to handle data in chunks of 32 bits.
+ * This makes it more complicated if we use 64 bits limbs in MPI,
+ * which prevents us from using a uniform access method as for p192.
+ *
+ * So, we define a mini abstraction layer to access 32 bit chunks,
+ * load them in 'cur' for work, and store them back from 'cur' when done.
+ *
+ * While at it, also define the size of N in terms of 32-bit chunks.
+ */
+#define LOAD32      cur = A(i);
+
+#if defined(MBEDTLS_HAVE_INT32)  /* 32 bit */
+
+#define MAX32       Nn
+#define A(j)        Np[j]
+#define STORE32     Np[i] = cur;
+#define STORE0      Np[i] = 0;
+
+#else /* 64 bit */
+
+#define MAX32   Nn * 2
+#define A(j)    (j) % 2 ? (uint32_t) (Np[(j) / 2] >> 32) :  \
+                          (uint32_t) (Np[(j) / 2])
+#define STORE32                                             \
+    if (i % 2) {                                            \
+        Np[i/2] &= 0x00000000FFFFFFFF;                      \
+        Np[i/2] |= (uint64_t) (cur) << 32;                  \
+    } else {                                                \
+        Np[i/2] &= 0xFFFFFFFF00000000;                      \
+        Np[i/2] |= (uint32_t) cur;                          \
+    }
+
+#define STORE0                                              \
+    if (i % 2) {                                            \
+        Np[i/2] &= 0x00000000FFFFFFFF;                      \
+    } else {                                                \
+        Np[i/2] &= 0xFFFFFFFF00000000;                      \
+    }
+
+#endif
+
+static inline int8_t extract_carry(int64_t cur)
+{
+    return (int8_t) (cur >> 32);
+}
+
+#define ADD(j)    cur += A(j)
+#define SUB(j)    cur -= A(j)
+
+#define ADD_CARRY(cc) cur += (cc)
+#define SUB_CARRY(cc) cur -= (cc)
+
+#define ADD_LAST ADD_CARRY(last_c)
+#define SUB_LAST SUB_CARRY(last_c)
+
+/*
+ * Helpers for the main 'loop'
+ */
+#define INIT(b)                                         \
+    int8_t c = 0, last_c;                               \
+    int64_t cur;                                        \
+    size_t i = 0;                                       \
+    LOAD32;
+
+#define NEXT                                            \
+    c = extract_carry(cur);                             \
+    STORE32; i++; LOAD32;                               \
+    ADD_CARRY(c);
+
+#define RESET                                           \
+    c = extract_carry(cur);                             \
+    last_c = c;                                         \
+    STORE32; i = 0; LOAD32;                             \
+    c = 0;                                              \
+
+#define LAST                                            \
+    c = extract_carry(cur);                             \
+    STORE32; i++;                                       \
+    if (c != 0)                                         \
+    return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;              \
+    while (i < MAX32) { STORE0; i++; }
+
+#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED)
+
+/*
+ * Fast quasi-reduction modulo p224 (FIPS 186-3 D.2.2)
+ */
+static int ecp_mod_p224(mbedtls_mpi *N)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    size_t expected_width = 2 * ((224 + biL - 1) / biL);
+    MBEDTLS_MPI_CHK(mbedtls_mpi_grow(N, expected_width));
+    ret = ecp_mod_p224_raw(N->p, expected_width);
+cleanup:
+    return ret;
+}
+
+static int ecp_mod_p224_raw(mbedtls_mpi_uint *Np, size_t Nn)
+{
+    if (Nn != 2 * ((224 + biL - 1) / biL)) {
+        return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
+    }
+
+    INIT(224);
+
+    SUB( 7); SUB(11);           NEXT;   // A0 += -A7  - A11
+    SUB( 8); SUB(12);           NEXT;   // A1 += -A8  - A12
+    SUB( 9); SUB(13);           NEXT;   // A2 += -A9  - A13
+    SUB(10); ADD( 7); ADD(11);  NEXT;   // A3 += -A10 + A7 + A11
+    SUB(11); ADD( 8); ADD(12);  NEXT;   // A4 += -A11 + A8 + A12
+    SUB(12); ADD( 9); ADD(13);  NEXT;   // A5 += -A12 + A9 + A13
+    SUB(13); ADD(10);                   // A6 += -A13 + A10
+
+    RESET;
+
+    SUB_LAST; NEXT;                     // A0
+              NEXT;                     // A1
+              NEXT;                     // A2
+    ADD_LAST; NEXT;                     // A3
+              NEXT;                     // A4
+              NEXT;                     // A5
+                                        // A6
+
+    RESET;
+
+    SUB_LAST; NEXT;                     // A0
+              NEXT;                     // A1
+              NEXT;                     // A2
+    ADD_LAST; NEXT;                     // A3
+              NEXT;                     // A4
+              NEXT;                     // A5
+                                        // A6
+
+    LAST;
+
+    return 0;
+}
+
+#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */
+
+#undef LOAD32
+#undef MAX32
+#undef A
+#undef STORE32
+#undef STORE0
+#undef ADD
+#undef SUB
+#undef ADD_CARRY
+#undef SUB_CARRY
+#undef ADD_LAST
+#undef SUB_LAST
+#undef INIT
+#undef NEXT
+#undef RESET
+#undef LAST
+
+#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED ||
+          MBEDTLS_ECP_DP_SECP256R1_ENABLED ||
+          MBEDTLS_ECP_DP_SECP384R1_ENABLED */
+
+#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) ||   \
+    defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED)
 /*
  * The reader is advised to first understand ecp_mod_p192() since the same
  * general structure is used here, but with additional complications:
@@ -5071,27 +5242,6 @@
     N->p[bits / 8 / sizeof(mbedtls_mpi_uint)] += msw;
 }
 
-#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED)
-/*
- * Fast quasi-reduction modulo p224 (FIPS 186-3 D.2.2)
- */
-static int ecp_mod_p224(mbedtls_mpi *N)
-{
-    INIT(224);
-
-    SUB(7); SUB(11);               NEXT;      // A0 += -A7 - A11
-    SUB(8); SUB(12);               NEXT;      // A1 += -A8 - A12
-    SUB(9); SUB(13);               NEXT;      // A2 += -A9 - A13
-    SUB(10); ADD(7); ADD(11);    NEXT;        // A3 += -A10 + A7 + A11
-    SUB(11); ADD(8); ADD(12);    NEXT;        // A4 += -A11 + A8 + A12
-    SUB(12); ADD(9); ADD(13);    NEXT;        // A5 += -A12 + A9 + A13
-    SUB(13); ADD(10);               LAST;     // A6 += -A13 + A10
-
-cleanup:
-    return ret;
-}
-#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */
-
 #if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED)
 /*
  * Fast quasi-reduction modulo p256 (FIPS 186-3 D.2.3)
@@ -5186,8 +5336,7 @@
 #undef NEXT
 #undef LAST
 
-#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED ||
-          MBEDTLS_ECP_DP_SECP256R1_ENABLED ||
+#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED ||
           MBEDTLS_ECP_DP_SECP384R1_ENABLED */
 
 #if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED)
diff --git a/library/ecp_invasive.h b/library/ecp_invasive.h
index 3d1321c..19d516f 100644
--- a/library/ecp_invasive.h
+++ b/library/ecp_invasive.h
@@ -32,8 +32,7 @@
 
 #if defined(MBEDTLS_TEST_HOOKS) && defined(MBEDTLS_ECP_C)
 
-#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) ||   \
-    defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) ||   \
+#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) ||   \
     defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED)
 /* Preconditions:
  *   - bits is a multiple of 64 or is 224
diff --git a/tests/suites/test_suite_ecp.function b/tests/suites/test_suite_ecp.function
index 4e74d9b..a38720c 100644
--- a/tests/suites/test_suite_ecp.function
+++ b/tests/suites/test_suite_ecp.function
@@ -8,8 +8,7 @@
 #include "bignum_mod_raw_invasive.h"
 
 #if defined(MBEDTLS_TEST_HOOKS) &&                  \
-    (defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) ||  \
-    defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) ||  \
+    (defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) ||  \
     defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED))
 #define HAVE_FIX_NEGATIVE
 #endif