Merge pull request #6979 from daverodgman/const-time-asm-vol

Inhibit compiler from optimising out const-time asm
diff --git a/ChangeLog.d/improve_x509_cert_writing_serial_number_management.txt b/ChangeLog.d/improve_x509_cert_writing_serial_number_management.txt
new file mode 100644
index 0000000..1764c2f
--- /dev/null
+++ b/ChangeLog.d/improve_x509_cert_writing_serial_number_management.txt
@@ -0,0 +1,19 @@
+Bugfix
+   * mbedtls_x509write_crt_set_serial() now explicitly rejects serial numbers
+     whose binary representation is longer than 20 bytes. This was already
+     forbidden by the standard (RFC5280 - section 4.1.2.2) and now it's being
+     enforced also at code level.
+
+New deprecations
+   * mbedtls_x509write_crt_set_serial() is now being deprecated in favor of
+     mbedtls_x509write_crt_set_serial_raw(). The goal here is to remove any
+     direct dependency of X509 on BIGNUM_C.
+
+Changes
+   * programs/x509/cert_write:
+     - now it accepts the serial number in 2 different formats: decimal and
+       hex. They cannot be used simultaneously
+     - "serial" is used for the decimal format and it's limted in size to
+       unsigned long long int
+     - "serial_hex" is used for the hex format; max length here is
+       MBEDTLS_X509_RFC5280_MAX_SERIAL_LEN*2
diff --git a/include/mbedtls/x509_crt.h b/include/mbedtls/x509_crt.h
index 661f8aa..7c3a625 100644
--- a/include/mbedtls/x509_crt.h
+++ b/include/mbedtls/x509_crt.h
@@ -197,7 +197,7 @@
 #define MBEDTLS_X509_CRT_VERSION_2              1
 #define MBEDTLS_X509_CRT_VERSION_3              2
 
-#define MBEDTLS_X509_RFC5280_MAX_SERIAL_LEN 32
+#define MBEDTLS_X509_RFC5280_MAX_SERIAL_LEN 20
 #define MBEDTLS_X509_RFC5280_UTC_TIME_LEN   15
 
 #if !defined(MBEDTLS_X509_MAX_FILE_PATH_LEN)
@@ -277,7 +277,8 @@
  */
 typedef struct mbedtls_x509write_cert {
     int MBEDTLS_PRIVATE(version);
-    mbedtls_mpi MBEDTLS_PRIVATE(serial);
+    unsigned char MBEDTLS_PRIVATE(serial)[MBEDTLS_X509_RFC5280_MAX_SERIAL_LEN];
+    size_t MBEDTLS_PRIVATE(serial_len);
     mbedtls_pk_context *MBEDTLS_PRIVATE(subject_key);
     mbedtls_pk_context *MBEDTLS_PRIVATE(issuer_key);
     mbedtls_asn1_named_data *MBEDTLS_PRIVATE(subject);
@@ -986,15 +987,43 @@
  */
 void mbedtls_x509write_crt_set_version(mbedtls_x509write_cert *ctx, int version);
 
+#if defined(MBEDTLS_BIGNUM_C) && !defined(MBEDTLS_DEPRECATED_REMOVED)
 /**
  * \brief           Set the serial number for a Certificate.
  *
+ * \deprecated      This function is deprecated and will be removed in a
+ *                  future version of the library. Please use
+ *                  mbedtls_x509write_crt_set_serial_raw() instead.
+ *
+ * \note            Even though the MBEDTLS_BIGNUM_C guard looks redundant since
+ *                  X509 depends on PK and PK depends on BIGNUM, this emphasizes
+ *                  a direct dependency between X509 and BIGNUM which is going
+ *                  to be deprecated in the future.
+ *
  * \param ctx       CRT context to use
  * \param serial    serial number to set
  *
  * \return          0 if successful
  */
-int mbedtls_x509write_crt_set_serial(mbedtls_x509write_cert *ctx, const mbedtls_mpi *serial);
+int MBEDTLS_DEPRECATED mbedtls_x509write_crt_set_serial(
+    mbedtls_x509write_cert *ctx, const mbedtls_mpi *serial);
+#endif // MBEDTLS_BIGNUM_C && !MBEDTLS_DEPRECATED_REMOVED
+
+/**
+ * \brief           Set the serial number for a Certificate.
+ *
+ * \param ctx          CRT context to use
+ * \param serial       A raw array of bytes containing the serial number in big
+ *                     endian format
+ * \param serial_len   Length of valid bytes (expressed in bytes) in \p serial
+ *                     input buffer
+ *
+ * \return          0 if successful, or
+ *                  MBEDTLS_ERR_X509_BAD_INPUT_DATA if the provided input buffer
+ *                  is too big (longer than MBEDTLS_X509_RFC5280_MAX_SERIAL_LEN)
+ */
+int mbedtls_x509write_crt_set_serial_raw(mbedtls_x509write_cert *ctx,
+                                         unsigned char *serial, size_t serial_len);
 
 /**
  * \brief           Set the validity period for a Certificate
diff --git a/library/bignum_mod_raw.c b/library/bignum_mod_raw.c
index 826dd07..bf0cb25 100644
--- a/library/bignum_mod_raw.c
+++ b/library/bignum_mod_raw.c
@@ -33,6 +33,8 @@
 #include "bignum_mod.h"
 #include "constant_time_internal.h"
 
+#include "bignum_mod_raw_invasive.h"
+
 void mbedtls_mpi_mod_raw_cond_assign(mbedtls_mpi_uint *X,
                                      const mbedtls_mpi_uint *A,
                                      const mbedtls_mpi_mod_modulus *N,
@@ -118,6 +120,19 @@
     (void) mbedtls_mpi_core_add_if(X, N->p, N->limbs, (unsigned) c);
 }
 
+#if defined(MBEDTLS_TEST_HOOKS)
+
+MBEDTLS_STATIC_TESTABLE
+void mbedtls_mpi_mod_raw_fix_quasi_reduction(mbedtls_mpi_uint *X,
+                                             const mbedtls_mpi_mod_modulus *N)
+{
+    mbedtls_mpi_uint c = mbedtls_mpi_core_sub(X, X, N->p, N->limbs);
+
+    (void) mbedtls_mpi_core_add_if(X, N->p, N->limbs, (unsigned) c);
+}
+
+#endif /* MBEDTLS_TEST_HOOKS */
+
 void mbedtls_mpi_mod_raw_mul(mbedtls_mpi_uint *X,
                              const mbedtls_mpi_uint *A,
                              const mbedtls_mpi_uint *B,
diff --git a/library/bignum_mod_raw_invasive.h b/library/bignum_mod_raw_invasive.h
new file mode 100644
index 0000000..ead8394
--- /dev/null
+++ b/library/bignum_mod_raw_invasive.h
@@ -0,0 +1,46 @@
+/**
+ * \file bignum_mod_raw_invasive.h
+ *
+ * \brief Function declarations for invasive functions of Low-level
+ *        modular bignum.
+ */
+/**
+ *  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 MBEDTLS_BIGNUM_MOD_RAW_INVASIVE_H
+#define MBEDTLS_BIGNUM_MOD_RAW_INVASIVE_H
+
+#include "common.h"
+#include "mbedtls/bignum.h"
+#include "bignum_mod.h"
+
+#if defined(MBEDTLS_TEST_HOOKS)
+
+/** Convert the result of a quasi-reduction to its canonical representative.
+ *
+ * \param[in,out] X     The address of the MPI to be converted. Must have the
+ *                      same number of limbs as \p N. The input value must
+ *                      be in range 0 <= X < 2N.
+ * \param[in]     N     The address of the modulus.
+ */
+MBEDTLS_STATIC_TESTABLE
+void mbedtls_mpi_mod_raw_fix_quasi_reduction(mbedtls_mpi_uint *X,
+                                             const mbedtls_mpi_mod_modulus *N);
+
+#endif /* MBEDTLS_TEST_HOOKS */
+
+#endif /* MBEDTLS_BIGNUM_MOD_RAW_INVASIVE_H */
diff --git a/library/x509write_crt.c b/library/x509write_crt.c
index febd0e6..4f23395 100644
--- a/library/x509write_crt.c
+++ b/library/x509write_crt.c
@@ -52,14 +52,11 @@
 {
     memset(ctx, 0, sizeof(mbedtls_x509write_cert));
 
-    mbedtls_mpi_init(&ctx->serial);
     ctx->version = MBEDTLS_X509_CRT_VERSION_3;
 }
 
 void mbedtls_x509write_crt_free(mbedtls_x509write_cert *ctx)
 {
-    mbedtls_mpi_free(&ctx->serial);
-
     mbedtls_asn1_free_named_data_list(&ctx->subject);
     mbedtls_asn1_free_named_data_list(&ctx->issuer);
     mbedtls_asn1_free_named_data_list(&ctx->extensions);
@@ -103,17 +100,42 @@
     return mbedtls_x509_string_to_names(&ctx->issuer, issuer_name);
 }
 
+#if defined(MBEDTLS_BIGNUM_C) && !defined(MBEDTLS_DEPRECATED_REMOVED)
 int mbedtls_x509write_crt_set_serial(mbedtls_x509write_cert *ctx,
                                      const mbedtls_mpi *serial)
 {
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    int ret;
+    size_t tmp_len;
 
-    if ((ret = mbedtls_mpi_copy(&ctx->serial, serial)) != 0) {
+    /* Ensure that the MPI value fits into the buffer */
+    tmp_len = mbedtls_mpi_size(serial);
+    if (tmp_len > MBEDTLS_X509_RFC5280_MAX_SERIAL_LEN) {
+        return MBEDTLS_ERR_X509_BAD_INPUT_DATA;
+    }
+
+    ctx->serial_len = tmp_len;
+
+    ret = mbedtls_mpi_write_binary(serial, ctx->serial, tmp_len);
+    if (ret < 0) {
         return ret;
     }
 
     return 0;
 }
+#endif // MBEDTLS_BIGNUM_C && !MBEDTLS_DEPRECATED_REMOVED
+
+int mbedtls_x509write_crt_set_serial_raw(mbedtls_x509write_cert *ctx,
+                                         unsigned char *serial, size_t serial_len)
+{
+    if (serial_len > MBEDTLS_X509_RFC5280_MAX_SERIAL_LEN) {
+        return MBEDTLS_ERR_X509_BAD_INPUT_DATA;
+    }
+
+    ctx->serial_len = serial_len;
+    memcpy(ctx->serial, serial, serial_len);
+
+    return 0;
+}
 
 int mbedtls_x509write_crt_set_validity(mbedtls_x509write_cert *ctx,
                                        const char *not_before,
@@ -510,9 +532,29 @@
 
     /*
      *  Serial   ::=  INTEGER
+     *
+     * Written data is:
+     * - "ctx->serial_len" bytes for the raw serial buffer
+     *   - if MSb of "serial" is 1, then prepend an extra 0x00 byte
+     * - 1 byte for the length
+     * - 1 byte for the TAG
      */
-    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_mpi(&c, buf,
-                                                     &ctx->serial));
+    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_raw_buffer(&c, buf,
+                                                            ctx->serial, ctx->serial_len));
+    if (*c & 0x80) {
+        if (c - buf < 1) {
+            return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL;
+        }
+        *(--c) = 0x0;
+        len++;
+        MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf,
+                                                         ctx->serial_len + 1));
+    } else {
+        MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf,
+                                                         ctx->serial_len));
+    }
+    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&c, buf,
+                                                     MBEDTLS_ASN1_INTEGER));
 
     /*
      *  Version  ::=  INTEGER  {  v1(0), v2(1), v3(2)  }
diff --git a/programs/x509/cert_write.c b/programs/x509/cert_write.c
index 3e134dd..287dd34 100644
--- a/programs/x509/cert_write.c
+++ b/programs/x509/cert_write.c
@@ -43,10 +43,12 @@
 #include "mbedtls/ctr_drbg.h"
 #include "mbedtls/md.h"
 #include "mbedtls/error.h"
+#include "test/helpers.h"
 
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <errno.h>
 
 #define SET_OID(x, oid) \
     do { x.len = MBEDTLS_OID_SIZE(oid); x.p = (unsigned char *) oid; } while (0)
@@ -75,6 +77,7 @@
 #define DFL_NOT_BEFORE          "20010101000000"
 #define DFL_NOT_AFTER           "20301231235959"
 #define DFL_SERIAL              "1"
+#define DFL_SERIAL_HEX          "1"
 #define DFL_SELFSIGN            0
 #define DFL_IS_CA               0
 #define DFL_MAX_PATHLEN         -1
@@ -110,6 +113,13 @@
     "    issuer_pwd=%%s           default: (empty)\n"       \
     "    output_file=%%s          default: cert.crt\n"      \
     "    serial=%%s               default: 1\n"             \
+    "                            In decimal format; it can be used as\n"     \
+    "                            alternative to serial_hex, but it's\n"      \
+    "                            limited in max length to\n"                 \
+    "                            unsigned long long int\n"                   \
+    "    serial_hex=%%s           default: 1\n"             \
+    "                            In hex format; it can be used as\n"         \
+    "                            alternative to serial\n"                    \
     "    not_before=%%s           default: 20010101000000\n" \
     "    not_after=%%s            default: 20301231235959\n" \
     "    is_ca=%%d                default: 0 (disabled)\n"  \
@@ -159,6 +169,11 @@
     "   format=pem|der           default: pem\n"         \
     "\n"
 
+typedef enum {
+    SERIAL_FRMT_UNSPEC,
+    SERIAL_FRMT_DEC,
+    SERIAL_FRMT_HEX
+} serial_format_t;
 
 /*
  * global options
@@ -175,7 +190,8 @@
     const char *issuer_name;    /* issuer name for certificate          */
     const char *not_before;     /* validity period not before           */
     const char *not_after;      /* validity period not after            */
-    const char *serial;         /* serial number string                 */
+    const char *serial;         /* serial number string (decimal)       */
+    const char *serial_hex;     /* serial number string (hex)           */
     int selfsign;               /* selfsign the certificate             */
     int is_ca;                  /* is a CA certificate                  */
     int max_pathlen;            /* maximum CA path length               */
@@ -235,6 +251,44 @@
     return 0;
 }
 
+int parse_serial_decimal_format(unsigned char *obuf, size_t obufmax,
+                                const char *ibuf, size_t *len)
+{
+    unsigned long long int dec;
+    unsigned int remaining_bytes = sizeof(dec);
+    unsigned char *p = obuf;
+    unsigned char val;
+    char *end_ptr = NULL;
+
+    errno = 0;
+    dec = strtoull(ibuf, &end_ptr, 10);
+
+    if ((errno != 0) || (end_ptr == ibuf)) {
+        return -1;
+    }
+
+    *len = 0;
+
+    while (remaining_bytes > 0) {
+        if (obufmax < (*len + 1)) {
+            return -1;
+        }
+
+        val = (dec >> ((remaining_bytes - 1) * 8)) & 0xFF;
+
+        /* Skip leading zeros */
+        if ((val != 0) || (*len != 0)) {
+            *p = val;
+            (*len)++;
+            p++;
+        }
+
+        remaining_bytes--;
+    }
+
+    return 0;
+}
+
 int main(int argc, char *argv[])
 {
     int ret = 1;
@@ -252,7 +306,9 @@
     mbedtls_x509_csr csr;
 #endif
     mbedtls_x509write_cert crt;
-    mbedtls_mpi serial;
+    serial_format_t serial_frmt = SERIAL_FRMT_UNSPEC;
+    unsigned char serial[MBEDTLS_X509_RFC5280_MAX_SERIAL_LEN];
+    size_t serial_len;
     mbedtls_asn1_sequence *ext_key_usage;
     mbedtls_entropy_context entropy;
     mbedtls_ctr_drbg_context ctr_drbg;
@@ -264,7 +320,6 @@
     mbedtls_x509write_crt_init(&crt);
     mbedtls_pk_init(&loaded_issuer_key);
     mbedtls_pk_init(&loaded_subject_key);
-    mbedtls_mpi_init(&serial);
     mbedtls_ctr_drbg_init(&ctr_drbg);
     mbedtls_entropy_init(&entropy);
 #if defined(MBEDTLS_X509_CSR_PARSE_C)
@@ -272,6 +327,7 @@
 #endif
     mbedtls_x509_crt_init(&issuer_crt);
     memset(buf, 0, sizeof(buf));
+    memset(serial, 0, sizeof(serial));
 
     if (argc == 0) {
 usage:
@@ -291,6 +347,7 @@
     opt.not_before          = DFL_NOT_BEFORE;
     opt.not_after           = DFL_NOT_AFTER;
     opt.serial              = DFL_SERIAL;
+    opt.serial_hex          = DFL_SERIAL_HEX;
     opt.selfsign            = DFL_SELFSIGN;
     opt.is_ca               = DFL_IS_CA;
     opt.max_pathlen         = DFL_MAX_PATHLEN;
@@ -335,7 +392,19 @@
         } else if (strcmp(p, "not_after") == 0) {
             opt.not_after = q;
         } else if (strcmp(p, "serial") == 0) {
+            if (serial_frmt != SERIAL_FRMT_UNSPEC) {
+                mbedtls_printf("Invalid attempt to set the serial more than once\n");
+                goto usage;
+            }
+            serial_frmt = SERIAL_FRMT_DEC;
             opt.serial = q;
+        } else if (strcmp(p, "serial_hex") == 0) {
+            if (serial_frmt != SERIAL_FRMT_UNSPEC) {
+                mbedtls_printf("Invalid attempt to set the serial more than once\n");
+                goto usage;
+            }
+            serial_frmt = SERIAL_FRMT_HEX;
+            opt.serial_hex = q;
         } else if (strcmp(p, "authority_identifier") == 0) {
             opt.authority_identifier = atoi(q);
             if (opt.authority_identifier != 0 &&
@@ -514,10 +583,16 @@
     mbedtls_printf("  . Reading serial number...");
     fflush(stdout);
 
-    if ((ret = mbedtls_mpi_read_string(&serial, 10, opt.serial)) != 0) {
-        mbedtls_strerror(ret, buf, sizeof(buf));
-        mbedtls_printf(" failed\n  !  mbedtls_mpi_read_string "
-                       "returned -0x%04x - %s\n\n", (unsigned int) -ret, buf);
+    if (serial_frmt == SERIAL_FRMT_HEX) {
+        ret = mbedtls_test_unhexify(serial, sizeof(serial),
+                                    opt.serial_hex, &serial_len);
+    } else { // SERIAL_FRMT_DEC || SERIAL_FRMT_UNSPEC
+        ret = parse_serial_decimal_format(serial, sizeof(serial),
+                                          opt.serial, &serial_len);
+    }
+
+    if (ret != 0) {
+        mbedtls_printf(" failed\n  !  Unable to parse serial\n");
         goto exit;
     }
 
@@ -661,10 +736,10 @@
     mbedtls_x509write_crt_set_version(&crt, opt.version);
     mbedtls_x509write_crt_set_md_alg(&crt, opt.md);
 
-    ret = mbedtls_x509write_crt_set_serial(&crt, &serial);
+    ret = mbedtls_x509write_crt_set_serial_raw(&crt, serial, serial_len);
     if (ret != 0) {
         mbedtls_strerror(ret, buf, sizeof(buf));
-        mbedtls_printf(" failed\n  !  mbedtls_x509write_crt_set_serial "
+        mbedtls_printf(" failed\n  !  mbedtls_x509write_crt_set_serial_raw "
                        "returned -0x%04x - %s\n\n", (unsigned int) -ret, buf);
         goto exit;
     }
@@ -807,7 +882,6 @@
     mbedtls_x509write_crt_free(&crt);
     mbedtls_pk_free(&loaded_subject_key);
     mbedtls_pk_free(&loaded_issuer_key);
-    mbedtls_mpi_free(&serial);
     mbedtls_ctr_drbg_free(&ctr_drbg);
     mbedtls_entropy_free(&entropy);
 
diff --git a/scripts/mbedtls_dev/bignum_mod_raw.py b/scripts/mbedtls_dev/bignum_mod_raw.py
index f9d9899..d197b54 100644
--- a/scripts/mbedtls_dev/bignum_mod_raw.py
+++ b/scripts/mbedtls_dev/bignum_mod_raw.py
@@ -51,6 +51,37 @@
         result = (self.int_a - self.int_b) % self.int_n
         return [self.format_result(result)]
 
+class BignumModRawFixQuasiReduction(bignum_common.ModOperationCommon,
+                                    BignumModRawTarget):
+    """Test cases for ecp quasi_reduction()."""
+    symbol = "-"
+    test_function = "mpi_mod_raw_fix_quasi_reduction"
+    test_name = "fix_quasi_reduction"
+    input_style = "fixed"
+    arity = 1
+
+    # Extend the default values with n < x < 2n
+    input_values = bignum_common.ModOperationCommon.input_values + [
+        "73",
+
+        # First number generated by random.getrandbits(1024) - seed(3,2)
+        "ea7b5bf55eb561a4216363698b529b4a97b750923ceb3ffd",
+
+        # First number generated by random.getrandbits(1024) - seed(1,2)
+        ("cd447e35b8b6d8fe442e3d437204e52db2221a58008a05a6c4647159c324c985"
+         "9b810e766ec9d28663ca828dd5f4b3b2e4b06ce60741c7a87ce42c8218072e8c"
+         "35bf992dc9e9c616612e7696a6cecc1b78e510617311d8a3c2ce6f447ed4d57b"
+         "1e2feb89414c343c1027c4d1c386bbc4cd613e30d8f16adf91b7584a2265b1f5")
+    ] # type: List[str]
+
+    def result(self) -> List[str]:
+        result = self.int_a % self.int_n
+        return [self.format_result(result)]
+
+    @property
+    def is_valid(self) -> bool:
+        return bool(self.int_a < 2 * self.int_n)
+
 class BignumModRawMul(bignum_common.ModOperationCommon,
                       BignumModRawTarget):
     """Test cases for bignum mpi_mod_raw_mul()."""
diff --git a/tests/data_files/Makefile b/tests/data_files/Makefile
index 388b0ce..9c7a95d 100644
--- a/tests/data_files/Makefile
+++ b/tests/data_files/Makefile
@@ -972,6 +972,15 @@
 
 server1.crt: server1.key server1.req.sha256 $(test_ca_crt) $(test_ca_key_file_rsa)
 	$(MBEDTLS_CERT_WRITE) request_file=server1.req.sha256 issuer_crt=$(test_ca_crt) issuer_key=$(test_ca_key_file_rsa) issuer_pwd=$(test_ca_pwd_rsa) version=1 not_before=20190210144406 not_after=20290210144406 md=SHA1 version=3 output_file=$@
+server1.long_serial.crt: server1.key server1.req.sha256 $(test_ca_crt) $(test_ca_key_file_rsa)
+	echo "112233445566778899aabbccddeeff0011223344" > test-ca.server1.tmp.serial
+	$(OPENSSL) ca -in server1.req.sha256 -key PolarSSLTest -config test-ca.server1.test_serial.opensslconf -notext -batch -out $@
+server1.80serial.crt: server1.key server1.req.sha256 $(test_ca_crt) $(test_ca_key_file_rsa)
+	echo "8011223344" > test-ca.server1.tmp.serial
+	$(OPENSSL) ca -in server1.req.sha256 -key PolarSSLTest -config test-ca.server1.test_serial.opensslconf -notext -batch -out $@
+server1.long_serial_FF.crt: server1.key server1.req.sha256 $(test_ca_crt) $(test_ca_key_file_rsa)
+	echo "ffffffffffffffffffffffffffffffff" > test-ca.server1.tmp.serial
+	$(OPENSSL) ca -in server1.req.sha256 -key PolarSSLTest -config test-ca.server1.test_serial.opensslconf -notext -batch -out $@
 server1.noauthid.crt: server1.key server1.req.sha256 $(test_ca_crt) $(test_ca_key_file_rsa)
 	$(MBEDTLS_CERT_WRITE) request_file=server1.req.sha256 issuer_crt=$(test_ca_crt) issuer_key=$(test_ca_key_file_rsa) issuer_pwd=$(test_ca_pwd_rsa) not_before=20190210144406 not_after=20290210144406 md=SHA1 authority_identifier=0 version=3 output_file=$@
 server1.crt.der: server1.crt
diff --git a/tests/data_files/server1.80serial.crt b/tests/data_files/server1.80serial.crt
new file mode 100644
index 0000000..3ce8570
--- /dev/null
+++ b/tests/data_files/server1.80serial.crt
@@ -0,0 +1,20 @@
+-----BEGIN CERTIFICATE-----
+MIIDRDCCAiygAwIBAgIGAIARIjNEMA0GCSqGSIb3DQEBBQUAMDsxCzAJBgNVBAYT
+Ak5MMREwDwYDVQQKDAhQb2xhclNTTDEZMBcGA1UEAwwQUG9sYXJTU0wgVGVzdCBD
+QTAeFw0xOTAyMTAxNDQ0MDZaFw0yOTAyMTAxNDQ0MDZaMDwxCzAJBgNVBAYTAk5M
+MREwDwYDVQQKDAhQb2xhclNTTDEaMBgGA1UEAwwRUG9sYXJTU0wgU2VydmVyIDEw
+ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCpAh89QGrVVVOL/TbugmUu
+FWFeib+46EWQ2+6IFlLT8UNQR5YSWWSHa/0r4Eb5c77dz5LhkVvtZqBviSl5RYDQ
+g2rVQUN3Xzl8CQRHgrBXOXDto+wVGR6oMwhHwQVCqf1Mw7Tf3QYfTRBRQGdzEw9A
++G2BJV8KsVPGMH4VOaz5Wu5/kp6mBVvnE5eFtSOS2dQkBtUJJYl1B92mGo8/CRm+
+rWUsZOuVm9z+QV4XptpsW2nMAroULBYknErczdD3Umdz8S2gI/1+9DHKLXDKiQsE
+2y6mT3Buns69WIniU1meblqSZeKIPwyUGaPd5eidlRPtKdurcBLcWsprF6tSglSx
+AgMBAAGjTTBLMAkGA1UdEwQCMAAwHQYDVR0OBBYEFB901j8pwXR0RTsFEiw9qL1D
+WQKmMB8GA1UdIwQYMBaAFLRa5KWz3tJS9rnVppUP6z68x/3/MA0GCSqGSIb3DQEB
+BQUAA4IBAQBJKeTUCctb/wCxBte2AIiaTfATzukTVtGhKkdy3cY6U2DVSXc+s+jr
+Kut8AYnjp1T6bho98RHbbk+hu+0gBWL2ysJd1+slLBUEotUMTkzgA1YdBXy9J/eM
+HJ2a0ydFll/m2rXx7RRJWSbcgPZxQLDfollnNVfhcb75O3GsT3YfEIsjLmon7NHr
+rJmTp773trg0cNJ6j5dKMA/2SQH5PL1cmcFgNfVZ+etNRIhwpIQYySWJ/468Mcg5
+ZKPY6nubIIj+HPB3Mhy8d9U3gAJvc9iEdzbKjrkJdVROONsyMYge4vnbjyKUr7/m
+ZN1O6pZy9Fvgbdhvx4ZHpfgEsa1qfLCH
+-----END CERTIFICATE-----
diff --git a/tests/data_files/server1.long_serial.crt b/tests/data_files/server1.long_serial.crt
new file mode 100644
index 0000000..1bd6955
--- /dev/null
+++ b/tests/data_files/server1.long_serial.crt
@@ -0,0 +1,20 @@
+-----BEGIN CERTIFICATE-----
+MIIDUjCCAjqgAwIBAgIUESIzRFVmd4iZqrvM3e7/ABEiM0QwDQYJKoZIhvcNAQEF
+BQAwOzELMAkGA1UEBhMCTkwxETAPBgNVBAoMCFBvbGFyU1NMMRkwFwYDVQQDDBBQ
+b2xhclNTTCBUZXN0IENBMB4XDTE5MDIxMDE0NDQwNloXDTI5MDIxMDE0NDQwNlow
+PDELMAkGA1UEBhMCTkwxETAPBgNVBAoMCFBvbGFyU1NMMRowGAYDVQQDDBFQb2xh
+clNTTCBTZXJ2ZXIgMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKkC
+Hz1AatVVU4v9Nu6CZS4VYV6Jv7joRZDb7ogWUtPxQ1BHlhJZZIdr/SvgRvlzvt3P
+kuGRW+1moG+JKXlFgNCDatVBQ3dfOXwJBEeCsFc5cO2j7BUZHqgzCEfBBUKp/UzD
+tN/dBh9NEFFAZ3MTD0D4bYElXwqxU8YwfhU5rPla7n+SnqYFW+cTl4W1I5LZ1CQG
+1QkliXUH3aYajz8JGb6tZSxk65Wb3P5BXhem2mxbacwCuhQsFiScStzN0PdSZ3Px
+LaAj/X70McotcMqJCwTbLqZPcG6ezr1YieJTWZ5uWpJl4og/DJQZo93l6J2VE+0p
+26twEtxaymsXq1KCVLECAwEAAaNNMEswCQYDVR0TBAIwADAdBgNVHQ4EFgQUH3TW
+PynBdHRFOwUSLD2ovUNZAqYwHwYDVR0jBBgwFoAUtFrkpbPe0lL2udWmlQ/rPrzH
+/f8wDQYJKoZIhvcNAQEFBQADggEBAC9qt4BC8zKb5o00ZVtTX0XYKWchHKYSrHk2
+r+zfW8pRcSaTGRTtMGkF7vozFrCX4Pr4vCKXOYFKQ/UEpWv5WzW7nB0+Ja0g4gnc
+9bLtg51n+IIG93ITGDm5+9YpsX6HsXSBpfY0vo9TwKg3bG1X26WG8j6m+V684hwV
+yveRUIrSvvgVJOBSe5rhn/pLmcpbI0nkPBGlqPd10qWc0RYSrSAa3bq/dpoqR7hY
+BGbbV1/9IgFhr2r44R17bhqevK3VhK4KOPRT5VMXjTh1iG4L13lIxBIuu+Lw0Pc0
+s+gQTGntA/sZkijC7mw0/q3nsRDKhHHXTDf2gjdUhMvFwYzmKBI=
+-----END CERTIFICATE-----
diff --git a/tests/data_files/server1.long_serial_FF.crt b/tests/data_files/server1.long_serial_FF.crt
new file mode 100644
index 0000000..8094fd7
--- /dev/null
+++ b/tests/data_files/server1.long_serial_FF.crt
@@ -0,0 +1,20 @@
+-----BEGIN CERTIFICATE-----
+MIIDTzCCAjegAwIBAgIRAP////////////////////8wDQYJKoZIhvcNAQEFBQAw
+OzELMAkGA1UEBhMCTkwxETAPBgNVBAoMCFBvbGFyU1NMMRkwFwYDVQQDDBBQb2xh
+clNTTCBUZXN0IENBMB4XDTE5MDIxMDE0NDQwNloXDTI5MDIxMDE0NDQwNlowPDEL
+MAkGA1UEBhMCTkwxETAPBgNVBAoMCFBvbGFyU1NMMRowGAYDVQQDDBFQb2xhclNT
+TCBTZXJ2ZXIgMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKkCHz1A
+atVVU4v9Nu6CZS4VYV6Jv7joRZDb7ogWUtPxQ1BHlhJZZIdr/SvgRvlzvt3PkuGR
+W+1moG+JKXlFgNCDatVBQ3dfOXwJBEeCsFc5cO2j7BUZHqgzCEfBBUKp/UzDtN/d
+Bh9NEFFAZ3MTD0D4bYElXwqxU8YwfhU5rPla7n+SnqYFW+cTl4W1I5LZ1CQG1Qkl
+iXUH3aYajz8JGb6tZSxk65Wb3P5BXhem2mxbacwCuhQsFiScStzN0PdSZ3PxLaAj
+/X70McotcMqJCwTbLqZPcG6ezr1YieJTWZ5uWpJl4og/DJQZo93l6J2VE+0p26tw
+EtxaymsXq1KCVLECAwEAAaNNMEswCQYDVR0TBAIwADAdBgNVHQ4EFgQUH3TWPynB
+dHRFOwUSLD2ovUNZAqYwHwYDVR0jBBgwFoAUtFrkpbPe0lL2udWmlQ/rPrzH/f8w
+DQYJKoZIhvcNAQEFBQADggEBADYfhZU2lWxBamt7m3A4XQj6bZ4BZlabv5IbLI32
+nej6w/6/gsXPI85nfZqpIn6IYwAeDRdJo/eUqYkIdoy5DEP+50pgCGJK5HAoBWVJ
+THKeVJn/vPH3Dz/CaCYQoHTmSi+ChfIhPh84UUdfVpv2qNInII4RxFlSAHUkRMbV
+BX6imMSD5M508G6vWGUUc6G/sx/s7vtVeGGPyNOQPgwMTes60Mewpu9LKKaSwfqQ
+DgEa8WzxPrPEyOUiIp7ClwlXe3JECHIjm445qmENgfY/8tlsyAdYKSkotfiuoUWb
+daylD6QVUXn67loYDPZALghpDxmSm21VE7feTWOUbOpe14U=
+-----END CERTIFICATE-----
diff --git a/tests/data_files/test-ca.server1.test_serial.opensslconf b/tests/data_files/test-ca.server1.test_serial.opensslconf
new file mode 100644
index 0000000..43a520e
--- /dev/null
+++ b/tests/data_files/test-ca.server1.test_serial.opensslconf
@@ -0,0 +1,25 @@
+ [ ca ]
+ default_ca             = test-ca
+
+ [ test-ca ]
+ certificate            = test-ca.crt
+ private_key            = test-ca.key
+ serial                 = test-ca.server1.tmp.serial
+ default_md             = sha1
+ default_startdate      = 20190210144406Z
+ default_enddate        = 20290210144406Z
+ x509_extensions        = v3_ca
+ new_certs_dir          = ./
+ database               = ./test-ca.server1.db
+ policy                 = policy_match
+ unique_subject         = no
+
+ [v3_ca]
+ basicConstraints = CA:false
+ subjectKeyIdentifier=hash
+ authorityKeyIdentifier=keyid:always
+
+ [policy_match]
+ countryName            = supplied
+ organizationName       = supplied
+ commonName             = supplied
diff --git a/tests/scripts/all.sh b/tests/scripts/all.sh
index 2221d59..883d58b 100755
--- a/tests/scripts/all.sh
+++ b/tests/scripts/all.sh
@@ -1768,6 +1768,9 @@
 
     msg "test: make, full_no_deprecated config" # ~ 5s
     make test
+
+    msg "test: ensure that X509 has no direct dependency on BIGNUM_C"
+    not grep mbedtls_mpi library/libmbedx509.a
 }
 
 component_test_full_no_deprecated_deprecated_warning () {
diff --git a/tests/suites/test_suite_bignum_mod_raw.function b/tests/suites/test_suite_bignum_mod_raw.function
index 9310b0e..24ecba3 100644
--- a/tests/suites/test_suite_bignum_mod_raw.function
+++ b/tests/suites/test_suite_bignum_mod_raw.function
@@ -6,6 +6,8 @@
 #include "constant_time_internal.h"
 #include "test/constant_flow.h"
 
+#include "bignum_mod_raw_invasive.h"
+
 /* END_HEADER */
 
 /* BEGIN_DEPENDENCIES
@@ -338,6 +340,56 @@
 }
 /* END_CASE */
 
+/* BEGIN_CASE depends_on:MBEDTLS_TEST_HOOKS */
+void mpi_mod_raw_fix_quasi_reduction(char *input_N,
+                                     char *input_X,
+                                     char *result)
+{
+    mbedtls_mpi_uint *X = NULL;
+    mbedtls_mpi_uint *N = NULL;
+    mbedtls_mpi_uint *res = NULL;
+    mbedtls_mpi_uint *tmp = NULL;
+    size_t limbs_X;
+    size_t limbs_N;
+    size_t limbs_res;
+
+    mbedtls_mpi_mod_modulus m;
+    mbedtls_mpi_mod_modulus_init(&m);
+
+    TEST_EQUAL(mbedtls_test_read_mpi_core(&X,   &limbs_X,   input_X), 0);
+    TEST_EQUAL(mbedtls_test_read_mpi_core(&N,   &limbs_N,   input_N), 0);
+    TEST_EQUAL(mbedtls_test_read_mpi_core(&res, &limbs_res, result),  0);
+
+    size_t limbs = limbs_N;
+    size_t bytes = limbs * sizeof(mbedtls_mpi_uint);
+
+    TEST_EQUAL(limbs_X,   limbs);
+    TEST_EQUAL(limbs_res, limbs);
+
+    ASSERT_ALLOC(tmp, limbs);
+    memcpy(tmp, X, bytes);
+
+    /* Check that 0 <= X < 2N */
+    mbedtls_mpi_uint c = mbedtls_mpi_core_sub(tmp, X, N, limbs);
+    TEST_ASSERT(c || mbedtls_mpi_core_lt_ct(tmp, N, limbs));
+
+    TEST_EQUAL(mbedtls_mpi_mod_modulus_setup(
+                   &m, N, limbs,
+                   MBEDTLS_MPI_MOD_REP_MONTGOMERY), 0);
+
+    mbedtls_mpi_mod_raw_fix_quasi_reduction(X, &m);
+    ASSERT_COMPARE(X, bytes, res, bytes);
+
+exit:
+    mbedtls_free(X);
+    mbedtls_free(res);
+    mbedtls_free(tmp);
+
+    mbedtls_mpi_mod_modulus_free(&m);
+    mbedtls_free(N);
+}
+/* END_CASE */
+
 /* BEGIN_CASE */
 void mpi_mod_raw_mul(char *input_A,
                      char *input_B,
diff --git a/tests/suites/test_suite_ecp.data b/tests/suites/test_suite_ecp.data
index 9311200..9a13793 100644
--- a/tests/suites/test_suite_ecp.data
+++ b/tests/suites/test_suite_ecp.data
@@ -1038,4 +1038,3 @@
 ECP check order for CURVE448
 depends_on:MBEDTLS_ECP_DP_CURVE448_ENABLED
 ecp_check_order:MBEDTLS_ECP_DP_CURVE448:"3fffffffffffffffffffffffffffffffffffffffffffffffffffffff7cca23e9c44edb49aed63690216cc2728dc58f552378c292ab5844f3"
-
diff --git a/tests/suites/test_suite_x509write.data b/tests/suites/test_suite_x509write.data
index c55c9d1..885ba00 100644
--- a/tests/suites/test_suite_x509write.data
+++ b/tests/suites/test_suite_x509write.data
@@ -60,95 +60,107 @@
 
 Certificate write check Server1 SHA1
 depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15:MBEDTLS_DES_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_HAS_ALG_MD5_VIA_MD_OR_PSA_BASED_ON_USE_PSA
-x509_crt_check:"data_files/server1.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=PolarSSL Test CA":"1":"20190210144406":"20290210144406":MBEDTLS_MD_SHA1:0:0:"NULL":0:0:1:-1:"data_files/server1.crt":0:0:"data_files/test-ca.crt"
+x509_crt_check:"data_files/server1.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=PolarSSL Test CA":"01":"20190210144406":"20290210144406":MBEDTLS_MD_SHA1:0:0:"NULL":0:0:1:-1:"data_files/server1.crt":0:0:"data_files/test-ca.crt"
 
 Certificate write check Server1 SHA1, not before 1970
 depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15:MBEDTLS_DES_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_HAS_ALG_MD5_VIA_MD_OR_PSA_BASED_ON_USE_PSA
-x509_crt_check:"data_files/server1.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=PolarSSL Test CA":"1":"19700210144406":"20290210144406":MBEDTLS_MD_SHA1:0:0:"NULL":0:0:1:-1:"":0:0:"data_files/test-ca.crt"
+x509_crt_check:"data_files/server1.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=PolarSSL Test CA":"01":"19700210144406":"20290210144406":MBEDTLS_MD_SHA1:0:0:"NULL":0:0:1:-1:"":0:0:"data_files/test-ca.crt"
 
 Certificate write check Server1 SHA1, not after 2050
 depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15:MBEDTLS_DES_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_HAS_ALG_MD5_VIA_MD_OR_PSA_BASED_ON_USE_PSA
-x509_crt_check:"data_files/server1.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=PolarSSL Test CA":"1":"20190210144406":"20500210144406":MBEDTLS_MD_SHA1:0:0:"NULL":0:0:1:-1:"":0:0:"data_files/test-ca.crt"
+x509_crt_check:"data_files/server1.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=PolarSSL Test CA":"01":"20190210144406":"20500210144406":MBEDTLS_MD_SHA1:0:0:"NULL":0:0:1:-1:"":0:0:"data_files/test-ca.crt"
 
 Certificate write check Server1 SHA1, not before 1970, not after 2050
 depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15:MBEDTLS_DES_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_HAS_ALG_MD5_VIA_MD_OR_PSA_BASED_ON_USE_PSA
-x509_crt_check:"data_files/server1.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=PolarSSL Test CA":"1":"19700210144406":"20500210144406":MBEDTLS_MD_SHA1:0:0:"NULL":0:0:1:-1:"":0:0:"data_files/test-ca.crt"
+x509_crt_check:"data_files/server1.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=PolarSSL Test CA":"01":"19700210144406":"20500210144406":MBEDTLS_MD_SHA1:0:0:"NULL":0:0:1:-1:"":0:0:"data_files/test-ca.crt"
 
 Certificate write check Server1 SHA1, not before 2050, not after 2059
 depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15:MBEDTLS_DES_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_HAS_ALG_MD5_VIA_MD_OR_PSA_BASED_ON_USE_PSA
-x509_crt_check:"data_files/server1.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=PolarSSL Test CA":"1":"20500210144406":"20590210144406":MBEDTLS_MD_SHA1:0:0:"NULL":0:0:1:-1:"":0:0:"data_files/test-ca.crt"
+x509_crt_check:"data_files/server1.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=PolarSSL Test CA":"01":"20500210144406":"20590210144406":MBEDTLS_MD_SHA1:0:0:"NULL":0:0:1:-1:"":0:0:"data_files/test-ca.crt"
 
 Certificate write check Server1 SHA1, key_usage
 depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15:MBEDTLS_DES_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_HAS_ALG_MD5_VIA_MD_OR_PSA_BASED_ON_USE_PSA
-x509_crt_check:"data_files/server1.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=PolarSSL Test CA":"1":"20190210144406":"20290210144406":MBEDTLS_MD_SHA1:MBEDTLS_X509_KU_DIGITAL_SIGNATURE | MBEDTLS_X509_KU_NON_REPUDIATION | MBEDTLS_X509_KU_KEY_ENCIPHERMENT:1:"NULL":0:0:1:-1:"data_files/server1.key_usage.crt":0:0:"data_files/test-ca.crt"
+x509_crt_check:"data_files/server1.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=PolarSSL Test CA":"01":"20190210144406":"20290210144406":MBEDTLS_MD_SHA1:MBEDTLS_X509_KU_DIGITAL_SIGNATURE | MBEDTLS_X509_KU_NON_REPUDIATION | MBEDTLS_X509_KU_KEY_ENCIPHERMENT:1:"NULL":0:0:1:-1:"data_files/server1.key_usage.crt":0:0:"data_files/test-ca.crt"
 
 Certificate write check Server1 SHA1, one ext_key_usage
 depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15:MBEDTLS_DES_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_HAS_ALG_MD5_VIA_MD_OR_PSA_BASED_ON_USE_PSA
-x509_crt_check:"data_files/server1.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=PolarSSL Test CA":"1":"20110212144406":"20210212144406":MBEDTLS_MD_SHA1:0:0:"serverAuth":0:0:1:-1:"data_files/server1.key_ext_usage.crt":0:0:"data_files/test-ca.crt"
+x509_crt_check:"data_files/server1.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=PolarSSL Test CA":"01":"20110212144406":"20210212144406":MBEDTLS_MD_SHA1:0:0:"serverAuth":0:0:1:-1:"data_files/server1.key_ext_usage.crt":0:0:"data_files/test-ca.crt"
 
 Certificate write check Server1 SHA1, two ext_key_usages
 depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15:MBEDTLS_DES_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_HAS_ALG_MD5_VIA_MD_OR_PSA_BASED_ON_USE_PSA
-x509_crt_check:"data_files/server1.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=PolarSSL Test CA":"1":"20110212144406":"20210212144406":MBEDTLS_MD_SHA1:0:0:"codeSigning,timeStamping":0:0:1:-1:"data_files/server1.key_ext_usages.crt":0:0:"data_files/test-ca.crt"
+x509_crt_check:"data_files/server1.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=PolarSSL Test CA":"01":"20110212144406":"20210212144406":MBEDTLS_MD_SHA1:0:0:"codeSigning,timeStamping":0:0:1:-1:"data_files/server1.key_ext_usages.crt":0:0:"data_files/test-ca.crt"
 
 Certificate write check Server1 SHA1, ns_cert_type
 depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15:MBEDTLS_DES_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_HAS_ALG_MD5_VIA_MD_OR_PSA_BASED_ON_USE_PSA
-x509_crt_check:"data_files/server1.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=PolarSSL Test CA":"1":"20190210144406":"20290210144406":MBEDTLS_MD_SHA1:0:0:"NULL":MBEDTLS_X509_NS_CERT_TYPE_SSL_SERVER:1:1:-1:"data_files/server1.cert_type.crt":0:0:"data_files/test-ca.crt"
+x509_crt_check:"data_files/server1.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=PolarSSL Test CA":"01":"20190210144406":"20290210144406":MBEDTLS_MD_SHA1:0:0:"NULL":MBEDTLS_X509_NS_CERT_TYPE_SSL_SERVER:1:1:-1:"data_files/server1.cert_type.crt":0:0:"data_files/test-ca.crt"
 
 Certificate write check Server1 SHA1, version 1
 depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15:MBEDTLS_DES_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_HAS_ALG_MD5_VIA_MD_OR_PSA_BASED_ON_USE_PSA
-x509_crt_check:"data_files/server1.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=PolarSSL Test CA":"1":"20190210144406":"20290210144406":MBEDTLS_MD_SHA1:0:0:"NULL":0:0:1:MBEDTLS_X509_CRT_VERSION_1:"data_files/server1.v1.crt":0:0:"data_files/test-ca.crt"
+x509_crt_check:"data_files/server1.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=PolarSSL Test CA":"01":"20190210144406":"20290210144406":MBEDTLS_MD_SHA1:0:0:"NULL":0:0:1:MBEDTLS_X509_CRT_VERSION_1:"data_files/server1.v1.crt":0:0:"data_files/test-ca.crt"
 
 Certificate write check Server1 SHA1, CA
 depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15:MBEDTLS_DES_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_HAS_ALG_MD5_VIA_MD_OR_PSA_BASED_ON_USE_PSA
-x509_crt_check:"data_files/server1.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=PolarSSL Test CA":"1":"20190210144406":"20290210144406":MBEDTLS_MD_SHA1:0:0:"NULL":0:0:1:-1:"data_files/server1.ca.crt":0:1:"data_files/test-ca.crt"
+x509_crt_check:"data_files/server1.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=PolarSSL Test CA":"01":"20190210144406":"20290210144406":MBEDTLS_MD_SHA1:0:0:"NULL":0:0:1:-1:"data_files/server1.ca.crt":0:1:"data_files/test-ca.crt"
 
 Certificate write check Server1 SHA1, RSA_ALT
 depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15:MBEDTLS_DES_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_HAS_ALG_MD5_VIA_MD_OR_PSA_BASED_ON_USE_PSA
-x509_crt_check:"data_files/server1.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=PolarSSL Test CA":"1":"20190210144406":"20290210144406":MBEDTLS_MD_SHA1:0:0:"NULL":0:0:0:-1:"data_files/server1.noauthid.crt":1:0:"data_files/test-ca.crt"
+x509_crt_check:"data_files/server1.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=PolarSSL Test CA":"01":"20190210144406":"20290210144406":MBEDTLS_MD_SHA1:0:0:"NULL":0:0:0:-1:"data_files/server1.noauthid.crt":1:0:"data_files/test-ca.crt"
 
 Certificate write check Server1 SHA1, RSA_ALT, key_usage
 depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15:MBEDTLS_DES_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_HAS_ALG_MD5_VIA_MD_OR_PSA_BASED_ON_USE_PSA
-x509_crt_check:"data_files/server1.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=PolarSSL Test CA":"1":"20190210144406":"20290210144406":MBEDTLS_MD_SHA1:MBEDTLS_X509_KU_DIGITAL_SIGNATURE | MBEDTLS_X509_KU_NON_REPUDIATION | MBEDTLS_X509_KU_KEY_ENCIPHERMENT:1:"NULL":0:0:0:-1:"data_files/server1.key_usage_noauthid.crt":1:0:"data_files/test-ca.crt"
+x509_crt_check:"data_files/server1.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=PolarSSL Test CA":"01":"20190210144406":"20290210144406":MBEDTLS_MD_SHA1:MBEDTLS_X509_KU_DIGITAL_SIGNATURE | MBEDTLS_X509_KU_NON_REPUDIATION | MBEDTLS_X509_KU_KEY_ENCIPHERMENT:1:"NULL":0:0:0:-1:"data_files/server1.key_usage_noauthid.crt":1:0:"data_files/test-ca.crt"
 
 Certificate write check Server1 SHA1, RSA_ALT, ns_cert_type
 depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15:MBEDTLS_DES_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_HAS_ALG_MD5_VIA_MD_OR_PSA_BASED_ON_USE_PSA
-x509_crt_check:"data_files/server1.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=PolarSSL Test CA":"1":"20190210144406":"20290210144406":MBEDTLS_MD_SHA1:0:0:"NULL":MBEDTLS_X509_NS_CERT_TYPE_SSL_SERVER:1:0:-1:"data_files/server1.cert_type_noauthid.crt":1:0:"data_files/test-ca.crt"
+x509_crt_check:"data_files/server1.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=PolarSSL Test CA":"01":"20190210144406":"20290210144406":MBEDTLS_MD_SHA1:0:0:"NULL":MBEDTLS_X509_NS_CERT_TYPE_SSL_SERVER:1:0:-1:"data_files/server1.cert_type_noauthid.crt":1:0:"data_files/test-ca.crt"
 
 Certificate write check Server1 SHA1, RSA_ALT, version 1
 depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15:MBEDTLS_DES_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_HAS_ALG_MD5_VIA_MD_OR_PSA_BASED_ON_USE_PSA
-x509_crt_check:"data_files/server1.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=PolarSSL Test CA":"1":"20190210144406":"20290210144406":MBEDTLS_MD_SHA1:0:0:"NULL":0:0:0:MBEDTLS_X509_CRT_VERSION_1:"data_files/server1.v1.crt":1:0:"data_files/test-ca.crt"
+x509_crt_check:"data_files/server1.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=PolarSSL Test CA":"01":"20190210144406":"20290210144406":MBEDTLS_MD_SHA1:0:0:"NULL":0:0:0:MBEDTLS_X509_CRT_VERSION_1:"data_files/server1.v1.crt":1:0:"data_files/test-ca.crt"
 
 Certificate write check Server1 SHA1, RSA_ALT, CA
 depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15:MBEDTLS_DES_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_HAS_ALG_MD5_VIA_MD_OR_PSA_BASED_ON_USE_PSA
-x509_crt_check:"data_files/server1.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=PolarSSL Test CA":"1":"20190210144406":"20290210144406":MBEDTLS_MD_SHA1:0:0:"NULL":0:0:0:-1:"data_files/server1.ca_noauthid.crt":1:1:"data_files/test-ca.crt"
+x509_crt_check:"data_files/server1.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=PolarSSL Test CA":"01":"20190210144406":"20290210144406":MBEDTLS_MD_SHA1:0:0:"NULL":0:0:0:-1:"data_files/server1.ca_noauthid.crt":1:1:"data_files/test-ca.crt"
 
 Certificate write check Server1 SHA1, Opaque
 depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15:MBEDTLS_DES_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_HAS_ALG_MD5_VIA_MD_OR_PSA_BASED_ON_USE_PSA:MBEDTLS_USE_PSA_CRYPTO
-x509_crt_check:"data_files/server1.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=PolarSSL Test CA":"1":"20190210144406":"20290210144406":MBEDTLS_MD_SHA1:0:0:"NULL":0:0:1:-1:"data_files/server1.crt":2:0:"data_files/test-ca.crt"
+x509_crt_check:"data_files/server1.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=PolarSSL Test CA":"01":"20190210144406":"20290210144406":MBEDTLS_MD_SHA1:0:0:"NULL":0:0:1:-1:"data_files/server1.crt":2:0:"data_files/test-ca.crt"
 
 Certificate write check Server1 SHA1, Opaque, key_usage
 depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15:MBEDTLS_DES_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_HAS_ALG_MD5_VIA_MD_OR_PSA_BASED_ON_USE_PSA:MBEDTLS_USE_PSA_CRYPTO
-x509_crt_check:"data_files/server1.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=PolarSSL Test CA":"1":"20190210144406":"20290210144406":MBEDTLS_MD_SHA1:MBEDTLS_X509_KU_DIGITAL_SIGNATURE | MBEDTLS_X509_KU_NON_REPUDIATION | MBEDTLS_X509_KU_KEY_ENCIPHERMENT:1:"NULL":0:0:1:-1:"data_files/server1.key_usage.crt":2:0:"data_files/test-ca.crt"
+x509_crt_check:"data_files/server1.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=PolarSSL Test CA":"01":"20190210144406":"20290210144406":MBEDTLS_MD_SHA1:MBEDTLS_X509_KU_DIGITAL_SIGNATURE | MBEDTLS_X509_KU_NON_REPUDIATION | MBEDTLS_X509_KU_KEY_ENCIPHERMENT:1:"NULL":0:0:1:-1:"data_files/server1.key_usage.crt":2:0:"data_files/test-ca.crt"
 
 Certificate write check Server1 SHA1, Opaque, ns_cert_type
 depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15:MBEDTLS_DES_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_HAS_ALG_MD5_VIA_MD_OR_PSA_BASED_ON_USE_PSA:MBEDTLS_USE_PSA_CRYPTO
-x509_crt_check:"data_files/server1.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=PolarSSL Test CA":"1":"20190210144406":"20290210144406":MBEDTLS_MD_SHA1:0:0:"NULL":MBEDTLS_X509_NS_CERT_TYPE_SSL_SERVER:1:1:-1:"data_files/server1.cert_type.crt":2:0:"data_files/test-ca.crt"
+x509_crt_check:"data_files/server1.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=PolarSSL Test CA":"01":"20190210144406":"20290210144406":MBEDTLS_MD_SHA1:0:0:"NULL":MBEDTLS_X509_NS_CERT_TYPE_SSL_SERVER:1:1:-1:"data_files/server1.cert_type.crt":2:0:"data_files/test-ca.crt"
 
 Certificate write check Server1 SHA1, Opaque, version 1
 depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15:MBEDTLS_DES_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_HAS_ALG_MD5_VIA_MD_OR_PSA_BASED_ON_USE_PSA:MBEDTLS_USE_PSA_CRYPTO
-x509_crt_check:"data_files/server1.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=PolarSSL Test CA":"1":"20190210144406":"20290210144406":MBEDTLS_MD_SHA1:0:0:"NULL":0:0:1:MBEDTLS_X509_CRT_VERSION_1:"data_files/server1.v1.crt":2:0:"data_files/test-ca.crt"
+x509_crt_check:"data_files/server1.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=PolarSSL Test CA":"01":"20190210144406":"20290210144406":MBEDTLS_MD_SHA1:0:0:"NULL":0:0:1:MBEDTLS_X509_CRT_VERSION_1:"data_files/server1.v1.crt":2:0:"data_files/test-ca.crt"
 
 Certificate write check Server1 SHA1, Opaque, CA
 depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15:MBEDTLS_DES_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_HAS_ALG_MD5_VIA_MD_OR_PSA_BASED_ON_USE_PSA:MBEDTLS_USE_PSA_CRYPTO
-x509_crt_check:"data_files/server1.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=PolarSSL Test CA":"1":"20190210144406":"20290210144406":MBEDTLS_MD_SHA1:0:0:"NULL":0:0:1:-1:"data_files/server1.ca.crt":2:1:"data_files/test-ca.crt"
+x509_crt_check:"data_files/server1.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=PolarSSL Test CA":"01":"20190210144406":"20290210144406":MBEDTLS_MD_SHA1:0:0:"NULL":0:0:1:-1:"data_files/server1.ca.crt":2:1:"data_files/test-ca.crt"
+
+Certificate write check Server1 SHA1, Full length serial
+depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15:MBEDTLS_DES_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_HAS_ALG_MD5_VIA_MD_OR_PSA_BASED_ON_USE_PSA
+x509_crt_check:"data_files/server1.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=PolarSSL Test CA":"112233445566778899aabbccddeeff0011223344":"20190210144406":"20290210144406":MBEDTLS_MD_SHA1:0:0:"NULL":0:0:1:-1:"data_files/server1.long_serial.crt":0:0:"data_files/test-ca.crt"
+
+Certificate write check Server1 SHA1, Serial starting with 0x80
+depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15:MBEDTLS_DES_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_HAS_ALG_MD5_VIA_MD_OR_PSA_BASED_ON_USE_PSA
+x509_crt_check:"data_files/server1.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=PolarSSL Test CA":"8011223344":"20190210144406":"20290210144406":MBEDTLS_MD_SHA1:0:0:"NULL":0:0:1:-1:"data_files/server1.80serial.crt":0:0:"data_files/test-ca.crt"
+
+Certificate write check Server1 SHA1, All 0xFF full length serial
+depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15:MBEDTLS_DES_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_HAS_ALG_MD5_VIA_MD_OR_PSA_BASED_ON_USE_PSA
+x509_crt_check:"data_files/server1.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=PolarSSL Test CA":"ffffffffffffffffffffffffffffffff":"20190210144406":"20290210144406":MBEDTLS_MD_SHA1:0:0:"NULL":0:0:1:-1:"data_files/server1.long_serial_FF.crt":0:0:"data_files/test-ca.crt"
 
 Certificate write check Server5 ECDSA
 depends_on:MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA:MBEDTLS_ECDSA_C:MBEDTLS_ECDSA_DETERMINISTIC:MBEDTLS_ECP_DP_SECP384R1_ENABLED:MBEDTLS_ECP_DP_SECP256R1_ENABLED
-x509_crt_check:"data_files/server5.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca2.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=Polarssl Test EC CA":"1":"20190210144406":"20290210144406":MBEDTLS_MD_SHA256:0:0:"NULL":0:0:1:-1:"data_files/server5.crt":0:0:"data_files/test-ca2.crt"
+x509_crt_check:"data_files/server5.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca2.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=Polarssl Test EC CA":"01":"20190210144406":"20290210144406":MBEDTLS_MD_SHA256:0:0:"NULL":0:0:1:-1:"data_files/server5.crt":0:0:"data_files/test-ca2.crt"
 
 Certificate write check Server5 ECDSA, Opaque
 depends_on:MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA:MBEDTLS_ECDSA_C:MBEDTLS_ECDSA_DETERMINISTIC:MBEDTLS_ECP_DP_SECP384R1_ENABLED:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_USE_PSA_CRYPTO
-x509_crt_check:"data_files/server5.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca2.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=Polarssl Test EC CA":"1":"20190210144406":"20290210144406":MBEDTLS_MD_SHA256:0:0:"NULL":0:0:1:-1:"":2:0:"data_files/test-ca2.crt"
+x509_crt_check:"data_files/server5.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca2.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=Polarssl Test EC CA":"01":"20190210144406":"20290210144406":MBEDTLS_MD_SHA256:0:0:"NULL":0:0:1:-1:"":2:0:"data_files/test-ca2.crt"
 
 X509 String to Names #1
 mbedtls_x509_string_to_names:"C=NL,O=Offspark\, Inc., OU=PolarSSL":"C=NL, O=Offspark\, Inc., OU=PolarSSL":0
@@ -167,3 +179,6 @@
 
 X509 String to Names #6 (Escape at end)
 mbedtls_x509_string_to_names:"C=NL, O=Offspark\":"":MBEDTLS_ERR_X509_INVALID_NAME
+
+Check max serial length
+x509_set_serial_check:
diff --git a/tests/suites/test_suite_x509write.function b/tests/suites/test_suite_x509write.function
index 03b9bae..056d26a 100644
--- a/tests/suites/test_suite_x509write.function
+++ b/tests/suites/test_suite_x509write.function
@@ -300,7 +300,7 @@
 void x509_crt_check(char *subject_key_file, char *subject_pwd,
                     char *subject_name, char *issuer_key_file,
                     char *issuer_pwd, char *issuer_name,
-                    char *serial_str, char *not_before, char *not_after,
+                    data_t *serial_arg, char *not_before, char *not_after,
                     int md_type, int key_usage, int set_key_usage,
                     char *ext_key_usage,
                     int cert_type, int set_cert_type, int auth_ident,
@@ -315,7 +315,9 @@
     unsigned char check_buf[5000];
     unsigned char *p, *end;
     unsigned char tag, sz;
-    mbedtls_mpi serial;
+#if defined(MBEDTLS_TEST_DEPRECATED) && defined(MBEDTLS_BIGNUM_C)
+    mbedtls_mpi serial_mpi;
+#endif
     int ret, before_tag, after_tag;
     size_t olen = 0, pem_len = 0, buf_index = 0;
     int der_len = -1;
@@ -327,7 +329,9 @@
     mbedtls_pk_type_t issuer_key_type;
 
     memset(&rnd_info, 0x2a, sizeof(mbedtls_test_rnd_pseudo_info));
-    mbedtls_mpi_init(&serial);
+#if defined(MBEDTLS_TEST_DEPRECATED) && defined(MBEDTLS_BIGNUM_C)
+    mbedtls_mpi_init(&serial_mpi);
+#endif
 
     USE_PSA_INIT();
 
@@ -384,13 +388,18 @@
         TEST_ASSERT(mbedtls_pk_get_type(&issuer_key) == MBEDTLS_PK_OPAQUE);
     }
 
-    TEST_ASSERT(mbedtls_test_read_mpi(&serial, serial_str) == 0);
-
     if (ver != -1) {
         mbedtls_x509write_crt_set_version(&crt, ver);
     }
 
-    TEST_ASSERT(mbedtls_x509write_crt_set_serial(&crt, &serial) == 0);
+#if defined(MBEDTLS_TEST_DEPRECATED) && defined(MBEDTLS_BIGNUM_C)
+    TEST_ASSERT(mbedtls_mpi_read_binary(&serial_mpi, serial_arg->x,
+                                        serial_arg->len) == 0);
+    TEST_ASSERT(mbedtls_x509write_crt_set_serial(&crt, &serial_mpi) == 0);
+#else
+    TEST_ASSERT(mbedtls_x509write_crt_set_serial_raw(&crt, serial_arg->x,
+                                                     serial_arg->len) == 0);
+#endif
     TEST_ASSERT(mbedtls_x509write_crt_set_validity(&crt, not_before,
                                                    not_after) == 0);
     mbedtls_x509write_crt_set_md_alg(&crt, md_type);
@@ -549,7 +558,9 @@
     mbedtls_pk_free(&issuer_key_alt);
     mbedtls_pk_free(&subject_key);
     mbedtls_pk_free(&issuer_key);
-    mbedtls_mpi_free(&serial);
+#if defined(MBEDTLS_TEST_DEPRECATED) && defined(MBEDTLS_BIGNUM_C)
+    mbedtls_mpi_free(&serial_mpi);
+#endif
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
     psa_destroy_key(key_id);
 #endif
@@ -557,6 +568,37 @@
 }
 /* END_CASE */
 
+/* BEGIN_CASE depends_on:MBEDTLS_X509_CRT_WRITE_C */
+void x509_set_serial_check()
+{
+    mbedtls_x509write_cert ctx;
+    uint8_t invalid_serial[MBEDTLS_X509_RFC5280_MAX_SERIAL_LEN + 1];
+
+    memset(invalid_serial, 0x01, sizeof(invalid_serial));
+
+#if defined(MBEDTLS_TEST_DEPRECATED) && defined(MBEDTLS_BIGNUM_C)
+    mbedtls_mpi serial_mpi;
+
+    mbedtls_mpi_init(&serial_mpi);
+    TEST_EQUAL(mbedtls_mpi_read_binary(&serial_mpi, invalid_serial,
+                                       sizeof(invalid_serial)), 0);
+    TEST_EQUAL(mbedtls_x509write_crt_set_serial(&ctx, &serial_mpi),
+               MBEDTLS_ERR_X509_BAD_INPUT_DATA);
+#endif
+
+    TEST_EQUAL(mbedtls_x509write_crt_set_serial_raw(&ctx, invalid_serial,
+                                                    sizeof(invalid_serial)),
+               MBEDTLS_ERR_X509_BAD_INPUT_DATA);
+
+exit:
+#if defined(MBEDTLS_TEST_DEPRECATED) && defined(MBEDTLS_BIGNUM_C)
+    mbedtls_mpi_free(&serial_mpi);
+#else
+    ;
+#endif
+}
+/* END_CASE */
+
 /* BEGIN_CASE depends_on:MBEDTLS_X509_CREATE_C:MBEDTLS_X509_USE_C */
 void mbedtls_x509_string_to_names(char *name, char *parsed_name, int result
                                   )