Move bignum helpers to their own module

Move bignum-related helper functions to their own files under tests/include
and tests/src. The primary motivation is that a subsequent commit will make
bignum_helpers.h include library/bignum*.h, but we want to be able to
include <test/helpers.h> without having the library directory on the include
path (we do this in some programs under programs/ intended for testing).

Signed-off-by: Gilles Peskine <Gilles.Peskine@arm.com>
diff --git a/tests/include/test/bignum_helpers.h b/tests/include/test/bignum_helpers.h
new file mode 100644
index 0000000..22ce7f7
--- /dev/null
+++ b/tests/include/test/bignum_helpers.h
@@ -0,0 +1,90 @@
+/**
+ * \file bignum_helpers.h
+ *
+ * \brief   This file contains the prototypes of helper functions for
+ *          bignum-related testing.
+ */
+
+/*
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *  not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+#ifndef TEST_BIGNUM_HELPERS_H
+#define TEST_BIGNUM_HELPERS_H
+
+#include <mbedtls/build_info.h>
+
+#if defined(MBEDTLS_BIGNUM_C)
+
+#include <mbedtls/bignum.h>
+
+/** Allocate and populate a core MPI from a test case argument.
+ *
+ * This function allocates exactly as many limbs as necessary to fit
+ * the length of the input. In other words, it preserves leading zeros.
+ *
+ * The limb array is allocated with mbedtls_calloc() and must later be
+ * freed with mbedtls_free().
+ *
+ * \param[in,out] pX    The address where a pointer to the allocated limb
+ *                      array will be stored.
+ *                      \c *pX must be null on entry.
+ *                      On exit, \c *pX is null on error or if the number
+ *                      of limbs is 0.
+ * \param[out] plimbs   The address where the number of limbs will be stored.
+ * \param[in] input     The test argument to read.
+ *                      It is interpreted as a hexadecimal representation
+ *                      of a non-negative integer.
+ *
+ * \return \c 0 on success, an \c MBEDTLS_ERR_MPI_xxx error code otherwise.
+ */
+int mbedtls_test_read_mpi_core( mbedtls_mpi_uint **pX, size_t *plimbs,
+                                const char *input );
+
+/** Read an MPI from a hexadecimal string.
+ *
+ * Like mbedtls_mpi_read_string(), but with tighter guarantees around
+ * edge cases.
+ *
+ * - This function guarantees that if \p s begins with '-' then the sign
+ *   bit of the result will be negative, even if the value is 0.
+ *   When this function encounters such a "negative 0", it
+ *   increments #mbedtls_test_case_uses_negative_0.
+ * - The size of the result is exactly the minimum number of limbs needed
+ *   to fit the digits in the input. In particular, this function constructs
+ *   a bignum with 0 limbs for an empty string, and a bignum with leading 0
+ *   limbs if the string has sufficiently many leading 0 digits.
+ *   This is important so that the "0 (null)" and "0 (1 limb)" and
+ *   "leading zeros" test cases do what they claim.
+ *
+ * \param[out] X        The MPI object to populate. It must be initialized.
+ * \param[in] s         The null-terminated hexadecimal string to read from.
+ *
+ * \return \c 0 on success, an \c MBEDTLS_ERR_MPI_xxx error code otherwise.
+ */
+int mbedtls_test_read_mpi( mbedtls_mpi *X, const char *s );
+
+/** Nonzero if the current test case had an input parsed with
+ * mbedtls_test_read_mpi() that is a negative 0 (`"-"`, `"-0"`, `"-00"`, etc.,
+ * constructing a result with the sign bit set to -1 and the value being
+ * all-limbs-0, which is not a valid representation in #mbedtls_mpi but is
+ * tested for robustness).
+ */
+extern unsigned mbedtls_test_case_uses_negative_0;
+
+#endif /* MBEDTLS_BIGNUM_C */
+
+#endif /* TEST_BIGNUM_HELPERS_H */
diff --git a/tests/include/test/helpers.h b/tests/include/test/helpers.h
index 5f9bde6..b64bfcb 100644
--- a/tests/include/test/helpers.h
+++ b/tests/include/test/helpers.h
@@ -216,6 +216,17 @@
                           int len );
 
 /**
+ * \brief Convert hexadecimal digit to an integer.
+ *
+ * \param c        The digit to convert (`'0'` to `'9'`, `'A'` to `'F'` or
+ *                 `'a'` to `'f'`).
+ * \param[out] uc  On success, the value of the digit (0 to 15).
+ *
+ * \return         0 on success, -1 if \p c is not a hexadecimal digit.
+ */
+int mbedtls_test_ascii2uc(const char c, unsigned char *uc);
+
+/**
  * Allocate and zeroize a buffer.
  *
  * If the size if zero, a pointer to a zeroized 1-byte buffer is returned.
@@ -269,60 +280,4 @@
                                  const char *file, int line);
 #endif
 
-#if defined(MBEDTLS_BIGNUM_C)
-/** Allocate and populate a core MPI from a test case argument.
- *
- * This function allocates exactly as many limbs as necessary to fit
- * the length of the input. In other words, it preserves leading zeros.
- *
- * The limb array is allocated with mbedtls_calloc() and must later be
- * freed with mbedtls_free().
- *
- * \param[in,out] pX    The address where a pointer to the allocated limb
- *                      array will be stored.
- *                      \c *pX must be null on entry.
- *                      On exit, \c *pX is null on error or if the number
- *                      of limbs is 0.
- * \param[out] plimbs   The address where the number of limbs will be stored.
- * \param[in] input     The test argument to read.
- *                      It is interpreted as a hexadecimal representation
- *                      of a non-negative integer.
- *
- * \return \c 0 on success, an \c MBEDTLS_ERR_MPI_xxx error code otherwise.
- */
-int mbedtls_test_read_mpi_core( mbedtls_mpi_uint **pX, size_t *plimbs,
-                                const char *input );
-
-/** Read an MPI from a hexadecimal string.
- *
- * Like mbedtls_mpi_read_string(), but with tighter guarantees around
- * edge cases.
- *
- * - This function guarantees that if \p s begins with '-' then the sign
- *   bit of the result will be negative, even if the value is 0.
- *   When this function encounters such a "negative 0", it
- *   increments #mbedtls_test_case_uses_negative_0.
- * - The size of the result is exactly the minimum number of limbs needed
- *   to fit the digits in the input. In particular, this function constructs
- *   a bignum with 0 limbs for an empty string, and a bignum with leading 0
- *   limbs if the string has sufficiently many leading 0 digits.
- *   This is important so that the "0 (null)" and "0 (1 limb)" and
- *   "leading zeros" test cases do what they claim.
- *
- * \param[out] X        The MPI object to populate. It must be initialized.
- * \param[in] s         The null-terminated hexadecimal string to read from.
- *
- * \return \c 0 on success, an \c MBEDTLS_ERR_MPI_xxx error code otherwise.
- */
-int mbedtls_test_read_mpi( mbedtls_mpi *X, const char *s );
-
-/** Nonzero if the current test case had an input parsed with
- * mbedtls_test_read_mpi() that is a negative 0 (`"-"`, `"-0"`, `"-00"`, etc.,
- * constructing a result with the sign bit set to -1 and the value being
- * all-limbs-0, which is not a valid representation in #mbedtls_mpi but is
- * tested for robustness).
- */
-extern unsigned mbedtls_test_case_uses_negative_0;
-#endif /* MBEDTLS_BIGNUM_C */
-
 #endif /* TEST_HELPERS_H */
diff --git a/tests/src/bignum_helpers.c b/tests/src/bignum_helpers.c
new file mode 100644
index 0000000..575bd03
--- /dev/null
+++ b/tests/src/bignum_helpers.c
@@ -0,0 +1,119 @@
+/**
+ * \file bignum_helpers.c
+ *
+ * \brief   This file contains the prototypes of helper functions for
+ *          bignum-related testing.
+ */
+
+/*
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *  not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+#define MBEDTLS_ALLOW_PRIVATE_ACCESS
+#include <test/bignum_helpers.h>
+
+#if defined(MBEDTLS_BIGNUM_C)
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <mbedtls/bignum.h>
+#include <bignum_core.h>
+#include <bignum_mod.h>
+#include <bignum_mod_raw.h>
+
+#include <test/helpers.h>
+#include <test/macros.h>
+
+int mbedtls_test_read_mpi_core( mbedtls_mpi_uint **pX, size_t *plimbs,
+                                const char *input )
+{
+    /* Sanity check */
+    if( *pX != NULL )
+        return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
+
+    size_t hex_len = strlen( input );
+    size_t byte_len = ( hex_len + 1 ) / 2;
+    *plimbs = CHARS_TO_LIMBS( byte_len );
+
+    /* A core bignum is not allowed to be empty. Forbid it as test data,
+     * this way static analyzers have a chance of knowing we don't expect
+     * the bignum functions to support empty inputs. */
+    if( *plimbs == 0 )
+        return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
+
+    *pX = mbedtls_calloc( *plimbs, sizeof( **pX ) );
+    if( *pX == NULL )
+        return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
+
+    unsigned char *byte_start = ( unsigned char * ) *pX;
+    if( byte_len % sizeof( mbedtls_mpi_uint ) != 0 )
+    {
+        byte_start += sizeof( mbedtls_mpi_uint ) - byte_len % sizeof( mbedtls_mpi_uint );
+    }
+    if( ( hex_len & 1 ) != 0 )
+    {
+        /* mbedtls_test_unhexify wants an even number of hex digits */
+        TEST_ASSERT( mbedtls_test_ascii2uc( *input, byte_start ) == 0 );
+        ++byte_start;
+        ++input;
+        --byte_len;
+    }
+    TEST_ASSERT( mbedtls_test_unhexify( byte_start,
+                                        byte_len,
+                                        input,
+                                        &byte_len ) == 0 );
+
+    mbedtls_mpi_core_bigendian_to_host( *pX, *plimbs );
+    return( 0 );
+
+exit:
+    mbedtls_free( *pX );
+    return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
+}
+
+int mbedtls_test_read_mpi( mbedtls_mpi *X, const char *s )
+{
+    int negative = 0;
+    /* Always set the sign bit to -1 if the input has a minus sign, even for 0.
+     * This creates an invalid representation, which mbedtls_mpi_read_string()
+     * avoids but we want to be able to create that in test data. */
+    if( s[0] == '-' )
+    {
+        ++s;
+        negative = 1;
+    }
+    /* mbedtls_mpi_read_string() currently retains leading zeros.
+     * It always allocates at least one limb for the value 0. */
+    if( s[0] == 0 )
+    {
+        mbedtls_mpi_free( X );
+        return( 0 );
+    }
+    int ret = mbedtls_mpi_read_string( X, 16, s );
+    if( ret != 0 )
+        return( ret );
+    if( negative )
+    {
+        if( mbedtls_mpi_cmp_int( X, 0 ) == 0 )
+            ++mbedtls_test_case_uses_negative_0;
+        X->s = -1;
+    }
+    return( 0 );
+}
+
+#endif /* MBEDTLS_BIGNUM_C */
+
diff --git a/tests/src/helpers.c b/tests/src/helpers.c
index 7c83714..be5c465 100644
--- a/tests/src/helpers.c
+++ b/tests/src/helpers.c
@@ -48,7 +48,7 @@
 #endif /* MBEDTLS_PLATFORM_C */
 }
 
-static int ascii2uc(const char c, unsigned char *uc)
+int mbedtls_test_ascii2uc(const char c, unsigned char *uc)
 {
     if( ( c >= '0' ) && ( c <= '9' ) )
         *uc = c - '0';
@@ -207,10 +207,10 @@
 
     while( *ibuf != 0 )
     {
-        if ( ascii2uc( *(ibuf++), &uc ) != 0 )
+        if ( mbedtls_test_ascii2uc( *(ibuf++), &uc ) != 0 )
             return( -1 );
 
-        if ( ascii2uc( *(ibuf++), &uc2 ) != 0 )
+        if ( mbedtls_test_ascii2uc( *(ibuf++), &uc2 ) != 0 )
             return( -1 );
 
         *(obuf++) = ( uc << 4 ) | uc2;
@@ -350,84 +350,3 @@
     }
 }
 #endif /* MBEDTLS_TEST_HOOKS */
-
-#if defined(MBEDTLS_BIGNUM_C)
-#include "bignum_core.h"
-
-int mbedtls_test_read_mpi_core( mbedtls_mpi_uint **pX, size_t *plimbs,
-                                const char *input )
-{
-    /* Sanity check */
-    if( *pX != NULL )
-        return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
-
-    size_t hex_len = strlen( input );
-    size_t byte_len = ( hex_len + 1 ) / 2;
-    *plimbs = CHARS_TO_LIMBS( byte_len );
-
-    /* A core bignum is not allowed to be empty. Forbid it as test data,
-     * this way static analyzers have a chance of knowing we don't expect
-     * the bignum functions to support empty inputs. */
-    if( *plimbs == 0 )
-        return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
-
-    *pX = mbedtls_calloc( *plimbs, sizeof( **pX ) );
-    if( *pX == NULL )
-        return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
-
-    unsigned char *byte_start = ( unsigned char * ) *pX;
-    if( byte_len % sizeof( mbedtls_mpi_uint ) != 0 )
-    {
-        byte_start += sizeof( mbedtls_mpi_uint ) - byte_len % sizeof( mbedtls_mpi_uint );
-    }
-    if( ( hex_len & 1 ) != 0 )
-    {
-        /* mbedtls_test_unhexify wants an even number of hex digits */
-        TEST_ASSERT( ascii2uc( *input, byte_start ) == 0 );
-        ++byte_start;
-        ++input;
-        --byte_len;
-    }
-    TEST_ASSERT( mbedtls_test_unhexify( byte_start,
-                                        byte_len,
-                                        input,
-                                        &byte_len ) == 0 );
-
-    mbedtls_mpi_core_bigendian_to_host( *pX, *plimbs );
-    return( 0 );
-
-exit:
-    mbedtls_free( *pX );
-    return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
-}
-
-int mbedtls_test_read_mpi( mbedtls_mpi *X, const char *s )
-{
-    int negative = 0;
-    /* Always set the sign bit to -1 if the input has a minus sign, even for 0.
-     * This creates an invalid representation, which mbedtls_mpi_read_string()
-     * avoids but we want to be able to create that in test data. */
-    if( s[0] == '-' )
-    {
-        ++s;
-        negative = 1;
-    }
-    /* mbedtls_mpi_read_string() currently retains leading zeros.
-     * It always allocates at least one limb for the value 0. */
-    if( s[0] == 0 )
-    {
-        mbedtls_mpi_free( X );
-        return( 0 );
-    }
-    int ret = mbedtls_mpi_read_string( X, 16, s );
-    if( ret != 0 )
-        return( ret );
-    if( negative )
-    {
-        if( mbedtls_mpi_cmp_int( X, 0 ) == 0 )
-            ++mbedtls_test_case_uses_negative_0;
-        X->s = -1;
-    }
-    return( 0 );
-}
-#endif
diff --git a/tests/suites/helpers.function b/tests/suites/helpers.function
index fe33f9b..8249564 100644
--- a/tests/suites/helpers.function
+++ b/tests/suites/helpers.function
@@ -5,6 +5,7 @@
 #include <test/helpers.h>
 #include <test/macros.h>
 #include <test/random.h>
+#include <test/bignum_helpers.h>
 #include <test/psa_crypto_helpers.h>
 
 #include <stdlib.h>