quickjs-tart

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

mbedtls.c (50115B)


      1 /***************************************************************************
      2  *                                  _   _ ____  _
      3  *  Project                     ___| | | |  _ \| |
      4  *                             / __| | | | |_) | |
      5  *                            | (__| |_| |  _ <| |___
      6  *                             \___|\___/|_| \_\_____|
      7  *
      8  * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
      9  * Copyright (C) Hoi-Ho Chan, <hoiho.chan@gmail.com>
     10  *
     11  * This software is licensed as described in the file COPYING, which
     12  * you should have received as part of this distribution. The terms
     13  * are also available at https://curl.se/docs/copyright.html.
     14  *
     15  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
     16  * copies of the Software, and permit persons to whom the Software is
     17  * furnished to do so, under the terms of the COPYING file.
     18  *
     19  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
     20  * KIND, either express or implied.
     21  *
     22  * SPDX-License-Identifier: curl
     23  *
     24  ***************************************************************************/
     25 
     26 /*
     27  * Source file for all mbedTLS-specific code for the TLS/SSL layer. No code
     28  * but vtls.c should ever call or use these functions.
     29  *
     30  */
     31 
     32 #include "../curl_setup.h"
     33 
     34 #ifdef USE_MBEDTLS
     35 
     36 /* Define this to enable lots of debugging for mbedTLS */
     37 /* #define MBEDTLS_DEBUG */
     38 
     39 #include <mbedtls/version.h>
     40 #if MBEDTLS_VERSION_NUMBER >= 0x02040000
     41 #include <mbedtls/net_sockets.h>
     42 #else
     43 #include <mbedtls/net.h>
     44 #endif
     45 #include <mbedtls/ssl.h>
     46 #include <mbedtls/x509.h>
     47 
     48 #include <mbedtls/error.h>
     49 #include <mbedtls/entropy.h>
     50 #include <mbedtls/ctr_drbg.h>
     51 #include <mbedtls/sha256.h>
     52 
     53 #if MBEDTLS_VERSION_MAJOR >= 2
     54 #  ifdef MBEDTLS_DEBUG
     55 #    include <mbedtls/debug.h>
     56 #  endif
     57 #endif /* MBEDTLS_VERSION_MAJOR >= 2 */
     58 
     59 #include "cipher_suite.h"
     60 #include "../urldata.h"
     61 #include "../sendf.h"
     62 #include "../curlx/inet_pton.h"
     63 #include "mbedtls.h"
     64 #include "vtls.h"
     65 #include "vtls_int.h"
     66 #include "vtls_scache.h"
     67 #include "x509asn1.h"
     68 #include "../parsedate.h"
     69 #include "../connect.h" /* for the connect timeout */
     70 #include "../select.h"
     71 #include "../multiif.h"
     72 #include "mbedtls_threadlock.h"
     73 #include "../strdup.h"
     74 
     75 /* The last 3 #include files should be in this order */
     76 #include "../curl_printf.h"
     77 #include "../curl_memory.h"
     78 #include "../memdebug.h"
     79 
     80 /* ALPN for http2 */
     81 #if defined(USE_HTTP2) && defined(MBEDTLS_SSL_ALPN)
     82 #  define HAS_ALPN_MBEDTLS
     83 #endif
     84 
     85 struct mbed_ssl_backend_data {
     86   mbedtls_ctr_drbg_context ctr_drbg;
     87   mbedtls_entropy_context entropy;
     88   mbedtls_ssl_context ssl;
     89   mbedtls_x509_crt cacert;
     90   mbedtls_x509_crt clicert;
     91 #ifdef MBEDTLS_X509_CRL_PARSE_C
     92   mbedtls_x509_crl crl;
     93 #endif
     94   mbedtls_pk_context pk;
     95   mbedtls_ssl_config config;
     96 #ifdef HAS_ALPN_MBEDTLS
     97   const char *protocols[3];
     98 #endif
     99   int *ciphersuites;
    100   size_t send_blocked_len;
    101   BIT(initialized); /* mbedtls_ssl_context is initialized */
    102   BIT(sent_shutdown);
    103   BIT(send_blocked);
    104 };
    105 
    106 /* apply threading? */
    107 #if (defined(USE_THREADS_POSIX) && defined(HAVE_PTHREAD_H)) ||  \
    108   defined(_WIN32)
    109 #define HAS_THREADING_SUPPORT
    110 #endif
    111 
    112 #ifndef MBEDTLS_ERROR_C
    113 #define mbedtls_strerror(a,b,c) b[0] = 0
    114 #endif
    115 
    116 /* PSA can be used independently of TLS 1.3 */
    117 #if defined(MBEDTLS_USE_PSA_CRYPTO) && MBEDTLS_VERSION_NUMBER >= 0x03060000
    118 #define HAS_PSA_SUPPORT
    119 #endif
    120 
    121 #if defined(MBEDTLS_SSL_PROTO_TLS1_3) && MBEDTLS_VERSION_NUMBER >= 0x03060000
    122 #define HAS_TLS13_SUPPORT
    123 #endif
    124 
    125 #if defined(HAS_TLS13_SUPPORT) && defined(MBEDTLS_SSL_SESSION_TICKETS)
    126 #define HAS_SESSION_TICKETS
    127 #endif
    128 
    129 #ifdef HAS_THREADING_SUPPORT
    130 static mbedtls_entropy_context ts_entropy;
    131 
    132 static int entropy_init_initialized = 0;
    133 
    134 static void entropy_init_mutex(mbedtls_entropy_context *ctx)
    135 {
    136   /* lock 0 = entropy_init_mutex() */
    137   Curl_mbedtlsthreadlock_lock_function(0);
    138   if(entropy_init_initialized == 0) {
    139     mbedtls_entropy_init(ctx);
    140     entropy_init_initialized = 1;
    141   }
    142   Curl_mbedtlsthreadlock_unlock_function(0);
    143 }
    144 
    145 static void entropy_cleanup_mutex(mbedtls_entropy_context *ctx)
    146 {
    147   /* lock 0 = use same lock as init */
    148   Curl_mbedtlsthreadlock_lock_function(0);
    149   if(entropy_init_initialized == 1) {
    150     mbedtls_entropy_free(ctx);
    151     entropy_init_initialized = 0;
    152   }
    153   Curl_mbedtlsthreadlock_unlock_function(0);
    154 }
    155 
    156 static int entropy_func_mutex(void *data, unsigned char *output, size_t len)
    157 {
    158   int ret;
    159   /* lock 1 = entropy_func_mutex() */
    160   Curl_mbedtlsthreadlock_lock_function(1);
    161   ret = mbedtls_entropy_func(data, output, len);
    162   Curl_mbedtlsthreadlock_unlock_function(1);
    163 
    164   return ret;
    165 }
    166 
    167 #endif /* HAS_THREADING_SUPPORT */
    168 
    169 #ifdef MBEDTLS_DEBUG
    170 static void mbed_debug(void *context, int level, const char *f_name,
    171                        int line_nb, const char *line)
    172 {
    173   struct Curl_easy *data = (struct Curl_easy *)context;
    174   (void) level;
    175   (void) line_nb;
    176   (void) f_name;
    177 
    178   if(data) {
    179     size_t len = strlen(line);
    180     if(len && (line[len - 1] == '\n'))
    181       /* discount any trailing newline */
    182       len--;
    183     infof(data, "%.*s", (int)len, line);
    184   }
    185 }
    186 #endif
    187 
    188 static int mbedtls_bio_cf_write(void *bio,
    189                                 const unsigned char *buf, size_t blen)
    190 {
    191   struct Curl_cfilter *cf = bio;
    192   struct Curl_easy *data = CF_DATA_CURRENT(cf);
    193   size_t nwritten;
    194   CURLcode result;
    195 
    196   DEBUGASSERT(data);
    197   if(!data)
    198     return 0;
    199 
    200   result = Curl_conn_cf_send(cf->next, data, (const char *)buf, blen, FALSE,
    201                              &nwritten);
    202   CURL_TRC_CF(data, cf, "mbedtls_bio_cf_out_write(len=%zu) -> %d, %zu",
    203               blen, result, nwritten);
    204   if(CURLE_AGAIN == result)
    205     return MBEDTLS_ERR_SSL_WANT_WRITE;
    206   return result ? -1 : (int)nwritten;
    207 }
    208 
    209 static int mbedtls_bio_cf_read(void *bio, unsigned char *buf, size_t blen)
    210 {
    211   struct Curl_cfilter *cf = bio;
    212   struct Curl_easy *data = CF_DATA_CURRENT(cf);
    213   size_t nread;
    214   CURLcode result;
    215 
    216   DEBUGASSERT(data);
    217   if(!data)
    218     return 0;
    219   /* OpenSSL catches this case, so should we. */
    220   if(!buf)
    221     return 0;
    222 
    223   result = Curl_conn_cf_recv(cf->next, data, (char *)buf, blen, &nread);
    224   CURL_TRC_CF(data, cf, "mbedtls_bio_cf_in_read(len=%zu) -> %d, %zu",
    225               blen, result, nread);
    226   if(CURLE_AGAIN == result)
    227     return MBEDTLS_ERR_SSL_WANT_READ;
    228   return result ? -1 : (int)nread;
    229 }
    230 
    231 /*
    232  *  profile
    233  */
    234 static const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_fr =
    235 {
    236   /* Hashes from SHA-1 and above */
    237   MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA1) |
    238   MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_RIPEMD160) |
    239   MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA224) |
    240   MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA256) |
    241   MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA384) |
    242   MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA512),
    243   0xFFFFFFF, /* Any PK alg    */
    244   0xFFFFFFF, /* Any curve     */
    245   1024,      /* RSA min key len */
    246 };
    247 
    248 /* See https://web.archive.org/web/20200921194007/tls.mbed.org/discussions/
    249    generic/howto-determine-exact-buffer-len-for-mbedtls_pk_write_pubkey_der
    250 */
    251 #define RSA_PUB_DER_MAX_BYTES   (38 + 2 * MBEDTLS_MPI_MAX_SIZE)
    252 #define ECP_PUB_DER_MAX_BYTES   (30 + 2 * MBEDTLS_ECP_MAX_BYTES)
    253 
    254 #define PUB_DER_MAX_BYTES   (RSA_PUB_DER_MAX_BYTES > ECP_PUB_DER_MAX_BYTES ? \
    255                              RSA_PUB_DER_MAX_BYTES : ECP_PUB_DER_MAX_BYTES)
    256 
    257 static CURLcode
    258 mbed_set_ssl_version_min_max(struct Curl_easy *data,
    259                              struct mbed_ssl_backend_data *backend,
    260                              struct ssl_primary_config *conn_config)
    261 {
    262   /* TLS 1.0 and TLS 1.1 were dropped with mbedTLS 3.0.0 (2021). So, since
    263    * then, and before the introduction of TLS 1.3 in 3.6.0 (2024), this
    264    * function basically always sets TLS 1.2 as min/max, unless given
    265    * unsupported option values. */
    266 
    267 #if MBEDTLS_VERSION_NUMBER < 0x03020000
    268   int ver_min = MBEDTLS_SSL_MINOR_VERSION_3; /* TLS 1.2 */
    269   int ver_max = MBEDTLS_SSL_MINOR_VERSION_3; /* TLS 1.2 */
    270 #else
    271   /* mbedTLS 3.2.0 (2022) introduced new methods for setting TLS version */
    272   mbedtls_ssl_protocol_version ver_min = MBEDTLS_SSL_VERSION_TLS1_2;
    273   mbedtls_ssl_protocol_version ver_max =
    274 #ifdef HAS_TLS13_SUPPORT
    275     MBEDTLS_SSL_VERSION_TLS1_3
    276 #else
    277     MBEDTLS_SSL_VERSION_TLS1_2
    278 #endif
    279     ;
    280 #endif
    281 
    282   switch(conn_config->version) {
    283   case CURL_SSLVERSION_DEFAULT:
    284 #if MBEDTLS_VERSION_NUMBER < 0x03000000
    285   case CURL_SSLVERSION_TLSv1:
    286   case CURL_SSLVERSION_TLSv1_0:
    287     ver_min = MBEDTLS_SSL_MINOR_VERSION_1;
    288     break;
    289   case CURL_SSLVERSION_TLSv1_1:
    290     ver_min = MBEDTLS_SSL_MINOR_VERSION_2;
    291     break;
    292 #else
    293   case CURL_SSLVERSION_TLSv1:
    294   case CURL_SSLVERSION_TLSv1_0:
    295   case CURL_SSLVERSION_TLSv1_1:
    296 #endif
    297   case CURL_SSLVERSION_TLSv1_2:
    298 #if MBEDTLS_VERSION_NUMBER < 0x03020000
    299     ver_min = MBEDTLS_SSL_MINOR_VERSION_3; /* TLS 1.2 */
    300 #else
    301     ver_min = MBEDTLS_SSL_VERSION_TLS1_2;
    302 #endif
    303     break;
    304   case CURL_SSLVERSION_TLSv1_3:
    305 #ifdef HAS_TLS13_SUPPORT
    306     ver_min = MBEDTLS_SSL_VERSION_TLS1_3;
    307     break;
    308 #endif
    309   default:
    310     failf(data, "mbedTLS: unsupported minimum TLS version value: %x",
    311           conn_config->version);
    312     return CURLE_SSL_CONNECT_ERROR;
    313   }
    314 
    315   switch(conn_config->version_max) {
    316   case CURL_SSLVERSION_MAX_DEFAULT:
    317   case CURL_SSLVERSION_MAX_NONE:
    318   case CURL_SSLVERSION_MAX_TLSv1_3:
    319 #ifdef HAS_TLS13_SUPPORT
    320     ver_max = MBEDTLS_SSL_VERSION_TLS1_3;
    321     break;
    322 #endif
    323   case CURL_SSLVERSION_MAX_TLSv1_2:
    324 #if MBEDTLS_VERSION_NUMBER < 0x03020000
    325     ver_max = MBEDTLS_SSL_MINOR_VERSION_3; /* TLS 1.2 */
    326 #else
    327     ver_max = MBEDTLS_SSL_VERSION_TLS1_2;
    328 #endif
    329     break;
    330 #if MBEDTLS_VERSION_NUMBER < 0x03000000
    331   case CURL_SSLVERSION_MAX_TLSv1_1:
    332     ver_max = MBEDTLS_SSL_MINOR_VERSION_2;
    333     break;
    334   case CURL_SSLVERSION_MAX_TLSv1_0:
    335     ver_max = MBEDTLS_SSL_MINOR_VERSION_1;
    336     break;
    337 #else
    338   case CURL_SSLVERSION_MAX_TLSv1_1:
    339   case CURL_SSLVERSION_MAX_TLSv1_0:
    340 #endif
    341   default:
    342     failf(data, "mbedTLS: unsupported maximum TLS version value");
    343     return CURLE_SSL_CONNECT_ERROR;
    344   }
    345 
    346 #if MBEDTLS_VERSION_NUMBER < 0x03020000
    347   mbedtls_ssl_conf_min_version(&backend->config, MBEDTLS_SSL_MAJOR_VERSION_3,
    348                                ver_min);
    349   mbedtls_ssl_conf_max_version(&backend->config, MBEDTLS_SSL_MAJOR_VERSION_3,
    350                                ver_max);
    351 #else
    352   mbedtls_ssl_conf_min_tls_version(&backend->config, ver_min);
    353   mbedtls_ssl_conf_max_tls_version(&backend->config, ver_max);
    354 #endif
    355 
    356   return CURLE_OK;
    357 }
    358 
    359 /* TLS_ECJPAKE_WITH_AES_128_CCM_8 (0xC0FF) is marked experimental
    360    in mbedTLS. The number is not reserved by IANA nor is the
    361    cipher suite present in other SSL implementations. Provide
    362    provisional support for specifying the cipher suite here. */
    363 #ifdef MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8
    364 #if MBEDTLS_VERSION_NUMBER >= 0x03020000
    365 static int
    366 mbed_cipher_suite_get_str(uint16_t id, char *buf, size_t buf_size,
    367                           bool prefer_rfc)
    368 {
    369   if(id == MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8)
    370     msnprintf(buf, buf_size, "%s", "TLS_ECJPAKE_WITH_AES_128_CCM_8");
    371   else
    372     return Curl_cipher_suite_get_str(id, buf, buf_size, prefer_rfc);
    373   return 0;
    374 }
    375 #endif
    376 
    377 static uint16_t
    378 mbed_cipher_suite_walk_str(const char **str, const char **end)
    379 {
    380   uint16_t id = Curl_cipher_suite_walk_str(str, end);
    381   size_t len = *end - *str;
    382 
    383   if(!id) {
    384     if(curl_strnequal("TLS_ECJPAKE_WITH_AES_128_CCM_8", *str, len))
    385       id = MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8;
    386   }
    387   return id;
    388 }
    389 #else
    390 #define mbed_cipher_suite_get_str Curl_cipher_suite_get_str
    391 #define mbed_cipher_suite_walk_str Curl_cipher_suite_walk_str
    392 #endif
    393 
    394 static CURLcode
    395 mbed_set_selected_ciphers(struct Curl_easy *data,
    396                           struct mbed_ssl_backend_data *backend,
    397                           const char *ciphers12,
    398                           const char *ciphers13)
    399 {
    400   const char *ciphers = ciphers12;
    401   const int *supported;
    402   int *selected;
    403   size_t supported_len, count = 0, default13_count = 0, i, j;
    404   const char *ptr, *end;
    405 
    406   supported = mbedtls_ssl_list_ciphersuites();
    407   for(i = 0; supported[i] != 0; i++);
    408   supported_len = i;
    409 
    410   selected = malloc(sizeof(int) * (supported_len + 1));
    411   if(!selected)
    412     return CURLE_OUT_OF_MEMORY;
    413 
    414 #ifndef HAS_TLS13_SUPPORT
    415   (void) ciphers13, (void) j;
    416 #else
    417   if(!ciphers13) {
    418     /* Add default TLSv1.3 ciphers to selection */
    419     for(j = 0; j < supported_len; j++) {
    420       uint16_t id = (uint16_t) supported[j];
    421       if(strncmp(mbedtls_ssl_get_ciphersuite_name(id), "TLS1-3", 6) != 0)
    422         continue;
    423 
    424       selected[count++] = id;
    425     }
    426 
    427     default13_count = count;
    428   }
    429   else
    430     ciphers = ciphers13;
    431 
    432 add_ciphers:
    433 #endif
    434   for(ptr = ciphers; ptr[0] != '\0' && count < supported_len; ptr = end) {
    435     uint16_t id = mbed_cipher_suite_walk_str(&ptr, &end);
    436 
    437     /* Check if cipher is supported */
    438     if(id) {
    439       for(i = 0; i < supported_len && supported[i] != id; i++);
    440       if(i == supported_len)
    441         id = 0;
    442     }
    443     if(!id) {
    444       if(ptr[0] != '\0')
    445         infof(data, "mbedTLS: unknown cipher in list: \"%.*s\"",
    446               (int) (end - ptr), ptr);
    447       continue;
    448     }
    449 
    450     /* No duplicates allowed (so selected cannot overflow) */
    451     for(i = 0; i < count && selected[i] != id; i++);
    452     if(i < count) {
    453       if(i >= default13_count)
    454         infof(data, "mbedTLS: duplicate cipher in list: \"%.*s\"",
    455               (int) (end - ptr), ptr);
    456       continue;
    457     }
    458 
    459     selected[count++] = id;
    460   }
    461 
    462 #ifdef HAS_TLS13_SUPPORT
    463   if(ciphers == ciphers13 && ciphers12) {
    464     ciphers = ciphers12;
    465     goto add_ciphers;
    466   }
    467 
    468   if(!ciphers12) {
    469     /* Add default TLSv1.2 ciphers to selection */
    470     for(j = 0; j < supported_len; j++) {
    471       uint16_t id = (uint16_t) supported[j];
    472       if(strncmp(mbedtls_ssl_get_ciphersuite_name(id), "TLS1-3", 6) == 0)
    473         continue;
    474 
    475       /* No duplicates allowed (so selected cannot overflow) */
    476       for(i = 0; i < count && selected[i] != id; i++);
    477       if(i < count)
    478         continue;
    479 
    480       selected[count++] = id;
    481     }
    482   }
    483 #endif
    484 
    485   selected[count] = 0;
    486 
    487   if(count == 0) {
    488     free(selected);
    489     failf(data, "mbedTLS: no supported cipher in list");
    490     return CURLE_SSL_CIPHER;
    491   }
    492 
    493   /* mbedtls_ssl_conf_ciphersuites(): The ciphersuites array is not copied.
    494      It must remain valid for the lifetime of the SSL configuration */
    495   backend->ciphersuites = selected;
    496   mbedtls_ssl_conf_ciphersuites(&backend->config, backend->ciphersuites);
    497   return CURLE_OK;
    498 }
    499 
    500 static void
    501 mbed_dump_cert_info(struct Curl_easy *data, const mbedtls_x509_crt *crt)
    502 {
    503 #if defined(CURL_DISABLE_VERBOSE_STRINGS) || \
    504     (MBEDTLS_VERSION_NUMBER >= 0x03000000 && defined(MBEDTLS_X509_REMOVE_INFO))
    505   (void) data, (void) crt;
    506 #else
    507   const size_t bufsize = 16384;
    508   char *p, *buffer = malloc(bufsize);
    509 
    510   if(buffer && mbedtls_x509_crt_info(buffer, bufsize, " ", crt) > 0) {
    511     infof(data, "Server certificate:");
    512     for(p = buffer; *p; p += *p != '\0') {
    513       size_t s = strcspn(p, "\n");
    514       infof(data, "%.*s", (int) s, p);
    515       p += s;
    516     }
    517   }
    518   else
    519     infof(data, "Unable to dump certificate information");
    520 
    521   free(buffer);
    522 #endif
    523 }
    524 
    525 static void
    526 mbed_extract_certinfo(struct Curl_easy *data, const mbedtls_x509_crt *crt)
    527 {
    528   CURLcode result;
    529   const mbedtls_x509_crt *cur;
    530   int i;
    531 
    532   for(i = 0, cur = crt; cur; ++i, cur = cur->next);
    533   result = Curl_ssl_init_certinfo(data, i);
    534 
    535   for(i = 0, cur = crt; result == CURLE_OK && cur; ++i, cur = cur->next) {
    536     const char *beg = (const char *) cur->raw.p;
    537     const char *end = beg + cur->raw.len;
    538     result = Curl_extract_certinfo(data, i, beg, end);
    539   }
    540 }
    541 
    542 static int mbed_verify_cb(void *ptr, mbedtls_x509_crt *crt,
    543                           int depth, uint32_t *flags)
    544 {
    545   struct Curl_cfilter *cf = (struct Curl_cfilter *) ptr;
    546   struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
    547   struct Curl_easy *data = CF_DATA_CURRENT(cf);
    548 
    549   if(depth == 0) {
    550     if(data->set.verbose)
    551       mbed_dump_cert_info(data, crt);
    552     if(data->set.ssl.certinfo)
    553       mbed_extract_certinfo(data, crt);
    554   }
    555 
    556   if(!conn_config->verifypeer)
    557     *flags = 0;
    558   else if(!conn_config->verifyhost)
    559     *flags &= ~MBEDTLS_X509_BADCERT_CN_MISMATCH;
    560 
    561   if(*flags) {
    562 #if MBEDTLS_VERSION_NUMBER < 0x03000000 || !defined(MBEDTLS_X509_REMOVE_INFO)
    563     char buf[128];
    564     mbedtls_x509_crt_verify_info(buf, sizeof(buf), "", *flags);
    565     failf(data, "mbedTLS: %s", buf);
    566 #else
    567     failf(data, "mbedTLS: certificate verification error 0x%08x", *flags);
    568 #endif
    569   }
    570 
    571   return 0;
    572 }
    573 
    574 static CURLcode
    575 mbed_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
    576 {
    577   struct ssl_connect_data *connssl = cf->ctx;
    578   struct mbed_ssl_backend_data *backend =
    579     (struct mbed_ssl_backend_data *)connssl->backend;
    580   struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
    581   const struct curl_blob *ca_info_blob = conn_config->ca_info_blob;
    582   struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
    583   const char * const ssl_cafile =
    584     /* CURLOPT_CAINFO_BLOB overrides CURLOPT_CAINFO */
    585     (ca_info_blob ? NULL : conn_config->CAfile);
    586   const bool verifypeer = conn_config->verifypeer;
    587   const char * const ssl_capath = conn_config->CApath;
    588   char * const ssl_cert = ssl_config->primary.clientcert;
    589   const struct curl_blob *ssl_cert_blob = ssl_config->primary.cert_blob;
    590   const char * const ssl_crlfile = ssl_config->primary.CRLfile;
    591   const char *hostname = connssl->peer.hostname;
    592   int ret = -1;
    593   char errorbuf[128];
    594 
    595   DEBUGASSERT(backend);
    596   DEBUGASSERT(!backend->initialized);
    597 
    598   if((conn_config->version == CURL_SSLVERSION_SSLv2) ||
    599      (conn_config->version == CURL_SSLVERSION_SSLv3)) {
    600     failf(data, "Not supported SSL version");
    601     return CURLE_NOT_BUILT_IN;
    602   }
    603 
    604 #ifdef HAS_THREADING_SUPPORT
    605   mbedtls_ctr_drbg_init(&backend->ctr_drbg);
    606 
    607   ret = mbedtls_ctr_drbg_seed(&backend->ctr_drbg, entropy_func_mutex,
    608                               &ts_entropy, NULL, 0);
    609   if(ret) {
    610     mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
    611     failf(data, "mbedtls_ctr_drbg_seed returned (-0x%04X) %s",
    612           -ret, errorbuf);
    613     return CURLE_FAILED_INIT;
    614   }
    615 #else
    616   mbedtls_entropy_init(&backend->entropy);
    617   mbedtls_ctr_drbg_init(&backend->ctr_drbg);
    618 
    619   ret = mbedtls_ctr_drbg_seed(&backend->ctr_drbg, mbedtls_entropy_func,
    620                               &backend->entropy, NULL, 0);
    621   if(ret) {
    622     mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
    623     failf(data, "mbedtls_ctr_drbg_seed returned (-0x%04X) %s",
    624           -ret, errorbuf);
    625     return CURLE_FAILED_INIT;
    626   }
    627 #endif /* HAS_THREADING_SUPPORT */
    628 
    629   /* Load the trusted CA */
    630   mbedtls_x509_crt_init(&backend->cacert);
    631 
    632   if(ca_info_blob && verifypeer) {
    633     /* Unfortunately, mbedtls_x509_crt_parse() requires the data to be null
    634        terminated even when provided the exact length, forcing us to waste
    635        extra memory here. */
    636     unsigned char *newblob = Curl_memdup0(ca_info_blob->data,
    637                                           ca_info_blob->len);
    638     if(!newblob)
    639       return CURLE_OUT_OF_MEMORY;
    640     ret = mbedtls_x509_crt_parse(&backend->cacert, newblob,
    641                                  ca_info_blob->len + 1);
    642     free(newblob);
    643     if(ret < 0) {
    644       mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
    645       failf(data, "Error importing ca cert blob - mbedTLS: (-0x%04X) %s",
    646             -ret, errorbuf);
    647       return CURLE_SSL_CERTPROBLEM;
    648     }
    649   }
    650 
    651   if(ssl_cafile && verifypeer) {
    652 #ifdef MBEDTLS_FS_IO
    653     ret = mbedtls_x509_crt_parse_file(&backend->cacert, ssl_cafile);
    654 
    655     if(ret < 0) {
    656       mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
    657       failf(data, "Error reading ca cert file %s - mbedTLS: (-0x%04X) %s",
    658             ssl_cafile, -ret, errorbuf);
    659       return CURLE_SSL_CACERT_BADFILE;
    660     }
    661 #else
    662     failf(data, "mbedtls: functions that use the filesystem not built in");
    663     return CURLE_NOT_BUILT_IN;
    664 #endif
    665   }
    666 
    667   if(ssl_capath) {
    668 #ifdef MBEDTLS_FS_IO
    669     ret = mbedtls_x509_crt_parse_path(&backend->cacert, ssl_capath);
    670 
    671     if(ret < 0) {
    672       mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
    673       failf(data, "Error reading ca cert path %s - mbedTLS: (-0x%04X) %s",
    674             ssl_capath, -ret, errorbuf);
    675 
    676       if(verifypeer)
    677         return CURLE_SSL_CACERT_BADFILE;
    678     }
    679 #else
    680     failf(data, "mbedtls: functions that use the filesystem not built in");
    681     return CURLE_NOT_BUILT_IN;
    682 #endif
    683   }
    684 
    685   /* Load the client certificate */
    686   mbedtls_x509_crt_init(&backend->clicert);
    687 
    688   if(ssl_cert) {
    689 #ifdef MBEDTLS_FS_IO
    690     ret = mbedtls_x509_crt_parse_file(&backend->clicert, ssl_cert);
    691 
    692     if(ret) {
    693       mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
    694       failf(data, "Error reading client cert file %s - mbedTLS: (-0x%04X) %s",
    695             ssl_cert, -ret, errorbuf);
    696 
    697       return CURLE_SSL_CERTPROBLEM;
    698     }
    699 #else
    700     failf(data, "mbedtls: functions that use the filesystem not built in");
    701     return CURLE_NOT_BUILT_IN;
    702 #endif
    703   }
    704 
    705   if(ssl_cert_blob) {
    706     /* Unfortunately, mbedtls_x509_crt_parse() requires the data to be null
    707        terminated even when provided the exact length, forcing us to waste
    708        extra memory here. */
    709     unsigned char *newblob = Curl_memdup0(ssl_cert_blob->data,
    710                                           ssl_cert_blob->len);
    711     if(!newblob)
    712       return CURLE_OUT_OF_MEMORY;
    713     ret = mbedtls_x509_crt_parse(&backend->clicert, newblob,
    714                                  ssl_cert_blob->len + 1);
    715     free(newblob);
    716 
    717     if(ret) {
    718       mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
    719       failf(data, "Error reading client cert data %s - mbedTLS: (-0x%04X) %s",
    720             ssl_config->key, -ret, errorbuf);
    721       return CURLE_SSL_CERTPROBLEM;
    722     }
    723   }
    724 
    725   /* Load the client private key */
    726   mbedtls_pk_init(&backend->pk);
    727 
    728   if(ssl_config->key || ssl_config->key_blob) {
    729     if(ssl_config->key) {
    730 #ifdef MBEDTLS_FS_IO
    731 #if MBEDTLS_VERSION_NUMBER >= 0x03000000
    732       ret = mbedtls_pk_parse_keyfile(&backend->pk, ssl_config->key,
    733                                      ssl_config->key_passwd,
    734                                      mbedtls_ctr_drbg_random,
    735                                      &backend->ctr_drbg);
    736 #else
    737       ret = mbedtls_pk_parse_keyfile(&backend->pk, ssl_config->key,
    738                                      ssl_config->key_passwd);
    739 #endif
    740       if(ret == 0 && !(mbedtls_pk_can_do(&backend->pk, MBEDTLS_PK_RSA) ||
    741                        mbedtls_pk_can_do(&backend->pk, MBEDTLS_PK_ECKEY)))
    742         ret = MBEDTLS_ERR_PK_TYPE_MISMATCH;
    743 
    744       if(ret) {
    745         mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
    746         failf(data, "Error reading private key %s - mbedTLS: (-0x%04X) %s",
    747               ssl_config->key, -ret, errorbuf);
    748         return CURLE_SSL_CERTPROBLEM;
    749       }
    750 #else
    751       failf(data, "mbedtls: functions that use the filesystem not built in");
    752       return CURLE_NOT_BUILT_IN;
    753 #endif
    754     }
    755     else {
    756       const struct curl_blob *ssl_key_blob = ssl_config->key_blob;
    757       const unsigned char *key_data =
    758         (const unsigned char *)ssl_key_blob->data;
    759       const char *passwd = ssl_config->key_passwd;
    760 #if MBEDTLS_VERSION_NUMBER >= 0x03000000
    761       ret = mbedtls_pk_parse_key(&backend->pk, key_data, ssl_key_blob->len,
    762                                  (const unsigned char *)passwd,
    763                                  passwd ? strlen(passwd) : 0,
    764                                  mbedtls_ctr_drbg_random,
    765                                  &backend->ctr_drbg);
    766 #else
    767       ret = mbedtls_pk_parse_key(&backend->pk, key_data, ssl_key_blob->len,
    768                                  (const unsigned char *)passwd,
    769                                  passwd ? strlen(passwd) : 0);
    770 #endif
    771       if(ret == 0 && !(mbedtls_pk_can_do(&backend->pk, MBEDTLS_PK_RSA) ||
    772                        mbedtls_pk_can_do(&backend->pk, MBEDTLS_PK_ECKEY)))
    773         ret = MBEDTLS_ERR_PK_TYPE_MISMATCH;
    774 
    775       if(ret) {
    776         mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
    777         failf(data, "Error parsing private key - mbedTLS: (-0x%04X) %s",
    778               -ret, errorbuf);
    779         return CURLE_SSL_CERTPROBLEM;
    780       }
    781     }
    782   }
    783 
    784   /* Load the CRL */
    785 #ifdef MBEDTLS_X509_CRL_PARSE_C
    786   mbedtls_x509_crl_init(&backend->crl);
    787 
    788   if(ssl_crlfile) {
    789 #ifdef MBEDTLS_FS_IO
    790     ret = mbedtls_x509_crl_parse_file(&backend->crl, ssl_crlfile);
    791 
    792     if(ret) {
    793       mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
    794       failf(data, "Error reading CRL file %s - mbedTLS: (-0x%04X) %s",
    795             ssl_crlfile, -ret, errorbuf);
    796 
    797       return CURLE_SSL_CRL_BADFILE;
    798     }
    799 #else
    800     failf(data, "mbedtls: functions that use the filesystem not built in");
    801     return CURLE_NOT_BUILT_IN;
    802 #endif
    803   }
    804 #else
    805   if(ssl_crlfile) {
    806     failf(data, "mbedtls: crl support not built in");
    807     return CURLE_NOT_BUILT_IN;
    808   }
    809 #endif
    810 
    811   infof(data, "mbedTLS: Connecting to %s:%d", hostname, connssl->peer.port);
    812 
    813   mbedtls_ssl_config_init(&backend->config);
    814   ret = mbedtls_ssl_config_defaults(&backend->config,
    815                                     MBEDTLS_SSL_IS_CLIENT,
    816                                     MBEDTLS_SSL_TRANSPORT_STREAM,
    817                                     MBEDTLS_SSL_PRESET_DEFAULT);
    818   if(ret) {
    819     failf(data, "mbedTLS: ssl_config failed");
    820     return CURLE_SSL_CONNECT_ERROR;
    821   }
    822 
    823 #if defined(HAS_SESSION_TICKETS) && MBEDTLS_VERSION_NUMBER >= 0x03060100
    824   /* New in mbedTLS 3.6.1, need to enable, default is now disabled */
    825   mbedtls_ssl_conf_tls13_enable_signal_new_session_tickets(&backend->config,
    826     MBEDTLS_SSL_TLS1_3_SIGNAL_NEW_SESSION_TICKETS_ENABLED);
    827 #endif
    828 
    829   /* Always let mbedTLS verify certificates, if verifypeer or verifyhost are
    830    * disabled we clear the corresponding error flags in the verify callback
    831    * function. That is also where we log verification errors. */
    832   mbedtls_ssl_conf_verify(&backend->config, mbed_verify_cb, cf);
    833   mbedtls_ssl_conf_authmode(&backend->config, MBEDTLS_SSL_VERIFY_REQUIRED);
    834 
    835   mbedtls_ssl_init(&backend->ssl);
    836   backend->initialized = TRUE;
    837 
    838   /* new profile with RSA min key len = 1024 ... */
    839   mbedtls_ssl_conf_cert_profile(&backend->config,
    840                                 &mbedtls_x509_crt_profile_fr);
    841 
    842   ret = mbed_set_ssl_version_min_max(data, backend, conn_config);
    843   if(ret != CURLE_OK)
    844     return ret;
    845 
    846   mbedtls_ssl_conf_rng(&backend->config, mbedtls_ctr_drbg_random,
    847                        &backend->ctr_drbg);
    848 
    849   ret = mbedtls_ssl_setup(&backend->ssl, &backend->config);
    850   if(ret) {
    851     mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
    852     failf(data, "ssl_setup failed - mbedTLS: (-0x%04X) %s",
    853           -ret, errorbuf);
    854     return CURLE_SSL_CONNECT_ERROR;
    855   }
    856 
    857   mbedtls_ssl_set_bio(&backend->ssl, cf,
    858                       mbedtls_bio_cf_write,
    859                       mbedtls_bio_cf_read,
    860                       NULL /*  rev_timeout() */);
    861 
    862 #ifndef HAS_TLS13_SUPPORT
    863   if(conn_config->cipher_list) {
    864     CURLcode result = mbed_set_selected_ciphers(data, backend,
    865                                                 conn_config->cipher_list,
    866                                                 NULL);
    867 #else
    868   if(conn_config->cipher_list || conn_config->cipher_list13) {
    869     CURLcode result = mbed_set_selected_ciphers(data, backend,
    870                                                 conn_config->cipher_list,
    871                                                 conn_config->cipher_list13);
    872 #endif
    873     if(result != CURLE_OK) {
    874       failf(data, "mbedTLS: failed to set cipher suites");
    875       return result;
    876     }
    877   }
    878   else {
    879     mbedtls_ssl_conf_ciphersuites(&backend->config,
    880                                   mbedtls_ssl_list_ciphersuites());
    881   }
    882 
    883 
    884 #if defined(MBEDTLS_SSL_RENEGOTIATION)
    885   mbedtls_ssl_conf_renegotiation(&backend->config,
    886                                  MBEDTLS_SSL_RENEGOTIATION_ENABLED);
    887 #endif
    888 
    889 #if defined(MBEDTLS_SSL_SESSION_TICKETS)
    890   mbedtls_ssl_conf_session_tickets(&backend->config,
    891                                    MBEDTLS_SSL_SESSION_TICKETS_DISABLED);
    892 #endif
    893 
    894   /* Check if there is a cached ID we can/should use here! */
    895   if(ssl_config->primary.cache_session) {
    896     struct Curl_ssl_session *sc_session = NULL;
    897     CURLcode result;
    898 
    899     result = Curl_ssl_scache_take(cf, data, connssl->peer.scache_key,
    900                                   &sc_session);
    901     if(!result && sc_session && sc_session->sdata && sc_session->sdata_len) {
    902       mbedtls_ssl_session session;
    903 
    904       mbedtls_ssl_session_init(&session);
    905       ret = mbedtls_ssl_session_load(&session, sc_session->sdata,
    906                                      sc_session->sdata_len);
    907       if(ret) {
    908         failf(data, "SSL session error loading: -0x%x", -ret);
    909       }
    910       else {
    911         ret = mbedtls_ssl_set_session(&backend->ssl, &session);
    912         if(ret)
    913           failf(data, "SSL session error setting: -0x%x", -ret);
    914         else
    915           infof(data, "SSL reusing session ID");
    916       }
    917       mbedtls_ssl_session_free(&session);
    918     }
    919     Curl_ssl_scache_return(cf, data, connssl->peer.scache_key, sc_session);
    920   }
    921 
    922   mbedtls_ssl_conf_ca_chain(&backend->config,
    923                             &backend->cacert,
    924 #ifdef MBEDTLS_X509_CRL_PARSE_C
    925                             &backend->crl);
    926 #else
    927                             NULL);
    928 #endif
    929 
    930   if(ssl_config->key || ssl_config->key_blob) {
    931     mbedtls_ssl_conf_own_cert(&backend->config,
    932                               &backend->clicert, &backend->pk);
    933   }
    934 
    935   if(mbedtls_ssl_set_hostname(&backend->ssl, connssl->peer.sni ?
    936                               connssl->peer.sni : connssl->peer.hostname)) {
    937     /* mbedtls_ssl_set_hostname() sets the name to use in CN/SAN checks and
    938        the name to set in the SNI extension. So even if curl connects to a
    939        host specified as an IP address, this function must be used. */
    940     failf(data, "Failed to set SNI");
    941     return CURLE_SSL_CONNECT_ERROR;
    942   }
    943 
    944 #ifdef HAS_ALPN_MBEDTLS
    945   if(connssl->alpn) {
    946     struct alpn_proto_buf proto;
    947     size_t i;
    948 
    949     for(i = 0; i < connssl->alpn->count; ++i) {
    950       backend->protocols[i] = connssl->alpn->entries[i];
    951     }
    952     /* this function does not clone the protocols array, which is why we need
    953        to keep it around */
    954     if(mbedtls_ssl_conf_alpn_protocols(&backend->config,
    955                                        &backend->protocols[0])) {
    956       failf(data, "Failed setting ALPN protocols");
    957       return CURLE_SSL_CONNECT_ERROR;
    958     }
    959     Curl_alpn_to_proto_str(&proto, connssl->alpn);
    960     infof(data, VTLS_INFOF_ALPN_OFFER_1STR, proto.data);
    961   }
    962 #endif
    963 
    964 #ifdef MBEDTLS_DEBUG
    965   /* In order to make that work in mbedtls MBEDTLS_DEBUG_C must be defined. */
    966   mbedtls_ssl_conf_dbg(&backend->config, mbed_debug, data);
    967   /* - 0 No debug
    968    * - 1 Error
    969    * - 2 State change
    970    * - 3 Informational
    971    * - 4 Verbose
    972    */
    973   mbedtls_debug_set_threshold(4);
    974 #endif
    975 
    976   /* give application a chance to interfere with mbedTLS set up. */
    977   if(data->set.ssl.fsslctx) {
    978     CURLcode result = (*data->set.ssl.fsslctx)(data, &backend->config,
    979                                                data->set.ssl.fsslctxp);
    980     if(result != CURLE_OK) {
    981       failf(data, "error signaled by ssl ctx callback");
    982       return result;
    983     }
    984   }
    985 
    986   connssl->connecting_state = ssl_connect_2;
    987 
    988   return CURLE_OK;
    989 }
    990 
    991 static CURLcode
    992 mbed_connect_step2(struct Curl_cfilter *cf, struct Curl_easy *data)
    993 {
    994   int ret;
    995   struct ssl_connect_data *connssl = cf->ctx;
    996   struct mbed_ssl_backend_data *backend =
    997     (struct mbed_ssl_backend_data *)connssl->backend;
    998 #ifndef CURL_DISABLE_PROXY
    999   const char * const pinnedpubkey = Curl_ssl_cf_is_proxy(cf) ?
   1000     data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] :
   1001     data->set.str[STRING_SSL_PINNEDPUBLICKEY];
   1002 #else
   1003   const char * const pinnedpubkey = data->set.str[STRING_SSL_PINNEDPUBLICKEY];
   1004 #endif
   1005 
   1006   DEBUGASSERT(backend);
   1007 
   1008   ret = mbedtls_ssl_handshake(&backend->ssl);
   1009 
   1010   if(ret == MBEDTLS_ERR_SSL_WANT_READ) {
   1011     connssl->io_need = CURL_SSL_IO_NEED_RECV;
   1012     return CURLE_OK;
   1013   }
   1014   else if(ret == MBEDTLS_ERR_SSL_WANT_WRITE) {
   1015     connssl->io_need = CURL_SSL_IO_NEED_SEND;
   1016     return CURLE_OK;
   1017   }
   1018   else if(ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED) {
   1019     failf(data, "peer certificate could not be verified");
   1020     return CURLE_PEER_FAILED_VERIFICATION;
   1021   }
   1022   else if(ret) {
   1023     char errorbuf[128];
   1024 #if MBEDTLS_VERSION_NUMBER >= 0x03020000
   1025     CURL_TRC_CF(data, cf, "TLS version %04X",
   1026                 mbedtls_ssl_get_version_number(&backend->ssl));
   1027 #endif
   1028     mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
   1029     failf(data, "ssl_handshake returned: (-0x%04X) %s",
   1030           -ret, errorbuf);
   1031     return CURLE_SSL_CONNECT_ERROR;
   1032   }
   1033 
   1034 #if MBEDTLS_VERSION_NUMBER >= 0x03020000
   1035   {
   1036     char cipher_str[64];
   1037     uint16_t cipher_id;
   1038     cipher_id = (uint16_t)
   1039                 mbedtls_ssl_get_ciphersuite_id_from_ssl(&backend->ssl);
   1040     mbed_cipher_suite_get_str(cipher_id, cipher_str, sizeof(cipher_str), TRUE);
   1041     infof(data, "mbedTLS: %s Handshake complete, cipher is %s",
   1042           mbedtls_ssl_get_version(&backend->ssl), cipher_str);
   1043   }
   1044 #else
   1045   infof(data, "mbedTLS: %s Handshake complete",
   1046         mbedtls_ssl_get_version(&backend->ssl));
   1047 #endif
   1048 
   1049   if(pinnedpubkey) {
   1050     int size;
   1051     CURLcode result;
   1052     const mbedtls_x509_crt *peercert;
   1053     mbedtls_x509_crt *p = NULL;
   1054     unsigned char *pubkey = NULL;
   1055 
   1056     peercert = mbedtls_ssl_get_peer_cert(&backend->ssl);
   1057 #if MBEDTLS_VERSION_NUMBER == 0x03000000
   1058     if(!peercert || !peercert->MBEDTLS_PRIVATE(raw).MBEDTLS_PRIVATE(p) ||
   1059        !peercert->MBEDTLS_PRIVATE(raw).MBEDTLS_PRIVATE(len)) {
   1060 #else
   1061     if(!peercert || !peercert->raw.p || !peercert->raw.len) {
   1062 #endif
   1063       failf(data, "Failed due to missing peer certificate");
   1064       return CURLE_SSL_PINNEDPUBKEYNOTMATCH;
   1065     }
   1066 
   1067     p = calloc(1, sizeof(*p));
   1068 
   1069     if(!p)
   1070       return CURLE_OUT_OF_MEMORY;
   1071 
   1072     pubkey = malloc(PUB_DER_MAX_BYTES);
   1073 
   1074     if(!pubkey) {
   1075       result = CURLE_OUT_OF_MEMORY;
   1076       goto pinnedpubkey_error;
   1077     }
   1078 
   1079     mbedtls_x509_crt_init(p);
   1080 
   1081     /* Make a copy of our const peercert because mbedtls_pk_write_pubkey_der
   1082        needs a non-const key, for now.
   1083        https://github.com/Mbed-TLS/mbedtls/issues/396 */
   1084 #if MBEDTLS_VERSION_NUMBER == 0x03000000
   1085     if(mbedtls_x509_crt_parse_der(p,
   1086                         peercert->MBEDTLS_PRIVATE(raw).MBEDTLS_PRIVATE(p),
   1087                         peercert->MBEDTLS_PRIVATE(raw).MBEDTLS_PRIVATE(len))) {
   1088 #else
   1089     if(mbedtls_x509_crt_parse_der(p, peercert->raw.p, peercert->raw.len)) {
   1090 #endif
   1091       failf(data, "Failed copying peer certificate");
   1092       result = CURLE_SSL_PINNEDPUBKEYNOTMATCH;
   1093       goto pinnedpubkey_error;
   1094     }
   1095 
   1096 #if MBEDTLS_VERSION_NUMBER == 0x03000000
   1097     size = mbedtls_pk_write_pubkey_der(&p->MBEDTLS_PRIVATE(pk), pubkey,
   1098                                        PUB_DER_MAX_BYTES);
   1099 #else
   1100     size = mbedtls_pk_write_pubkey_der(&p->pk, pubkey, PUB_DER_MAX_BYTES);
   1101 #endif
   1102 
   1103     if(size <= 0) {
   1104       failf(data, "Failed copying public key from peer certificate");
   1105       result = CURLE_SSL_PINNEDPUBKEYNOTMATCH;
   1106       goto pinnedpubkey_error;
   1107     }
   1108 
   1109     /* mbedtls_pk_write_pubkey_der writes data at the end of the buffer. */
   1110     result = Curl_pin_peer_pubkey(data,
   1111                                   pinnedpubkey,
   1112                                   &pubkey[PUB_DER_MAX_BYTES - size], size);
   1113 pinnedpubkey_error:
   1114     mbedtls_x509_crt_free(p);
   1115     free(p);
   1116     free(pubkey);
   1117     if(result) {
   1118       return result;
   1119     }
   1120   }
   1121 
   1122 #ifdef HAS_ALPN_MBEDTLS
   1123   if(connssl->alpn) {
   1124     const char *proto = mbedtls_ssl_get_alpn_protocol(&backend->ssl);
   1125 
   1126     Curl_alpn_set_negotiated(cf, data, connssl, (const unsigned char *)proto,
   1127                              proto ? strlen(proto) : 0);
   1128   }
   1129 #endif
   1130 
   1131   connssl->connecting_state = ssl_connect_3;
   1132   infof(data, "SSL connected");
   1133 
   1134   return CURLE_OK;
   1135 }
   1136 
   1137 static CURLcode
   1138 mbed_new_session(struct Curl_cfilter *cf, struct Curl_easy *data)
   1139 {
   1140   struct ssl_connect_data *connssl = cf->ctx;
   1141   struct mbed_ssl_backend_data *backend =
   1142     (struct mbed_ssl_backend_data *)connssl->backend;
   1143   struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
   1144   mbedtls_ssl_session session;
   1145   bool msession_alloced = FALSE;
   1146   struct Curl_ssl_session *sc_session = NULL;
   1147   unsigned char *sdata = NULL;
   1148   size_t slen = 0;
   1149   int ietf_tls_id;
   1150   CURLcode result = CURLE_OK;
   1151   int ret;
   1152 
   1153   DEBUGASSERT(backend);
   1154   if(!ssl_config->primary.cache_session)
   1155     return CURLE_OK;
   1156 
   1157   mbedtls_ssl_session_init(&session);
   1158   ret = mbedtls_ssl_get_session(&backend->ssl, &session);
   1159   msession_alloced = (ret != MBEDTLS_ERR_SSL_ALLOC_FAILED);
   1160   if(ret) {
   1161     failf(data, "mbedtls_ssl_get_session returned -0x%x", -ret);
   1162     result = CURLE_SSL_CONNECT_ERROR;
   1163     goto out;
   1164   }
   1165 
   1166   mbedtls_ssl_session_save(&session, NULL, 0, &slen);
   1167   if(!slen) {
   1168     failf(data, "failed to serialize session: length is 0");
   1169     goto out;
   1170   }
   1171 
   1172   sdata = malloc(slen);
   1173   if(!sdata) {
   1174     result = CURLE_OUT_OF_MEMORY;
   1175     goto out;
   1176   }
   1177 
   1178   ret = mbedtls_ssl_session_save(&session, sdata, slen, &slen);
   1179   if(ret) {
   1180     failf(data, "failed to serialize session: -0x%x", -ret);
   1181     goto out;
   1182   }
   1183 
   1184 #if MBEDTLS_VERSION_NUMBER >= 0x03020000
   1185   ietf_tls_id = mbedtls_ssl_get_version_number(&backend->ssl);
   1186 #else
   1187   ietf_tls_id = CURL_IETF_PROTO_UNKNOWN;
   1188 #endif
   1189   result = Curl_ssl_session_create(sdata, slen,
   1190                                    ietf_tls_id,
   1191                                    connssl->negotiated.alpn, 0, 0,
   1192                                    &sc_session);
   1193   sdata = NULL;  /* call took ownership */
   1194   if(!result)
   1195     result = Curl_ssl_scache_put(cf, data, connssl->peer.scache_key,
   1196                                  sc_session);
   1197 
   1198 out:
   1199   if(msession_alloced)
   1200     mbedtls_ssl_session_free(&session);
   1201   free(sdata);
   1202   return result;
   1203 }
   1204 
   1205 static CURLcode mbed_send(struct Curl_cfilter *cf, struct Curl_easy *data,
   1206                           const void *mem, size_t len,
   1207                           size_t *pnwritten)
   1208 {
   1209   struct ssl_connect_data *connssl = cf->ctx;
   1210   struct mbed_ssl_backend_data *backend =
   1211     (struct mbed_ssl_backend_data *)connssl->backend;
   1212   CURLcode result = CURLE_OK;
   1213   int nwritten;
   1214 
   1215   (void)data;
   1216   *pnwritten = 0;
   1217   DEBUGASSERT(backend);
   1218   /* mbedtls is picky when a mbedtls_ssl_write) was previously blocked.
   1219    * It requires to be called with the same amount of bytes again, or it
   1220    * will lose bytes, e.g. reporting all was sent but they were not.
   1221    * Remember the blocked length and use that when set. */
   1222   if(backend->send_blocked) {
   1223     DEBUGASSERT(backend->send_blocked_len <= len);
   1224     CURL_TRC_CF(data, cf, "mbedtls_ssl_write(len=%zu) -> previously blocked "
   1225                 "on %zu bytes", len, backend->send_blocked_len);
   1226     len = backend->send_blocked_len;
   1227   }
   1228 
   1229   nwritten = mbedtls_ssl_write(&backend->ssl, (const unsigned char *)mem, len);
   1230 
   1231   if(nwritten >= 0) {
   1232     *pnwritten = (size_t)nwritten;
   1233     backend->send_blocked = FALSE;
   1234   }
   1235   else {
   1236     CURL_TRC_CF(data, cf, "mbedtls_ssl_write(len=%zu) -> -0x%04X",
   1237                 len, -nwritten);
   1238     result = ((nwritten == MBEDTLS_ERR_SSL_WANT_WRITE)
   1239 #ifdef HAS_TLS13_SUPPORT
   1240       || (nwritten == MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET)
   1241 #endif
   1242       ) ? CURLE_AGAIN : CURLE_SEND_ERROR;
   1243     if((result == CURLE_AGAIN) && !backend->send_blocked) {
   1244       backend->send_blocked = TRUE;
   1245       backend->send_blocked_len = len;
   1246     }
   1247   }
   1248 
   1249   CURL_TRC_CF(data, cf, "mbedtls_ssl_write(len=%zu) -> %d, %zu",
   1250               len, result, *pnwritten);
   1251   return result;
   1252 }
   1253 
   1254 static CURLcode mbedtls_shutdown(struct Curl_cfilter *cf,
   1255                                  struct Curl_easy *data,
   1256                                  bool send_shutdown, bool *done)
   1257 {
   1258   struct ssl_connect_data *connssl = cf->ctx;
   1259   struct mbed_ssl_backend_data *backend =
   1260     (struct mbed_ssl_backend_data *)connssl->backend;
   1261   unsigned char buf[1024];
   1262   CURLcode result = CURLE_OK;
   1263   int ret;
   1264   size_t i;
   1265 
   1266   DEBUGASSERT(backend);
   1267 
   1268   if(!backend->initialized || cf->shutdown) {
   1269     *done = TRUE;
   1270     return CURLE_OK;
   1271   }
   1272 
   1273   connssl->io_need = CURL_SSL_IO_NEED_NONE;
   1274   *done = FALSE;
   1275 
   1276   if(!backend->sent_shutdown) {
   1277     /* do this only once */
   1278     backend->sent_shutdown = TRUE;
   1279     if(send_shutdown) {
   1280       ret = mbedtls_ssl_close_notify(&backend->ssl);
   1281       switch(ret) {
   1282       case 0: /* we sent it, receive from the server */
   1283         break;
   1284       case MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY: /* server also closed */
   1285         *done = TRUE;
   1286         goto out;
   1287       case MBEDTLS_ERR_SSL_WANT_READ:
   1288         connssl->io_need = CURL_SSL_IO_NEED_RECV;
   1289         goto out;
   1290       case MBEDTLS_ERR_SSL_WANT_WRITE:
   1291         connssl->io_need = CURL_SSL_IO_NEED_SEND;
   1292         goto out;
   1293       default:
   1294         CURL_TRC_CF(data, cf, "mbedtls_shutdown error -0x%04X", -ret);
   1295         result = CURLE_RECV_ERROR;
   1296         goto out;
   1297       }
   1298     }
   1299   }
   1300 
   1301   /* SSL should now have started the shutdown from our side. Since it
   1302    * was not complete, we are lacking the close notify from the server. */
   1303   for(i = 0; i < 10; ++i) {
   1304     ret = mbedtls_ssl_read(&backend->ssl, buf, sizeof(buf));
   1305     /* This seems to be a bug in mbedTLS TLSv1.3 where it reports
   1306      * WANT_READ, but has not encountered an EAGAIN. */
   1307     if(ret == MBEDTLS_ERR_SSL_WANT_READ)
   1308       ret = mbedtls_ssl_read(&backend->ssl, buf, sizeof(buf));
   1309 #ifdef HAS_TLS13_SUPPORT
   1310     if(ret == MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET)
   1311       continue;
   1312 #endif
   1313     if(ret <= 0)
   1314       break;
   1315   }
   1316 
   1317   if(ret > 0) {
   1318     /* still data coming in? */
   1319     CURL_TRC_CF(data, cf, "mbedtls_shutdown, still getting data");
   1320   }
   1321   else if(ret == 0 || (ret == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY)) {
   1322     /* We got the close notify alert and are done. */
   1323     CURL_TRC_CF(data, cf, "mbedtls_shutdown done");
   1324     *done = TRUE;
   1325   }
   1326   else if(ret == MBEDTLS_ERR_SSL_WANT_READ) {
   1327     CURL_TRC_CF(data, cf, "mbedtls_shutdown, need RECV");
   1328     connssl->io_need = CURL_SSL_IO_NEED_RECV;
   1329   }
   1330   else if(ret == MBEDTLS_ERR_SSL_WANT_WRITE) {
   1331     CURL_TRC_CF(data, cf, "mbedtls_shutdown, need SEND");
   1332     connssl->io_need = CURL_SSL_IO_NEED_SEND;
   1333   }
   1334   else {
   1335     CURL_TRC_CF(data, cf, "mbedtls_shutdown error -0x%04X", -ret);
   1336     result = CURLE_RECV_ERROR;
   1337   }
   1338 
   1339 out:
   1340   cf->shutdown = (result || *done);
   1341   return result;
   1342 }
   1343 
   1344 static void mbedtls_close(struct Curl_cfilter *cf, struct Curl_easy *data)
   1345 {
   1346   struct ssl_connect_data *connssl = cf->ctx;
   1347   struct mbed_ssl_backend_data *backend =
   1348     (struct mbed_ssl_backend_data *)connssl->backend;
   1349 
   1350   (void)data;
   1351   DEBUGASSERT(backend);
   1352   if(backend->initialized) {
   1353     mbedtls_pk_free(&backend->pk);
   1354     mbedtls_x509_crt_free(&backend->clicert);
   1355     mbedtls_x509_crt_free(&backend->cacert);
   1356 #ifdef MBEDTLS_X509_CRL_PARSE_C
   1357     mbedtls_x509_crl_free(&backend->crl);
   1358 #endif
   1359     Curl_safefree(backend->ciphersuites);
   1360     mbedtls_ssl_config_free(&backend->config);
   1361     mbedtls_ssl_free(&backend->ssl);
   1362     mbedtls_ctr_drbg_free(&backend->ctr_drbg);
   1363 #ifndef HAS_THREADING_SUPPORT
   1364     mbedtls_entropy_free(&backend->entropy);
   1365 #endif /* HAS_THREADING_SUPPORT */
   1366     backend->initialized = FALSE;
   1367   }
   1368 }
   1369 
   1370 static CURLcode mbed_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
   1371                           char *buf, size_t buffersize,
   1372                           size_t *pnread)
   1373 {
   1374   struct ssl_connect_data *connssl = cf->ctx;
   1375   struct mbed_ssl_backend_data *backend =
   1376     (struct mbed_ssl_backend_data *)connssl->backend;
   1377   CURLcode result = CURLE_OK;
   1378   int nread;
   1379 
   1380   (void)data;
   1381   DEBUGASSERT(backend);
   1382   *pnread = 0;
   1383 
   1384   nread = mbedtls_ssl_read(&backend->ssl, (unsigned char *)buf, buffersize);
   1385   if(nread > 0)
   1386     *pnread = (size_t)nread;
   1387   else {
   1388     CURL_TRC_CF(data, cf, "mbedtls_ssl_read(len=%zu) -> -0x%04X",
   1389                 buffersize, -nread);
   1390     switch(nread) {
   1391 #ifdef HAS_SESSION_TICKETS
   1392     case MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET:
   1393       mbed_new_session(cf, data);
   1394       FALLTHROUGH();
   1395 #endif
   1396     case MBEDTLS_ERR_SSL_WANT_READ:
   1397       result = CURLE_AGAIN;
   1398       break;
   1399     case MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY:
   1400       result = CURLE_OK;
   1401       break;
   1402     default: {
   1403       char errorbuf[128];
   1404       mbedtls_strerror(nread, errorbuf, sizeof(errorbuf));
   1405       failf(data, "ssl_read returned: (-0x%04X) %s", -nread, errorbuf);
   1406       result = CURLE_RECV_ERROR;
   1407       break;
   1408     }
   1409     }
   1410   }
   1411   return result;
   1412 }
   1413 
   1414 static size_t mbedtls_version(char *buffer, size_t size)
   1415 {
   1416 #ifdef MBEDTLS_VERSION_C
   1417   /* if mbedtls_version_get_number() is available it is better */
   1418   unsigned int version = mbedtls_version_get_number();
   1419   return msnprintf(buffer, size, "mbedTLS/%u.%u.%u", version >> 24,
   1420                    (version >> 16) & 0xff, (version >> 8) & 0xff);
   1421 #else
   1422   return msnprintf(buffer, size, "mbedTLS/%s", MBEDTLS_VERSION_STRING);
   1423 #endif
   1424 }
   1425 
   1426 /* 'data' might be NULL */
   1427 static CURLcode mbedtls_random(struct Curl_easy *data,
   1428                                unsigned char *entropy, size_t length)
   1429 {
   1430 #if defined(MBEDTLS_CTR_DRBG_C)
   1431   int ret;
   1432   mbedtls_entropy_context ctr_entropy;
   1433   mbedtls_ctr_drbg_context ctr_drbg;
   1434   mbedtls_entropy_init(&ctr_entropy);
   1435   mbedtls_ctr_drbg_init(&ctr_drbg);
   1436   (void)data;
   1437 
   1438   ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func,
   1439                               &ctr_entropy, NULL, 0);
   1440 
   1441   if(!ret)
   1442     ret = mbedtls_ctr_drbg_random(&ctr_drbg, entropy, length);
   1443 
   1444   mbedtls_ctr_drbg_free(&ctr_drbg);
   1445   mbedtls_entropy_free(&ctr_entropy);
   1446 
   1447   return ret == 0 ? CURLE_OK : CURLE_FAILED_INIT;
   1448 #elif defined(MBEDTLS_HAVEGE_C)
   1449   mbedtls_havege_state hs;
   1450   mbedtls_havege_init(&hs);
   1451   mbedtls_havege_random(&hs, entropy, length);
   1452   mbedtls_havege_free(&hs);
   1453   return CURLE_OK;
   1454 #else
   1455   return CURLE_NOT_BUILT_IN;
   1456 #endif
   1457 }
   1458 
   1459 static CURLcode mbedtls_connect(struct Curl_cfilter *cf,
   1460                                 struct Curl_easy *data,
   1461                                 bool *done)
   1462 {
   1463   CURLcode retcode;
   1464   struct ssl_connect_data *connssl = cf->ctx;
   1465 
   1466   /* check if the connection has already been established */
   1467   if(ssl_connection_complete == connssl->state) {
   1468     *done = TRUE;
   1469     return CURLE_OK;
   1470   }
   1471 
   1472   *done = FALSE;
   1473   connssl->io_need = CURL_SSL_IO_NEED_NONE;
   1474 
   1475   if(ssl_connect_1 == connssl->connecting_state) {
   1476     retcode = mbed_connect_step1(cf, data);
   1477     if(retcode)
   1478       return retcode;
   1479   }
   1480 
   1481   if(ssl_connect_2 == connssl->connecting_state) {
   1482     retcode = mbed_connect_step2(cf, data);
   1483     if(retcode)
   1484       return retcode;
   1485   }
   1486 
   1487   if(ssl_connect_3 == connssl->connecting_state) {
   1488     /* For tls1.3 we get notified about new sessions */
   1489 #if MBEDTLS_VERSION_NUMBER >= 0x03020000
   1490     struct ssl_connect_data *ctx = cf->ctx;
   1491     struct mbed_ssl_backend_data *backend =
   1492       (struct mbed_ssl_backend_data *)ctx->backend;
   1493 
   1494     if(mbedtls_ssl_get_version_number(&backend->ssl) <=
   1495        MBEDTLS_SSL_VERSION_TLS1_2) {
   1496 #else
   1497     {  /* no TLSv1.3 supported here */
   1498 #endif
   1499       retcode = mbed_new_session(cf, data);
   1500       if(retcode)
   1501         return retcode;
   1502     }
   1503     connssl->connecting_state = ssl_connect_done;
   1504   }
   1505 
   1506   if(ssl_connect_done == connssl->connecting_state) {
   1507     connssl->state = ssl_connection_complete;
   1508     *done = TRUE;
   1509   }
   1510 
   1511   return CURLE_OK;
   1512 }
   1513 
   1514 /*
   1515  * return 0 error initializing SSL
   1516  * return 1 SSL initialized successfully
   1517  */
   1518 static int mbedtls_init(void)
   1519 {
   1520   if(!Curl_mbedtlsthreadlock_thread_setup())
   1521     return 0;
   1522 #ifdef HAS_THREADING_SUPPORT
   1523   entropy_init_mutex(&ts_entropy);
   1524 #endif
   1525 #ifdef HAS_PSA_SUPPORT
   1526   {
   1527     int ret;
   1528 #ifdef HAS_THREADING_SUPPORT
   1529     Curl_mbedtlsthreadlock_lock_function(0);
   1530 #endif
   1531     ret = psa_crypto_init();
   1532 #ifdef HAS_THREADING_SUPPORT
   1533     Curl_mbedtlsthreadlock_unlock_function(0);
   1534 #endif
   1535     if(ret != PSA_SUCCESS)
   1536       return 0;
   1537   }
   1538 #endif /* HAS_PSA_SUPPORT */
   1539   return 1;
   1540 }
   1541 
   1542 static void mbedtls_cleanup(void)
   1543 {
   1544 #ifdef HAS_THREADING_SUPPORT
   1545   entropy_cleanup_mutex(&ts_entropy);
   1546 #endif
   1547   (void)Curl_mbedtlsthreadlock_thread_cleanup();
   1548 }
   1549 
   1550 static bool mbedtls_data_pending(struct Curl_cfilter *cf,
   1551                                  const struct Curl_easy *data)
   1552 {
   1553   struct ssl_connect_data *ctx = cf->ctx;
   1554   struct mbed_ssl_backend_data *backend;
   1555 
   1556   (void)data;
   1557   DEBUGASSERT(ctx && ctx->backend);
   1558   backend = (struct mbed_ssl_backend_data *)ctx->backend;
   1559   return mbedtls_ssl_get_bytes_avail(&backend->ssl) != 0;
   1560 }
   1561 
   1562 static CURLcode mbedtls_sha256sum(const unsigned char *input,
   1563                                   size_t inputlen,
   1564                                   unsigned char *sha256sum,
   1565                                   size_t sha256len UNUSED_PARAM)
   1566 {
   1567   (void)sha256len;
   1568 #if MBEDTLS_VERSION_NUMBER < 0x02070000
   1569   mbedtls_sha256(input, inputlen, sha256sum, 0);
   1570 #else
   1571   /* returns 0 on success, otherwise failure */
   1572 #if MBEDTLS_VERSION_NUMBER >= 0x03000000
   1573   if(mbedtls_sha256(input, inputlen, sha256sum, 0) != 0)
   1574 #else
   1575   if(mbedtls_sha256_ret(input, inputlen, sha256sum, 0) != 0)
   1576 #endif
   1577     return CURLE_BAD_FUNCTION_ARGUMENT;
   1578 #endif
   1579   return CURLE_OK;
   1580 }
   1581 
   1582 static void *mbedtls_get_internals(struct ssl_connect_data *connssl,
   1583                                    CURLINFO info UNUSED_PARAM)
   1584 {
   1585   struct mbed_ssl_backend_data *backend =
   1586     (struct mbed_ssl_backend_data *)connssl->backend;
   1587   (void)info;
   1588   DEBUGASSERT(backend);
   1589   return &backend->ssl;
   1590 }
   1591 
   1592 const struct Curl_ssl Curl_ssl_mbedtls = {
   1593   { CURLSSLBACKEND_MBEDTLS, "mbedtls" }, /* info */
   1594 
   1595   SSLSUPP_CA_PATH |
   1596   SSLSUPP_CAINFO_BLOB |
   1597   SSLSUPP_CERTINFO |
   1598   SSLSUPP_PINNEDPUBKEY |
   1599   SSLSUPP_SSL_CTX |
   1600 #ifdef HAS_TLS13_SUPPORT
   1601   SSLSUPP_TLS13_CIPHERSUITES |
   1602 #endif
   1603   SSLSUPP_HTTPS_PROXY |
   1604   SSLSUPP_CIPHER_LIST,
   1605 
   1606   sizeof(struct mbed_ssl_backend_data),
   1607 
   1608   mbedtls_init,                     /* init */
   1609   mbedtls_cleanup,                  /* cleanup */
   1610   mbedtls_version,                  /* version */
   1611   mbedtls_shutdown,                 /* shutdown */
   1612   mbedtls_data_pending,             /* data_pending */
   1613   mbedtls_random,                   /* random */
   1614   NULL,                             /* cert_status_request */
   1615   mbedtls_connect,                  /* connect */
   1616   Curl_ssl_adjust_pollset,          /* adjust_pollset */
   1617   mbedtls_get_internals,            /* get_internals */
   1618   mbedtls_close,                    /* close_one */
   1619   NULL,                             /* close_all */
   1620   NULL,                             /* set_engine */
   1621   NULL,                             /* set_engine_default */
   1622   NULL,                             /* engines_list */
   1623   mbedtls_sha256sum,                /* sha256sum */
   1624   mbed_recv,                        /* recv decrypted data */
   1625   mbed_send,                        /* send data to encrypt */
   1626   NULL,                             /* get_channel_binding */
   1627 };
   1628 
   1629 #endif /* USE_MBEDTLS */