x509: enhancement and fixes

- enhance mbedtls_x509write_crt_set_serial(): avoid use of useless
  temporary buffer

- fix mbedtls_x509write_crt_der(): add an extra 0x00 byte at the
  beginning of serial if the MSb of serial is 1, as required from
  ASN.1

Signed-off-by: Valerio Setti <vsetti@baylibre.com>
diff --git a/library/x509write_crt.c b/library/x509write_crt.c
index 5cd1e30..4725c5f 100644
--- a/library/x509write_crt.c
+++ b/library/x509write_crt.c
@@ -105,7 +105,6 @@
                                      const mbedtls_mpi *serial)
 {
     int ret;
-    unsigned char tmp[MBEDTLS_X509_RFC5280_MAX_SERIAL_LEN];
     size_t tmp_len;
 
     /* Ensure that the MPI value fits into the buffer */
@@ -116,16 +115,11 @@
 
     ctx->serial_len = tmp_len;
 
-    ret = mbedtls_mpi_write_binary(serial, tmp,
-                                   MBEDTLS_X509_RFC5280_MAX_SERIAL_LEN);
+    ret = mbedtls_mpi_write_binary(serial, ctx->serial, tmp_len);
     if (ret < 0) {
         return ret;
     }
 
-    /* Copy data to the internal structure skipping leading zeros */
-    memcpy(ctx->serial, &tmp[MBEDTLS_X509_RFC5280_MAX_SERIAL_LEN - tmp_len],
-           tmp_len);
-
     return 0;
 }
 #endif // MBEDTLS_BIGNUM_C && !MBEDTLS_DEPRECATED_REMOVED
@@ -540,14 +534,25 @@
      *  Serial   ::=  INTEGER
      *
      * Written data is:
-     * - [ctx->serial_len] bytes for the raw serial buffer
+     * - "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_raw_buffer(&c, buf,
                                                             ctx->serial, ctx->serial_len));
-    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf,
-                                                     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));