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