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, 0,
435 wolfSSL_SESSION_get_timeout(session),
436 &sc_session);
437 sdata = NULL; /* took ownership of sdata */
438 if(!result) {
439 result = Curl_ssl_scache_put(cf, data, ssl_peer_key, sc_session);
440 /* took ownership of `sc_session` */
441 }
442
443 out:
444 free(sdata);
445 return result;
446 }
447
wssl_vtls_new_session_cb(WOLFSSL * ssl,WOLFSSL_SESSION * session)448 static int wssl_vtls_new_session_cb(WOLFSSL *ssl, WOLFSSL_SESSION *session)
449 {
450 struct Curl_cfilter *cf;
451
452 cf = (struct Curl_cfilter*)wolfSSL_get_app_data(ssl);
453 DEBUGASSERT(cf != NULL);
454 if(cf && session) {
455 struct ssl_connect_data *connssl = cf->ctx;
456 struct Curl_easy *data = CF_DATA_CURRENT(cf);
457 DEBUGASSERT(connssl);
458 DEBUGASSERT(data);
459 if(connssl && data) {
460 (void)Curl_wssl_cache_session(cf, data, connssl->peer.scache_key,
461 session, wolfSSL_version(ssl),
462 connssl->negotiated.alpn);
463 }
464 }
465 return 0;
466 }
467
Curl_wssl_setup_session(struct Curl_cfilter * cf,struct Curl_easy * data,struct wolfssl_ctx * wss,const char * ssl_peer_key)468 CURLcode Curl_wssl_setup_session(struct Curl_cfilter *cf,
469 struct Curl_easy *data,
470 struct wolfssl_ctx *wss,
471 const char *ssl_peer_key)
472 {
473 struct Curl_ssl_session *sc_session = NULL;
474 CURLcode result;
475
476 result = Curl_ssl_scache_take(cf, data, ssl_peer_key, &sc_session);
477 if(!result && sc_session && sc_session->sdata && sc_session->sdata_len) {
478 WOLFSSL_SESSION *session;
479 /* wolfSSL changes the passed pointer for whatever reasons, yikes */
480 const unsigned char *sdata = sc_session->sdata;
481 session = wolfSSL_d2i_SSL_SESSION(NULL, &sdata,
482 (long)sc_session->sdata_len);
483 if(session) {
484 int ret = wolfSSL_set_session(wss->handle, session);
485 if(ret != WOLFSSL_SUCCESS) {
486 Curl_ssl_session_destroy(sc_session);
487 sc_session = NULL;
488 infof(data, "cached session not accepted (%d), "
489 "removing from cache", ret);
490 }
491 else
492 infof(data, "SSL reusing session ID");
493 wolfSSL_SESSION_free(session);
494 }
495 else {
496 failf(data, "could not decode previous session");
497 }
498 }
499 Curl_ssl_scache_return(cf, data, ssl_peer_key, sc_session);
500 return result;
501 }
502
wssl_populate_x509_store(struct Curl_cfilter * cf,struct Curl_easy * data,WOLFSSL_X509_STORE * store,struct wolfssl_ctx * wssl)503 static CURLcode wssl_populate_x509_store(struct Curl_cfilter *cf,
504 struct Curl_easy *data,
505 WOLFSSL_X509_STORE *store,
506 struct wolfssl_ctx *wssl)
507 {
508 struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
509 const struct curl_blob *ca_info_blob = conn_config->ca_info_blob;
510 const char * const ssl_cafile =
511 /* CURLOPT_CAINFO_BLOB overrides CURLOPT_CAINFO */
512 (ca_info_blob ? NULL : conn_config->CAfile);
513 const char * const ssl_capath = conn_config->CApath;
514 struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
515 bool imported_native_ca = FALSE;
516
517 #if !defined(NO_FILESYSTEM) && defined(WOLFSSL_SYS_CA_CERTS)
518 /* load native CA certificates */
519 if(ssl_config->native_ca_store) {
520 if(wolfSSL_CTX_load_system_CA_certs(wssl->ctx) != WOLFSSL_SUCCESS) {
521 infof(data, "error importing native CA store, continuing anyway");
522 }
523 else {
524 imported_native_ca = TRUE;
525 infof(data, "successfully imported native CA store");
526 wssl->x509_store_setup = TRUE;
527 }
528 }
529 #endif /* !NO_FILESYSTEM */
530
531 /* load certificate blob */
532 if(ca_info_blob) {
533 if(wolfSSL_CTX_load_verify_buffer(wssl->ctx, ca_info_blob->data,
534 (long)ca_info_blob->len,
535 WOLFSSL_FILETYPE_PEM) !=
536 WOLFSSL_SUCCESS) {
537 if(imported_native_ca) {
538 infof(data, "error importing CA certificate blob, continuing anyway");
539 }
540 else {
541 failf(data, "error importing CA certificate blob");
542 return CURLE_SSL_CACERT_BADFILE;
543 }
544 }
545 else {
546 infof(data, "successfully imported CA certificate blob");
547 wssl->x509_store_setup = TRUE;
548 }
549 }
550
551 #ifndef NO_FILESYSTEM
552 /* load trusted cacert from file if not blob */
553
554 CURL_TRC_CF(data, cf, "wssl_populate_x509_store, path=%s, blob=%d",
555 ssl_cafile ? ssl_cafile : "none", !!ca_info_blob);
556 if(!store)
557 return CURLE_OUT_OF_MEMORY;
558
559 if((ssl_cafile || ssl_capath) && (!wssl->x509_store_setup)) {
560 int rc =
561 wolfSSL_CTX_load_verify_locations_ex(wssl->ctx,
562 ssl_cafile,
563 ssl_capath,
564 WOLFSSL_LOAD_FLAG_IGNORE_ERR);
565 if(WOLFSSL_SUCCESS != rc) {
566 if(conn_config->verifypeer) {
567 /* Fail if we insist on successfully verifying the server. */
568 failf(data, "error setting certificate verify locations:"
569 " CAfile: %s CApath: %s",
570 ssl_cafile ? ssl_cafile : "none",
571 ssl_capath ? ssl_capath : "none");
572 return CURLE_SSL_CACERT_BADFILE;
573 }
574 else {
575 /* Just continue with a warning if no strict certificate
576 verification is required. */
577 infof(data, "error setting certificate verify locations,"
578 " continuing anyway:");
579 }
580 }
581 else {
582 /* Everything is fine. */
583 infof(data, "successfully set certificate verify locations:");
584 }
585 infof(data, " CAfile: %s", ssl_cafile ? ssl_cafile : "none");
586 infof(data, " CApath: %s", ssl_capath ? ssl_capath : "none");
587 }
588 #endif
589 (void)store;
590 wssl->x509_store_setup = TRUE;
591 return CURLE_OK;
592 }
593
594 /* key to use at `multi->proto_hash` */
595 #define MPROTO_WSSL_X509_KEY "tls:wssl:x509:share"
596
597 struct wssl_x509_share {
598 char *CAfile; /* CAfile path used to generate X509 store */
599 WOLFSSL_X509_STORE *store; /* cached X509 store or NULL if none */
600 struct curltime time; /* when the cached store was created */
601 };
602
wssl_x509_share_free(void * key,size_t key_len,void * p)603 static void wssl_x509_share_free(void *key, size_t key_len, void *p)
604 {
605 struct wssl_x509_share *share = p;
606 DEBUGASSERT(key_len == (sizeof(MPROTO_WSSL_X509_KEY)-1));
607 DEBUGASSERT(!memcmp(MPROTO_WSSL_X509_KEY, key, key_len));
608 (void)key;
609 (void)key_len;
610 if(share->store) {
611 wolfSSL_X509_STORE_free(share->store);
612 }
613 free(share->CAfile);
614 free(share);
615 }
616
617 static bool
wssl_cached_x509_store_expired(const struct Curl_easy * data,const struct wssl_x509_share * mb)618 wssl_cached_x509_store_expired(const struct Curl_easy *data,
619 const struct wssl_x509_share *mb)
620 {
621 const struct ssl_general_config *cfg = &data->set.general_ssl;
622 struct curltime now = Curl_now();
623 timediff_t elapsed_ms = Curl_timediff(now, mb->time);
624 timediff_t timeout_ms = cfg->ca_cache_timeout * (timediff_t)1000;
625
626 if(timeout_ms < 0)
627 return FALSE;
628
629 return elapsed_ms >= timeout_ms;
630 }
631
632 static bool
wssl_cached_x509_store_different(struct Curl_cfilter * cf,const struct wssl_x509_share * mb)633 wssl_cached_x509_store_different(struct Curl_cfilter *cf,
634 const struct wssl_x509_share *mb)
635 {
636 struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
637 if(!mb->CAfile || !conn_config->CAfile)
638 return mb->CAfile != conn_config->CAfile;
639
640 return strcmp(mb->CAfile, conn_config->CAfile);
641 }
642
wssl_get_cached_x509_store(struct Curl_cfilter * cf,const struct Curl_easy * data)643 static WOLFSSL_X509_STORE *wssl_get_cached_x509_store(struct Curl_cfilter *cf,
644 const struct Curl_easy *data)
645 {
646 struct Curl_multi *multi = data->multi;
647 struct wssl_x509_share *share;
648 WOLFSSL_X509_STORE *store = NULL;
649
650 DEBUGASSERT(multi);
651 share = multi ? Curl_hash_pick(&multi->proto_hash,
652 (void *)MPROTO_WSSL_X509_KEY,
653 sizeof(MPROTO_WSSL_X509_KEY)-1) : NULL;
654 if(share && share->store &&
655 !wssl_cached_x509_store_expired(data, share) &&
656 !wssl_cached_x509_store_different(cf, share)) {
657 store = share->store;
658 }
659
660 return store;
661 }
662
wssl_set_cached_x509_store(struct Curl_cfilter * cf,const struct Curl_easy * data,WOLFSSL_X509_STORE * store)663 static void wssl_set_cached_x509_store(struct Curl_cfilter *cf,
664 const struct Curl_easy *data,
665 WOLFSSL_X509_STORE *store)
666 {
667 struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
668 struct Curl_multi *multi = data->multi;
669 struct wssl_x509_share *share;
670
671 DEBUGASSERT(multi);
672 if(!multi)
673 return;
674 share = Curl_hash_pick(&multi->proto_hash,
675 (void *)MPROTO_WSSL_X509_KEY,
676 sizeof(MPROTO_WSSL_X509_KEY)-1);
677
678 if(!share) {
679 share = calloc(1, sizeof(*share));
680 if(!share)
681 return;
682 if(!Curl_hash_add2(&multi->proto_hash,
683 (void *)MPROTO_WSSL_X509_KEY,
684 sizeof(MPROTO_WSSL_X509_KEY)-1,
685 share, wssl_x509_share_free)) {
686 free(share);
687 return;
688 }
689 }
690
691 if(wolfSSL_X509_STORE_up_ref(store)) {
692 char *CAfile = NULL;
693
694 if(conn_config->CAfile) {
695 CAfile = strdup(conn_config->CAfile);
696 if(!CAfile) {
697 wolfSSL_X509_STORE_free(store);
698 return;
699 }
700 }
701
702 if(share->store) {
703 wolfSSL_X509_STORE_free(share->store);
704 free(share->CAfile);
705 }
706
707 share->time = Curl_now();
708 share->store = store;
709 share->CAfile = CAfile;
710 }
711 }
712
Curl_wssl_setup_x509_store(struct Curl_cfilter * cf,struct Curl_easy * data,struct wolfssl_ctx * wssl)713 CURLcode Curl_wssl_setup_x509_store(struct Curl_cfilter *cf,
714 struct Curl_easy *data,
715 struct wolfssl_ctx *wssl)
716 {
717 struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
718 struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
719 CURLcode result = CURLE_OK;
720 WOLFSSL_X509_STORE *cached_store;
721 bool cache_criteria_met;
722
723 /* Consider the X509 store cacheable if it comes exclusively from a CAfile,
724 or no source is provided and we are falling back to wolfSSL's built-in
725 default. */
726 cache_criteria_met = (data->set.general_ssl.ca_cache_timeout != 0) &&
727 conn_config->verifypeer &&
728 !conn_config->CApath &&
729 !conn_config->ca_info_blob &&
730 !ssl_config->primary.CRLfile &&
731 !ssl_config->native_ca_store;
732
733 cached_store = cache_criteria_met ? wssl_get_cached_x509_store(cf, data)
734 : NULL;
735 if(cached_store && wolfSSL_CTX_get_cert_store(wssl->ctx) == cached_store) {
736 /* The cached store is already in use, do nothing. */
737 }
738 else if(cached_store && wolfSSL_X509_STORE_up_ref(cached_store)) {
739 wolfSSL_CTX_set_cert_store(wssl->ctx, cached_store);
740 }
741 else if(cache_criteria_met) {
742 /* wolfSSL's initial store in CTX is not shareable by default.
743 * Make a new one, suitable for adding to the cache. See #14278 */
744 WOLFSSL_X509_STORE *store = wolfSSL_X509_STORE_new();
745 if(!store) {
746 failf(data, "SSL: could not create a X509 store");
747 return CURLE_OUT_OF_MEMORY;
748 }
749 wolfSSL_CTX_set_cert_store(wssl->ctx, store);
750
751 result = wssl_populate_x509_store(cf, data, store, wssl);
752 if(!result) {
753 wssl_set_cached_x509_store(cf, data, store);
754 }
755 }
756 else {
757 /* We never share the CTX's store, use it. */
758 WOLFSSL_X509_STORE *store = wolfSSL_CTX_get_cert_store(wssl->ctx);
759 result = wssl_populate_x509_store(cf, data, store, wssl);
760 }
761
762 return result;
763 }
764
765 #ifdef WOLFSSL_TLS13
766 static CURLcode
wssl_add_default_ciphers(bool tls13,struct dynbuf * buf)767 wssl_add_default_ciphers(bool tls13, struct dynbuf *buf)
768 {
769 int i;
770 char *str;
771
772 for(i = 0; (str = wolfSSL_get_cipher_list(i)); i++) {
773 size_t n;
774 if((strncmp(str, "TLS13", 5) == 0) != tls13)
775 continue;
776
777 /* if there already is data in the string, add colon separator */
778 if(Curl_dyn_len(buf)) {
779 CURLcode result = Curl_dyn_addn(buf, ":", 1);
780 if(result)
781 return result;
782 }
783
784 n = strlen(str);
785 if(Curl_dyn_addn(buf, str, n))
786 return CURLE_OUT_OF_MEMORY;
787 }
788
789 return CURLE_OK;
790 }
791 #endif
792
793 /* 4.2.0 (2019) */
794 #if LIBWOLFSSL_VERSION_HEX < 0x04002000 || !defined(OPENSSL_EXTRA)
795 static int
wssl_legacy_CTX_set_min_proto_version(WOLFSSL_CTX * ctx,int version)796 wssl_legacy_CTX_set_min_proto_version(WOLFSSL_CTX* ctx, int version)
797 {
798 int res;
799 switch(version) {
800 default:
801 case TLS1_VERSION:
802 res = wolfSSL_CTX_SetMinVersion(ctx, WOLFSSL_TLSV1);
803 if(res == WOLFSSL_SUCCESS)
804 return res;
805 FALLTHROUGH();
806 case TLS1_1_VERSION:
807 res = wolfSSL_CTX_SetMinVersion(ctx, WOLFSSL_TLSV1_1);
808 if(res == WOLFSSL_SUCCESS)
809 return res;
810 FALLTHROUGH();
811 case TLS1_2_VERSION:
812 res = wolfSSL_CTX_SetMinVersion(ctx, WOLFSSL_TLSV1_2);
813 #ifdef WOLFSSL_TLS13
814 if(res == WOLFSSL_SUCCESS)
815 return res;
816 FALLTHROUGH();
817 case TLS1_3_VERSION:
818 res = wolfSSL_CTX_SetMinVersion(ctx, WOLFSSL_TLSV1_3);
819 #endif
820 }
821 return res;
822 }
823 static int
wssl_legacy_CTX_set_max_proto_version(WOLFSSL_CTX * ctx,int version)824 wssl_legacy_CTX_set_max_proto_version(WOLFSSL_CTX* ctx, int version)
825 {
826 (void) ctx, (void) version;
827 return WOLFSSL_NOT_IMPLEMENTED;
828 }
829 #define wolfSSL_CTX_set_min_proto_version wssl_legacy_CTX_set_min_proto_version
830 #define wolfSSL_CTX_set_max_proto_version wssl_legacy_CTX_set_max_proto_version
831 #endif
832
833 /*
834 * This function loads all the client/CA certificates and CRLs. Setup the TLS
835 * layer and do all necessary magic.
836 */
837 static CURLcode
wolfssl_connect_step1(struct Curl_cfilter * cf,struct Curl_easy * data)838 wolfssl_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
839 {
840 int res;
841 char *curves;
842 struct ssl_connect_data *connssl = cf->ctx;
843 struct wolfssl_ctx *backend =
844 (struct wolfssl_ctx *)connssl->backend;
845 struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
846 const struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
847 WOLFSSL_METHOD* req_method = NULL;
848 #ifdef WOLFSSL_HAVE_KYBER
849 word16 pqkem = 0;
850 size_t idx = 0;
851 #endif
852
853 DEBUGASSERT(backend);
854
855 if(connssl->state == ssl_connection_complete)
856 return CURLE_OK;
857
858 #if LIBWOLFSSL_VERSION_HEX < 0x04002000 /* 4.2.0 (2019) */
859 req_method = wolfSSLv23_client_method();
860 #else
861 req_method = wolfTLS_client_method();
862 #endif
863 if(!req_method) {
864 failf(data, "wolfSSL: could not create a client method");
865 return CURLE_OUT_OF_MEMORY;
866 }
867
868 if(backend->ctx)
869 wolfSSL_CTX_free(backend->ctx);
870
871 backend->ctx = wolfSSL_CTX_new(req_method);
872 if(!backend->ctx) {
873 failf(data, "wolfSSL: could not create a context");
874 return CURLE_OUT_OF_MEMORY;
875 }
876
877 switch(conn_config->version) {
878 case CURL_SSLVERSION_DEFAULT:
879 case CURL_SSLVERSION_TLSv1:
880 case CURL_SSLVERSION_TLSv1_0:
881 res = wolfSSL_CTX_set_min_proto_version(backend->ctx, TLS1_VERSION);
882 break;
883 case CURL_SSLVERSION_TLSv1_1:
884 res = wolfSSL_CTX_set_min_proto_version(backend->ctx, TLS1_1_VERSION);
885 break;
886 case CURL_SSLVERSION_TLSv1_2:
887 res = wolfSSL_CTX_set_min_proto_version(backend->ctx, TLS1_2_VERSION);
888 break;
889 #ifdef WOLFSSL_TLS13
890 case CURL_SSLVERSION_TLSv1_3:
891 res = wolfSSL_CTX_set_min_proto_version(backend->ctx, TLS1_3_VERSION);
892 break;
893 #endif
894 default:
895 failf(data, "wolfSSL: unsupported minimum TLS version value");
896 return CURLE_SSL_CONNECT_ERROR;
897 }
898 if(res != WOLFSSL_SUCCESS) {
899 failf(data, "wolfSSL: failed set the minimum TLS version");
900 return CURLE_SSL_CONNECT_ERROR;
901 }
902
903 switch(conn_config->version_max) {
904 #ifdef WOLFSSL_TLS13
905 case CURL_SSLVERSION_MAX_TLSv1_3:
906 res = wolfSSL_CTX_set_max_proto_version(backend->ctx, TLS1_3_VERSION);
907 break;
908 #endif
909 case CURL_SSLVERSION_MAX_TLSv1_2:
910 res = wolfSSL_CTX_set_max_proto_version(backend->ctx, TLS1_2_VERSION);
911 break;
912 case CURL_SSLVERSION_MAX_TLSv1_1:
913 res = wolfSSL_CTX_set_max_proto_version(backend->ctx, TLS1_1_VERSION);
914 break;
915 case CURL_SSLVERSION_MAX_TLSv1_0:
916 res = wolfSSL_CTX_set_max_proto_version(backend->ctx, TLS1_VERSION);
917 break;
918 case CURL_SSLVERSION_MAX_DEFAULT:
919 case CURL_SSLVERSION_MAX_NONE:
920 res = WOLFSSL_SUCCESS;
921 break;
922 default:
923 failf(data, "wolfSSL: unsupported maximum TLS version value");
924 return CURLE_SSL_CONNECT_ERROR;
925 }
926 if(res != WOLFSSL_SUCCESS) {
927 failf(data, "wolfSSL: failed set the maximum TLS version");
928 return CURLE_SSL_CONNECT_ERROR;
929 }
930
931 #ifndef WOLFSSL_TLS13
932 {
933 char *ciphers = conn_config->cipher_list;
934 if(ciphers) {
935 if(!SSL_CTX_set_cipher_list(backend->ctx, ciphers)) {
936 failf(data, "failed setting cipher list: %s", ciphers);
937 return CURLE_SSL_CIPHER;
938 }
939 infof(data, "Cipher selection: %s", ciphers);
940 }
941 }
942 #else
943 #define MAX_CIPHER_LEN 4096
944 if(conn_config->cipher_list || conn_config->cipher_list13) {
945 const char *ciphers12 = conn_config->cipher_list;
946 const char *ciphers13 = conn_config->cipher_list13;
947 struct dynbuf c;
948 CURLcode result;
949 Curl_dyn_init(&c, MAX_CIPHER_LEN);
950
951 if(ciphers13)
952 result = Curl_dyn_add(&c, ciphers13);
953 else
954 result = wssl_add_default_ciphers(TRUE, &c);
955
956 if(!result) {
957 if(ciphers12) {
958 if(Curl_dyn_len(&c))
959 result = Curl_dyn_addn(&c, ":", 1);
960 if(!result)
961 result = Curl_dyn_add(&c, ciphers12);
962 }
963 else
964 result = wssl_add_default_ciphers(FALSE, &c);
965 }
966 if(result)
967 return result;
968
969 if(!wolfSSL_CTX_set_cipher_list(backend->ctx, Curl_dyn_ptr(&c))) {
970 failf(data, "failed setting cipher list: %s", Curl_dyn_ptr(&c));
971 Curl_dyn_free(&c);
972 return CURLE_SSL_CIPHER;
973 }
974 infof(data, "Cipher selection: %s", Curl_dyn_ptr(&c));
975 Curl_dyn_free(&c);
976 }
977 #endif
978
979 curves = conn_config->curves;
980 if(curves) {
981
982 #ifdef WOLFSSL_HAVE_KYBER
983 for(idx = 0; gnm[idx].name != NULL; idx++) {
984 if(strncmp(curves, gnm[idx].name, strlen(gnm[idx].name)) == 0) {
985 pqkem = gnm[idx].group;
986 break;
987 }
988 }
989
990 if(pqkem == 0)
991 #endif
992 {
993 if(!wolfSSL_CTX_set1_curves_list(backend->ctx, curves)) {
994 failf(data, "failed setting curves list: '%s'", curves);
995 return CURLE_SSL_CIPHER;
996 }
997 }
998 }
999
1000 /* Load the client certificate, and private key */
1001 #ifndef NO_FILESYSTEM
1002 if(ssl_config->primary.cert_blob || ssl_config->primary.clientcert) {
1003 const char *cert_file = ssl_config->primary.clientcert;
1004 const char *key_file = ssl_config->key;
1005 const struct curl_blob *cert_blob = ssl_config->primary.cert_blob;
1006 const struct curl_blob *key_blob = ssl_config->key_blob;
1007 int file_type = wolfssl_do_file_type(ssl_config->cert_type);
1008 int rc;
1009
1010 switch(file_type) {
1011 case WOLFSSL_FILETYPE_PEM:
1012 rc = cert_blob ?
1013 wolfSSL_CTX_use_certificate_chain_buffer(backend->ctx,
1014 cert_blob->data,
1015 (long)cert_blob->len) :
1016 wolfSSL_CTX_use_certificate_chain_file(backend->ctx, cert_file);
1017 break;
1018 case WOLFSSL_FILETYPE_ASN1:
1019 rc = cert_blob ?
1020 wolfSSL_CTX_use_certificate_buffer(backend->ctx, cert_blob->data,
1021 (long)cert_blob->len, file_type) :
1022 wolfSSL_CTX_use_certificate_file(backend->ctx, cert_file, file_type);
1023 break;
1024 default:
1025 failf(data, "unknown cert type");
1026 return CURLE_BAD_FUNCTION_ARGUMENT;
1027 }
1028 if(rc != 1) {
1029 failf(data, "unable to use client certificate");
1030 return CURLE_SSL_CONNECT_ERROR;
1031 }
1032
1033 if(!key_blob && !key_file) {
1034 key_blob = cert_blob;
1035 key_file = cert_file;
1036 }
1037 else
1038 file_type = wolfssl_do_file_type(ssl_config->key_type);
1039
1040 rc = key_blob ?
1041 wolfSSL_CTX_use_PrivateKey_buffer(backend->ctx, key_blob->data,
1042 (long)key_blob->len, file_type) :
1043 wolfSSL_CTX_use_PrivateKey_file(backend->ctx, key_file, file_type);
1044 if(rc != 1) {
1045 failf(data, "unable to set private key");
1046 return CURLE_SSL_CONNECT_ERROR;
1047 }
1048 }
1049 #else /* NO_FILESYSTEM */
1050 if(ssl_config->primary.cert_blob) {
1051 const struct curl_blob *cert_blob = ssl_config->primary.cert_blob;
1052 const struct curl_blob *key_blob = ssl_config->key_blob;
1053 int file_type = wolfssl_do_file_type(ssl_config->cert_type);
1054 int rc;
1055
1056 switch(file_type) {
1057 case WOLFSSL_FILETYPE_PEM:
1058 rc = wolfSSL_CTX_use_certificate_chain_buffer(backend->ctx,
1059 cert_blob->data,
1060 (long)cert_blob->len);
1061 break;
1062 case WOLFSSL_FILETYPE_ASN1:
1063 rc = wolfSSL_CTX_use_certificate_buffer(backend->ctx, cert_blob->data,
1064 (long)cert_blob->len, file_type);
1065 break;
1066 default:
1067 failf(data, "unknown cert type");
1068 return CURLE_BAD_FUNCTION_ARGUMENT;
1069 }
1070 if(rc != 1) {
1071 failf(data, "unable to use client certificate");
1072 return CURLE_SSL_CONNECT_ERROR;
1073 }
1074
1075 if(!key_blob)
1076 key_blob = cert_blob;
1077 else
1078 file_type = wolfssl_do_file_type(ssl_config->key_type);
1079
1080 if(wolfSSL_CTX_use_PrivateKey_buffer(backend->ctx, key_blob->data,
1081 (long)key_blob->len,
1082 file_type) != 1) {
1083 failf(data, "unable to set private key");
1084 return CURLE_SSL_CONNECT_ERROR;
1085 }
1086 }
1087 #endif /* !NO_FILESYSTEM */
1088
1089 /* SSL always tries to verify the peer, this only says whether it should
1090 * fail to connect if the verification fails, or if it should continue
1091 * anyway. In the latter case the result of the verification is checked with
1092 * SSL_get_verify_result() below. */
1093 wolfSSL_CTX_set_verify(backend->ctx,
1094 conn_config->verifypeer ? WOLFSSL_VERIFY_PEER :
1095 WOLFSSL_VERIFY_NONE, NULL);
1096
1097 #ifdef HAVE_SNI
1098 if(connssl->peer.sni) {
1099 size_t sni_len = strlen(connssl->peer.sni);
1100 if((sni_len < USHRT_MAX)) {
1101 if(wolfSSL_CTX_UseSNI(backend->ctx, WOLFSSL_SNI_HOST_NAME,
1102 connssl->peer.sni,
1103 (unsigned short)sni_len) != 1) {
1104 failf(data, "Failed to set SNI");
1105 return CURLE_SSL_CONNECT_ERROR;
1106 }
1107 }
1108 }
1109 #endif
1110
1111 /* give application a chance to interfere with SSL set up. */
1112 if(data->set.ssl.fsslctx) {
1113 CURLcode result;
1114 if(!backend->x509_store_setup) {
1115 result = Curl_wssl_setup_x509_store(cf, data, backend);
1116 if(result)
1117 return result;
1118 }
1119 result = (*data->set.ssl.fsslctx)(data, backend->ctx,
1120 data->set.ssl.fsslctxp);
1121 if(result) {
1122 failf(data, "error signaled by ssl ctx callback");
1123 return result;
1124 }
1125 }
1126 #ifdef NO_FILESYSTEM
1127 else if(conn_config->verifypeer) {
1128 failf(data, "SSL: Certificates cannot be loaded because wolfSSL was built"
1129 " with \"no filesystem\". Either disable peer verification"
1130 " (insecure) or if you are building an application with libcurl you"
1131 " can load certificates via CURLOPT_SSL_CTX_FUNCTION.");
1132 return CURLE_SSL_CONNECT_ERROR;
1133 }
1134 #endif
1135
1136 /* Let's make an SSL structure */
1137 if(backend->handle)
1138 wolfSSL_free(backend->handle);
1139 backend->handle = wolfSSL_new(backend->ctx);
1140 if(!backend->handle) {
1141 failf(data, "SSL: could not create a handle");
1142 return CURLE_OUT_OF_MEMORY;
1143 }
1144
1145 #ifdef WOLFSSL_HAVE_KYBER
1146 if(pqkem) {
1147 if(wolfSSL_UseKeyShare(backend->handle, pqkem) != WOLFSSL_SUCCESS) {
1148 failf(data, "unable to use PQ KEM");
1149 }
1150 }
1151 #endif
1152
1153 #ifdef HAVE_ALPN
1154 if(connssl->alpn) {
1155 struct alpn_proto_buf proto;
1156 CURLcode result;
1157
1158 result = Curl_alpn_to_proto_str(&proto, connssl->alpn);
1159 if(result ||
1160 wolfSSL_UseALPN(backend->handle,
1161 (char *)proto.data, (unsigned int)proto.len,
1162 WOLFSSL_ALPN_CONTINUE_ON_MISMATCH) != WOLFSSL_SUCCESS) {
1163 failf(data, "SSL: failed setting ALPN protocols");
1164 return CURLE_SSL_CONNECT_ERROR;
1165 }
1166 infof(data, VTLS_INFOF_ALPN_OFFER_1STR, proto.data);
1167 }
1168 #endif /* HAVE_ALPN */
1169
1170 #ifdef OPENSSL_EXTRA
1171 if(Curl_tls_keylog_enabled()) {
1172 /* Ensure the Client Random is preserved. */
1173 wolfSSL_KeepArrays(backend->handle);
1174 #if defined(HAVE_SECRET_CALLBACK) && defined(WOLFSSL_TLS13)
1175 wolfSSL_set_tls13_secret_cb(backend->handle,
1176 wolfssl_tls13_secret_callback, NULL);
1177 #endif
1178 }
1179 #endif /* OPENSSL_EXTRA */
1180
1181 #ifdef HAVE_SECURE_RENEGOTIATION
1182 if(wolfSSL_UseSecureRenegotiation(backend->handle) != SSL_SUCCESS) {
1183 failf(data, "SSL: failed setting secure renegotiation");
1184 return CURLE_SSL_CONNECT_ERROR;
1185 }
1186 #endif /* HAVE_SECURE_RENEGOTIATION */
1187
1188 /* Check if there is a cached ID we can/should use here! */
1189 if(ssl_config->primary.cache_session) {
1190 /* Set session from cache if there is one */
1191 (void)Curl_wssl_setup_session(cf, data, backend, connssl->peer.scache_key);
1192 /* Register to get notified when a new session is received */
1193 wolfSSL_set_app_data(backend->handle, cf);
1194 wolfSSL_CTX_sess_set_new_cb(backend->ctx, wssl_vtls_new_session_cb);
1195 }
1196
1197 #ifdef USE_ECH_WOLFSSL
1198 if(ECH_ENABLED(data)) {
1199 int trying_ech_now = 0;
1200
1201 if(data->set.str[STRING_ECH_PUBLIC]) {
1202 infof(data, "ECH: outername not (yet) supported with wolfSSL");
1203 return CURLE_SSL_CONNECT_ERROR;
1204 }
1205 if(data->set.tls_ech == CURLECH_GREASE) {
1206 infof(data, "ECH: GREASE'd ECH not yet supported for wolfSSL");
1207 return CURLE_SSL_CONNECT_ERROR;
1208 }
1209 if(data->set.tls_ech & CURLECH_CLA_CFG
1210 && data->set.str[STRING_ECH_CONFIG]) {
1211 char *b64val = data->set.str[STRING_ECH_CONFIG];
1212 word32 b64len = 0;
1213
1214 b64len = (word32) strlen(b64val);
1215 if(b64len
1216 && wolfSSL_SetEchConfigsBase64(backend->handle, b64val, b64len)
1217 != WOLFSSL_SUCCESS) {
1218 if(data->set.tls_ech & CURLECH_HARD)
1219 return CURLE_SSL_CONNECT_ERROR;
1220 }
1221 else {
1222 trying_ech_now = 1;
1223 infof(data, "ECH: ECHConfig from command line");
1224 }
1225 }
1226 else {
1227 struct Curl_dns_entry *dns = NULL;
1228
1229 dns = Curl_fetch_addr(data, connssl->peer.hostname, connssl->peer.port);
1230 if(!dns) {
1231 infof(data, "ECH: requested but no DNS info available");
1232 if(data->set.tls_ech & CURLECH_HARD)
1233 return CURLE_SSL_CONNECT_ERROR;
1234 }
1235 else {
1236 struct Curl_https_rrinfo *rinfo = NULL;
1237
1238 rinfo = dns->hinfo;
1239 if(rinfo && rinfo->echconfiglist) {
1240 unsigned char *ecl = rinfo->echconfiglist;
1241 size_t elen = rinfo->echconfiglist_len;
1242
1243 infof(data, "ECH: ECHConfig from DoH HTTPS RR");
1244 if(wolfSSL_SetEchConfigs(backend->handle, ecl, (word32) elen) !=
1245 WOLFSSL_SUCCESS) {
1246 infof(data, "ECH: wolfSSL_SetEchConfigs failed");
1247 if(data->set.tls_ech & CURLECH_HARD)
1248 return CURLE_SSL_CONNECT_ERROR;
1249 }
1250 else {
1251 trying_ech_now = 1;
1252 infof(data, "ECH: imported ECHConfigList of length %ld", elen);
1253 }
1254 }
1255 else {
1256 infof(data, "ECH: requested but no ECHConfig available");
1257 if(data->set.tls_ech & CURLECH_HARD)
1258 return CURLE_SSL_CONNECT_ERROR;
1259 }
1260 Curl_resolv_unlink(data, &dns);
1261 }
1262 }
1263
1264 if(trying_ech_now && wolfSSL_set_min_proto_version(backend->handle,
1265 TLS1_3_VERSION) != 1) {
1266 infof(data, "ECH: cannot force TLSv1.3 [ERROR]");
1267 return CURLE_SSL_CONNECT_ERROR;
1268 }
1269
1270 }
1271 #endif /* USE_ECH_WOLFSSL */
1272
1273 #ifdef USE_BIO_CHAIN
1274 {
1275 WOLFSSL_BIO *bio;
1276
1277 bio = wolfSSL_BIO_new(wolfssl_bio_cf_method);
1278 if(!bio)
1279 return CURLE_OUT_OF_MEMORY;
1280
1281 wolfSSL_BIO_set_data(bio, cf);
1282 wolfSSL_set_bio(backend->handle, bio, bio);
1283 }
1284 #else /* USE_BIO_CHAIN */
1285 /* pass the raw socket into the SSL layer */
1286 if(!wolfSSL_set_fd(backend->handle,
1287 (int)Curl_conn_cf_get_socket(cf, data))) {
1288 failf(data, "SSL: SSL_set_fd failed");
1289 return CURLE_SSL_CONNECT_ERROR;
1290 }
1291 #endif /* !USE_BIO_CHAIN */
1292
1293 connssl->connecting_state = ssl_connect_2;
1294 return CURLE_OK;
1295 }
1296
1297
wolfssl_strerror(unsigned long error,char * buf,unsigned long size)1298 static char *wolfssl_strerror(unsigned long error, char *buf,
1299 unsigned long size)
1300 {
1301 DEBUGASSERT(size > 40);
1302 *buf = '\0';
1303
1304 wolfSSL_ERR_error_string_n(error, buf, size);
1305
1306 if(!*buf) {
1307 const char *msg = error ? "Unknown error" : "No error";
1308 /* the string fits because the assert above assures this */
1309 strcpy(buf, msg);
1310 }
1311
1312 return buf;
1313 }
1314
1315
1316 static CURLcode
wolfssl_connect_step2(struct Curl_cfilter * cf,struct Curl_easy * data)1317 wolfssl_connect_step2(struct Curl_cfilter *cf, struct Curl_easy *data)
1318 {
1319 int ret = -1;
1320 struct ssl_connect_data *connssl = cf->ctx;
1321 struct wolfssl_ctx *backend =
1322 (struct wolfssl_ctx *)connssl->backend;
1323 struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
1324 #ifndef CURL_DISABLE_PROXY
1325 const char * const pinnedpubkey = Curl_ssl_cf_is_proxy(cf) ?
1326 data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] :
1327 data->set.str[STRING_SSL_PINNEDPUBLICKEY];
1328 #else
1329 const char * const pinnedpubkey = data->set.str[STRING_SSL_PINNEDPUBLICKEY];
1330 #endif
1331
1332 DEBUGASSERT(backend);
1333
1334 wolfSSL_ERR_clear_error();
1335
1336 /* Enable RFC2818 checks */
1337 if(conn_config->verifyhost) {
1338 char *snihost = connssl->peer.sni ?
1339 connssl->peer.sni : connssl->peer.hostname;
1340 if(wolfSSL_check_domain_name(backend->handle, snihost) == WOLFSSL_FAILURE)
1341 return CURLE_SSL_CONNECT_ERROR;
1342 }
1343
1344 if(!backend->x509_store_setup) {
1345 /* After having send off the ClientHello, we prepare the x509
1346 * store to verify the coming certificate from the server */
1347 CURLcode result;
1348 result = Curl_wssl_setup_x509_store(cf, data, backend);
1349 if(result)
1350 return result;
1351 }
1352
1353 connssl->io_need = CURL_SSL_IO_NEED_NONE;
1354 ret = wolfSSL_connect(backend->handle);
1355
1356 #ifdef OPENSSL_EXTRA
1357 if(Curl_tls_keylog_enabled()) {
1358 /* If key logging is enabled, wait for the handshake to complete and then
1359 * proceed with logging secrets (for TLS 1.2 or older).
1360 *
1361 * During the handshake (ret==-1), wolfSSL_want_read() is true as it waits
1362 * for the server response. At that point the master secret is not yet
1363 * available, so we must not try to read it.
1364 * To log the secret on completion with a handshake failure, detect
1365 * completion via the observation that there is nothing to read or write.
1366 * Note that OpenSSL SSL_want_read() is always true here. If wolfSSL ever
1367 * changes, the worst case is that no key is logged on error.
1368 */
1369 if(ret == WOLFSSL_SUCCESS ||
1370 (!wolfSSL_want_read(backend->handle) &&
1371 !wolfSSL_want_write(backend->handle))) {
1372 wolfssl_log_tls12_secret(backend->handle);
1373 /* Client Random and master secrets are no longer needed, erase these.
1374 * Ignored while the handshake is still in progress. */
1375 wolfSSL_FreeArrays(backend->handle);
1376 }
1377 }
1378 #endif /* OPENSSL_EXTRA */
1379
1380 if(ret != 1) {
1381 int detail = wolfSSL_get_error(backend->handle, ret);
1382
1383 if(WOLFSSL_ERROR_WANT_READ == detail) {
1384 connssl->io_need = CURL_SSL_IO_NEED_RECV;
1385 return CURLE_OK;
1386 }
1387 else if(WOLFSSL_ERROR_WANT_WRITE == detail) {
1388 connssl->io_need = CURL_SSL_IO_NEED_SEND;
1389 return CURLE_OK;
1390 }
1391 /* There is no easy way to override only the CN matching.
1392 * This will enable the override of both mismatching SubjectAltNames
1393 * as also mismatching CN fields */
1394 else if(DOMAIN_NAME_MISMATCH == detail) {
1395 #if 1
1396 failf(data, " subject alt name(s) or common name do not match \"%s\"",
1397 connssl->peer.dispname);
1398 return CURLE_PEER_FAILED_VERIFICATION;
1399 #else
1400 /* When the wolfssl_check_domain_name() is used and you desire to
1401 * continue on a DOMAIN_NAME_MISMATCH, i.e. 'ssl_config.verifyhost
1402 * == 0', CyaSSL version 2.4.0 will fail with an INCOMPLETE_DATA
1403 * error. The only way to do this is currently to switch the
1404 * Wolfssl_check_domain_name() in and out based on the
1405 * 'ssl_config.verifyhost' value. */
1406 if(conn_config->verifyhost) {
1407 failf(data,
1408 " subject alt name(s) or common name do not match \"%s\"\n",
1409 connssl->dispname);
1410 return CURLE_PEER_FAILED_VERIFICATION;
1411 }
1412 else {
1413 infof(data,
1414 " subject alt name(s) and/or common name do not match \"%s\"",
1415 connssl->dispname);
1416 return CURLE_OK;
1417 }
1418 #endif
1419 }
1420 else if(ASN_NO_SIGNER_E == detail) {
1421 if(conn_config->verifypeer) {
1422 failf(data, " CA signer not available for verification");
1423 return CURLE_SSL_CACERT_BADFILE;
1424 }
1425 else {
1426 /* Just continue with a warning if no strict certificate
1427 verification is required. */
1428 infof(data, "CA signer not available for verification, "
1429 "continuing anyway");
1430 }
1431 }
1432 else if(ASN_AFTER_DATE_E == detail) {
1433 failf(data, "server verification failed: certificate has expired.");
1434 return CURLE_PEER_FAILED_VERIFICATION;
1435 }
1436 else if(ASN_BEFORE_DATE_E == detail) {
1437 failf(data, "server verification failed: certificate not valid yet.");
1438 return CURLE_PEER_FAILED_VERIFICATION;
1439 }
1440 #ifdef USE_ECH_WOLFSSL
1441 else if(-1 == detail) {
1442 /* try access a retry_config ECHConfigList for tracing */
1443 byte echConfigs[1000];
1444 word32 echConfigsLen = 1000;
1445 int rv = 0;
1446
1447 /* this currently does not produce the retry_configs */
1448 rv = wolfSSL_GetEchConfigs(backend->handle, echConfigs,
1449 &echConfigsLen);
1450 if(rv != WOLFSSL_SUCCESS) {
1451 infof(data, "Failed to get ECHConfigs");
1452 }
1453 else {
1454 char *b64str = NULL;
1455 size_t blen = 0;
1456
1457 rv = Curl_base64_encode((const char *)echConfigs, echConfigsLen,
1458 &b64str, &blen);
1459 if(!rv && b64str)
1460 infof(data, "ECH: (not yet) retry_configs %s", b64str);
1461 free(b64str);
1462 }
1463 }
1464 #endif
1465 else if(backend->io_result == CURLE_AGAIN) {
1466 return CURLE_OK;
1467 }
1468 else {
1469 char error_buffer[256];
1470 failf(data, "SSL_connect failed with error %d: %s", detail,
1471 wolfssl_strerror((unsigned long)detail, error_buffer,
1472 sizeof(error_buffer)));
1473 return CURLE_SSL_CONNECT_ERROR;
1474 }
1475 }
1476
1477 if(pinnedpubkey) {
1478 #ifdef KEEP_PEER_CERT
1479 WOLFSSL_X509 *x509;
1480 const char *x509_der;
1481 int x509_der_len;
1482 struct Curl_X509certificate x509_parsed;
1483 struct Curl_asn1Element *pubkey;
1484 CURLcode result;
1485
1486 x509 = wolfSSL_get_peer_certificate(backend->handle);
1487 if(!x509) {
1488 failf(data, "SSL: failed retrieving server certificate");
1489 return CURLE_SSL_PINNEDPUBKEYNOTMATCH;
1490 }
1491
1492 x509_der = (const char *)wolfSSL_X509_get_der(x509, &x509_der_len);
1493 if(!x509_der) {
1494 failf(data, "SSL: failed retrieving ASN.1 server certificate");
1495 return CURLE_SSL_PINNEDPUBKEYNOTMATCH;
1496 }
1497
1498 memset(&x509_parsed, 0, sizeof(x509_parsed));
1499 if(Curl_parseX509(&x509_parsed, x509_der, x509_der + x509_der_len))
1500 return CURLE_SSL_PINNEDPUBKEYNOTMATCH;
1501
1502 pubkey = &x509_parsed.subjectPublicKeyInfo;
1503 if(!pubkey->header || pubkey->end <= pubkey->header) {
1504 failf(data, "SSL: failed retrieving public key from server certificate");
1505 return CURLE_SSL_PINNEDPUBKEYNOTMATCH;
1506 }
1507
1508 result = Curl_pin_peer_pubkey(data,
1509 pinnedpubkey,
1510 (const unsigned char *)pubkey->header,
1511 (size_t)(pubkey->end - pubkey->header));
1512 wolfSSL_FreeX509(x509);
1513 if(result) {
1514 failf(data, "SSL: public key does not match pinned public key");
1515 return result;
1516 }
1517 #else
1518 failf(data, "Library lacks pinning support built-in");
1519 return CURLE_NOT_BUILT_IN;
1520 #endif
1521 }
1522
1523 #ifdef HAVE_ALPN
1524 if(connssl->alpn) {
1525 int rc;
1526 char *protocol = NULL;
1527 unsigned short protocol_len = 0;
1528
1529 rc = wolfSSL_ALPN_GetProtocol(backend->handle, &protocol, &protocol_len);
1530
1531 if(rc == WOLFSSL_SUCCESS) {
1532 Curl_alpn_set_negotiated(cf, data, connssl,
1533 (const unsigned char *)protocol, protocol_len);
1534 }
1535 else if(rc == WOLFSSL_ALPN_NOT_FOUND)
1536 Curl_alpn_set_negotiated(cf, data, connssl, NULL, 0);
1537 else {
1538 failf(data, "ALPN, failure getting protocol, error %d", rc);
1539 return CURLE_SSL_CONNECT_ERROR;
1540 }
1541 }
1542 #endif /* HAVE_ALPN */
1543
1544 connssl->connecting_state = ssl_connect_3;
1545 #if (LIBWOLFSSL_VERSION_HEX >= 0x03009010)
1546 infof(data, "SSL connection using %s / %s",
1547 wolfSSL_get_version(backend->handle),
1548 wolfSSL_get_cipher_name(backend->handle));
1549 #else
1550 infof(data, "SSL connected");
1551 #endif
1552
1553 return CURLE_OK;
1554 }
1555
wolfssl_send(struct Curl_cfilter * cf,struct Curl_easy * data,const void * mem,size_t len,CURLcode * curlcode)1556 static ssize_t wolfssl_send(struct Curl_cfilter *cf,
1557 struct Curl_easy *data,
1558 const void *mem,
1559 size_t len,
1560 CURLcode *curlcode)
1561 {
1562 struct ssl_connect_data *connssl = cf->ctx;
1563 struct wolfssl_ctx *backend =
1564 (struct wolfssl_ctx *)connssl->backend;
1565 int memlen = (len > (size_t)INT_MAX) ? INT_MAX : (int)len;
1566 int rc;
1567
1568 DEBUGASSERT(backend);
1569
1570 wolfSSL_ERR_clear_error();
1571
1572 rc = wolfSSL_write(backend->handle, mem, memlen);
1573 if(rc <= 0) {
1574 int err = wolfSSL_get_error(backend->handle, rc);
1575
1576 switch(err) {
1577 case WOLFSSL_ERROR_WANT_READ:
1578 case WOLFSSL_ERROR_WANT_WRITE:
1579 /* there is data pending, re-invoke SSL_write() */
1580 CURL_TRC_CF(data, cf, "wolfssl_send(len=%zu) -> AGAIN", len);
1581 *curlcode = CURLE_AGAIN;
1582 return -1;
1583 default:
1584 if(backend->io_result == CURLE_AGAIN) {
1585 CURL_TRC_CF(data, cf, "wolfssl_send(len=%zu) -> AGAIN", len);
1586 *curlcode = CURLE_AGAIN;
1587 return -1;
1588 }
1589 CURL_TRC_CF(data, cf, "wolfssl_send(len=%zu) -> %d, %d", len, rc, err);
1590 {
1591 char error_buffer[256];
1592 failf(data, "SSL write: %s, errno %d",
1593 wolfssl_strerror((unsigned long)err, error_buffer,
1594 sizeof(error_buffer)),
1595 SOCKERRNO);
1596 }
1597 *curlcode = CURLE_SEND_ERROR;
1598 return -1;
1599 }
1600 }
1601 CURL_TRC_CF(data, cf, "wolfssl_send(len=%zu) -> %d", len, rc);
1602 return rc;
1603 }
1604
wolfssl_shutdown(struct Curl_cfilter * cf,struct Curl_easy * data,bool send_shutdown,bool * done)1605 static CURLcode wolfssl_shutdown(struct Curl_cfilter *cf,
1606 struct Curl_easy *data,
1607 bool send_shutdown, bool *done)
1608 {
1609 struct ssl_connect_data *connssl = cf->ctx;
1610 struct wolfssl_ctx *wctx = (struct wolfssl_ctx *)connssl->backend;
1611 CURLcode result = CURLE_OK;
1612 char buf[1024];
1613 char error_buffer[256];
1614 int nread = -1, err;
1615 size_t i;
1616 int detail;
1617
1618 DEBUGASSERT(wctx);
1619 if(!wctx->handle || cf->shutdown) {
1620 *done = TRUE;
1621 goto out;
1622 }
1623
1624 wctx->shutting_down = TRUE;
1625 connssl->io_need = CURL_SSL_IO_NEED_NONE;
1626 *done = FALSE;
1627 if(!(wolfSSL_get_shutdown(wctx->handle) & WOLFSSL_SENT_SHUTDOWN)) {
1628 /* We have not started the shutdown from our side yet. Check
1629 * if the server already sent us one. */
1630 wolfSSL_ERR_clear_error();
1631 nread = wolfSSL_read(wctx->handle, buf, (int)sizeof(buf));
1632 err = wolfSSL_get_error(wctx->handle, nread);
1633 CURL_TRC_CF(data, cf, "wolfSSL_read, nread=%d, err=%d", nread, err);
1634 if(!nread && err == WOLFSSL_ERROR_ZERO_RETURN) {
1635 bool input_pending;
1636 /* Yes, it did. */
1637 if(!send_shutdown) {
1638 CURL_TRC_CF(data, cf, "SSL shutdown received, not sending");
1639 *done = TRUE;
1640 goto out;
1641 }
1642 else if(!cf->next->cft->is_alive(cf->next, data, &input_pending)) {
1643 /* Server closed the connection after its closy notify. It
1644 * seems not interested to see our close notify, so do not
1645 * send it. We are done. */
1646 CURL_TRC_CF(data, cf, "peer closed connection");
1647 connssl->peer_closed = TRUE;
1648 *done = TRUE;
1649 goto out;
1650 }
1651 }
1652 }
1653
1654 /* SSL should now have started the shutdown from our side. Since it
1655 * was not complete, we are lacking the close notify from the server. */
1656 if(send_shutdown) {
1657 wolfSSL_ERR_clear_error();
1658 if(wolfSSL_shutdown(wctx->handle) == 1) {
1659 CURL_TRC_CF(data, cf, "SSL shutdown finished");
1660 *done = TRUE;
1661 goto out;
1662 }
1663 if(WOLFSSL_ERROR_WANT_WRITE == wolfSSL_get_error(wctx->handle, nread)) {
1664 CURL_TRC_CF(data, cf, "SSL shutdown still wants to send");
1665 connssl->io_need = CURL_SSL_IO_NEED_SEND;
1666 goto out;
1667 }
1668 /* Having sent the close notify, we use wolfSSL_read() to get the
1669 * missing close notify from the server. */
1670 }
1671
1672 for(i = 0; i < 10; ++i) {
1673 wolfSSL_ERR_clear_error();
1674 nread = wolfSSL_read(wctx->handle, buf, (int)sizeof(buf));
1675 if(nread <= 0)
1676 break;
1677 }
1678 err = wolfSSL_get_error(wctx->handle, nread);
1679 switch(err) {
1680 case WOLFSSL_ERROR_ZERO_RETURN: /* no more data */
1681 CURL_TRC_CF(data, cf, "SSL shutdown received");
1682 *done = TRUE;
1683 break;
1684 case WOLFSSL_ERROR_NONE: /* just did not get anything */
1685 case WOLFSSL_ERROR_WANT_READ:
1686 /* SSL has send its notify and now wants to read the reply
1687 * from the server. We are not really interested in that. */
1688 CURL_TRC_CF(data, cf, "SSL shutdown sent, want receive");
1689 connssl->io_need = CURL_SSL_IO_NEED_RECV;
1690 break;
1691 case WOLFSSL_ERROR_WANT_WRITE:
1692 CURL_TRC_CF(data, cf, "SSL shutdown send blocked");
1693 connssl->io_need = CURL_SSL_IO_NEED_SEND;
1694 break;
1695 default:
1696 detail = wolfSSL_get_error(wctx->handle, err);
1697 CURL_TRC_CF(data, cf, "SSL shutdown, error: '%s'(%d)",
1698 wolfssl_strerror((unsigned long)err, error_buffer,
1699 sizeof(error_buffer)),
1700 detail);
1701 result = CURLE_RECV_ERROR;
1702 break;
1703 }
1704
1705 out:
1706 cf->shutdown = (result || *done);
1707 return result;
1708 }
1709
wolfssl_close(struct Curl_cfilter * cf,struct Curl_easy * data)1710 static void wolfssl_close(struct Curl_cfilter *cf, struct Curl_easy *data)
1711 {
1712 struct ssl_connect_data *connssl = cf->ctx;
1713 struct wolfssl_ctx *backend =
1714 (struct wolfssl_ctx *)connssl->backend;
1715
1716 (void) data;
1717
1718 DEBUGASSERT(backend);
1719
1720 if(backend->handle) {
1721 wolfSSL_free(backend->handle);
1722 backend->handle = NULL;
1723 }
1724 if(backend->ctx) {
1725 wolfSSL_CTX_free(backend->ctx);
1726 backend->ctx = NULL;
1727 }
1728 }
1729
wolfssl_recv(struct Curl_cfilter * cf,struct Curl_easy * data,char * buf,size_t blen,CURLcode * curlcode)1730 static ssize_t wolfssl_recv(struct Curl_cfilter *cf,
1731 struct Curl_easy *data,
1732 char *buf, size_t blen,
1733 CURLcode *curlcode)
1734 {
1735 struct ssl_connect_data *connssl = cf->ctx;
1736 struct wolfssl_ctx *backend =
1737 (struct wolfssl_ctx *)connssl->backend;
1738 int buffsize = (blen > (size_t)INT_MAX) ? INT_MAX : (int)blen;
1739 int nread;
1740
1741 DEBUGASSERT(backend);
1742
1743 wolfSSL_ERR_clear_error();
1744 *curlcode = CURLE_OK;
1745
1746 nread = wolfSSL_read(backend->handle, buf, buffsize);
1747
1748 if(nread <= 0) {
1749 int err = wolfSSL_get_error(backend->handle, nread);
1750
1751 switch(err) {
1752 case WOLFSSL_ERROR_ZERO_RETURN: /* no more data */
1753 CURL_TRC_CF(data, cf, "wolfssl_recv(len=%zu) -> CLOSED", blen);
1754 *curlcode = CURLE_OK;
1755 return 0;
1756 case WOLFSSL_ERROR_NONE:
1757 case WOLFSSL_ERROR_WANT_READ:
1758 case WOLFSSL_ERROR_WANT_WRITE:
1759 if(!backend->io_result && connssl->peer_closed) {
1760 CURL_TRC_CF(data, cf, "wolfssl_recv(len=%zu) -> CLOSED", blen);
1761 *curlcode = CURLE_OK;
1762 return 0;
1763 }
1764 /* there is data pending, re-invoke wolfSSL_read() */
1765 CURL_TRC_CF(data, cf, "wolfssl_recv(len=%zu) -> AGAIN", blen);
1766 *curlcode = CURLE_AGAIN;
1767 return -1;
1768 default:
1769 if(backend->io_result == CURLE_AGAIN) {
1770 CURL_TRC_CF(data, cf, "wolfssl_recv(len=%zu) -> AGAIN", blen);
1771 *curlcode = CURLE_AGAIN;
1772 return -1;
1773 }
1774 else if(!backend->io_result && connssl->peer_closed) {
1775 CURL_TRC_CF(data, cf, "wolfssl_recv(len=%zu) -> CLOSED", blen);
1776 *curlcode = CURLE_OK;
1777 return 0;
1778 }
1779 else {
1780 char error_buffer[256];
1781 failf(data, "SSL read: %s, errno %d",
1782 wolfssl_strerror((unsigned long)err, error_buffer,
1783 sizeof(error_buffer)),
1784 SOCKERRNO);
1785 }
1786 *curlcode = CURLE_RECV_ERROR;
1787 return -1;
1788 }
1789 }
1790 CURL_TRC_CF(data, cf, "wolfssl_recv(len=%zu) -> %d", blen, nread);
1791 return nread;
1792 }
1793
1794
Curl_wssl_version(char * buffer,size_t size)1795 size_t Curl_wssl_version(char *buffer, size_t size)
1796 {
1797 #if LIBWOLFSSL_VERSION_HEX >= 0x03006000
1798 return msnprintf(buffer, size, "wolfSSL/%s", wolfSSL_lib_version());
1799 #elif defined(WOLFSSL_VERSION)
1800 return msnprintf(buffer, size, "wolfSSL/%s", WOLFSSL_VERSION);
1801 #endif
1802 }
1803
1804
wolfssl_init(void)1805 static int wolfssl_init(void)
1806 {
1807 int ret;
1808
1809 #ifdef OPENSSL_EXTRA
1810 Curl_tls_keylog_open();
1811 #endif
1812 ret = (wolfSSL_Init() == WOLFSSL_SUCCESS);
1813 wolfssl_bio_cf_init_methods();
1814 return ret;
1815 }
1816
1817
wolfssl_cleanup(void)1818 static void wolfssl_cleanup(void)
1819 {
1820 wolfssl_bio_cf_free_methods();
1821 wolfSSL_Cleanup();
1822 #ifdef OPENSSL_EXTRA
1823 Curl_tls_keylog_close();
1824 #endif
1825 }
1826
1827
wolfssl_data_pending(struct Curl_cfilter * cf,const struct Curl_easy * data)1828 static bool wolfssl_data_pending(struct Curl_cfilter *cf,
1829 const struct Curl_easy *data)
1830 {
1831 struct ssl_connect_data *ctx = cf->ctx;
1832 struct wolfssl_ctx *backend;
1833
1834 (void)data;
1835 DEBUGASSERT(ctx && ctx->backend);
1836
1837 backend = (struct wolfssl_ctx *)ctx->backend;
1838 if(backend->handle) /* SSL is in use */
1839 return wolfSSL_pending(backend->handle);
1840 else
1841 return FALSE;
1842 }
1843
1844 static CURLcode
wolfssl_connect_common(struct Curl_cfilter * cf,struct Curl_easy * data,bool nonblocking,bool * done)1845 wolfssl_connect_common(struct Curl_cfilter *cf,
1846 struct Curl_easy *data,
1847 bool nonblocking,
1848 bool *done)
1849 {
1850 CURLcode result;
1851 struct ssl_connect_data *connssl = cf->ctx;
1852 curl_socket_t sockfd = Curl_conn_cf_get_socket(cf, data);
1853
1854 /* check if the connection has already been established */
1855 if(ssl_connection_complete == connssl->state) {
1856 *done = TRUE;
1857 return CURLE_OK;
1858 }
1859
1860 if(ssl_connect_1 == connssl->connecting_state) {
1861 /* Find out how much more time we are allowed */
1862 const timediff_t timeout_ms = Curl_timeleft(data, NULL, TRUE);
1863
1864 if(timeout_ms < 0) {
1865 /* no need to continue if time already is up */
1866 failf(data, "SSL connection timeout");
1867 return CURLE_OPERATION_TIMEDOUT;
1868 }
1869
1870 result = wolfssl_connect_step1(cf, data);
1871 if(result)
1872 return result;
1873 }
1874
1875 while(ssl_connect_2 == connssl->connecting_state) {
1876
1877 /* check allowed time left */
1878 const timediff_t timeout_ms = Curl_timeleft(data, NULL, TRUE);
1879
1880 if(timeout_ms < 0) {
1881 /* no need to continue if time already is up */
1882 failf(data, "SSL connection timeout");
1883 return CURLE_OPERATION_TIMEDOUT;
1884 }
1885
1886 /* if ssl is expecting something, check if it is available. */
1887 if(connssl->io_need) {
1888 curl_socket_t writefd = (connssl->io_need & CURL_SSL_IO_NEED_SEND) ?
1889 sockfd : CURL_SOCKET_BAD;
1890 curl_socket_t readfd = (connssl->io_need & CURL_SSL_IO_NEED_RECV) ?
1891 sockfd : CURL_SOCKET_BAD;
1892 int what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd,
1893 nonblocking ? 0 : timeout_ms);
1894 if(what < 0) {
1895 /* fatal error */
1896 failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
1897 return CURLE_SSL_CONNECT_ERROR;
1898 }
1899 else if(0 == what) {
1900 if(nonblocking) {
1901 *done = FALSE;
1902 return CURLE_OK;
1903 }
1904 else {
1905 /* timeout */
1906 failf(data, "SSL connection timeout");
1907 return CURLE_OPERATION_TIMEDOUT;
1908 }
1909 }
1910 /* socket is readable or writable */
1911 }
1912
1913 /* Run transaction, and return to the caller if it failed or if
1914 * this connection is part of a multi handle and this loop would
1915 * execute again. This permits the owner of a multi handle to
1916 * abort a connection attempt before step2 has completed while
1917 * ensuring that a client using select() or epoll() will always
1918 * have a valid fdset to wait on.
1919 */
1920 result = wolfssl_connect_step2(cf, data);
1921 if(result || (nonblocking && (ssl_connect_2 == connssl->connecting_state)))
1922 return result;
1923 } /* repeat step2 until all transactions are done. */
1924
1925 if(ssl_connect_3 == connssl->connecting_state) {
1926 /* In other backends, this is where we verify the certificate, but
1927 * wolfSSL already does that as part of the handshake. */
1928 connssl->connecting_state = ssl_connect_done;
1929 }
1930
1931 if(ssl_connect_done == connssl->connecting_state) {
1932 connssl->state = ssl_connection_complete;
1933 *done = TRUE;
1934 }
1935 else
1936 *done = FALSE;
1937
1938 /* Reset our connect state machine */
1939 connssl->connecting_state = ssl_connect_1;
1940
1941 return CURLE_OK;
1942 }
1943
1944
wolfssl_connect_nonblocking(struct Curl_cfilter * cf,struct Curl_easy * data,bool * done)1945 static CURLcode wolfssl_connect_nonblocking(struct Curl_cfilter *cf,
1946 struct Curl_easy *data,
1947 bool *done)
1948 {
1949 return wolfssl_connect_common(cf, data, TRUE, done);
1950 }
1951
1952
wolfssl_connect(struct Curl_cfilter * cf,struct Curl_easy * data)1953 static CURLcode wolfssl_connect(struct Curl_cfilter *cf,
1954 struct Curl_easy *data)
1955 {
1956 CURLcode result;
1957 bool done = FALSE;
1958
1959 result = wolfssl_connect_common(cf, data, FALSE, &done);
1960 if(result)
1961 return result;
1962
1963 DEBUGASSERT(done);
1964
1965 return CURLE_OK;
1966 }
1967
wolfssl_random(struct Curl_easy * data,unsigned char * entropy,size_t length)1968 static CURLcode wolfssl_random(struct Curl_easy *data,
1969 unsigned char *entropy, size_t length)
1970 {
1971 WC_RNG rng;
1972 (void)data;
1973 if(wc_InitRng(&rng))
1974 return CURLE_FAILED_INIT;
1975 if(length > UINT_MAX)
1976 return CURLE_FAILED_INIT;
1977 if(wc_RNG_GenerateBlock(&rng, entropy, (unsigned)length))
1978 return CURLE_FAILED_INIT;
1979 if(wc_FreeRng(&rng))
1980 return CURLE_FAILED_INIT;
1981 return CURLE_OK;
1982 }
1983
wolfssl_sha256sum(const unsigned char * tmp,size_t tmplen,unsigned char * sha256sum,size_t unused)1984 static CURLcode wolfssl_sha256sum(const unsigned char *tmp, /* input */
1985 size_t tmplen,
1986 unsigned char *sha256sum /* output */,
1987 size_t unused)
1988 {
1989 wc_Sha256 SHA256pw;
1990 (void)unused;
1991 if(wc_InitSha256(&SHA256pw))
1992 return CURLE_FAILED_INIT;
1993 wc_Sha256Update(&SHA256pw, tmp, (word32)tmplen);
1994 wc_Sha256Final(&SHA256pw, sha256sum);
1995 return CURLE_OK;
1996 }
1997
wolfssl_get_internals(struct ssl_connect_data * connssl,CURLINFO info UNUSED_PARAM)1998 static void *wolfssl_get_internals(struct ssl_connect_data *connssl,
1999 CURLINFO info UNUSED_PARAM)
2000 {
2001 struct wolfssl_ctx *backend =
2002 (struct wolfssl_ctx *)connssl->backend;
2003 (void)info;
2004 DEBUGASSERT(backend);
2005 return backend->handle;
2006 }
2007
2008 const struct Curl_ssl Curl_ssl_wolfssl = {
2009 { CURLSSLBACKEND_WOLFSSL, "wolfssl" }, /* info */
2010
2011 #ifdef KEEP_PEER_CERT
2012 SSLSUPP_PINNEDPUBKEY |
2013 #endif
2014 #ifdef USE_BIO_CHAIN
2015 SSLSUPP_HTTPS_PROXY |
2016 #endif
2017 SSLSUPP_CA_PATH |
2018 SSLSUPP_CAINFO_BLOB |
2019 #ifdef USE_ECH_WOLFSSL
2020 SSLSUPP_ECH |
2021 #endif
2022 SSLSUPP_SSL_CTX |
2023 #ifdef WOLFSSL_TLS13
2024 SSLSUPP_TLS13_CIPHERSUITES |
2025 #endif
2026 SSLSUPP_CA_CACHE |
2027 SSLSUPP_CIPHER_LIST,
2028
2029 sizeof(struct wolfssl_ctx),
2030
2031 wolfssl_init, /* init */
2032 wolfssl_cleanup, /* cleanup */
2033 Curl_wssl_version, /* version */
2034 wolfssl_shutdown, /* shutdown */
2035 wolfssl_data_pending, /* data_pending */
2036 wolfssl_random, /* random */
2037 NULL, /* cert_status_request */
2038 wolfssl_connect, /* connect */
2039 wolfssl_connect_nonblocking, /* connect_nonblocking */
2040 Curl_ssl_adjust_pollset, /* adjust_pollset */
2041 wolfssl_get_internals, /* get_internals */
2042 wolfssl_close, /* close_one */
2043 NULL, /* close_all */
2044 NULL, /* set_engine */
2045 NULL, /* set_engine_default */
2046 NULL, /* engines_list */
2047 NULL, /* false_start */
2048 wolfssl_sha256sum, /* sha256sum */
2049 wolfssl_recv, /* recv decrypted data */
2050 wolfssl_send, /* send data to encrypt */
2051 NULL, /* get_channel_binding */
2052 };
2053
2054 #endif
2055