1 /*
2 * libwebsockets - small server side websockets and web server implementation
3 *
4 * Copyright (C) 2010 - 2019 Andy Green <andy@warmcat.com>
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to
8 * deal in the Software without restriction, including without limitation the
9 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10 * sell copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22 * IN THE SOFTWARE.
23 */
24
25 #include "private-lib-core.h"
26 #include <mbedtls/x509_csr.h>
27 #include <errno.h>
28
29 int
lws_tls_server_client_cert_verify_config(struct lws_vhost * vh)30 lws_tls_server_client_cert_verify_config(struct lws_vhost *vh)
31 {
32 int verify_options = SSL_VERIFY_PEER;
33
34 /* as a server, are we requiring clients to identify themselves? */
35 if (!lws_check_opt(vh->options,
36 LWS_SERVER_OPTION_REQUIRE_VALID_OPENSSL_CLIENT_CERT)) {
37 lwsl_notice("no client cert required\n");
38 return 0;
39 }
40
41 if (!lws_check_opt(vh->options, LWS_SERVER_OPTION_PEER_CERT_NOT_REQUIRED))
42 verify_options = SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
43
44 lwsl_notice("%s: vh %s requires client cert %d\n", __func__, vh->name,
45 verify_options);
46
47 SSL_CTX_set_verify(vh->tls.ssl_ctx, verify_options, NULL);
48
49 return 0;
50 }
51
52 static int
lws_mbedtls_sni_cb(void * arg,mbedtls_ssl_context * mbedtls_ctx,const unsigned char * servername,size_t len)53 lws_mbedtls_sni_cb(void *arg, mbedtls_ssl_context *mbedtls_ctx,
54 const unsigned char *servername, size_t len)
55 {
56 SSL *ssl = SSL_SSL_from_mbedtls_ssl_context(mbedtls_ctx);
57 struct lws_context *context = (struct lws_context *)arg;
58 struct lws_vhost *vhost, *vh;
59
60 lwsl_notice("%s: %s\n", __func__, servername);
61
62 /*
63 * We can only get ssl accepted connections by using a vhost's ssl_ctx
64 * find out which listening one took us and only match vhosts on the
65 * same port.
66 */
67 vh = context->vhost_list;
68 while (vh) {
69 if (!vh->being_destroyed &&
70 vh->tls.ssl_ctx == SSL_get_SSL_CTX(ssl))
71 break;
72 vh = vh->vhost_next;
73 }
74
75 if (!vh) {
76 assert(vh); /* can't match the incoming vh? */
77 return 0;
78 }
79
80 vhost = lws_select_vhost(context, vh->listen_port,
81 (const char *)servername);
82 if (!vhost) {
83 lwsl_info("SNI: none: %s:%d\n", servername, vh->listen_port);
84
85 return 0;
86 }
87
88 lwsl_info("SNI: Found: %s:%d at vhost '%s'\n", servername,
89 vh->listen_port, vhost->name);
90
91 if (!vhost->tls.ssl_ctx) {
92 lwsl_err("%s: vhost %s matches SNI but no valid cert\n",
93 __func__, vh->name);
94
95 return 1;
96 }
97
98 /* select the ssl ctx from the selected vhost for this conn */
99 SSL_set_SSL_CTX(ssl, vhost->tls.ssl_ctx);
100
101 return 0;
102 }
103
104 int
lws_tls_server_certs_load(struct lws_vhost * vhost,struct lws * wsi,const char * cert,const char * private_key,const char * mem_cert,size_t mem_cert_len,const char * mem_privkey,size_t mem_privkey_len)105 lws_tls_server_certs_load(struct lws_vhost *vhost, struct lws *wsi,
106 const char *cert, const char *private_key,
107 const char *mem_cert, size_t mem_cert_len,
108 const char *mem_privkey, size_t mem_privkey_len)
109 {
110 lws_filepos_t flen;
111 uint8_t *p = NULL;
112 long err;
113 int n;
114
115 if ((!cert || !private_key) && (!mem_cert || !mem_privkey)) {
116 lwsl_notice("%s: no usable input\n", __func__);
117 return 0;
118 }
119
120 n = (int)lws_tls_generic_cert_checks(vhost, cert, private_key);
121
122 if (n == LWS_TLS_EXTANT_NO && (!mem_cert || !mem_privkey))
123 return 0;
124
125 /*
126 * we can't read the root-privs files. But if mem_cert is provided,
127 * we should use that.
128 */
129 if (n == LWS_TLS_EXTANT_NO)
130 n = LWS_TLS_EXTANT_ALTERNATIVE;
131
132 if (n == LWS_TLS_EXTANT_ALTERNATIVE && (!mem_cert || !mem_privkey))
133 return 1; /* no alternative */
134
135 if (n == LWS_TLS_EXTANT_ALTERNATIVE) {
136 /*
137 * Although we have prepared update certs, we no longer have
138 * the rights to read our own cert + key we saved.
139 *
140 * If we were passed copies in memory buffers, use those
141 * instead.
142 *
143 * The passed memory-buffer cert image is in DER, and the
144 * memory-buffer private key image is PEM.
145 */
146 cert = NULL;
147 private_key = NULL;
148 }
149 if (lws_tls_alloc_pem_to_der_file(vhost->context, cert, mem_cert,
150 mem_cert_len, &p, &flen)) {
151 lwsl_err("couldn't find cert file %s\n", cert);
152
153 return 1;
154 }
155
156 err = SSL_CTX_use_certificate_ASN1(vhost->tls.ssl_ctx, (int)flen, p);
157 lws_free_set_NULL(p);
158 if (!err) {
159 lwsl_err("Problem loading cert\n");
160 return 1;
161 }
162
163 if (lws_tls_alloc_pem_to_der_file(vhost->context, private_key,
164 (char *)mem_privkey, mem_privkey_len,
165 &p, &flen)) {
166 lwsl_err("couldn't find private key\n");
167
168 return 1;
169 }
170
171 err = SSL_CTX_use_PrivateKey_ASN1(0, vhost->tls.ssl_ctx, p, (long)flen);
172 lws_free_set_NULL(p);
173 if (!err) {
174 lwsl_err("Problem loading key\n");
175
176 return 1;
177 }
178
179 vhost->tls.skipped_certs = 0;
180
181 return 0;
182 }
183
184 int
lws_tls_server_vhost_backend_init(const struct lws_context_creation_info * info,struct lws_vhost * vhost,struct lws * wsi)185 lws_tls_server_vhost_backend_init(const struct lws_context_creation_info *info,
186 struct lws_vhost *vhost, struct lws *wsi)
187 {
188 const SSL_METHOD *method = TLS_server_method();
189 uint8_t *p;
190 lws_filepos_t flen;
191 int n;
192
193 vhost->tls.ssl_ctx = SSL_CTX_new(method, &vhost->context->mcdc); /* create context */
194 if (!vhost->tls.ssl_ctx) {
195 lwsl_err("problem creating ssl context\n");
196 return 1;
197 }
198
199 if (!vhost->tls.use_ssl ||
200 (!info->ssl_cert_filepath && !info->server_ssl_cert_mem))
201 return 0;
202
203 if (info->ssl_ca_filepath) {
204 lwsl_notice("%s: vh %s: loading CA filepath %s\n", __func__,
205 vhost->name, info->ssl_ca_filepath);
206 if (lws_tls_alloc_pem_to_der_file(vhost->context,
207 info->ssl_ca_filepath, NULL, 0, &p, &flen)) {
208 lwsl_err("couldn't find client CA file %s\n",
209 info->ssl_ca_filepath);
210
211 return 1;
212 }
213
214 if (SSL_CTX_add_client_CA_ASN1(vhost->tls.ssl_ctx, (int)flen, p) != 1) {
215 lwsl_err("%s: SSL_CTX_add_client_CA_ASN1 unhappy\n",
216 __func__);
217 free(p);
218 return 1;
219 }
220 free(p);
221 } else {
222 if (info->server_ssl_ca_mem && info->server_ssl_ca_mem_len &&
223 SSL_CTX_add_client_CA_ASN1(vhost->tls.ssl_ctx,
224 (int)info->server_ssl_ca_mem_len,
225 info->server_ssl_ca_mem) != 1) {
226 lwsl_err("%s: mem SSL_CTX_add_client_CA_ASN1 unhappy\n",
227 __func__);
228 return 1;
229 }
230 lwsl_notice("%s: vh %s: mem CA OK\n", __func__, vhost->name);
231 }
232
233 n = lws_tls_server_certs_load(vhost, wsi, info->ssl_cert_filepath,
234 info->ssl_private_key_filepath,
235 info->server_ssl_cert_mem,
236 info->server_ssl_cert_mem_len,
237 info->server_ssl_private_key_mem,
238 info->server_ssl_private_key_mem_len);
239 if (n)
240 return n;
241
242 return 0;
243 }
244
245 int
lws_tls_server_new_nonblocking(struct lws * wsi,lws_sockfd_type accept_fd)246 lws_tls_server_new_nonblocking(struct lws *wsi, lws_sockfd_type accept_fd)
247 {
248 errno = 0;
249 wsi->tls.ssl = SSL_new(wsi->a.vhost->tls.ssl_ctx);
250 if (wsi->tls.ssl == NULL) {
251 lwsl_err("SSL_new failed: errno %d\n", errno);
252
253 lws_tls_err_describe_clear();
254 return 1;
255 }
256
257 SSL_set_fd(wsi->tls.ssl, (int)accept_fd);
258
259 if (wsi->a.vhost->tls.ssl_info_event_mask)
260 SSL_set_info_callback(wsi->tls.ssl, lws_ssl_info_callback);
261
262 SSL_set_sni_callback(wsi->tls.ssl, lws_mbedtls_sni_cb, wsi->a.context);
263
264 return 0;
265 }
266
267 #if defined(LWS_AMAZON_RTOS)
268 enum lws_ssl_capable_status
269 #else
270 int
271 #endif
lws_tls_server_abort_connection(struct lws * wsi)272 lws_tls_server_abort_connection(struct lws *wsi)
273 {
274 if (wsi->tls.use_ssl)
275 __lws_tls_shutdown(wsi);
276
277 SSL_free(wsi->tls.ssl);
278
279 return 0;
280 }
281
282 enum lws_ssl_capable_status
lws_tls_server_accept(struct lws * wsi)283 lws_tls_server_accept(struct lws *wsi)
284 {
285 union lws_tls_cert_info_results ir;
286 int m, n;
287
288 n = SSL_accept(wsi->tls.ssl);
289
290 wsi->skip_fallback = 1;
291 if (n == 1) {
292
293 if (strstr(wsi->a.vhost->name, ".invalid")) {
294 lwsl_notice("%s: vhost has .invalid, "
295 "rejecting accept\n", __func__);
296
297 return LWS_SSL_CAPABLE_ERROR;
298 }
299
300 n = lws_tls_peer_cert_info(wsi, LWS_TLS_CERT_INFO_COMMON_NAME,
301 &ir, sizeof(ir.ns.name));
302 if (!n)
303 lwsl_notice("%s: client cert CN '%s'\n",
304 __func__, ir.ns.name);
305 else
306 lwsl_info("%s: couldn't get client cert CN\n",
307 __func__);
308 return LWS_SSL_CAPABLE_DONE;
309 }
310
311 m = SSL_get_error(wsi->tls.ssl, n);
312 lwsl_debug("%s: %s: accept SSL_get_error %d errno %d\n", __func__,
313 lws_wsi_tag(wsi), m, errno);
314
315 // mbedtls wrapper only
316 if (m == SSL_ERROR_SYSCALL && errno == 11)
317 return LWS_SSL_CAPABLE_MORE_SERVICE_READ;
318
319 #if defined(__APPLE__)
320 if (m == SSL_ERROR_SYSCALL && errno == 35)
321 return LWS_SSL_CAPABLE_MORE_SERVICE_READ;
322 #endif
323
324 #if defined(WIN32)
325 if (m == SSL_ERROR_SYSCALL && errno == 0)
326 return LWS_SSL_CAPABLE_MORE_SERVICE_READ;
327 #endif
328
329 if (m == SSL_ERROR_SYSCALL || m == SSL_ERROR_SSL)
330 return LWS_SSL_CAPABLE_ERROR;
331
332 if (m == SSL_ERROR_WANT_READ || SSL_want_read(wsi->tls.ssl)) {
333 if (lws_change_pollfd(wsi, 0, LWS_POLLIN)) {
334 lwsl_info("%s: WANT_READ change_pollfd failed\n",
335 __func__);
336 return LWS_SSL_CAPABLE_ERROR;
337 }
338
339 lwsl_info("SSL_ERROR_WANT_READ\n");
340 return LWS_SSL_CAPABLE_MORE_SERVICE_READ;
341 }
342 if (m == SSL_ERROR_WANT_WRITE || SSL_want_write(wsi->tls.ssl)) {
343 lwsl_debug("%s: WANT_WRITE\n", __func__);
344
345 if (lws_change_pollfd(wsi, 0, LWS_POLLOUT)) {
346 lwsl_info("%s: WANT_WRITE change_pollfd failed\n",
347 __func__);
348 return LWS_SSL_CAPABLE_ERROR;
349 }
350 return LWS_SSL_CAPABLE_MORE_SERVICE_WRITE;
351 }
352
353 return LWS_SSL_CAPABLE_ERROR;
354 }
355
356 #if defined(LWS_WITH_ACME)
357 /*
358 * mbedtls doesn't support SAN for cert creation. So we use a known-good
359 * tls-sni-01 cert from OpenSSL that worked on Let's Encrypt, and just replace
360 * the pubkey n part and the signature part.
361 *
362 * This will need redoing for tls-sni-02...
363 */
364
365 static uint8_t ss_cert_leadin[] = {
366 0x30, 0x82,
367 0x05, 0x56, /* total length: LEN1 (+2 / +3) (correct for 513 + 512)*/
368
369 0x30, 0x82, /* length: LEN2 (+6 / +7) (correct for 513) */
370 0x03, 0x3e,
371
372 /* addition: v3 cert (+5 bytes)*/
373 0xa0, 0x03,
374 0x02, 0x01, 0x02,
375
376 0x02, 0x01, 0x01,
377 0x30, 0x0d, 0x06, 0x09, 0x2a,
378 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x3f,
379 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x47,
380 0x42, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0b,
381 0x73, 0x6f, 0x6d, 0x65, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x31,
382 0x1a, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x11, 0x74, 0x65,
383 0x6d, 0x70, 0x2e, 0x61, 0x63, 0x6d, 0x65, 0x2e, 0x69, 0x6e, 0x76, 0x61,
384 0x6c, 0x69, 0x64, 0x30, 0x1e, 0x17, 0x0d,
385
386 /* from 2017-10-29 ... */
387 0x31, 0x37, 0x31, 0x30, 0x32, 0x39, 0x31, 0x31, 0x34, 0x39, 0x34, 0x35,
388 0x5a, 0x17, 0x0d,
389
390 /* thru 2049-10-29 we immediately discard the private key, no worries */
391 0x34, 0x39, 0x31, 0x30, 0x32, 0x39, 0x31, 0x32, 0x34, 0x39, 0x34, 0x35,
392 0x5a,
393
394 0x30, 0x3f, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
395 0x02, 0x47, 0x42, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a,
396 0x0c, 0x0b, 0x73, 0x6f, 0x6d, 0x65, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e,
397 0x79, 0x31, 0x1a, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x11,
398 0x74, 0x65, 0x6d, 0x70, 0x2e, 0x61, 0x63, 0x6d, 0x65, 0x2e, 0x69, 0x6e,
399 0x76, 0x61, 0x6c, 0x69, 0x64, 0x30,
400
401 0x82,
402 0x02, 0x22, /* LEN3 (+C3 / C4) */
403 0x30, 0x0d, 0x06,
404 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00,
405 0x03,
406
407 0x82,
408 0x02, 0x0f, /* LEN4 (+D6 / D7) */
409
410 0x00, 0x30, 0x82,
411
412 0x02, 0x0a, /* LEN5 (+ DB / DC) */
413
414 0x02, 0x82,
415
416 //0x02, 0x01, /* length of n in bytes (including leading 00 if any) */
417 },
418
419 /* 1 + (keybits / 8) bytes N */
420
421 ss_cert_san_leadin[] = {
422 /* e - fixed */
423 0x02, 0x03, 0x01, 0x00, 0x01,
424
425 0xa3, 0x5d, 0x30, 0x5b, 0x30, 0x59, 0x06, 0x03, 0x55, 0x1d,
426 0x11, 0x04, 0x52, 0x30, 0x50, /* <-- SAN length + 2 */
427
428 0x82, 0x4e, /* <-- SAN length */
429 },
430
431 /* 78 bytes of SAN (tls-sni-01)
432 0x61, 0x64, 0x34, 0x31, 0x61, 0x66, 0x62, 0x65, 0x30, 0x63, 0x61, 0x34,
433 0x36, 0x34, 0x32, 0x66, 0x30, 0x61, 0x34, 0x34, 0x39, 0x64, 0x39, 0x63,
434 0x61, 0x37, 0x36, 0x65, 0x62, 0x61, 0x61, 0x62, 0x2e, 0x32, 0x38, 0x39,
435 0x34, 0x64, 0x34, 0x31, 0x36, 0x63, 0x39, 0x38, 0x33, 0x66, 0x31, 0x32,
436 0x65, 0x64, 0x37, 0x33, 0x31, 0x61, 0x33, 0x30, 0x66, 0x35, 0x63, 0x34,
437 0x34, 0x37, 0x37, 0x66, 0x65, 0x2e, 0x61, 0x63, 0x6d, 0x65, 0x2e, 0x69,
438 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, */
439
440 /* end of LEN2 area */
441
442 ss_cert_sig_leadin[] = {
443 /* it's saying that the signature is SHA256 + RSA */
444 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
445 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03,
446
447 0x82,
448 0x02, 0x01,
449 0x00,
450 };
451
452 /* (keybits / 8) bytes signature to end of LEN1 area */
453
454 #define SAN_A_LENGTH 78
455
456 int
lws_tls_acme_sni_cert_create(struct lws_vhost * vhost,const char * san_a,const char * san_b)457 lws_tls_acme_sni_cert_create(struct lws_vhost *vhost, const char *san_a,
458 const char *san_b)
459 {
460 int buflen = 0x560;
461 uint8_t *buf = lws_malloc((unsigned int)buflen, "tmp cert buf"), *p = buf, *pkey_asn1;
462 struct lws_genrsa_ctx ctx;
463 struct lws_gencrypto_keyelem el[LWS_GENCRYPTO_RSA_KEYEL_COUNT];
464 uint8_t digest[32];
465 struct lws_genhash_ctx hash_ctx;
466 int pkey_asn1_len = 3 * 1024;
467 int n, m, keybits = lws_plat_recommended_rsa_bits(), adj;
468
469 if (!buf)
470 return 1;
471
472 n = lws_genrsa_new_keypair(vhost->context, &ctx, LGRSAM_PKCS1_1_5,
473 &el[0], keybits);
474 if (n < 0) {
475 lws_genrsa_destroy_elements(&el[0]);
476 goto bail1;
477 }
478
479 n = sizeof(ss_cert_leadin);
480 memcpy(p, ss_cert_leadin, (unsigned int)n);
481 p += n;
482
483 adj = (0x0556 - 0x401) + (keybits / 4) + 1;
484 buf[2] = (uint8_t)(adj >> 8);
485 buf[3] = (uint8_t)(adj & 0xff);
486
487 adj = (0x033e - 0x201) + (keybits / 8) + 1;
488 buf[6] = (uint8_t)(adj >> 8);
489 buf[7] = (uint8_t)(adj & 0xff);
490
491 adj = (0x0222 - 0x201) + (keybits / 8) + 1;
492 buf[0xc3] = (uint8_t)(adj >> 8);
493 buf[0xc4] = (uint8_t)(adj & 0xff);
494
495 adj = (0x020f - 0x201) + (keybits / 8) + 1;
496 buf[0xd6] = (uint8_t)(adj >> 8);
497 buf[0xd7] = (uint8_t)(adj & 0xff);
498
499 adj = (0x020a - 0x201) + (keybits / 8) + 1;
500 buf[0xdb] = (uint8_t)(adj >> 8);
501 buf[0xdc] = (uint8_t)(adj & 0xff);
502
503 *p++ = (uint8_t)(((keybits / 8) + 1) >> 8);
504 *p++ = (uint8_t)(((keybits / 8) + 1) & 0xff);
505
506 /* we need to drop 1 + (keybits / 8) bytes of n in here, 00 + key */
507
508 *p++ = 0x00;
509 memcpy(p, el[LWS_GENCRYPTO_RSA_KEYEL_N].buf, el[LWS_GENCRYPTO_RSA_KEYEL_N].len);
510 p += el[LWS_GENCRYPTO_RSA_KEYEL_N].len;
511
512 memcpy(p, ss_cert_san_leadin, sizeof(ss_cert_san_leadin));
513 p += sizeof(ss_cert_san_leadin);
514
515 /* drop in 78 bytes of san_a */
516
517 memcpy(p, san_a, SAN_A_LENGTH);
518 p += SAN_A_LENGTH;
519 memcpy(p, ss_cert_sig_leadin, sizeof(ss_cert_sig_leadin));
520
521 p[17] = (uint8_t)(((keybits / 8) + 1) >> 8);
522 p[18] = (uint8_t)(((keybits / 8) + 1) & 0xff);
523
524 p += sizeof(ss_cert_sig_leadin);
525
526 /* hash the cert plaintext */
527
528 if (lws_genhash_init(&hash_ctx, LWS_GENHASH_TYPE_SHA256))
529 goto bail2;
530
531 if (lws_genhash_update(&hash_ctx, buf, lws_ptr_diff_size_t(p, buf))) {
532 lws_genhash_destroy(&hash_ctx, NULL);
533
534 goto bail2;
535 }
536 if (lws_genhash_destroy(&hash_ctx, digest))
537 goto bail2;
538
539 /* sign the hash */
540
541 n = lws_genrsa_hash_sign(&ctx, digest, LWS_GENHASH_TYPE_SHA256, p,
542 (size_t)((size_t)buflen - lws_ptr_diff_size_t(p, buf)));
543 if (n < 0)
544 goto bail2;
545 p += n;
546
547 pkey_asn1 = lws_malloc((unsigned int)pkey_asn1_len, "mbed crt tmp");
548 if (!pkey_asn1)
549 goto bail2;
550
551 m = lws_genrsa_render_pkey_asn1(&ctx, 1, pkey_asn1, (size_t)pkey_asn1_len);
552 if (m < 0) {
553 lws_free(pkey_asn1);
554 goto bail2;
555 }
556
557 // lwsl_hexdump_level(LLL_DEBUG, buf, lws_ptr_diff(p, buf));
558 n = SSL_CTX_use_certificate_ASN1(vhost->tls.ssl_ctx,
559 lws_ptr_diff(p, buf), buf);
560 if (n != 1) {
561 lws_free(pkey_asn1);
562 lwsl_err("%s: generated cert failed to load 0x%x\n",
563 __func__, -n);
564 } else {
565 //lwsl_debug("private key\n");
566 //lwsl_hexdump_level(LLL_DEBUG, pkey_asn1, n);
567
568 /* and to use our generated private key */
569 n = SSL_CTX_use_PrivateKey_ASN1(0, vhost->tls.ssl_ctx,
570 pkey_asn1, m);
571 lws_free(pkey_asn1);
572 if (n != 1) {
573 lwsl_err("%s: SSL_CTX_use_PrivateKey_ASN1 failed\n",
574 __func__);
575 }
576 }
577
578 lws_genrsa_destroy(&ctx);
579 lws_genrsa_destroy_elements(&el[0]);
580
581 lws_free(buf);
582
583 return n != 1;
584
585 bail2:
586 lws_genrsa_destroy(&ctx);
587 lws_genrsa_destroy_elements(&el[0]);
588 bail1:
589 lws_free(buf);
590
591 return -1;
592 }
593
594 void
lws_tls_acme_sni_cert_destroy(struct lws_vhost * vhost)595 lws_tls_acme_sni_cert_destroy(struct lws_vhost *vhost)
596 {
597 }
598
599 #if defined(LWS_WITH_JOSE)
600 static int
_rngf(void * context,unsigned char * buf,size_t len)601 _rngf(void *context, unsigned char *buf, size_t len)
602 {
603 if ((size_t)lws_get_random(context, buf, len) == len)
604 return 0;
605
606 return -1;
607 }
608
609 static const char *x5[] = { "C", "ST", "L", "O", "CN" };
610
611 /*
612 * CSR is output formatted as b64url(DER)
613 * Private key is output as a PEM in memory
614 */
615 int
lws_tls_acme_sni_csr_create(struct lws_context * context,const char * elements[],uint8_t * dcsr,size_t csr_len,char ** privkey_pem,size_t * privkey_len)616 lws_tls_acme_sni_csr_create(struct lws_context *context, const char *elements[],
617 uint8_t *dcsr, size_t csr_len, char **privkey_pem,
618 size_t *privkey_len)
619 {
620 mbedtls_x509write_csr csr;
621 mbedtls_pk_context mpk;
622 int buf_size = 4096, n;
623 char subject[200], *p = subject, *end = p + sizeof(subject) - 1;
624 uint8_t *buf = malloc((unsigned int)buf_size); /* malloc because given to user code */
625
626 if (!buf)
627 return -1;
628
629 mbedtls_x509write_csr_init(&csr);
630
631 mbedtls_pk_init(&mpk);
632 if (mbedtls_pk_setup(&mpk, mbedtls_pk_info_from_type(MBEDTLS_PK_RSA))) {
633 lwsl_notice("%s: pk_setup failed\n", __func__);
634 goto fail;
635 }
636
637 n = mbedtls_rsa_gen_key(mbedtls_pk_rsa(mpk), _rngf, context,
638 (unsigned int)lws_plat_recommended_rsa_bits(), 65537);
639 if (n) {
640 lwsl_notice("%s: failed to generate keys\n", __func__);
641
642 goto fail1;
643 }
644
645 /* subject must be formatted like "C=TW,O=warmcat,CN=myserver" */
646
647 for (n = 0; n < (int)LWS_ARRAY_SIZE(x5); n++) {
648 if (p != subject)
649 *p++ = ',';
650 if (elements[n])
651 p += lws_snprintf(p, lws_ptr_diff_size_t(end, p), "%s=%s", x5[n],
652 elements[n]);
653 }
654
655 if (mbedtls_x509write_csr_set_subject_name(&csr, subject))
656 goto fail1;
657
658 mbedtls_x509write_csr_set_key(&csr, &mpk);
659 mbedtls_x509write_csr_set_md_alg(&csr, MBEDTLS_MD_SHA256);
660
661 /*
662 * data is written at the end of the buffer! Use the
663 * return value to determine where you should start
664 * using the buffer
665 */
666 n = mbedtls_x509write_csr_der(&csr, buf, (size_t)buf_size, _rngf, context);
667 if (n < 0) {
668 lwsl_notice("%s: write csr der failed\n", __func__);
669 goto fail1;
670 }
671
672 /* we have it in DER, we need it in b64URL */
673
674 n = lws_jws_base64_enc((char *)(buf + buf_size) - n, (size_t)n,
675 (char *)dcsr, csr_len);
676 if (n < 0)
677 goto fail1;
678
679 /*
680 * okay, the CSR is done, last we need the private key in PEM
681 * re-use the DER CSR buf as the result buffer since we cn do it in
682 * one step
683 */
684
685 if (mbedtls_pk_write_key_pem(&mpk, buf, (size_t)buf_size)) {
686 lwsl_notice("write key pem failed\n");
687 goto fail1;
688 }
689
690 *privkey_pem = (char *)buf;
691 *privkey_len = strlen((const char *)buf);
692
693 mbedtls_pk_free(&mpk);
694 mbedtls_x509write_csr_free(&csr);
695
696 return n;
697
698 fail1:
699 mbedtls_pk_free(&mpk);
700 fail:
701 mbedtls_x509write_csr_free(&csr);
702 free(buf);
703
704 return -1;
705 }
706 #endif
707 #endif
708