Add core constant time comparison

Unfortunately reusing the new function from the signed constant time
comparison is not trivial.

One option would be to do temporary conditional swaps which would prevent
qualifying input to const. Another way would be to add an additional
flag for the sign and make it an integral part of the computation, which
would defeat the purpose of having an unsigned core comparison.

Going with two separate function for now and the signed version can be
retired/compiled out with the legacy API eventually.

The new function in theory could be placed into either
`library/constant_time.c` or `library/bignum_new.c`. Going with the
first as the other functions in the second are not constant time yet and
this distinction seems more valuable for new (as opposed to belonging to
the `_core` functions.

Signed-off-by: Janos Follath <janos.follath@arm.com>
diff --git a/tests/suites/test_suite_mpi.data b/tests/suites/test_suite_mpi.data
index 1974e3f..e52953c 100644
--- a/tests/suites/test_suite_mpi.data
+++ b/tests/suites/test_suite_mpi.data
@@ -409,6 +409,63 @@
 Test mbedtls_mpi_cmp_mpi: large negative < 0 (1 limb)
 mbedtls_mpi_cmp_mpi:"-1230000000000000000":"0":-1
 
+Base test mbedtls_mpi_core_lt_ct #1
+mbedtls_mpi_core_lt_ct:"02B5":"02B5":0
+
+Base test mbedtls_mpi_core_lt_ct #2
+mbedtls_mpi_core_lt_ct:"02B5":"02B4":0
+
+Base test mbedtls_mpi_core_lt_ct #3
+mbedtls_mpi_core_lt_ct:"02B5":"02B6":1
+
+Base test mbedtls_mpi_core_lt_ct (length=0)
+mbedtls_mpi_core_lt_ct:"":"":0
+
+Base test mbedtls_mpi_core_lt_ct (corner case - 64 bit) #1
+mbedtls_mpi_core_lt_ct:"7FFFFFFFFFFFFFFF":"FF":0
+
+Base test mbedtls_mpi_core_lt_ct (corner case - 64 bit) #2
+mbedtls_mpi_core_lt_ct:"8000000000000000":"7FFFFFFFFFFFFFFF":0
+
+Base test mbedtls_mpi_core_lt_ct (corner case - 64 bit) #3
+mbedtls_mpi_core_lt_ct:"8000000000000000":"01":0
+
+Base test mbedtls_mpi_core_lt_ct (corner case - 64 bit) #4
+mbedtls_mpi_core_lt_ct:"8000000000000000":"00":0
+
+Base test mbedtls_mpi_core_lt_ct (corner case - 64 bit) #5
+mbedtls_mpi_core_lt_ct:"FFFFFFFFFFFFFFFF":"FF":0
+
+Base test mbedtls_mpi_core_lt_ct (corner case - 32 bit) #1
+mbedtls_mpi_core_lt_ct:"7FFFFFFF":"FF":0
+
+Base test mbedtls_mpi_core_lt_ct (corner case - 32 bit) #2
+mbedtls_mpi_core_lt_ct:"80000000":"7FFFFFFF":0
+
+Base test mbedtls_mpi_core_lt_ct (corner case - 32 bit) #3
+mbedtls_mpi_core_lt_ct:"80000000":"01":0
+
+Base test mbedtls_mpi_core_lt_ct (corner case - 32 bit) #4
+mbedtls_mpi_core_lt_ct:"80000000":"00":0
+
+Base test mbedtls_mpi_core_lt_ct (corner case - 32 bit) #5
+mbedtls_mpi_core_lt_ct:"FFFFFFFF":"FF":0
+
+Multi-limb mbedtls_mpi_core_lt_ct (X<Y, zero vs non-zero MS limb)
+mbedtls_mpi_core_lt_ct:"00FFFFFFFFFFFFFFFF":"01FFFFFFFFFFFFFFFF":1
+
+Multi-limb mbedtls_mpi_core_lt_ct (X>Y, equal MS limbs)
+mbedtls_mpi_core_lt_ct:"EEFFFFFFFFFFFFFFFF":"EEFFFFFFFFFFFFFFF1":0
+
+Multi-limb mbedtls_mpi_core_lt_ct (X=Y)
+mbedtls_mpi_core_lt_ct:"EEFFFFFFFFFFFFFFFF":"EEFFFFFFFFFFFFFFFF":0
+
+Multi-limb mbedtls_mpi_core_lt_ct (Alternating limbs) #1
+mbedtls_mpi_core_lt_ct:"11FFFFFFFFFFFFFFFF":"FF1111111111111111":1
+
+Multi-limb mbedtls_mpi_core_lt_ct (Alternating limbs) #2
+mbedtls_mpi_core_lt_ct:"FF1111111111111111":"11FFFFFFFFFFFFFFFF":0
+
 Base test mbedtls_mpi_lt_mpi_ct #1
 mbedtls_mpi_lt_mpi_ct:1:"2B5":1:"2B5":0:0
 
diff --git a/tests/suites/test_suite_mpi.function b/tests/suites/test_suite_mpi.function
index b0d947c..ff87ea4 100644
--- a/tests/suites/test_suite_mpi.function
+++ b/tests/suites/test_suite_mpi.function
@@ -2,6 +2,8 @@
 #include "mbedtls/bignum.h"
 #include "mbedtls/entropy.h"
 #include "bignum_core.h"
+#include "constant_time_internal.h"
+#include "test/constant_flow.h"
 
 #if MBEDTLS_MPI_MAX_BITS > 792
 #define MPI_MAX_BITS_LARGER_THAN_792
@@ -608,6 +610,42 @@
 /* END_CASE */
 
 /* BEGIN_CASE */
+void mbedtls_mpi_core_lt_ct( data_t * input_X, data_t * input_Y, int input_ret )
+{
+    #define MAX_LEN 64
+    mbedtls_mpi_uint X[MAX_LEN];
+    mbedtls_mpi_uint Y[MAX_LEN];
+    unsigned exp_ret = input_ret;
+    unsigned ret;
+    size_t len = CHARS_TO_LIMBS(
+                    input_X->len > input_Y->len ? input_X->len : input_Y->len );
+
+    TEST_ASSERT( len <= MAX_LEN );
+
+    TEST_ASSERT( mbedtls_mpi_core_read_be( X, len, input_X->x, input_X->len )
+                 == 0 );
+    TEST_ASSERT( mbedtls_mpi_core_read_be( Y, len, input_Y->x, input_Y->len )
+                 == 0 );
+
+    TEST_CF_SECRET( X, len * sizeof( mbedtls_mpi_uint ) );
+    TEST_CF_SECRET( Y, len * sizeof( mbedtls_mpi_uint ) );
+
+    ret = mbedtls_mpi_core_lt_ct( X, Y, len );
+
+    TEST_CF_PUBLIC( X, len * sizeof( mbedtls_mpi_uint ) );
+    TEST_CF_PUBLIC( Y, len * sizeof( mbedtls_mpi_uint ) );
+    TEST_CF_PUBLIC( &ret, sizeof( ret ) );
+
+    TEST_ASSERT( ret == exp_ret );
+
+exit:
+    ;
+
+    #undef MAX_LEN
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
 void mbedtls_mpi_lt_mpi_ct( int size_X, char * input_X,
                             int size_Y, char * input_Y,
                             int input_ret, int input_err )