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