Merge pull request #9638 from gilles-peskine-arm/ssl-opt-sample-programs-dev

Test sample programs in ssl-opt.sh
diff --git a/ChangeLog.d/split-numeric-string-conversions-out-of-the-oid-module.txt b/ChangeLog.d/split-numeric-string-conversions-out-of-the-oid-module.txt
new file mode 100644
index 0000000..938e9ec
--- /dev/null
+++ b/ChangeLog.d/split-numeric-string-conversions-out-of-the-oid-module.txt
@@ -0,0 +1,4 @@
+Changes
+   * Functions regarding numeric string conversions for OIDs have been moved
+     from the OID module and now reside in X.509 module. This helps to reduce
+     the code size as these functions are not commonly used outside of X.509.
diff --git a/framework b/framework
index 8c488b1..4e9e839 160000
--- a/framework
+++ b/framework
@@ -1 +1 @@
-Subproject commit 8c488b1b8f86384450c922f22cd1bee0b996be13
+Subproject commit 4e9e8391cd64974d16234160532ef2d6dec9ced6
diff --git a/include/mbedtls/x509.h b/include/mbedtls/x509.h
index 453f598..18df19c 100644
--- a/include/mbedtls/x509.h
+++ b/include/mbedtls/x509.h
@@ -492,6 +492,38 @@
         p += (size_t) ret;                                  \
     } while (0)
 
+/**
+ * \brief           Translate an ASN.1 OID into its numeric representation
+ *                  (e.g. "\x2A\x86\x48\x86\xF7\x0D" into "1.2.840.113549")
+ *
+ * \param buf       buffer to put representation in
+ * \param size      size of the buffer
+ * \param oid       OID to translate
+ *
+ * \return          Length of the string written (excluding final NULL) or
+ *                  MBEDTLS_ERR_OID_BUF_TOO_SMALL in case of error
+ */
+int mbedtls_oid_get_numeric_string(char *buf, size_t size, const mbedtls_asn1_buf *oid);
+
+/**
+ * \brief           Translate a string containing a dotted-decimal
+ *                  representation of an ASN.1 OID into its encoded form
+ *                  (e.g. "1.2.840.113549" into "\x2A\x86\x48\x86\xF7\x0D").
+ *                  On success, this function allocates oid->buf from the
+ *                  heap. It must be freed by the caller using mbedtls_free().
+ *
+ * \param oid       #mbedtls_asn1_buf to populate with the DER-encoded OID
+ * \param oid_str   string representation of the OID to parse
+ * \param size      length of the OID string, not including any null terminator
+ *
+ * \return          0 if successful
+ * \return          #MBEDTLS_ERR_ASN1_INVALID_DATA if \p oid_str does not
+ *                  represent a valid OID
+ * \return          #MBEDTLS_ERR_ASN1_ALLOC_FAILED if the function fails to
+ *                  allocate oid->buf
+ */
+int mbedtls_oid_from_numeric_string(mbedtls_asn1_buf *oid, const char *oid_str, size_t size);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/library/x509.c b/library/x509.c
index a80ab53..be7b277 100644
--- a/library/x509.c
+++ b/library/x509.c
@@ -805,6 +805,75 @@
     return (i < 10) ? (i + '0') : (i - 10 + 'A');
 }
 
+/* Return the x.y.z.... style numeric string for the given OID */
+int mbedtls_oid_get_numeric_string(char *buf, size_t size,
+                                   const mbedtls_asn1_buf *oid)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    char *p = buf;
+    size_t n = size;
+    unsigned int value = 0;
+
+    if (size > INT_MAX) {
+        /* Avoid overflow computing return value */
+        return MBEDTLS_ERR_ASN1_INVALID_LENGTH;
+    }
+
+    if (oid->len <= 0) {
+        /* OID must not be empty */
+        return MBEDTLS_ERR_ASN1_OUT_OF_DATA;
+    }
+
+    for (size_t i = 0; i < oid->len; i++) {
+        /* Prevent overflow in value. */
+        if (value > (UINT_MAX >> 7)) {
+            return MBEDTLS_ERR_ASN1_INVALID_DATA;
+        }
+        if ((value == 0) && ((oid->p[i]) == 0x80)) {
+            /* Overlong encoding is not allowed */
+            return MBEDTLS_ERR_ASN1_INVALID_DATA;
+        }
+
+        value <<= 7;
+        value |= oid->p[i] & 0x7F;
+
+        if (!(oid->p[i] & 0x80)) {
+            /* Last byte */
+            if (n == size) {
+                int component1;
+                unsigned int component2;
+                /* First subidentifier contains first two OID components */
+                if (value >= 80) {
+                    component1 = '2';
+                    component2 = value - 80;
+                } else if (value >= 40) {
+                    component1 = '1';
+                    component2 = value - 40;
+                } else {
+                    component1 = '0';
+                    component2 = value;
+                }
+                ret = mbedtls_snprintf(p, n, "%c.%u", component1, component2);
+            } else {
+                ret = mbedtls_snprintf(p, n, ".%u", value);
+            }
+            if (ret < 2 || (size_t) ret >= n) {
+                return MBEDTLS_ERR_OID_BUF_TOO_SMALL;
+            }
+            n -= (size_t) ret;
+            p += ret;
+            value = 0;
+        }
+    }
+
+    if (value != 0) {
+        /* Unterminated subidentifier */
+        return MBEDTLS_ERR_ASN1_OUT_OF_DATA;
+    }
+
+    return (int) (size - n);
+}
+
 /*
  * Store the name in printable form into buf; no more
  * than size characters will be written
diff --git a/library/x509_create.c b/library/x509_create.c
index 839b5df..1309831 100644
--- a/library/x509_create.c
+++ b/library/x509_create.c
@@ -278,6 +278,182 @@
     return MBEDTLS_ERR_X509_INVALID_NAME;
 }
 
+static int oid_parse_number(unsigned int *num, const char **p, const char *bound)
+{
+    int ret = MBEDTLS_ERR_ASN1_INVALID_DATA;
+
+    *num = 0;
+
+    while (*p < bound && **p >= '0' && **p <= '9') {
+        ret = 0;
+        if (*num > (UINT_MAX / 10)) {
+            return MBEDTLS_ERR_ASN1_INVALID_DATA;
+        }
+        *num *= 10;
+        *num += **p - '0';
+        (*p)++;
+    }
+    return ret;
+}
+
+static size_t oid_subidentifier_num_bytes(unsigned int value)
+{
+    size_t num_bytes = 0;
+
+    do {
+        value >>= 7;
+        num_bytes++;
+    } while (value != 0);
+
+    return num_bytes;
+}
+
+static int oid_subidentifier_encode_into(unsigned char **p,
+                                         unsigned char *bound,
+                                         unsigned int value)
+{
+    size_t num_bytes = oid_subidentifier_num_bytes(value);
+
+    if ((size_t) (bound - *p) < num_bytes) {
+        return MBEDTLS_ERR_OID_BUF_TOO_SMALL;
+    }
+    (*p)[num_bytes - 1] = (unsigned char) (value & 0x7f);
+    value >>= 7;
+
+    for (size_t i = 2; i <= num_bytes; i++) {
+        (*p)[num_bytes - i] = 0x80 | (unsigned char) (value & 0x7f);
+        value >>= 7;
+    }
+    *p += num_bytes;
+
+    return 0;
+}
+
+/* Return the OID for the given x.y.z.... style numeric string  */
+int mbedtls_oid_from_numeric_string(mbedtls_asn1_buf *oid,
+                                    const char *oid_str, size_t size)
+{
+    int ret = MBEDTLS_ERR_ASN1_INVALID_DATA;
+    const char *str_ptr = oid_str;
+    const char *str_bound = oid_str + size;
+    unsigned int val = 0;
+    unsigned int component1, component2;
+    size_t encoded_len;
+    unsigned char *resized_mem;
+
+    /* Count the number of dots to get a worst-case allocation size. */
+    size_t num_dots = 0;
+    for (size_t i = 0; i < size; i++) {
+        if (oid_str[i] == '.') {
+            num_dots++;
+        }
+    }
+    /* Allocate maximum possible required memory:
+     * There are (num_dots + 1) integer components, but the first 2 share the
+     * same subidentifier, so we only need num_dots subidentifiers maximum. */
+    if (num_dots == 0 || (num_dots > MBEDTLS_OID_MAX_COMPONENTS - 1)) {
+        return MBEDTLS_ERR_ASN1_INVALID_DATA;
+    }
+    /* Each byte can store 7 bits, calculate number of bytes for a
+     * subidentifier:
+     *
+     * bytes = ceil(subidentifer_size * 8 / 7)
+     */
+    size_t bytes_per_subidentifier = (((sizeof(unsigned int) * 8) - 1) / 7)
+                                     + 1;
+    size_t max_possible_bytes = num_dots * bytes_per_subidentifier;
+    oid->p = mbedtls_calloc(max_possible_bytes, 1);
+    if (oid->p == NULL) {
+        return MBEDTLS_ERR_ASN1_ALLOC_FAILED;
+    }
+    unsigned char *out_ptr = oid->p;
+    unsigned char *out_bound = oid->p + max_possible_bytes;
+
+    ret = oid_parse_number(&component1, &str_ptr, str_bound);
+    if (ret != 0) {
+        goto error;
+    }
+    if (component1 > 2) {
+        /* First component can't be > 2 */
+        ret = MBEDTLS_ERR_ASN1_INVALID_DATA;
+        goto error;
+    }
+    if (str_ptr >= str_bound || *str_ptr != '.') {
+        ret = MBEDTLS_ERR_ASN1_INVALID_DATA;
+        goto error;
+    }
+    str_ptr++;
+
+    ret = oid_parse_number(&component2, &str_ptr, str_bound);
+    if (ret != 0) {
+        goto error;
+    }
+    if ((component1 < 2) && (component2 > 39)) {
+        /* Root nodes 0 and 1 may have up to 40 children, numbered 0-39 */
+        ret = MBEDTLS_ERR_ASN1_INVALID_DATA;
+        goto error;
+    }
+    if (str_ptr < str_bound) {
+        if (*str_ptr == '.') {
+            str_ptr++;
+        } else {
+            ret = MBEDTLS_ERR_ASN1_INVALID_DATA;
+            goto error;
+        }
+    }
+
+    if (component2 > (UINT_MAX - (component1 * 40))) {
+        ret = MBEDTLS_ERR_ASN1_INVALID_DATA;
+        goto error;
+    }
+    ret = oid_subidentifier_encode_into(&out_ptr, out_bound,
+                                        (component1 * 40) + component2);
+    if (ret != 0) {
+        goto error;
+    }
+
+    while (str_ptr < str_bound) {
+        ret = oid_parse_number(&val, &str_ptr, str_bound);
+        if (ret != 0) {
+            goto error;
+        }
+        if (str_ptr < str_bound) {
+            if (*str_ptr == '.') {
+                str_ptr++;
+            } else {
+                ret = MBEDTLS_ERR_ASN1_INVALID_DATA;
+                goto error;
+            }
+        }
+
+        ret = oid_subidentifier_encode_into(&out_ptr, out_bound, val);
+        if (ret != 0) {
+            goto error;
+        }
+    }
+
+    encoded_len = (size_t) (out_ptr - oid->p);
+    resized_mem = mbedtls_calloc(encoded_len, 1);
+    if (resized_mem == NULL) {
+        ret = MBEDTLS_ERR_ASN1_ALLOC_FAILED;
+        goto error;
+    }
+    memcpy(resized_mem, oid->p, encoded_len);
+    mbedtls_free(oid->p);
+    oid->p = resized_mem;
+    oid->len = encoded_len;
+
+    oid->tag = MBEDTLS_ASN1_OID;
+
+    return 0;
+
+error:
+    mbedtls_free(oid->p);
+    oid->p = NULL;
+    oid->len = 0;
+    return ret;
+}
+
 int mbedtls_x509_string_to_names(mbedtls_asn1_named_data **head, const char *name)
 {
     int ret = MBEDTLS_ERR_X509_INVALID_NAME;
diff --git a/scripts/config.py b/scripts/config.py
index fff4233..580a4bb 100755
--- a/scripts/config.py
+++ b/scripts/config.py
@@ -19,26 +19,33 @@
 from mbedtls_framework import config_common
 
 
-def is_full_section(section):
-    """Is this section affected by "config.py full" and friends?
+def is_boolean_setting(name, value):
+    """Is this a boolean setting?
 
-    In a config file where the sections are not used the whole config file
-    is an empty section (with value None) and the whole file is affected.
+    Mbed TLS boolean settings are enabled if the preprocessor macro is
+    defined, and disabled if the preprocessor macro is not defined. The
+    macro definition line in the configuration file has an empty expansion.
+
+    PSA_WANT_xxx settings are also boolean, but when they are enabled,
+    they expand to a nonzero value. We leave them undefined when they
+    are disabled. (Setting them to 0 currently means to enable them, but
+    this might change to mean disabling them. Currently we just never set
+    them to 0.)
     """
-    return section is None or section.endswith('support') or section.endswith('modules')
+    if name.startswith('PSA_WANT_'):
+        return True
+    if not value:
+        return True
+    return False
 
-def realfull_adapter(_name, active, section):
-    """Activate all symbols found in the global and boolean feature sections.
+def realfull_adapter(_name, _value, _active):
+    """Activate all symbols.
 
     This is intended for building the documentation, including the
     documentation of settings that are activated by defining an optional
-    preprocessor macro.
-
-    Do not activate definitions in the section containing symbols that are
-    supposed to be defined and documented in their own module.
+    preprocessor macro. There is no expectation that the resulting
+    configuration can be built.
     """
-    if section == 'Module configuration options':
-        return active
     return True
 
 PSA_UNSUPPORTED_FEATURE = frozenset([
@@ -138,9 +145,9 @@
         return is_seamless_alt(name)
     return True
 
-def full_adapter(name, active, section):
+def full_adapter(name, value, active):
     """Config adapter for "full"."""
-    if not is_full_section(section):
+    if not is_boolean_setting(name, value):
         return active
     return include_in_full(name)
 
@@ -176,9 +183,9 @@
         return False
     return True
 
-def baremetal_adapter(name, active, section):
+def baremetal_adapter(name, value, active):
     """Config adapter for "baremetal"."""
-    if not is_full_section(section):
+    if not is_boolean_setting(name, value):
         return active
     if name == 'MBEDTLS_NO_PLATFORM_ENTROPY':
         # No OS-provided entropy source
@@ -195,10 +202,10 @@
     'MBEDTLS_TEST_HOOKS', # only useful with the hosted test framework, increases code size
 ])
 
-def baremetal_size_adapter(name, active, section):
+def baremetal_size_adapter(name, value, active):
     if name in EXCLUDE_FOR_SIZE:
         return False
-    return baremetal_adapter(name, active, section)
+    return baremetal_adapter(name, value, active)
 
 def include_in_crypto(name):
     """Rules for symbols in a crypto configuration."""
@@ -219,15 +226,15 @@
 def crypto_adapter(adapter):
     """Modify an adapter to disable non-crypto symbols.
 
-    ``crypto_adapter(adapter)(name, active, section)`` is like
-    ``adapter(name, active, section)``, but unsets all X.509 and TLS symbols.
+    ``crypto_adapter(adapter)(name, value, active)`` is like
+    ``adapter(name, value, active)``, but unsets all X.509 and TLS symbols.
     """
-    def continuation(name, active, section):
+    def continuation(name, value, active):
         if not include_in_crypto(name):
             return False
         if adapter is None:
             return active
-        return adapter(name, active, section)
+        return adapter(name, value, active)
     return continuation
 
 DEPRECATED = frozenset([
@@ -237,34 +244,34 @@
 def no_deprecated_adapter(adapter):
     """Modify an adapter to disable deprecated symbols.
 
-    ``no_deprecated_adapter(adapter)(name, active, section)`` is like
-    ``adapter(name, active, section)``, but unsets all deprecated symbols
+    ``no_deprecated_adapter(adapter)(name, value, active)`` is like
+    ``adapter(name, value, active)``, but unsets all deprecated symbols
     and sets ``MBEDTLS_DEPRECATED_REMOVED``.
     """
-    def continuation(name, active, section):
+    def continuation(name, value, active):
         if name == 'MBEDTLS_DEPRECATED_REMOVED':
             return True
         if name in DEPRECATED:
             return False
         if adapter is None:
             return active
-        return adapter(name, active, section)
+        return adapter(name, value, active)
     return continuation
 
 def no_platform_adapter(adapter):
     """Modify an adapter to disable platform symbols.
 
-    ``no_platform_adapter(adapter)(name, active, section)`` is like
-    ``adapter(name, active, section)``, but unsets all platform symbols other
+    ``no_platform_adapter(adapter)(name, value, active)`` is like
+    ``adapter(name, value, active)``, but unsets all platform symbols other
     ``than MBEDTLS_PLATFORM_C.
     """
-    def continuation(name, active, section):
+    def continuation(name, value, active):
         # Allow MBEDTLS_PLATFORM_C but remove all other platform symbols.
         if name.startswith('MBEDTLS_PLATFORM_') and name != 'MBEDTLS_PLATFORM_C':
             return False
         if adapter is None:
             return active
-        return adapter(name, active, section)
+        return adapter(name, value, active)
     return continuation
 
 
diff --git a/tests/suites/test_suite_x509parse.data b/tests/suites/test_suite_x509parse.data
index 510b0a3..143d676 100644
--- a/tests/suites/test_suite_x509parse.data
+++ b/tests/suites/test_suite_x509parse.data
@@ -3439,3 +3439,52 @@
 X509 CRT parse Authority Key Id - Wrong Issuer sequence
 depends_on:PSA_WANT_ALG_MD5:MBEDTLS_RSA_C
 x509_crt_parse_authoritykeyid:"../framework/data_files/clusterfuzz-testcase-minimized-fuzz_x509crt-6666050834661376.crt.der":"":"":"":MBEDTLS_ERR_X509_INVALID_EXTENSIONS+MBEDTLS_ERR_ASN1_OUT_OF_DATA
+
+OID get numeric string - hardware module name
+oid_get_numeric_string:"2B06010505070804":0:"1.3.6.1.5.5.7.8.4"
+
+OID get numeric string - multi-byte subidentifier
+oid_get_numeric_string:"29903C":0:"1.1.2108"
+
+OID get numeric string - second component greater than 39
+oid_get_numeric_string:"81010000863A00":0:"2.49.0.0.826.0"
+
+OID get numeric string - multi-byte first subidentifier
+oid_get_numeric_string:"8837":0:"2.999"
+
+OID get numeric string - second subidentifier not terminated
+oid_get_numeric_string:"0081":MBEDTLS_ERR_ASN1_OUT_OF_DATA:""
+
+OID get numeric string - empty oid buffer
+oid_get_numeric_string:"":MBEDTLS_ERR_ASN1_OUT_OF_DATA:""
+
+OID get numeric string - no final / all bytes have top bit set
+oid_get_numeric_string:"818181":MBEDTLS_ERR_ASN1_OUT_OF_DATA:""
+
+OID get numeric string - 0.39
+oid_get_numeric_string:"27":0:"0.39"
+
+OID get numeric string - 1.0
+oid_get_numeric_string:"28":0:"1.0"
+
+OID get numeric string - 1.39
+oid_get_numeric_string:"4f":0:"1.39"
+
+OID get numeric string - 2.0
+oid_get_numeric_string:"50":0:"2.0"
+
+OID get numeric string - 1 byte first subidentifier beyond 2.39
+oid_get_numeric_string:"7f":0:"2.47"
+
+# Encodes the number 0x0400000000 as a subidentifier which overflows 32-bits
+OID get numeric string - 32-bit overflow
+oid_get_numeric_string:"C080808000":MBEDTLS_ERR_ASN1_INVALID_DATA:""
+
+OID get numeric string - 32-bit overflow, second subidentifier
+oid_get_numeric_string:"2BC080808000":MBEDTLS_ERR_ASN1_INVALID_DATA:""
+
+OID get numeric string - overlong encoding
+oid_get_numeric_string:"8001":MBEDTLS_ERR_ASN1_INVALID_DATA:""
+
+OID get numeric string - overlong encoding, second subidentifier
+oid_get_numeric_string:"2B8001":MBEDTLS_ERR_ASN1_INVALID_DATA:""
diff --git a/tests/suites/test_suite_x509parse.function b/tests/suites/test_suite_x509parse.function
index 9fc0e55..fae3657 100644
--- a/tests/suites/test_suite_x509parse.function
+++ b/tests/suites/test_suite_x509parse.function
@@ -10,6 +10,8 @@
 #include "mbedtls/base64.h"
 #include "mbedtls/error.h"
 #include "mbedtls/pk.h"
+#include "mbedtls/asn1.h"
+#include "mbedtls/asn1write.h"
 #include "string.h"
 
 #if MBEDTLS_X509_MAX_INTERMEDIATE_CA > 19
@@ -1747,3 +1749,27 @@
     mbedtls_x509_crt_free(&crt);
 }
 /* END_CASE */
+
+/* BEGIN_CASE depends_on:MBEDTLS_X509_USE_C */
+void oid_get_numeric_string(data_t *oid, int error_ret, char *result_str)
+{
+    char buf[256];
+    mbedtls_asn1_buf input_oid = { 0, 0, NULL };
+    int ret;
+
+    input_oid.tag = MBEDTLS_ASN1_OID;
+    /* Test that an empty OID is not dereferenced */
+    input_oid.p = oid->len ? oid->x : (void *) 1;
+    input_oid.len = oid->len;
+
+    ret = mbedtls_oid_get_numeric_string(buf, sizeof(buf), &input_oid);
+
+    if (error_ret == 0) {
+        TEST_EQUAL(ret, strlen(result_str));
+        TEST_ASSERT(ret >= 3);
+        TEST_EQUAL(strcmp(buf, result_str), 0);
+    } else {
+        TEST_EQUAL(ret, error_ret);
+    }
+}
+/* END_CASE */
diff --git a/tests/suites/test_suite_x509write.data b/tests/suites/test_suite_x509write.data
index 3fbb721..e4e08da 100644
--- a/tests/suites/test_suite_x509write.data
+++ b/tests/suites/test_suite_x509write.data
@@ -268,3 +268,52 @@
 
 Check max extension length
 x509_set_extension_length_check:
+
+OID from numeric string - hardware module name
+oid_from_numeric_string:"1.3.6.1.5.5.7.8.4":0:"2B06010505070804"
+
+OID from numeric string - multi-byte subidentifier
+oid_from_numeric_string:"1.1.2108":0:"29903C"
+
+OID from numeric string - second component greater than 39
+oid_from_numeric_string:"2.49.0.0.826.0":0:"81010000863A00"
+
+OID from numeric string - multi-byte first subidentifier
+oid_from_numeric_string:"2.999":0:"8837"
+
+OID from numeric string - empty string input
+oid_from_numeric_string:"":MBEDTLS_ERR_ASN1_INVALID_DATA:""
+
+OID from numeric string - first component not a number
+oid_from_numeric_string:"abc.1.2":MBEDTLS_ERR_ASN1_INVALID_DATA:""
+
+OID from numeric string - second component not a number
+oid_from_numeric_string:"1.abc.2":MBEDTLS_ERR_ASN1_INVALID_DATA:""
+
+OID from numeric string - first component too large
+oid_from_numeric_string:"3.1":MBEDTLS_ERR_ASN1_INVALID_DATA:""
+
+OID from numeric string - first component < 2, second > 39
+oid_from_numeric_string:"1.40":MBEDTLS_ERR_ASN1_INVALID_DATA:""
+
+OID from numeric string - third component not a number
+oid_from_numeric_string:"1.2.abc":MBEDTLS_ERR_ASN1_INVALID_DATA:""
+
+OID from numeric string - non-'.' separator between first and second
+oid_from_numeric_string:"1/2.3.4":MBEDTLS_ERR_ASN1_INVALID_DATA:""
+
+OID from numeric string - non-'.' separator between second and third
+oid_from_numeric_string:"1.2/3.4":MBEDTLS_ERR_ASN1_INVALID_DATA:""
+
+OID from numeric string - non-'.' separator between third and fourth
+oid_from_numeric_string:"1.2.3/4":MBEDTLS_ERR_ASN1_INVALID_DATA:""
+
+OID from numeric string - OID greater than max length (129 components)
+oid_from_numeric_string:"1.2.3.4.5.6.7.8.1.2.3.4.5.6.7.8.1.2.3.4.5.6.7.8.1.2.3.4.5.6.7.8.1.2.3.4.5.6.7.8.1.2.3.4.5.6.7.8.1.2.3.4.5.6.7.8.1.2.3.4.5.6.7.8.1.2.3.4.5.6.7.8.1.2.3.4.5.6.7.8.1.2.3.4.5.6.7.8.1.2.3.4.5.6.7.8.1.2.3.4.5.6.7.8.1.2.3.4.5.6.7.8.1.2.3.4.5.6.7.8.1.2.3.4.5.6.7.8.1":MBEDTLS_ERR_ASN1_INVALID_DATA:""
+
+OID from numeric string - OID with maximum subidentifier
+oid_from_numeric_string:"2.4294967215":0:"8FFFFFFF7F"
+
+OID from numeric string - OID with overflowing subidentifier
+oid_from_numeric_string:"2.4294967216":MBEDTLS_ERR_ASN1_INVALID_DATA:""
+
diff --git a/tests/suites/test_suite_x509write.function b/tests/suites/test_suite_x509write.function
index eb3c2f7..64b4e9e 100644
--- a/tests/suites/test_suite_x509write.function
+++ b/tests/suites/test_suite_x509write.function
@@ -6,6 +6,7 @@
 #include "mbedtls/pem.h"
 #include "mbedtls/oid.h"
 #include "mbedtls/rsa.h"
+#include "mbedtls/asn1.h"
 #include "mbedtls/asn1write.h"
 #include "mbedtls/pk.h"
 #include "mbedtls/psa_util.h"
@@ -761,3 +762,29 @@
     TEST_ASSERT(MBEDTLS_ERR_X509_BAD_INPUT_DATA == ret);
 }
 /* END_CASE */
+
+/* BEGIN_CASE depends_on:MBEDTLS_X509_USE_C */
+void oid_from_numeric_string(char *oid_str, int error_ret,
+                             data_t *exp_oid_buf)
+{
+    mbedtls_asn1_buf oid = { 0, 0, NULL };
+    mbedtls_asn1_buf exp_oid = { 0, 0, NULL };
+    int ret;
+
+    exp_oid.tag = MBEDTLS_ASN1_OID;
+    exp_oid.p = exp_oid_buf->x;
+    exp_oid.len = exp_oid_buf->len;
+
+    ret = mbedtls_oid_from_numeric_string(&oid, oid_str, strlen(oid_str));
+
+    if (error_ret == 0) {
+        TEST_EQUAL(oid.len, exp_oid.len);
+        TEST_ASSERT(memcmp(oid.p, exp_oid.p, oid.len) == 0);
+        mbedtls_free(oid.p);
+        oid.p = NULL;
+        oid.len = 0;
+    } else {
+        TEST_EQUAL(ret, error_ret);
+    }
+}
+/* END_CASE */
diff --git a/tf-psa-crypto/drivers/builtin/include/mbedtls/oid.h b/tf-psa-crypto/drivers/builtin/include/mbedtls/oid.h
index 0366944..e0ad35e 100644
--- a/tf-psa-crypto/drivers/builtin/include/mbedtls/oid.h
+++ b/tf-psa-crypto/drivers/builtin/include/mbedtls/oid.h
@@ -483,38 +483,6 @@
 } mbedtls_oid_descriptor_t;
 
 /**
- * \brief           Translate an ASN.1 OID into its numeric representation
- *                  (e.g. "\x2A\x86\x48\x86\xF7\x0D" into "1.2.840.113549")
- *
- * \param buf       buffer to put representation in
- * \param size      size of the buffer
- * \param oid       OID to translate
- *
- * \return          Length of the string written (excluding final NULL) or
- *                  MBEDTLS_ERR_OID_BUF_TOO_SMALL in case of error
- */
-int mbedtls_oid_get_numeric_string(char *buf, size_t size, const mbedtls_asn1_buf *oid);
-
-/**
- * \brief           Translate a string containing a dotted-decimal
- *                  representation of an ASN.1 OID into its encoded form
- *                  (e.g. "1.2.840.113549" into "\x2A\x86\x48\x86\xF7\x0D").
- *                  On success, this function allocates oid->buf from the
- *                  heap. It must be freed by the caller using mbedtls_free().
- *
- * \param oid       #mbedtls_asn1_buf to populate with the DER-encoded OID
- * \param oid_str   string representation of the OID to parse
- * \param size      length of the OID string, not including any null terminator
- *
- * \return          0 if successful
- * \return          #MBEDTLS_ERR_ASN1_INVALID_DATA if \p oid_str does not
- *                  represent a valid OID
- * \return          #MBEDTLS_ERR_ASN1_ALLOC_FAILED if the function fails to
- *                  allocate oid->buf
- */
-int mbedtls_oid_from_numeric_string(mbedtls_asn1_buf *oid, const char *oid_str, size_t size);
-
-/**
  * \brief          Translate an X.509 extension OID into local values
  *
  * \param oid      OID to use
diff --git a/tf-psa-crypto/drivers/builtin/src/oid.c b/tf-psa-crypto/drivers/builtin/src/oid.c
index 862f09d..ae30dfe 100644
--- a/tf-psa-crypto/drivers/builtin/src/oid.c
+++ b/tf-psa-crypto/drivers/builtin/src/oid.c
@@ -918,249 +918,4 @@
                  cipher_alg)
 #endif /* MBEDTLS_PKCS12_C && MBEDTLS_CIPHER_C */
 
-/* Return the x.y.z.... style numeric string for the given OID */
-int mbedtls_oid_get_numeric_string(char *buf, size_t size,
-                                   const mbedtls_asn1_buf *oid)
-{
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    char *p = buf;
-    size_t n = size;
-    unsigned int value = 0;
-
-    if (size > INT_MAX) {
-        /* Avoid overflow computing return value */
-        return MBEDTLS_ERR_ASN1_INVALID_LENGTH;
-    }
-
-    if (oid->len <= 0) {
-        /* OID must not be empty */
-        return MBEDTLS_ERR_ASN1_OUT_OF_DATA;
-    }
-
-    for (size_t i = 0; i < oid->len; i++) {
-        /* Prevent overflow in value. */
-        if (value > (UINT_MAX >> 7)) {
-            return MBEDTLS_ERR_ASN1_INVALID_DATA;
-        }
-        if ((value == 0) && ((oid->p[i]) == 0x80)) {
-            /* Overlong encoding is not allowed */
-            return MBEDTLS_ERR_ASN1_INVALID_DATA;
-        }
-
-        value <<= 7;
-        value |= oid->p[i] & 0x7F;
-
-        if (!(oid->p[i] & 0x80)) {
-            /* Last byte */
-            if (n == size) {
-                int component1;
-                unsigned int component2;
-                /* First subidentifier contains first two OID components */
-                if (value >= 80) {
-                    component1 = '2';
-                    component2 = value - 80;
-                } else if (value >= 40) {
-                    component1 = '1';
-                    component2 = value - 40;
-                } else {
-                    component1 = '0';
-                    component2 = value;
-                }
-                ret = mbedtls_snprintf(p, n, "%c.%u", component1, component2);
-            } else {
-                ret = mbedtls_snprintf(p, n, ".%u", value);
-            }
-            if (ret < 2 || (size_t) ret >= n) {
-                return MBEDTLS_ERR_OID_BUF_TOO_SMALL;
-            }
-            n -= (size_t) ret;
-            p += ret;
-            value = 0;
-        }
-    }
-
-    if (value != 0) {
-        /* Unterminated subidentifier */
-        return MBEDTLS_ERR_ASN1_OUT_OF_DATA;
-    }
-
-    return (int) (size - n);
-}
-
-static int oid_parse_number(unsigned int *num, const char **p, const char *bound)
-{
-    int ret = MBEDTLS_ERR_ASN1_INVALID_DATA;
-
-    *num = 0;
-
-    while (*p < bound && **p >= '0' && **p <= '9') {
-        ret = 0;
-        if (*num > (UINT_MAX / 10)) {
-            return MBEDTLS_ERR_ASN1_INVALID_DATA;
-        }
-        *num *= 10;
-        *num += **p - '0';
-        (*p)++;
-    }
-    return ret;
-}
-
-static size_t oid_subidentifier_num_bytes(unsigned int value)
-{
-    size_t num_bytes = 0;
-
-    do {
-        value >>= 7;
-        num_bytes++;
-    } while (value != 0);
-
-    return num_bytes;
-}
-
-static int oid_subidentifier_encode_into(unsigned char **p,
-                                         unsigned char *bound,
-                                         unsigned int value)
-{
-    size_t num_bytes = oid_subidentifier_num_bytes(value);
-
-    if ((size_t) (bound - *p) < num_bytes) {
-        return MBEDTLS_ERR_OID_BUF_TOO_SMALL;
-    }
-    (*p)[num_bytes - 1] = (unsigned char) (value & 0x7f);
-    value >>= 7;
-
-    for (size_t i = 2; i <= num_bytes; i++) {
-        (*p)[num_bytes - i] = 0x80 | (unsigned char) (value & 0x7f);
-        value >>= 7;
-    }
-    *p += num_bytes;
-
-    return 0;
-}
-
-/* Return the OID for the given x.y.z.... style numeric string  */
-int mbedtls_oid_from_numeric_string(mbedtls_asn1_buf *oid,
-                                    const char *oid_str, size_t size)
-{
-    int ret = MBEDTLS_ERR_ASN1_INVALID_DATA;
-    const char *str_ptr = oid_str;
-    const char *str_bound = oid_str + size;
-    unsigned int val = 0;
-    unsigned int component1, component2;
-    size_t encoded_len;
-    unsigned char *resized_mem;
-
-    /* Count the number of dots to get a worst-case allocation size. */
-    size_t num_dots = 0;
-    for (size_t i = 0; i < size; i++) {
-        if (oid_str[i] == '.') {
-            num_dots++;
-        }
-    }
-    /* Allocate maximum possible required memory:
-     * There are (num_dots + 1) integer components, but the first 2 share the
-     * same subidentifier, so we only need num_dots subidentifiers maximum. */
-    if (num_dots == 0 || (num_dots > MBEDTLS_OID_MAX_COMPONENTS - 1)) {
-        return MBEDTLS_ERR_ASN1_INVALID_DATA;
-    }
-    /* Each byte can store 7 bits, calculate number of bytes for a
-     * subidentifier:
-     *
-     * bytes = ceil(subidentifer_size * 8 / 7)
-     */
-    size_t bytes_per_subidentifier = (((sizeof(unsigned int) * 8) - 1) / 7)
-                                     + 1;
-    size_t max_possible_bytes = num_dots * bytes_per_subidentifier;
-    oid->p = mbedtls_calloc(max_possible_bytes, 1);
-    if (oid->p == NULL) {
-        return MBEDTLS_ERR_ASN1_ALLOC_FAILED;
-    }
-    unsigned char *out_ptr = oid->p;
-    unsigned char *out_bound = oid->p + max_possible_bytes;
-
-    ret = oid_parse_number(&component1, &str_ptr, str_bound);
-    if (ret != 0) {
-        goto error;
-    }
-    if (component1 > 2) {
-        /* First component can't be > 2 */
-        ret = MBEDTLS_ERR_ASN1_INVALID_DATA;
-        goto error;
-    }
-    if (str_ptr >= str_bound || *str_ptr != '.') {
-        ret = MBEDTLS_ERR_ASN1_INVALID_DATA;
-        goto error;
-    }
-    str_ptr++;
-
-    ret = oid_parse_number(&component2, &str_ptr, str_bound);
-    if (ret != 0) {
-        goto error;
-    }
-    if ((component1 < 2) && (component2 > 39)) {
-        /* Root nodes 0 and 1 may have up to 40 children, numbered 0-39 */
-        ret = MBEDTLS_ERR_ASN1_INVALID_DATA;
-        goto error;
-    }
-    if (str_ptr < str_bound) {
-        if (*str_ptr == '.') {
-            str_ptr++;
-        } else {
-            ret = MBEDTLS_ERR_ASN1_INVALID_DATA;
-            goto error;
-        }
-    }
-
-    if (component2 > (UINT_MAX - (component1 * 40))) {
-        ret = MBEDTLS_ERR_ASN1_INVALID_DATA;
-        goto error;
-    }
-    ret = oid_subidentifier_encode_into(&out_ptr, out_bound,
-                                        (component1 * 40) + component2);
-    if (ret != 0) {
-        goto error;
-    }
-
-    while (str_ptr < str_bound) {
-        ret = oid_parse_number(&val, &str_ptr, str_bound);
-        if (ret != 0) {
-            goto error;
-        }
-        if (str_ptr < str_bound) {
-            if (*str_ptr == '.') {
-                str_ptr++;
-            } else {
-                ret = MBEDTLS_ERR_ASN1_INVALID_DATA;
-                goto error;
-            }
-        }
-
-        ret = oid_subidentifier_encode_into(&out_ptr, out_bound, val);
-        if (ret != 0) {
-            goto error;
-        }
-    }
-
-    encoded_len = (size_t) (out_ptr - oid->p);
-    resized_mem = mbedtls_calloc(encoded_len, 1);
-    if (resized_mem == NULL) {
-        ret = MBEDTLS_ERR_ASN1_ALLOC_FAILED;
-        goto error;
-    }
-    memcpy(resized_mem, oid->p, encoded_len);
-    mbedtls_free(oid->p);
-    oid->p = resized_mem;
-    oid->len = encoded_len;
-
-    oid->tag = MBEDTLS_ASN1_OID;
-
-    return 0;
-
-error:
-    mbedtls_free(oid->p);
-    oid->p = NULL;
-    oid->len = 0;
-    return ret;
-}
-
 #endif /* MBEDTLS_OID_C */
diff --git a/tf-psa-crypto/tests/suites/test_suite_oid.data b/tf-psa-crypto/tests/suites/test_suite_oid.data
index 8919d42..42b0505 100644
--- a/tf-psa-crypto/tests/suites/test_suite_oid.data
+++ b/tf-psa-crypto/tests/suites/test_suite_oid.data
@@ -105,103 +105,6 @@
 OID hash id - invalid oid
 oid_get_md_alg_id:"2B864886f70d0204":-1
 
-OID get numeric string - hardware module name
-oid_get_numeric_string:"2B06010505070804":0:"1.3.6.1.5.5.7.8.4"
-
-OID get numeric string - multi-byte subidentifier
-oid_get_numeric_string:"29903C":0:"1.1.2108"
-
-OID get numeric string - second component greater than 39
-oid_get_numeric_string:"81010000863A00":0:"2.49.0.0.826.0"
-
-OID get numeric string - multi-byte first subidentifier
-oid_get_numeric_string:"8837":0:"2.999"
-
-OID get numeric string - second subidentifier not terminated
-oid_get_numeric_string:"0081":MBEDTLS_ERR_ASN1_OUT_OF_DATA:""
-
-OID get numeric string - empty oid buffer
-oid_get_numeric_string:"":MBEDTLS_ERR_ASN1_OUT_OF_DATA:""
-
-OID get numeric string - no final / all bytes have top bit set
-oid_get_numeric_string:"818181":MBEDTLS_ERR_ASN1_OUT_OF_DATA:""
-
-OID get numeric string - 0.39
-oid_get_numeric_string:"27":0:"0.39"
-
-OID get numeric string - 1.0
-oid_get_numeric_string:"28":0:"1.0"
-
-OID get numeric string - 1.39
-oid_get_numeric_string:"4f":0:"1.39"
-
-OID get numeric string - 2.0
-oid_get_numeric_string:"50":0:"2.0"
-
-OID get numeric string - 1 byte first subidentifier beyond 2.39
-oid_get_numeric_string:"7f":0:"2.47"
-
-# Encodes the number 0x0400000000 as a subidentifier which overflows 32-bits
-OID get numeric string - 32-bit overflow
-oid_get_numeric_string:"C080808000":MBEDTLS_ERR_ASN1_INVALID_DATA:""
-
-OID get numeric string - 32-bit overflow, second subidentifier
-oid_get_numeric_string:"2BC080808000":MBEDTLS_ERR_ASN1_INVALID_DATA:""
-
-OID get numeric string - overlong encoding
-oid_get_numeric_string:"8001":MBEDTLS_ERR_ASN1_INVALID_DATA:""
-
-OID get numeric string - overlong encoding, second subidentifier
-oid_get_numeric_string:"2B8001":MBEDTLS_ERR_ASN1_INVALID_DATA:""
-
-OID from numeric string - hardware module name
-oid_from_numeric_string:"1.3.6.1.5.5.7.8.4":0:"2B06010505070804"
-
-OID from numeric string - multi-byte subidentifier
-oid_from_numeric_string:"1.1.2108":0:"29903C"
-
-OID from numeric string - second component greater than 39
-oid_from_numeric_string:"2.49.0.0.826.0":0:"81010000863A00"
-
-OID from numeric string - multi-byte first subidentifier
-oid_from_numeric_string:"2.999":0:"8837"
-
-OID from numeric string - empty string input
-oid_from_numeric_string:"":MBEDTLS_ERR_ASN1_INVALID_DATA:""
-
-OID from numeric string - first component not a number
-oid_from_numeric_string:"abc.1.2":MBEDTLS_ERR_ASN1_INVALID_DATA:""
-
-OID from numeric string - second component not a number
-oid_from_numeric_string:"1.abc.2":MBEDTLS_ERR_ASN1_INVALID_DATA:""
-
-OID from numeric string - first component too large
-oid_from_numeric_string:"3.1":MBEDTLS_ERR_ASN1_INVALID_DATA:""
-
-OID from numeric string - first component < 2, second > 39
-oid_from_numeric_string:"1.40":MBEDTLS_ERR_ASN1_INVALID_DATA:""
-
-OID from numeric string - third component not a number
-oid_from_numeric_string:"1.2.abc":MBEDTLS_ERR_ASN1_INVALID_DATA:""
-
-OID from numeric string - non-'.' separator between first and second
-oid_from_numeric_string:"1/2.3.4":MBEDTLS_ERR_ASN1_INVALID_DATA:""
-
-OID from numeric string - non-'.' separator between second and third
-oid_from_numeric_string:"1.2/3.4":MBEDTLS_ERR_ASN1_INVALID_DATA:""
-
-OID from numeric string - non-'.' separator between third and fourth
-oid_from_numeric_string:"1.2.3/4":MBEDTLS_ERR_ASN1_INVALID_DATA:""
-
-OID from numeric string - OID greater than max length (129 components)
-oid_from_numeric_string:"1.2.3.4.5.6.7.8.1.2.3.4.5.6.7.8.1.2.3.4.5.6.7.8.1.2.3.4.5.6.7.8.1.2.3.4.5.6.7.8.1.2.3.4.5.6.7.8.1.2.3.4.5.6.7.8.1.2.3.4.5.6.7.8.1.2.3.4.5.6.7.8.1.2.3.4.5.6.7.8.1.2.3.4.5.6.7.8.1.2.3.4.5.6.7.8.1.2.3.4.5.6.7.8.1.2.3.4.5.6.7.8.1.2.3.4.5.6.7.8.1.2.3.4.5.6.7.8.1":MBEDTLS_ERR_ASN1_INVALID_DATA:""
-
-OID from numeric string - OID with maximum subidentifier
-oid_from_numeric_string:"2.4294967215":0:"8FFFFFFF7F"
-
-OID from numeric string - OID with overflowing subidentifier
-oid_from_numeric_string:"2.4294967216":MBEDTLS_ERR_ASN1_INVALID_DATA:""
-
 mbedtls_oid_get_md_hmac - RIPEMD160
 depends_on:PSA_WANT_ALG_RIPEMD160
 mbedtls_oid_get_md_hmac:"2B06010505080104":MBEDTLS_MD_RIPEMD160
diff --git a/tf-psa-crypto/tests/suites/test_suite_oid.function b/tf-psa-crypto/tests/suites/test_suite_oid.function
index 337f843..e96425e 100644
--- a/tf-psa-crypto/tests/suites/test_suite_oid.function
+++ b/tf-psa-crypto/tests/suites/test_suite_oid.function
@@ -118,53 +118,3 @@
     }
 }
 /* END_CASE */
-
-/* BEGIN_CASE */
-void oid_get_numeric_string(data_t *oid, int error_ret, char *result_str)
-{
-    char buf[256];
-    mbedtls_asn1_buf input_oid = { 0, 0, NULL };
-    int ret;
-
-    input_oid.tag = MBEDTLS_ASN1_OID;
-    /* Test that an empty OID is not dereferenced */
-    input_oid.p = oid->len ? oid->x : (void *) 1;
-    input_oid.len = oid->len;
-
-    ret = mbedtls_oid_get_numeric_string(buf, sizeof(buf), &input_oid);
-
-    if (error_ret == 0) {
-        TEST_EQUAL(ret, strlen(result_str));
-        TEST_ASSERT(ret >= 3);
-        TEST_EQUAL(strcmp(buf, result_str), 0);
-    } else {
-        TEST_EQUAL(ret, error_ret);
-    }
-}
-/* END_CASE */
-
-/* BEGIN_CASE */
-void oid_from_numeric_string(char *oid_str, int error_ret,
-                             data_t *exp_oid_buf)
-{
-    mbedtls_asn1_buf oid = { 0, 0, NULL };
-    mbedtls_asn1_buf exp_oid = { 0, 0, NULL };
-    int ret;
-
-    exp_oid.tag = MBEDTLS_ASN1_OID;
-    exp_oid.p = exp_oid_buf->x;
-    exp_oid.len = exp_oid_buf->len;
-
-    ret = mbedtls_oid_from_numeric_string(&oid, oid_str, strlen(oid_str));
-
-    if (error_ret == 0) {
-        TEST_EQUAL(oid.len, exp_oid.len);
-        TEST_ASSERT(memcmp(oid.p, exp_oid.p, oid.len) == 0);
-        mbedtls_free(oid.p);
-        oid.p = NULL;
-        oid.len = 0;
-    } else {
-        TEST_EQUAL(ret, error_ret);
-    }
-}
-/* END_CASE */