1 /***************************************************************************
2 * _ _ ____ _
3 * Project ___| | | | _ \| |
4 * / __| | | | |_) | |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
7 *
8 * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
9 *
10 * This software is licensed as described in the file COPYING, which
11 * you should have received as part of this distribution. The terms
12 * are also available at https://curl.se/docs/copyright.html.
13 *
14 * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15 * copies of the Software, and permit persons to whom the Software is
16 * furnished to do so, under the terms of the COPYING file.
17 *
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
20 *
21 * SPDX-License-Identifier: curl
22 *
23 ***************************************************************************/
24
25 /*
26 * Source file for all wolfSSL specific code for the TLS/SSL layer. No code
27 * but vtls.c should ever call or use these functions.
28 *
29 */
30
31 #include "curl_setup.h"
32
33 #ifdef USE_WOLFSSL
34
35 #define WOLFSSL_OPTIONS_IGNORE_SYS
36 #include <wolfssl/options.h>
37 #include <wolfssl/version.h>
38
39 #if LIBWOLFSSL_VERSION_HEX < 0x03004006 /* wolfSSL 3.4.6 (2015) */
40 #error "wolfSSL version should be at least 3.4.6"
41 #endif
42
43 /* To determine what functions are available we rely on one or both of:
44 - the user's options.h generated by wolfSSL
45 - the symbols detected by curl's configure
46 Since they are markedly different from one another, and one or the other may
47 not be available, we do some checking below to bring things in sync. */
48
49 /* HAVE_ALPN is wolfSSL's build time symbol for enabling ALPN in options.h. */
50 #ifndef HAVE_ALPN
51 #ifdef HAVE_WOLFSSL_USEALPN
52 #define HAVE_ALPN
53 #endif
54 #endif
55
56 #include <limits.h>
57
58 #include "urldata.h"
59 #include "sendf.h"
60 #include "inet_pton.h"
61 #include "vtls.h"
62 #include "vtls_int.h"
63 #include "vtls_scache.h"
64 #include "keylog.h"
65 #include "parsedate.h"
66 #include "connect.h" /* for the connect timeout */
67 #include "select.h"
68 #include "strcase.h"
69 #include "x509asn1.h"
70 #include "curl_printf.h"
71 #include "multiif.h"
72
73 #include <wolfssl/ssl.h>
74 #include <wolfssl/error-ssl.h>
75 #include "wolfssl.h"
76
77 /* The last #include files should be: */
78 #include "curl_memory.h"
79 #include "memdebug.h"
80
81 #ifdef HAVE_WOLFSSL_CTX_GENERATEECHCONFIG
82 #define USE_ECH_WOLFSSL
83 #endif
84
85 /* KEEP_PEER_CERT is a product of the presence of build time symbol
86 OPENSSL_EXTRA without NO_CERTS, depending on the version. KEEP_PEER_CERT is
87 in wolfSSL's settings.h, and the latter two are build time symbols in
88 options.h. */
89 #ifndef KEEP_PEER_CERT
90 #if defined(HAVE_WOLFSSL_GET_PEER_CERTIFICATE) || \
91 (defined(OPENSSL_EXTRA) && !defined(NO_CERTS))
92 #define KEEP_PEER_CERT
93 #endif
94 #endif
95
96 #ifdef HAVE_WOLFSSL_BIO
97 #define USE_BIO_CHAIN
98 #ifdef HAVE_WOLFSSL_FULL_BIO
99 #define USE_FULL_BIO
100 #else /* HAVE_WOLFSSL_FULL_BIO */
101 #undef USE_FULL_BIO
102 #endif
103 /* wolfSSL 5.7.4 and older do not have these symbols, but only the
104 * OpenSSL ones. */
105 #ifndef WOLFSSL_BIO_CTRL_GET_CLOSE
106 #define WOLFSSL_BIO_CTRL_GET_CLOSE BIO_CTRL_GET_CLOSE
107 #define WOLFSSL_BIO_CTRL_SET_CLOSE BIO_CTRL_SET_CLOSE
108 #define WOLFSSL_BIO_CTRL_FLUSH BIO_CTRL_FLUSH
109 #define WOLFSSL_BIO_CTRL_DUP BIO_CTRL_DUP
110 #define wolfSSL_BIO_set_retry_write BIO_set_retry_write
111 #define wolfSSL_BIO_set_retry_read BIO_set_retry_read
112 #endif /* !WOLFSSL_BIO_CTRL_GET_CLOSE */
113
114 #else /* HAVE_WOLFSSL_BIO */
115 #undef USE_BIO_CHAIN
116 #endif
117
118 #ifdef OPENSSL_EXTRA
119 /*
120 * Availability note:
121 * The TLS 1.3 secret callback (wolfSSL_set_tls13_secret_cb) was added in
122 * wolfSSL 4.4.0, but requires the -DHAVE_SECRET_CALLBACK build option. If that
123 * option is not set, then TLS 1.3 will not be logged.
124 * For TLS 1.2 and before, we use wolfSSL_get_keys().
125 * SSL_get_client_random and wolfSSL_get_keys require OPENSSL_EXTRA
126 * (--enable-opensslextra or --enable-all).
127 */
128 #if defined(HAVE_SECRET_CALLBACK) && defined(WOLFSSL_TLS13)
129 static int
wolfssl_tls13_secret_callback(SSL * ssl,int id,const unsigned char * secret,int secretSz,void * ctx)130 wolfssl_tls13_secret_callback(SSL *ssl, int id, const unsigned char *secret,
131 int secretSz, void *ctx)
132 {
133 const char *label;
134 unsigned char client_random[SSL3_RANDOM_SIZE];
135 (void)ctx;
136
137 if(!ssl || !Curl_tls_keylog_enabled()) {
138 return 0;
139 }
140
141 switch(id) {
142 case CLIENT_EARLY_TRAFFIC_SECRET:
143 label = "CLIENT_EARLY_TRAFFIC_SECRET";
144 break;
145 case CLIENT_HANDSHAKE_TRAFFIC_SECRET:
146 label = "CLIENT_HANDSHAKE_TRAFFIC_SECRET";
147 break;
148 case SERVER_HANDSHAKE_TRAFFIC_SECRET:
149 label = "SERVER_HANDSHAKE_TRAFFIC_SECRET";
150 break;
151 case CLIENT_TRAFFIC_SECRET:
152 label = "CLIENT_TRAFFIC_SECRET_0";
153 break;
154 case SERVER_TRAFFIC_SECRET:
155 label = "SERVER_TRAFFIC_SECRET_0";
156 break;
157 case EARLY_EXPORTER_SECRET:
158 label = "EARLY_EXPORTER_SECRET";
159 break;
160 case EXPORTER_SECRET:
161 label = "EXPORTER_SECRET";
162 break;
163 default:
164 return 0;
165 }
166
167 if(SSL_get_client_random(ssl, client_random, SSL3_RANDOM_SIZE) == 0) {
168 /* Should never happen as wolfSSL_KeepArrays() was called before. */
169 return 0;
170 }
171
172 Curl_tls_keylog_write(label, client_random, secret, secretSz);
173 return 0;
174 }
175 #endif /* defined(HAVE_SECRET_CALLBACK) && defined(WOLFSSL_TLS13) */
176
177 static void
wolfssl_log_tls12_secret(WOLFSSL * ssl)178 wolfssl_log_tls12_secret(WOLFSSL *ssl)
179 {
180 unsigned char *ms, *sr, *cr;
181 unsigned int msLen, srLen, crLen, i, x = 0;
182
183 #if LIBWOLFSSL_VERSION_HEX >= 0x0300d000 /* >= 3.13.0 */
184 /* wolfSSL_GetVersion is available since 3.13, we use it instead of
185 * SSL_version since the latter relies on OPENSSL_ALL (--enable-opensslall or
186 * --enable-all). Failing to perform this check could result in an unusable
187 * key log line when TLS 1.3 is actually negotiated. */
188 switch(wolfSSL_GetVersion(ssl)) {
189 case WOLFSSL_SSLV3:
190 case WOLFSSL_TLSV1:
191 case WOLFSSL_TLSV1_1:
192 case WOLFSSL_TLSV1_2:
193 break;
194 default:
195 /* TLS 1.3 does not use this mechanism, the "master secret" returned below
196 * is not directly usable. */
197 return;
198 }
199 #endif
200
201 if(wolfSSL_get_keys(ssl, &ms, &msLen, &sr, &srLen, &cr, &crLen) !=
202 WOLFSSL_SUCCESS) {
203 return;
204 }
205
206 /* Check for a missing master secret and skip logging. That can happen if
207 * curl rejects the server certificate and aborts the handshake.
208 */
209 for(i = 0; i < msLen; i++) {
210 x |= ms[i];
211 }
212 if(x == 0) {
213 return;
214 }
215
216 Curl_tls_keylog_write("CLIENT_RANDOM", cr, ms, msLen);
217 }
218 #endif /* OPENSSL_EXTRA */
219
wolfssl_do_file_type(const char * type)220 static int wolfssl_do_file_type(const char *type)
221 {
222 if(!type || !type[0])
223 return WOLFSSL_FILETYPE_PEM;
224 if(strcasecompare(type, "PEM"))
225 return WOLFSSL_FILETYPE_PEM;
226 if(strcasecompare(type, "DER"))
227 return WOLFSSL_FILETYPE_ASN1;
228 return -1;
229 }
230
231 #ifdef WOLFSSL_HAVE_KYBER
232 struct group_name_map {
233 const word16 group;
234 const char *name;
235 };
236
237 static const struct group_name_map gnm[] = {
238 { WOLFSSL_KYBER_LEVEL1, "KYBER_LEVEL1" },
239 { WOLFSSL_KYBER_LEVEL3, "KYBER_LEVEL3" },
240 { WOLFSSL_KYBER_LEVEL5, "KYBER_LEVEL5" },
241 { WOLFSSL_P256_KYBER_LEVEL1, "P256_KYBER_LEVEL1" },
242 { WOLFSSL_P384_KYBER_LEVEL3, "P384_KYBER_LEVEL3" },
243 { WOLFSSL_P521_KYBER_LEVEL5, "P521_KYBER_LEVEL5" },
244 { 0, NULL }
245 };
246 #endif
247
248 #ifdef USE_BIO_CHAIN
249
wolfssl_bio_cf_create(WOLFSSL_BIO * bio)250 static int wolfssl_bio_cf_create(WOLFSSL_BIO *bio)
251 {
252 #ifdef USE_FULL_BIO
253 wolfSSL_BIO_set_shutdown(bio, 1);
254 #endif
255 wolfSSL_BIO_set_data(bio, NULL);
256 return 1;
257 }
258
wolfssl_bio_cf_destroy(WOLFSSL_BIO * bio)259 static int wolfssl_bio_cf_destroy(WOLFSSL_BIO *bio)
260 {
261 if(!bio)
262 return 0;
263 return 1;
264 }
265
wolfssl_bio_cf_ctrl(WOLFSSL_BIO * bio,int cmd,long num,void * ptr)266 static long wolfssl_bio_cf_ctrl(WOLFSSL_BIO *bio, int cmd, long num, void *ptr)
267 {
268 struct Curl_cfilter *cf = wolfSSL_BIO_get_data(bio);
269 long ret = 1;
270
271 (void)cf;
272 (void)ptr;
273 (void)num;
274 switch(cmd) {
275 case WOLFSSL_BIO_CTRL_GET_CLOSE:
276 #ifdef USE_FULL_BIO
277 ret = (long)wolfSSL_BIO_get_shutdown(bio);
278 #else
279 ret = 0;
280 #endif
281 break;
282 case WOLFSSL_BIO_CTRL_SET_CLOSE:
283 #ifdef USE_FULL_BIO
284 wolfSSL_BIO_set_shutdown(bio, (int)num);
285 #endif
286 break;
287 case WOLFSSL_BIO_CTRL_FLUSH:
288 /* we do no delayed writes, but if we ever would, this
289 * needs to trigger it. */
290 ret = 1;
291 break;
292 case WOLFSSL_BIO_CTRL_DUP:
293 ret = 1;
294 break;
295 #ifdef WOLFSSL_BIO_CTRL_EOF
296 case WOLFSSL_BIO_CTRL_EOF:
297 /* EOF has been reached on input? */
298 return !cf->next || !cf->next->connected;
299 #endif
300 default:
301 ret = 0;
302 break;
303 }
304 return ret;
305 }
306
wolfssl_bio_cf_out_write(WOLFSSL_BIO * bio,const char * buf,int blen)307 static int wolfssl_bio_cf_out_write(WOLFSSL_BIO *bio,
308 const char *buf, int blen)
309 {
310 struct Curl_cfilter *cf = wolfSSL_BIO_get_data(bio);
311 struct ssl_connect_data *connssl = cf->ctx;
312 struct wolfssl_ctx *backend =
313 (struct wolfssl_ctx *)connssl->backend;
314 struct Curl_easy *data = CF_DATA_CURRENT(cf);
315 ssize_t nwritten, skiplen = 0;
316 CURLcode result = CURLE_OK;
317
318 DEBUGASSERT(data);
319 if(backend->shutting_down && backend->io_send_blocked_len &&
320 (backend->io_send_blocked_len < blen)) {
321 /* bug in wolfSSL: <https://github.com/wolfSSL/wolfssl/issues/7784>
322 * It adds the close notify message again every time we retry
323 * sending during shutdown. */
324 CURL_TRC_CF(data, cf, "bio_write, shutdown restrict send of %d"
325 " to %d bytes", blen, backend->io_send_blocked_len);
326 skiplen = (ssize_t)(blen - backend->io_send_blocked_len);
327 blen = backend->io_send_blocked_len;
328 }
329 nwritten = Curl_conn_cf_send(cf->next, data, buf, blen, FALSE, &result);
330 backend->io_result = result;
331 CURL_TRC_CF(data, cf, "bio_write(len=%d) -> %zd, %d",
332 blen, nwritten, result);
333 #ifdef USE_FULL_BIO
334 wolfSSL_BIO_clear_retry_flags(bio);
335 #endif
336 if(nwritten < 0 && CURLE_AGAIN == result) {
337 wolfSSL_BIO_set_retry_write(bio);
338 if(backend->shutting_down && !backend->io_send_blocked_len)
339 backend->io_send_blocked_len = blen;
340 }
341 else if(!result && skiplen)
342 nwritten += skiplen;
343 return (int)nwritten;
344 }
345
wolfssl_bio_cf_in_read(WOLFSSL_BIO * bio,char * buf,int blen)346 static int wolfssl_bio_cf_in_read(WOLFSSL_BIO *bio, char *buf, int blen)
347 {
348 struct Curl_cfilter *cf = wolfSSL_BIO_get_data(bio);
349 struct ssl_connect_data *connssl = cf->ctx;
350 struct wolfssl_ctx *backend =
351 (struct wolfssl_ctx *)connssl->backend;
352 struct Curl_easy *data = CF_DATA_CURRENT(cf);
353 ssize_t nread;
354 CURLcode result = CURLE_OK;
355
356 DEBUGASSERT(data);
357 /* OpenSSL catches this case, so should we. */
358 if(!buf)
359 return 0;
360
361 nread = Curl_conn_cf_recv(cf->next, data, buf, blen, &result);
362 backend->io_result = result;
363 CURL_TRC_CF(data, cf, "bio_read(len=%d) -> %zd, %d", blen, nread, result);
364 #ifdef USE_FULL_BIO
365 wolfSSL_BIO_clear_retry_flags(bio);
366 #endif
367 if(nread < 0 && CURLE_AGAIN == result)
368 wolfSSL_BIO_set_retry_read(bio);
369 else if(nread == 0)
370 connssl->peer_closed = TRUE;
371 return (int)nread;
372 }
373
374 static WOLFSSL_BIO_METHOD *wolfssl_bio_cf_method = NULL;
375
wolfssl_bio_cf_init_methods(void)376 static void wolfssl_bio_cf_init_methods(void)
377 {
378 wolfssl_bio_cf_method = wolfSSL_BIO_meth_new(WOLFSSL_BIO_MEMORY,
379 "wolfSSL CF BIO");
380 wolfSSL_BIO_meth_set_write(wolfssl_bio_cf_method, &wolfssl_bio_cf_out_write);
381 wolfSSL_BIO_meth_set_read(wolfssl_bio_cf_method, &wolfssl_bio_cf_in_read);
382 wolfSSL_BIO_meth_set_ctrl(wolfssl_bio_cf_method, &wolfssl_bio_cf_ctrl);
383 wolfSSL_BIO_meth_set_create(wolfssl_bio_cf_method, &wolfssl_bio_cf_create);
384 wolfSSL_BIO_meth_set_destroy(wolfssl_bio_cf_method, &wolfssl_bio_cf_destroy);
385 }
386
wolfssl_bio_cf_free_methods(void)387 static void wolfssl_bio_cf_free_methods(void)
388 {
389 wolfSSL_BIO_meth_free(wolfssl_bio_cf_method);
390 }
391
392 #else /* USE_BIO_CHAIN */
393
394 #define wolfssl_bio_cf_init_methods() Curl_nop_stmt
395 #define wolfssl_bio_cf_free_methods() Curl_nop_stmt
396
397 #endif /* !USE_BIO_CHAIN */
398
Curl_wssl_cache_session(struct Curl_cfilter * cf,struct Curl_easy * data,const char * ssl_peer_key,WOLFSSL_SESSION * session,int ietf_tls_id,const char * alpn)399 CURLcode Curl_wssl_cache_session(struct Curl_cfilter *cf,
400 struct Curl_easy *data,
401 const char *ssl_peer_key,
402 WOLFSSL_SESSION *session,
403 int ietf_tls_id,
404 const char *alpn)
405 {
406 CURLcode result = CURLE_OK;
407 struct Curl_ssl_session *sc_session = NULL;
408 unsigned char *sdata = NULL;
409 unsigned int sdata_len;
410
411 if(!session)
412 goto out;
413
414 sdata_len = wolfSSL_i2d_SSL_SESSION(session, NULL);
415 if(sdata_len <= 0) {
416 CURL_TRC_CF(data, cf, "fail to assess session length: %u", sdata_len);
417 result = CURLE_FAILED_INIT;
418 goto out;
419 }
420 sdata = calloc(1, sdata_len);
421 if(!sdata) {
422 failf(data, "unable to allocate session buffer of %u bytes", sdata_len);
423 result = CURLE_OUT_OF_MEMORY;
424 goto out;
425 }
426 sdata_len = wolfSSL_i2d_SSL_SESSION(session, &sdata);
427 if(sdata_len <= 0) {
428 CURL_TRC_CF(data, cf, "fail to serialize session: %u", sdata_len);
429 result = CURLE_FAILED_INIT;
430 goto out;
431 }
432
433 result = Curl_ssl_session_create(sdata, sdata_len,
434 ietf_tls_id, alpn,
435 (curl_off_t)time(NULL) +
436 wolfSSL_SESSION_get_timeout(session), 0,
437 &sc_session);
438 sdata = NULL; /* took ownership of sdata */
439 if(!result) {
440 result = Curl_ssl_scache_put(cf, data, ssl_peer_key, sc_session);
441 /* took ownership of `sc_session` */
442 }
443
444 out:
445 free(sdata);
446 return result;
447 }
448
wssl_vtls_new_session_cb(WOLFSSL * ssl,WOLFSSL_SESSION * session)449 static int wssl_vtls_new_session_cb(WOLFSSL *ssl, WOLFSSL_SESSION *session)
450 {
451 struct Curl_cfilter *cf;
452
453 cf = (struct Curl_cfilter*)wolfSSL_get_app_data(ssl);
454 DEBUGASSERT(cf != NULL);
455 if(cf && session) {
456 struct ssl_connect_data *connssl = cf->ctx;
457 struct Curl_easy *data = CF_DATA_CURRENT(cf);
458 DEBUGASSERT(connssl);
459 DEBUGASSERT(data);
460 if(connssl && data) {
461 (void)Curl_wssl_cache_session(cf, data, connssl->peer.scache_key,
462 session, wolfSSL_version(ssl),
463 connssl->negotiated.alpn);
464 }
465 }
466 return 0;
467 }
468
Curl_wssl_setup_session(struct Curl_cfilter * cf,struct Curl_easy * data,struct wolfssl_ctx * wss,const char * ssl_peer_key)469 CURLcode Curl_wssl_setup_session(struct Curl_cfilter *cf,
470 struct Curl_easy *data,
471 struct wolfssl_ctx *wss,
472 const char *ssl_peer_key)
473 {
474 struct Curl_ssl_session *sc_session = NULL;
475 CURLcode result;
476
477 result = Curl_ssl_scache_take(cf, data, ssl_peer_key, &sc_session);
478 if(!result && sc_session && sc_session->sdata && sc_session->sdata_len) {
479 WOLFSSL_SESSION *session;
480 /* wolfSSL changes the passed pointer for whatever reasons, yikes */
481 const unsigned char *sdata = sc_session->sdata;
482 session = wolfSSL_d2i_SSL_SESSION(NULL, &sdata,
483 (long)sc_session->sdata_len);
484 if(session) {
485 int ret = wolfSSL_set_session(wss->handle, session);
486 if(ret != WOLFSSL_SUCCESS) {
487 Curl_ssl_session_destroy(sc_session);
488 sc_session = NULL;
489 infof(data, "cached session not accepted (%d), "
490 "removing from cache", ret);
491 }
492 else
493 infof(data, "SSL reusing session ID");
494 wolfSSL_SESSION_free(session);
495 }
496 else {
497 failf(data, "could not decode previous session");
498 }
499 }
500 Curl_ssl_scache_return(cf, data, ssl_peer_key, sc_session);
501 return result;
502 }
503
wssl_populate_x509_store(struct Curl_cfilter * cf,struct Curl_easy * data,WOLFSSL_X509_STORE * store,struct wolfssl_ctx * wssl)504 static CURLcode wssl_populate_x509_store(struct Curl_cfilter *cf,
505 struct Curl_easy *data,
506 WOLFSSL_X509_STORE *store,
507 struct wolfssl_ctx *wssl)
508 {
509 struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
510 const struct curl_blob *ca_info_blob = conn_config->ca_info_blob;
511 const char * const ssl_cafile =
512 /* CURLOPT_CAINFO_BLOB overrides CURLOPT_CAINFO */
513 (ca_info_blob ? NULL : conn_config->CAfile);
514 const char * const ssl_capath = conn_config->CApath;
515 struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
516 bool imported_native_ca = FALSE;
517
518 #if !defined(NO_FILESYSTEM) && defined(WOLFSSL_SYS_CA_CERTS)
519 /* load native CA certificates */
520 if(ssl_config->native_ca_store) {
521 if(wolfSSL_CTX_load_system_CA_certs(wssl->ctx) != WOLFSSL_SUCCESS) {
522 infof(data, "error importing native CA store, continuing anyway");
523 }
524 else {
525 imported_native_ca = TRUE;
526 infof(data, "successfully imported native CA store");
527 wssl->x509_store_setup = TRUE;
528 }
529 }
530 #endif /* !NO_FILESYSTEM */
531
532 /* load certificate blob */
533 if(ca_info_blob) {
534 if(wolfSSL_CTX_load_verify_buffer(wssl->ctx, ca_info_blob->data,
535 (long)ca_info_blob->len,
536 WOLFSSL_FILETYPE_PEM) !=
537 WOLFSSL_SUCCESS) {
538 if(imported_native_ca) {
539 infof(data, "error importing CA certificate blob, continuing anyway");
540 }
541 else {
542 failf(data, "error importing CA certificate blob");
543 return CURLE_SSL_CACERT_BADFILE;
544 }
545 }
546 else {
547 infof(data, "successfully imported CA certificate blob");
548 wssl->x509_store_setup = TRUE;
549 }
550 }
551
552 #ifndef NO_FILESYSTEM
553 /* load trusted cacert from file if not blob */
554
555 CURL_TRC_CF(data, cf, "wssl_populate_x509_store, path=%s, blob=%d",
556 ssl_cafile ? ssl_cafile : "none", !!ca_info_blob);
557 if(!store)
558 return CURLE_OUT_OF_MEMORY;
559
560 if((ssl_cafile || ssl_capath) && (!wssl->x509_store_setup)) {
561 int rc =
562 wolfSSL_CTX_load_verify_locations_ex(wssl->ctx,
563 ssl_cafile,
564 ssl_capath,
565 WOLFSSL_LOAD_FLAG_IGNORE_ERR);
566 if(WOLFSSL_SUCCESS != rc) {
567 if(conn_config->verifypeer) {
568 /* Fail if we insist on successfully verifying the server. */
569 failf(data, "error setting certificate verify locations:"
570 " CAfile: %s CApath: %s",
571 ssl_cafile ? ssl_cafile : "none",
572 ssl_capath ? ssl_capath : "none");
573 return CURLE_SSL_CACERT_BADFILE;
574 }
575 else {
576 /* Just continue with a warning if no strict certificate
577 verification is required. */
578 infof(data, "error setting certificate verify locations,"
579 " continuing anyway:");
580 }
581 }
582 else {
583 /* Everything is fine. */
584 infof(data, "successfully set certificate verify locations:");
585 }
586 infof(data, " CAfile: %s", ssl_cafile ? ssl_cafile : "none");
587 infof(data, " CApath: %s", ssl_capath ? ssl_capath : "none");
588 }
589 #endif
590 (void)store;
591 wssl->x509_store_setup = TRUE;
592 return CURLE_OK;
593 }
594
595 /* key to use at `multi->proto_hash` */
596 #define MPROTO_WSSL_X509_KEY "tls:wssl:x509:share"
597
598 struct wssl_x509_share {
599 char *CAfile; /* CAfile path used to generate X509 store */
600 WOLFSSL_X509_STORE *store; /* cached X509 store or NULL if none */
601 struct curltime time; /* when the cached store was created */
602 };
603
wssl_x509_share_free(void * key,size_t key_len,void * p)604 static void wssl_x509_share_free(void *key, size_t key_len, void *p)
605 {
606 struct wssl_x509_share *share = p;
607 DEBUGASSERT(key_len == (sizeof(MPROTO_WSSL_X509_KEY)-1));
608 DEBUGASSERT(!memcmp(MPROTO_WSSL_X509_KEY, key, key_len));
609 (void)key;
610 (void)key_len;
611 if(share->store) {
612 wolfSSL_X509_STORE_free(share->store);
613 }
614 free(share->CAfile);
615 free(share);
616 }
617
618 static bool
wssl_cached_x509_store_expired(const struct Curl_easy * data,const struct wssl_x509_share * mb)619 wssl_cached_x509_store_expired(const struct Curl_easy *data,
620 const struct wssl_x509_share *mb)
621 {
622 const struct ssl_general_config *cfg = &data->set.general_ssl;
623 struct curltime now = Curl_now();
624 timediff_t elapsed_ms = Curl_timediff(now, mb->time);
625 timediff_t timeout_ms = cfg->ca_cache_timeout * (timediff_t)1000;
626
627 if(timeout_ms < 0)
628 return FALSE;
629
630 return elapsed_ms >= timeout_ms;
631 }
632
633 static bool
wssl_cached_x509_store_different(struct Curl_cfilter * cf,const struct wssl_x509_share * mb)634 wssl_cached_x509_store_different(struct Curl_cfilter *cf,
635 const struct wssl_x509_share *mb)
636 {
637 struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
638 if(!mb->CAfile || !conn_config->CAfile)
639 return mb->CAfile != conn_config->CAfile;
640
641 return strcmp(mb->CAfile, conn_config->CAfile);
642 }
643
wssl_get_cached_x509_store(struct Curl_cfilter * cf,const struct Curl_easy * data)644 static WOLFSSL_X509_STORE *wssl_get_cached_x509_store(struct Curl_cfilter *cf,
645 const struct Curl_easy *data)
646 {
647 struct Curl_multi *multi = data->multi;
648 struct wssl_x509_share *share;
649 WOLFSSL_X509_STORE *store = NULL;
650
651 DEBUGASSERT(multi);
652 share = multi ? Curl_hash_pick(&multi->proto_hash,
653 (void *)MPROTO_WSSL_X509_KEY,
654 sizeof(MPROTO_WSSL_X509_KEY)-1) : NULL;
655 if(share && share->store &&
656 !wssl_cached_x509_store_expired(data, share) &&
657 !wssl_cached_x509_store_different(cf, share)) {
658 store = share->store;
659 }
660
661 return store;
662 }
663
wssl_set_cached_x509_store(struct Curl_cfilter * cf,const struct Curl_easy * data,WOLFSSL_X509_STORE * store)664 static void wssl_set_cached_x509_store(struct Curl_cfilter *cf,
665 const struct Curl_easy *data,
666 WOLFSSL_X509_STORE *store)
667 {
668 struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
669 struct Curl_multi *multi = data->multi;
670 struct wssl_x509_share *share;
671
672 DEBUGASSERT(multi);
673 if(!multi)
674 return;
675 share = Curl_hash_pick(&multi->proto_hash,
676 (void *)MPROTO_WSSL_X509_KEY,
677 sizeof(MPROTO_WSSL_X509_KEY)-1);
678
679 if(!share) {
680 share = calloc(1, sizeof(*share));
681 if(!share)
682 return;
683 if(!Curl_hash_add2(&multi->proto_hash,
684 (void *)MPROTO_WSSL_X509_KEY,
685 sizeof(MPROTO_WSSL_X509_KEY)-1,
686 share, wssl_x509_share_free)) {
687 free(share);
688 return;
689 }
690 }
691
692 if(wolfSSL_X509_STORE_up_ref(store)) {
693 char *CAfile = NULL;
694
695 if(conn_config->CAfile) {
696 CAfile = strdup(conn_config->CAfile);
697 if(!CAfile) {
698 wolfSSL_X509_STORE_free(store);
699 return;
700 }
701 }
702
703 if(share->store) {
704 wolfSSL_X509_STORE_free(share->store);
705 free(share->CAfile);
706 }
707
708 share->time = Curl_now();
709 share->store = store;
710 share->CAfile = CAfile;
711 }
712 }
713
Curl_wssl_setup_x509_store(struct Curl_cfilter * cf,struct Curl_easy * data,struct wolfssl_ctx * wssl)714 CURLcode Curl_wssl_setup_x509_store(struct Curl_cfilter *cf,
715 struct Curl_easy *data,
716 struct wolfssl_ctx *wssl)
717 {
718 struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
719 struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
720 CURLcode result = CURLE_OK;
721 WOLFSSL_X509_STORE *cached_store;
722 bool cache_criteria_met;
723
724 /* Consider the X509 store cacheable if it comes exclusively from a CAfile,
725 or no source is provided and we are falling back to wolfSSL's built-in
726 default. */
727 cache_criteria_met = (data->set.general_ssl.ca_cache_timeout != 0) &&
728 conn_config->verifypeer &&
729 !conn_config->CApath &&
730 !conn_config->ca_info_blob &&
731 !ssl_config->primary.CRLfile &&
732 !ssl_config->native_ca_store;
733
734 cached_store = cache_criteria_met ? wssl_get_cached_x509_store(cf, data)
735 : NULL;
736 if(cached_store && wolfSSL_CTX_get_cert_store(wssl->ctx) == cached_store) {
737 /* The cached store is already in use, do nothing. */
738 }
739 else if(cached_store && wolfSSL_X509_STORE_up_ref(cached_store)) {
740 wolfSSL_CTX_set_cert_store(wssl->ctx, cached_store);
741 }
742 else if(cache_criteria_met) {
743 /* wolfSSL's initial store in CTX is not shareable by default.
744 * Make a new one, suitable for adding to the cache. See #14278 */
745 WOLFSSL_X509_STORE *store = wolfSSL_X509_STORE_new();
746 if(!store) {
747 failf(data, "SSL: could not create a X509 store");
748 return CURLE_OUT_OF_MEMORY;
749 }
750 wolfSSL_CTX_set_cert_store(wssl->ctx, store);
751
752 result = wssl_populate_x509_store(cf, data, store, wssl);
753 if(!result) {
754 wssl_set_cached_x509_store(cf, data, store);
755 }
756 }
757 else {
758 /* We never share the CTX's store, use it. */
759 WOLFSSL_X509_STORE *store = wolfSSL_CTX_get_cert_store(wssl->ctx);
760 result = wssl_populate_x509_store(cf, data, store, wssl);
761 }
762
763 return result;
764 }
765
766 #ifdef WOLFSSL_TLS13
767 static CURLcode
wssl_add_default_ciphers(bool tls13,struct dynbuf * buf)768 wssl_add_default_ciphers(bool tls13, struct dynbuf *buf)
769 {
770 int i;
771 char *str;
772
773 for(i = 0; (str = wolfSSL_get_cipher_list(i)); i++) {
774 size_t n;
775 if((strncmp(str, "TLS13", 5) == 0) != tls13)
776 continue;
777
778 /* if there already is data in the string, add colon separator */
779 if(Curl_dyn_len(buf)) {
780 CURLcode result = Curl_dyn_addn(buf, ":", 1);
781 if(result)
782 return result;
783 }
784
785 n = strlen(str);
786 if(Curl_dyn_addn(buf, str, n))
787 return CURLE_OUT_OF_MEMORY;
788 }
789
790 return CURLE_OK;
791 }
792 #endif
793
794 /* 4.2.0 (2019) */
795 #if LIBWOLFSSL_VERSION_HEX < 0x04002000 || !defined(OPENSSL_EXTRA)
796 static int
wssl_legacy_CTX_set_min_proto_version(WOLFSSL_CTX * ctx,int version)797 wssl_legacy_CTX_set_min_proto_version(WOLFSSL_CTX* ctx, int version)
798 {
799 int res;
800 switch(version) {
801 default:
802 case TLS1_VERSION:
803 res = wolfSSL_CTX_SetMinVersion(ctx, WOLFSSL_TLSV1);
804 if(res == WOLFSSL_SUCCESS)
805 return res;
806 FALLTHROUGH();
807 case TLS1_1_VERSION:
808 res = wolfSSL_CTX_SetMinVersion(ctx, WOLFSSL_TLSV1_1);
809 if(res == WOLFSSL_SUCCESS)
810 return res;
811 FALLTHROUGH();
812 case TLS1_2_VERSION:
813 res = wolfSSL_CTX_SetMinVersion(ctx, WOLFSSL_TLSV1_2);
814 #ifdef WOLFSSL_TLS13
815 if(res == WOLFSSL_SUCCESS)
816 return res;
817 FALLTHROUGH();
818 case TLS1_3_VERSION:
819 res = wolfSSL_CTX_SetMinVersion(ctx, WOLFSSL_TLSV1_3);
820 #endif
821 }
822 return res;
823 }
824 static int
wssl_legacy_CTX_set_max_proto_version(WOLFSSL_CTX * ctx,int version)825 wssl_legacy_CTX_set_max_proto_version(WOLFSSL_CTX* ctx, int version)
826 {
827 (void) ctx, (void) version;
828 return WOLFSSL_NOT_IMPLEMENTED;
829 }
830 #define wolfSSL_CTX_set_min_proto_version wssl_legacy_CTX_set_min_proto_version
831 #define wolfSSL_CTX_set_max_proto_version wssl_legacy_CTX_set_max_proto_version
832 #endif
833
834 /*
835 * This function loads all the client/CA certificates and CRLs. Setup the TLS
836 * layer and do all necessary magic.
837 */
838 static CURLcode
wolfssl_connect_step1(struct Curl_cfilter * cf,struct Curl_easy * data)839 wolfssl_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
840 {
841 int res;
842 char *curves;
843 struct ssl_connect_data *connssl = cf->ctx;
844 struct wolfssl_ctx *backend =
845 (struct wolfssl_ctx *)connssl->backend;
846 struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
847 const struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
848 WOLFSSL_METHOD* req_method = NULL;
849 #ifdef WOLFSSL_HAVE_KYBER
850 word16 pqkem = 0;
851 size_t idx = 0;
852 #endif
853
854 DEBUGASSERT(backend);
855
856 if(connssl->state == ssl_connection_complete)
857 return CURLE_OK;
858
859 #if LIBWOLFSSL_VERSION_HEX < 0x04002000 /* 4.2.0 (2019) */
860 req_method = wolfSSLv23_client_method();
861 #else
862 req_method = wolfTLS_client_method();
863 #endif
864 if(!req_method) {
865 failf(data, "wolfSSL: could not create a client method");
866 return CURLE_OUT_OF_MEMORY;
867 }
868
869 if(backend->ctx)
870 wolfSSL_CTX_free(backend->ctx);
871
872 backend->ctx = wolfSSL_CTX_new(req_method);
873 if(!backend->ctx) {
874 failf(data, "wolfSSL: could not create a context");
875 return CURLE_OUT_OF_MEMORY;
876 }
877
878 switch(conn_config->version) {
879 case CURL_SSLVERSION_DEFAULT:
880 case CURL_SSLVERSION_TLSv1:
881 case CURL_SSLVERSION_TLSv1_0:
882 res = wolfSSL_CTX_set_min_proto_version(backend->ctx, TLS1_VERSION);
883 break;
884 case CURL_SSLVERSION_TLSv1_1:
885 res = wolfSSL_CTX_set_min_proto_version(backend->ctx, TLS1_1_VERSION);
886 break;
887 case CURL_SSLVERSION_TLSv1_2:
888 res = wolfSSL_CTX_set_min_proto_version(backend->ctx, TLS1_2_VERSION);
889 break;
890 #ifdef WOLFSSL_TLS13
891 case CURL_SSLVERSION_TLSv1_3:
892 res = wolfSSL_CTX_set_min_proto_version(backend->ctx, TLS1_3_VERSION);
893 break;
894 #endif
895 default:
896 failf(data, "wolfSSL: unsupported minimum TLS version value");
897 return CURLE_SSL_CONNECT_ERROR;
898 }
899 if(res != WOLFSSL_SUCCESS) {
900 failf(data, "wolfSSL: failed set the minimum TLS version");
901 return CURLE_SSL_CONNECT_ERROR;
902 }
903
904 switch(conn_config->version_max) {
905 #ifdef WOLFSSL_TLS13
906 case CURL_SSLVERSION_MAX_TLSv1_3:
907 res = wolfSSL_CTX_set_max_proto_version(backend->ctx, TLS1_3_VERSION);
908 break;
909 #endif
910 case CURL_SSLVERSION_MAX_TLSv1_2:
911 res = wolfSSL_CTX_set_max_proto_version(backend->ctx, TLS1_2_VERSION);
912 break;
913 case CURL_SSLVERSION_MAX_TLSv1_1:
914 res = wolfSSL_CTX_set_max_proto_version(backend->ctx, TLS1_1_VERSION);
915 break;
916 case CURL_SSLVERSION_MAX_TLSv1_0:
917 res = wolfSSL_CTX_set_max_proto_version(backend->ctx, TLS1_VERSION);
918 break;
919 case CURL_SSLVERSION_MAX_DEFAULT:
920 case CURL_SSLVERSION_MAX_NONE:
921 res = WOLFSSL_SUCCESS;
922 break;
923 default:
924 failf(data, "wolfSSL: unsupported maximum TLS version value");
925 return CURLE_SSL_CONNECT_ERROR;
926 }
927 if(res != WOLFSSL_SUCCESS) {
928 failf(data, "wolfSSL: failed set the maximum TLS version");
929 return CURLE_SSL_CONNECT_ERROR;
930 }
931
932 #ifndef WOLFSSL_TLS13
933 {
934 char *ciphers = conn_config->cipher_list;
935 if(ciphers) {
936 if(!SSL_CTX_set_cipher_list(backend->ctx, ciphers)) {
937 failf(data, "failed setting cipher list: %s", ciphers);
938 return CURLE_SSL_CIPHER;
939 }
940 infof(data, "Cipher selection: %s", ciphers);
941 }
942 }
943 #else
944 #define MAX_CIPHER_LEN 4096
945 if(conn_config->cipher_list || conn_config->cipher_list13) {
946 const char *ciphers12 = conn_config->cipher_list;
947 const char *ciphers13 = conn_config->cipher_list13;
948 struct dynbuf c;
949 CURLcode result;
950 Curl_dyn_init(&c, MAX_CIPHER_LEN);
951
952 if(ciphers13)
953 result = Curl_dyn_add(&c, ciphers13);
954 else
955 result = wssl_add_default_ciphers(TRUE, &c);
956
957 if(!result) {
958 if(ciphers12) {
959 if(Curl_dyn_len(&c))
960 result = Curl_dyn_addn(&c, ":", 1);
961 if(!result)
962 result = Curl_dyn_add(&c, ciphers12);
963 }
964 else
965 result = wssl_add_default_ciphers(FALSE, &c);
966 }
967 if(result)
968 return result;
969
970 if(!wolfSSL_CTX_set_cipher_list(backend->ctx, Curl_dyn_ptr(&c))) {
971 failf(data, "failed setting cipher list: %s", Curl_dyn_ptr(&c));
972 Curl_dyn_free(&c);
973 return CURLE_SSL_CIPHER;
974 }
975 infof(data, "Cipher selection: %s", Curl_dyn_ptr(&c));
976 Curl_dyn_free(&c);
977 }
978 #endif
979
980 curves = conn_config->curves;
981 if(curves) {
982
983 #ifdef WOLFSSL_HAVE_KYBER
984 for(idx = 0; gnm[idx].name != NULL; idx++) {
985 if(strncmp(curves, gnm[idx].name, strlen(gnm[idx].name)) == 0) {
986 pqkem = gnm[idx].group;
987 break;
988 }
989 }
990
991 if(pqkem == 0)
992 #endif
993 {
994 if(!wolfSSL_CTX_set1_curves_list(backend->ctx, curves)) {
995 failf(data, "failed setting curves list: '%s'", curves);
996 return CURLE_SSL_CIPHER;
997 }
998 }
999 }
1000
1001 /* Load the client certificate, and private key */
1002 #ifndef NO_FILESYSTEM
1003 if(ssl_config->primary.cert_blob || ssl_config->primary.clientcert) {
1004 const char *cert_file = ssl_config->primary.clientcert;
1005 const char *key_file = ssl_config->key;
1006 const struct curl_blob *cert_blob = ssl_config->primary.cert_blob;
1007 const struct curl_blob *key_blob = ssl_config->key_blob;
1008 int file_type = wolfssl_do_file_type(ssl_config->cert_type);
1009 int rc;
1010
1011 switch(file_type) {
1012 case WOLFSSL_FILETYPE_PEM:
1013 rc = cert_blob ?
1014 wolfSSL_CTX_use_certificate_chain_buffer(backend->ctx,
1015 cert_blob->data,
1016 (long)cert_blob->len) :
1017 wolfSSL_CTX_use_certificate_chain_file(backend->ctx, cert_file);
1018 break;
1019 case WOLFSSL_FILETYPE_ASN1:
1020 rc = cert_blob ?
1021 wolfSSL_CTX_use_certificate_buffer(backend->ctx, cert_blob->data,
1022 (long)cert_blob->len, file_type) :
1023 wolfSSL_CTX_use_certificate_file(backend->ctx, cert_file, file_type);
1024 break;
1025 default:
1026 failf(data, "unknown cert type");
1027 return CURLE_BAD_FUNCTION_ARGUMENT;
1028 }
1029 if(rc != 1) {
1030 failf(data, "unable to use client certificate");
1031 return CURLE_SSL_CONNECT_ERROR;
1032 }
1033
1034 if(!key_blob && !key_file) {
1035 key_blob = cert_blob;
1036 key_file = cert_file;
1037 }
1038 else
1039 file_type = wolfssl_do_file_type(ssl_config->key_type);
1040
1041 rc = key_blob ?
1042 wolfSSL_CTX_use_PrivateKey_buffer(backend->ctx, key_blob->data,
1043 (long)key_blob->len, file_type) :
1044 wolfSSL_CTX_use_PrivateKey_file(backend->ctx, key_file, file_type);
1045 if(rc != 1) {
1046 failf(data, "unable to set private key");
1047 return CURLE_SSL_CONNECT_ERROR;
1048 }
1049 }
1050 #else /* NO_FILESYSTEM */
1051 if(ssl_config->primary.cert_blob) {
1052 const struct curl_blob *cert_blob = ssl_config->primary.cert_blob;
1053 const struct curl_blob *key_blob = ssl_config->key_blob;
1054 int file_type = wolfssl_do_file_type(ssl_config->cert_type);
1055 int rc;
1056
1057 switch(file_type) {
1058 case WOLFSSL_FILETYPE_PEM:
1059 rc = wolfSSL_CTX_use_certificate_chain_buffer(backend->ctx,
1060 cert_blob->data,
1061 (long)cert_blob->len);
1062 break;
1063 case WOLFSSL_FILETYPE_ASN1:
1064 rc = wolfSSL_CTX_use_certificate_buffer(backend->ctx, cert_blob->data,
1065 (long)cert_blob->len, file_type);
1066 break;
1067 default:
1068 failf(data, "unknown cert type");
1069 return CURLE_BAD_FUNCTION_ARGUMENT;
1070 }
1071 if(rc != 1) {
1072 failf(data, "unable to use client certificate");
1073 return CURLE_SSL_CONNECT_ERROR;
1074 }
1075
1076 if(!key_blob)
1077 key_blob = cert_blob;
1078 else
1079 file_type = wolfssl_do_file_type(ssl_config->key_type);
1080
1081 if(wolfSSL_CTX_use_PrivateKey_buffer(backend->ctx, key_blob->data,
1082 (long)key_blob->len,
1083 file_type) != 1) {
1084 failf(data, "unable to set private key");
1085 return CURLE_SSL_CONNECT_ERROR;
1086 }
1087 }
1088 #endif /* !NO_FILESYSTEM */
1089
1090 /* SSL always tries to verify the peer, this only says whether it should
1091 * fail to connect if the verification fails, or if it should continue
1092 * anyway. In the latter case the result of the verification is checked with
1093 * SSL_get_verify_result() below. */
1094 wolfSSL_CTX_set_verify(backend->ctx,
1095 conn_config->verifypeer ? WOLFSSL_VERIFY_PEER :
1096 WOLFSSL_VERIFY_NONE, NULL);
1097
1098 #ifdef HAVE_SNI
1099 if(connssl->peer.sni) {
1100 size_t sni_len = strlen(connssl->peer.sni);
1101 if((sni_len < USHRT_MAX)) {
1102 if(wolfSSL_CTX_UseSNI(backend->ctx, WOLFSSL_SNI_HOST_NAME,
1103 connssl->peer.sni,
1104 (unsigned short)sni_len) != 1) {
1105 failf(data, "Failed to set SNI");
1106 return CURLE_SSL_CONNECT_ERROR;
1107 }
1108 }
1109 }
1110 #endif
1111
1112 /* give application a chance to interfere with SSL set up. */
1113 if(data->set.ssl.fsslctx) {
1114 CURLcode result;
1115 if(!backend->x509_store_setup) {
1116 result = Curl_wssl_setup_x509_store(cf, data, backend);
1117 if(result)
1118 return result;
1119 }
1120 result = (*data->set.ssl.fsslctx)(data, backend->ctx,
1121 data->set.ssl.fsslctxp);
1122 if(result) {
1123 failf(data, "error signaled by ssl ctx callback");
1124 return result;
1125 }
1126 }
1127 #ifdef NO_FILESYSTEM
1128 else if(conn_config->verifypeer) {
1129 failf(data, "SSL: Certificates cannot be loaded because wolfSSL was built"
1130 " with \"no filesystem\". Either disable peer verification"
1131 " (insecure) or if you are building an application with libcurl you"
1132 " can load certificates via CURLOPT_SSL_CTX_FUNCTION.");
1133 return CURLE_SSL_CONNECT_ERROR;
1134 }
1135 #endif
1136
1137 /* Let's make an SSL structure */
1138 if(backend->handle)
1139 wolfSSL_free(backend->handle);
1140 backend->handle = wolfSSL_new(backend->ctx);
1141 if(!backend->handle) {
1142 failf(data, "SSL: could not create a handle");
1143 return CURLE_OUT_OF_MEMORY;
1144 }
1145
1146 #ifdef WOLFSSL_HAVE_KYBER
1147 if(pqkem) {
1148 if(wolfSSL_UseKeyShare(backend->handle, pqkem) != WOLFSSL_SUCCESS) {
1149 failf(data, "unable to use PQ KEM");
1150 }
1151 }
1152 #endif
1153
1154 #ifdef HAVE_ALPN
1155 if(connssl->alpn) {
1156 struct alpn_proto_buf proto;
1157 CURLcode result;
1158
1159 result = Curl_alpn_to_proto_str(&proto, connssl->alpn);
1160 if(result ||
1161 wolfSSL_UseALPN(backend->handle,
1162 (char *)proto.data, (unsigned int)proto.len,
1163 WOLFSSL_ALPN_CONTINUE_ON_MISMATCH) != WOLFSSL_SUCCESS) {
1164 failf(data, "SSL: failed setting ALPN protocols");
1165 return CURLE_SSL_CONNECT_ERROR;
1166 }
1167 infof(data, VTLS_INFOF_ALPN_OFFER_1STR, proto.data);
1168 }
1169 #endif /* HAVE_ALPN */
1170
1171 #ifdef OPENSSL_EXTRA
1172 if(Curl_tls_keylog_enabled()) {
1173 /* Ensure the Client Random is preserved. */
1174 wolfSSL_KeepArrays(backend->handle);
1175 #if defined(HAVE_SECRET_CALLBACK) && defined(WOLFSSL_TLS13)
1176 wolfSSL_set_tls13_secret_cb(backend->handle,
1177 wolfssl_tls13_secret_callback, NULL);
1178 #endif
1179 }
1180 #endif /* OPENSSL_EXTRA */
1181
1182 #ifdef HAVE_SECURE_RENEGOTIATION
1183 if(wolfSSL_UseSecureRenegotiation(backend->handle) != SSL_SUCCESS) {
1184 failf(data, "SSL: failed setting secure renegotiation");
1185 return CURLE_SSL_CONNECT_ERROR;
1186 }
1187 #endif /* HAVE_SECURE_RENEGOTIATION */
1188
1189 /* Check if there is a cached ID we can/should use here! */
1190 if(ssl_config->primary.cache_session) {
1191 /* Set session from cache if there is one */
1192 (void)Curl_wssl_setup_session(cf, data, backend, connssl->peer.scache_key);
1193 /* Register to get notified when a new session is received */
1194 wolfSSL_set_app_data(backend->handle, cf);
1195 wolfSSL_CTX_sess_set_new_cb(backend->ctx, wssl_vtls_new_session_cb);
1196 }
1197
1198 #ifdef USE_ECH_WOLFSSL
1199 if(ECH_ENABLED(data)) {
1200 int trying_ech_now = 0;
1201
1202 if(data->set.str[STRING_ECH_PUBLIC]) {
1203 infof(data, "ECH: outername not (yet) supported with wolfSSL");
1204 return CURLE_SSL_CONNECT_ERROR;
1205 }
1206 if(data->set.tls_ech == CURLECH_GREASE) {
1207 infof(data, "ECH: GREASE'd ECH not yet supported for wolfSSL");
1208 return CURLE_SSL_CONNECT_ERROR;
1209 }
1210 if(data->set.tls_ech & CURLECH_CLA_CFG
1211 && data->set.str[STRING_ECH_CONFIG]) {
1212 char *b64val = data->set.str[STRING_ECH_CONFIG];
1213 word32 b64len = 0;
1214
1215 b64len = (word32) strlen(b64val);
1216 if(b64len
1217 && wolfSSL_SetEchConfigsBase64(backend->handle, b64val, b64len)
1218 != WOLFSSL_SUCCESS) {
1219 if(data->set.tls_ech & CURLECH_HARD)
1220 return CURLE_SSL_CONNECT_ERROR;
1221 }
1222 else {
1223 trying_ech_now = 1;
1224 infof(data, "ECH: ECHConfig from command line");
1225 }
1226 }
1227 else {
1228 struct Curl_dns_entry *dns = NULL;
1229
1230 dns = Curl_fetch_addr(data, connssl->peer.hostname, connssl->peer.port);
1231 if(!dns) {
1232 infof(data, "ECH: requested but no DNS info available");
1233 if(data->set.tls_ech & CURLECH_HARD)
1234 return CURLE_SSL_CONNECT_ERROR;
1235 }
1236 else {
1237 struct Curl_https_rrinfo *rinfo = NULL;
1238
1239 rinfo = dns->hinfo;
1240 if(rinfo && rinfo->echconfiglist) {
1241 unsigned char *ecl = rinfo->echconfiglist;
1242 size_t elen = rinfo->echconfiglist_len;
1243
1244 infof(data, "ECH: ECHConfig from DoH HTTPS RR");
1245 if(wolfSSL_SetEchConfigs(backend->handle, ecl, (word32) elen) !=
1246 WOLFSSL_SUCCESS) {
1247 infof(data, "ECH: wolfSSL_SetEchConfigs failed");
1248 if(data->set.tls_ech & CURLECH_HARD)
1249 return CURLE_SSL_CONNECT_ERROR;
1250 }
1251 else {
1252 trying_ech_now = 1;
1253 infof(data, "ECH: imported ECHConfigList of length %ld", elen);
1254 }
1255 }
1256 else {
1257 infof(data, "ECH: requested but no ECHConfig available");
1258 if(data->set.tls_ech & CURLECH_HARD)
1259 return CURLE_SSL_CONNECT_ERROR;
1260 }
1261 Curl_resolv_unlink(data, &dns);
1262 }
1263 }
1264
1265 if(trying_ech_now && wolfSSL_set_min_proto_version(backend->handle,
1266 TLS1_3_VERSION) != 1) {
1267 infof(data, "ECH: cannot force TLSv1.3 [ERROR]");
1268 return CURLE_SSL_CONNECT_ERROR;
1269 }
1270
1271 }
1272 #endif /* USE_ECH_WOLFSSL */
1273
1274 #ifdef USE_BIO_CHAIN
1275 {
1276 WOLFSSL_BIO *bio;
1277
1278 bio = wolfSSL_BIO_new(wolfssl_bio_cf_method);
1279 if(!bio)
1280 return CURLE_OUT_OF_MEMORY;
1281
1282 wolfSSL_BIO_set_data(bio, cf);
1283 wolfSSL_set_bio(backend->handle, bio, bio);
1284 }
1285 #else /* USE_BIO_CHAIN */
1286 /* pass the raw socket into the SSL layer */
1287 if(!wolfSSL_set_fd(backend->handle,
1288 (int)Curl_conn_cf_get_socket(cf, data))) {
1289 failf(data, "SSL: SSL_set_fd failed");
1290 return CURLE_SSL_CONNECT_ERROR;
1291 }
1292 #endif /* !USE_BIO_CHAIN */
1293
1294 connssl->connecting_state = ssl_connect_2;
1295 return CURLE_OK;
1296 }
1297
1298
wolfssl_strerror(unsigned long error,char * buf,unsigned long size)1299 static char *wolfssl_strerror(unsigned long error, char *buf,
1300 unsigned long size)
1301 {
1302 DEBUGASSERT(size > 40);
1303 *buf = '\0';
1304
1305 wolfSSL_ERR_error_string_n(error, buf, size);
1306
1307 if(!*buf) {
1308 const char *msg = error ? "Unknown error" : "No error";
1309 /* the string fits because the assert above assures this */
1310 strcpy(buf, msg);
1311 }
1312
1313 return buf;
1314 }
1315
1316
1317 static CURLcode
wolfssl_connect_step2(struct Curl_cfilter * cf,struct Curl_easy * data)1318 wolfssl_connect_step2(struct Curl_cfilter *cf, struct Curl_easy *data)
1319 {
1320 int ret = -1;
1321 struct ssl_connect_data *connssl = cf->ctx;
1322 struct wolfssl_ctx *backend =
1323 (struct wolfssl_ctx *)connssl->backend;
1324 struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
1325 #ifndef CURL_DISABLE_PROXY
1326 const char * const pinnedpubkey = Curl_ssl_cf_is_proxy(cf) ?
1327 data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] :
1328 data->set.str[STRING_SSL_PINNEDPUBLICKEY];
1329 #else
1330 const char * const pinnedpubkey = data->set.str[STRING_SSL_PINNEDPUBLICKEY];
1331 #endif
1332
1333 DEBUGASSERT(backend);
1334
1335 wolfSSL_ERR_clear_error();
1336
1337 /* Enable RFC2818 checks */
1338 if(conn_config->verifyhost) {
1339 char *snihost = connssl->peer.sni ?
1340 connssl->peer.sni : connssl->peer.hostname;
1341 if(wolfSSL_check_domain_name(backend->handle, snihost) == WOLFSSL_FAILURE)
1342 return CURLE_SSL_CONNECT_ERROR;
1343 }
1344
1345 if(!backend->x509_store_setup) {
1346 /* After having send off the ClientHello, we prepare the x509
1347 * store to verify the coming certificate from the server */
1348 CURLcode result;
1349 result = Curl_wssl_setup_x509_store(cf, data, backend);
1350 if(result)
1351 return result;
1352 }
1353
1354 connssl->io_need = CURL_SSL_IO_NEED_NONE;
1355 ret = wolfSSL_connect(backend->handle);
1356
1357 #ifdef OPENSSL_EXTRA
1358 if(Curl_tls_keylog_enabled()) {
1359 /* If key logging is enabled, wait for the handshake to complete and then
1360 * proceed with logging secrets (for TLS 1.2 or older).
1361 *
1362 * During the handshake (ret==-1), wolfSSL_want_read() is true as it waits
1363 * for the server response. At that point the master secret is not yet
1364 * available, so we must not try to read it.
1365 * To log the secret on completion with a handshake failure, detect
1366 * completion via the observation that there is nothing to read or write.
1367 * Note that OpenSSL SSL_want_read() is always true here. If wolfSSL ever
1368 * changes, the worst case is that no key is logged on error.
1369 */
1370 if(ret == WOLFSSL_SUCCESS ||
1371 (!wolfSSL_want_read(backend->handle) &&
1372 !wolfSSL_want_write(backend->handle))) {
1373 wolfssl_log_tls12_secret(backend->handle);
1374 /* Client Random and master secrets are no longer needed, erase these.
1375 * Ignored while the handshake is still in progress. */
1376 wolfSSL_FreeArrays(backend->handle);
1377 }
1378 }
1379 #endif /* OPENSSL_EXTRA */
1380
1381 if(ret != 1) {
1382 int detail = wolfSSL_get_error(backend->handle, ret);
1383
1384 if(WOLFSSL_ERROR_WANT_READ == detail) {
1385 connssl->io_need = CURL_SSL_IO_NEED_RECV;
1386 return CURLE_OK;
1387 }
1388 else if(WOLFSSL_ERROR_WANT_WRITE == detail) {
1389 connssl->io_need = CURL_SSL_IO_NEED_SEND;
1390 return CURLE_OK;
1391 }
1392 /* There is no easy way to override only the CN matching.
1393 * This will enable the override of both mismatching SubjectAltNames
1394 * as also mismatching CN fields */
1395 else if(DOMAIN_NAME_MISMATCH == detail) {
1396 #if 1
1397 failf(data, " subject alt name(s) or common name do not match \"%s\"",
1398 connssl->peer.dispname);
1399 return CURLE_PEER_FAILED_VERIFICATION;
1400 #else
1401 /* When the wolfssl_check_domain_name() is used and you desire to
1402 * continue on a DOMAIN_NAME_MISMATCH, i.e. 'ssl_config.verifyhost
1403 * == 0', CyaSSL version 2.4.0 will fail with an INCOMPLETE_DATA
1404 * error. The only way to do this is currently to switch the
1405 * Wolfssl_check_domain_name() in and out based on the
1406 * 'ssl_config.verifyhost' value. */
1407 if(conn_config->verifyhost) {
1408 failf(data,
1409 " subject alt name(s) or common name do not match \"%s\"\n",
1410 connssl->dispname);
1411 return CURLE_PEER_FAILED_VERIFICATION;
1412 }
1413 else {
1414 infof(data,
1415 " subject alt name(s) and/or common name do not match \"%s\"",
1416 connssl->dispname);
1417 return CURLE_OK;
1418 }
1419 #endif
1420 }
1421 else if(ASN_NO_SIGNER_E == detail) {
1422 if(conn_config->verifypeer) {
1423 failf(data, " CA signer not available for verification");
1424 return CURLE_SSL_CACERT_BADFILE;
1425 }
1426 else {
1427 /* Just continue with a warning if no strict certificate
1428 verification is required. */
1429 infof(data, "CA signer not available for verification, "
1430 "continuing anyway");
1431 }
1432 }
1433 else if(ASN_AFTER_DATE_E == detail) {
1434 failf(data, "server verification failed: certificate has expired.");
1435 return CURLE_PEER_FAILED_VERIFICATION;
1436 }
1437 else if(ASN_BEFORE_DATE_E == detail) {
1438 failf(data, "server verification failed: certificate not valid yet.");
1439 return CURLE_PEER_FAILED_VERIFICATION;
1440 }
1441 #ifdef USE_ECH_WOLFSSL
1442 else if(-1 == detail) {
1443 /* try access a retry_config ECHConfigList for tracing */
1444 byte echConfigs[1000];
1445 word32 echConfigsLen = 1000;
1446 int rv = 0;
1447
1448 /* this currently does not produce the retry_configs */
1449 rv = wolfSSL_GetEchConfigs(backend->handle, echConfigs,
1450 &echConfigsLen);
1451 if(rv != WOLFSSL_SUCCESS) {
1452 infof(data, "Failed to get ECHConfigs");
1453 }
1454 else {
1455 char *b64str = NULL;
1456 size_t blen = 0;
1457
1458 rv = Curl_base64_encode((const char *)echConfigs, echConfigsLen,
1459 &b64str, &blen);
1460 if(!rv && b64str)
1461 infof(data, "ECH: (not yet) retry_configs %s", b64str);
1462 free(b64str);
1463 }
1464 }
1465 #endif
1466 else if(backend->io_result == CURLE_AGAIN) {
1467 return CURLE_OK;
1468 }
1469 else {
1470 char error_buffer[256];
1471 failf(data, "SSL_connect failed with error %d: %s", detail,
1472 wolfssl_strerror((unsigned long)detail, error_buffer,
1473 sizeof(error_buffer)));
1474 return CURLE_SSL_CONNECT_ERROR;
1475 }
1476 }
1477
1478 if(pinnedpubkey) {
1479 #ifdef KEEP_PEER_CERT
1480 WOLFSSL_X509 *x509;
1481 const char *x509_der;
1482 int x509_der_len;
1483 struct Curl_X509certificate x509_parsed;
1484 struct Curl_asn1Element *pubkey;
1485 CURLcode result;
1486
1487 x509 = wolfSSL_get_peer_certificate(backend->handle);
1488 if(!x509) {
1489 failf(data, "SSL: failed retrieving server certificate");
1490 return CURLE_SSL_PINNEDPUBKEYNOTMATCH;
1491 }
1492
1493 x509_der = (const char *)wolfSSL_X509_get_der(x509, &x509_der_len);
1494 if(!x509_der) {
1495 failf(data, "SSL: failed retrieving ASN.1 server certificate");
1496 return CURLE_SSL_PINNEDPUBKEYNOTMATCH;
1497 }
1498
1499 memset(&x509_parsed, 0, sizeof(x509_parsed));
1500 if(Curl_parseX509(&x509_parsed, x509_der, x509_der + x509_der_len))
1501 return CURLE_SSL_PINNEDPUBKEYNOTMATCH;
1502
1503 pubkey = &x509_parsed.subjectPublicKeyInfo;
1504 if(!pubkey->header || pubkey->end <= pubkey->header) {
1505 failf(data, "SSL: failed retrieving public key from server certificate");
1506 return CURLE_SSL_PINNEDPUBKEYNOTMATCH;
1507 }
1508
1509 result = Curl_pin_peer_pubkey(data,
1510 pinnedpubkey,
1511 (const unsigned char *)pubkey->header,
1512 (size_t)(pubkey->end - pubkey->header));
1513 wolfSSL_FreeX509(x509);
1514 if(result) {
1515 failf(data, "SSL: public key does not match pinned public key");
1516 return result;
1517 }
1518 #else
1519 failf(data, "Library lacks pinning support built-in");
1520 return CURLE_NOT_BUILT_IN;
1521 #endif
1522 }
1523
1524 #ifdef HAVE_ALPN
1525 if(connssl->alpn) {
1526 int rc;
1527 char *protocol = NULL;
1528 unsigned short protocol_len = 0;
1529
1530 rc = wolfSSL_ALPN_GetProtocol(backend->handle, &protocol, &protocol_len);
1531
1532 if(rc == WOLFSSL_SUCCESS) {
1533 Curl_alpn_set_negotiated(cf, data, connssl,
1534 (const unsigned char *)protocol, protocol_len);
1535 }
1536 else if(rc == WOLFSSL_ALPN_NOT_FOUND)
1537 Curl_alpn_set_negotiated(cf, data, connssl, NULL, 0);
1538 else {
1539 failf(data, "ALPN, failure getting protocol, error %d", rc);
1540 return CURLE_SSL_CONNECT_ERROR;
1541 }
1542 }
1543 #endif /* HAVE_ALPN */
1544
1545 connssl->connecting_state = ssl_connect_3;
1546 #if (LIBWOLFSSL_VERSION_HEX >= 0x03009010)
1547 infof(data, "SSL connection using %s / %s",
1548 wolfSSL_get_version(backend->handle),
1549 wolfSSL_get_cipher_name(backend->handle));
1550 #else
1551 infof(data, "SSL connected");
1552 #endif
1553
1554 return CURLE_OK;
1555 }
1556
wolfssl_send(struct Curl_cfilter * cf,struct Curl_easy * data,const void * mem,size_t len,CURLcode * curlcode)1557 static ssize_t wolfssl_send(struct Curl_cfilter *cf,
1558 struct Curl_easy *data,
1559 const void *mem,
1560 size_t len,
1561 CURLcode *curlcode)
1562 {
1563 struct ssl_connect_data *connssl = cf->ctx;
1564 struct wolfssl_ctx *backend =
1565 (struct wolfssl_ctx *)connssl->backend;
1566 int memlen = (len > (size_t)INT_MAX) ? INT_MAX : (int)len;
1567 int rc;
1568
1569 DEBUGASSERT(backend);
1570
1571 wolfSSL_ERR_clear_error();
1572
1573 rc = wolfSSL_write(backend->handle, mem, memlen);
1574 if(rc <= 0) {
1575 int err = wolfSSL_get_error(backend->handle, rc);
1576
1577 switch(err) {
1578 case WOLFSSL_ERROR_WANT_READ:
1579 case WOLFSSL_ERROR_WANT_WRITE:
1580 /* there is data pending, re-invoke SSL_write() */
1581 CURL_TRC_CF(data, cf, "wolfssl_send(len=%zu) -> AGAIN", len);
1582 *curlcode = CURLE_AGAIN;
1583 return -1;
1584 default:
1585 if(backend->io_result == CURLE_AGAIN) {
1586 CURL_TRC_CF(data, cf, "wolfssl_send(len=%zu) -> AGAIN", len);
1587 *curlcode = CURLE_AGAIN;
1588 return -1;
1589 }
1590 CURL_TRC_CF(data, cf, "wolfssl_send(len=%zu) -> %d, %d", len, rc, err);
1591 {
1592 char error_buffer[256];
1593 failf(data, "SSL write: %s, errno %d",
1594 wolfssl_strerror((unsigned long)err, error_buffer,
1595 sizeof(error_buffer)),
1596 SOCKERRNO);
1597 }
1598 *curlcode = CURLE_SEND_ERROR;
1599 return -1;
1600 }
1601 }
1602 CURL_TRC_CF(data, cf, "wolfssl_send(len=%zu) -> %d", len, rc);
1603 return rc;
1604 }
1605
wolfssl_shutdown(struct Curl_cfilter * cf,struct Curl_easy * data,bool send_shutdown,bool * done)1606 static CURLcode wolfssl_shutdown(struct Curl_cfilter *cf,
1607 struct Curl_easy *data,
1608 bool send_shutdown, bool *done)
1609 {
1610 struct ssl_connect_data *connssl = cf->ctx;
1611 struct wolfssl_ctx *wctx = (struct wolfssl_ctx *)connssl->backend;
1612 CURLcode result = CURLE_OK;
1613 char buf[1024];
1614 char error_buffer[256];
1615 int nread = -1, err;
1616 size_t i;
1617 int detail;
1618
1619 DEBUGASSERT(wctx);
1620 if(!wctx->handle || cf->shutdown) {
1621 *done = TRUE;
1622 goto out;
1623 }
1624
1625 wctx->shutting_down = TRUE;
1626 connssl->io_need = CURL_SSL_IO_NEED_NONE;
1627 *done = FALSE;
1628 if(!(wolfSSL_get_shutdown(wctx->handle) & WOLFSSL_SENT_SHUTDOWN)) {
1629 /* We have not started the shutdown from our side yet. Check
1630 * if the server already sent us one. */
1631 wolfSSL_ERR_clear_error();
1632 nread = wolfSSL_read(wctx->handle, buf, (int)sizeof(buf));
1633 err = wolfSSL_get_error(wctx->handle, nread);
1634 CURL_TRC_CF(data, cf, "wolfSSL_read, nread=%d, err=%d", nread, err);
1635 if(!nread && err == WOLFSSL_ERROR_ZERO_RETURN) {
1636 bool input_pending;
1637 /* Yes, it did. */
1638 if(!send_shutdown) {
1639 CURL_TRC_CF(data, cf, "SSL shutdown received, not sending");
1640 *done = TRUE;
1641 goto out;
1642 }
1643 else if(!cf->next->cft->is_alive(cf->next, data, &input_pending)) {
1644 /* Server closed the connection after its closy notify. It
1645 * seems not interested to see our close notify, so do not
1646 * send it. We are done. */
1647 CURL_TRC_CF(data, cf, "peer closed connection");
1648 connssl->peer_closed = TRUE;
1649 *done = TRUE;
1650 goto out;
1651 }
1652 }
1653 }
1654
1655 /* SSL should now have started the shutdown from our side. Since it
1656 * was not complete, we are lacking the close notify from the server. */
1657 if(send_shutdown) {
1658 wolfSSL_ERR_clear_error();
1659 if(wolfSSL_shutdown(wctx->handle) == 1) {
1660 CURL_TRC_CF(data, cf, "SSL shutdown finished");
1661 *done = TRUE;
1662 goto out;
1663 }
1664 if(WOLFSSL_ERROR_WANT_WRITE == wolfSSL_get_error(wctx->handle, nread)) {
1665 CURL_TRC_CF(data, cf, "SSL shutdown still wants to send");
1666 connssl->io_need = CURL_SSL_IO_NEED_SEND;
1667 goto out;
1668 }
1669 /* Having sent the close notify, we use wolfSSL_read() to get the
1670 * missing close notify from the server. */
1671 }
1672
1673 for(i = 0; i < 10; ++i) {
1674 wolfSSL_ERR_clear_error();
1675 nread = wolfSSL_read(wctx->handle, buf, (int)sizeof(buf));
1676 if(nread <= 0)
1677 break;
1678 }
1679 err = wolfSSL_get_error(wctx->handle, nread);
1680 switch(err) {
1681 case WOLFSSL_ERROR_ZERO_RETURN: /* no more data */
1682 CURL_TRC_CF(data, cf, "SSL shutdown received");
1683 *done = TRUE;
1684 break;
1685 case WOLFSSL_ERROR_NONE: /* just did not get anything */
1686 case WOLFSSL_ERROR_WANT_READ:
1687 /* SSL has send its notify and now wants to read the reply
1688 * from the server. We are not really interested in that. */
1689 CURL_TRC_CF(data, cf, "SSL shutdown sent, want receive");
1690 connssl->io_need = CURL_SSL_IO_NEED_RECV;
1691 break;
1692 case WOLFSSL_ERROR_WANT_WRITE:
1693 CURL_TRC_CF(data, cf, "SSL shutdown send blocked");
1694 connssl->io_need = CURL_SSL_IO_NEED_SEND;
1695 break;
1696 default:
1697 detail = wolfSSL_get_error(wctx->handle, err);
1698 CURL_TRC_CF(data, cf, "SSL shutdown, error: '%s'(%d)",
1699 wolfssl_strerror((unsigned long)err, error_buffer,
1700 sizeof(error_buffer)),
1701 detail);
1702 result = CURLE_RECV_ERROR;
1703 break;
1704 }
1705
1706 out:
1707 cf->shutdown = (result || *done);
1708 return result;
1709 }
1710
wolfssl_close(struct Curl_cfilter * cf,struct Curl_easy * data)1711 static void wolfssl_close(struct Curl_cfilter *cf, struct Curl_easy *data)
1712 {
1713 struct ssl_connect_data *connssl = cf->ctx;
1714 struct wolfssl_ctx *backend =
1715 (struct wolfssl_ctx *)connssl->backend;
1716
1717 (void) data;
1718
1719 DEBUGASSERT(backend);
1720
1721 if(backend->handle) {
1722 wolfSSL_free(backend->handle);
1723 backend->handle = NULL;
1724 }
1725 if(backend->ctx) {
1726 wolfSSL_CTX_free(backend->ctx);
1727 backend->ctx = NULL;
1728 }
1729 }
1730
wolfssl_recv(struct Curl_cfilter * cf,struct Curl_easy * data,char * buf,size_t blen,CURLcode * curlcode)1731 static ssize_t wolfssl_recv(struct Curl_cfilter *cf,
1732 struct Curl_easy *data,
1733 char *buf, size_t blen,
1734 CURLcode *curlcode)
1735 {
1736 struct ssl_connect_data *connssl = cf->ctx;
1737 struct wolfssl_ctx *backend =
1738 (struct wolfssl_ctx *)connssl->backend;
1739 int buffsize = (blen > (size_t)INT_MAX) ? INT_MAX : (int)blen;
1740 int nread;
1741
1742 DEBUGASSERT(backend);
1743
1744 wolfSSL_ERR_clear_error();
1745 *curlcode = CURLE_OK;
1746
1747 nread = wolfSSL_read(backend->handle, buf, buffsize);
1748
1749 if(nread <= 0) {
1750 int err = wolfSSL_get_error(backend->handle, nread);
1751
1752 switch(err) {
1753 case WOLFSSL_ERROR_ZERO_RETURN: /* no more data */
1754 CURL_TRC_CF(data, cf, "wolfssl_recv(len=%zu) -> CLOSED", blen);
1755 *curlcode = CURLE_OK;
1756 return 0;
1757 case WOLFSSL_ERROR_NONE:
1758 case WOLFSSL_ERROR_WANT_READ:
1759 case WOLFSSL_ERROR_WANT_WRITE:
1760 if(!backend->io_result && connssl->peer_closed) {
1761 CURL_TRC_CF(data, cf, "wolfssl_recv(len=%zu) -> CLOSED", blen);
1762 *curlcode = CURLE_OK;
1763 return 0;
1764 }
1765 /* there is data pending, re-invoke wolfSSL_read() */
1766 CURL_TRC_CF(data, cf, "wolfssl_recv(len=%zu) -> AGAIN", blen);
1767 *curlcode = CURLE_AGAIN;
1768 return -1;
1769 default:
1770 if(backend->io_result == CURLE_AGAIN) {
1771 CURL_TRC_CF(data, cf, "wolfssl_recv(len=%zu) -> AGAIN", blen);
1772 *curlcode = CURLE_AGAIN;
1773 return -1;
1774 }
1775 else if(!backend->io_result && connssl->peer_closed) {
1776 CURL_TRC_CF(data, cf, "wolfssl_recv(len=%zu) -> CLOSED", blen);
1777 *curlcode = CURLE_OK;
1778 return 0;
1779 }
1780 else {
1781 char error_buffer[256];
1782 failf(data, "SSL read: %s, errno %d",
1783 wolfssl_strerror((unsigned long)err, error_buffer,
1784 sizeof(error_buffer)),
1785 SOCKERRNO);
1786 }
1787 *curlcode = CURLE_RECV_ERROR;
1788 return -1;
1789 }
1790 }
1791 CURL_TRC_CF(data, cf, "wolfssl_recv(len=%zu) -> %d", blen, nread);
1792 return nread;
1793 }
1794
1795
Curl_wssl_version(char * buffer,size_t size)1796 size_t Curl_wssl_version(char *buffer, size_t size)
1797 {
1798 #if LIBWOLFSSL_VERSION_HEX >= 0x03006000
1799 return msnprintf(buffer, size, "wolfSSL/%s", wolfSSL_lib_version());
1800 #elif defined(WOLFSSL_VERSION)
1801 return msnprintf(buffer, size, "wolfSSL/%s", WOLFSSL_VERSION);
1802 #endif
1803 }
1804
1805
wolfssl_init(void)1806 static int wolfssl_init(void)
1807 {
1808 int ret;
1809
1810 #ifdef OPENSSL_EXTRA
1811 Curl_tls_keylog_open();
1812 #endif
1813 ret = (wolfSSL_Init() == WOLFSSL_SUCCESS);
1814 wolfssl_bio_cf_init_methods();
1815 return ret;
1816 }
1817
1818
wolfssl_cleanup(void)1819 static void wolfssl_cleanup(void)
1820 {
1821 wolfssl_bio_cf_free_methods();
1822 wolfSSL_Cleanup();
1823 #ifdef OPENSSL_EXTRA
1824 Curl_tls_keylog_close();
1825 #endif
1826 }
1827
1828
wolfssl_data_pending(struct Curl_cfilter * cf,const struct Curl_easy * data)1829 static bool wolfssl_data_pending(struct Curl_cfilter *cf,
1830 const struct Curl_easy *data)
1831 {
1832 struct ssl_connect_data *ctx = cf->ctx;
1833 struct wolfssl_ctx *backend;
1834
1835 (void)data;
1836 DEBUGASSERT(ctx && ctx->backend);
1837
1838 backend = (struct wolfssl_ctx *)ctx->backend;
1839 if(backend->handle) /* SSL is in use */
1840 return wolfSSL_pending(backend->handle);
1841 else
1842 return FALSE;
1843 }
1844
1845 static CURLcode
wolfssl_connect_common(struct Curl_cfilter * cf,struct Curl_easy * data,bool nonblocking,bool * done)1846 wolfssl_connect_common(struct Curl_cfilter *cf,
1847 struct Curl_easy *data,
1848 bool nonblocking,
1849 bool *done)
1850 {
1851 CURLcode result;
1852 struct ssl_connect_data *connssl = cf->ctx;
1853 curl_socket_t sockfd = Curl_conn_cf_get_socket(cf, data);
1854
1855 /* check if the connection has already been established */
1856 if(ssl_connection_complete == connssl->state) {
1857 *done = TRUE;
1858 return CURLE_OK;
1859 }
1860
1861 if(ssl_connect_1 == connssl->connecting_state) {
1862 /* Find out how much more time we are allowed */
1863 const timediff_t timeout_ms = Curl_timeleft(data, NULL, TRUE);
1864
1865 if(timeout_ms < 0) {
1866 /* no need to continue if time already is up */
1867 failf(data, "SSL connection timeout");
1868 return CURLE_OPERATION_TIMEDOUT;
1869 }
1870
1871 result = wolfssl_connect_step1(cf, data);
1872 if(result)
1873 return result;
1874 }
1875
1876 while(ssl_connect_2 == connssl->connecting_state) {
1877
1878 /* check allowed time left */
1879 const timediff_t timeout_ms = Curl_timeleft(data, NULL, TRUE);
1880
1881 if(timeout_ms < 0) {
1882 /* no need to continue if time already is up */
1883 failf(data, "SSL connection timeout");
1884 return CURLE_OPERATION_TIMEDOUT;
1885 }
1886
1887 /* if ssl is expecting something, check if it is available. */
1888 if(connssl->io_need) {
1889 curl_socket_t writefd = (connssl->io_need & CURL_SSL_IO_NEED_SEND) ?
1890 sockfd : CURL_SOCKET_BAD;
1891 curl_socket_t readfd = (connssl->io_need & CURL_SSL_IO_NEED_RECV) ?
1892 sockfd : CURL_SOCKET_BAD;
1893 int what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd,
1894 nonblocking ? 0 : timeout_ms);
1895 if(what < 0) {
1896 /* fatal error */
1897 failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
1898 return CURLE_SSL_CONNECT_ERROR;
1899 }
1900 else if(0 == what) {
1901 if(nonblocking) {
1902 *done = FALSE;
1903 return CURLE_OK;
1904 }
1905 else {
1906 /* timeout */
1907 failf(data, "SSL connection timeout");
1908 return CURLE_OPERATION_TIMEDOUT;
1909 }
1910 }
1911 /* socket is readable or writable */
1912 }
1913
1914 /* Run transaction, and return to the caller if it failed or if
1915 * this connection is part of a multi handle and this loop would
1916 * execute again. This permits the owner of a multi handle to
1917 * abort a connection attempt before step2 has completed while
1918 * ensuring that a client using select() or epoll() will always
1919 * have a valid fdset to wait on.
1920 */
1921 result = wolfssl_connect_step2(cf, data);
1922 if(result || (nonblocking && (ssl_connect_2 == connssl->connecting_state)))
1923 return result;
1924 } /* repeat step2 until all transactions are done. */
1925
1926 if(ssl_connect_3 == connssl->connecting_state) {
1927 /* In other backends, this is where we verify the certificate, but
1928 * wolfSSL already does that as part of the handshake. */
1929 connssl->connecting_state = ssl_connect_done;
1930 }
1931
1932 if(ssl_connect_done == connssl->connecting_state) {
1933 connssl->state = ssl_connection_complete;
1934 *done = TRUE;
1935 }
1936 else
1937 *done = FALSE;
1938
1939 /* Reset our connect state machine */
1940 connssl->connecting_state = ssl_connect_1;
1941
1942 return CURLE_OK;
1943 }
1944
1945
wolfssl_connect_nonblocking(struct Curl_cfilter * cf,struct Curl_easy * data,bool * done)1946 static CURLcode wolfssl_connect_nonblocking(struct Curl_cfilter *cf,
1947 struct Curl_easy *data,
1948 bool *done)
1949 {
1950 return wolfssl_connect_common(cf, data, TRUE, done);
1951 }
1952
1953
wolfssl_connect(struct Curl_cfilter * cf,struct Curl_easy * data)1954 static CURLcode wolfssl_connect(struct Curl_cfilter *cf,
1955 struct Curl_easy *data)
1956 {
1957 CURLcode result;
1958 bool done = FALSE;
1959
1960 result = wolfssl_connect_common(cf, data, FALSE, &done);
1961 if(result)
1962 return result;
1963
1964 DEBUGASSERT(done);
1965
1966 return CURLE_OK;
1967 }
1968
wolfssl_random(struct Curl_easy * data,unsigned char * entropy,size_t length)1969 static CURLcode wolfssl_random(struct Curl_easy *data,
1970 unsigned char *entropy, size_t length)
1971 {
1972 WC_RNG rng;
1973 (void)data;
1974 if(wc_InitRng(&rng))
1975 return CURLE_FAILED_INIT;
1976 if(length > UINT_MAX)
1977 return CURLE_FAILED_INIT;
1978 if(wc_RNG_GenerateBlock(&rng, entropy, (unsigned)length))
1979 return CURLE_FAILED_INIT;
1980 if(wc_FreeRng(&rng))
1981 return CURLE_FAILED_INIT;
1982 return CURLE_OK;
1983 }
1984
wolfssl_sha256sum(const unsigned char * tmp,size_t tmplen,unsigned char * sha256sum,size_t unused)1985 static CURLcode wolfssl_sha256sum(const unsigned char *tmp, /* input */
1986 size_t tmplen,
1987 unsigned char *sha256sum /* output */,
1988 size_t unused)
1989 {
1990 wc_Sha256 SHA256pw;
1991 (void)unused;
1992 if(wc_InitSha256(&SHA256pw))
1993 return CURLE_FAILED_INIT;
1994 wc_Sha256Update(&SHA256pw, tmp, (word32)tmplen);
1995 wc_Sha256Final(&SHA256pw, sha256sum);
1996 return CURLE_OK;
1997 }
1998
wolfssl_get_internals(struct ssl_connect_data * connssl,CURLINFO info UNUSED_PARAM)1999 static void *wolfssl_get_internals(struct ssl_connect_data *connssl,
2000 CURLINFO info UNUSED_PARAM)
2001 {
2002 struct wolfssl_ctx *backend =
2003 (struct wolfssl_ctx *)connssl->backend;
2004 (void)info;
2005 DEBUGASSERT(backend);
2006 return backend->handle;
2007 }
2008
2009 const struct Curl_ssl Curl_ssl_wolfssl = {
2010 { CURLSSLBACKEND_WOLFSSL, "wolfssl" }, /* info */
2011
2012 #ifdef KEEP_PEER_CERT
2013 SSLSUPP_PINNEDPUBKEY |
2014 #endif
2015 #ifdef USE_BIO_CHAIN
2016 SSLSUPP_HTTPS_PROXY |
2017 #endif
2018 SSLSUPP_CA_PATH |
2019 SSLSUPP_CAINFO_BLOB |
2020 #ifdef USE_ECH_WOLFSSL
2021 SSLSUPP_ECH |
2022 #endif
2023 SSLSUPP_SSL_CTX |
2024 #ifdef WOLFSSL_TLS13
2025 SSLSUPP_TLS13_CIPHERSUITES |
2026 #endif
2027 SSLSUPP_CA_CACHE |
2028 SSLSUPP_CIPHER_LIST,
2029
2030 sizeof(struct wolfssl_ctx),
2031
2032 wolfssl_init, /* init */
2033 wolfssl_cleanup, /* cleanup */
2034 Curl_wssl_version, /* version */
2035 wolfssl_shutdown, /* shutdown */
2036 wolfssl_data_pending, /* data_pending */
2037 wolfssl_random, /* random */
2038 NULL, /* cert_status_request */
2039 wolfssl_connect, /* connect */
2040 wolfssl_connect_nonblocking, /* connect_nonblocking */
2041 Curl_ssl_adjust_pollset, /* adjust_pollset */
2042 wolfssl_get_internals, /* get_internals */
2043 wolfssl_close, /* close_one */
2044 NULL, /* close_all */
2045 NULL, /* set_engine */
2046 NULL, /* set_engine_default */
2047 NULL, /* engines_list */
2048 NULL, /* false_start */
2049 wolfssl_sha256sum, /* sha256sum */
2050 wolfssl_recv, /* recv decrypted data */
2051 wolfssl_send, /* send data to encrypt */
2052 NULL, /* get_channel_binding */
2053 };
2054
2055 #endif
2056