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#include "private-lib-core.h"
26d4afb5ceSopenharmony_ci#include "private-lib-tls-mbedtls.h"
27d4afb5ceSopenharmony_ci#include <mbedtls/oid.h>
28d4afb5ceSopenharmony_ci
29d4afb5ceSopenharmony_ci#if defined(LWS_PLAT_OPTEE) || defined(OPTEE_DEV_KIT)
30d4afb5ceSopenharmony_cistruct tm {
31d4afb5ceSopenharmony_ciint    tm_sec; //   seconds [0,61]
32d4afb5ceSopenharmony_ciint    tm_min; //   minutes [0,59]
33d4afb5ceSopenharmony_ciint    tm_hour; //  hour [0,23]
34d4afb5ceSopenharmony_ciint    tm_mday; //  day of month [1,31]
35d4afb5ceSopenharmony_ciint    tm_mon; //   month of year [0,11]
36d4afb5ceSopenharmony_ciint    tm_year; //  years since 1900
37d4afb5ceSopenharmony_ciint    tm_wday; //  day of week [0,6] (Sunday = 0)
38d4afb5ceSopenharmony_ciint    tm_yday; //  day of year [0,365]
39d4afb5ceSopenharmony_ciint    tm_isdst; // daylight savings flag
40d4afb5ceSopenharmony_ci};
41d4afb5ceSopenharmony_citime_t mktime(struct tm *t)
42d4afb5ceSopenharmony_ci{
43d4afb5ceSopenharmony_ci	return (time_t)0;
44d4afb5ceSopenharmony_ci}
45d4afb5ceSopenharmony_ci#endif
46d4afb5ceSopenharmony_ci
47d4afb5ceSopenharmony_cistatic time_t
48d4afb5ceSopenharmony_cilws_tls_mbedtls_time_to_unix(mbedtls_x509_time *xtime)
49d4afb5ceSopenharmony_ci{
50d4afb5ceSopenharmony_ci	struct tm t;
51d4afb5ceSopenharmony_ci
52d4afb5ceSopenharmony_ci	if (!xtime || !xtime->MBEDTLS_PRIVATE_V30_ONLY(year) || xtime->MBEDTLS_PRIVATE_V30_ONLY(year) < 0)
53d4afb5ceSopenharmony_ci		return (time_t)(long long)-1;
54d4afb5ceSopenharmony_ci
55d4afb5ceSopenharmony_ci	memset(&t, 0, sizeof(t));
56d4afb5ceSopenharmony_ci
57d4afb5ceSopenharmony_ci	t.tm_year = xtime->MBEDTLS_PRIVATE_V30_ONLY(year) - 1900;
58d4afb5ceSopenharmony_ci	t.tm_mon = xtime->MBEDTLS_PRIVATE_V30_ONLY(mon) - 1; /* mbedtls months are 1+, tm are 0+ */
59d4afb5ceSopenharmony_ci	t.tm_mday = xtime->MBEDTLS_PRIVATE_V30_ONLY(day) - 1; /* mbedtls days are 1+, tm are 0+ */
60d4afb5ceSopenharmony_ci	t.tm_hour = xtime->MBEDTLS_PRIVATE_V30_ONLY(hour);
61d4afb5ceSopenharmony_ci	t.tm_min = xtime->MBEDTLS_PRIVATE_V30_ONLY(min);
62d4afb5ceSopenharmony_ci	t.tm_sec = xtime->MBEDTLS_PRIVATE_V30_ONLY(sec);
63d4afb5ceSopenharmony_ci	t.tm_isdst = -1;
64d4afb5ceSopenharmony_ci
65d4afb5ceSopenharmony_ci	return mktime(&t);
66d4afb5ceSopenharmony_ci}
67d4afb5ceSopenharmony_ci
68d4afb5ceSopenharmony_cistatic int
69d4afb5ceSopenharmony_cilws_tls_mbedtls_get_x509_name(mbedtls_x509_name *name,
70d4afb5ceSopenharmony_ci			      union lws_tls_cert_info_results *buf, size_t len)
71d4afb5ceSopenharmony_ci{
72d4afb5ceSopenharmony_ci	int r = -1;
73d4afb5ceSopenharmony_ci
74d4afb5ceSopenharmony_ci	buf->ns.len = 0;
75d4afb5ceSopenharmony_ci
76d4afb5ceSopenharmony_ci	while (name) {
77d4afb5ceSopenharmony_ci		/*
78d4afb5ceSopenharmony_ci		if (MBEDTLS_OID_CMP(type, &name->oid)) {
79d4afb5ceSopenharmony_ci			name = name->next;
80d4afb5ceSopenharmony_ci			continue;
81d4afb5ceSopenharmony_ci		}
82d4afb5ceSopenharmony_ci*/
83d4afb5ceSopenharmony_ci		lws_strnncpy(&buf->ns.name[buf->ns.len],
84d4afb5ceSopenharmony_ci			     (const char *)name->MBEDTLS_PRIVATE_V30_ONLY(val).MBEDTLS_PRIVATE_V30_ONLY(p),
85d4afb5ceSopenharmony_ci			     name->MBEDTLS_PRIVATE_V30_ONLY(val).MBEDTLS_PRIVATE_V30_ONLY(len),
86d4afb5ceSopenharmony_ci			     len - (size_t)buf->ns.len);
87d4afb5ceSopenharmony_ci		buf->ns.len = (int)strlen(buf->ns.name);
88d4afb5ceSopenharmony_ci
89d4afb5ceSopenharmony_ci		r = 0;
90d4afb5ceSopenharmony_ci		name = name->MBEDTLS_PRIVATE_V30_ONLY(next);
91d4afb5ceSopenharmony_ci	}
92d4afb5ceSopenharmony_ci
93d4afb5ceSopenharmony_ci	return r;
94d4afb5ceSopenharmony_ci}
95d4afb5ceSopenharmony_ci
96d4afb5ceSopenharmony_ci
97d4afb5ceSopenharmony_ciint
98d4afb5ceSopenharmony_cilws_tls_mbedtls_cert_info(mbedtls_x509_crt *x509, enum lws_tls_cert_info type,
99d4afb5ceSopenharmony_ci			  union lws_tls_cert_info_results *buf, size_t len)
100d4afb5ceSopenharmony_ci{
101d4afb5ceSopenharmony_ci	mbedtls_x509_buf skid;
102d4afb5ceSopenharmony_ci	lws_mbedtls_x509_authority akid;
103d4afb5ceSopenharmony_ci
104d4afb5ceSopenharmony_ci	if (!x509)
105d4afb5ceSopenharmony_ci		return -1;
106d4afb5ceSopenharmony_ci
107d4afb5ceSopenharmony_ci	if (!len)
108d4afb5ceSopenharmony_ci		len = sizeof(buf->ns.name);
109d4afb5ceSopenharmony_ci
110d4afb5ceSopenharmony_ci	switch (type) {
111d4afb5ceSopenharmony_ci	case LWS_TLS_CERT_INFO_VALIDITY_FROM:
112d4afb5ceSopenharmony_ci		buf->time = lws_tls_mbedtls_time_to_unix(&x509->MBEDTLS_PRIVATE_V30_ONLY(valid_from));
113d4afb5ceSopenharmony_ci		if (buf->time == (time_t)(long long)-1)
114d4afb5ceSopenharmony_ci			return -1;
115d4afb5ceSopenharmony_ci		break;
116d4afb5ceSopenharmony_ci
117d4afb5ceSopenharmony_ci	case LWS_TLS_CERT_INFO_VALIDITY_TO:
118d4afb5ceSopenharmony_ci		buf->time = lws_tls_mbedtls_time_to_unix(&x509->MBEDTLS_PRIVATE_V30_ONLY(valid_to));
119d4afb5ceSopenharmony_ci		if (buf->time == (time_t)(long long)-1)
120d4afb5ceSopenharmony_ci			return -1;
121d4afb5ceSopenharmony_ci		break;
122d4afb5ceSopenharmony_ci
123d4afb5ceSopenharmony_ci	case LWS_TLS_CERT_INFO_COMMON_NAME:
124d4afb5ceSopenharmony_ci		return lws_tls_mbedtls_get_x509_name(&x509->MBEDTLS_PRIVATE_V30_ONLY(subject), buf, len);
125d4afb5ceSopenharmony_ci
126d4afb5ceSopenharmony_ci	case LWS_TLS_CERT_INFO_ISSUER_NAME:
127d4afb5ceSopenharmony_ci		return lws_tls_mbedtls_get_x509_name(&x509->MBEDTLS_PRIVATE_V30_ONLY(issuer), buf, len);
128d4afb5ceSopenharmony_ci
129d4afb5ceSopenharmony_ci	case LWS_TLS_CERT_INFO_USAGE:
130d4afb5ceSopenharmony_ci		buf->usage = x509->MBEDTLS_PRIVATE(key_usage);
131d4afb5ceSopenharmony_ci		break;
132d4afb5ceSopenharmony_ci
133d4afb5ceSopenharmony_ci	case LWS_TLS_CERT_INFO_OPAQUE_PUBLIC_KEY:
134d4afb5ceSopenharmony_ci	{
135d4afb5ceSopenharmony_ci		char *p = buf->ns.name;
136d4afb5ceSopenharmony_ci		size_t r = len, u;
137d4afb5ceSopenharmony_ci
138d4afb5ceSopenharmony_ci		switch (mbedtls_pk_get_type(&x509->MBEDTLS_PRIVATE_V30_ONLY(pk))) {
139d4afb5ceSopenharmony_ci		case MBEDTLS_PK_RSA:
140d4afb5ceSopenharmony_ci		{
141d4afb5ceSopenharmony_ci			mbedtls_rsa_context *rsa = mbedtls_pk_rsa(x509->MBEDTLS_PRIVATE_V30_ONLY(pk));
142d4afb5ceSopenharmony_ci
143d4afb5ceSopenharmony_ci			if (mbedtls_mpi_write_string(&rsa->MBEDTLS_PRIVATE(N), 16, p, r, &u))
144d4afb5ceSopenharmony_ci				return -1;
145d4afb5ceSopenharmony_ci			r -= u;
146d4afb5ceSopenharmony_ci			p += u;
147d4afb5ceSopenharmony_ci			if (mbedtls_mpi_write_string(&rsa->MBEDTLS_PRIVATE(E), 16, p, r, &u))
148d4afb5ceSopenharmony_ci				return -1;
149d4afb5ceSopenharmony_ci
150d4afb5ceSopenharmony_ci			p += u;
151d4afb5ceSopenharmony_ci			buf->ns.len = lws_ptr_diff(p, buf->ns.name);
152d4afb5ceSopenharmony_ci			break;
153d4afb5ceSopenharmony_ci		}
154d4afb5ceSopenharmony_ci		case MBEDTLS_PK_ECKEY:
155d4afb5ceSopenharmony_ci		{
156d4afb5ceSopenharmony_ci			mbedtls_ecp_keypair *ecp = mbedtls_pk_ec(x509->MBEDTLS_PRIVATE_V30_ONLY(pk));
157d4afb5ceSopenharmony_ci
158d4afb5ceSopenharmony_ci			if (mbedtls_mpi_write_string(&ecp->MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(X), 16, p, r, &u))
159d4afb5ceSopenharmony_ci				 return -1;
160d4afb5ceSopenharmony_ci			r -= u;
161d4afb5ceSopenharmony_ci			p += u;
162d4afb5ceSopenharmony_ci			if (mbedtls_mpi_write_string(&ecp->MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(Y), 16, p, r, &u))
163d4afb5ceSopenharmony_ci				 return -1;
164d4afb5ceSopenharmony_ci			r -= u;
165d4afb5ceSopenharmony_ci			p += u;
166d4afb5ceSopenharmony_ci			if (mbedtls_mpi_write_string(&ecp->MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(Z), 16, p, r, &u))
167d4afb5ceSopenharmony_ci				 return -1;
168d4afb5ceSopenharmony_ci			p += u;
169d4afb5ceSopenharmony_ci			buf->ns.len = lws_ptr_diff(p, buf->ns.name);
170d4afb5ceSopenharmony_ci			break;
171d4afb5ceSopenharmony_ci		}
172d4afb5ceSopenharmony_ci		default:
173d4afb5ceSopenharmony_ci			lwsl_notice("%s: x509 has unsupported pubkey type %d\n",
174d4afb5ceSopenharmony_ci				    __func__,
175d4afb5ceSopenharmony_ci				    mbedtls_pk_get_type(&x509->MBEDTLS_PRIVATE_V30_ONLY(pk)));
176d4afb5ceSopenharmony_ci
177d4afb5ceSopenharmony_ci			return -1;
178d4afb5ceSopenharmony_ci		}
179d4afb5ceSopenharmony_ci		break;
180d4afb5ceSopenharmony_ci	}
181d4afb5ceSopenharmony_ci	case LWS_TLS_CERT_INFO_DER_RAW:
182d4afb5ceSopenharmony_ci
183d4afb5ceSopenharmony_ci		buf->ns.len = (int)x509->MBEDTLS_PRIVATE_V30_ONLY(raw).MBEDTLS_PRIVATE_V30_ONLY(len);
184d4afb5ceSopenharmony_ci
185d4afb5ceSopenharmony_ci		if (len < x509->MBEDTLS_PRIVATE_V30_ONLY(raw).MBEDTLS_PRIVATE_V30_ONLY(len))
186d4afb5ceSopenharmony_ci			/*
187d4afb5ceSopenharmony_ci			 * The buffer is too small and the attempt failed, but
188d4afb5ceSopenharmony_ci			 * the required object length is in buf->ns.len
189d4afb5ceSopenharmony_ci			 */
190d4afb5ceSopenharmony_ci			return -1;
191d4afb5ceSopenharmony_ci
192d4afb5ceSopenharmony_ci		memcpy(buf->ns.name, x509->MBEDTLS_PRIVATE_V30_ONLY(raw).MBEDTLS_PRIVATE_V30_ONLY(p),
193d4afb5ceSopenharmony_ci				x509->MBEDTLS_PRIVATE_V30_ONLY(raw).MBEDTLS_PRIVATE_V30_ONLY(len));
194d4afb5ceSopenharmony_ci		break;
195d4afb5ceSopenharmony_ci
196d4afb5ceSopenharmony_ci	case LWS_TLS_CERT_INFO_AUTHORITY_KEY_ID:
197d4afb5ceSopenharmony_ci
198d4afb5ceSopenharmony_ci		memset(&akid, 0, sizeof(akid));
199d4afb5ceSopenharmony_ci		memset(&skid, 0, sizeof(skid));
200d4afb5ceSopenharmony_ci
201d4afb5ceSopenharmony_ci		lws_x509_get_crt_ext(x509, &skid, &akid);
202d4afb5ceSopenharmony_ci		if (akid.keyIdentifier.MBEDTLS_PRIVATE_V30_ONLY(tag) != MBEDTLS_ASN1_OCTET_STRING)
203d4afb5ceSopenharmony_ci			return 1;
204d4afb5ceSopenharmony_ci		buf->ns.len = (int)akid.keyIdentifier.MBEDTLS_PRIVATE_V30_ONLY(len);
205d4afb5ceSopenharmony_ci		if (!akid.keyIdentifier.MBEDTLS_PRIVATE_V30_ONLY(p) ||
206d4afb5ceSopenharmony_ci		    len < (size_t)buf->ns.len)
207d4afb5ceSopenharmony_ci			return -1;
208d4afb5ceSopenharmony_ci		memcpy(buf->ns.name, akid.keyIdentifier.MBEDTLS_PRIVATE_V30_ONLY(p), (size_t)buf->ns.len);
209d4afb5ceSopenharmony_ci		break;
210d4afb5ceSopenharmony_ci
211d4afb5ceSopenharmony_ci	case LWS_TLS_CERT_INFO_AUTHORITY_KEY_ID_ISSUER: {
212d4afb5ceSopenharmony_ci		mbedtls_x509_sequence * ip;
213d4afb5ceSopenharmony_ci
214d4afb5ceSopenharmony_ci		memset(&akid, 0, sizeof(akid));
215d4afb5ceSopenharmony_ci		memset(&skid, 0, sizeof(skid));
216d4afb5ceSopenharmony_ci
217d4afb5ceSopenharmony_ci		lws_x509_get_crt_ext(x509, &skid, &akid);
218d4afb5ceSopenharmony_ci
219d4afb5ceSopenharmony_ci		ip = &akid.authorityCertIssuer;
220d4afb5ceSopenharmony_ci
221d4afb5ceSopenharmony_ci		buf->ns.len = 0;
222d4afb5ceSopenharmony_ci
223d4afb5ceSopenharmony_ci		while (ip) {
224d4afb5ceSopenharmony_ci			if (akid.keyIdentifier.MBEDTLS_PRIVATE_V30_ONLY(tag) != MBEDTLS_ASN1_OCTET_STRING ||
225d4afb5ceSopenharmony_ci			    !ip->MBEDTLS_PRIVATE_V30_ONLY(buf).MBEDTLS_PRIVATE_V30_ONLY(p) ||
226d4afb5ceSopenharmony_ci			    ip->MBEDTLS_PRIVATE_V30_ONLY(buf).MBEDTLS_PRIVATE_V30_ONLY(len) < 9 ||
227d4afb5ceSopenharmony_ci			    len < (size_t)ip->MBEDTLS_PRIVATE_V30_ONLY(buf).MBEDTLS_PRIVATE_V30_ONLY(len) - 9u)
228d4afb5ceSopenharmony_ci			break;
229d4afb5ceSopenharmony_ci
230d4afb5ceSopenharmony_ci			memcpy(buf->ns.name + buf->ns.len, ip->MBEDTLS_PRIVATE_V30_ONLY(buf).MBEDTLS_PRIVATE_V30_ONLY(p),
231d4afb5ceSopenharmony_ci					(size_t)ip->MBEDTLS_PRIVATE_V30_ONLY(buf).MBEDTLS_PRIVATE_V30_ONLY(len) - 9);
232d4afb5ceSopenharmony_ci			buf->ns.len = buf->ns.len + (int)ip->MBEDTLS_PRIVATE_V30_ONLY(buf).MBEDTLS_PRIVATE_V30_ONLY(len) - 9;
233d4afb5ceSopenharmony_ci
234d4afb5ceSopenharmony_ci			ip = ip->MBEDTLS_PRIVATE_V30_ONLY(next);
235d4afb5ceSopenharmony_ci		}
236d4afb5ceSopenharmony_ci		break;
237d4afb5ceSopenharmony_ci	}
238d4afb5ceSopenharmony_ci	case LWS_TLS_CERT_INFO_AUTHORITY_KEY_ID_SERIAL:
239d4afb5ceSopenharmony_ci
240d4afb5ceSopenharmony_ci		memset(&akid, 0, sizeof(akid));
241d4afb5ceSopenharmony_ci		memset(&skid, 0, sizeof(skid));
242d4afb5ceSopenharmony_ci
243d4afb5ceSopenharmony_ci		lws_x509_get_crt_ext(x509, &skid, &akid);
244d4afb5ceSopenharmony_ci
245d4afb5ceSopenharmony_ci		if (akid.authorityCertSerialNumber.MBEDTLS_PRIVATE_V30_ONLY(tag) != MBEDTLS_ASN1_OCTET_STRING)
246d4afb5ceSopenharmony_ci			return 1;
247d4afb5ceSopenharmony_ci		buf->ns.len = (int)akid.authorityCertSerialNumber.MBEDTLS_PRIVATE_V30_ONLY(len);
248d4afb5ceSopenharmony_ci		if (!akid.authorityCertSerialNumber.MBEDTLS_PRIVATE_V30_ONLY(p) ||
249d4afb5ceSopenharmony_ci		    len < (size_t)buf->ns.len)
250d4afb5ceSopenharmony_ci			return -1;
251d4afb5ceSopenharmony_ci		memcpy(buf->ns.name, akid.authorityCertSerialNumber.
252d4afb5ceSopenharmony_ci				MBEDTLS_PRIVATE_V30_ONLY(p), (size_t)buf->ns.len);
253d4afb5ceSopenharmony_ci		break;
254d4afb5ceSopenharmony_ci
255d4afb5ceSopenharmony_ci	case LWS_TLS_CERT_INFO_SUBJECT_KEY_ID:
256d4afb5ceSopenharmony_ci
257d4afb5ceSopenharmony_ci		memset(&akid, 0, sizeof(akid));
258d4afb5ceSopenharmony_ci		memset(&skid, 0, sizeof(skid));
259d4afb5ceSopenharmony_ci
260d4afb5ceSopenharmony_ci		lws_x509_get_crt_ext(x509, &skid, &akid);
261d4afb5ceSopenharmony_ci
262d4afb5ceSopenharmony_ci		if (skid.MBEDTLS_PRIVATE_V30_ONLY(tag) != MBEDTLS_ASN1_OCTET_STRING)
263d4afb5ceSopenharmony_ci			return 1;
264d4afb5ceSopenharmony_ci		buf->ns.len = (int)skid.MBEDTLS_PRIVATE_V30_ONLY(len);
265d4afb5ceSopenharmony_ci		if (len < (size_t)buf->ns.len)
266d4afb5ceSopenharmony_ci			return -1;
267d4afb5ceSopenharmony_ci		memcpy(buf->ns.name, skid.MBEDTLS_PRIVATE_V30_ONLY(p), (size_t)buf->ns.len);
268d4afb5ceSopenharmony_ci		break;
269d4afb5ceSopenharmony_ci	default:
270d4afb5ceSopenharmony_ci		return -1;
271d4afb5ceSopenharmony_ci	}
272d4afb5ceSopenharmony_ci
273d4afb5ceSopenharmony_ci	return 0;
274d4afb5ceSopenharmony_ci}
275d4afb5ceSopenharmony_ci
276d4afb5ceSopenharmony_ci#if defined(LWS_WITH_NETWORK)
277d4afb5ceSopenharmony_ciint
278d4afb5ceSopenharmony_cilws_tls_vhost_cert_info(struct lws_vhost *vhost, enum lws_tls_cert_info type,
279d4afb5ceSopenharmony_ci		        union lws_tls_cert_info_results *buf, size_t len)
280d4afb5ceSopenharmony_ci{
281d4afb5ceSopenharmony_ci	mbedtls_x509_crt *x509;
282d4afb5ceSopenharmony_ci
283d4afb5ceSopenharmony_ci	x509 = ssl_ctx_get_mbedtls_x509_crt(vhost->tls.ssl_ctx);
284d4afb5ceSopenharmony_ci
285d4afb5ceSopenharmony_ci	return lws_tls_mbedtls_cert_info(x509, type, buf, len);
286d4afb5ceSopenharmony_ci}
287d4afb5ceSopenharmony_ci
288d4afb5ceSopenharmony_ciint
289d4afb5ceSopenharmony_cilws_tls_peer_cert_info(struct lws *wsi, enum lws_tls_cert_info type,
290d4afb5ceSopenharmony_ci		       union lws_tls_cert_info_results *buf, size_t len)
291d4afb5ceSopenharmony_ci{
292d4afb5ceSopenharmony_ci	mbedtls_x509_crt *x509;
293d4afb5ceSopenharmony_ci
294d4afb5ceSopenharmony_ci	wsi = lws_get_network_wsi(wsi);
295d4afb5ceSopenharmony_ci
296d4afb5ceSopenharmony_ci	x509 = ssl_get_peer_mbedtls_x509_crt(wsi->tls.ssl);
297d4afb5ceSopenharmony_ci
298d4afb5ceSopenharmony_ci	if (!x509)
299d4afb5ceSopenharmony_ci		return -1;
300d4afb5ceSopenharmony_ci
301d4afb5ceSopenharmony_ci	switch (type) {
302d4afb5ceSopenharmony_ci	case LWS_TLS_CERT_INFO_VERIFIED:
303d4afb5ceSopenharmony_ci		buf->verified = SSL_get_verify_result(wsi->tls.ssl) == X509_V_OK;
304d4afb5ceSopenharmony_ci		return 0;
305d4afb5ceSopenharmony_ci	default:
306d4afb5ceSopenharmony_ci		return lws_tls_mbedtls_cert_info(x509, type, buf, len);
307d4afb5ceSopenharmony_ci	}
308d4afb5ceSopenharmony_ci
309d4afb5ceSopenharmony_ci	return -1;
310d4afb5ceSopenharmony_ci}
311d4afb5ceSopenharmony_ci#endif
312d4afb5ceSopenharmony_ci
313d4afb5ceSopenharmony_ciint
314d4afb5ceSopenharmony_cilws_x509_info(struct lws_x509_cert *x509, enum lws_tls_cert_info type,
315d4afb5ceSopenharmony_ci	      union lws_tls_cert_info_results *buf, size_t len)
316d4afb5ceSopenharmony_ci{
317d4afb5ceSopenharmony_ci	return lws_tls_mbedtls_cert_info(&x509->cert, type, buf, len);
318d4afb5ceSopenharmony_ci}
319d4afb5ceSopenharmony_ci
320d4afb5ceSopenharmony_ciint
321d4afb5ceSopenharmony_cilws_x509_create(struct lws_x509_cert **x509)
322d4afb5ceSopenharmony_ci{
323d4afb5ceSopenharmony_ci	*x509 = lws_malloc(sizeof(**x509), __func__);
324d4afb5ceSopenharmony_ci
325d4afb5ceSopenharmony_ci	return !(*x509);
326d4afb5ceSopenharmony_ci}
327d4afb5ceSopenharmony_ci
328d4afb5ceSopenharmony_ci/*
329d4afb5ceSopenharmony_ci * Parse one DER-encoded or one or more concatenated PEM-encoded certificates
330d4afb5ceSopenharmony_ci * and add them to the chained list.
331d4afb5ceSopenharmony_ci */
332d4afb5ceSopenharmony_ci
333d4afb5ceSopenharmony_ciint
334d4afb5ceSopenharmony_cilws_x509_parse_from_pem(struct lws_x509_cert *x509, const void *pem, size_t len)
335d4afb5ceSopenharmony_ci{
336d4afb5ceSopenharmony_ci	int ret;
337d4afb5ceSopenharmony_ci
338d4afb5ceSopenharmony_ci	mbedtls_x509_crt_init(&x509->cert);
339d4afb5ceSopenharmony_ci
340d4afb5ceSopenharmony_ci	ret = mbedtls_x509_crt_parse(&x509->cert, pem, len);
341d4afb5ceSopenharmony_ci	if (ret) {
342d4afb5ceSopenharmony_ci		if (ret > 0)
343d4afb5ceSopenharmony_ci			mbedtls_x509_crt_free(&x509->cert);
344d4afb5ceSopenharmony_ci		lwsl_err("%s: unable to parse PEM cert: -0x%x\n",
345d4afb5ceSopenharmony_ci			 __func__, -ret);
346d4afb5ceSopenharmony_ci
347d4afb5ceSopenharmony_ci		return -1;
348d4afb5ceSopenharmony_ci	}
349d4afb5ceSopenharmony_ci
350d4afb5ceSopenharmony_ci	return 0;
351d4afb5ceSopenharmony_ci}
352d4afb5ceSopenharmony_ci
353d4afb5ceSopenharmony_ciint
354d4afb5ceSopenharmony_cilws_x509_verify(struct lws_x509_cert *x509, struct lws_x509_cert *trusted,
355d4afb5ceSopenharmony_ci		const char *common_name)
356d4afb5ceSopenharmony_ci{
357d4afb5ceSopenharmony_ci	uint32_t flags = 0;
358d4afb5ceSopenharmony_ci	int ret;
359d4afb5ceSopenharmony_ci
360d4afb5ceSopenharmony_ci	ret = mbedtls_x509_crt_verify_with_profile(&x509->cert, &trusted->cert,
361d4afb5ceSopenharmony_ci						   NULL,
362d4afb5ceSopenharmony_ci						   &mbedtls_x509_crt_profile_next,
363d4afb5ceSopenharmony_ci						   common_name, &flags, NULL,
364d4afb5ceSopenharmony_ci						   NULL);
365d4afb5ceSopenharmony_ci
366d4afb5ceSopenharmony_ci	if (ret) {
367d4afb5ceSopenharmony_ci		lwsl_err("%s: unable to parse PEM cert: -0x%x\n",
368d4afb5ceSopenharmony_ci			 __func__, -ret);
369d4afb5ceSopenharmony_ci
370d4afb5ceSopenharmony_ci		return -1;
371d4afb5ceSopenharmony_ci	}
372d4afb5ceSopenharmony_ci
373d4afb5ceSopenharmony_ci	return 0;
374d4afb5ceSopenharmony_ci}
375d4afb5ceSopenharmony_ci
376d4afb5ceSopenharmony_ci#if defined(LWS_WITH_JOSE)
377d4afb5ceSopenharmony_ci
378d4afb5ceSopenharmony_ciint
379d4afb5ceSopenharmony_cilws_x509_public_to_jwk(struct lws_jwk *jwk, struct lws_x509_cert *x509,
380d4afb5ceSopenharmony_ci		       const char *curves, int rsa_min_bits)
381d4afb5ceSopenharmony_ci{
382d4afb5ceSopenharmony_ci	int kt = (int)mbedtls_pk_get_type(&x509->cert.MBEDTLS_PRIVATE_V30_ONLY(pk)),
383d4afb5ceSopenharmony_ci			n, count = 0, ret = -1;
384d4afb5ceSopenharmony_ci	mbedtls_rsa_context *rsactx;
385d4afb5ceSopenharmony_ci	mbedtls_ecp_keypair *ecpctx;
386d4afb5ceSopenharmony_ci	mbedtls_mpi *mpi[LWS_GENCRYPTO_RSA_KEYEL_COUNT];
387d4afb5ceSopenharmony_ci
388d4afb5ceSopenharmony_ci	memset(jwk, 0, sizeof(*jwk));
389d4afb5ceSopenharmony_ci
390d4afb5ceSopenharmony_ci	switch (kt) {
391d4afb5ceSopenharmony_ci	case MBEDTLS_PK_RSA:
392d4afb5ceSopenharmony_ci		lwsl_notice("%s: RSA key\n", __func__);
393d4afb5ceSopenharmony_ci		jwk->kty = LWS_GENCRYPTO_KTY_RSA;
394d4afb5ceSopenharmony_ci		rsactx = mbedtls_pk_rsa(x509->cert.MBEDTLS_PRIVATE_V30_ONLY(pk));
395d4afb5ceSopenharmony_ci
396d4afb5ceSopenharmony_ci		mpi[LWS_GENCRYPTO_RSA_KEYEL_E] = &rsactx->MBEDTLS_PRIVATE(E);
397d4afb5ceSopenharmony_ci		mpi[LWS_GENCRYPTO_RSA_KEYEL_N] = &rsactx->MBEDTLS_PRIVATE(N);
398d4afb5ceSopenharmony_ci		mpi[LWS_GENCRYPTO_RSA_KEYEL_D] = &rsactx->MBEDTLS_PRIVATE(D);
399d4afb5ceSopenharmony_ci		mpi[LWS_GENCRYPTO_RSA_KEYEL_P] = &rsactx->MBEDTLS_PRIVATE(P);
400d4afb5ceSopenharmony_ci		mpi[LWS_GENCRYPTO_RSA_KEYEL_Q] = &rsactx->MBEDTLS_PRIVATE(Q);
401d4afb5ceSopenharmony_ci		mpi[LWS_GENCRYPTO_RSA_KEYEL_DP] = &rsactx->MBEDTLS_PRIVATE(DP);
402d4afb5ceSopenharmony_ci		mpi[LWS_GENCRYPTO_RSA_KEYEL_DQ] = &rsactx->MBEDTLS_PRIVATE(DQ);
403d4afb5ceSopenharmony_ci		mpi[LWS_GENCRYPTO_RSA_KEYEL_QI] = &rsactx->MBEDTLS_PRIVATE(QP);
404d4afb5ceSopenharmony_ci
405d4afb5ceSopenharmony_ci		count = LWS_GENCRYPTO_RSA_KEYEL_QI + 1;
406d4afb5ceSopenharmony_ci		n = LWS_GENCRYPTO_RSA_KEYEL_E;
407d4afb5ceSopenharmony_ci		break;
408d4afb5ceSopenharmony_ci
409d4afb5ceSopenharmony_ci	case MBEDTLS_PK_ECKEY:
410d4afb5ceSopenharmony_ci		lwsl_notice("%s: EC key\n", __func__);
411d4afb5ceSopenharmony_ci		jwk->kty = LWS_GENCRYPTO_KTY_EC;
412d4afb5ceSopenharmony_ci		ecpctx = mbedtls_pk_ec(x509->cert.MBEDTLS_PRIVATE_V30_ONLY(pk));
413d4afb5ceSopenharmony_ci		mpi[LWS_GENCRYPTO_EC_KEYEL_X] = &ecpctx->MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(X);
414d4afb5ceSopenharmony_ci		mpi[LWS_GENCRYPTO_EC_KEYEL_D] = &ecpctx->MBEDTLS_PRIVATE(d);
415d4afb5ceSopenharmony_ci		mpi[LWS_GENCRYPTO_EC_KEYEL_Y] = &ecpctx->MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(Y);
416d4afb5ceSopenharmony_ci
417d4afb5ceSopenharmony_ci		if (lws_genec_confirm_curve_allowed_by_tls_id(curves,
418d4afb5ceSopenharmony_ci				(int)ecpctx->MBEDTLS_PRIVATE(grp).id, jwk))
419d4afb5ceSopenharmony_ci			/* already logged */
420d4afb5ceSopenharmony_ci			goto bail;
421d4afb5ceSopenharmony_ci
422d4afb5ceSopenharmony_ci		count = LWS_GENCRYPTO_EC_KEYEL_COUNT;
423d4afb5ceSopenharmony_ci		n = LWS_GENCRYPTO_EC_KEYEL_X;
424d4afb5ceSopenharmony_ci		break;
425d4afb5ceSopenharmony_ci	default:
426d4afb5ceSopenharmony_ci		lwsl_err("%s: key type %d not supported\n", __func__, kt);
427d4afb5ceSopenharmony_ci
428d4afb5ceSopenharmony_ci		return -1;
429d4afb5ceSopenharmony_ci	}
430d4afb5ceSopenharmony_ci
431d4afb5ceSopenharmony_ci	for (; n < count; n++) {
432d4afb5ceSopenharmony_ci		if (!mbedtls_mpi_size(mpi[n]))
433d4afb5ceSopenharmony_ci			continue;
434d4afb5ceSopenharmony_ci
435d4afb5ceSopenharmony_ci		jwk->e[n].buf = lws_malloc(mbedtls_mpi_size(mpi[n]), "certjwk");
436d4afb5ceSopenharmony_ci		if (!jwk->e[n].buf)
437d4afb5ceSopenharmony_ci			goto bail;
438d4afb5ceSopenharmony_ci		jwk->e[n].len = (uint32_t)mbedtls_mpi_size(mpi[n]);
439d4afb5ceSopenharmony_ci		mbedtls_mpi_write_binary(mpi[n], jwk->e[n].buf, jwk->e[n].len);
440d4afb5ceSopenharmony_ci	}
441d4afb5ceSopenharmony_ci
442d4afb5ceSopenharmony_ci	ret = 0;
443d4afb5ceSopenharmony_ci
444d4afb5ceSopenharmony_cibail:
445d4afb5ceSopenharmony_ci	/* jwk destroy will clean up partials */
446d4afb5ceSopenharmony_ci	if (ret)
447d4afb5ceSopenharmony_ci		lws_jwk_destroy(jwk);
448d4afb5ceSopenharmony_ci
449d4afb5ceSopenharmony_ci	return ret;
450d4afb5ceSopenharmony_ci}
451d4afb5ceSopenharmony_ci
452d4afb5ceSopenharmony_ciint
453d4afb5ceSopenharmony_cilws_x509_jwk_privkey_pem(struct lws_context *cx, struct lws_jwk *jwk,
454d4afb5ceSopenharmony_ci			 void *pem, size_t len, const char *passphrase)
455d4afb5ceSopenharmony_ci{
456d4afb5ceSopenharmony_ci	mbedtls_rsa_context *rsactx;
457d4afb5ceSopenharmony_ci	mbedtls_ecp_keypair *ecpctx;
458d4afb5ceSopenharmony_ci	mbedtls_pk_context pk;
459d4afb5ceSopenharmony_ci	mbedtls_mpi *mpi[LWS_GENCRYPTO_RSA_KEYEL_COUNT];
460d4afb5ceSopenharmony_ci	int n, ret = -1, count = 0;
461d4afb5ceSopenharmony_ci
462d4afb5ceSopenharmony_ci	mbedtls_pk_init(&pk);
463d4afb5ceSopenharmony_ci
464d4afb5ceSopenharmony_ci	n = 0;
465d4afb5ceSopenharmony_ci	if (passphrase)
466d4afb5ceSopenharmony_ci		n = (int)strlen(passphrase);
467d4afb5ceSopenharmony_ci	n = mbedtls_pk_parse_key(&pk, pem, len, (uint8_t *)passphrase, (unsigned int)n
468d4afb5ceSopenharmony_ci#if defined(MBEDTLS_VERSION_NUMBER) && MBEDTLS_VERSION_NUMBER >= 0x03000000
469d4afb5ceSopenharmony_ci					, mbedtls_ctr_drbg_random, &cx->mcdc
470d4afb5ceSopenharmony_ci#endif
471d4afb5ceSopenharmony_ci			);
472d4afb5ceSopenharmony_ci	if (n) {
473d4afb5ceSopenharmony_ci		lwsl_err("%s: parse PEM key failed: -0x%x\n", __func__, -n);
474d4afb5ceSopenharmony_ci
475d4afb5ceSopenharmony_ci		return -1;
476d4afb5ceSopenharmony_ci	}
477d4afb5ceSopenharmony_ci
478d4afb5ceSopenharmony_ci	/* the incoming private key type */
479d4afb5ceSopenharmony_ci	switch (mbedtls_pk_get_type(&pk)) {
480d4afb5ceSopenharmony_ci	case MBEDTLS_PK_RSA:
481d4afb5ceSopenharmony_ci		if (jwk->kty != LWS_GENCRYPTO_KTY_RSA) {
482d4afb5ceSopenharmony_ci			lwsl_err("%s: RSA privkey, non-RSA jwk\n", __func__);
483d4afb5ceSopenharmony_ci			goto bail;
484d4afb5ceSopenharmony_ci		}
485d4afb5ceSopenharmony_ci		rsactx = mbedtls_pk_rsa(pk);
486d4afb5ceSopenharmony_ci		mpi[LWS_GENCRYPTO_RSA_KEYEL_D] = &rsactx->MBEDTLS_PRIVATE(D);
487d4afb5ceSopenharmony_ci		mpi[LWS_GENCRYPTO_RSA_KEYEL_P] = &rsactx->MBEDTLS_PRIVATE(P);
488d4afb5ceSopenharmony_ci		mpi[LWS_GENCRYPTO_RSA_KEYEL_Q] = &rsactx->MBEDTLS_PRIVATE(Q);
489d4afb5ceSopenharmony_ci		n = LWS_GENCRYPTO_RSA_KEYEL_D;
490d4afb5ceSopenharmony_ci		count = LWS_GENCRYPTO_RSA_KEYEL_Q + 1;
491d4afb5ceSopenharmony_ci		break;
492d4afb5ceSopenharmony_ci	case MBEDTLS_PK_ECKEY:
493d4afb5ceSopenharmony_ci		if (jwk->kty != LWS_GENCRYPTO_KTY_EC) {
494d4afb5ceSopenharmony_ci			lwsl_err("%s: EC privkey, non-EC jwk\n", __func__);
495d4afb5ceSopenharmony_ci			goto bail;
496d4afb5ceSopenharmony_ci		}
497d4afb5ceSopenharmony_ci		ecpctx = mbedtls_pk_ec(pk);
498d4afb5ceSopenharmony_ci		mpi[LWS_GENCRYPTO_EC_KEYEL_D] = &ecpctx->MBEDTLS_PRIVATE(d);
499d4afb5ceSopenharmony_ci		n = LWS_GENCRYPTO_EC_KEYEL_D;
500d4afb5ceSopenharmony_ci		count = n + 1;
501d4afb5ceSopenharmony_ci		break;
502d4afb5ceSopenharmony_ci	default:
503d4afb5ceSopenharmony_ci		lwsl_err("%s: unusable key type %d\n", __func__,
504d4afb5ceSopenharmony_ci				mbedtls_pk_get_type(&pk));
505d4afb5ceSopenharmony_ci		goto bail;
506d4afb5ceSopenharmony_ci	}
507d4afb5ceSopenharmony_ci
508d4afb5ceSopenharmony_ci	for (; n < count; n++) {
509d4afb5ceSopenharmony_ci		if (!mbedtls_mpi_size(mpi[n])) {
510d4afb5ceSopenharmony_ci			lwsl_err("%s: empty privkey\n", __func__);
511d4afb5ceSopenharmony_ci			goto bail;
512d4afb5ceSopenharmony_ci		}
513d4afb5ceSopenharmony_ci
514d4afb5ceSopenharmony_ci		jwk->e[n].buf = lws_malloc(mbedtls_mpi_size(mpi[n]), "certjwk");
515d4afb5ceSopenharmony_ci		if (!jwk->e[n].buf)
516d4afb5ceSopenharmony_ci			goto bail;
517d4afb5ceSopenharmony_ci		jwk->e[n].len = (uint32_t)mbedtls_mpi_size(mpi[n]);
518d4afb5ceSopenharmony_ci		mbedtls_mpi_write_binary(mpi[n], jwk->e[n].buf, jwk->e[n].len);
519d4afb5ceSopenharmony_ci	}
520d4afb5ceSopenharmony_ci
521d4afb5ceSopenharmony_ci	ret = 0;
522d4afb5ceSopenharmony_ci
523d4afb5ceSopenharmony_cibail:
524d4afb5ceSopenharmony_ci	mbedtls_pk_free(&pk);
525d4afb5ceSopenharmony_ci
526d4afb5ceSopenharmony_ci	return ret;
527d4afb5ceSopenharmony_ci}
528d4afb5ceSopenharmony_ci#endif
529d4afb5ceSopenharmony_ci
530d4afb5ceSopenharmony_civoid
531d4afb5ceSopenharmony_cilws_x509_destroy(struct lws_x509_cert **x509)
532d4afb5ceSopenharmony_ci{
533d4afb5ceSopenharmony_ci	if (!*x509)
534d4afb5ceSopenharmony_ci		return;
535d4afb5ceSopenharmony_ci
536d4afb5ceSopenharmony_ci	mbedtls_x509_crt_free(&(*x509)->cert);
537d4afb5ceSopenharmony_ci
538d4afb5ceSopenharmony_ci	lws_free_set_NULL(*x509);
539d4afb5ceSopenharmony_ci}
540