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