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#define WIN32_LEAN_AND_MEAN
26#include "private-lib-core.h"
27#include "private-lib-tls-openssl.h"
28
29#if !defined(LWS_PLAT_OPTEE)
30static int
31dec(char c)
32{
33	return c - '0';
34}
35#endif
36
37static time_t
38lws_tls_openssl_asn1time_to_unix(ASN1_TIME *as)
39{
40#if !defined(LWS_PLAT_OPTEE)
41
42	const char *p = (const char *)as->data;
43	struct tm t;
44
45	/* [YY]YYMMDDHHMMSSZ */
46
47	memset(&t, 0, sizeof(t));
48
49	if (strlen(p) == 13) {
50		t.tm_year = (dec(p[0]) * 10) + dec(p[1]) + 100;
51		p += 2;
52	} else {
53		t.tm_year = (dec(p[0]) * 1000) + (dec(p[1]) * 100) +
54			    (dec(p[2]) * 10) + dec(p[3]);
55		p += 4;
56	}
57	t.tm_mon = (dec(p[0]) * 10) + dec(p[1]) - 1;
58	p += 2;
59	t.tm_mday = (dec(p[0]) * 10) + dec(p[1]) - 1;
60	p += 2;
61	t.tm_hour = (dec(p[0]) * 10) + dec(p[1]);
62	p += 2;
63	t.tm_min = (dec(p[0]) * 10) + dec(p[1]);
64	p += 2;
65	t.tm_sec = (dec(p[0]) * 10) + dec(p[1]);
66	t.tm_isdst = 0;
67
68	return mktime(&t);
69#else
70	return (time_t)-1;
71#endif
72}
73
74#if defined(USE_WOLFSSL)
75#define AUTHORITY_KEYID WOLFSSL_AUTHORITY_KEYID
76#endif
77
78int
79lws_tls_openssl_cert_info(X509 *x509, enum lws_tls_cert_info type,
80			  union lws_tls_cert_info_results *buf, size_t len)
81{
82#ifndef USE_WOLFSSL
83	const unsigned char *dp;
84	ASN1_OCTET_STRING *val;
85	AUTHORITY_KEYID *akid;
86	X509_EXTENSION *ext;
87	int tag, xclass, r = 1;
88	long xlen, loc;
89#endif
90	X509_NAME *xn;
91#if !defined(LWS_PLAT_OPTEE)
92	char *p;
93#endif
94
95	buf->ns.len = 0;
96
97	if (!x509)
98		return -1;
99	if (!len)
100		len = sizeof(buf->ns.name);
101
102#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(X509_get_notBefore)
103#define X509_get_notBefore(x)	X509_getm_notBefore(x)
104#define X509_get_notAfter(x)	X509_getm_notAfter(x)
105#endif
106
107	switch (type) {
108	case LWS_TLS_CERT_INFO_VALIDITY_FROM:
109		buf->time = lws_tls_openssl_asn1time_to_unix(
110					X509_get_notBefore(x509));
111		if (buf->time == (time_t)-1)
112			return -1;
113		break;
114
115	case LWS_TLS_CERT_INFO_VALIDITY_TO:
116		buf->time = lws_tls_openssl_asn1time_to_unix(
117					X509_get_notAfter(x509));
118		if (buf->time == (time_t)-1)
119			return -1;
120		break;
121
122	case LWS_TLS_CERT_INFO_COMMON_NAME:
123#if defined(LWS_PLAT_OPTEE)
124		return -1;
125#else
126		xn = X509_get_subject_name(x509);
127		if (!xn)
128			return -1;
129		X509_NAME_oneline(xn, buf->ns.name, (int)len - 2);
130		p = strstr(buf->ns.name, "/CN=");
131		if (p)
132			memmove(buf->ns.name, p + 4, strlen(p + 4) + 1);
133		buf->ns.len = (int)strlen(buf->ns.name);
134		return 0;
135#endif
136	case LWS_TLS_CERT_INFO_ISSUER_NAME:
137		xn = X509_get_issuer_name(x509);
138		if (!xn)
139			return -1;
140		X509_NAME_oneline(xn, buf->ns.name, (int)len - 1);
141		buf->ns.len = (int)strlen(buf->ns.name);
142		return 0;
143
144	case LWS_TLS_CERT_INFO_USAGE:
145#if defined(LWS_HAVE_X509_get_key_usage)
146		buf->usage = X509_get_key_usage(x509);
147		break;
148#else
149		return -1;
150#endif
151
152	case LWS_TLS_CERT_INFO_OPAQUE_PUBLIC_KEY:
153	{
154#ifndef USE_WOLFSSL
155		size_t klen = (unsigned int)i2d_X509_PUBKEY(X509_get_X509_PUBKEY(x509), NULL);
156		uint8_t *tmp, *ptmp;
157
158		if (!klen || klen > len)
159			return -1;
160
161		tmp = (uint8_t *)OPENSSL_malloc(klen);
162		if (!tmp)
163			return -1;
164
165		ptmp = tmp;
166		if (i2d_X509_PUBKEY(
167			      X509_get_X509_PUBKEY(x509), &ptmp) != (int)klen ||
168		    !ptmp || lws_ptr_diff(ptmp, tmp) != (int)klen) {
169			lwsl_info("%s: cert public key extraction failed\n",
170				  __func__);
171			if (ptmp)
172				OPENSSL_free(tmp);
173
174			return -1;
175		}
176
177		buf->ns.len = (int)klen;
178		memcpy(buf->ns.name, tmp, klen);
179		OPENSSL_free(tmp);
180#endif
181		return 0;
182	}
183	case LWS_TLS_CERT_INFO_DER_RAW:
184	{
185		int der_len = i2d_X509(x509, NULL);
186		uint8_t *tmp = (uint8_t *)buf->ns.name;
187
188		buf->ns.len = der_len < 0 ? 0 : der_len;
189
190		if (der_len < 0 || (size_t)der_len > len)
191			return -1;
192
193		der_len = i2d_X509(x509, &tmp);
194		if (der_len < 0)
195			return -1;
196
197		return 0;
198	}
199
200#ifndef USE_WOLFSSL
201
202	case LWS_TLS_CERT_INFO_AUTHORITY_KEY_ID:
203		loc = X509_get_ext_by_NID(x509, NID_authority_key_identifier, -1);
204		if (loc < 0)
205			return 1;
206
207		ext = X509_get_ext(x509, (int)loc);
208		if (!ext)
209			return 1;
210#ifndef USE_WOLFSSL
211		akid = (AUTHORITY_KEYID *)X509V3_EXT_d2i(ext);
212#else
213		akid = (AUTHORITY_KEYID *)wolfSSL_X509V3_EXT_d2i(ext);
214#endif
215		if (!akid || !akid->keyid)
216			return 1;
217		val = akid->keyid;
218		dp = (const unsigned char *)val->data;
219		xlen = val->length;
220
221		buf->ns.len = (int)xlen;
222		if (len < (size_t)buf->ns.len)
223			return -1;
224
225		memcpy(buf->ns.name, dp, (size_t)buf->ns.len);
226
227		AUTHORITY_KEYID_free(akid);
228		break;
229
230	case LWS_TLS_CERT_INFO_AUTHORITY_KEY_ID_ISSUER:
231		loc = X509_get_ext_by_NID(x509, NID_authority_key_identifier, -1);
232		if (loc < 0)
233			return 1;
234
235		ext = X509_get_ext(x509, (int)loc);
236		if (!ext)
237			return 1;
238
239#ifndef USE_WOLFSSL
240		akid = (AUTHORITY_KEYID *)X509V3_EXT_d2i(ext);
241#else
242		akid = (AUTHORITY_KEYID *)wolfSSL_X509V3_EXT_d2i(ext);
243#endif
244		if (!akid || !akid->issuer)
245			return 1;
246
247#if defined(LWS_HAVE_OPENSSL_STACK)
248		{
249			const X509V3_EXT_METHOD* method = X509V3_EXT_get(ext);
250			STACK_OF(CONF_VALUE) *cv;
251			int j;
252
253			cv = i2v_GENERAL_NAMES((X509V3_EXT_METHOD*)method, akid->issuer, NULL);
254			if (!cv)
255				goto bail_ak;
256
257		        for (j = 0; j < OPENSSL_sk_num((const OPENSSL_STACK *)&cv); j++) {
258		            CONF_VALUE *nval = OPENSSL_sk_value((const OPENSSL_STACK *)&cv, j);
259		            size_t ln = (nval->name ? strlen(nval->name) : 0),
260		        	   lv = (nval->value ? strlen(nval->value) : 0),
261		        	   l = ln + lv;
262
263		            if (len > l) {
264		        	    if (nval->name)
265		        		    memcpy(buf->ns.name + buf->ns.len, nval->name, ln);
266		        	    if (nval->value)
267		        		    memcpy(buf->ns.name + buf->ns.len + ln, nval->value, lv);
268		        	    buf->ns.len = (int)((size_t)buf->ns.len + l);
269		        	    len -= l;
270		        	    buf->ns.name[buf->ns.len] = '\0';
271
272		        	    r = 0;
273		            }
274		        }
275		}
276
277bail_ak:
278#endif
279		AUTHORITY_KEYID_free(akid);
280
281		return r;
282
283	case LWS_TLS_CERT_INFO_AUTHORITY_KEY_ID_SERIAL:
284		loc = X509_get_ext_by_NID(x509, NID_authority_key_identifier, -1);
285		if (loc < 0)
286			return 1;
287
288		ext = X509_get_ext(x509, (int)loc);
289		if (!ext)
290			return 1;
291		akid = (AUTHORITY_KEYID *)X509V3_EXT_d2i(ext);
292		if (!akid || !akid->serial)
293			return 1;
294
295#if 0
296		// need to handle blobs, and ASN1_INTEGER_get_uint64 not
297		// available on older openssl
298		{
299			uint64_t res;
300			if (ASN1_INTEGER_get_uint64(&res, akid->serial) != 1)
301				break;
302			buf->ns.len = lws_snprintf(buf->ns.name, len, "%llu",
303					(unsigned long long)res);
304		}
305#endif
306		break;
307
308	case LWS_TLS_CERT_INFO_SUBJECT_KEY_ID:
309
310		loc = X509_get_ext_by_NID(x509, NID_subject_key_identifier, -1);
311		if (loc < 0)
312			return 1;
313
314		ext = X509_get_ext(x509, (int)loc);
315		if (!ext)
316			return 1;
317
318		val = X509_EXTENSION_get_data(ext);
319		if (!val)
320			return 1;
321
322#if defined(USE_WOLFSSL)
323		return 1;
324#else
325		dp = (const unsigned char *)val->data;
326
327		if (ASN1_get_object(&dp, &xlen,
328				    &tag, &xclass, val->length) & 0x80)
329			return -1;
330
331		if (tag != V_ASN1_OCTET_STRING) {
332			lwsl_notice("not octet string %d\n", (int)tag);
333			return 1;
334		}
335#endif
336		buf->ns.len = (int)xlen;
337		if (len < (size_t)buf->ns.len)
338			return -1;
339
340		memcpy(buf->ns.name, dp, (size_t)buf->ns.len);
341		break;
342#endif
343
344	default:
345		return -1;
346	}
347
348	return 0;
349}
350
351int
352lws_x509_info(struct lws_x509_cert *x509, enum lws_tls_cert_info type,
353	      union lws_tls_cert_info_results *buf, size_t len)
354{
355	return lws_tls_openssl_cert_info(x509->cert, type, buf, len);
356}
357
358#if defined(LWS_WITH_NETWORK)
359int
360lws_tls_vhost_cert_info(struct lws_vhost *vhost, enum lws_tls_cert_info type,
361		        union lws_tls_cert_info_results *buf, size_t len)
362{
363#if defined(LWS_HAVE_SSL_CTX_get0_certificate)
364	X509 *x509 = SSL_CTX_get0_certificate(vhost->tls.ssl_ctx);
365
366	return lws_tls_openssl_cert_info(x509, type, buf, len);
367#else
368	lwsl_notice("openssl is too old to support %s\n", __func__);
369
370	return -1;
371#endif
372}
373
374
375
376int
377lws_tls_peer_cert_info(struct lws *wsi, enum lws_tls_cert_info type,
378		       union lws_tls_cert_info_results *buf, size_t len)
379{
380	int rc = 0;
381	X509 *x509;
382
383	wsi = lws_get_network_wsi(wsi);
384
385	x509 = SSL_get_peer_certificate(wsi->tls.ssl);
386
387	if (!x509) {
388		lwsl_debug("no peer cert\n");
389
390		return -1;
391	}
392
393	switch (type) {
394	case LWS_TLS_CERT_INFO_VERIFIED:
395		buf->verified = SSL_get_verify_result(wsi->tls.ssl) ==
396					X509_V_OK;
397		break;
398	default:
399		rc = lws_tls_openssl_cert_info(x509, type, buf, len);
400	}
401
402	X509_free(x509);
403
404	return rc;
405}
406#endif
407
408int
409lws_x509_create(struct lws_x509_cert **x509)
410{
411	*x509 = lws_malloc(sizeof(**x509), __func__);
412	if (*x509)
413		(*x509)->cert = NULL;
414
415	return !(*x509);
416}
417
418int
419lws_x509_parse_from_pem(struct lws_x509_cert *x509, const void *pem, size_t len)
420{
421	BIO* bio = BIO_new(BIO_s_mem());
422
423	BIO_write(bio, pem, (int)len);
424	x509->cert = PEM_read_bio_X509(bio, NULL, NULL, NULL);
425	BIO_free(bio);
426	if (!x509->cert) {
427		lwsl_err("%s: unable to parse PEM cert\n", __func__);
428		lws_tls_err_describe_clear();
429
430		return -1;
431	}
432
433	return 0;
434}
435
436int
437lws_x509_verify(struct lws_x509_cert *x509, struct lws_x509_cert *trusted,
438		const char *common_name)
439{
440	char c[32], *p;
441	int ret;
442
443	if (common_name) {
444		X509_NAME *xn = X509_get_subject_name(x509->cert);
445		if (!xn)
446			return -1;
447		X509_NAME_oneline(xn, c, (int)sizeof(c) - 2);
448		p = strstr(c, "/CN=");
449		if (p)
450			p = p + 4;
451		else
452			p = c;
453
454		if (strcmp(p, common_name)) {
455			lwsl_err("%s: common name mismatch\n", __func__);
456			return -1;
457		}
458	}
459
460	ret = X509_check_issued(trusted->cert, x509->cert);
461	if (ret != X509_V_OK) {
462		lwsl_err("%s: unable to verify cert relationship\n", __func__);
463		lws_tls_err_describe_clear();
464
465		return -1;
466	}
467
468	return 0;
469}
470
471#if defined(LWS_WITH_JOSE)
472int
473lws_x509_public_to_jwk(struct lws_jwk *jwk, struct lws_x509_cert *x509,
474		       const char *curves, int rsa_min_bits)
475{
476	int id, n, ret = -1, count;
477	ASN1_OBJECT *obj = NULL;
478	const EC_POINT *ecpoint;
479	const EC_GROUP *ecgroup;
480	EC_KEY *ecpub = NULL;
481	X509_PUBKEY *pubkey;
482	RSA *rsapub = NULL;
483	BIGNUM *mpi[4];
484	EVP_PKEY *pkey;
485
486	memset(jwk, 0, sizeof(*jwk));
487
488	pubkey = X509_get_X509_PUBKEY(x509->cert);
489	if (!pubkey) {
490		lwsl_err("%s: missing pubkey alg in cert\n", __func__);
491
492		goto bail;
493	}
494
495	if (X509_PUBKEY_get0_param(&obj, NULL, NULL, NULL, pubkey) != 1) {
496		lwsl_err("%s: missing pubkey alg in cert\n", __func__);
497
498		goto bail;
499	}
500
501	id = OBJ_obj2nid(obj);
502	if (id == NID_undef) {
503		lwsl_err("%s: missing pubkey alg in cert\n", __func__);
504
505		goto bail;
506	}
507
508	lwsl_debug("%s: key type %d \"%s\"\n", __func__, id, OBJ_nid2ln(id));
509
510	pkey = X509_get_pubkey(x509->cert);
511	if (!pkey) {
512		lwsl_notice("%s: unable to extract pubkey", __func__);
513
514		goto bail;
515	}
516
517	switch (id) {
518	case NID_X9_62_id_ecPublicKey:
519		lwsl_debug("%s: EC key\n", __func__);
520		jwk->kty = LWS_GENCRYPTO_KTY_EC;
521
522		if (!curves) {
523			lwsl_err("%s: ec curves not allowed\n", __func__);
524
525			goto bail1;
526		}
527
528		ecpub = EVP_PKEY_get1_EC_KEY(pkey);
529		if (!ecpub) {
530			lwsl_notice("%s: missing EC pubkey\n", __func__);
531
532			goto bail1;
533		}
534
535		ecpoint = EC_KEY_get0_public_key(ecpub);
536		if (!ecpoint) {
537			lwsl_err("%s: EC_KEY_get0_public_key failed\n", __func__);
538			goto bail2;
539		}
540
541		ecgroup = EC_KEY_get0_group(ecpub);
542		if (!ecgroup) {
543			lwsl_err("%s: EC_KEY_get0_group failed\n", __func__);
544			goto bail2;
545		}
546
547		/* validate the curve against ones we allow */
548
549		if (lws_genec_confirm_curve_allowed_by_tls_id(curves,
550				EC_GROUP_get_curve_name(ecgroup), jwk))
551			/* already logged */
552			goto bail2;
553
554		mpi[LWS_GENCRYPTO_EC_KEYEL_CRV] = NULL;
555		mpi[LWS_GENCRYPTO_EC_KEYEL_X] = BN_new(); /* X */
556		mpi[LWS_GENCRYPTO_EC_KEYEL_D] = NULL;
557		mpi[LWS_GENCRYPTO_EC_KEYEL_Y] = BN_new(); /* Y */
558
559#if defined(LWS_HAVE_EC_POINT_get_affine_coordinates)
560		if (EC_POINT_get_affine_coordinates(ecgroup, ecpoint,
561#else
562		if (EC_POINT_get_affine_coordinates_GFp(ecgroup, ecpoint,
563#endif
564						  mpi[LWS_GENCRYPTO_EC_KEYEL_X],
565						  mpi[LWS_GENCRYPTO_EC_KEYEL_Y],
566							  NULL) != 1) {
567			BN_clear_free(mpi[LWS_GENCRYPTO_EC_KEYEL_X]);
568			BN_clear_free(mpi[LWS_GENCRYPTO_EC_KEYEL_Y]);
569			lwsl_err("%s: EC_POINT_get_aff failed\n", __func__);
570			goto bail2;
571		}
572		count = LWS_GENCRYPTO_EC_KEYEL_COUNT;
573		n = LWS_GENCRYPTO_EC_KEYEL_X;
574		break;
575
576	case NID_rsaEncryption:
577		lwsl_debug("%s: rsa key\n", __func__);
578		jwk->kty = LWS_GENCRYPTO_KTY_RSA;
579
580		rsapub = EVP_PKEY_get1_RSA(pkey);
581		if (!rsapub) {
582			lwsl_notice("%s: missing RSA pubkey\n", __func__);
583
584			goto bail1;
585		}
586
587		if ((size_t)RSA_size(rsapub) * 8 < (size_t)rsa_min_bits) {
588			lwsl_err("%s: key bits %d less than minimum %d\n",
589				 __func__, RSA_size(rsapub) * 8, rsa_min_bits);
590
591			goto bail2;
592		}
593
594#if defined(LWS_HAVE_RSA_SET0_KEY)
595		/* we don't need d... but the api wants to write it */
596		RSA_get0_key(rsapub,
597			    (const BIGNUM **)&mpi[LWS_GENCRYPTO_RSA_KEYEL_N],
598			    (const BIGNUM **)&mpi[LWS_GENCRYPTO_RSA_KEYEL_E],
599			    (const BIGNUM **)&mpi[LWS_GENCRYPTO_RSA_KEYEL_D]);
600#else
601		mpi[LWS_GENCRYPTO_RSA_KEYEL_E] = rsapub->e;
602		mpi[LWS_GENCRYPTO_RSA_KEYEL_N] = rsapub->n;
603		mpi[LWS_GENCRYPTO_RSA_KEYEL_D] = NULL;
604#endif
605		count = LWS_GENCRYPTO_RSA_KEYEL_D;
606		n = LWS_GENCRYPTO_RSA_KEYEL_E;
607		break;
608	default:
609		lwsl_err("%s: unknown NID\n", __func__);
610		goto bail2;
611	}
612
613	for (; n < count; n++) {
614		if (!mpi[n])
615			continue;
616		jwk->e[n].len = (unsigned int)BN_num_bytes(mpi[n]);
617		jwk->e[n].buf = lws_malloc(jwk->e[n].len, "certkeyimp");
618		if (!jwk->e[n].buf) {
619			if (id == NID_X9_62_id_ecPublicKey) {
620				BN_clear_free(mpi[LWS_GENCRYPTO_EC_KEYEL_X]);
621				BN_clear_free(mpi[LWS_GENCRYPTO_EC_KEYEL_Y]);
622			}
623			goto bail2;
624		}
625		BN_bn2bin(mpi[n], jwk->e[n].buf);
626	}
627
628	if (id == NID_X9_62_id_ecPublicKey) {
629		BN_clear_free(mpi[LWS_GENCRYPTO_EC_KEYEL_X]);
630		BN_clear_free(mpi[LWS_GENCRYPTO_EC_KEYEL_Y]);
631	}
632
633	ret = 0;
634
635bail2:
636	if (id == NID_X9_62_id_ecPublicKey)
637		EC_KEY_free(ecpub);
638	else
639		RSA_free(rsapub);
640
641bail1:
642	EVP_PKEY_free(pkey);
643bail:
644	/* jwk destroy will clean any partial state */
645	if (ret)
646		lws_jwk_destroy(jwk);
647
648	return ret;
649}
650
651static int
652lws_x509_jwk_privkey_pem_pp_cb(char *buf, int size, int rwflag, void *u)
653{
654	const char *pp = (const char *)u;
655	size_t n = strlen(pp);
656
657	if ((int)n > size - 1)
658		return -1;
659
660	memcpy(buf, pp, n + 1);
661
662	return (int)n;
663}
664
665int
666lws_x509_jwk_privkey_pem(struct lws_context *cx, struct lws_jwk *jwk,
667			 void *pem, size_t len, const char *passphrase)
668{
669	BIO* bio = BIO_new(BIO_s_mem());
670	BIGNUM *mpi, *dummy[6];
671	EVP_PKEY *pkey = NULL;
672	EC_KEY *ecpriv = NULL;
673	RSA *rsapriv = NULL;
674	const BIGNUM *cmpi;
675	int n, m, ret = -1;
676
677	BIO_write(bio, pem, (int)len);
678	PEM_read_bio_PrivateKey(bio, &pkey, lws_x509_jwk_privkey_pem_pp_cb,
679				(void *)passphrase);
680	BIO_free(bio);
681	lws_explicit_bzero((void *)pem, len);
682	if (!pkey) {
683		lwsl_err("%s: unable to parse PEM privkey\n", __func__);
684		lws_tls_err_describe_clear();
685
686		return -1;
687	}
688
689	/* confirm the key type matches the existing jwk situation */
690
691	switch (jwk->kty) {
692	case LWS_GENCRYPTO_KTY_EC:
693		if (EVP_PKEY_type(EVP_PKEY_id(pkey)) != EVP_PKEY_EC) {
694			lwsl_err("%s: jwk is EC but privkey isn't\n", __func__);
695
696			goto bail;
697		}
698		ecpriv = EVP_PKEY_get1_EC_KEY(pkey);
699		if (!ecpriv) {
700			lwsl_notice("%s: missing EC key\n", __func__);
701
702			goto bail;
703		}
704
705		cmpi = EC_KEY_get0_private_key(ecpriv);
706
707		/* quick size check first */
708
709		n = BN_num_bytes(cmpi);
710		if (jwk->e[LWS_GENCRYPTO_EC_KEYEL_Y].len != (uint32_t)n) {
711			lwsl_err("%s: jwk key size doesn't match\n", __func__);
712
713			goto bail1;
714		}
715
716		/* TODO.. check public curve / group + point */
717
718		jwk->e[LWS_GENCRYPTO_EC_KEYEL_D].len = (unsigned int)n;
719		jwk->e[LWS_GENCRYPTO_EC_KEYEL_D].buf = lws_malloc((unsigned int)n, "ec");
720		if (!jwk->e[LWS_GENCRYPTO_EC_KEYEL_D].buf)
721			goto bail1;
722
723		m = BN_bn2binpad(cmpi, jwk->e[LWS_GENCRYPTO_EC_KEYEL_D].buf,
724				      (int32_t)jwk->e[LWS_GENCRYPTO_EC_KEYEL_D].len);
725		if ((unsigned int)m != (unsigned int)BN_num_bytes(cmpi))
726			goto bail1;
727
728		break;
729
730	case LWS_GENCRYPTO_KTY_RSA:
731		if (EVP_PKEY_type(EVP_PKEY_id(pkey)) != EVP_PKEY_RSA) {
732			lwsl_err("%s: RSA jwk, non-RSA privkey\n", __func__);
733
734			goto bail;
735		}
736		rsapriv = EVP_PKEY_get1_RSA(pkey);
737		if (!rsapriv) {
738			lwsl_notice("%s: missing RSA key\n", __func__);
739
740			goto bail;
741		}
742
743#if defined(LWS_HAVE_RSA_SET0_KEY) && !defined(USE_WOLFSSL)
744		RSA_get0_key(rsapriv, (const BIGNUM **)&dummy[0], /* n */
745				      (const BIGNUM **)&dummy[1], /* e */
746				      (const BIGNUM **)&mpi);	  /* d */
747		RSA_get0_factors(rsapriv, (const BIGNUM **)&dummy[4],  /* p */
748					  (const BIGNUM **)&dummy[5]); /* q */
749#else
750		dummy[0] = rsapriv->n;
751		dummy[1] = rsapriv->e;
752		dummy[4] = rsapriv->p;
753		dummy[5] = rsapriv->q;
754		mpi = rsapriv->d;
755#endif
756
757		/* quick size check first */
758
759		n = BN_num_bytes(mpi);
760		if (jwk->e[LWS_GENCRYPTO_RSA_KEYEL_N].len != (uint32_t)n) {
761			lwsl_err("%s: jwk key size doesn't match\n", __func__);
762
763			goto bail1;
764		}
765
766		/* then check that n & e match what we got from the cert */
767
768		dummy[2] = BN_bin2bn(jwk->e[LWS_GENCRYPTO_RSA_KEYEL_N].buf,
769				     (int32_t)jwk->e[LWS_GENCRYPTO_RSA_KEYEL_N].len,
770				     NULL);
771		dummy[3] = BN_bin2bn(jwk->e[LWS_GENCRYPTO_RSA_KEYEL_E].buf,
772				     (int32_t)jwk->e[LWS_GENCRYPTO_RSA_KEYEL_E].len,
773				     NULL);
774
775		m = BN_cmp(dummy[2], dummy[0]) | BN_cmp(dummy[3], dummy[1]);
776		BN_clear_free(dummy[2]);
777		BN_clear_free(dummy[3]);
778		if (m) {
779			lwsl_err("%s: privkey doesn't match jwk pubkey\n",
780				 __func__);
781
782			goto bail1;
783		}
784
785		/* accept d from the PEM privkey into the JWK */
786
787		jwk->e[LWS_GENCRYPTO_RSA_KEYEL_D].len = (unsigned int)n;
788		jwk->e[LWS_GENCRYPTO_RSA_KEYEL_D].buf = lws_malloc((unsigned int)n, "privjk");
789		if (!jwk->e[LWS_GENCRYPTO_RSA_KEYEL_D].buf)
790			goto bail1;
791
792		BN_bn2bin(mpi, jwk->e[LWS_GENCRYPTO_RSA_KEYEL_D].buf);
793
794		/* accept p and q from the PEM privkey into the JWK */
795
796		jwk->e[LWS_GENCRYPTO_RSA_KEYEL_P].len = (unsigned int)BN_num_bytes(dummy[4]);
797		jwk->e[LWS_GENCRYPTO_RSA_KEYEL_P].buf = lws_malloc((unsigned int)n, "privjk");
798		if (!jwk->e[LWS_GENCRYPTO_RSA_KEYEL_P].buf) {
799			lws_free_set_NULL(jwk->e[LWS_GENCRYPTO_RSA_KEYEL_D].buf);
800			goto bail1;
801		}
802		BN_bn2bin(dummy[4], jwk->e[LWS_GENCRYPTO_RSA_KEYEL_P].buf);
803
804		jwk->e[LWS_GENCRYPTO_RSA_KEYEL_Q].len = (unsigned int)BN_num_bytes(dummy[5]);
805		jwk->e[LWS_GENCRYPTO_RSA_KEYEL_Q].buf = lws_malloc((unsigned int)n, "privjk");
806		if (!jwk->e[LWS_GENCRYPTO_RSA_KEYEL_Q].buf) {
807			lws_free_set_NULL(jwk->e[LWS_GENCRYPTO_RSA_KEYEL_D].buf);
808			lws_free_set_NULL(jwk->e[LWS_GENCRYPTO_RSA_KEYEL_P].buf);
809			goto bail1;
810		}
811		BN_bn2bin(dummy[5], jwk->e[LWS_GENCRYPTO_RSA_KEYEL_Q].buf);
812		break;
813	default:
814		lwsl_err("%s: JWK has unknown kty %d\n", __func__, jwk->kty);
815		return -1;
816	}
817
818	ret = 0;
819
820bail1:
821	if (jwk->kty == LWS_GENCRYPTO_KTY_EC)
822		EC_KEY_free(ecpriv);
823	else
824		RSA_free(rsapriv);
825
826bail:
827	EVP_PKEY_free(pkey);
828
829	return ret;
830}
831#endif
832
833void
834lws_x509_destroy(struct lws_x509_cert **x509)
835{
836	if (!*x509)
837		return;
838
839	if ((*x509)->cert) {
840		X509_free((*x509)->cert);
841		(*x509)->cert = NULL;
842	}
843
844	lws_free_set_NULL(*x509);
845}
846