• 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 "private-lib-tls-openssl.h"
27 
28 #if !defined(LWS_PLAT_OPTEE)
29 static int
dec(char c)30 dec(char c)
31 {
32 	return c - '0';
33 }
34 #endif
35 
36 static time_t
lws_tls_openssl_asn1time_to_unix(ASN1_TIME * as)37 lws_tls_openssl_asn1time_to_unix(ASN1_TIME *as)
38 {
39 #if !defined(LWS_PLAT_OPTEE)
40 
41 	const char *p = (const char *)as->data;
42 	struct tm t;
43 
44 	/* [YY]YYMMDDHHMMSSZ */
45 
46 	memset(&t, 0, sizeof(t));
47 
48 	if (strlen(p) == 13) {
49 		t.tm_year = (dec(p[0]) * 10) + dec(p[1]) + 100;
50 		p += 2;
51 	} else {
52 		t.tm_year = (dec(p[0]) * 1000) + (dec(p[1]) * 100) +
53 			    (dec(p[2]) * 10) + dec(p[3]);
54 		p += 4;
55 	}
56 	t.tm_mon = (dec(p[0]) * 10) + dec(p[1]) - 1;
57 	p += 2;
58 	t.tm_mday = (dec(p[0]) * 10) + dec(p[1]) - 1;
59 	p += 2;
60 	t.tm_hour = (dec(p[0]) * 10) + dec(p[1]);
61 	p += 2;
62 	t.tm_min = (dec(p[0]) * 10) + dec(p[1]);
63 	p += 2;
64 	t.tm_sec = (dec(p[0]) * 10) + dec(p[1]);
65 	t.tm_isdst = 0;
66 
67 	return mktime(&t);
68 #else
69 	return (time_t)-1;
70 #endif
71 }
72 
73 int
lws_tls_openssl_cert_info(X509 * x509,enum lws_tls_cert_info type,union lws_tls_cert_info_results * buf,size_t len)74 lws_tls_openssl_cert_info(X509 *x509, enum lws_tls_cert_info type,
75 			  union lws_tls_cert_info_results *buf, size_t len)
76 {
77 	X509_NAME *xn;
78 #if !defined(LWS_PLAT_OPTEE)
79 	char *p;
80 #endif
81 
82 	if (!x509)
83 		return -1;
84 
85 #if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(X509_get_notBefore)
86 #define X509_get_notBefore(x)	X509_getm_notBefore(x)
87 #define X509_get_notAfter(x)	X509_getm_notAfter(x)
88 #endif
89 
90 	switch (type) {
91 	case LWS_TLS_CERT_INFO_VALIDITY_FROM:
92 		buf->time = lws_tls_openssl_asn1time_to_unix(
93 					X509_get_notBefore(x509));
94 		if (buf->time == (time_t)-1)
95 			return -1;
96 		break;
97 
98 	case LWS_TLS_CERT_INFO_VALIDITY_TO:
99 		buf->time = lws_tls_openssl_asn1time_to_unix(
100 					X509_get_notAfter(x509));
101 		if (buf->time == (time_t)-1)
102 			return -1;
103 		break;
104 
105 	case LWS_TLS_CERT_INFO_COMMON_NAME:
106 #if defined(LWS_PLAT_OPTEE)
107 		return -1;
108 #else
109 		xn = X509_get_subject_name(x509);
110 		if (!xn)
111 			return -1;
112 		X509_NAME_oneline(xn, buf->ns.name, (int)len - 2);
113 		p = strstr(buf->ns.name, "/CN=");
114 		if (p)
115 			memmove(buf->ns.name, p + 4, strlen(p + 4) + 1);
116 		buf->ns.len = (int)strlen(buf->ns.name);
117 		return 0;
118 #endif
119 	case LWS_TLS_CERT_INFO_ISSUER_NAME:
120 		xn = X509_get_issuer_name(x509);
121 		if (!xn)
122 			return -1;
123 		X509_NAME_oneline(xn, buf->ns.name, (int)len - 1);
124 		buf->ns.len = (int)strlen(buf->ns.name);
125 		return 0;
126 
127 	case LWS_TLS_CERT_INFO_USAGE:
128 #if defined(LWS_HAVE_X509_get_key_usage)
129 		buf->usage = X509_get_key_usage(x509);
130 		break;
131 #else
132 		return -1;
133 #endif
134 
135 	case LWS_TLS_CERT_INFO_OPAQUE_PUBLIC_KEY:
136 	{
137 #ifndef USE_WOLFSSL
138 		size_t klen = i2d_X509_PUBKEY(X509_get_X509_PUBKEY(x509), NULL);
139 		uint8_t *tmp, *ptmp;
140 
141 		if (!klen || klen > len)
142 			return -1;
143 
144 		tmp = (uint8_t *)OPENSSL_malloc(klen);
145 		if (!tmp)
146 			return -1;
147 
148 		ptmp = tmp;
149 		if (i2d_X509_PUBKEY(
150 			      X509_get_X509_PUBKEY(x509), &ptmp) != (int)klen ||
151 		    !ptmp || lws_ptr_diff(ptmp, tmp) != (int)klen) {
152 			lwsl_info("%s: cert public key extraction failed\n",
153 				  __func__);
154 			if (ptmp)
155 				OPENSSL_free(tmp);
156 
157 			return -1;
158 		}
159 
160 		buf->ns.len = (int)klen;
161 		memcpy(buf->ns.name, tmp, klen);
162 		OPENSSL_free(tmp);
163 #endif
164 		return 0;
165 	}
166 	default:
167 		return -1;
168 	}
169 
170 	return 0;
171 }
172 
173 int
lws_x509_info(struct lws_x509_cert * x509,enum lws_tls_cert_info type,union lws_tls_cert_info_results * buf,size_t len)174 lws_x509_info(struct lws_x509_cert *x509, enum lws_tls_cert_info type,
175 	      union lws_tls_cert_info_results *buf, size_t len)
176 {
177 	return lws_tls_openssl_cert_info(x509->cert, type, buf, len);
178 }
179 
180 #if defined(LWS_WITH_NETWORK)
181 int
lws_tls_vhost_cert_info(struct lws_vhost * vhost,enum lws_tls_cert_info type,union lws_tls_cert_info_results * buf,size_t len)182 lws_tls_vhost_cert_info(struct lws_vhost *vhost, enum lws_tls_cert_info type,
183 		        union lws_tls_cert_info_results *buf, size_t len)
184 {
185 #if defined(LWS_HAVE_SSL_CTX_get0_certificate)
186 	X509 *x509 = SSL_CTX_get0_certificate(vhost->tls.ssl_ctx);
187 
188 	return lws_tls_openssl_cert_info(x509, type, buf, len);
189 #else
190 	lwsl_notice("openssl is too old to support %s\n", __func__);
191 
192 	return -1;
193 #endif
194 }
195 
196 
197 
198 int
lws_tls_peer_cert_info(struct lws * wsi,enum lws_tls_cert_info type,union lws_tls_cert_info_results * buf,size_t len)199 lws_tls_peer_cert_info(struct lws *wsi, enum lws_tls_cert_info type,
200 		       union lws_tls_cert_info_results *buf, size_t len)
201 {
202 	int rc = 0;
203 	X509 *x509;
204 
205 	wsi = lws_get_network_wsi(wsi);
206 
207 	x509 = SSL_get_peer_certificate(wsi->tls.ssl);
208 
209 	if (!x509) {
210 		lwsl_debug("no peer cert\n");
211 
212 		return -1;
213 	}
214 
215 	switch (type) {
216 	case LWS_TLS_CERT_INFO_VERIFIED:
217 		buf->verified = SSL_get_verify_result(wsi->tls.ssl) ==
218 					X509_V_OK;
219 		break;
220 	default:
221 		rc = lws_tls_openssl_cert_info(x509, type, buf, len);
222 	}
223 
224 	X509_free(x509);
225 
226 	return rc;
227 }
228 #endif
229 
230 int
lws_x509_create(struct lws_x509_cert ** x509)231 lws_x509_create(struct lws_x509_cert **x509)
232 {
233 	*x509 = lws_malloc(sizeof(**x509), __func__);
234 	if (*x509)
235 		(*x509)->cert = NULL;
236 
237 	return !(*x509);
238 }
239 
240 int
lws_x509_parse_from_pem(struct lws_x509_cert * x509,const void * pem,size_t len)241 lws_x509_parse_from_pem(struct lws_x509_cert *x509, const void *pem, size_t len)
242 {
243 	BIO* bio = BIO_new(BIO_s_mem());
244 
245 	BIO_write(bio, pem, (int)len);
246 	x509->cert = PEM_read_bio_X509(bio, NULL, NULL, NULL);
247 	BIO_free(bio);
248 	if (!x509->cert) {
249 		lwsl_err("%s: unable to parse PEM cert\n", __func__);
250 		lws_tls_err_describe_clear();
251 
252 		return -1;
253 	}
254 
255 	return 0;
256 }
257 
258 int
lws_x509_verify(struct lws_x509_cert * x509,struct lws_x509_cert * trusted,const char * common_name)259 lws_x509_verify(struct lws_x509_cert *x509, struct lws_x509_cert *trusted,
260 		const char *common_name)
261 {
262 	char c[32], *p;
263 	int ret;
264 
265 	if (common_name) {
266 		X509_NAME *xn = X509_get_subject_name(x509->cert);
267 		if (!xn)
268 			return -1;
269 		X509_NAME_oneline(xn, c, (int)sizeof(c) - 2);
270 		p = strstr(c, "/CN=");
271 		if (p)
272 			p = p + 4;
273 		else
274 			p = c;
275 
276 		if (strcmp(p, common_name)) {
277 			lwsl_err("%s: common name mismatch\n", __func__);
278 			return -1;
279 		}
280 	}
281 
282 	ret = X509_check_issued(trusted->cert, x509->cert);
283 	if (ret != X509_V_OK) {
284 		lwsl_err("%s: unable to verify cert relationship\n", __func__);
285 		lws_tls_err_describe_clear();
286 
287 		return -1;
288 	}
289 
290 	return 0;
291 }
292 
293 #if defined(LWS_WITH_JOSE)
294 int
lws_x509_public_to_jwk(struct lws_jwk * jwk,struct lws_x509_cert * x509,const char * curves,int rsa_min_bits)295 lws_x509_public_to_jwk(struct lws_jwk *jwk, struct lws_x509_cert *x509,
296 		       const char *curves, int rsa_min_bits)
297 {
298 	int id, n, ret = -1, count;
299 	ASN1_OBJECT *obj = NULL;
300 	const EC_POINT *ecpoint;
301 	const EC_GROUP *ecgroup;
302 	EC_KEY *ecpub = NULL;
303 	X509_PUBKEY *pubkey;
304 	RSA *rsapub = NULL;
305 	BIGNUM *mpi[4];
306 	EVP_PKEY *pkey;
307 
308 	memset(jwk, 0, sizeof(*jwk));
309 
310 	pubkey = X509_get_X509_PUBKEY(x509->cert);
311 	if (!pubkey) {
312 		lwsl_err("%s: missing pubkey alg in cert\n", __func__);
313 
314 		goto bail;
315 	}
316 
317 	if (X509_PUBKEY_get0_param(&obj, NULL, NULL, NULL, pubkey) != 1) {
318 		lwsl_err("%s: missing pubkey alg in cert\n", __func__);
319 
320 		goto bail;
321 	}
322 
323 	id = OBJ_obj2nid(obj);
324 	if (id == NID_undef) {
325 		lwsl_err("%s: missing pubkey alg in cert\n", __func__);
326 
327 		goto bail;
328 	}
329 
330 	lwsl_debug("%s: key type %d \"%s\"\n", __func__, id, OBJ_nid2ln(id));
331 
332 	pkey = X509_get_pubkey(x509->cert);
333 	if (!pkey) {
334 		lwsl_notice("%s: unable to extract pubkey", __func__);
335 
336 		goto bail;
337 	}
338 
339 	switch (id) {
340 	case NID_X9_62_id_ecPublicKey:
341 		lwsl_debug("%s: EC key\n", __func__);
342 		jwk->kty = LWS_GENCRYPTO_KTY_EC;
343 
344 		if (!curves) {
345 			lwsl_err("%s: ec curves not allowed\n", __func__);
346 
347 			goto bail1;
348 		}
349 
350 		ecpub = EVP_PKEY_get1_EC_KEY(pkey);
351 		if (!ecpub) {
352 			lwsl_notice("%s: missing EC pubkey\n", __func__);
353 
354 			goto bail1;
355 		}
356 
357 		ecpoint = EC_KEY_get0_public_key(ecpub);
358 		if (!ecpoint) {
359 			lwsl_err("%s: EC_KEY_get0_public_key failed\n", __func__);
360 			goto bail2;
361 		}
362 
363 		ecgroup = EC_KEY_get0_group(ecpub);
364 		if (!ecgroup) {
365 			lwsl_err("%s: EC_KEY_get0_group failed\n", __func__);
366 			goto bail2;
367 		}
368 
369 		/* validate the curve against ones we allow */
370 
371 		if (lws_genec_confirm_curve_allowed_by_tls_id(curves,
372 				EC_GROUP_get_curve_name(ecgroup), jwk))
373 			/* already logged */
374 			goto bail2;
375 
376 		mpi[LWS_GENCRYPTO_EC_KEYEL_CRV] = NULL;
377 		mpi[LWS_GENCRYPTO_EC_KEYEL_X] = BN_new(); /* X */
378 		mpi[LWS_GENCRYPTO_EC_KEYEL_D] = NULL;
379 		mpi[LWS_GENCRYPTO_EC_KEYEL_Y] = BN_new(); /* Y */
380 
381 #if defined(LWS_HAVE_EC_POINT_get_affine_coordinates)
382 		if (EC_POINT_get_affine_coordinates(ecgroup, ecpoint,
383 #else
384 		if (EC_POINT_get_affine_coordinates_GFp(ecgroup, ecpoint,
385 #endif
386 						  mpi[LWS_GENCRYPTO_EC_KEYEL_X],
387 						  mpi[LWS_GENCRYPTO_EC_KEYEL_Y],
388 							  NULL) != 1) {
389 			BN_clear_free(mpi[LWS_GENCRYPTO_EC_KEYEL_X]);
390 			BN_clear_free(mpi[LWS_GENCRYPTO_EC_KEYEL_Y]);
391 			lwsl_err("%s: EC_POINT_get_aff failed\n", __func__);
392 			goto bail2;
393 		}
394 		count = LWS_GENCRYPTO_EC_KEYEL_COUNT;
395 		n = LWS_GENCRYPTO_EC_KEYEL_X;
396 		break;
397 
398 	case NID_rsaEncryption:
399 		lwsl_debug("%s: rsa key\n", __func__);
400 		jwk->kty = LWS_GENCRYPTO_KTY_RSA;
401 
402 		rsapub = EVP_PKEY_get1_RSA(pkey);
403 		if (!rsapub) {
404 			lwsl_notice("%s: missing RSA pubkey\n", __func__);
405 
406 			goto bail1;
407 		}
408 
409 		if ((size_t)RSA_size(rsapub) * 8 < (size_t)rsa_min_bits) {
410 			lwsl_err("%s: key bits %d less than minimum %d\n",
411 				 __func__, RSA_size(rsapub) * 8, rsa_min_bits);
412 
413 			goto bail2;
414 		}
415 
416 #if defined(LWS_HAVE_RSA_SET0_KEY)
417 		/* we don't need d... but the api wants to write it */
418 		RSA_get0_key(rsapub,
419 			    (const BIGNUM **)&mpi[LWS_GENCRYPTO_RSA_KEYEL_N],
420 			    (const BIGNUM **)&mpi[LWS_GENCRYPTO_RSA_KEYEL_E],
421 			    (const BIGNUM **)&mpi[LWS_GENCRYPTO_RSA_KEYEL_D]);
422 #else
423 		mpi[LWS_GENCRYPTO_RSA_KEYEL_E] = rsapub->e;
424 		mpi[LWS_GENCRYPTO_RSA_KEYEL_N] = rsapub->n;
425 		mpi[LWS_GENCRYPTO_RSA_KEYEL_D] = NULL;
426 #endif
427 		count = LWS_GENCRYPTO_RSA_KEYEL_D;
428 		n = LWS_GENCRYPTO_RSA_KEYEL_E;
429 		break;
430 	default:
431 		lwsl_err("%s: unknown NID\n", __func__);
432 		goto bail2;
433 	}
434 
435 	for (; n < count; n++) {
436 		if (!mpi[n])
437 			continue;
438 		jwk->e[n].len = BN_num_bytes(mpi[n]);
439 		jwk->e[n].buf = lws_malloc(jwk->e[n].len, "certkeyimp");
440 		if (!jwk->e[n].buf) {
441 			if (id == NID_X9_62_id_ecPublicKey) {
442 				BN_clear_free(mpi[LWS_GENCRYPTO_EC_KEYEL_X]);
443 				BN_clear_free(mpi[LWS_GENCRYPTO_EC_KEYEL_Y]);
444 			}
445 			goto bail2;
446 		}
447 		BN_bn2bin(mpi[n], jwk->e[n].buf);
448 	}
449 
450 	if (id == NID_X9_62_id_ecPublicKey) {
451 		BN_clear_free(mpi[LWS_GENCRYPTO_EC_KEYEL_X]);
452 		BN_clear_free(mpi[LWS_GENCRYPTO_EC_KEYEL_Y]);
453 	}
454 
455 	ret = 0;
456 
457 bail2:
458 	if (id == NID_X9_62_id_ecPublicKey)
459 		EC_KEY_free(ecpub);
460 	else
461 		RSA_free(rsapub);
462 
463 bail1:
464 	EVP_PKEY_free(pkey);
465 bail:
466 	/* jwk destroy will clean any partial state */
467 	if (ret)
468 		lws_jwk_destroy(jwk);
469 
470 	return ret;
471 }
472 
473 static int
lws_x509_jwk_privkey_pem_pp_cb(char * buf,int size,int rwflag,void * u)474 lws_x509_jwk_privkey_pem_pp_cb(char *buf, int size, int rwflag, void *u)
475 {
476 	const char *pp = (const char *)u;
477 	int n = strlen(pp);
478 
479 	if (n > size - 1)
480 		return -1;
481 
482 	memcpy(buf, pp, n + 1);
483 
484 	return n;
485 }
486 
487 int
lws_x509_jwk_privkey_pem(struct lws_jwk * jwk,void * pem,size_t len,const char * passphrase)488 lws_x509_jwk_privkey_pem(struct lws_jwk *jwk, void *pem, size_t len,
489 			 const char *passphrase)
490 {
491 	BIO* bio = BIO_new(BIO_s_mem());
492 	BIGNUM *mpi, *dummy[6];
493 	EVP_PKEY *pkey = NULL;
494 	EC_KEY *ecpriv = NULL;
495 	RSA *rsapriv = NULL;
496 	const BIGNUM *cmpi;
497 	int n, m, ret = -1;
498 
499 	BIO_write(bio, pem, (int)len);
500 	PEM_read_bio_PrivateKey(bio, &pkey, lws_x509_jwk_privkey_pem_pp_cb,
501 				(void *)passphrase);
502 	BIO_free(bio);
503 	lws_explicit_bzero((void *)pem, len);
504 	if (!pkey) {
505 		lwsl_err("%s: unable to parse PEM privkey\n", __func__);
506 		lws_tls_err_describe_clear();
507 
508 		return -1;
509 	}
510 
511 	/* confirm the key type matches the existing jwk situation */
512 
513 	switch (jwk->kty) {
514 	case LWS_GENCRYPTO_KTY_EC:
515 		if (EVP_PKEY_type(EVP_PKEY_id(pkey)) != EVP_PKEY_EC) {
516 			lwsl_err("%s: jwk is EC but privkey isn't\n", __func__);
517 
518 			goto bail;
519 		}
520 		ecpriv = EVP_PKEY_get1_EC_KEY(pkey);
521 		if (!ecpriv) {
522 			lwsl_notice("%s: missing EC key\n", __func__);
523 
524 			goto bail;
525 		}
526 
527 		cmpi = EC_KEY_get0_private_key(ecpriv);
528 
529 		/* quick size check first */
530 
531 		n = BN_num_bytes(cmpi);
532 		if (jwk->e[LWS_GENCRYPTO_EC_KEYEL_Y].len != (uint32_t)n) {
533 			lwsl_err("%s: jwk key size doesn't match\n", __func__);
534 
535 			goto bail1;
536 		}
537 
538 		/* TODO.. check public curve / group + point */
539 
540 		jwk->e[LWS_GENCRYPTO_EC_KEYEL_D].len = n;
541 		jwk->e[LWS_GENCRYPTO_EC_KEYEL_D].buf = lws_malloc(n, "ec");
542 		if (!jwk->e[LWS_GENCRYPTO_EC_KEYEL_D].buf)
543 			goto bail1;
544 
545 		m = BN_bn2binpad(cmpi, jwk->e[LWS_GENCRYPTO_EC_KEYEL_D].buf,
546 				      jwk->e[LWS_GENCRYPTO_EC_KEYEL_D].len);
547 		if ((unsigned int)m != (unsigned int)BN_num_bytes(cmpi))
548 			goto bail1;
549 
550 		break;
551 
552 	case LWS_GENCRYPTO_KTY_RSA:
553 		if (EVP_PKEY_type(EVP_PKEY_id(pkey)) != EVP_PKEY_RSA) {
554 			lwsl_err("%s: RSA jwk, non-RSA privkey\n", __func__);
555 
556 			goto bail;
557 		}
558 		rsapriv = EVP_PKEY_get1_RSA(pkey);
559 		if (!rsapriv) {
560 			lwsl_notice("%s: missing RSA key\n", __func__);
561 
562 			goto bail;
563 		}
564 
565 #if defined(LWS_HAVE_RSA_SET0_KEY)
566 		RSA_get0_key(rsapriv, (const BIGNUM **)&dummy[0], /* n */
567 				      (const BIGNUM **)&dummy[1], /* e */
568 				      (const BIGNUM **)&mpi);	  /* d */
569 		RSA_get0_factors(rsapriv, (const BIGNUM **)&dummy[4],  /* p */
570 					  (const BIGNUM **)&dummy[5]); /* q */
571 #else
572 		dummy[0] = rsapriv->n;
573 		dummy[1] = rsapriv->e;
574 		dummy[4] = rsapriv->p;
575 		dummy[5] = rsapriv->q;
576 		mpi = rsapriv->d;
577 #endif
578 
579 		/* quick size check first */
580 
581 		n = BN_num_bytes(mpi);
582 		if (jwk->e[LWS_GENCRYPTO_RSA_KEYEL_N].len != (uint32_t)n) {
583 			lwsl_err("%s: jwk key size doesn't match\n", __func__);
584 
585 			goto bail1;
586 		}
587 
588 		/* then check that n & e match what we got from the cert */
589 
590 		dummy[2] = BN_bin2bn(jwk->e[LWS_GENCRYPTO_RSA_KEYEL_N].buf,
591 				     jwk->e[LWS_GENCRYPTO_RSA_KEYEL_N].len,
592 				     NULL);
593 		dummy[3] = BN_bin2bn(jwk->e[LWS_GENCRYPTO_RSA_KEYEL_E].buf,
594 				     jwk->e[LWS_GENCRYPTO_RSA_KEYEL_E].len,
595 				     NULL);
596 
597 		m = BN_cmp(dummy[2], dummy[0]) | BN_cmp(dummy[3], dummy[1]);
598 		BN_clear_free(dummy[2]);
599 		BN_clear_free(dummy[3]);
600 		if (m) {
601 			lwsl_err("%s: privkey doesn't match jwk pubkey\n",
602 				 __func__);
603 
604 			goto bail1;
605 		}
606 
607 		/* accept d from the PEM privkey into the JWK */
608 
609 		jwk->e[LWS_GENCRYPTO_RSA_KEYEL_D].len = n;
610 		jwk->e[LWS_GENCRYPTO_RSA_KEYEL_D].buf = lws_malloc(n, "privjk");
611 		if (!jwk->e[LWS_GENCRYPTO_RSA_KEYEL_D].buf)
612 			goto bail1;
613 
614 		BN_bn2bin(mpi, jwk->e[LWS_GENCRYPTO_RSA_KEYEL_D].buf);
615 
616 		/* accept p and q from the PEM privkey into the JWK */
617 
618 		jwk->e[LWS_GENCRYPTO_RSA_KEYEL_P].len = BN_num_bytes(dummy[4]);
619 		jwk->e[LWS_GENCRYPTO_RSA_KEYEL_P].buf = lws_malloc(n, "privjk");
620 		if (!jwk->e[LWS_GENCRYPTO_RSA_KEYEL_P].buf) {
621 			lws_free_set_NULL(jwk->e[LWS_GENCRYPTO_RSA_KEYEL_D].buf);
622 			goto bail1;
623 		}
624 		BN_bn2bin(dummy[4], jwk->e[LWS_GENCRYPTO_RSA_KEYEL_P].buf);
625 
626 		jwk->e[LWS_GENCRYPTO_RSA_KEYEL_Q].len = BN_num_bytes(dummy[5]);
627 		jwk->e[LWS_GENCRYPTO_RSA_KEYEL_Q].buf = lws_malloc(n, "privjk");
628 		if (!jwk->e[LWS_GENCRYPTO_RSA_KEYEL_Q].buf) {
629 			lws_free_set_NULL(jwk->e[LWS_GENCRYPTO_RSA_KEYEL_D].buf);
630 			lws_free_set_NULL(jwk->e[LWS_GENCRYPTO_RSA_KEYEL_P].buf);
631 			goto bail1;
632 		}
633 		BN_bn2bin(dummy[5], jwk->e[LWS_GENCRYPTO_RSA_KEYEL_Q].buf);
634 		break;
635 	default:
636 		lwsl_err("%s: JWK has unknown kty %d\n", __func__, jwk->kty);
637 		return -1;
638 	}
639 
640 	ret = 0;
641 
642 bail1:
643 	if (jwk->kty == LWS_GENCRYPTO_KTY_EC)
644 		EC_KEY_free(ecpriv);
645 	else
646 		RSA_free(rsapriv);
647 
648 bail:
649 	EVP_PKEY_free(pkey);
650 
651 	return ret;
652 }
653 #endif
654 
655 void
lws_x509_destroy(struct lws_x509_cert ** x509)656 lws_x509_destroy(struct lws_x509_cert **x509)
657 {
658 	if (!*x509)
659 		return;
660 
661 	if ((*x509)->cert) {
662 		X509_free((*x509)->cert);
663 		(*x509)->cert = NULL;
664 	}
665 
666 	lws_free_set_NULL(*x509);
667 }
668