xref: /curl/lib/vtls/wolfssl.c (revision fbf5d507)
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