|
1 | 1 | #include "SSLCert.hpp"
|
2 | 2 |
|
| 3 | +#include <Arduino.h> |
| 4 | + |
| 5 | +#ifndef HTTPS_DISABLE_SELFSIGNING |
| 6 | +#include <mbedtls/asn1write.h> |
| 7 | +#include <mbedtls/oid.h> |
| 8 | +#endif |
| 9 | + |
3 | 10 | namespace httpsserver {
|
4 | 11 |
|
5 | 12 | SSLCert::SSLCert(unsigned char * certData, uint16_t certLength, unsigned char * pkData, uint16_t pkLength):
|
@@ -53,6 +60,56 @@ void SSLCert::clear() {
|
53 | 60 |
|
54 | 61 | #ifndef HTTPS_DISABLE_SELFSIGNING
|
55 | 62 |
|
| 63 | +/** |
| 64 | + * Returns the CN value from a DN, or "" if it cannot be found |
| 65 | + */ |
| 66 | +static std::string get_cn(std::string dn) { |
| 67 | + size_t cnStart = dn.find("CN="); |
| 68 | + if (cnStart == std::string::npos) { |
| 69 | + return ""; |
| 70 | + } |
| 71 | + cnStart += 3; |
| 72 | + size_t cnStop = dn.find(",", cnStart); |
| 73 | + if (cnStop == std::string::npos) { |
| 74 | + cnStop = dn.length(); |
| 75 | + } |
| 76 | + return dn.substr(cnStart, cnStop - cnStart); |
| 77 | +} |
| 78 | + |
| 79 | +/** |
| 80 | + * Sets the DN as subjectAltName extension in the certificate |
| 81 | + */ |
| 82 | +static int add_subject_alt_name(mbedtls_x509write_cert *crt, std::string &cn) { |
| 83 | + size_t bufsize = cn.length() + 8; // some additional space for tags and length fields |
| 84 | + uint8_t buf[bufsize]; |
| 85 | + uint8_t *p = &buf[bufsize - 1]; |
| 86 | + uint8_t *start = buf; |
| 87 | + int length = 0; |
| 88 | + int ret; // used by MBEDTLS macro |
| 89 | + |
| 90 | + // The ASN structure that we will construct as parameter for write_crt_set_extension is as follows: |
| 91 | + // | 0x30 = Sequence | length | 0x82 = dNSName, context-specific | length | cn0 | cn1 | cn2 | cn3 | .. | cnn | |
| 92 | + // ↑ : ↑ `-------------v------------------´: |
| 93 | + // | : `-------------------´ : |
| 94 | + // | `----------v------------------------------------------------------------------´ |
| 95 | + // `---------------´ |
| 96 | + // Let's encrypt has useful infos: https://letsencrypt.org/docs/a-warm-welcome-to-asn1-and-der/#choice-and-any-encoding |
| 97 | + MBEDTLS_ASN1_CHK_ADD(length, |
| 98 | + mbedtls_asn1_write_raw_buffer(&p, start, (uint8_t*)cn.c_str(), cn.length())); |
| 99 | + MBEDTLS_ASN1_CHK_ADD(length, |
| 100 | + mbedtls_asn1_write_len(&p, start, length)); |
| 101 | + MBEDTLS_ASN1_CHK_ADD(length, |
| 102 | + mbedtls_asn1_write_tag(&p, start, MBEDTLS_ASN1_CONTEXT_SPECIFIC | 0x02)); // 0x02 = dNSName |
| 103 | + MBEDTLS_ASN1_CHK_ADD(length, |
| 104 | + mbedtls_asn1_write_len(&p, start, length)); |
| 105 | + MBEDTLS_ASN1_CHK_ADD(length, |
| 106 | + mbedtls_asn1_write_tag(&p, start, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE )); |
| 107 | + return mbedtls_x509write_crt_set_extension( crt, |
| 108 | + MBEDTLS_OID_SUBJECT_ALT_NAME, MBEDTLS_OID_SIZE(MBEDTLS_OID_SUBJECT_ALT_NAME), |
| 109 | + 0, // not critical |
| 110 | + p, length); |
| 111 | +} |
| 112 | + |
56 | 113 | /**
|
57 | 114 | * Function to create the key for a self-signed certificate.
|
58 | 115 | *
|
@@ -169,6 +226,12 @@ static int cert_write(SSLCert &certCtx, std::string dn, std::string validityFrom
|
169 | 226 | char dn_cstr[dn.length()+1];
|
170 | 227 | strcpy(dn_cstr, dn.c_str());
|
171 | 228 |
|
| 229 | + // Get the common name for the subject alternative name |
| 230 | + std::string cn = get_cn(dn); |
| 231 | + if (cn == "") { |
| 232 | + return HTTPS_SERVER_ERROR_CERTGEN_CN; |
| 233 | + } |
| 234 | + |
172 | 235 | // Initialize the entropy source
|
173 | 236 | mbedtls_entropy_init( &entropy );
|
174 | 237 |
|
@@ -209,6 +272,13 @@ static int cert_write(SSLCert &certCtx, std::string dn, std::string validityFrom
|
209 | 272 | goto error_after_cert;
|
210 | 273 | }
|
211 | 274 |
|
| 275 | + // Set subject alternative name |
| 276 | + stepRes = add_subject_alt_name( &crt, cn ); |
| 277 | + if (stepRes != 0) { |
| 278 | + funcRes = HTTPS_SERVER_ERROR_CERTGEN_NAME; |
| 279 | + goto error_after_cert; |
| 280 | + } |
| 281 | + |
212 | 282 | // Set the validity of the certificate. At the moment, it's fixed from 2019 to end of 2029.
|
213 | 283 | stepRes = mbedtls_x509write_crt_set_validity( &crt, validityFrom.c_str(), validityTo.c_str());
|
214 | 284 | if (stepRes != 0) {
|
@@ -281,6 +351,7 @@ static int cert_write(SSLCert &certCtx, std::string dn, std::string validityFrom
|
281 | 351 | error_after_entropy:
|
282 | 352 | mbedtls_ctr_drbg_free( &ctr_drbg );
|
283 | 353 | mbedtls_entropy_free( &entropy );
|
| 354 | + |
284 | 355 | return funcRes;
|
285 | 356 | }
|
286 | 357 |
|
|
0 commit comments