xref: /aosp_15_r20/external/libwebsockets/lib/tls/mbedtls/mbedtls-client.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 - 2021 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 #include "private-lib-core.h"
26*1c60b9acSAndroid Build Coastguard Worker #include "private-lib-tls-mbedtls.h"
27*1c60b9acSAndroid Build Coastguard Worker 
28*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_TLS_JIT_TRUST)
29*1c60b9acSAndroid Build Coastguard Worker 
30*1c60b9acSAndroid Build Coastguard Worker /*
31*1c60b9acSAndroid Build Coastguard Worker  * We get called for each peer certificate that was provided in turn.
32*1c60b9acSAndroid Build Coastguard Worker  *
33*1c60b9acSAndroid Build Coastguard Worker  * Our job is just to collect the AKID and SKIDs into ssl->kid_chain, and walk
34*1c60b9acSAndroid Build Coastguard Worker  * later at verification result time if it failed.
35*1c60b9acSAndroid Build Coastguard Worker  *
36*1c60b9acSAndroid Build Coastguard Worker  * None of these should be trusted, even if a misconfigured server sends us
37*1c60b9acSAndroid Build Coastguard Worker  * his root CA.
38*1c60b9acSAndroid Build Coastguard Worker  */
39*1c60b9acSAndroid Build Coastguard Worker 
40*1c60b9acSAndroid Build Coastguard Worker static int
lws_mbedtls_client_verify_callback(SSL * ssl,mbedtls_x509_crt * x509)41*1c60b9acSAndroid Build Coastguard Worker lws_mbedtls_client_verify_callback(SSL *ssl, mbedtls_x509_crt *x509)
42*1c60b9acSAndroid Build Coastguard Worker {
43*1c60b9acSAndroid Build Coastguard Worker 	union lws_tls_cert_info_results ci;
44*1c60b9acSAndroid Build Coastguard Worker 
45*1c60b9acSAndroid Build Coastguard Worker 	/* we reached the max we can hold? */
46*1c60b9acSAndroid Build Coastguard Worker 
47*1c60b9acSAndroid Build Coastguard Worker 	if (ssl->kid_chain.count == LWS_ARRAY_SIZE(ssl->kid_chain.akid))
48*1c60b9acSAndroid Build Coastguard Worker 		return 0;
49*1c60b9acSAndroid Build Coastguard Worker 
50*1c60b9acSAndroid Build Coastguard Worker 	/* if not, stash the SKID and AKID into the next kid slot */
51*1c60b9acSAndroid Build Coastguard Worker 
52*1c60b9acSAndroid Build Coastguard Worker 	if (!lws_tls_mbedtls_cert_info(x509, LWS_TLS_CERT_INFO_SUBJECT_KEY_ID,
53*1c60b9acSAndroid Build Coastguard Worker 				       &ci, 0))
54*1c60b9acSAndroid Build Coastguard Worker 		lws_tls_kid_copy(&ci,
55*1c60b9acSAndroid Build Coastguard Worker 				 &ssl->kid_chain.skid[ssl->kid_chain.count]);
56*1c60b9acSAndroid Build Coastguard Worker 
57*1c60b9acSAndroid Build Coastguard Worker 	if (!lws_tls_mbedtls_cert_info(x509, LWS_TLS_CERT_INFO_AUTHORITY_KEY_ID,
58*1c60b9acSAndroid Build Coastguard Worker 				       &ci, 0))
59*1c60b9acSAndroid Build Coastguard Worker 		lws_tls_kid_copy(&ci,
60*1c60b9acSAndroid Build Coastguard Worker 				 &ssl->kid_chain.akid[ssl->kid_chain.count]);
61*1c60b9acSAndroid Build Coastguard Worker 
62*1c60b9acSAndroid Build Coastguard Worker 	ssl->kid_chain.count++;
63*1c60b9acSAndroid Build Coastguard Worker 
64*1c60b9acSAndroid Build Coastguard Worker 	// lwsl_notice("%s: %u\n", __func__, ssl->kid_chain.count);
65*1c60b9acSAndroid Build Coastguard Worker 
66*1c60b9acSAndroid Build Coastguard Worker 	return 0;
67*1c60b9acSAndroid Build Coastguard Worker }
68*1c60b9acSAndroid Build Coastguard Worker 
69*1c60b9acSAndroid Build Coastguard Worker #endif
70*1c60b9acSAndroid Build Coastguard Worker 
71*1c60b9acSAndroid Build Coastguard Worker int
lws_ssl_client_bio_create(struct lws * wsi)72*1c60b9acSAndroid Build Coastguard Worker lws_ssl_client_bio_create(struct lws *wsi)
73*1c60b9acSAndroid Build Coastguard Worker {
74*1c60b9acSAndroid Build Coastguard Worker 	char hostname[128], *p;
75*1c60b9acSAndroid Build Coastguard Worker 	const char *alpn_comma = wsi->a.context->tls.alpn_default;
76*1c60b9acSAndroid Build Coastguard Worker 	struct alpn_ctx protos;
77*1c60b9acSAndroid Build Coastguard Worker 	int fl = SSL_VERIFY_PEER;
78*1c60b9acSAndroid Build Coastguard Worker 
79*1c60b9acSAndroid Build Coastguard Worker 	if (wsi->stash)
80*1c60b9acSAndroid Build Coastguard Worker 		lws_strncpy(hostname, wsi->stash->cis[CIS_HOST], sizeof(hostname));
81*1c60b9acSAndroid Build Coastguard Worker 	else
82*1c60b9acSAndroid Build Coastguard Worker 		if (lws_hdr_copy(wsi, hostname, sizeof(hostname),
83*1c60b9acSAndroid Build Coastguard Worker 				_WSI_TOKEN_CLIENT_HOST) <= 0) {
84*1c60b9acSAndroid Build Coastguard Worker 			lwsl_err("%s: Unable to get hostname\n", __func__);
85*1c60b9acSAndroid Build Coastguard Worker 
86*1c60b9acSAndroid Build Coastguard Worker 			return -1;
87*1c60b9acSAndroid Build Coastguard Worker 		}
88*1c60b9acSAndroid Build Coastguard Worker 
89*1c60b9acSAndroid Build Coastguard Worker 	/*
90*1c60b9acSAndroid Build Coastguard Worker 	 * remove any :port part on the hostname... necessary for network
91*1c60b9acSAndroid Build Coastguard Worker 	 * connection but typical certificates do not contain it
92*1c60b9acSAndroid Build Coastguard Worker 	 */
93*1c60b9acSAndroid Build Coastguard Worker 	p = hostname;
94*1c60b9acSAndroid Build Coastguard Worker 	while (*p) {
95*1c60b9acSAndroid Build Coastguard Worker 		if (*p == ':') {
96*1c60b9acSAndroid Build Coastguard Worker 			*p = '\0';
97*1c60b9acSAndroid Build Coastguard Worker 			break;
98*1c60b9acSAndroid Build Coastguard Worker 		}
99*1c60b9acSAndroid Build Coastguard Worker 		p++;
100*1c60b9acSAndroid Build Coastguard Worker 	}
101*1c60b9acSAndroid Build Coastguard Worker 
102*1c60b9acSAndroid Build Coastguard Worker 	wsi->tls.ssl = SSL_new(wsi->a.vhost->tls.ssl_client_ctx);
103*1c60b9acSAndroid Build Coastguard Worker 	if (!wsi->tls.ssl) {
104*1c60b9acSAndroid Build Coastguard Worker 		lwsl_info("%s: SSL_new() failed\n", __func__);
105*1c60b9acSAndroid Build Coastguard Worker 		return -1;
106*1c60b9acSAndroid Build Coastguard Worker 	}
107*1c60b9acSAndroid Build Coastguard Worker 
108*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_TLS_SESSIONS)
109*1c60b9acSAndroid Build Coastguard Worker 	if (!(wsi->a.vhost->options & LWS_SERVER_OPTION_DISABLE_TLS_SESSION_CACHE))
110*1c60b9acSAndroid Build Coastguard Worker 		lws_tls_reuse_session(wsi);
111*1c60b9acSAndroid Build Coastguard Worker #endif
112*1c60b9acSAndroid Build Coastguard Worker 
113*1c60b9acSAndroid Build Coastguard Worker 	if (wsi->a.vhost->tls.ssl_info_event_mask)
114*1c60b9acSAndroid Build Coastguard Worker 		SSL_set_info_callback(wsi->tls.ssl, lws_ssl_info_callback);
115*1c60b9acSAndroid Build Coastguard Worker 
116*1c60b9acSAndroid Build Coastguard Worker 	if (!(wsi->tls.use_ssl & LCCSCF_SKIP_SERVER_CERT_HOSTNAME_CHECK)) {
117*1c60b9acSAndroid Build Coastguard Worker 		X509_VERIFY_PARAM *param = SSL_get0_param(wsi->tls.ssl);
118*1c60b9acSAndroid Build Coastguard Worker 		/* Enable automatic hostname checks */
119*1c60b9acSAndroid Build Coastguard Worker 	//	X509_VERIFY_PARAM_set_hostflags(param,
120*1c60b9acSAndroid Build Coastguard Worker 	//				X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS);
121*1c60b9acSAndroid Build Coastguard Worker 		lwsl_info("%s: setting hostname %s\n", __func__, hostname);
122*1c60b9acSAndroid Build Coastguard Worker 		if (X509_VERIFY_PARAM_set1_host(param, hostname, 0) != 1)
123*1c60b9acSAndroid Build Coastguard Worker 			return -1;
124*1c60b9acSAndroid Build Coastguard Worker 	}
125*1c60b9acSAndroid Build Coastguard Worker 
126*1c60b9acSAndroid Build Coastguard Worker 	if (wsi->a.vhost->tls.alpn)
127*1c60b9acSAndroid Build Coastguard Worker 		alpn_comma = wsi->a.vhost->tls.alpn;
128*1c60b9acSAndroid Build Coastguard Worker 
129*1c60b9acSAndroid Build Coastguard Worker 	if (wsi->stash) {
130*1c60b9acSAndroid Build Coastguard Worker 		lws_strncpy(hostname, wsi->stash->cis[CIS_HOST],
131*1c60b9acSAndroid Build Coastguard Worker 				sizeof(hostname));
132*1c60b9acSAndroid Build Coastguard Worker 		if (wsi->stash->cis[CIS_ALPN])
133*1c60b9acSAndroid Build Coastguard Worker 			alpn_comma = wsi->stash->cis[CIS_ALPN];
134*1c60b9acSAndroid Build Coastguard Worker 	} else {
135*1c60b9acSAndroid Build Coastguard Worker 		if (lws_hdr_copy(wsi, hostname, sizeof(hostname),
136*1c60b9acSAndroid Build Coastguard Worker 				_WSI_TOKEN_CLIENT_ALPN) > 0)
137*1c60b9acSAndroid Build Coastguard Worker 			alpn_comma = hostname;
138*1c60b9acSAndroid Build Coastguard Worker 	}
139*1c60b9acSAndroid Build Coastguard Worker 
140*1c60b9acSAndroid Build Coastguard Worker 	lwsl_info("%s: %s: client conn sending ALPN list '%s'\n",
141*1c60b9acSAndroid Build Coastguard Worker 		  __func__, lws_wsi_tag(wsi), alpn_comma);
142*1c60b9acSAndroid Build Coastguard Worker 
143*1c60b9acSAndroid Build Coastguard Worker 	protos.len = (uint8_t)lws_alpn_comma_to_openssl(alpn_comma, protos.data,
144*1c60b9acSAndroid Build Coastguard Worker 					       sizeof(protos.data) - 1);
145*1c60b9acSAndroid Build Coastguard Worker 
146*1c60b9acSAndroid Build Coastguard Worker 	/* with mbedtls, protos is not pointed to after exit from this call */
147*1c60b9acSAndroid Build Coastguard Worker 	SSL_set_alpn_select_cb(wsi->tls.ssl, &protos);
148*1c60b9acSAndroid Build Coastguard Worker 
149*1c60b9acSAndroid Build Coastguard Worker 	if (wsi->flags & LCCSCF_ALLOW_SELFSIGNED) {
150*1c60b9acSAndroid Build Coastguard Worker 		lwsl_notice("%s: allowing selfsigned\n", __func__);
151*1c60b9acSAndroid Build Coastguard Worker 		fl = SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
152*1c60b9acSAndroid Build Coastguard Worker 	}
153*1c60b9acSAndroid Build Coastguard Worker 
154*1c60b9acSAndroid Build Coastguard Worker 	if (wsi->flags & LCCSCF_ALLOW_INSECURE)
155*1c60b9acSAndroid Build Coastguard Worker 		fl = SSL_VERIFY_NONE;
156*1c60b9acSAndroid Build Coastguard Worker 
157*1c60b9acSAndroid Build Coastguard Worker 	/*
158*1c60b9acSAndroid Build Coastguard Worker 	 * use server name indication (SNI), if supported,
159*1c60b9acSAndroid Build Coastguard Worker 	 * when establishing connection
160*1c60b9acSAndroid Build Coastguard Worker 	 */
161*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_TLS_JIT_TRUST)
162*1c60b9acSAndroid Build Coastguard Worker 	SSL_set_verify(wsi->tls.ssl, SSL_VERIFY_PEER,
163*1c60b9acSAndroid Build Coastguard Worker 			lws_mbedtls_client_verify_callback);
164*1c60b9acSAndroid Build Coastguard Worker 	(void)fl;
165*1c60b9acSAndroid Build Coastguard Worker #else
166*1c60b9acSAndroid Build Coastguard Worker 	SSL_set_verify(wsi->tls.ssl, fl, NULL);
167*1c60b9acSAndroid Build Coastguard Worker #endif
168*1c60b9acSAndroid Build Coastguard Worker 
169*1c60b9acSAndroid Build Coastguard Worker 	SSL_set_fd(wsi->tls.ssl, (int)wsi->desc.sockfd);
170*1c60b9acSAndroid Build Coastguard Worker 
171*1c60b9acSAndroid Build Coastguard Worker 	if (wsi->sys_tls_client_cert) {
172*1c60b9acSAndroid Build Coastguard Worker 		lws_system_blob_t *b = lws_system_get_blob(wsi->a.context,
173*1c60b9acSAndroid Build Coastguard Worker 					LWS_SYSBLOB_TYPE_CLIENT_CERT_DER,
174*1c60b9acSAndroid Build Coastguard Worker 					wsi->sys_tls_client_cert - 1);
175*1c60b9acSAndroid Build Coastguard Worker 		const uint8_t *pem_data = NULL;
176*1c60b9acSAndroid Build Coastguard Worker 		uint8_t *data = NULL;
177*1c60b9acSAndroid Build Coastguard Worker 		lws_filepos_t flen;
178*1c60b9acSAndroid Build Coastguard Worker 		size_t size;
179*1c60b9acSAndroid Build Coastguard Worker 		int err = 0;
180*1c60b9acSAndroid Build Coastguard Worker 
181*1c60b9acSAndroid Build Coastguard Worker 		if (!b)
182*1c60b9acSAndroid Build Coastguard Worker 			goto no_client_cert;
183*1c60b9acSAndroid Build Coastguard Worker 
184*1c60b9acSAndroid Build Coastguard Worker 		/*
185*1c60b9acSAndroid Build Coastguard Worker 		 * Set up the per-connection client cert
186*1c60b9acSAndroid Build Coastguard Worker 		 */
187*1c60b9acSAndroid Build Coastguard Worker 
188*1c60b9acSAndroid Build Coastguard Worker 		size = lws_system_blob_get_size(b);
189*1c60b9acSAndroid Build Coastguard Worker 		if (!size)
190*1c60b9acSAndroid Build Coastguard Worker 			goto no_client_cert;
191*1c60b9acSAndroid Build Coastguard Worker 
192*1c60b9acSAndroid Build Coastguard Worker 		if (lws_system_blob_get_single_ptr(b, &pem_data))
193*1c60b9acSAndroid Build Coastguard Worker 			goto no_client_cert;
194*1c60b9acSAndroid Build Coastguard Worker 
195*1c60b9acSAndroid Build Coastguard Worker 		if (lws_tls_alloc_pem_to_der_file(wsi->a.context, NULL,
196*1c60b9acSAndroid Build Coastguard Worker 						  (const char *)pem_data, size,
197*1c60b9acSAndroid Build Coastguard Worker 						  &data, &flen))
198*1c60b9acSAndroid Build Coastguard Worker 			goto no_client_cert;
199*1c60b9acSAndroid Build Coastguard Worker 		size = (size_t) flen;
200*1c60b9acSAndroid Build Coastguard Worker 
201*1c60b9acSAndroid Build Coastguard Worker 		err = SSL_use_certificate_ASN1(wsi->tls.ssl, data, (int)size);
202*1c60b9acSAndroid Build Coastguard Worker 		lws_free_set_NULL(data);
203*1c60b9acSAndroid Build Coastguard Worker 		if (err != 1)
204*1c60b9acSAndroid Build Coastguard Worker 			goto no_client_cert;
205*1c60b9acSAndroid Build Coastguard Worker 
206*1c60b9acSAndroid Build Coastguard Worker 		b = lws_system_get_blob(wsi->a.context,
207*1c60b9acSAndroid Build Coastguard Worker 					LWS_SYSBLOB_TYPE_CLIENT_KEY_DER,
208*1c60b9acSAndroid Build Coastguard Worker 					wsi->sys_tls_client_cert - 1);
209*1c60b9acSAndroid Build Coastguard Worker 		if (!b)
210*1c60b9acSAndroid Build Coastguard Worker 			goto no_client_cert;
211*1c60b9acSAndroid Build Coastguard Worker 		size = lws_system_blob_get_size(b);
212*1c60b9acSAndroid Build Coastguard Worker 		if (!size)
213*1c60b9acSAndroid Build Coastguard Worker 			goto no_client_cert;
214*1c60b9acSAndroid Build Coastguard Worker 
215*1c60b9acSAndroid Build Coastguard Worker 		if (lws_system_blob_get_single_ptr(b, &pem_data))
216*1c60b9acSAndroid Build Coastguard Worker 			goto no_client_cert;
217*1c60b9acSAndroid Build Coastguard Worker 
218*1c60b9acSAndroid Build Coastguard Worker 		if (lws_tls_alloc_pem_to_der_file(wsi->a.context, NULL,
219*1c60b9acSAndroid Build Coastguard Worker 						  (const char *)pem_data, size,
220*1c60b9acSAndroid Build Coastguard Worker 						  &data, &flen))
221*1c60b9acSAndroid Build Coastguard Worker 			goto no_client_cert;
222*1c60b9acSAndroid Build Coastguard Worker 		size = (size_t) flen;
223*1c60b9acSAndroid Build Coastguard Worker 
224*1c60b9acSAndroid Build Coastguard Worker 		err = SSL_use_PrivateKey_ASN1(0, wsi->tls.ssl, data, (int)size);
225*1c60b9acSAndroid Build Coastguard Worker 		lws_free_set_NULL(data);
226*1c60b9acSAndroid Build Coastguard Worker 		if (err != 1)
227*1c60b9acSAndroid Build Coastguard Worker 			goto no_client_cert;
228*1c60b9acSAndroid Build Coastguard Worker 
229*1c60b9acSAndroid Build Coastguard Worker 		/* no wrapper api for check key */
230*1c60b9acSAndroid Build Coastguard Worker 
231*1c60b9acSAndroid Build Coastguard Worker 		lwsl_notice("%s: set system client cert %u\n", __func__,
232*1c60b9acSAndroid Build Coastguard Worker 				wsi->sys_tls_client_cert - 1);
233*1c60b9acSAndroid Build Coastguard Worker 	}
234*1c60b9acSAndroid Build Coastguard Worker 
235*1c60b9acSAndroid Build Coastguard Worker 	return 0;
236*1c60b9acSAndroid Build Coastguard Worker 
237*1c60b9acSAndroid Build Coastguard Worker no_client_cert:
238*1c60b9acSAndroid Build Coastguard Worker 	lwsl_err("%s: unable to set up system client cert %d\n", __func__,
239*1c60b9acSAndroid Build Coastguard Worker 			wsi->sys_tls_client_cert - 1);
240*1c60b9acSAndroid Build Coastguard Worker 
241*1c60b9acSAndroid Build Coastguard Worker 	return 1;
242*1c60b9acSAndroid Build Coastguard Worker }
243*1c60b9acSAndroid Build Coastguard Worker 
ERR_get_error(void)244*1c60b9acSAndroid Build Coastguard Worker int ERR_get_error(void)
245*1c60b9acSAndroid Build Coastguard Worker {
246*1c60b9acSAndroid Build Coastguard Worker 	return 0;
247*1c60b9acSAndroid Build Coastguard Worker }
248*1c60b9acSAndroid Build Coastguard Worker 
249*1c60b9acSAndroid Build Coastguard Worker enum lws_ssl_capable_status
lws_tls_client_connect(struct lws * wsi,char * errbuf,size_t elen)250*1c60b9acSAndroid Build Coastguard Worker lws_tls_client_connect(struct lws *wsi, char *errbuf, size_t elen)
251*1c60b9acSAndroid Build Coastguard Worker {
252*1c60b9acSAndroid Build Coastguard Worker 	int m, n = SSL_connect(wsi->tls.ssl), en;
253*1c60b9acSAndroid Build Coastguard Worker 
254*1c60b9acSAndroid Build Coastguard Worker 	if (n == 1) {
255*1c60b9acSAndroid Build Coastguard Worker 		lws_tls_server_conn_alpn(wsi);
256*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_TLS_SESSIONS)
257*1c60b9acSAndroid Build Coastguard Worker 		lws_tls_session_new_mbedtls(wsi);
258*1c60b9acSAndroid Build Coastguard Worker #endif
259*1c60b9acSAndroid Build Coastguard Worker 		lwsl_info("%s: client connect OK\n", __func__);
260*1c60b9acSAndroid Build Coastguard Worker 		return LWS_SSL_CAPABLE_DONE;
261*1c60b9acSAndroid Build Coastguard Worker 	}
262*1c60b9acSAndroid Build Coastguard Worker 
263*1c60b9acSAndroid Build Coastguard Worker 	en = (int)LWS_ERRNO;
264*1c60b9acSAndroid Build Coastguard Worker 	m = SSL_get_error(wsi->tls.ssl, n);
265*1c60b9acSAndroid Build Coastguard Worker 
266*1c60b9acSAndroid Build Coastguard Worker 	if (m == SSL_ERROR_WANT_READ || SSL_want_read(wsi->tls.ssl))
267*1c60b9acSAndroid Build Coastguard Worker 		return LWS_SSL_CAPABLE_MORE_SERVICE_READ;
268*1c60b9acSAndroid Build Coastguard Worker 
269*1c60b9acSAndroid Build Coastguard Worker 	if (m == SSL_ERROR_WANT_WRITE || SSL_want_write(wsi->tls.ssl))
270*1c60b9acSAndroid Build Coastguard Worker 		return LWS_SSL_CAPABLE_MORE_SERVICE_WRITE;
271*1c60b9acSAndroid Build Coastguard Worker 
272*1c60b9acSAndroid Build Coastguard Worker 	if (!n) /* we don't know what he wants, but he says to retry */
273*1c60b9acSAndroid Build Coastguard Worker 		return LWS_SSL_CAPABLE_MORE_SERVICE;
274*1c60b9acSAndroid Build Coastguard Worker 
275*1c60b9acSAndroid Build Coastguard Worker 	if (m == SSL_ERROR_SYSCALL && !en)
276*1c60b9acSAndroid Build Coastguard Worker 		return LWS_SSL_CAPABLE_MORE_SERVICE;
277*1c60b9acSAndroid Build Coastguard Worker 
278*1c60b9acSAndroid Build Coastguard Worker 	lws_snprintf(errbuf, elen, "mbedtls connect %d %d %d", n, m, en);
279*1c60b9acSAndroid Build Coastguard Worker 
280*1c60b9acSAndroid Build Coastguard Worker 	return LWS_SSL_CAPABLE_ERROR;
281*1c60b9acSAndroid Build Coastguard Worker }
282*1c60b9acSAndroid Build Coastguard Worker 
283*1c60b9acSAndroid Build Coastguard Worker int
lws_tls_client_confirm_peer_cert(struct lws * wsi,char * ebuf,size_t ebuf_len)284*1c60b9acSAndroid Build Coastguard Worker lws_tls_client_confirm_peer_cert(struct lws *wsi, char *ebuf, size_t ebuf_len)
285*1c60b9acSAndroid Build Coastguard Worker {
286*1c60b9acSAndroid Build Coastguard Worker 	int n;
287*1c60b9acSAndroid Build Coastguard Worker 	unsigned int avoid = 0;
288*1c60b9acSAndroid Build Coastguard Worker 	X509 *peer = SSL_get_peer_certificate(wsi->tls.ssl);
289*1c60b9acSAndroid Build Coastguard Worker 	struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi];
290*1c60b9acSAndroid Build Coastguard Worker 	const char *type = "";
291*1c60b9acSAndroid Build Coastguard Worker 	char *sb = (char *)&pt->serv_buf[0];
292*1c60b9acSAndroid Build Coastguard Worker 
293*1c60b9acSAndroid Build Coastguard Worker 	if (!peer) {
294*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_SYS_METRICS)
295*1c60b9acSAndroid Build Coastguard Worker 		lws_metrics_hist_bump_describe_wsi(wsi, lws_metrics_priv_to_pub(
296*1c60b9acSAndroid Build Coastguard Worker 					wsi->a.context->mth_conn_failures),
297*1c60b9acSAndroid Build Coastguard Worker 						   "tls=\"nocert\"");
298*1c60b9acSAndroid Build Coastguard Worker #endif
299*1c60b9acSAndroid Build Coastguard Worker 		lwsl_info("peer did not provide cert\n");
300*1c60b9acSAndroid Build Coastguard Worker 		lws_snprintf(ebuf, ebuf_len, "no peer cert");
301*1c60b9acSAndroid Build Coastguard Worker 
302*1c60b9acSAndroid Build Coastguard Worker 		return -1;
303*1c60b9acSAndroid Build Coastguard Worker 	}
304*1c60b9acSAndroid Build Coastguard Worker 
305*1c60b9acSAndroid Build Coastguard Worker 	n = (int)SSL_get_verify_result(wsi->tls.ssl);
306*1c60b9acSAndroid Build Coastguard Worker 	lwsl_debug("get_verify says %d\n", n);
307*1c60b9acSAndroid Build Coastguard Worker 
308*1c60b9acSAndroid Build Coastguard Worker 	switch (n) {
309*1c60b9acSAndroid Build Coastguard Worker 	case X509_V_OK:
310*1c60b9acSAndroid Build Coastguard Worker 		return 0;
311*1c60b9acSAndroid Build Coastguard Worker 
312*1c60b9acSAndroid Build Coastguard Worker 	case X509_V_ERR_HOSTNAME_MISMATCH:
313*1c60b9acSAndroid Build Coastguard Worker 		type = "hostname";
314*1c60b9acSAndroid Build Coastguard Worker 		avoid = LCCSCF_SKIP_SERVER_CERT_HOSTNAME_CHECK;
315*1c60b9acSAndroid Build Coastguard Worker 		break;
316*1c60b9acSAndroid Build Coastguard Worker 
317*1c60b9acSAndroid Build Coastguard Worker 	case X509_V_ERR_INVALID_CA:
318*1c60b9acSAndroid Build Coastguard Worker 		type = "invalidca";
319*1c60b9acSAndroid Build Coastguard Worker 		avoid = LCCSCF_ALLOW_SELFSIGNED;
320*1c60b9acSAndroid Build Coastguard Worker 		break;
321*1c60b9acSAndroid Build Coastguard Worker 
322*1c60b9acSAndroid Build Coastguard Worker 	case X509_V_ERR_CERT_NOT_YET_VALID:
323*1c60b9acSAndroid Build Coastguard Worker 		type = "notyetvalid";
324*1c60b9acSAndroid Build Coastguard Worker 		avoid = LCCSCF_ALLOW_EXPIRED;
325*1c60b9acSAndroid Build Coastguard Worker 		break;
326*1c60b9acSAndroid Build Coastguard Worker 
327*1c60b9acSAndroid Build Coastguard Worker 	case X509_V_ERR_CERT_HAS_EXPIRED:
328*1c60b9acSAndroid Build Coastguard Worker 		type = "expired";
329*1c60b9acSAndroid Build Coastguard Worker 		avoid = LCCSCF_ALLOW_EXPIRED;
330*1c60b9acSAndroid Build Coastguard Worker 		break;
331*1c60b9acSAndroid Build Coastguard Worker 	}
332*1c60b9acSAndroid Build Coastguard Worker 
333*1c60b9acSAndroid Build Coastguard Worker 	lwsl_info("%s: cert problem: %s\n", __func__, type);
334*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_SYS_METRICS)
335*1c60b9acSAndroid Build Coastguard Worker 	{
336*1c60b9acSAndroid Build Coastguard Worker 		char buckname[64];
337*1c60b9acSAndroid Build Coastguard Worker 		lws_snprintf(buckname, sizeof(buckname), "tls=\"%s\"", type);
338*1c60b9acSAndroid Build Coastguard Worker 		lws_metrics_hist_bump_describe_wsi(wsi,
339*1c60b9acSAndroid Build Coastguard Worker 		     lws_metrics_priv_to_pub(wsi->a.context->mth_conn_failures),
340*1c60b9acSAndroid Build Coastguard Worker 			      buckname);
341*1c60b9acSAndroid Build Coastguard Worker 	}
342*1c60b9acSAndroid Build Coastguard Worker #endif
343*1c60b9acSAndroid Build Coastguard Worker 	if (wsi->tls.use_ssl & avoid) {
344*1c60b9acSAndroid Build Coastguard Worker 		lwsl_info("%s: allowing anyway\n", __func__);
345*1c60b9acSAndroid Build Coastguard Worker 
346*1c60b9acSAndroid Build Coastguard Worker 		return 0;
347*1c60b9acSAndroid Build Coastguard Worker 	}
348*1c60b9acSAndroid Build Coastguard Worker 
349*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_TLS_JIT_TRUST)
350*1c60b9acSAndroid Build Coastguard Worker 	if (n == X509_V_ERR_INVALID_CA)
351*1c60b9acSAndroid Build Coastguard Worker 	    lws_tls_jit_trust_sort_kids(wsi, &wsi->tls.ssl->kid_chain);
352*1c60b9acSAndroid Build Coastguard Worker #endif
353*1c60b9acSAndroid Build Coastguard Worker 	lws_snprintf(ebuf, ebuf_len,
354*1c60b9acSAndroid Build Coastguard Worker 		"server's cert didn't look good, %s (use_ssl 0x%x) X509_V_ERR = %d: %s\n",
355*1c60b9acSAndroid Build Coastguard Worker 		type, (unsigned int)wsi->tls.use_ssl, n,
356*1c60b9acSAndroid Build Coastguard Worker 		ERR_error_string((unsigned long)n, sb));
357*1c60b9acSAndroid Build Coastguard Worker 
358*1c60b9acSAndroid Build Coastguard Worker 	lwsl_info("%s\n", ebuf);
359*1c60b9acSAndroid Build Coastguard Worker 
360*1c60b9acSAndroid Build Coastguard Worker 	lws_tls_err_describe_clear();
361*1c60b9acSAndroid Build Coastguard Worker 
362*1c60b9acSAndroid Build Coastguard Worker 	return -1;
363*1c60b9acSAndroid Build Coastguard Worker }
364*1c60b9acSAndroid Build Coastguard Worker 
365*1c60b9acSAndroid Build Coastguard Worker int
lws_tls_client_create_vhost_context(struct lws_vhost * vh,const struct lws_context_creation_info * info,const char * cipher_list,const char * ca_filepath,const void * ca_mem,unsigned int ca_mem_len,const char * cert_filepath,const void * cert_mem,unsigned int cert_mem_len,const char * private_key_filepath,const void * key_mem,unsigned int key_mem_len)366*1c60b9acSAndroid Build Coastguard Worker lws_tls_client_create_vhost_context(struct lws_vhost *vh,
367*1c60b9acSAndroid Build Coastguard Worker 				    const struct lws_context_creation_info *info,
368*1c60b9acSAndroid Build Coastguard Worker 				    const char *cipher_list,
369*1c60b9acSAndroid Build Coastguard Worker 				    const char *ca_filepath,
370*1c60b9acSAndroid Build Coastguard Worker 				    const void *ca_mem,
371*1c60b9acSAndroid Build Coastguard Worker 				    unsigned int ca_mem_len,
372*1c60b9acSAndroid Build Coastguard Worker 				    const char *cert_filepath,
373*1c60b9acSAndroid Build Coastguard Worker 				    const void *cert_mem,
374*1c60b9acSAndroid Build Coastguard Worker 				    unsigned int cert_mem_len,
375*1c60b9acSAndroid Build Coastguard Worker 				    const char *private_key_filepath,
376*1c60b9acSAndroid Build Coastguard Worker 					const void *key_mem,
377*1c60b9acSAndroid Build Coastguard Worker 					unsigned int key_mem_len
378*1c60b9acSAndroid Build Coastguard Worker 					)
379*1c60b9acSAndroid Build Coastguard Worker {
380*1c60b9acSAndroid Build Coastguard Worker 	X509 *d2i_X509(X509 **cert, const unsigned char *buffer, long len);
381*1c60b9acSAndroid Build Coastguard Worker 	SSL_METHOD *method = (SSL_METHOD *)TLS_client_method();
382*1c60b9acSAndroid Build Coastguard Worker 	unsigned long error;
383*1c60b9acSAndroid Build Coastguard Worker 	int n;
384*1c60b9acSAndroid Build Coastguard Worker 
385*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_TLS_SESSIONS)
386*1c60b9acSAndroid Build Coastguard Worker 	vh->tls_session_cache_max = info->tls_session_cache_max ?
387*1c60b9acSAndroid Build Coastguard Worker 				    info->tls_session_cache_max : 10;
388*1c60b9acSAndroid Build Coastguard Worker 	lws_tls_session_cache(vh, info->tls_session_timeout);
389*1c60b9acSAndroid Build Coastguard Worker #endif
390*1c60b9acSAndroid Build Coastguard Worker 
391*1c60b9acSAndroid Build Coastguard Worker 	if (!method) {
392*1c60b9acSAndroid Build Coastguard Worker 		error = (unsigned long)ERR_get_error();
393*1c60b9acSAndroid Build Coastguard Worker 		lwsl_err("problem creating ssl method %lu: %s\n",
394*1c60b9acSAndroid Build Coastguard Worker 			error, ERR_error_string(error,
395*1c60b9acSAndroid Build Coastguard Worker 				      (char *)vh->context->pt[0].serv_buf));
396*1c60b9acSAndroid Build Coastguard Worker 		return 1;
397*1c60b9acSAndroid Build Coastguard Worker 	}
398*1c60b9acSAndroid Build Coastguard Worker 	/* create context */
399*1c60b9acSAndroid Build Coastguard Worker 	vh->tls.ssl_client_ctx = SSL_CTX_new(method, &vh->context->mcdc);
400*1c60b9acSAndroid Build Coastguard Worker 	if (!vh->tls.ssl_client_ctx) {
401*1c60b9acSAndroid Build Coastguard Worker 		error = (unsigned long)ERR_get_error();
402*1c60b9acSAndroid Build Coastguard Worker 		lwsl_err("problem creating ssl context %lu: %s\n",
403*1c60b9acSAndroid Build Coastguard Worker 			error, ERR_error_string(error,
404*1c60b9acSAndroid Build Coastguard Worker 				      (char *)vh->context->pt[0].serv_buf));
405*1c60b9acSAndroid Build Coastguard Worker 		return 1;
406*1c60b9acSAndroid Build Coastguard Worker 	}
407*1c60b9acSAndroid Build Coastguard Worker 
408*1c60b9acSAndroid Build Coastguard Worker 	if (!ca_filepath && (!ca_mem || !ca_mem_len))
409*1c60b9acSAndroid Build Coastguard Worker 		return 0;
410*1c60b9acSAndroid Build Coastguard Worker 
411*1c60b9acSAndroid Build Coastguard Worker 	if (ca_filepath) {
412*1c60b9acSAndroid Build Coastguard Worker #if !defined(LWS_PLAT_OPTEE)
413*1c60b9acSAndroid Build Coastguard Worker 		uint8_t *buf;
414*1c60b9acSAndroid Build Coastguard Worker 		lws_filepos_t len;
415*1c60b9acSAndroid Build Coastguard Worker 
416*1c60b9acSAndroid Build Coastguard Worker 		if (alloc_file(vh->context, ca_filepath, &buf, &len)) {
417*1c60b9acSAndroid Build Coastguard Worker 			lwsl_err("Load CA cert file %s failed\n", ca_filepath);
418*1c60b9acSAndroid Build Coastguard Worker 			return 1;
419*1c60b9acSAndroid Build Coastguard Worker 		}
420*1c60b9acSAndroid Build Coastguard Worker 		vh->tls.x509_client_CA = d2i_X509(NULL, buf, (long)len);
421*1c60b9acSAndroid Build Coastguard Worker 		free(buf);
422*1c60b9acSAndroid Build Coastguard Worker 
423*1c60b9acSAndroid Build Coastguard Worker 		lwsl_info("Loading vh %s client CA for verification %s\n", vh->name, ca_filepath);
424*1c60b9acSAndroid Build Coastguard Worker #endif
425*1c60b9acSAndroid Build Coastguard Worker 	} else {
426*1c60b9acSAndroid Build Coastguard Worker 		vh->tls.x509_client_CA = d2i_X509(NULL, (uint8_t*)ca_mem, (long)ca_mem_len);
427*1c60b9acSAndroid Build Coastguard Worker 		lwsl_info("%s: using mem client CA cert %d\n",
428*1c60b9acSAndroid Build Coastguard Worker 			    __func__, ca_mem_len);
429*1c60b9acSAndroid Build Coastguard Worker 	}
430*1c60b9acSAndroid Build Coastguard Worker 
431*1c60b9acSAndroid Build Coastguard Worker 	if (!vh->tls.x509_client_CA) {
432*1c60b9acSAndroid Build Coastguard Worker 		lwsl_err("client CA: x509 parse failed\n");
433*1c60b9acSAndroid Build Coastguard Worker 		return 1;
434*1c60b9acSAndroid Build Coastguard Worker 	}
435*1c60b9acSAndroid Build Coastguard Worker 
436*1c60b9acSAndroid Build Coastguard Worker 	if (!vh->tls.ssl_ctx)
437*1c60b9acSAndroid Build Coastguard Worker 		SSL_CTX_add_client_CA(vh->tls.ssl_client_ctx, vh->tls.x509_client_CA);
438*1c60b9acSAndroid Build Coastguard Worker 	else
439*1c60b9acSAndroid Build Coastguard Worker 		SSL_CTX_add_client_CA(vh->tls.ssl_ctx, vh->tls.x509_client_CA);
440*1c60b9acSAndroid Build Coastguard Worker 
441*1c60b9acSAndroid Build Coastguard Worker 	/* support for client-side certificate authentication */
442*1c60b9acSAndroid Build Coastguard Worker 	if (cert_filepath) {
443*1c60b9acSAndroid Build Coastguard Worker #if !defined(LWS_PLAT_OPTEE)
444*1c60b9acSAndroid Build Coastguard Worker 		uint8_t *buf;
445*1c60b9acSAndroid Build Coastguard Worker 		lws_filepos_t amount;
446*1c60b9acSAndroid Build Coastguard Worker 
447*1c60b9acSAndroid Build Coastguard Worker 		if (lws_tls_use_any_upgrade_check_extant(cert_filepath) !=
448*1c60b9acSAndroid Build Coastguard Worker 				LWS_TLS_EXTANT_YES &&
449*1c60b9acSAndroid Build Coastguard Worker 		    (info->options & LWS_SERVER_OPTION_IGNORE_MISSING_CERT))
450*1c60b9acSAndroid Build Coastguard Worker 			return 0;
451*1c60b9acSAndroid Build Coastguard Worker 
452*1c60b9acSAndroid Build Coastguard Worker 		lwsl_notice("%s: doing cert filepath %s\n", __func__,
453*1c60b9acSAndroid Build Coastguard Worker 				cert_filepath);
454*1c60b9acSAndroid Build Coastguard Worker 
455*1c60b9acSAndroid Build Coastguard Worker 		if (alloc_file(vh->context, cert_filepath, &buf, &amount))
456*1c60b9acSAndroid Build Coastguard Worker 			return 1;
457*1c60b9acSAndroid Build Coastguard Worker 
458*1c60b9acSAndroid Build Coastguard Worker 		buf[amount++] = '\0';
459*1c60b9acSAndroid Build Coastguard Worker 
460*1c60b9acSAndroid Build Coastguard Worker 		n = SSL_CTX_use_certificate_ASN1(vh->tls.ssl_client_ctx,
461*1c60b9acSAndroid Build Coastguard Worker 				(int)amount, buf);
462*1c60b9acSAndroid Build Coastguard Worker 		lws_free(buf);
463*1c60b9acSAndroid Build Coastguard Worker 		if (n < 1) {
464*1c60b9acSAndroid Build Coastguard Worker 			lwsl_err("problem %d getting cert '%s'\n", n,
465*1c60b9acSAndroid Build Coastguard Worker 				 cert_filepath);
466*1c60b9acSAndroid Build Coastguard Worker 			lws_tls_err_describe_clear();
467*1c60b9acSAndroid Build Coastguard Worker 			return 1;
468*1c60b9acSAndroid Build Coastguard Worker 		}
469*1c60b9acSAndroid Build Coastguard Worker 
470*1c60b9acSAndroid Build Coastguard Worker 		lwsl_info("Loaded client cert %s\n", cert_filepath);
471*1c60b9acSAndroid Build Coastguard Worker #endif
472*1c60b9acSAndroid Build Coastguard Worker 	} else if (cert_mem && cert_mem_len) {
473*1c60b9acSAndroid Build Coastguard Worker 		/* lwsl_hexdump_notice(cert_mem, cert_mem_len - 1); */
474*1c60b9acSAndroid Build Coastguard Worker 		n = SSL_CTX_use_certificate_ASN1(vh->tls.ssl_client_ctx,
475*1c60b9acSAndroid Build Coastguard Worker 						 (int)cert_mem_len, cert_mem);
476*1c60b9acSAndroid Build Coastguard Worker 		if (n < 1) {
477*1c60b9acSAndroid Build Coastguard Worker 			lwsl_err("%s: (mbedtls) problem interpreting client cert\n",
478*1c60b9acSAndroid Build Coastguard Worker 				 __func__);
479*1c60b9acSAndroid Build Coastguard Worker 			lws_tls_err_describe_clear();
480*1c60b9acSAndroid Build Coastguard Worker 			return 1;
481*1c60b9acSAndroid Build Coastguard Worker 		}
482*1c60b9acSAndroid Build Coastguard Worker 		lwsl_info("%s: using mem client cert %d\n",
483*1c60b9acSAndroid Build Coastguard Worker 			    __func__, cert_mem_len);
484*1c60b9acSAndroid Build Coastguard Worker 	}
485*1c60b9acSAndroid Build Coastguard Worker 
486*1c60b9acSAndroid Build Coastguard Worker 	if (private_key_filepath) {
487*1c60b9acSAndroid Build Coastguard Worker #if !defined(LWS_PLAT_OPTEE)
488*1c60b9acSAndroid Build Coastguard Worker 
489*1c60b9acSAndroid Build Coastguard Worker 		uint8_t *buf;
490*1c60b9acSAndroid Build Coastguard Worker 		lws_filepos_t amount;
491*1c60b9acSAndroid Build Coastguard Worker 
492*1c60b9acSAndroid Build Coastguard Worker 		lwsl_notice("%s: doing private key filepath %s\n", __func__,
493*1c60b9acSAndroid Build Coastguard Worker 				private_key_filepath);
494*1c60b9acSAndroid Build Coastguard Worker 		if (alloc_file(vh->context, private_key_filepath, &buf, &amount))
495*1c60b9acSAndroid Build Coastguard Worker 			return 1;
496*1c60b9acSAndroid Build Coastguard Worker 
497*1c60b9acSAndroid Build Coastguard Worker 		buf[amount++] = '\0';
498*1c60b9acSAndroid Build Coastguard Worker 
499*1c60b9acSAndroid Build Coastguard Worker 		n = SSL_CTX_use_PrivateKey_ASN1(0, vh->tls.ssl_client_ctx,
500*1c60b9acSAndroid Build Coastguard Worker 				buf, (long)amount);
501*1c60b9acSAndroid Build Coastguard Worker 
502*1c60b9acSAndroid Build Coastguard Worker 		lws_free(buf);
503*1c60b9acSAndroid Build Coastguard Worker 		if (n < 1) {
504*1c60b9acSAndroid Build Coastguard Worker 			lwsl_err("problem %d getting private key '%s'\n", n,
505*1c60b9acSAndroid Build Coastguard Worker 				 private_key_filepath);
506*1c60b9acSAndroid Build Coastguard Worker 			lws_tls_err_describe_clear();
507*1c60b9acSAndroid Build Coastguard Worker 			return 1;
508*1c60b9acSAndroid Build Coastguard Worker 		}
509*1c60b9acSAndroid Build Coastguard Worker 
510*1c60b9acSAndroid Build Coastguard Worker 		lwsl_notice("Loaded private key %s\n", private_key_filepath);
511*1c60b9acSAndroid Build Coastguard Worker #endif
512*1c60b9acSAndroid Build Coastguard Worker 	} else if (key_mem && key_mem_len) {
513*1c60b9acSAndroid Build Coastguard Worker 		/* lwsl_hexdump_notice(cert_mem, cert_mem_len - 1); */
514*1c60b9acSAndroid Build Coastguard Worker 		n = SSL_CTX_use_PrivateKey_ASN1(0, vh->tls.ssl_client_ctx,
515*1c60b9acSAndroid Build Coastguard Worker 				key_mem, (long)key_mem_len - 1);
516*1c60b9acSAndroid Build Coastguard Worker 
517*1c60b9acSAndroid Build Coastguard Worker 		if (n < 1) {
518*1c60b9acSAndroid Build Coastguard Worker 			lwsl_err("%s: (mbedtls) problem interpreting private key\n",
519*1c60b9acSAndroid Build Coastguard Worker 				 __func__);
520*1c60b9acSAndroid Build Coastguard Worker 			lws_tls_err_describe_clear();
521*1c60b9acSAndroid Build Coastguard Worker 			return 1;
522*1c60b9acSAndroid Build Coastguard Worker 		}
523*1c60b9acSAndroid Build Coastguard Worker 		lwsl_info("%s: using mem private key %d\n",
524*1c60b9acSAndroid Build Coastguard Worker 			    __func__, key_mem_len);
525*1c60b9acSAndroid Build Coastguard Worker 
526*1c60b9acSAndroid Build Coastguard Worker 	}
527*1c60b9acSAndroid Build Coastguard Worker 	return 0;
528*1c60b9acSAndroid Build Coastguard Worker }
529*1c60b9acSAndroid Build Coastguard Worker 
530*1c60b9acSAndroid Build Coastguard Worker int
lws_tls_client_vhost_extra_cert_mem(struct lws_vhost * vh,const uint8_t * der,size_t der_len)531*1c60b9acSAndroid Build Coastguard Worker lws_tls_client_vhost_extra_cert_mem(struct lws_vhost *vh,
532*1c60b9acSAndroid Build Coastguard Worker                 const uint8_t *der, size_t der_len)
533*1c60b9acSAndroid Build Coastguard Worker {
534*1c60b9acSAndroid Build Coastguard Worker 	if (SSL_CTX_add_client_CA_ASN1(vh->tls.ssl_client_ctx, (int)der_len, der) != 1) {
535*1c60b9acSAndroid Build Coastguard Worker 		lwsl_err("%s: failed\n", __func__);
536*1c60b9acSAndroid Build Coastguard Worker 			return 1;
537*1c60b9acSAndroid Build Coastguard Worker 	}
538*1c60b9acSAndroid Build Coastguard Worker 
539*1c60b9acSAndroid Build Coastguard Worker 	return 0;
540*1c60b9acSAndroid Build Coastguard Worker }
541*1c60b9acSAndroid Build Coastguard Worker 
542