Merge pull request #1239 from Mbed-TLS/change-mpi-mla-to-constant-time

Change mbedtls_mpi_core_mla() to be constant time
diff --git a/library/bignum_core.c b/library/bignum_core.c
index ee3d704..39ab6e9 100644
--- a/library/bignum_core.c
+++ b/library/bignum_core.c
@@ -490,7 +490,7 @@
 
     while (excess_len--) {
         *d += c;
-        c = (*d < c);
+        c = mbedtls_ct_mpi_uint_if(mbedtls_ct_uint_lt(*d, c), 1, 0);
         d++;
     }
 
diff --git a/library/bignum_core.h b/library/bignum_core.h
index b32d607..eac91f5 100644
--- a/library/bignum_core.h
+++ b/library/bignum_core.h
@@ -400,6 +400,9 @@
  *
  * This function operates modulo `2^(biL*X_limbs)`.
  *
+ * This function operates in constant time with respect to the values
+ * of \p X and \p A and \p b.
+ *
  * \param[in,out] X  The pointer to the (little-endian) array
  *                   representing the bignum to accumulate onto.
  * \param X_limbs    The number of limbs of \p X. This must be
diff --git a/tests/suites/test_suite_bignum_core.function b/tests/suites/test_suite_bignum_core.function
index bd1dfa6..0869a1e 100644
--- a/tests/suites/test_suite_bignum_core.function
+++ b/tests/suites/test_suite_bignum_core.function
@@ -787,16 +787,36 @@
     memcpy(a, A.p, A.n * sizeof(mbedtls_mpi_uint));
     memcpy(x, X->p, X->n * sizeof(mbedtls_mpi_uint));
 
+#if !defined(MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN)
+    TEST_CF_SECRET(a, bytes);
+    TEST_CF_SECRET(B.p, B.n * sizeof(mbedtls_mpi_uint));
+    TEST_CF_SECRET(S.p, sizeof(mbedtls_mpi_uint));
+#endif
+
     /* 1a) A += B * s => we should get the correct carry */
     TEST_EQUAL(mbedtls_mpi_core_mla(a, limbs, B.p, B.n, *S.p), *cy->p);
 
+#if !defined(MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN)
+    TEST_CF_PUBLIC(a, bytes);
+    TEST_CF_PUBLIC(B.p, B.n * sizeof(mbedtls_mpi_uint));
+    TEST_CF_PUBLIC(S.p, sizeof(mbedtls_mpi_uint));
+#endif
+
     /* 1b) A += B * s => we should get the correct result */
     TEST_MEMORY_COMPARE(a, bytes, x, bytes);
 
     if (A.n == B.n && memcmp(A.p, B.p, bytes) == 0) {
         /* Check when A and B are aliased */
         memcpy(a, A.p, A.n * sizeof(mbedtls_mpi_uint));
+#if !defined(MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN)
+        TEST_CF_SECRET(a, bytes);
+        TEST_CF_SECRET(S.p, sizeof(mbedtls_mpi_uint));
+#endif
         TEST_EQUAL(mbedtls_mpi_core_mla(a, limbs, a, limbs, *S.p), *cy->p);
+#if !defined(MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN)
+        TEST_CF_PUBLIC(a, bytes);
+        TEST_CF_PUBLIC(S.p, sizeof(mbedtls_mpi_uint));
+#endif
         TEST_MEMORY_COMPARE(a, bytes, x, bytes);
     }