From ccdd9752865b4ca24e788f74e38fa423040df468 Mon Sep 17 00:00:00 2001 From: Andrzej Kurek Date: Sat, 1 Apr 2023 10:38:30 -0400 Subject: [PATCH] Add a certificate exercising all supported SAN types This will be used for comparison in unit tests. Add a possibility to write certificates with SAN in cert_write. Signed-off-by: Andrzej Kurek --- programs/x509/cert_write.c | 102 +++++++++++++++++- tests/data_files/Makefile | 2 + .../data_files/server1.allSubjectAltNames.crt | 23 ++++ 3 files changed, 125 insertions(+), 2 deletions(-) create mode 100644 tests/data_files/server1.allSubjectAltNames.crt diff --git a/programs/x509/cert_write.c b/programs/x509/cert_write.c index 51b09f3d6..ac6187a19 100644 --- a/programs/x509/cert_write.c +++ b/programs/x509/cert_write.c @@ -79,6 +79,7 @@ int main(void) #define DFL_NOT_AFTER "20301231235959" #define DFL_SERIAL "1" #define DFL_SERIAL_HEX "1" +#define DFL_EXT_SUBJECTALTNAME "" #define DFL_SELFSIGN 0 #define DFL_IS_CA 0 #define DFL_MAX_PATHLEN -1 @@ -134,6 +135,13 @@ int main(void) " subject_identifier=%%s default: 1\n" \ " Possible values: 0, 1\n" \ " (Considered for v3 only)\n" \ + " san=%%s default: (none)\n" \ + " Comma-separated-list of values:\n" \ + " DNS:value\n" \ + " URI:value\n" \ + " RFC822:value\n" \ + " IP:value (Only IPv4 is supported)\n" \ + " DN:value\n" \ " authority_identifier=%%s default: 1\n" \ " Possible values: 0, 1\n" \ " (Considered for v3 only)\n" \ @@ -188,6 +196,7 @@ struct options { const char *issuer_pwd; /* password for the issuer key file */ const char *output_file; /* where to store the constructed CRT */ const char *subject_name; /* subject name for certificate */ + mbedtls_x509_san_list *san_list; /* subjectAltName for certificate */ const char *issuer_name; /* issuer name for certificate */ const char *not_before; /* validity period not before */ const char *not_after; /* validity period not after */ @@ -207,6 +216,19 @@ struct options { int format; /* format */ } opt; +static int ip_string_to_bytes(const char *str, uint8_t *bytes, int maxBytes) +{ + for (int i = 0; i < maxBytes; i++) { + bytes[i] = strtoul(str, NULL, 16); + str = strchr(str, '.'); + if (str == NULL || *str == '\0') { + break; + } + str++; + } + return 0; +} + int write_certificate(mbedtls_x509write_cert *crt, const char *output_file, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) @@ -301,7 +323,7 @@ int main(int argc, char *argv[]) char buf[1024]; char issuer_name[256]; int i; - char *p, *q, *r; + char *p, *q, *r, *r2; #if defined(MBEDTLS_X509_CSR_PARSE_C) char subject_name[256]; mbedtls_x509_csr csr; @@ -314,7 +336,8 @@ int main(int argc, char *argv[]) mbedtls_entropy_context entropy; mbedtls_ctr_drbg_context ctr_drbg; const char *pers = "crt example app"; - + mbedtls_x509_san_list *cur, *prev; + uint8_t ip[4] = { 0 }; /* * Set to sane values */ @@ -370,6 +393,7 @@ usage: opt.authority_identifier = DFL_AUTH_IDENT; opt.basic_constraints = DFL_CONSTRAINTS; opt.format = DFL_FORMAT; + opt.san_list = NULL; for (i = 1; i < argc; i++) { @@ -526,6 +550,69 @@ usage: *tail = ext_key_usage; tail = &ext_key_usage->next; + q = r; + } + } else if (strcmp(p, "san") == 0) { + prev = NULL; + + while (q != NULL) { + if ((r = strchr(q, ';')) != NULL) { + *r++ = '\0'; + } + + cur = mbedtls_calloc(1, sizeof(mbedtls_x509_san_list)); + if (cur == NULL) { + mbedtls_printf("Not enough memory for subjectAltName list\n"); + goto usage; + } + + cur->next = NULL; + + if ((r2 = strchr(q, ':')) != NULL) { + *r2++ = '\0'; + } + if (strcmp(q, "RFC822") == 0) { + cur->node.type = MBEDTLS_X509_SAN_RFC822_NAME; + } else if (strcmp(q, "URI") == 0) { + cur->node.type = MBEDTLS_X509_SAN_UNIFORM_RESOURCE_IDENTIFIER; + } else if (strcmp(q, "DNS") == 0) { + cur->node.type = MBEDTLS_X509_SAN_DNS_NAME; + } else if (strcmp(q, "IP") == 0) { + cur->node.type = MBEDTLS_X509_SAN_IP_ADDRESS; + ip_string_to_bytes(r2, ip, 4); + cur->node.san.unstructured_name.p = (unsigned char *) ip; + cur->node.san.unstructured_name.len = sizeof(ip); + } else if (strcmp(q, "DN") == 0) { + mbedtls_asn1_named_data *ext_san_dirname = NULL; + cur->node.type = MBEDTLS_X509_SAN_DIRECTORY_NAME; + if ((ret = mbedtls_x509_string_to_names(&ext_san_dirname, + r2)) != 0) { + mbedtls_strerror(ret, buf, sizeof(buf)); + mbedtls_printf( + " failed\n ! mbedtls_x509_string_to_names " + "returned -0x%04x - %s\n\n", + (unsigned int) -ret, buf); + goto exit; + } + cur->node.san.directory_name = *ext_san_dirname; + } else { + mbedtls_free(cur); + goto usage; + } + + if (strcmp(q, "IP") != 0 && strcmp(q, "DN") != 0) { + q = r2; + cur->node.san.unstructured_name.p = (unsigned char *) q; + cur->node.san.unstructured_name.len = strlen(q); + } + + if (prev == NULL) { + opt.san_list = cur; + } else { + prev->next = cur; + } + + prev = cur; q = r; } } else if (strcmp(p, "ns_cert_type") == 0) { @@ -833,6 +920,17 @@ usage: mbedtls_printf(" ok\n"); } + if (opt.san_list != NULL) { + ret = mbedtls_x509write_crt_set_subject_alternative_name(&crt, opt.san_list); + + if (ret != 0) { + mbedtls_printf( + " failed\n ! mbedtls_x509write_csr_set_subject_alternative_name returned %d", + ret); + goto exit; + } + } + if (opt.ext_key_usage) { mbedtls_printf(" . Adding the Extended Key Usage extension ..."); fflush(stdout); diff --git a/tests/data_files/Makefile b/tests/data_files/Makefile index 2bc17fb24..fd68336e1 100644 --- a/tests/data_files/Makefile +++ b/tests/data_files/Makefile @@ -1198,6 +1198,8 @@ test_ca_server1_config_file = test-ca.server1.opensslconf 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.allSubjectAltNames.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=$@ san=URI:http://pki.example.com\;IP:1.2.3.4\;DN:C=UK,O="Mbed TLS",CN="SubjectAltName test"\;DNS:example.com\;RFC822:mail@example.com 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 $@ diff --git a/tests/data_files/server1.allSubjectAltNames.crt b/tests/data_files/server1.allSubjectAltNames.crt new file mode 100644 index 000000000..13af87310 --- /dev/null +++ b/tests/data_files/server1.allSubjectAltNames.crt @@ -0,0 +1,23 @@ +-----BEGIN CERTIFICATE----- +MIIDzTCCArWgAwIBAgIBATANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJOTDER +MA8GA1UECgwIUG9sYXJTU0wxGTAXBgNVBAMMEFBvbGFyU1NMIFRlc3QgQ0EwHhcN +MTkwMjEwMTQ0NDA2WhcNMjkwMjEwMTQ0NDA2WjA8MQswCQYDVQQGEwJOTDERMA8G +A1UECgwIUG9sYXJTU0wxGjAYBgNVBAMMEVBvbGFyU1NMIFNlcnZlciAxMIIBIjAN +BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqQIfPUBq1VVTi/027oJlLhVhXom/ +uOhFkNvuiBZS0/FDUEeWEllkh2v9K+BG+XO+3c+S4ZFb7Wagb4kpeUWA0INq1UFD +d185fAkER4KwVzlw7aPsFRkeqDMIR8EFQqn9TMO0390GH00QUUBncxMPQPhtgSVf +CrFTxjB+FTms+Vruf5KepgVb5xOXhbUjktnUJAbVCSWJdQfdphqPPwkZvq1lLGTr +lZvc/kFeF6babFtpzAK6FCwWJJxK3M3Q91Jnc/EtoCP9fvQxyi1wyokLBNsupk9w +bp7OvViJ4lNZnm5akmXiiD8MlBmj3eXonZUT7Snbq3AS3FrKaxerUoJUsQIDAQAB +o4HaMIHXMAkGA1UdEwQCMAAwHQYDVR0OBBYEFB901j8pwXR0RTsFEiw9qL1DWQKm +MB8GA1UdIwQYMBaAFLRa5KWz3tJS9rnVppUP6z68x/3/MIGJBgNVHREEgYEwf4EQ +bWFpbEBleGFtcGxlLmNvbYILZXhhbXBsZS5jb22kQDA+MQswCQYDVQQGEwJVSzER +MA8GA1UECgwITWJlZCBUTFMxHDAaBgNVBAMME1N1YmplY3RBbHROYW1lIHRlc3SH +BAECAwSGFmh0dHA6Ly9wa2kuZXhhbXBsZS5jb20wDQYJKoZIhvcNAQEFBQADggEB +AGPFB8YGpe6PRniPkYVlpCf5WwleYCpcP4AEvFHj5dD1UcBcqKjppJRGssg+S0fP +nNwYRjaVjKuhWSGIMrk0nZqsiexnkCma0S8kdFvHtCfbR9c9pQSn44olVMbHx/t8 +dzv7Z48HqsqvG0hn3AwDlZ+KrnTZFzzpWzfLkbPdZko/oHoFmqEekEuyOK9vO3fj +eNm5SzYtqOigw8TxkTb1+Qi9Cj66VEwVESW1y/TL9073Kx0lBoY8wj1Pvfdhplrg +IwYIwrr0HM+7nlYEhEI++NAbZhjQoS2kF5i7xpomUkYH9ePbrwWYBcuN00pljXEm +ioY0KKlx00fRehPH/6TBHZI= +-----END CERTIFICATE-----