quickjs-tart

quickjs-based runtime for wallet-core logic
Log | Files | Refs | README | LICENSE

wolfssl.c (71254B)


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