x509: fix endianness and input data format for x509write_crt_set_serial_new
Signed-off-by: Valerio Setti <vsetti@baylibre.com>
diff --git a/include/mbedtls/x509_crt.h b/include/mbedtls/x509_crt.h
index 810873c..f88e8cc 100644
--- a/include/mbedtls/x509_crt.h
+++ b/include/mbedtls/x509_crt.h
@@ -1013,17 +1013,17 @@
* \brief Set the serial number for a Certificate.
*
* \param ctx CRT context to use
- * \param serial_buff Input buffer containing the serial number in big
- * endian format
+ * \param serial_buff A raw array of bytes containing the serial number
+ * in big endian format
* \param serial_buff_len Length of the previous input buffer 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)
- * - contains invalid chars
+ * 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_new(mbedtls_x509write_cert *ctx,
- char *serial_buff, size_t serial_buff_len);
+ unsigned char *serial_buff,
+ size_t serial_buff_len);
/**
* \brief Set the validity period for a Certificate
diff --git a/library/x509write_crt.c b/library/x509write_crt.c
index 718b6f0..da9ef6c 100644
--- a/library/x509write_crt.c
+++ b/library/x509write_crt.c
@@ -122,42 +122,24 @@
return ret;
}
- /* Reverse the string since "tmp" is in big endian format */
- for (int i = 0; i < MBEDTLS_X509_RFC5280_MAX_SERIAL_LEN; i++) {
- ctx->serial[i] = tmp[MBEDTLS_X509_RFC5280_MAX_SERIAL_LEN - 1 - i];
- }
+ /* 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
int mbedtls_x509write_crt_set_serial_new(mbedtls_x509write_cert *ctx,
- char *serial_buff, size_t serial_buff_len)
+ unsigned char *serial_buff,
+ size_t serial_buff_len)
{
- int i, j;
- char c;
- unsigned char val;
-
if (serial_buff_len > MBEDTLS_X509_RFC5280_MAX_SERIAL_LEN) {
return MBEDTLS_ERR_X509_BAD_INPUT_DATA;
}
- /* Store data in little endian format */
- for (i = 0, j = serial_buff_len - 1; j == 0; i++, j--) {
- c = serial_buff[j];
- if (c >= 0x30 && c <= 0x39) {
- val = c - 0x30;
- } else if (c >= 0x41 && c <= 0x46) {
- val = c - 0x37;
- } else if (c >= 0x61 && c <= 0x66) {
- val = c - 0x57;
- } else {
- return MBEDTLS_ERR_X509_BAD_INPUT_DATA;
- }
-
- ctx->serial[i] = val;
- }
- ctx->serial_len = i;
+ ctx->serial_len = serial_buff_len;
+ memcpy(ctx->serial, serial_buff, serial_buff_len);
return 0;
}
diff --git a/programs/x509/cert_write.c b/programs/x509/cert_write.c
index ec4d325..05d7677 100644
--- a/programs/x509/cert_write.c
+++ b/programs/x509/cert_write.c
@@ -235,6 +235,42 @@
return 0;
}
+/*
+ * Convert the input "in_buff" string to a raw byte array "out_buff". The amount
+ * of converted data is returned on "written_data".
+ */
+static int parse_serial(const char *in_buff, size_t in_buff_len,
+ unsigned char *out_buff, size_t out_buff_len,
+ size_t *written_data)
+{
+ char c;
+ unsigned char val;
+ int i;
+
+ if (out_buff_len < in_buff_len) {
+ return -1;
+ }
+
+ *written_data = 0;
+
+ for (i = 0; i < (int) in_buff_len; i++, (*written_data)++) {
+ c = in_buff[i];
+ if (c >= 0x30 && c <= 0x39) {
+ val = c - 0x30;
+ } else if (c >= 0x41 && c <= 0x46) {
+ val = c - 0x37;
+ } else if (c >= 0x61 && c <= 0x66) {
+ val = c - 0x57;
+ } else {
+ return -1;
+ }
+
+ out_buff[i] = val;
+ }
+
+ return 0;
+}
+
int main(int argc, char *argv[])
{
int ret = 1;
@@ -252,7 +288,8 @@
mbedtls_x509_csr csr;
#endif
mbedtls_x509write_cert crt;
- mbedtls_mpi serial;
+ 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 +301,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)
@@ -514,15 +550,6 @@
mbedtls_printf(" . Reading serial number...");
fflush(stdout);
-#if defined(MBEDTLS_BIGNUM_C)
- 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);
- goto exit;
- }
-#endif
-
mbedtls_printf(" ok\n");
// Parse issuer certificate if present
@@ -663,24 +690,18 @@
mbedtls_x509write_crt_set_version(&crt, opt.version);
mbedtls_x509write_crt_set_md_alg(&crt, opt.md);
-#if defined(MBEDTLS_BIGNUM_C) && !defined(MBEDTLS_DEPRECATED_REMOVED)
- ret = mbedtls_x509write_crt_set_serial(&crt, &serial);
- if (ret != 0) {
- mbedtls_strerror(ret, buf, sizeof(buf));
- mbedtls_printf(" failed\n ! mbedtls_x509write_crt_set_serial "
- "returned -0x%04x - %s\n\n", (unsigned int) -ret, buf);
+ if (parse_serial(opt.serial, strlen(opt.serial),
+ serial, sizeof(serial), &serial_len) < 0) {
+ mbedtls_printf(" failed\n ! Unable to parse serial\n\n");
goto exit;
}
-#else
- ret = mbedtls_x509write_crt_set_serial_new(&crt, opt.serial,
- strlen(opt.serial));
+ ret = mbedtls_x509write_crt_set_serial_new(&crt, serial, serial_len);
if (ret != 0) {
mbedtls_strerror(ret, buf, sizeof(buf));
mbedtls_printf(" failed\n ! mbedtls_x509write_crt_set_serial_new "
"returned -0x%04x - %s\n\n", (unsigned int) -ret, buf);
goto exit;
}
-#endif
ret = mbedtls_x509write_crt_set_validity(&crt, opt.not_before, opt.not_after);
if (ret != 0) {
@@ -820,7 +841,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);