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