• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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