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