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