Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 87cb548

Browse filesBrowse files
committed
self-signed certificates: Add CN as subjectAltName
1 parent daf6ca1 commit 87cb548
Copy full SHA for 87cb548

File tree

Expand file treeCollapse file tree

3 files changed

+76
-2
lines changed
Filter options
Expand file treeCollapse file tree

3 files changed

+76
-2
lines changed

‎CHANGELOG.md

Copy file name to clipboardExpand all lines: CHANGELOG.md
+2-2Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,15 @@
44

55
New functionality:
66

7-
7+
For self-signed certificates generated on the ESP32, the CN is now added as subjectAltName
88

99
Bug fixes:
1010

1111
1212

1313
Breaking changes:
1414

15-
15+
Generating self-signed certificates requires now a `CN=` as part of the distinguished name of the subject
1616

1717
## [v1.0.0](https://github.com/fhessel/esp32_https_server/releases/tag/v1.0.0)
1818

‎src/SSLCert.cpp

Copy file name to clipboardExpand all lines: src/SSLCert.cpp
+71Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
#include "SSLCert.hpp"
22

3+
#include <Arduino.h>
4+
5+
#ifndef HTTPS_DISABLE_SELFSIGNING
6+
#include <mbedtls/asn1write.h>
7+
#include <mbedtls/oid.h>
8+
#endif
9+
310
namespace httpsserver {
411

512
SSLCert::SSLCert(unsigned char * certData, uint16_t certLength, unsigned char * pkData, uint16_t pkLength):
@@ -53,6 +60,56 @@ void SSLCert::clear() {
5360

5461
#ifndef HTTPS_DISABLE_SELFSIGNING
5562

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+
56113
/**
57114
* Function to create the key for a self-signed certificate.
58115
*
@@ -169,6 +226,12 @@ static int cert_write(SSLCert &certCtx, std::string dn, std::string validityFrom
169226
char dn_cstr[dn.length()+1];
170227
strcpy(dn_cstr, dn.c_str());
171228

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+
172235
// Initialize the entropy source
173236
mbedtls_entropy_init( &entropy );
174237

@@ -209,6 +272,13 @@ static int cert_write(SSLCert &certCtx, std::string dn, std::string validityFrom
209272
goto error_after_cert;
210273
}
211274

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+
212282
// Set the validity of the certificate. At the moment, it's fixed from 2019 to end of 2029.
213283
stepRes = mbedtls_x509write_crt_set_validity( &crt, validityFrom.c_str(), validityTo.c_str());
214284
if (stepRes != 0) {
@@ -281,6 +351,7 @@ static int cert_write(SSLCert &certCtx, std::string dn, std::string validityFrom
281351
error_after_entropy:
282352
mbedtls_ctr_drbg_free( &ctr_drbg );
283353
mbedtls_entropy_free( &entropy );
354+
284355
return funcRes;
285356
}
286357

‎src/SSLCert.hpp

Copy file name to clipboardExpand all lines: src/SSLCert.hpp
+3Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#define HTTPS_SERVER_ERROR_CERTGEN_NAME 0x17
2828
#define HTTPS_SERVER_ERROR_CERTGEN_SERIAL 0x18
2929
#define HTTPS_SERVER_ERROR_CERTGEN_VALIDITY 0x19
30+
#define HTTPS_SERVER_ERROR_CERTGEN_CN 0x1a
3031

3132
#endif // !HTTPS_DISABLE_SELFSIGNING
3233

@@ -165,6 +166,8 @@ enum SSLKeySize {
165166
* would be:
166167
* CN=myesp.local,O=acme,C=US
167168
*
169+
* The subjectAltName is extracted from the CN component of the distinguished name.
170+
*
168171
* The strings validFrom and validUntil have to be formatted like this:
169172
* "20190101000000", "20300101000000"
170173
*

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.