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