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 enum lws_ssl_capable_status
lws_tls_server_abort_connection(struct lws *wsi)268 lws_tls_server_abort_connection(struct lws *wsi)
269 {
270 if (wsi->tls.use_ssl)
271 __lws_tls_shutdown(wsi);
272
273 SSL_free(wsi->tls.ssl);
274
275 return 0;
276 }
277
278 enum lws_ssl_capable_status
lws_tls_server_accept(struct lws *wsi)279 lws_tls_server_accept(struct lws *wsi)
280 {
281 union lws_tls_cert_info_results ir;
282 int m, n;
283
284 n = SSL_accept(wsi->tls.ssl);
285
286 wsi->skip_fallback = 1;
287 if (n == 1) {
288
289 if (strstr(wsi->a.vhost->name, ".invalid")) {
290 lwsl_notice("%s: vhost has .invalid, "
291 "rejecting accept\n", __func__);
292
293 return LWS_SSL_CAPABLE_ERROR;
294 }
295
296 n = lws_tls_peer_cert_info(wsi, LWS_TLS_CERT_INFO_COMMON_NAME,
297 &ir, sizeof(ir.ns.name));
298 if (!n)
299 lwsl_notice("%s: client cert CN '%s'\n",
300 __func__, ir.ns.name);
301 else
302 lwsl_info("%s: couldn't get client cert CN\n",
303 __func__);
304 return LWS_SSL_CAPABLE_DONE;
305 }
306
307 m = SSL_get_error(wsi->tls.ssl, n);
308 lwsl_debug("%s: %s: accept SSL_get_error %d errno %d\n", __func__,
309 lws_wsi_tag(wsi), m, errno);
310
311 // mbedtls wrapper only
312 if (m == SSL_ERROR_SYSCALL && errno == 11)
313 return LWS_SSL_CAPABLE_MORE_SERVICE_READ;
314
315 #if defined(__APPLE__)
316 if (m == SSL_ERROR_SYSCALL && errno == 35)
317 return LWS_SSL_CAPABLE_MORE_SERVICE_READ;
318 #endif
319
320 #if defined(WIN32)
321 if (m == SSL_ERROR_SYSCALL && errno == 0)
322 return LWS_SSL_CAPABLE_MORE_SERVICE_READ;
323 #endif
324
325 if (m == SSL_ERROR_SYSCALL || m == SSL_ERROR_SSL)
326 return LWS_SSL_CAPABLE_ERROR;
327
328 if (m == SSL_ERROR_WANT_READ || SSL_want_read(wsi->tls.ssl)) {
329 if (lws_change_pollfd(wsi, 0, LWS_POLLIN)) {
330 lwsl_info("%s: WANT_READ change_pollfd failed\n",
331 __func__);
332 return LWS_SSL_CAPABLE_ERROR;
333 }
334
335 lwsl_info("SSL_ERROR_WANT_READ\n");
336 return LWS_SSL_CAPABLE_MORE_SERVICE_READ;
337 }
338 if (m == SSL_ERROR_WANT_WRITE || SSL_want_write(wsi->tls.ssl)) {
339 lwsl_debug("%s: WANT_WRITE\n", __func__);
340
341 if (lws_change_pollfd(wsi, 0, LWS_POLLOUT)) {
342 lwsl_info("%s: WANT_WRITE change_pollfd failed\n",
343 __func__);
344 return LWS_SSL_CAPABLE_ERROR;
345 }
346 return LWS_SSL_CAPABLE_MORE_SERVICE_WRITE;
347 }
348
349 return LWS_SSL_CAPABLE_ERROR;
350 }
351
352 #if defined(LWS_WITH_ACME)
353 /*
354 * mbedtls doesn't support SAN for cert creation. So we use a known-good
355 * tls-sni-01 cert from OpenSSL that worked on Let's Encrypt, and just replace
356 * the pubkey n part and the signature part.
357 *
358 * This will need redoing for tls-sni-02...
359 */
360
361 static uint8_t ss_cert_leadin[] = {
362 0x30, 0x82,
363 0x05, 0x56, /* total length: LEN1 (+2 / +3) (correct for 513 + 512)*/
364
365 0x30, 0x82, /* length: LEN2 (+6 / +7) (correct for 513) */
366 0x03, 0x3e,
367
368 /* addition: v3 cert (+5 bytes)*/
369 0xa0, 0x03,
370 0x02, 0x01, 0x02,
371
372 0x02, 0x01, 0x01,
373 0x30, 0x0d, 0x06, 0x09, 0x2a,
374 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x3f,
375 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x47,
376 0x42, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0b,
377 0x73, 0x6f, 0x6d, 0x65, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x31,
378 0x1a, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x11, 0x74, 0x65,
379 0x6d, 0x70, 0x2e, 0x61, 0x63, 0x6d, 0x65, 0x2e, 0x69, 0x6e, 0x76, 0x61,
380 0x6c, 0x69, 0x64, 0x30, 0x1e, 0x17, 0x0d,
381
382 /* from 2017-10-29 ... */
383 0x31, 0x37, 0x31, 0x30, 0x32, 0x39, 0x31, 0x31, 0x34, 0x39, 0x34, 0x35,
384 0x5a, 0x17, 0x0d,
385
386 /* thru 2049-10-29 we immediately discard the private key, no worries */
387 0x34, 0x39, 0x31, 0x30, 0x32, 0x39, 0x31, 0x32, 0x34, 0x39, 0x34, 0x35,
388 0x5a,
389
390 0x30, 0x3f, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
391 0x02, 0x47, 0x42, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a,
392 0x0c, 0x0b, 0x73, 0x6f, 0x6d, 0x65, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e,
393 0x79, 0x31, 0x1a, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x11,
394 0x74, 0x65, 0x6d, 0x70, 0x2e, 0x61, 0x63, 0x6d, 0x65, 0x2e, 0x69, 0x6e,
395 0x76, 0x61, 0x6c, 0x69, 0x64, 0x30,
396
397 0x82,
398 0x02, 0x22, /* LEN3 (+C3 / C4) */
399 0x30, 0x0d, 0x06,
400 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00,
401 0x03,
402
403 0x82,
404 0x02, 0x0f, /* LEN4 (+D6 / D7) */
405
406 0x00, 0x30, 0x82,
407
408 0x02, 0x0a, /* LEN5 (+ DB / DC) */
409
410 0x02, 0x82,
411
412 //0x02, 0x01, /* length of n in bytes (including leading 00 if any) */
413 },
414
415 /* 1 + (keybits / 8) bytes N */
416
417 ss_cert_san_leadin[] = {
418 /* e - fixed */
419 0x02, 0x03, 0x01, 0x00, 0x01,
420
421 0xa3, 0x5d, 0x30, 0x5b, 0x30, 0x59, 0x06, 0x03, 0x55, 0x1d,
422 0x11, 0x04, 0x52, 0x30, 0x50, /* <-- SAN length + 2 */
423
424 0x82, 0x4e, /* <-- SAN length */
425 },
426
427 /* 78 bytes of SAN (tls-sni-01)
428 0x61, 0x64, 0x34, 0x31, 0x61, 0x66, 0x62, 0x65, 0x30, 0x63, 0x61, 0x34,
429 0x36, 0x34, 0x32, 0x66, 0x30, 0x61, 0x34, 0x34, 0x39, 0x64, 0x39, 0x63,
430 0x61, 0x37, 0x36, 0x65, 0x62, 0x61, 0x61, 0x62, 0x2e, 0x32, 0x38, 0x39,
431 0x34, 0x64, 0x34, 0x31, 0x36, 0x63, 0x39, 0x38, 0x33, 0x66, 0x31, 0x32,
432 0x65, 0x64, 0x37, 0x33, 0x31, 0x61, 0x33, 0x30, 0x66, 0x35, 0x63, 0x34,
433 0x34, 0x37, 0x37, 0x66, 0x65, 0x2e, 0x61, 0x63, 0x6d, 0x65, 0x2e, 0x69,
434 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, */
435
436 /* end of LEN2 area */
437
438 ss_cert_sig_leadin[] = {
439 /* it's saying that the signature is SHA256 + RSA */
440 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
441 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03,
442
443 0x82,
444 0x02, 0x01,
445 0x00,
446 };
447
448 /* (keybits / 8) bytes signature to end of LEN1 area */
449
450 #define SAN_A_LENGTH 78
451
452 int
lws_tls_acme_sni_cert_create(struct lws_vhost *vhost, const char *san_a, const char *san_b)453 lws_tls_acme_sni_cert_create(struct lws_vhost *vhost, const char *san_a,
454 const char *san_b)
455 {
456 int buflen = 0x560;
457 uint8_t *buf = lws_malloc((unsigned int)buflen, "tmp cert buf"), *p = buf, *pkey_asn1;
458 struct lws_genrsa_ctx ctx;
459 struct lws_gencrypto_keyelem el[LWS_GENCRYPTO_RSA_KEYEL_COUNT];
460 uint8_t digest[32];
461 struct lws_genhash_ctx hash_ctx;
462 int pkey_asn1_len = 3 * 1024;
463 int n, m, keybits = lws_plat_recommended_rsa_bits(), adj;
464
465 if (!buf)
466 return 1;
467
468 n = lws_genrsa_new_keypair(vhost->context, &ctx, LGRSAM_PKCS1_1_5,
469 &el[0], keybits);
470 if (n < 0) {
471 lws_genrsa_destroy_elements(&el[0]);
472 goto bail1;
473 }
474
475 n = sizeof(ss_cert_leadin);
476 memcpy(p, ss_cert_leadin, (unsigned int)n);
477 p += n;
478
479 adj = (0x0556 - 0x401) + (keybits / 4) + 1;
480 buf[2] = (uint8_t)(adj >> 8);
481 buf[3] = (uint8_t)(adj & 0xff);
482
483 adj = (0x033e - 0x201) + (keybits / 8) + 1;
484 buf[6] = (uint8_t)(adj >> 8);
485 buf[7] = (uint8_t)(adj & 0xff);
486
487 adj = (0x0222 - 0x201) + (keybits / 8) + 1;
488 buf[0xc3] = (uint8_t)(adj >> 8);
489 buf[0xc4] = (uint8_t)(adj & 0xff);
490
491 adj = (0x020f - 0x201) + (keybits / 8) + 1;
492 buf[0xd6] = (uint8_t)(adj >> 8);
493 buf[0xd7] = (uint8_t)(adj & 0xff);
494
495 adj = (0x020a - 0x201) + (keybits / 8) + 1;
496 buf[0xdb] = (uint8_t)(adj >> 8);
497 buf[0xdc] = (uint8_t)(adj & 0xff);
498
499 *p++ = (uint8_t)(((keybits / 8) + 1) >> 8);
500 *p++ = (uint8_t)(((keybits / 8) + 1) & 0xff);
501
502 /* we need to drop 1 + (keybits / 8) bytes of n in here, 00 + key */
503
504 *p++ = 0x00;
505 memcpy(p, el[LWS_GENCRYPTO_RSA_KEYEL_N].buf, el[LWS_GENCRYPTO_RSA_KEYEL_N].len);
506 p += el[LWS_GENCRYPTO_RSA_KEYEL_N].len;
507
508 memcpy(p, ss_cert_san_leadin, sizeof(ss_cert_san_leadin));
509 p += sizeof(ss_cert_san_leadin);
510
511 /* drop in 78 bytes of san_a */
512
513 memcpy(p, san_a, SAN_A_LENGTH);
514 p += SAN_A_LENGTH;
515 memcpy(p, ss_cert_sig_leadin, sizeof(ss_cert_sig_leadin));
516
517 p[17] = (uint8_t)(((keybits / 8) + 1) >> 8);
518 p[18] = (uint8_t)(((keybits / 8) + 1) & 0xff);
519
520 p += sizeof(ss_cert_sig_leadin);
521
522 /* hash the cert plaintext */
523
524 if (lws_genhash_init(&hash_ctx, LWS_GENHASH_TYPE_SHA256))
525 goto bail2;
526
527 if (lws_genhash_update(&hash_ctx, buf, lws_ptr_diff_size_t(p, buf))) {
528 lws_genhash_destroy(&hash_ctx, NULL);
529
530 goto bail2;
531 }
532 if (lws_genhash_destroy(&hash_ctx, digest))
533 goto bail2;
534
535 /* sign the hash */
536
537 n = lws_genrsa_hash_sign(&ctx, digest, LWS_GENHASH_TYPE_SHA256, p,
538 (size_t)((size_t)buflen - lws_ptr_diff_size_t(p, buf)));
539 if (n < 0)
540 goto bail2;
541 p += n;
542
543 pkey_asn1 = lws_malloc((unsigned int)pkey_asn1_len, "mbed crt tmp");
544 if (!pkey_asn1)
545 goto bail2;
546
547 m = lws_genrsa_render_pkey_asn1(&ctx, 1, pkey_asn1, (size_t)pkey_asn1_len);
548 if (m < 0) {
549 lws_free(pkey_asn1);
550 goto bail2;
551 }
552
553 // lwsl_hexdump_level(LLL_DEBUG, buf, lws_ptr_diff(p, buf));
554 n = SSL_CTX_use_certificate_ASN1(vhost->tls.ssl_ctx,
555 lws_ptr_diff(p, buf), buf);
556 if (n != 1) {
557 lws_free(pkey_asn1);
558 lwsl_err("%s: generated cert failed to load 0x%x\n",
559 __func__, -n);
560 } else {
561 //lwsl_debug("private key\n");
562 //lwsl_hexdump_level(LLL_DEBUG, pkey_asn1, n);
563
564 /* and to use our generated private key */
565 n = SSL_CTX_use_PrivateKey_ASN1(0, vhost->tls.ssl_ctx,
566 pkey_asn1, m);
567 lws_free(pkey_asn1);
568 if (n != 1) {
569 lwsl_err("%s: SSL_CTX_use_PrivateKey_ASN1 failed\n",
570 __func__);
571 }
572 }
573
574 lws_genrsa_destroy(&ctx);
575 lws_genrsa_destroy_elements(&el[0]);
576
577 lws_free(buf);
578
579 return n != 1;
580
581 bail2:
582 lws_genrsa_destroy(&ctx);
583 lws_genrsa_destroy_elements(&el[0]);
584 bail1:
585 lws_free(buf);
586
587 return -1;
588 }
589
590 void
lws_tls_acme_sni_cert_destroy(struct lws_vhost *vhost)591 lws_tls_acme_sni_cert_destroy(struct lws_vhost *vhost)
592 {
593 }
594
595 #if defined(LWS_WITH_JOSE)
596 static int
_rngf(void *context, unsigned char *buf, size_t len)597 _rngf(void *context, unsigned char *buf, size_t len)
598 {
599 if ((size_t)lws_get_random(context, buf, len) == len)
600 return 0;
601
602 return -1;
603 }
604
605 static const char *x5[] = { "C", "ST", "L", "O", "CN" };
606
607 /*
608 * CSR is output formatted as b64url(DER)
609 * Private key is output as a PEM in memory
610 */
611 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)612 lws_tls_acme_sni_csr_create(struct lws_context *context, const char *elements[],
613 uint8_t *dcsr, size_t csr_len, char **privkey_pem,
614 size_t *privkey_len)
615 {
616 mbedtls_x509write_csr csr;
617 mbedtls_pk_context mpk;
618 int buf_size = 4096, n;
619 char subject[200], *p = subject, *end = p + sizeof(subject) - 1;
620 uint8_t *buf = malloc((unsigned int)buf_size); /* malloc because given to user code */
621
622 if (!buf)
623 return -1;
624
625 mbedtls_x509write_csr_init(&csr);
626
627 mbedtls_pk_init(&mpk);
628 if (mbedtls_pk_setup(&mpk, mbedtls_pk_info_from_type(MBEDTLS_PK_RSA))) {
629 lwsl_notice("%s: pk_setup failed\n", __func__);
630 goto fail;
631 }
632
633 n = mbedtls_rsa_gen_key(mbedtls_pk_rsa(mpk), _rngf, context,
634 (unsigned int)lws_plat_recommended_rsa_bits(), 65537);
635 if (n) {
636 lwsl_notice("%s: failed to generate keys\n", __func__);
637
638 goto fail1;
639 }
640
641 /* subject must be formatted like "C=TW,O=warmcat,CN=myserver" */
642
643 for (n = 0; n < (int)LWS_ARRAY_SIZE(x5); n++) {
644 if (p != subject)
645 *p++ = ',';
646 if (elements[n])
647 p += lws_snprintf(p, lws_ptr_diff_size_t(end, p), "%s=%s", x5[n],
648 elements[n]);
649 }
650
651 if (mbedtls_x509write_csr_set_subject_name(&csr, subject))
652 goto fail1;
653
654 mbedtls_x509write_csr_set_key(&csr, &mpk);
655 mbedtls_x509write_csr_set_md_alg(&csr, MBEDTLS_MD_SHA256);
656
657 /*
658 * data is written at the end of the buffer! Use the
659 * return value to determine where you should start
660 * using the buffer
661 */
662 n = mbedtls_x509write_csr_der(&csr, buf, (size_t)buf_size, _rngf, context);
663 if (n < 0) {
664 lwsl_notice("%s: write csr der failed\n", __func__);
665 goto fail1;
666 }
667
668 /* we have it in DER, we need it in b64URL */
669
670 n = lws_jws_base64_enc((char *)(buf + buf_size) - n, (size_t)n,
671 (char *)dcsr, csr_len);
672 if (n < 0)
673 goto fail1;
674
675 /*
676 * okay, the CSR is done, last we need the private key in PEM
677 * re-use the DER CSR buf as the result buffer since we cn do it in
678 * one step
679 */
680
681 if (mbedtls_pk_write_key_pem(&mpk, buf, (size_t)buf_size)) {
682 lwsl_notice("write key pem failed\n");
683 goto fail1;
684 }
685
686 *privkey_pem = (char *)buf;
687 *privkey_len = strlen((const char *)buf);
688
689 mbedtls_pk_free(&mpk);
690 mbedtls_x509write_csr_free(&csr);
691
692 return n;
693
694 fail1:
695 mbedtls_pk_free(&mpk);
696 fail:
697 mbedtls_x509write_csr_free(&csr);
698 free(buf);
699
700 return -1;
701 }
702 #endif
703 #endif
704