xref: /aosp_15_r20/external/libwebsockets/lib/tls/openssl/openssl-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 - 2019 Andy Green <[email protected]>
5*1c60b9acSAndroid Build Coastguard Worker  *
6*1c60b9acSAndroid Build Coastguard Worker  * Permission is hereby granted, free of charge, to any person obtaining a copy
7*1c60b9acSAndroid Build Coastguard Worker  * of this software and associated documentation files (the "Software"), to
8*1c60b9acSAndroid Build Coastguard Worker  * deal in the Software without restriction, including without limitation the
9*1c60b9acSAndroid Build Coastguard Worker  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10*1c60b9acSAndroid Build Coastguard Worker  * sell copies of the Software, and to permit persons to whom the Software is
11*1c60b9acSAndroid Build Coastguard Worker  * furnished to do so, subject to the following conditions:
12*1c60b9acSAndroid Build Coastguard Worker  *
13*1c60b9acSAndroid Build Coastguard Worker  * The above copyright notice and this permission notice shall be included in
14*1c60b9acSAndroid Build Coastguard Worker  * all copies or substantial portions of the Software.
15*1c60b9acSAndroid Build Coastguard Worker  *
16*1c60b9acSAndroid Build Coastguard Worker  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17*1c60b9acSAndroid Build Coastguard Worker  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18*1c60b9acSAndroid Build Coastguard Worker  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19*1c60b9acSAndroid Build Coastguard Worker  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20*1c60b9acSAndroid Build Coastguard Worker  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21*1c60b9acSAndroid Build Coastguard Worker  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22*1c60b9acSAndroid Build Coastguard Worker  * IN THE SOFTWARE.
23*1c60b9acSAndroid Build Coastguard Worker  */
24*1c60b9acSAndroid Build Coastguard Worker 
25*1c60b9acSAndroid Build Coastguard Worker #include "lws_config.h"
26*1c60b9acSAndroid Build Coastguard Worker #ifdef LWS_HAVE_X509_VERIFY_PARAM_set1_host
27*1c60b9acSAndroid Build Coastguard Worker /* Before glibc 2.10, strnlen required _GNU_SOURCE */
28*1c60b9acSAndroid Build Coastguard Worker #if !defined(_GNU_SOURCE)
29*1c60b9acSAndroid Build Coastguard Worker #define _GNU_SOURCE
30*1c60b9acSAndroid Build Coastguard Worker #endif
31*1c60b9acSAndroid Build Coastguard Worker #endif
32*1c60b9acSAndroid Build Coastguard Worker #include <string.h>
33*1c60b9acSAndroid Build Coastguard Worker 
34*1c60b9acSAndroid Build Coastguard Worker #include "private-lib-core.h"
35*1c60b9acSAndroid Build Coastguard Worker #include "private-lib-tls-openssl.h"
36*1c60b9acSAndroid Build Coastguard Worker 
37*1c60b9acSAndroid Build Coastguard Worker /*
38*1c60b9acSAndroid Build Coastguard Worker  * Care: many openssl apis return 1 for success.  These are translated to the
39*1c60b9acSAndroid Build Coastguard Worker  * lws convention of 0 for success.
40*1c60b9acSAndroid Build Coastguard Worker  */
41*1c60b9acSAndroid Build Coastguard Worker 
42*1c60b9acSAndroid Build Coastguard Worker int lws_openssl_describe_cipher(struct lws *wsi);
43*1c60b9acSAndroid Build Coastguard Worker 
44*1c60b9acSAndroid Build Coastguard Worker extern int openssl_websocket_private_data_index,
45*1c60b9acSAndroid Build Coastguard Worker     openssl_SSL_CTX_private_data_index;
46*1c60b9acSAndroid Build Coastguard Worker 
47*1c60b9acSAndroid Build Coastguard Worker #if !defined(USE_WOLFSSL)
48*1c60b9acSAndroid Build Coastguard Worker 
49*1c60b9acSAndroid Build Coastguard Worker #if 0
50*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_TLS_JIT_TRUST)
51*1c60b9acSAndroid Build Coastguard Worker 
52*1c60b9acSAndroid Build Coastguard Worker /*
53*1c60b9acSAndroid Build Coastguard Worker  * Completion of sync or async JIT trust lookup
54*1c60b9acSAndroid Build Coastguard Worker  */
55*1c60b9acSAndroid Build Coastguard Worker 
56*1c60b9acSAndroid Build Coastguard Worker int
57*1c60b9acSAndroid Build Coastguard Worker lws_tls_jit_trust_got_cert_cb(void *got_opaque, const uint8_t *der,
58*1c60b9acSAndroid Build Coastguard Worker 			      size_t der_len)
59*1c60b9acSAndroid Build Coastguard Worker {
60*1c60b9acSAndroid Build Coastguard Worker 	X509 *x = d2i_X509(NULL, &der, (long)der_len);
61*1c60b9acSAndroid Build Coastguard Worker 	/** !!! this is not safe for async atm */
62*1c60b9acSAndroid Build Coastguard Worker 	struct lws *wsi = (struct lws *)got_opaque;
63*1c60b9acSAndroid Build Coastguard Worker 	X509_STORE *xs;
64*1c60b9acSAndroid Build Coastguard Worker 	int ret = 0;
65*1c60b9acSAndroid Build Coastguard Worker 
66*1c60b9acSAndroid Build Coastguard Worker 	if (!x) {
67*1c60b9acSAndroid Build Coastguard Worker 		lwsl_err("%s: failed\n", __func__);
68*1c60b9acSAndroid Build Coastguard Worker 		return 1;
69*1c60b9acSAndroid Build Coastguard Worker 	}
70*1c60b9acSAndroid Build Coastguard Worker 
71*1c60b9acSAndroid Build Coastguard Worker 	xs = SSL_CTX_get_cert_store(SSL_get_SSL_CTX(wsi->tls.ssl));
72*1c60b9acSAndroid Build Coastguard Worker 	if (xs) {
73*1c60b9acSAndroid Build Coastguard Worker 		if (X509_STORE_add_cert(xs, x) != 1) {
74*1c60b9acSAndroid Build Coastguard Worker 			lwsl_warn("%s: unable to set trusted CA\n", __func__);
75*1c60b9acSAndroid Build Coastguard Worker 			ret = 1;
76*1c60b9acSAndroid Build Coastguard Worker 		} else
77*1c60b9acSAndroid Build Coastguard Worker 			lwsl_notice("%s: added trusted CA to CTX for next time\n",
78*1c60b9acSAndroid Build Coastguard Worker 					__func__);
79*1c60b9acSAndroid Build Coastguard Worker 	} else
80*1c60b9acSAndroid Build Coastguard Worker 		lwsl_warn("%s: couldn't get cert store\n", __func__);
81*1c60b9acSAndroid Build Coastguard Worker 
82*1c60b9acSAndroid Build Coastguard Worker 	X509_free(x);
83*1c60b9acSAndroid Build Coastguard Worker 
84*1c60b9acSAndroid Build Coastguard Worker 	return ret;
85*1c60b9acSAndroid Build Coastguard Worker }
86*1c60b9acSAndroid Build Coastguard Worker #endif
87*1c60b9acSAndroid Build Coastguard Worker #endif
88*1c60b9acSAndroid Build Coastguard Worker 
89*1c60b9acSAndroid Build Coastguard Worker static int
OpenSSL_client_verify_callback(int preverify_ok,X509_STORE_CTX * x509_ctx)90*1c60b9acSAndroid Build Coastguard Worker OpenSSL_client_verify_callback(int preverify_ok, X509_STORE_CTX *x509_ctx)
91*1c60b9acSAndroid Build Coastguard Worker {
92*1c60b9acSAndroid Build Coastguard Worker 	SSL *ssl;
93*1c60b9acSAndroid Build Coastguard Worker 	int n, err = 0;
94*1c60b9acSAndroid Build Coastguard Worker 	struct lws *wsi;
95*1c60b9acSAndroid Build Coastguard Worker 
96*1c60b9acSAndroid Build Coastguard Worker 	/* keep old behaviour accepting self-signed server certs */
97*1c60b9acSAndroid Build Coastguard Worker 	if (!preverify_ok) {
98*1c60b9acSAndroid Build Coastguard Worker 		err = X509_STORE_CTX_get_error(x509_ctx);
99*1c60b9acSAndroid Build Coastguard Worker 
100*1c60b9acSAndroid Build Coastguard Worker 		if (err != X509_V_OK) {
101*1c60b9acSAndroid Build Coastguard Worker 			ssl = X509_STORE_CTX_get_ex_data(x509_ctx,
102*1c60b9acSAndroid Build Coastguard Worker 					SSL_get_ex_data_X509_STORE_CTX_idx());
103*1c60b9acSAndroid Build Coastguard Worker 			wsi = SSL_get_ex_data(ssl,
104*1c60b9acSAndroid Build Coastguard Worker 					openssl_websocket_private_data_index);
105*1c60b9acSAndroid Build Coastguard Worker 			if (!wsi) {
106*1c60b9acSAndroid Build Coastguard Worker 				lwsl_err("%s: can't get wsi from ssl privdata\n",
107*1c60b9acSAndroid Build Coastguard Worker 					 __func__);
108*1c60b9acSAndroid Build Coastguard Worker 
109*1c60b9acSAndroid Build Coastguard Worker 				return 0;
110*1c60b9acSAndroid Build Coastguard Worker 			}
111*1c60b9acSAndroid Build Coastguard Worker 
112*1c60b9acSAndroid Build Coastguard Worker 			if ((err == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT ||
113*1c60b9acSAndroid Build Coastguard Worker 			     err == X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN) &&
114*1c60b9acSAndroid Build Coastguard Worker 			     wsi->tls.use_ssl & LCCSCF_ALLOW_SELFSIGNED) {
115*1c60b9acSAndroid Build Coastguard Worker 				lwsl_notice("accepting self-signed "
116*1c60b9acSAndroid Build Coastguard Worker 					    "certificate (verify_callback)\n");
117*1c60b9acSAndroid Build Coastguard Worker 				X509_STORE_CTX_set_error(x509_ctx, X509_V_OK);
118*1c60b9acSAndroid Build Coastguard Worker 				return 1;	// ok
119*1c60b9acSAndroid Build Coastguard Worker 		} else if ((err == X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY ||
120*1c60b9acSAndroid Build Coastguard Worker 			    err == X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE) &&
121*1c60b9acSAndroid Build Coastguard Worker 			    wsi->tls.use_ssl & LCCSCF_ALLOW_INSECURE) {
122*1c60b9acSAndroid Build Coastguard Worker 				lwsl_notice("accepting non-trusted certificate\n");
123*1c60b9acSAndroid Build Coastguard Worker 				X509_STORE_CTX_set_error(x509_ctx, X509_V_OK);
124*1c60b9acSAndroid Build Coastguard Worker 				return 1;  /* ok */
125*1c60b9acSAndroid Build Coastguard Worker 			} else if ((err == X509_V_ERR_CERT_NOT_YET_VALID ||
126*1c60b9acSAndroid Build Coastguard Worker 				    err == X509_V_ERR_CERT_HAS_EXPIRED) &&
127*1c60b9acSAndroid Build Coastguard Worker 				    wsi->tls.use_ssl & LCCSCF_ALLOW_EXPIRED) {
128*1c60b9acSAndroid Build Coastguard Worker 				if (err == X509_V_ERR_CERT_NOT_YET_VALID)
129*1c60b9acSAndroid Build Coastguard Worker 					lwsl_notice("accepting not yet valid "
130*1c60b9acSAndroid Build Coastguard Worker 						    "certificate (verify_"
131*1c60b9acSAndroid Build Coastguard Worker 						    "callback)\n");
132*1c60b9acSAndroid Build Coastguard Worker 				else if (err == X509_V_ERR_CERT_HAS_EXPIRED)
133*1c60b9acSAndroid Build Coastguard Worker 					lwsl_notice("accepting expired "
134*1c60b9acSAndroid Build Coastguard Worker 						    "certificate (verify_"
135*1c60b9acSAndroid Build Coastguard Worker 						    "callback)\n");
136*1c60b9acSAndroid Build Coastguard Worker 				X509_STORE_CTX_set_error(x509_ctx, X509_V_OK);
137*1c60b9acSAndroid Build Coastguard Worker 				return 1;	// ok
138*1c60b9acSAndroid Build Coastguard Worker 			}
139*1c60b9acSAndroid Build Coastguard Worker 		}
140*1c60b9acSAndroid Build Coastguard Worker 	}
141*1c60b9acSAndroid Build Coastguard Worker 
142*1c60b9acSAndroid Build Coastguard Worker 	ssl = X509_STORE_CTX_get_ex_data(x509_ctx,
143*1c60b9acSAndroid Build Coastguard Worker 					 SSL_get_ex_data_X509_STORE_CTX_idx());
144*1c60b9acSAndroid Build Coastguard Worker 	wsi = SSL_get_ex_data(ssl, openssl_websocket_private_data_index);
145*1c60b9acSAndroid Build Coastguard Worker 	if (!wsi) {
146*1c60b9acSAndroid Build Coastguard Worker 		lwsl_err("%s: can't get wsi from ssl privdata\n",  __func__);
147*1c60b9acSAndroid Build Coastguard Worker 
148*1c60b9acSAndroid Build Coastguard Worker 		return 0;
149*1c60b9acSAndroid Build Coastguard Worker 	}
150*1c60b9acSAndroid Build Coastguard Worker 
151*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_TLS_JIT_TRUST)
152*1c60b9acSAndroid Build Coastguard Worker 	if (err == X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY) {
153*1c60b9acSAndroid Build Coastguard Worker 		union lws_tls_cert_info_results ci;
154*1c60b9acSAndroid Build Coastguard Worker 		STACK_OF(X509) *x509_stack;
155*1c60b9acSAndroid Build Coastguard Worker 
156*1c60b9acSAndroid Build Coastguard Worker 		x509_stack = X509_STORE_CTX_get1_chain(x509_ctx);
157*1c60b9acSAndroid Build Coastguard Worker 		if (x509_stack) {
158*1c60b9acSAndroid Build Coastguard Worker 
159*1c60b9acSAndroid Build Coastguard Worker 			for (n = 0; n < OPENSSL_sk_num((const OPENSSL_STACK *)x509_stack) &&
160*1c60b9acSAndroid Build Coastguard Worker 				    wsi->tls.kid_chain.count !=
161*1c60b9acSAndroid Build Coastguard Worker 				     LWS_ARRAY_SIZE(wsi->tls.kid_chain.akid); n++) {
162*1c60b9acSAndroid Build Coastguard Worker 				X509 *x509 = OPENSSL_sk_value((const OPENSSL_STACK *)x509_stack, n);
163*1c60b9acSAndroid Build Coastguard Worker 
164*1c60b9acSAndroid Build Coastguard Worker 				if (!lws_tls_openssl_cert_info(x509,
165*1c60b9acSAndroid Build Coastguard Worker 					    LWS_TLS_CERT_INFO_SUBJECT_KEY_ID,
166*1c60b9acSAndroid Build Coastguard Worker 					    &ci, 0))
167*1c60b9acSAndroid Build Coastguard Worker 					lws_tls_kid_copy(&ci,
168*1c60b9acSAndroid Build Coastguard Worker 						&wsi->tls.kid_chain.skid[
169*1c60b9acSAndroid Build Coastguard Worker 						     wsi->tls.kid_chain.count]);
170*1c60b9acSAndroid Build Coastguard Worker 
171*1c60b9acSAndroid Build Coastguard Worker 				if (!lws_tls_openssl_cert_info(x509,
172*1c60b9acSAndroid Build Coastguard Worker 					     LWS_TLS_CERT_INFO_AUTHORITY_KEY_ID,
173*1c60b9acSAndroid Build Coastguard Worker 					     &ci, 0))
174*1c60b9acSAndroid Build Coastguard Worker 					lws_tls_kid_copy(&ci,
175*1c60b9acSAndroid Build Coastguard Worker 						 &wsi->tls.kid_chain.akid[
176*1c60b9acSAndroid Build Coastguard Worker 						     wsi->tls.kid_chain.count]);
177*1c60b9acSAndroid Build Coastguard Worker 
178*1c60b9acSAndroid Build Coastguard Worker 				wsi->tls.kid_chain.count++;
179*1c60b9acSAndroid Build Coastguard Worker 			}
180*1c60b9acSAndroid Build Coastguard Worker 
181*1c60b9acSAndroid Build Coastguard Worker 			sk_X509_pop_free(x509_stack, X509_free);
182*1c60b9acSAndroid Build Coastguard Worker 		}
183*1c60b9acSAndroid Build Coastguard Worker 
184*1c60b9acSAndroid Build Coastguard Worker 		lws_tls_jit_trust_sort_kids(wsi, &wsi->tls.kid_chain);
185*1c60b9acSAndroid Build Coastguard Worker 	}
186*1c60b9acSAndroid Build Coastguard Worker #endif
187*1c60b9acSAndroid Build Coastguard Worker 
188*1c60b9acSAndroid Build Coastguard Worker 	n = lws_get_context_protocol(wsi->a.context, 0).callback(wsi,
189*1c60b9acSAndroid Build Coastguard Worker 			LWS_CALLBACK_OPENSSL_PERFORM_SERVER_CERT_VERIFICATION,
190*1c60b9acSAndroid Build Coastguard Worker 			x509_ctx, ssl, (unsigned int)preverify_ok);
191*1c60b9acSAndroid Build Coastguard Worker 
192*1c60b9acSAndroid Build Coastguard Worker 	/* keep old behaviour if something wrong with server certs */
193*1c60b9acSAndroid Build Coastguard Worker 	/* if ssl error is overruled in callback and cert is ok,
194*1c60b9acSAndroid Build Coastguard Worker 	 * X509_STORE_CTX_set_error(x509_ctx, X509_V_OK); must be set and
195*1c60b9acSAndroid Build Coastguard Worker 	 * return value is 0 from callback */
196*1c60b9acSAndroid Build Coastguard Worker 	if (!preverify_ok) {
197*1c60b9acSAndroid Build Coastguard Worker 		int err = X509_STORE_CTX_get_error(x509_ctx);
198*1c60b9acSAndroid Build Coastguard Worker 
199*1c60b9acSAndroid Build Coastguard Worker 		if (err != X509_V_OK) {
200*1c60b9acSAndroid Build Coastguard Worker 			/* cert validation error was not handled in callback */
201*1c60b9acSAndroid Build Coastguard Worker 			int depth = X509_STORE_CTX_get_error_depth(x509_ctx);
202*1c60b9acSAndroid Build Coastguard Worker 			const char *msg = X509_verify_cert_error_string(err);
203*1c60b9acSAndroid Build Coastguard Worker 
204*1c60b9acSAndroid Build Coastguard Worker 			lws_strncpy(wsi->tls.err_helper, msg,
205*1c60b9acSAndroid Build Coastguard Worker 				    sizeof(wsi->tls.err_helper));
206*1c60b9acSAndroid Build Coastguard Worker 
207*1c60b9acSAndroid Build Coastguard Worker 			lwsl_err("SSL error: %s (preverify_ok=%d;err=%d;"
208*1c60b9acSAndroid Build Coastguard Worker 				 "depth=%d)\n", msg, preverify_ok, err, depth);
209*1c60b9acSAndroid Build Coastguard Worker 
210*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_SYS_METRICS)
211*1c60b9acSAndroid Build Coastguard Worker 			{
212*1c60b9acSAndroid Build Coastguard Worker 				char buckname[64];
213*1c60b9acSAndroid Build Coastguard Worker 
214*1c60b9acSAndroid Build Coastguard Worker 				lws_snprintf(buckname, sizeof(buckname),
215*1c60b9acSAndroid Build Coastguard Worker 					     "tls=\"%s\"", msg);
216*1c60b9acSAndroid Build Coastguard Worker 				lws_metrics_hist_bump_describe_wsi(wsi,
217*1c60b9acSAndroid Build Coastguard Worker 					lws_metrics_priv_to_pub(wsi->a.context->mth_conn_failures),
218*1c60b9acSAndroid Build Coastguard Worker 					buckname);
219*1c60b9acSAndroid Build Coastguard Worker 			}
220*1c60b9acSAndroid Build Coastguard Worker #endif
221*1c60b9acSAndroid Build Coastguard Worker 
222*1c60b9acSAndroid Build Coastguard Worker 			return preverify_ok;	// not ok
223*1c60b9acSAndroid Build Coastguard Worker 		}
224*1c60b9acSAndroid Build Coastguard Worker 	}
225*1c60b9acSAndroid Build Coastguard Worker 	/*
226*1c60b9acSAndroid Build Coastguard Worker 	 * convert callback return code from 0 = OK to verify callback
227*1c60b9acSAndroid Build Coastguard Worker 	 * return value 1 = OK
228*1c60b9acSAndroid Build Coastguard Worker 	 */
229*1c60b9acSAndroid Build Coastguard Worker 	return !n;
230*1c60b9acSAndroid Build Coastguard Worker }
231*1c60b9acSAndroid Build Coastguard Worker #endif
232*1c60b9acSAndroid Build Coastguard Worker 
233*1c60b9acSAndroid Build Coastguard Worker int
lws_ssl_client_bio_create(struct lws * wsi)234*1c60b9acSAndroid Build Coastguard Worker lws_ssl_client_bio_create(struct lws *wsi)
235*1c60b9acSAndroid Build Coastguard Worker {
236*1c60b9acSAndroid Build Coastguard Worker 	char hostname[128], *p;
237*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_HAVE_SSL_set_alpn_protos) && \
238*1c60b9acSAndroid Build Coastguard Worker     defined(LWS_HAVE_SSL_get0_alpn_selected)
239*1c60b9acSAndroid Build Coastguard Worker 	uint8_t openssl_alpn[40];
240*1c60b9acSAndroid Build Coastguard Worker 	const char *alpn_comma = wsi->a.context->tls.alpn_default;
241*1c60b9acSAndroid Build Coastguard Worker 	int n;
242*1c60b9acSAndroid Build Coastguard Worker #endif
243*1c60b9acSAndroid Build Coastguard Worker 
244*1c60b9acSAndroid Build Coastguard Worker 	if (wsi->stash) {
245*1c60b9acSAndroid Build Coastguard Worker 		lws_strncpy(hostname, wsi->stash->cis[CIS_HOST], sizeof(hostname));
246*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_HAVE_SSL_set_alpn_protos) && \
247*1c60b9acSAndroid Build Coastguard Worker     defined(LWS_HAVE_SSL_get0_alpn_selected)
248*1c60b9acSAndroid Build Coastguard Worker 		alpn_comma = wsi->stash->cis[CIS_ALPN];
249*1c60b9acSAndroid Build Coastguard Worker #endif
250*1c60b9acSAndroid Build Coastguard Worker 	} else {
251*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
252*1c60b9acSAndroid Build Coastguard Worker 		if (lws_hdr_copy(wsi, hostname, sizeof(hostname),
253*1c60b9acSAndroid Build Coastguard Worker 				 _WSI_TOKEN_CLIENT_HOST) <= 0)
254*1c60b9acSAndroid Build Coastguard Worker #endif
255*1c60b9acSAndroid Build Coastguard Worker 		{
256*1c60b9acSAndroid Build Coastguard Worker 			lwsl_err("%s: Unable to get hostname\n", __func__);
257*1c60b9acSAndroid Build Coastguard Worker 
258*1c60b9acSAndroid Build Coastguard Worker 			return -1;
259*1c60b9acSAndroid Build Coastguard Worker 		}
260*1c60b9acSAndroid Build Coastguard Worker 	}
261*1c60b9acSAndroid Build Coastguard Worker 
262*1c60b9acSAndroid Build Coastguard Worker 	/*
263*1c60b9acSAndroid Build Coastguard Worker 	 * remove any :port part on the hostname... necessary for network
264*1c60b9acSAndroid Build Coastguard Worker 	 * connection but typical certificates do not contain it
265*1c60b9acSAndroid Build Coastguard Worker 	 */
266*1c60b9acSAndroid Build Coastguard Worker 	p = hostname;
267*1c60b9acSAndroid Build Coastguard Worker 	while (*p) {
268*1c60b9acSAndroid Build Coastguard Worker 		if (*p == ':') {
269*1c60b9acSAndroid Build Coastguard Worker 			*p = '\0';
270*1c60b9acSAndroid Build Coastguard Worker 			break;
271*1c60b9acSAndroid Build Coastguard Worker 		}
272*1c60b9acSAndroid Build Coastguard Worker 		p++;
273*1c60b9acSAndroid Build Coastguard Worker 	}
274*1c60b9acSAndroid Build Coastguard Worker 
275*1c60b9acSAndroid Build Coastguard Worker 	wsi->tls.ssl = SSL_new(wsi->a.vhost->tls.ssl_client_ctx);
276*1c60b9acSAndroid Build Coastguard Worker 	if (!wsi->tls.ssl) {
277*1c60b9acSAndroid Build Coastguard Worker 		const char *es = ERR_error_string(
278*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_BORINGSSL)
279*1c60b9acSAndroid Build Coastguard Worker 	(uint32_t)
280*1c60b9acSAndroid Build Coastguard Worker #else
281*1c60b9acSAndroid Build Coastguard Worker 	(unsigned long)
282*1c60b9acSAndroid Build Coastguard Worker #endif
283*1c60b9acSAndroid Build Coastguard Worker 	lws_ssl_get_error(wsi, 0), NULL);
284*1c60b9acSAndroid Build Coastguard Worker 		lwsl_err("SSL_new failed: %s\n", es);
285*1c60b9acSAndroid Build Coastguard Worker 		lws_tls_err_describe_clear();
286*1c60b9acSAndroid Build Coastguard Worker 		return -1;
287*1c60b9acSAndroid Build Coastguard Worker 	}
288*1c60b9acSAndroid Build Coastguard Worker 
289*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_TLS_SESSIONS)
290*1c60b9acSAndroid Build Coastguard Worker 	if (!(wsi->a.vhost->options & LWS_SERVER_OPTION_DISABLE_TLS_SESSION_CACHE))
291*1c60b9acSAndroid Build Coastguard Worker 		lws_tls_reuse_session(wsi);
292*1c60b9acSAndroid Build Coastguard Worker #endif
293*1c60b9acSAndroid Build Coastguard Worker 
294*1c60b9acSAndroid Build Coastguard Worker #if defined (LWS_HAVE_SSL_SET_INFO_CALLBACK)
295*1c60b9acSAndroid Build Coastguard Worker 	if (wsi->a.vhost->tls.ssl_info_event_mask)
296*1c60b9acSAndroid Build Coastguard Worker 		SSL_set_info_callback(wsi->tls.ssl, lws_ssl_info_callback);
297*1c60b9acSAndroid Build Coastguard Worker #endif
298*1c60b9acSAndroid Build Coastguard Worker 
299*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_HAVE_X509_VERIFY_PARAM_set1_host)
300*1c60b9acSAndroid Build Coastguard Worker 	if (!(wsi->tls.use_ssl & LCCSCF_SKIP_SERVER_CERT_HOSTNAME_CHECK)) {
301*1c60b9acSAndroid Build Coastguard Worker #if !defined(USE_WOLFSSL)
302*1c60b9acSAndroid Build Coastguard Worker 
303*1c60b9acSAndroid Build Coastguard Worker 		X509_VERIFY_PARAM *param = SSL_get0_param(wsi->tls.ssl);
304*1c60b9acSAndroid Build Coastguard Worker 
305*1c60b9acSAndroid Build Coastguard Worker 		/* Enable automatic hostname checks */
306*1c60b9acSAndroid Build Coastguard Worker 		X509_VERIFY_PARAM_set_hostflags(param,
307*1c60b9acSAndroid Build Coastguard Worker 					X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS);
308*1c60b9acSAndroid Build Coastguard Worker 		/* Handle the case where the hostname is an IP address */
309*1c60b9acSAndroid Build Coastguard Worker 		if (!X509_VERIFY_PARAM_set1_ip_asc(param, hostname))
310*1c60b9acSAndroid Build Coastguard Worker 			X509_VERIFY_PARAM_set1_host(param, hostname,
311*1c60b9acSAndroid Build Coastguard Worker 					strnlen(hostname, sizeof(hostname)));
312*1c60b9acSAndroid Build Coastguard Worker #endif
313*1c60b9acSAndroid Build Coastguard Worker 
314*1c60b9acSAndroid Build Coastguard Worker 	}
315*1c60b9acSAndroid Build Coastguard Worker #else
316*1c60b9acSAndroid Build Coastguard Worker 	if (!(wsi->tls.use_ssl & LCCSCF_SKIP_SERVER_CERT_HOSTNAME_CHECK)) {
317*1c60b9acSAndroid Build Coastguard Worker 		lwsl_err("%s: your tls lib is too old to have "
318*1c60b9acSAndroid Build Coastguard Worker 			 "X509_VERIFY_PARAM_set1_host, failing all client tls\n",
319*1c60b9acSAndroid Build Coastguard Worker 			 __func__);
320*1c60b9acSAndroid Build Coastguard Worker 		return -1;
321*1c60b9acSAndroid Build Coastguard Worker 	}
322*1c60b9acSAndroid Build Coastguard Worker #endif
323*1c60b9acSAndroid Build Coastguard Worker 
324*1c60b9acSAndroid Build Coastguard Worker #if !defined(USE_WOLFSSL)
325*1c60b9acSAndroid Build Coastguard Worker #ifndef USE_OLD_CYASSL
326*1c60b9acSAndroid Build Coastguard Worker 	/* OpenSSL_client_verify_callback will be called @ SSL_connect() */
327*1c60b9acSAndroid Build Coastguard Worker 	SSL_set_verify(wsi->tls.ssl, SSL_VERIFY_PEER,
328*1c60b9acSAndroid Build Coastguard Worker 		       OpenSSL_client_verify_callback);
329*1c60b9acSAndroid Build Coastguard Worker #endif
330*1c60b9acSAndroid Build Coastguard Worker #endif
331*1c60b9acSAndroid Build Coastguard Worker 
332*1c60b9acSAndroid Build Coastguard Worker #if !defined(USE_WOLFSSL)
333*1c60b9acSAndroid Build Coastguard Worker 	SSL_set_mode(wsi->tls.ssl,  SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
334*1c60b9acSAndroid Build Coastguard Worker #endif
335*1c60b9acSAndroid Build Coastguard Worker 	/*
336*1c60b9acSAndroid Build Coastguard Worker 	 * use server name indication (SNI), if supported,
337*1c60b9acSAndroid Build Coastguard Worker 	 * when establishing connection
338*1c60b9acSAndroid Build Coastguard Worker 	 */
339*1c60b9acSAndroid Build Coastguard Worker #ifdef USE_WOLFSSL
340*1c60b9acSAndroid Build Coastguard Worker #ifdef USE_OLD_CYASSL
341*1c60b9acSAndroid Build Coastguard Worker #ifdef CYASSL_SNI_HOST_NAME
342*1c60b9acSAndroid Build Coastguard Worker 	CyaSSL_UseSNI(wsi->tls.ssl, CYASSL_SNI_HOST_NAME, hostname,
343*1c60b9acSAndroid Build Coastguard Worker 		      strlen(hostname));
344*1c60b9acSAndroid Build Coastguard Worker #endif
345*1c60b9acSAndroid Build Coastguard Worker #else
346*1c60b9acSAndroid Build Coastguard Worker #if defined(WOLFSSL_SNI_HOST_NAME) || defined(HAVE_SNI)
347*1c60b9acSAndroid Build Coastguard Worker 	wolfSSL_UseSNI(wsi->tls.ssl, WOLFSSL_SNI_HOST_NAME, hostname,
348*1c60b9acSAndroid Build Coastguard Worker 		       (unsigned short)strlen(hostname));
349*1c60b9acSAndroid Build Coastguard Worker #endif
350*1c60b9acSAndroid Build Coastguard Worker #endif
351*1c60b9acSAndroid Build Coastguard Worker #else
352*1c60b9acSAndroid Build Coastguard Worker #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
353*1c60b9acSAndroid Build Coastguard Worker 	SSL_set_tlsext_host_name(wsi->tls.ssl, hostname);
354*1c60b9acSAndroid Build Coastguard Worker #endif
355*1c60b9acSAndroid Build Coastguard Worker #endif
356*1c60b9acSAndroid Build Coastguard Worker 
357*1c60b9acSAndroid Build Coastguard Worker #ifdef USE_WOLFSSL
358*1c60b9acSAndroid Build Coastguard Worker 	/*
359*1c60b9acSAndroid Build Coastguard Worker 	 * wolfSSL/CyaSSL does certificate verification differently
360*1c60b9acSAndroid Build Coastguard Worker 	 * from OpenSSL.
361*1c60b9acSAndroid Build Coastguard Worker 	 * If we should ignore the certificate, we need to set
362*1c60b9acSAndroid Build Coastguard Worker 	 * this before SSL_new and SSL_connect is called.
363*1c60b9acSAndroid Build Coastguard Worker 	 * Otherwise the connect will simply fail with error code -155
364*1c60b9acSAndroid Build Coastguard Worker 	 */
365*1c60b9acSAndroid Build Coastguard Worker #ifdef USE_OLD_CYASSL
366*1c60b9acSAndroid Build Coastguard Worker 	if (wsi->tls.use_ssl & LCCSCF_ALLOW_SELFSIGNED)
367*1c60b9acSAndroid Build Coastguard Worker 		CyaSSL_set_verify(wsi->tls.ssl, SSL_VERIFY_NONE, NULL);
368*1c60b9acSAndroid Build Coastguard Worker #else
369*1c60b9acSAndroid Build Coastguard Worker 	if (wsi->tls.use_ssl & LCCSCF_ALLOW_SELFSIGNED)
370*1c60b9acSAndroid Build Coastguard Worker 		wolfSSL_set_verify(wsi->tls.ssl, SSL_VERIFY_NONE, NULL);
371*1c60b9acSAndroid Build Coastguard Worker #endif
372*1c60b9acSAndroid Build Coastguard Worker #endif /* USE_WOLFSSL */
373*1c60b9acSAndroid Build Coastguard Worker 
374*1c60b9acSAndroid Build Coastguard Worker 	wsi->tls.client_bio = BIO_new_socket((int)(lws_intptr_t)wsi->desc.sockfd,
375*1c60b9acSAndroid Build Coastguard Worker 					     BIO_NOCLOSE);
376*1c60b9acSAndroid Build Coastguard Worker 	SSL_set_bio(wsi->tls.ssl, wsi->tls.client_bio, wsi->tls.client_bio);
377*1c60b9acSAndroid Build Coastguard Worker 
378*1c60b9acSAndroid Build Coastguard Worker #ifdef USE_WOLFSSL
379*1c60b9acSAndroid Build Coastguard Worker #ifdef USE_OLD_CYASSL
380*1c60b9acSAndroid Build Coastguard Worker 	CyaSSL_set_using_nonblock(wsi->tls.ssl, 1);
381*1c60b9acSAndroid Build Coastguard Worker #else
382*1c60b9acSAndroid Build Coastguard Worker 	wolfSSL_set_using_nonblock(wsi->tls.ssl, 1);
383*1c60b9acSAndroid Build Coastguard Worker #endif
384*1c60b9acSAndroid Build Coastguard Worker #else
385*1c60b9acSAndroid Build Coastguard Worker 	BIO_set_nbio(wsi->tls.client_bio, 1); /* nonblocking */
386*1c60b9acSAndroid Build Coastguard Worker #endif
387*1c60b9acSAndroid Build Coastguard Worker 
388*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_HAVE_SSL_set_alpn_protos) && \
389*1c60b9acSAndroid Build Coastguard Worker     defined(LWS_HAVE_SSL_get0_alpn_selected)
390*1c60b9acSAndroid Build Coastguard Worker 	if (wsi->a.vhost->tls.alpn)
391*1c60b9acSAndroid Build Coastguard Worker 		alpn_comma = wsi->a.vhost->tls.alpn;
392*1c60b9acSAndroid Build Coastguard Worker 	if (wsi->stash)
393*1c60b9acSAndroid Build Coastguard Worker 		alpn_comma = wsi->stash->cis[CIS_ALPN];
394*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
395*1c60b9acSAndroid Build Coastguard Worker 	if (lws_hdr_copy(wsi, hostname, sizeof(hostname),
396*1c60b9acSAndroid Build Coastguard Worker 			 _WSI_TOKEN_CLIENT_ALPN) > 0)
397*1c60b9acSAndroid Build Coastguard Worker 		alpn_comma = hostname;
398*1c60b9acSAndroid Build Coastguard Worker #endif
399*1c60b9acSAndroid Build Coastguard Worker 
400*1c60b9acSAndroid Build Coastguard Worker 	lwsl_info("%s client conn using alpn list '%s'\n", wsi->role_ops->name, alpn_comma);
401*1c60b9acSAndroid Build Coastguard Worker 
402*1c60b9acSAndroid Build Coastguard Worker 	n = lws_alpn_comma_to_openssl(alpn_comma, openssl_alpn,
403*1c60b9acSAndroid Build Coastguard Worker 				      sizeof(openssl_alpn) - 1);
404*1c60b9acSAndroid Build Coastguard Worker 
405*1c60b9acSAndroid Build Coastguard Worker 	SSL_set_alpn_protos(wsi->tls.ssl, openssl_alpn, (unsigned int)n);
406*1c60b9acSAndroid Build Coastguard Worker #endif
407*1c60b9acSAndroid Build Coastguard Worker 
408*1c60b9acSAndroid Build Coastguard Worker 	SSL_set_ex_data(wsi->tls.ssl, openssl_websocket_private_data_index,
409*1c60b9acSAndroid Build Coastguard Worker 			wsi);
410*1c60b9acSAndroid Build Coastguard Worker 
411*1c60b9acSAndroid Build Coastguard Worker 	if (wsi->sys_tls_client_cert) {
412*1c60b9acSAndroid Build Coastguard Worker 		lws_system_blob_t *b = lws_system_get_blob(wsi->a.context,
413*1c60b9acSAndroid Build Coastguard Worker 					LWS_SYSBLOB_TYPE_CLIENT_CERT_DER,
414*1c60b9acSAndroid Build Coastguard Worker 					wsi->sys_tls_client_cert - 1);
415*1c60b9acSAndroid Build Coastguard Worker 		const uint8_t *data;
416*1c60b9acSAndroid Build Coastguard Worker 		size_t size;
417*1c60b9acSAndroid Build Coastguard Worker 
418*1c60b9acSAndroid Build Coastguard Worker 		if (!b)
419*1c60b9acSAndroid Build Coastguard Worker 			goto no_client_cert;
420*1c60b9acSAndroid Build Coastguard Worker 
421*1c60b9acSAndroid Build Coastguard Worker 		/*
422*1c60b9acSAndroid Build Coastguard Worker 		 * Set up the per-connection client cert
423*1c60b9acSAndroid Build Coastguard Worker 		 */
424*1c60b9acSAndroid Build Coastguard Worker 
425*1c60b9acSAndroid Build Coastguard Worker 		size = lws_system_blob_get_size(b);
426*1c60b9acSAndroid Build Coastguard Worker 		if (!size)
427*1c60b9acSAndroid Build Coastguard Worker 			goto no_client_cert;
428*1c60b9acSAndroid Build Coastguard Worker 
429*1c60b9acSAndroid Build Coastguard Worker 		if (lws_system_blob_get_single_ptr(b, &data))
430*1c60b9acSAndroid Build Coastguard Worker 			goto no_client_cert;
431*1c60b9acSAndroid Build Coastguard Worker 
432*1c60b9acSAndroid Build Coastguard Worker 		if (SSL_use_certificate_ASN1(wsi->tls.ssl,
433*1c60b9acSAndroid Build Coastguard Worker #if defined(USE_WOLFSSL)
434*1c60b9acSAndroid Build Coastguard Worker 			(unsigned char *)
435*1c60b9acSAndroid Build Coastguard Worker #endif
436*1c60b9acSAndroid Build Coastguard Worker 					data,
437*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_BORINGSSL)
438*1c60b9acSAndroid Build Coastguard Worker 					(size_t)
439*1c60b9acSAndroid Build Coastguard Worker #else
440*1c60b9acSAndroid Build Coastguard Worker 					(int)
441*1c60b9acSAndroid Build Coastguard Worker #endif
442*1c60b9acSAndroid Build Coastguard Worker 					size) != 1) {
443*1c60b9acSAndroid Build Coastguard Worker 			lwsl_err("%s: use_certificate failed\n", __func__);
444*1c60b9acSAndroid Build Coastguard Worker 			lws_tls_err_describe_clear();
445*1c60b9acSAndroid Build Coastguard Worker 			goto no_client_cert;
446*1c60b9acSAndroid Build Coastguard Worker 		}
447*1c60b9acSAndroid Build Coastguard Worker 
448*1c60b9acSAndroid Build Coastguard Worker 		b = lws_system_get_blob(wsi->a.context,
449*1c60b9acSAndroid Build Coastguard Worker 					LWS_SYSBLOB_TYPE_CLIENT_KEY_DER,
450*1c60b9acSAndroid Build Coastguard Worker 					wsi->sys_tls_client_cert - 1);
451*1c60b9acSAndroid Build Coastguard Worker 		if (!b)
452*1c60b9acSAndroid Build Coastguard Worker 			goto no_client_cert;
453*1c60b9acSAndroid Build Coastguard Worker 
454*1c60b9acSAndroid Build Coastguard Worker 		size = lws_system_blob_get_size(b);
455*1c60b9acSAndroid Build Coastguard Worker 		if (!size)
456*1c60b9acSAndroid Build Coastguard Worker 			goto no_client_cert;
457*1c60b9acSAndroid Build Coastguard Worker 
458*1c60b9acSAndroid Build Coastguard Worker 		if (lws_system_blob_get_single_ptr(b, &data))
459*1c60b9acSAndroid Build Coastguard Worker 			goto no_client_cert;
460*1c60b9acSAndroid Build Coastguard Worker 
461*1c60b9acSAndroid Build Coastguard Worker 		if (SSL_use_PrivateKey_ASN1(EVP_PKEY_RSA, wsi->tls.ssl,
462*1c60b9acSAndroid Build Coastguard Worker #if defined(USE_WOLFSSL)
463*1c60b9acSAndroid Build Coastguard Worker 			(unsigned char *)
464*1c60b9acSAndroid Build Coastguard Worker #endif
465*1c60b9acSAndroid Build Coastguard Worker 
466*1c60b9acSAndroid Build Coastguard Worker 					    data,
467*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_BORINGSSL)
468*1c60b9acSAndroid Build Coastguard Worker 					(size_t)
469*1c60b9acSAndroid Build Coastguard Worker #else
470*1c60b9acSAndroid Build Coastguard Worker 					(int)
471*1c60b9acSAndroid Build Coastguard Worker #endif
472*1c60b9acSAndroid Build Coastguard Worker 					    size) != 1 &&
473*1c60b9acSAndroid Build Coastguard Worker 		    SSL_use_PrivateKey_ASN1(EVP_PKEY_EC, wsi->tls.ssl,
474*1c60b9acSAndroid Build Coastguard Worker #if defined(USE_WOLFSSL)
475*1c60b9acSAndroid Build Coastguard Worker 			(unsigned char *)
476*1c60b9acSAndroid Build Coastguard Worker #endif
477*1c60b9acSAndroid Build Coastguard Worker 					    data,
478*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_BORINGSSL)
479*1c60b9acSAndroid Build Coastguard Worker 					(size_t)
480*1c60b9acSAndroid Build Coastguard Worker #else
481*1c60b9acSAndroid Build Coastguard Worker 					(int)
482*1c60b9acSAndroid Build Coastguard Worker #endif
483*1c60b9acSAndroid Build Coastguard Worker 					    size) != 1) {
484*1c60b9acSAndroid Build Coastguard Worker 			lwsl_err("%s: use_privkey failed\n", __func__);
485*1c60b9acSAndroid Build Coastguard Worker 			lws_tls_err_describe_clear();
486*1c60b9acSAndroid Build Coastguard Worker 			goto no_client_cert;
487*1c60b9acSAndroid Build Coastguard Worker 		}
488*1c60b9acSAndroid Build Coastguard Worker 
489*1c60b9acSAndroid Build Coastguard Worker 		if (SSL_check_private_key(wsi->tls.ssl) != 1) {
490*1c60b9acSAndroid Build Coastguard Worker 			lwsl_err("Private SSL key doesn't match cert\n");
491*1c60b9acSAndroid Build Coastguard Worker 			lws_tls_err_describe_clear();
492*1c60b9acSAndroid Build Coastguard Worker 			return 1;
493*1c60b9acSAndroid Build Coastguard Worker 		}
494*1c60b9acSAndroid Build Coastguard Worker 
495*1c60b9acSAndroid Build Coastguard Worker 		lwsl_notice("%s: set system client cert %u\n", __func__,
496*1c60b9acSAndroid Build Coastguard Worker 				wsi->sys_tls_client_cert - 1);
497*1c60b9acSAndroid Build Coastguard Worker 	}
498*1c60b9acSAndroid Build Coastguard Worker 
499*1c60b9acSAndroid Build Coastguard Worker 	return 0;
500*1c60b9acSAndroid Build Coastguard Worker 
501*1c60b9acSAndroid Build Coastguard Worker no_client_cert:
502*1c60b9acSAndroid Build Coastguard Worker 	lwsl_err("%s: unable to set up system client cert %d\n", __func__,
503*1c60b9acSAndroid Build Coastguard Worker 			wsi->sys_tls_client_cert - 1);
504*1c60b9acSAndroid Build Coastguard Worker 
505*1c60b9acSAndroid Build Coastguard Worker 	return 1;
506*1c60b9acSAndroid Build Coastguard Worker }
507*1c60b9acSAndroid Build Coastguard Worker 
508*1c60b9acSAndroid Build Coastguard Worker enum lws_ssl_capable_status
lws_tls_client_connect(struct lws * wsi,char * errbuf,size_t elen)509*1c60b9acSAndroid Build Coastguard Worker lws_tls_client_connect(struct lws *wsi, char *errbuf, size_t elen)
510*1c60b9acSAndroid Build Coastguard Worker {
511*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_HAVE_SSL_set_alpn_protos) && \
512*1c60b9acSAndroid Build Coastguard Worker     defined(LWS_HAVE_SSL_get0_alpn_selected)
513*1c60b9acSAndroid Build Coastguard Worker 	const unsigned char *prot;
514*1c60b9acSAndroid Build Coastguard Worker 	char a[32];
515*1c60b9acSAndroid Build Coastguard Worker 	unsigned int len;
516*1c60b9acSAndroid Build Coastguard Worker #endif
517*1c60b9acSAndroid Build Coastguard Worker 	int m, n, en;
518*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_TLS_SESSIONS) && defined(LWS_HAVE_SSL_SESSION_set_time)
519*1c60b9acSAndroid Build Coastguard Worker 	SSL_SESSION *sess;
520*1c60b9acSAndroid Build Coastguard Worker #endif
521*1c60b9acSAndroid Build Coastguard Worker 	errno = 0;
522*1c60b9acSAndroid Build Coastguard Worker 	ERR_clear_error();
523*1c60b9acSAndroid Build Coastguard Worker 	wsi->tls.err_helper[0] = '\0';
524*1c60b9acSAndroid Build Coastguard Worker 	n = SSL_connect(wsi->tls.ssl);
525*1c60b9acSAndroid Build Coastguard Worker 	en = errno;
526*1c60b9acSAndroid Build Coastguard Worker 
527*1c60b9acSAndroid Build Coastguard Worker 	m = lws_ssl_get_error(wsi, n);
528*1c60b9acSAndroid Build Coastguard Worker 
529*1c60b9acSAndroid Build Coastguard Worker 	if (m == SSL_ERROR_SYSCALL
530*1c60b9acSAndroid Build Coastguard Worker #if defined(WIN32)
531*1c60b9acSAndroid Build Coastguard Worker 			&& en
532*1c60b9acSAndroid Build Coastguard Worker #endif
533*1c60b9acSAndroid Build Coastguard Worker 	) {
534*1c60b9acSAndroid Build Coastguard Worker #if defined(WIN32) || (_LWS_ENABLED_LOGS & LLL_INFO)
535*1c60b9acSAndroid Build Coastguard Worker 		lwsl_info("%s: n %d, m %d, errno %d\n", __func__, n, m, en);
536*1c60b9acSAndroid Build Coastguard Worker #endif
537*1c60b9acSAndroid Build Coastguard Worker 		lws_snprintf(errbuf, elen, "connect SYSCALL %d", en);
538*1c60b9acSAndroid Build Coastguard Worker 		return LWS_SSL_CAPABLE_ERROR;
539*1c60b9acSAndroid Build Coastguard Worker 	}
540*1c60b9acSAndroid Build Coastguard Worker 
541*1c60b9acSAndroid Build Coastguard Worker 	if (m == SSL_ERROR_SSL) {
542*1c60b9acSAndroid Build Coastguard Worker 		n = lws_snprintf(errbuf, elen, "tls: %s", wsi->tls.err_helper);
543*1c60b9acSAndroid Build Coastguard Worker 		if (!wsi->tls.err_helper[0])
544*1c60b9acSAndroid Build Coastguard Worker 			ERR_error_string_n((unsigned int)m, errbuf + n, (elen - (unsigned int)n));
545*1c60b9acSAndroid Build Coastguard Worker 		return LWS_SSL_CAPABLE_ERROR;
546*1c60b9acSAndroid Build Coastguard Worker 	}
547*1c60b9acSAndroid Build Coastguard Worker 
548*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_TLS_SESSIONS)
549*1c60b9acSAndroid Build Coastguard Worker 	if (SSL_session_reused(wsi->tls.ssl)) {
550*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_HAVE_SSL_SESSION_set_time)
551*1c60b9acSAndroid Build Coastguard Worker 		sess = SSL_get_session(wsi->tls.ssl);
552*1c60b9acSAndroid Build Coastguard Worker 		if (sess) /* should always be true */
553*1c60b9acSAndroid Build Coastguard Worker #if defined(OPENSSL_IS_BORINGSSL)
554*1c60b9acSAndroid Build Coastguard Worker 			SSL_SESSION_set_time(sess, (uint64_t)time(NULL)); /* extend session lifetime */
555*1c60b9acSAndroid Build Coastguard Worker #else
556*1c60b9acSAndroid Build Coastguard Worker 			SSL_SESSION_set_time(sess, (long)time(NULL)); /* extend session lifetime */
557*1c60b9acSAndroid Build Coastguard Worker #endif
558*1c60b9acSAndroid Build Coastguard Worker #endif
559*1c60b9acSAndroid Build Coastguard Worker 	}
560*1c60b9acSAndroid Build Coastguard Worker #endif
561*1c60b9acSAndroid Build Coastguard Worker 
562*1c60b9acSAndroid Build Coastguard Worker 	if (m == SSL_ERROR_WANT_READ || SSL_want_read(wsi->tls.ssl))
563*1c60b9acSAndroid Build Coastguard Worker 		return LWS_SSL_CAPABLE_MORE_SERVICE_READ;
564*1c60b9acSAndroid Build Coastguard Worker 
565*1c60b9acSAndroid Build Coastguard Worker 	if (m == SSL_ERROR_WANT_WRITE || SSL_want_write(wsi->tls.ssl))
566*1c60b9acSAndroid Build Coastguard Worker 		return LWS_SSL_CAPABLE_MORE_SERVICE_WRITE;
567*1c60b9acSAndroid Build Coastguard Worker 
568*1c60b9acSAndroid Build Coastguard Worker 	if (n == 1 || m == SSL_ERROR_SYSCALL) {
569*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_HAVE_SSL_set_alpn_protos) && \
570*1c60b9acSAndroid Build Coastguard Worker     defined(LWS_HAVE_SSL_get0_alpn_selected)
571*1c60b9acSAndroid Build Coastguard Worker 		SSL_get0_alpn_selected(wsi->tls.ssl, &prot, &len);
572*1c60b9acSAndroid Build Coastguard Worker 
573*1c60b9acSAndroid Build Coastguard Worker 		if (len >= sizeof(a))
574*1c60b9acSAndroid Build Coastguard Worker 			len = sizeof(a) - 1;
575*1c60b9acSAndroid Build Coastguard Worker 		memcpy(a, (const char *)prot, len);
576*1c60b9acSAndroid Build Coastguard Worker 		a[len] = '\0';
577*1c60b9acSAndroid Build Coastguard Worker 
578*1c60b9acSAndroid Build Coastguard Worker 		lws_role_call_alpn_negotiated(wsi, (const char *)a);
579*1c60b9acSAndroid Build Coastguard Worker #endif
580*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_TLS_SYNTHESIZE_CB)
581*1c60b9acSAndroid Build Coastguard Worker 		lws_sul_schedule(wsi->a.context, wsi->tsi,
582*1c60b9acSAndroid Build Coastguard Worker 				 &wsi->tls.sul_cb_synth,
583*1c60b9acSAndroid Build Coastguard Worker 				 lws_sess_cache_synth_cb, 500 * LWS_US_PER_MS);
584*1c60b9acSAndroid Build Coastguard Worker #endif
585*1c60b9acSAndroid Build Coastguard Worker 
586*1c60b9acSAndroid Build Coastguard Worker 		lwsl_info("client connect OK\n");
587*1c60b9acSAndroid Build Coastguard Worker 		lws_openssl_describe_cipher(wsi);
588*1c60b9acSAndroid Build Coastguard Worker 		return LWS_SSL_CAPABLE_DONE;
589*1c60b9acSAndroid Build Coastguard Worker 	}
590*1c60b9acSAndroid Build Coastguard Worker 
591*1c60b9acSAndroid Build Coastguard Worker 	if (!n) /* we don't know what he wants, but he says to retry */
592*1c60b9acSAndroid Build Coastguard Worker 		return LWS_SSL_CAPABLE_MORE_SERVICE;
593*1c60b9acSAndroid Build Coastguard Worker 
594*1c60b9acSAndroid Build Coastguard Worker 	lws_snprintf(errbuf, elen, "connect unk %d", m);
595*1c60b9acSAndroid Build Coastguard Worker 
596*1c60b9acSAndroid Build Coastguard Worker 	return LWS_SSL_CAPABLE_ERROR;
597*1c60b9acSAndroid Build Coastguard Worker }
598*1c60b9acSAndroid Build Coastguard Worker 
599*1c60b9acSAndroid Build Coastguard Worker int
lws_tls_client_confirm_peer_cert(struct lws * wsi,char * ebuf,size_t ebuf_len)600*1c60b9acSAndroid Build Coastguard Worker lws_tls_client_confirm_peer_cert(struct lws *wsi, char *ebuf, size_t ebuf_len)
601*1c60b9acSAndroid Build Coastguard Worker {
602*1c60b9acSAndroid Build Coastguard Worker #if !defined(USE_WOLFSSL)
603*1c60b9acSAndroid Build Coastguard Worker 	struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi];
604*1c60b9acSAndroid Build Coastguard Worker 	char *p = (char *)&pt->serv_buf[0];
605*1c60b9acSAndroid Build Coastguard Worker 	const char *es, *type = "";
606*1c60b9acSAndroid Build Coastguard Worker 	unsigned int avoid = 0;
607*1c60b9acSAndroid Build Coastguard Worker 	char *sb = p;
608*1c60b9acSAndroid Build Coastguard Worker 	long n;
609*1c60b9acSAndroid Build Coastguard Worker 
610*1c60b9acSAndroid Build Coastguard Worker 	errno = 0;
611*1c60b9acSAndroid Build Coastguard Worker 	ERR_clear_error();
612*1c60b9acSAndroid Build Coastguard Worker 	n = SSL_get_verify_result(wsi->tls.ssl);
613*1c60b9acSAndroid Build Coastguard Worker 
614*1c60b9acSAndroid Build Coastguard Worker 	switch (n) {
615*1c60b9acSAndroid Build Coastguard Worker 	case X509_V_OK:
616*1c60b9acSAndroid Build Coastguard Worker 		return 0;
617*1c60b9acSAndroid Build Coastguard Worker 
618*1c60b9acSAndroid Build Coastguard Worker 	case X509_V_ERR_HOSTNAME_MISMATCH:
619*1c60b9acSAndroid Build Coastguard Worker 		type = "tls=hostname";
620*1c60b9acSAndroid Build Coastguard Worker 		avoid = LCCSCF_SKIP_SERVER_CERT_HOSTNAME_CHECK;
621*1c60b9acSAndroid Build Coastguard Worker 		break;
622*1c60b9acSAndroid Build Coastguard Worker 
623*1c60b9acSAndroid Build Coastguard Worker 	case X509_V_ERR_INVALID_CA:
624*1c60b9acSAndroid Build Coastguard Worker 	case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
625*1c60b9acSAndroid Build Coastguard Worker 	case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN:
626*1c60b9acSAndroid Build Coastguard Worker 		type = "tls=invalidca";
627*1c60b9acSAndroid Build Coastguard Worker 		avoid = LCCSCF_ALLOW_SELFSIGNED;
628*1c60b9acSAndroid Build Coastguard Worker 		break;
629*1c60b9acSAndroid Build Coastguard Worker 
630*1c60b9acSAndroid Build Coastguard Worker 	case X509_V_ERR_CERT_NOT_YET_VALID:
631*1c60b9acSAndroid Build Coastguard Worker 		type = "tls=notyetvalid";
632*1c60b9acSAndroid Build Coastguard Worker 		avoid = LCCSCF_ALLOW_EXPIRED;
633*1c60b9acSAndroid Build Coastguard Worker 		break;
634*1c60b9acSAndroid Build Coastguard Worker 
635*1c60b9acSAndroid Build Coastguard Worker 	case X509_V_ERR_CERT_HAS_EXPIRED:
636*1c60b9acSAndroid Build Coastguard Worker 		type = "tls=expired";
637*1c60b9acSAndroid Build Coastguard Worker 		avoid = LCCSCF_ALLOW_EXPIRED;
638*1c60b9acSAndroid Build Coastguard Worker 		break;
639*1c60b9acSAndroid Build Coastguard Worker 	}
640*1c60b9acSAndroid Build Coastguard Worker 
641*1c60b9acSAndroid Build Coastguard Worker 	lwsl_info("%s: cert problem: %s\n", __func__, type);
642*1c60b9acSAndroid Build Coastguard Worker 
643*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_SYS_METRICS)
644*1c60b9acSAndroid Build Coastguard Worker 	lws_metrics_hist_bump_describe_wsi(wsi,
645*1c60b9acSAndroid Build Coastguard Worker 			lws_metrics_priv_to_pub(wsi->a.context->mth_conn_failures), type);
646*1c60b9acSAndroid Build Coastguard Worker #endif
647*1c60b9acSAndroid Build Coastguard Worker 
648*1c60b9acSAndroid Build Coastguard Worker 	if (wsi->tls.use_ssl & avoid) {
649*1c60b9acSAndroid Build Coastguard Worker 		lwsl_info("%s: allowing anyway\n", __func__);
650*1c60b9acSAndroid Build Coastguard Worker 
651*1c60b9acSAndroid Build Coastguard Worker 		return 0;
652*1c60b9acSAndroid Build Coastguard Worker 	}
653*1c60b9acSAndroid Build Coastguard Worker 
654*1c60b9acSAndroid Build Coastguard Worker 	es = ERR_error_string(
655*1c60b9acSAndroid Build Coastguard Worker 	#if defined(LWS_WITH_BORINGSSL)
656*1c60b9acSAndroid Build Coastguard Worker 					 (uint32_t)
657*1c60b9acSAndroid Build Coastguard Worker 	#else
658*1c60b9acSAndroid Build Coastguard Worker 					 (unsigned long)
659*1c60b9acSAndroid Build Coastguard Worker 	#endif
660*1c60b9acSAndroid Build Coastguard Worker 					 n, sb);
661*1c60b9acSAndroid Build Coastguard Worker 	lws_snprintf(ebuf, ebuf_len,
662*1c60b9acSAndroid Build Coastguard Worker 		"server's cert didn't look good, %s X509_V_ERR = %ld: %s\n",
663*1c60b9acSAndroid Build Coastguard Worker 		 type, n, es);
664*1c60b9acSAndroid Build Coastguard Worker 	lwsl_info("%s\n", ebuf);
665*1c60b9acSAndroid Build Coastguard Worker 	lws_tls_err_describe_clear();
666*1c60b9acSAndroid Build Coastguard Worker 
667*1c60b9acSAndroid Build Coastguard Worker 	return -1;
668*1c60b9acSAndroid Build Coastguard Worker 
669*1c60b9acSAndroid Build Coastguard Worker #else /* USE_WOLFSSL */
670*1c60b9acSAndroid Build Coastguard Worker 	return 0;
671*1c60b9acSAndroid Build Coastguard Worker #endif
672*1c60b9acSAndroid Build Coastguard Worker }
673*1c60b9acSAndroid Build Coastguard Worker 
674*1c60b9acSAndroid Build Coastguard Worker int
lws_tls_client_vhost_extra_cert_mem(struct lws_vhost * vh,const uint8_t * der,size_t der_len)675*1c60b9acSAndroid Build Coastguard Worker lws_tls_client_vhost_extra_cert_mem(struct lws_vhost *vh,
676*1c60b9acSAndroid Build Coastguard Worker                 const uint8_t *der, size_t der_len)
677*1c60b9acSAndroid Build Coastguard Worker {
678*1c60b9acSAndroid Build Coastguard Worker 	X509_STORE *st;
679*1c60b9acSAndroid Build Coastguard Worker #if defined(USE_WOLFSSL)
680*1c60b9acSAndroid Build Coastguard Worker 	X509 *x  = d2i_X509(NULL, &der, (int)der_len);
681*1c60b9acSAndroid Build Coastguard Worker #else
682*1c60b9acSAndroid Build Coastguard Worker 	X509 *x  = d2i_X509(NULL, &der, (long)der_len);
683*1c60b9acSAndroid Build Coastguard Worker #endif
684*1c60b9acSAndroid Build Coastguard Worker 	int n;
685*1c60b9acSAndroid Build Coastguard Worker 
686*1c60b9acSAndroid Build Coastguard Worker 	if (!x) {
687*1c60b9acSAndroid Build Coastguard Worker 		lwsl_err("%s: Failed to load DER\n", __func__);
688*1c60b9acSAndroid Build Coastguard Worker 		lws_tls_err_describe_clear();
689*1c60b9acSAndroid Build Coastguard Worker 		return 1;
690*1c60b9acSAndroid Build Coastguard Worker 	}
691*1c60b9acSAndroid Build Coastguard Worker 
692*1c60b9acSAndroid Build Coastguard Worker 	st = SSL_CTX_get_cert_store(vh->tls.ssl_client_ctx);
693*1c60b9acSAndroid Build Coastguard Worker 	if (!st) {
694*1c60b9acSAndroid Build Coastguard Worker 		lwsl_err("%s: failed to get cert store\n", __func__);
695*1c60b9acSAndroid Build Coastguard Worker 		X509_free(x);
696*1c60b9acSAndroid Build Coastguard Worker 		return 1;
697*1c60b9acSAndroid Build Coastguard Worker 	}
698*1c60b9acSAndroid Build Coastguard Worker 
699*1c60b9acSAndroid Build Coastguard Worker 	n = X509_STORE_add_cert(st, x);
700*1c60b9acSAndroid Build Coastguard Worker 	if (n != 1)
701*1c60b9acSAndroid Build Coastguard Worker 		lwsl_err("%s: failed to add cert\n", __func__);
702*1c60b9acSAndroid Build Coastguard Worker 
703*1c60b9acSAndroid Build Coastguard Worker 	X509_free(x);
704*1c60b9acSAndroid Build Coastguard Worker 
705*1c60b9acSAndroid Build Coastguard Worker 	return n != 1;
706*1c60b9acSAndroid Build Coastguard Worker }
707*1c60b9acSAndroid Build Coastguard Worker 
708*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)709*1c60b9acSAndroid Build Coastguard Worker lws_tls_client_create_vhost_context(struct lws_vhost *vh,
710*1c60b9acSAndroid Build Coastguard Worker 				    const struct lws_context_creation_info *info,
711*1c60b9acSAndroid Build Coastguard Worker 				    const char *cipher_list,
712*1c60b9acSAndroid Build Coastguard Worker 				    const char *ca_filepath,
713*1c60b9acSAndroid Build Coastguard Worker 				    const void *ca_mem,
714*1c60b9acSAndroid Build Coastguard Worker 				    unsigned int ca_mem_len,
715*1c60b9acSAndroid Build Coastguard Worker 				    const char *cert_filepath,
716*1c60b9acSAndroid Build Coastguard Worker 				    const void *cert_mem,
717*1c60b9acSAndroid Build Coastguard Worker 				    unsigned int cert_mem_len,
718*1c60b9acSAndroid Build Coastguard Worker 				    const char *private_key_filepath,
719*1c60b9acSAndroid Build Coastguard Worker 					const void *key_mem,
720*1c60b9acSAndroid Build Coastguard Worker 				    unsigned int key_mem_len
721*1c60b9acSAndroid Build Coastguard Worker 					)
722*1c60b9acSAndroid Build Coastguard Worker {
723*1c60b9acSAndroid Build Coastguard Worker 	struct lws_tls_client_reuse *tcr;
724*1c60b9acSAndroid Build Coastguard Worker 	X509_STORE *x509_store;
725*1c60b9acSAndroid Build Coastguard Worker 	unsigned long error;
726*1c60b9acSAndroid Build Coastguard Worker 	SSL_METHOD *method;
727*1c60b9acSAndroid Build Coastguard Worker 	EVP_MD_CTX *mdctx;
728*1c60b9acSAndroid Build Coastguard Worker 	unsigned int len;
729*1c60b9acSAndroid Build Coastguard Worker 	uint8_t hash[32];
730*1c60b9acSAndroid Build Coastguard Worker 	X509 *client_CA;
731*1c60b9acSAndroid Build Coastguard Worker 	char c;
732*1c60b9acSAndroid Build Coastguard Worker 	int n;
733*1c60b9acSAndroid Build Coastguard Worker 
734*1c60b9acSAndroid Build Coastguard Worker 	/* basic openssl init already happened in context init */
735*1c60b9acSAndroid Build Coastguard Worker 
736*1c60b9acSAndroid Build Coastguard Worker 	/* choose the most recent spin of the api */
737*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_HAVE_TLS_CLIENT_METHOD)
738*1c60b9acSAndroid Build Coastguard Worker 	method = (SSL_METHOD *)TLS_client_method();
739*1c60b9acSAndroid Build Coastguard Worker #elif defined(LWS_HAVE_TLSV1_2_CLIENT_METHOD)
740*1c60b9acSAndroid Build Coastguard Worker 	method = (SSL_METHOD *)TLSv1_2_client_method();
741*1c60b9acSAndroid Build Coastguard Worker #else
742*1c60b9acSAndroid Build Coastguard Worker 	method = (SSL_METHOD *)SSLv23_client_method();
743*1c60b9acSAndroid Build Coastguard Worker #endif
744*1c60b9acSAndroid Build Coastguard Worker 
745*1c60b9acSAndroid Build Coastguard Worker 	if (!method) {
746*1c60b9acSAndroid Build Coastguard Worker 		const char *es;
747*1c60b9acSAndroid Build Coastguard Worker 
748*1c60b9acSAndroid Build Coastguard Worker 		error = ERR_get_error();
749*1c60b9acSAndroid Build Coastguard Worker 		es = ERR_error_string(
750*1c60b9acSAndroid Build Coastguard Worker 		#if defined(LWS_WITH_BORINGSSL)
751*1c60b9acSAndroid Build Coastguard Worker 			(uint32_t)
752*1c60b9acSAndroid Build Coastguard Worker 		#else
753*1c60b9acSAndroid Build Coastguard Worker 			(unsigned long)
754*1c60b9acSAndroid Build Coastguard Worker 		#endif
755*1c60b9acSAndroid Build Coastguard Worker 			 error, (char *)vh->context->pt[0].serv_buf);
756*1c60b9acSAndroid Build Coastguard Worker 		lwsl_err("problem creating ssl method %lu: %s\n",
757*1c60b9acSAndroid Build Coastguard Worker 			error, es);
758*1c60b9acSAndroid Build Coastguard Worker 		return 1;
759*1c60b9acSAndroid Build Coastguard Worker 	}
760*1c60b9acSAndroid Build Coastguard Worker 
761*1c60b9acSAndroid Build Coastguard Worker 	/*
762*1c60b9acSAndroid Build Coastguard Worker 	 * OpenSSL client contexts are quite expensive, because they bring in
763*1c60b9acSAndroid Build Coastguard Worker 	 * the system certificate bundle for each one.  So if you have multiple
764*1c60b9acSAndroid Build Coastguard Worker 	 * vhosts, each with a client context, it can add up to several
765*1c60b9acSAndroid Build Coastguard Worker 	 * megabytes of heap.  In the case the client contexts are configured
766*1c60b9acSAndroid Build Coastguard Worker 	 * identically, they could perfectly well have shared just the one.
767*1c60b9acSAndroid Build Coastguard Worker 	 *
768*1c60b9acSAndroid Build Coastguard Worker 	 * For that reason, use a hash to fingerprint the context configuration
769*1c60b9acSAndroid Build Coastguard Worker 	 * and prefer to reuse an existing one with the same fingerprint if
770*1c60b9acSAndroid Build Coastguard Worker 	 * possible.
771*1c60b9acSAndroid Build Coastguard Worker 	 */
772*1c60b9acSAndroid Build Coastguard Worker 
773*1c60b9acSAndroid Build Coastguard Worker 	 mdctx = EVP_MD_CTX_create();
774*1c60b9acSAndroid Build Coastguard Worker 	 if (!mdctx)
775*1c60b9acSAndroid Build Coastguard Worker 		 return 1;
776*1c60b9acSAndroid Build Coastguard Worker 
777*1c60b9acSAndroid Build Coastguard Worker 	if (EVP_DigestInit_ex(mdctx, EVP_sha256(), NULL) != 1) {
778*1c60b9acSAndroid Build Coastguard Worker 		EVP_MD_CTX_destroy(mdctx);
779*1c60b9acSAndroid Build Coastguard Worker 
780*1c60b9acSAndroid Build Coastguard Worker 		return 1;
781*1c60b9acSAndroid Build Coastguard Worker 	}
782*1c60b9acSAndroid Build Coastguard Worker 
783*1c60b9acSAndroid Build Coastguard Worker 	if (info->ssl_client_options_set)
784*1c60b9acSAndroid Build Coastguard Worker 		EVP_DigestUpdate(mdctx, &info->ssl_client_options_set,
785*1c60b9acSAndroid Build Coastguard Worker 				 sizeof(info->ssl_client_options_set));
786*1c60b9acSAndroid Build Coastguard Worker 
787*1c60b9acSAndroid Build Coastguard Worker #if (OPENSSL_VERSION_NUMBER >= 0x009080df) && !defined(USE_WOLFSSL)
788*1c60b9acSAndroid Build Coastguard Worker 	if (info->ssl_client_options_clear)
789*1c60b9acSAndroid Build Coastguard Worker 		EVP_DigestUpdate(mdctx, &info->ssl_client_options_clear,
790*1c60b9acSAndroid Build Coastguard Worker 				 sizeof(info->ssl_client_options_clear));
791*1c60b9acSAndroid Build Coastguard Worker #endif
792*1c60b9acSAndroid Build Coastguard Worker 
793*1c60b9acSAndroid Build Coastguard Worker 	if (cipher_list)
794*1c60b9acSAndroid Build Coastguard Worker 		EVP_DigestUpdate(mdctx, cipher_list, strlen(cipher_list));
795*1c60b9acSAndroid Build Coastguard Worker 
796*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_HAVE_SSL_CTX_set_ciphersuites)
797*1c60b9acSAndroid Build Coastguard Worker 	if (info->client_tls_1_3_plus_cipher_list)
798*1c60b9acSAndroid Build Coastguard Worker 		EVP_DigestUpdate(mdctx, info->client_tls_1_3_plus_cipher_list,
799*1c60b9acSAndroid Build Coastguard Worker 				 strlen(info->client_tls_1_3_plus_cipher_list));
800*1c60b9acSAndroid Build Coastguard Worker #endif
801*1c60b9acSAndroid Build Coastguard Worker 
802*1c60b9acSAndroid Build Coastguard Worker 	if (!lws_check_opt(vh->options, LWS_SERVER_OPTION_DISABLE_OS_CA_CERTS)) {
803*1c60b9acSAndroid Build Coastguard Worker 		c = 1;
804*1c60b9acSAndroid Build Coastguard Worker 		EVP_DigestUpdate(mdctx, &c, 1);
805*1c60b9acSAndroid Build Coastguard Worker 	}
806*1c60b9acSAndroid Build Coastguard Worker 
807*1c60b9acSAndroid Build Coastguard Worker 	if (ca_filepath)
808*1c60b9acSAndroid Build Coastguard Worker 		EVP_DigestUpdate(mdctx, ca_filepath, strlen(ca_filepath));
809*1c60b9acSAndroid Build Coastguard Worker 
810*1c60b9acSAndroid Build Coastguard Worker 	if (cert_filepath)
811*1c60b9acSAndroid Build Coastguard Worker 		EVP_DigestUpdate(mdctx, cert_filepath, strlen(cert_filepath));
812*1c60b9acSAndroid Build Coastguard Worker 
813*1c60b9acSAndroid Build Coastguard Worker 	if (private_key_filepath)
814*1c60b9acSAndroid Build Coastguard Worker 		EVP_DigestUpdate(mdctx, private_key_filepath,
815*1c60b9acSAndroid Build Coastguard Worker 				 strlen(private_key_filepath));
816*1c60b9acSAndroid Build Coastguard Worker 	if (ca_mem && ca_mem_len)
817*1c60b9acSAndroid Build Coastguard Worker 		EVP_DigestUpdate(mdctx, ca_mem, ca_mem_len);
818*1c60b9acSAndroid Build Coastguard Worker 
819*1c60b9acSAndroid Build Coastguard Worker 	if (cert_mem && cert_mem_len)
820*1c60b9acSAndroid Build Coastguard Worker 		EVP_DigestUpdate(mdctx, cert_mem, cert_mem_len);
821*1c60b9acSAndroid Build Coastguard Worker 
822*1c60b9acSAndroid Build Coastguard Worker 	len = sizeof(hash);
823*1c60b9acSAndroid Build Coastguard Worker 	EVP_DigestFinal_ex(mdctx, hash, &len);
824*1c60b9acSAndroid Build Coastguard Worker 	EVP_MD_CTX_destroy(mdctx);
825*1c60b9acSAndroid Build Coastguard Worker 
826*1c60b9acSAndroid Build Coastguard Worker 	/* look for existing client context with same config already */
827*1c60b9acSAndroid Build Coastguard Worker 
828*1c60b9acSAndroid Build Coastguard Worker 	lws_start_foreach_dll_safe(struct lws_dll2 *, p, tp,
829*1c60b9acSAndroid Build Coastguard Worker 			 lws_dll2_get_head(&vh->context->tls.cc_owner)) {
830*1c60b9acSAndroid Build Coastguard Worker 		tcr = lws_container_of(p, struct lws_tls_client_reuse, cc_list);
831*1c60b9acSAndroid Build Coastguard Worker 
832*1c60b9acSAndroid Build Coastguard Worker 		if (!memcmp(hash, tcr->hash, len)) {
833*1c60b9acSAndroid Build Coastguard Worker 
834*1c60b9acSAndroid Build Coastguard Worker 			/* it's a match */
835*1c60b9acSAndroid Build Coastguard Worker 
836*1c60b9acSAndroid Build Coastguard Worker 			tcr->refcount++;
837*1c60b9acSAndroid Build Coastguard Worker 			vh->tls.ssl_client_ctx = tcr->ssl_client_ctx;
838*1c60b9acSAndroid Build Coastguard Worker 			vh->tls.tcr = tcr;
839*1c60b9acSAndroid Build Coastguard Worker 
840*1c60b9acSAndroid Build Coastguard Worker 			lwsl_info("%s: vh %s: reusing client ctx %d: use %d\n",
841*1c60b9acSAndroid Build Coastguard Worker 				   __func__, vh->name, tcr->index,
842*1c60b9acSAndroid Build Coastguard Worker 				   tcr->refcount);
843*1c60b9acSAndroid Build Coastguard Worker 
844*1c60b9acSAndroid Build Coastguard Worker 			return 0;
845*1c60b9acSAndroid Build Coastguard Worker 		}
846*1c60b9acSAndroid Build Coastguard Worker 	} lws_end_foreach_dll_safe(p, tp);
847*1c60b9acSAndroid Build Coastguard Worker 
848*1c60b9acSAndroid Build Coastguard Worker 	/* no existing one the same... create new client SSL_CTX */
849*1c60b9acSAndroid Build Coastguard Worker 
850*1c60b9acSAndroid Build Coastguard Worker 	errno = 0;
851*1c60b9acSAndroid Build Coastguard Worker 	ERR_clear_error();
852*1c60b9acSAndroid Build Coastguard Worker 	vh->tls.ssl_client_ctx = SSL_CTX_new(method);
853*1c60b9acSAndroid Build Coastguard Worker 	if (!vh->tls.ssl_client_ctx) {
854*1c60b9acSAndroid Build Coastguard Worker 		const char *es;
855*1c60b9acSAndroid Build Coastguard Worker 
856*1c60b9acSAndroid Build Coastguard Worker 		error = ERR_get_error();
857*1c60b9acSAndroid Build Coastguard Worker 		es = ERR_error_string(
858*1c60b9acSAndroid Build Coastguard Worker 		#if defined(LWS_WITH_BORINGSSL)
859*1c60b9acSAndroid Build Coastguard Worker 			(uint32_t)
860*1c60b9acSAndroid Build Coastguard Worker 		#else
861*1c60b9acSAndroid Build Coastguard Worker 			(unsigned long)
862*1c60b9acSAndroid Build Coastguard Worker 		#endif
863*1c60b9acSAndroid Build Coastguard Worker 			 error, (char *)vh->context->pt[0].serv_buf);
864*1c60b9acSAndroid Build Coastguard Worker 		lwsl_err("problem creating ssl context %lu: %s\n",
865*1c60b9acSAndroid Build Coastguard Worker 			error, es);
866*1c60b9acSAndroid Build Coastguard Worker 		return 1;
867*1c60b9acSAndroid Build Coastguard Worker 	}
868*1c60b9acSAndroid Build Coastguard Worker 
869*1c60b9acSAndroid Build Coastguard Worker 	lws_plat_vhost_tls_client_ctx_init(vh);
870*1c60b9acSAndroid Build Coastguard Worker 
871*1c60b9acSAndroid Build Coastguard Worker 	tcr = lws_zalloc(sizeof(*tcr), "client ctx tcr");
872*1c60b9acSAndroid Build Coastguard Worker 	if (!tcr) {
873*1c60b9acSAndroid Build Coastguard Worker 		SSL_CTX_free(vh->tls.ssl_client_ctx);
874*1c60b9acSAndroid Build Coastguard Worker 		return 1;
875*1c60b9acSAndroid Build Coastguard Worker 	}
876*1c60b9acSAndroid Build Coastguard Worker 
877*1c60b9acSAndroid Build Coastguard Worker 	tcr->ssl_client_ctx = vh->tls.ssl_client_ctx;
878*1c60b9acSAndroid Build Coastguard Worker 	tcr->refcount = 1;
879*1c60b9acSAndroid Build Coastguard Worker 	memcpy(tcr->hash, hash, len);
880*1c60b9acSAndroid Build Coastguard Worker 	tcr->index = vh->context->tls.count_client_contexts++;
881*1c60b9acSAndroid Build Coastguard Worker 	lws_dll2_add_head(&tcr->cc_list, &vh->context->tls.cc_owner);
882*1c60b9acSAndroid Build Coastguard Worker 
883*1c60b9acSAndroid Build Coastguard Worker 	lwsl_info("%s: vh %s: created new client ctx %d\n", __func__,
884*1c60b9acSAndroid Build Coastguard Worker 			vh->name, tcr->index);
885*1c60b9acSAndroid Build Coastguard Worker 
886*1c60b9acSAndroid Build Coastguard Worker 	/* bind the tcr to the client context */
887*1c60b9acSAndroid Build Coastguard Worker 
888*1c60b9acSAndroid Build Coastguard Worker 	vh->tls.tcr = tcr;
889*1c60b9acSAndroid Build Coastguard Worker 
890*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_TLS_SESSIONS)
891*1c60b9acSAndroid Build Coastguard Worker 	vh->tls_session_cache_max = info->tls_session_cache_max ?
892*1c60b9acSAndroid Build Coastguard Worker 				    info->tls_session_cache_max : 10;
893*1c60b9acSAndroid Build Coastguard Worker 	lws_tls_session_cache(vh, info->tls_session_timeout);
894*1c60b9acSAndroid Build Coastguard Worker #endif
895*1c60b9acSAndroid Build Coastguard Worker 
896*1c60b9acSAndroid Build Coastguard Worker #ifdef SSL_OP_NO_COMPRESSION
897*1c60b9acSAndroid Build Coastguard Worker 	SSL_CTX_set_options(vh->tls.ssl_client_ctx, SSL_OP_NO_COMPRESSION);
898*1c60b9acSAndroid Build Coastguard Worker #endif
899*1c60b9acSAndroid Build Coastguard Worker 
900*1c60b9acSAndroid Build Coastguard Worker 	SSL_CTX_set_options(vh->tls.ssl_client_ctx,
901*1c60b9acSAndroid Build Coastguard Worker 			    SSL_OP_CIPHER_SERVER_PREFERENCE);
902*1c60b9acSAndroid Build Coastguard Worker 
903*1c60b9acSAndroid Build Coastguard Worker 	SSL_CTX_set_mode(vh->tls.ssl_client_ctx,
904*1c60b9acSAndroid Build Coastguard Worker 			 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
905*1c60b9acSAndroid Build Coastguard Worker 			 SSL_MODE_RELEASE_BUFFERS);
906*1c60b9acSAndroid Build Coastguard Worker 
907*1c60b9acSAndroid Build Coastguard Worker 	if (info->ssl_client_options_set)
908*1c60b9acSAndroid Build Coastguard Worker 		SSL_CTX_set_options(vh->tls.ssl_client_ctx,
909*1c60b9acSAndroid Build Coastguard Worker #if !defined(USE_WOLFSSL)
910*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_BORINGSSL)
911*1c60b9acSAndroid Build Coastguard Worker 				(uint32_t)
912*1c60b9acSAndroid Build Coastguard Worker #else
913*1c60b9acSAndroid Build Coastguard Worker #if (OPENSSL_VERSION_NUMBER >= 0x10003000l) && \
914*1c60b9acSAndroid Build Coastguard Worker 	!defined(LIBRESSL_VERSION_NUMBER) /* not documented by openssl */
915*1c60b9acSAndroid Build Coastguard Worker 				    (unsigned long)
916*1c60b9acSAndroid Build Coastguard Worker #else
917*1c60b9acSAndroid Build Coastguard Worker 				    (long)
918*1c60b9acSAndroid Build Coastguard Worker #endif
919*1c60b9acSAndroid Build Coastguard Worker #endif
920*1c60b9acSAndroid Build Coastguard Worker #endif
921*1c60b9acSAndroid Build Coastguard Worker 				    info->ssl_client_options_set);
922*1c60b9acSAndroid Build Coastguard Worker 
923*1c60b9acSAndroid Build Coastguard Worker 	/* SSL_clear_options introduced in 0.9.8m */
924*1c60b9acSAndroid Build Coastguard Worker #if (OPENSSL_VERSION_NUMBER >= 0x009080df) && !defined(USE_WOLFSSL)
925*1c60b9acSAndroid Build Coastguard Worker 	if (info->ssl_client_options_clear)
926*1c60b9acSAndroid Build Coastguard Worker 		SSL_CTX_clear_options(vh->tls.ssl_client_ctx,
927*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_BORINGSSL)
928*1c60b9acSAndroid Build Coastguard Worker 				(uint32_t)
929*1c60b9acSAndroid Build Coastguard Worker #else
930*1c60b9acSAndroid Build Coastguard Worker #if (OPENSSL_VERSION_NUMBER >= 0x10003000l) && \
931*1c60b9acSAndroid Build Coastguard Worker 	!defined(LIBRESSL_VERSION_NUMBER) /* not documented by openssl */
932*1c60b9acSAndroid Build Coastguard Worker 				    (unsigned long)
933*1c60b9acSAndroid Build Coastguard Worker #else
934*1c60b9acSAndroid Build Coastguard Worker 				    (long)
935*1c60b9acSAndroid Build Coastguard Worker #endif
936*1c60b9acSAndroid Build Coastguard Worker #endif
937*1c60b9acSAndroid Build Coastguard Worker 				      info->ssl_client_options_clear);
938*1c60b9acSAndroid Build Coastguard Worker #endif
939*1c60b9acSAndroid Build Coastguard Worker 
940*1c60b9acSAndroid Build Coastguard Worker 	if (cipher_list)
941*1c60b9acSAndroid Build Coastguard Worker 		SSL_CTX_set_cipher_list(vh->tls.ssl_client_ctx, cipher_list);
942*1c60b9acSAndroid Build Coastguard Worker 
943*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_HAVE_SSL_CTX_set_ciphersuites)
944*1c60b9acSAndroid Build Coastguard Worker 	if (info->client_tls_1_3_plus_cipher_list)
945*1c60b9acSAndroid Build Coastguard Worker 		SSL_CTX_set_ciphersuites(vh->tls.ssl_client_ctx,
946*1c60b9acSAndroid Build Coastguard Worker 					 info->client_tls_1_3_plus_cipher_list);
947*1c60b9acSAndroid Build Coastguard Worker #endif
948*1c60b9acSAndroid Build Coastguard Worker 
949*1c60b9acSAndroid Build Coastguard Worker #ifdef LWS_SSL_CLIENT_USE_OS_CA_CERTS
950*1c60b9acSAndroid Build Coastguard Worker 	if (!lws_check_opt(vh->options, LWS_SERVER_OPTION_DISABLE_OS_CA_CERTS))
951*1c60b9acSAndroid Build Coastguard Worker 		/* loads OS default CA certs */
952*1c60b9acSAndroid Build Coastguard Worker 		SSL_CTX_set_default_verify_paths(vh->tls.ssl_client_ctx);
953*1c60b9acSAndroid Build Coastguard Worker #endif
954*1c60b9acSAndroid Build Coastguard Worker 
955*1c60b9acSAndroid Build Coastguard Worker 	/* openssl init for cert verification (for client sockets) */
956*1c60b9acSAndroid Build Coastguard Worker 	if (!ca_filepath && (!ca_mem || !ca_mem_len)) {
957*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_HAVE_SSL_CTX_load_verify_dir)
958*1c60b9acSAndroid Build Coastguard Worker 		if (!SSL_CTX_load_verify_dir(
959*1c60b9acSAndroid Build Coastguard Worker 			vh->tls.ssl_client_ctx, LWS_OPENSSL_CLIENT_CERTS))
960*1c60b9acSAndroid Build Coastguard Worker #else
961*1c60b9acSAndroid Build Coastguard Worker 		if (!SSL_CTX_load_verify_locations(
962*1c60b9acSAndroid Build Coastguard Worker 			vh->tls.ssl_client_ctx, NULL, LWS_OPENSSL_CLIENT_CERTS))
963*1c60b9acSAndroid Build Coastguard Worker #endif
964*1c60b9acSAndroid Build Coastguard Worker 			lwsl_err("Unable to load SSL Client certs from %s "
965*1c60b9acSAndroid Build Coastguard Worker 			    "(set by LWS_OPENSSL_CLIENT_CERTS) -- "
966*1c60b9acSAndroid Build Coastguard Worker 			    "client ssl isn't going to work\n",
967*1c60b9acSAndroid Build Coastguard Worker 			    LWS_OPENSSL_CLIENT_CERTS);
968*1c60b9acSAndroid Build Coastguard Worker 	} else if (ca_filepath) {
969*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_HAVE_SSL_CTX_load_verify_file)
970*1c60b9acSAndroid Build Coastguard Worker 		if (!SSL_CTX_load_verify_file(
971*1c60b9acSAndroid Build Coastguard Worker 			vh->tls.ssl_client_ctx, ca_filepath)) {
972*1c60b9acSAndroid Build Coastguard Worker #else
973*1c60b9acSAndroid Build Coastguard Worker 		if (!SSL_CTX_load_verify_locations(
974*1c60b9acSAndroid Build Coastguard Worker 			vh->tls.ssl_client_ctx, ca_filepath, NULL)) {
975*1c60b9acSAndroid Build Coastguard Worker #endif
976*1c60b9acSAndroid Build Coastguard Worker 			lwsl_err(
977*1c60b9acSAndroid Build Coastguard Worker 				"Unable to load SSL Client certs "
978*1c60b9acSAndroid Build Coastguard Worker 				"file from %s -- client ssl isn't "
979*1c60b9acSAndroid Build Coastguard Worker 				"going to work\n", ca_filepath);
980*1c60b9acSAndroid Build Coastguard Worker 			lws_tls_err_describe_clear();
981*1c60b9acSAndroid Build Coastguard Worker 		}
982*1c60b9acSAndroid Build Coastguard Worker 		else
983*1c60b9acSAndroid Build Coastguard Worker 			lwsl_info("loaded ssl_ca_filepath\n");
984*1c60b9acSAndroid Build Coastguard Worker 	} else {
985*1c60b9acSAndroid Build Coastguard Worker 
986*1c60b9acSAndroid Build Coastguard Worker 		lws_filepos_t amount = 0;
987*1c60b9acSAndroid Build Coastguard Worker 		const uint8_t *up;
988*1c60b9acSAndroid Build Coastguard Worker 		uint8_t *up1;
989*1c60b9acSAndroid Build Coastguard Worker 
990*1c60b9acSAndroid Build Coastguard Worker 		if (lws_tls_alloc_pem_to_der_file(vh->context, NULL, ca_mem,
991*1c60b9acSAndroid Build Coastguard Worker 						  ca_mem_len, &up1, &amount)) {
992*1c60b9acSAndroid Build Coastguard Worker 			lwsl_err("%s: Unable to decode x.509 mem\n", __func__);
993*1c60b9acSAndroid Build Coastguard Worker 			lwsl_hexdump_notice(ca_mem, ca_mem_len);
994*1c60b9acSAndroid Build Coastguard Worker 			return 1;
995*1c60b9acSAndroid Build Coastguard Worker 		}
996*1c60b9acSAndroid Build Coastguard Worker 
997*1c60b9acSAndroid Build Coastguard Worker 		up = up1;
998*1c60b9acSAndroid Build Coastguard Worker #if defined(USE_WOLFSSL)
999*1c60b9acSAndroid Build Coastguard Worker 		client_CA = d2i_X509(NULL, &up, (int)amount);
1000*1c60b9acSAndroid Build Coastguard Worker #else
1001*1c60b9acSAndroid Build Coastguard Worker 		client_CA = d2i_X509(NULL, &up, (long)amount);
1002*1c60b9acSAndroid Build Coastguard Worker #endif
1003*1c60b9acSAndroid Build Coastguard Worker 		if (!client_CA) {
1004*1c60b9acSAndroid Build Coastguard Worker 			lwsl_err("%s: d2i_X509 failed\n", __func__);
1005*1c60b9acSAndroid Build Coastguard Worker 			lwsl_hexdump_notice(up1, (size_t)amount);
1006*1c60b9acSAndroid Build Coastguard Worker 			lws_tls_err_describe_clear();
1007*1c60b9acSAndroid Build Coastguard Worker 		} else {
1008*1c60b9acSAndroid Build Coastguard Worker 			x509_store = X509_STORE_new();
1009*1c60b9acSAndroid Build Coastguard Worker 			if (!X509_STORE_add_cert(x509_store, client_CA)) {
1010*1c60b9acSAndroid Build Coastguard Worker 				X509_STORE_free(x509_store);
1011*1c60b9acSAndroid Build Coastguard Worker 				lwsl_err("Unable to load SSL Client certs from "
1012*1c60b9acSAndroid Build Coastguard Worker 					 "ssl_ca_mem -- client ssl isn't going to "
1013*1c60b9acSAndroid Build Coastguard Worker 					 "work\n");
1014*1c60b9acSAndroid Build Coastguard Worker 				lws_tls_err_describe_clear();
1015*1c60b9acSAndroid Build Coastguard Worker 			} else {
1016*1c60b9acSAndroid Build Coastguard Worker 				/* it doesn't increment x509_store ref counter */
1017*1c60b9acSAndroid Build Coastguard Worker 				SSL_CTX_set_cert_store(vh->tls.ssl_client_ctx,
1018*1c60b9acSAndroid Build Coastguard Worker 						       x509_store);
1019*1c60b9acSAndroid Build Coastguard Worker 				lwsl_info("loaded ssl_ca_mem\n");
1020*1c60b9acSAndroid Build Coastguard Worker 			}
1021*1c60b9acSAndroid Build Coastguard Worker 		}
1022*1c60b9acSAndroid Build Coastguard Worker 		if (client_CA)
1023*1c60b9acSAndroid Build Coastguard Worker 			X509_free(client_CA);
1024*1c60b9acSAndroid Build Coastguard Worker 		lws_free(up1);
1025*1c60b9acSAndroid Build Coastguard Worker 	//	lws_tls_client_vhost_extra_cert_mem(vh, ca_mem, ca_mem_len);
1026*1c60b9acSAndroid Build Coastguard Worker 	}
1027*1c60b9acSAndroid Build Coastguard Worker 
1028*1c60b9acSAndroid Build Coastguard Worker 	/*
1029*1c60b9acSAndroid Build Coastguard Worker 	 * callback allowing user code to load extra verification certs
1030*1c60b9acSAndroid Build Coastguard Worker 	 * helping the client to verify server identity
1031*1c60b9acSAndroid Build Coastguard Worker 	 */
1032*1c60b9acSAndroid Build Coastguard Worker 
1033*1c60b9acSAndroid Build Coastguard Worker 	/* support for client-side certificate authentication */
1034*1c60b9acSAndroid Build Coastguard Worker 
1035*1c60b9acSAndroid Build Coastguard Worker 	if (cert_filepath) {
1036*1c60b9acSAndroid Build Coastguard Worker 		if (lws_tls_use_any_upgrade_check_extant(cert_filepath) !=
1037*1c60b9acSAndroid Build Coastguard Worker 				LWS_TLS_EXTANT_YES &&
1038*1c60b9acSAndroid Build Coastguard Worker 		    (info->options & LWS_SERVER_OPTION_IGNORE_MISSING_CERT))
1039*1c60b9acSAndroid Build Coastguard Worker 			return 0;
1040*1c60b9acSAndroid Build Coastguard Worker 
1041*1c60b9acSAndroid Build Coastguard Worker 		lwsl_notice("%s: doing cert filepath %s\n", __func__,
1042*1c60b9acSAndroid Build Coastguard Worker 				cert_filepath);
1043*1c60b9acSAndroid Build Coastguard Worker 		n = SSL_CTX_use_certificate_chain_file(vh->tls.ssl_client_ctx,
1044*1c60b9acSAndroid Build Coastguard Worker 						       cert_filepath);
1045*1c60b9acSAndroid Build Coastguard Worker 		if (n < 1) {
1046*1c60b9acSAndroid Build Coastguard Worker 			lwsl_err("problem %d getting cert '%s'\n", n,
1047*1c60b9acSAndroid Build Coastguard Worker 				 cert_filepath);
1048*1c60b9acSAndroid Build Coastguard Worker 			lws_tls_err_describe_clear();
1049*1c60b9acSAndroid Build Coastguard Worker 			return 1;
1050*1c60b9acSAndroid Build Coastguard Worker 		}
1051*1c60b9acSAndroid Build Coastguard Worker 		lwsl_info("Loaded client cert %s\n", cert_filepath);
1052*1c60b9acSAndroid Build Coastguard Worker 
1053*1c60b9acSAndroid Build Coastguard Worker 	} else if (cert_mem && cert_mem_len) {
1054*1c60b9acSAndroid Build Coastguard Worker 		lws_filepos_t flen;
1055*1c60b9acSAndroid Build Coastguard Worker 		uint8_t *p;
1056*1c60b9acSAndroid Build Coastguard Worker 
1057*1c60b9acSAndroid Build Coastguard Worker 		if (lws_tls_alloc_pem_to_der_file(vh->context, NULL, cert_mem,
1058*1c60b9acSAndroid Build Coastguard Worker 						  cert_mem_len, &p, &flen)) {
1059*1c60b9acSAndroid Build Coastguard Worker 			lwsl_err("%s: couldn't read cert file\n", __func__);
1060*1c60b9acSAndroid Build Coastguard Worker 
1061*1c60b9acSAndroid Build Coastguard Worker 			return 1;
1062*1c60b9acSAndroid Build Coastguard Worker 		}
1063*1c60b9acSAndroid Build Coastguard Worker 
1064*1c60b9acSAndroid Build Coastguard Worker 		n = SSL_CTX_use_certificate_ASN1(vh->tls.ssl_client_ctx,
1065*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_BORINGSSL)
1066*1c60b9acSAndroid Build Coastguard Worker 				(size_t)
1067*1c60b9acSAndroid Build Coastguard Worker #else
1068*1c60b9acSAndroid Build Coastguard Worker 				(int)
1069*1c60b9acSAndroid Build Coastguard Worker #endif
1070*1c60b9acSAndroid Build Coastguard Worker 				flen, p);
1071*1c60b9acSAndroid Build Coastguard Worker 
1072*1c60b9acSAndroid Build Coastguard Worker 		if (n < 1) {
1073*1c60b9acSAndroid Build Coastguard Worker 			lwsl_err("%s: problem interpreting client cert\n",  __func__);
1074*1c60b9acSAndroid Build Coastguard Worker 			lws_tls_err_describe_clear();
1075*1c60b9acSAndroid Build Coastguard Worker 		}
1076*1c60b9acSAndroid Build Coastguard Worker 
1077*1c60b9acSAndroid Build Coastguard Worker 		lws_free_set_NULL(p);
1078*1c60b9acSAndroid Build Coastguard Worker 
1079*1c60b9acSAndroid Build Coastguard Worker 		if (n != 1)
1080*1c60b9acSAndroid Build Coastguard Worker 			return 1;
1081*1c60b9acSAndroid Build Coastguard Worker 
1082*1c60b9acSAndroid Build Coastguard Worker 	}
1083*1c60b9acSAndroid Build Coastguard Worker 	if (private_key_filepath) {
1084*1c60b9acSAndroid Build Coastguard Worker 		lwsl_info("%s: using private key filepath\n", __func__);
1085*1c60b9acSAndroid Build Coastguard Worker 		lws_ssl_bind_passphrase(vh->tls.ssl_client_ctx, 1, info);
1086*1c60b9acSAndroid Build Coastguard Worker 		/* set the private key from KeyFile */
1087*1c60b9acSAndroid Build Coastguard Worker 		if (SSL_CTX_use_PrivateKey_file(vh->tls.ssl_client_ctx,
1088*1c60b9acSAndroid Build Coastguard Worker 		    private_key_filepath, SSL_FILETYPE_PEM) != 1) {
1089*1c60b9acSAndroid Build Coastguard Worker 			lwsl_err("use_PrivateKey_file '%s'\n",
1090*1c60b9acSAndroid Build Coastguard Worker 				 private_key_filepath);
1091*1c60b9acSAndroid Build Coastguard Worker 			lws_tls_err_describe_clear();
1092*1c60b9acSAndroid Build Coastguard Worker 			return 1;
1093*1c60b9acSAndroid Build Coastguard Worker 		}
1094*1c60b9acSAndroid Build Coastguard Worker 		lwsl_info("Loaded client cert private key %s\n",
1095*1c60b9acSAndroid Build Coastguard Worker 			    private_key_filepath);
1096*1c60b9acSAndroid Build Coastguard Worker 
1097*1c60b9acSAndroid Build Coastguard Worker 		/* verify private key */
1098*1c60b9acSAndroid Build Coastguard Worker 		if (!SSL_CTX_check_private_key(vh->tls.ssl_client_ctx)) {
1099*1c60b9acSAndroid Build Coastguard Worker 			lwsl_err("Private SSL key doesn't match cert\n");
1100*1c60b9acSAndroid Build Coastguard Worker 			return 1;
1101*1c60b9acSAndroid Build Coastguard Worker 		}
1102*1c60b9acSAndroid Build Coastguard Worker 	}
1103*1c60b9acSAndroid Build Coastguard Worker 	else if (key_mem && key_mem_len) {
1104*1c60b9acSAndroid Build Coastguard Worker 
1105*1c60b9acSAndroid Build Coastguard Worker 		lws_filepos_t flen;
1106*1c60b9acSAndroid Build Coastguard Worker 		uint8_t *p;
1107*1c60b9acSAndroid Build Coastguard Worker 
1108*1c60b9acSAndroid Build Coastguard Worker 		if (lws_tls_alloc_pem_to_der_file(vh->context, NULL, key_mem,
1109*1c60b9acSAndroid Build Coastguard Worker 						  key_mem_len, &p, &flen)) {
1110*1c60b9acSAndroid Build Coastguard Worker 			lwsl_err("%s: couldn't use mem cert\n", __func__);
1111*1c60b9acSAndroid Build Coastguard Worker 
1112*1c60b9acSAndroid Build Coastguard Worker 			return 1;
1113*1c60b9acSAndroid Build Coastguard Worker 		}
1114*1c60b9acSAndroid Build Coastguard Worker 
1115*1c60b9acSAndroid Build Coastguard Worker 		n = SSL_CTX_use_PrivateKey_ASN1(EVP_PKEY_RSA, vh->tls.ssl_client_ctx, p,
1116*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_BORINGSSL)
1117*1c60b9acSAndroid Build Coastguard Worker 				(size_t)
1118*1c60b9acSAndroid Build Coastguard Worker #else
1119*1c60b9acSAndroid Build Coastguard Worker 				(long)(lws_intptr_t)
1120*1c60b9acSAndroid Build Coastguard Worker #endif
1121*1c60b9acSAndroid Build Coastguard Worker 						flen);
1122*1c60b9acSAndroid Build Coastguard Worker 		if (n != 1)
1123*1c60b9acSAndroid Build Coastguard Worker 			n = SSL_CTX_use_PrivateKey_ASN1(EVP_PKEY_EC,
1124*1c60b9acSAndroid Build Coastguard Worker 							vh->tls.ssl_client_ctx, p,
1125*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_BORINGSSL)
1126*1c60b9acSAndroid Build Coastguard Worker 				(size_t)
1127*1c60b9acSAndroid Build Coastguard Worker #else
1128*1c60b9acSAndroid Build Coastguard Worker 				(long)(lws_intptr_t)
1129*1c60b9acSAndroid Build Coastguard Worker #endif
1130*1c60b9acSAndroid Build Coastguard Worker 						flen);
1131*1c60b9acSAndroid Build Coastguard Worker 
1132*1c60b9acSAndroid Build Coastguard Worker 		lws_free_set_NULL(p);
1133*1c60b9acSAndroid Build Coastguard Worker 
1134*1c60b9acSAndroid Build Coastguard Worker 		if (n != 1)  {
1135*1c60b9acSAndroid Build Coastguard Worker 			lwsl_err("%s: unable to use key_mem\n", __func__);
1136*1c60b9acSAndroid Build Coastguard Worker 
1137*1c60b9acSAndroid Build Coastguard Worker 			return 1;
1138*1c60b9acSAndroid Build Coastguard Worker 		}
1139*1c60b9acSAndroid Build Coastguard Worker 	}
1140*1c60b9acSAndroid Build Coastguard Worker 
1141*1c60b9acSAndroid Build Coastguard Worker 	return 0;
1142*1c60b9acSAndroid Build Coastguard Worker }
1143*1c60b9acSAndroid Build Coastguard Worker 
1144*1c60b9acSAndroid Build Coastguard Worker 
1145