quickjs-tart

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

gtls.c (71376B)


      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 GnuTLS-specific code for the TLS/SSL layer. No code
     27  * but vtls.c should ever call or use these functions.
     28  *
     29  * Note: do not use the GnuTLS' *_t variable type names in this source code,
     30  * since they were not present in 1.0.X.
     31  */
     32 
     33 #include "../curl_setup.h"
     34 
     35 #ifdef USE_GNUTLS
     36 
     37 #include <gnutls/abstract.h>
     38 #include <gnutls/gnutls.h>
     39 #include <gnutls/x509.h>
     40 #include <gnutls/crypto.h>
     41 #include <nettle/sha2.h>
     42 
     43 #include "../urldata.h"
     44 #include "../sendf.h"
     45 #include "../curlx/inet_pton.h"
     46 #include "keylog.h"
     47 #include "gtls.h"
     48 #include "vtls.h"
     49 #include "vtls_int.h"
     50 #include "vtls_scache.h"
     51 #include "../vauth/vauth.h"
     52 #include "../parsedate.h"
     53 #include "../connect.h" /* for the connect timeout */
     54 #include "../progress.h"
     55 #include "../select.h"
     56 #include "../strdup.h"
     57 #include "../curlx/warnless.h"
     58 #include "x509asn1.h"
     59 #include "../multiif.h"
     60 #include "../curl_printf.h"
     61 #include "../curl_memory.h"
     62 /* The last #include file should be: */
     63 #include "../memdebug.h"
     64 
     65 /* Enable GnuTLS debugging by defining GTLSDEBUG */
     66 /*#define GTLSDEBUG */
     67 
     68 #ifdef GTLSDEBUG
     69 static void tls_log_func(int level, const char *str)
     70 {
     71     fprintf(stderr, "|<%d>| %s", level, str);
     72 }
     73 #endif
     74 static bool gtls_inited = FALSE;
     75 
     76 #if !defined(GNUTLS_VERSION_NUMBER) || (GNUTLS_VERSION_NUMBER < 0x03010a)
     77 #error "too old GnuTLS version"
     78 #endif
     79 
     80 # include <gnutls/ocsp.h>
     81 
     82 struct gtls_ssl_backend_data {
     83   struct gtls_ctx gtls;
     84 };
     85 
     86 static ssize_t gtls_push(void *s, const void *buf, size_t blen)
     87 {
     88   struct Curl_cfilter *cf = s;
     89   struct ssl_connect_data *connssl = cf->ctx;
     90   struct gtls_ssl_backend_data *backend =
     91     (struct gtls_ssl_backend_data *)connssl->backend;
     92   struct Curl_easy *data = CF_DATA_CURRENT(cf);
     93   size_t nwritten;
     94   CURLcode result;
     95 
     96   DEBUGASSERT(data);
     97   result = Curl_conn_cf_send(cf->next, data, buf, blen, FALSE, &nwritten);
     98   CURL_TRC_CF(data, cf, "gtls_push(len=%zu) -> %d, %zu",
     99               blen, result, nwritten);
    100   backend->gtls.io_result = result;
    101   if(result) {
    102     /* !checksrc! disable ERRNOVAR 1 */
    103     gnutls_transport_set_errno(backend->gtls.session,
    104                                (CURLE_AGAIN == result) ? EAGAIN : EINVAL);
    105     return -1;
    106   }
    107   return (ssize_t)nwritten;
    108 }
    109 
    110 static ssize_t gtls_pull(void *s, void *buf, size_t blen)
    111 {
    112   struct Curl_cfilter *cf = s;
    113   struct ssl_connect_data *connssl = cf->ctx;
    114   struct gtls_ssl_backend_data *backend =
    115     (struct gtls_ssl_backend_data *)connssl->backend;
    116   struct Curl_easy *data = CF_DATA_CURRENT(cf);
    117   size_t nread;
    118   CURLcode result;
    119 
    120   DEBUGASSERT(data);
    121   if(!backend->gtls.shared_creds->trust_setup) {
    122     result = Curl_gtls_client_trust_setup(cf, data, &backend->gtls);
    123     if(result) {
    124       /* !checksrc! disable ERRNOVAR 1 */
    125       gnutls_transport_set_errno(backend->gtls.session, EINVAL);
    126       backend->gtls.io_result = result;
    127       return -1;
    128     }
    129   }
    130 
    131   result = Curl_conn_cf_recv(cf->next, data, buf, blen, &nread);
    132   CURL_TRC_CF(data, cf, "glts_pull(len=%zu) -> %d, %zd",
    133               blen, result, nread);
    134   backend->gtls.io_result = result;
    135   if(result) {
    136     /* !checksrc! disable ERRNOVAR 1 */
    137     gnutls_transport_set_errno(backend->gtls.session,
    138                                (CURLE_AGAIN == result) ? EAGAIN : EINVAL);
    139     return -1;
    140   }
    141   else if(nread == 0)
    142     connssl->peer_closed = TRUE;
    143   return (ssize_t)nread;
    144 }
    145 
    146 /* gtls_init()
    147  *
    148  * Global GnuTLS init, called from Curl_ssl_init(). This calls functions that
    149  * are not thread-safe and thus this function itself is not thread-safe and
    150  * must only be called from within curl_global_init() to keep the thread
    151  * situation under control!
    152  */
    153 static int gtls_init(void)
    154 {
    155   int ret = 1;
    156   if(!gtls_inited) {
    157     ret = gnutls_global_init() ? 0 : 1;
    158 #ifdef GTLSDEBUG
    159     gnutls_global_set_log_function(tls_log_func);
    160     gnutls_global_set_log_level(2);
    161 #endif
    162     gtls_inited = TRUE;
    163   }
    164   return ret;
    165 }
    166 
    167 static void gtls_cleanup(void)
    168 {
    169   if(gtls_inited) {
    170     gnutls_global_deinit();
    171     gtls_inited = FALSE;
    172   }
    173 }
    174 
    175 #ifndef CURL_DISABLE_VERBOSE_STRINGS
    176 static void showtime(struct Curl_easy *data,
    177                      const char *text,
    178                      time_t stamp)
    179 {
    180   struct tm buffer;
    181   const struct tm *tm = &buffer;
    182   char str[96];
    183   CURLcode result = Curl_gmtime(stamp, &buffer);
    184   if(result)
    185     return;
    186 
    187   msnprintf(str,
    188             sizeof(str),
    189             "  %s: %s, %02d %s %4d %02d:%02d:%02d GMT",
    190             text,
    191             Curl_wkday[tm->tm_wday ? tm->tm_wday-1 : 6],
    192             tm->tm_mday,
    193             Curl_month[tm->tm_mon],
    194             tm->tm_year + 1900,
    195             tm->tm_hour,
    196             tm->tm_min,
    197             tm->tm_sec);
    198   infof(data, "%s", str);
    199 }
    200 #endif
    201 
    202 static gnutls_datum_t load_file(const char *file)
    203 {
    204   FILE *f;
    205   gnutls_datum_t loaded_file = { NULL, 0 };
    206   long filelen;
    207   void *ptr;
    208 
    209   f = fopen(file, "rb");
    210   if(!f)
    211     return loaded_file;
    212   if(fseek(f, 0, SEEK_END) != 0
    213      || (filelen = ftell(f)) < 0
    214      || fseek(f, 0, SEEK_SET) != 0
    215      || !(ptr = malloc((size_t)filelen)))
    216     goto out;
    217   if(fread(ptr, 1, (size_t)filelen, f) < (size_t)filelen) {
    218     free(ptr);
    219     goto out;
    220   }
    221 
    222   loaded_file.data = ptr;
    223   loaded_file.size = (unsigned int)filelen;
    224 out:
    225   fclose(f);
    226   return loaded_file;
    227 }
    228 
    229 static void unload_file(gnutls_datum_t data)
    230 {
    231   free(data.data);
    232 }
    233 
    234 
    235 /* this function does an SSL/TLS (re-)handshake */
    236 static CURLcode handshake(struct Curl_cfilter *cf,
    237                           struct Curl_easy *data)
    238 {
    239   struct ssl_connect_data *connssl = cf->ctx;
    240   struct gtls_ssl_backend_data *backend =
    241     (struct gtls_ssl_backend_data *)connssl->backend;
    242   gnutls_session_t session;
    243   int rc;
    244 
    245   DEBUGASSERT(backend);
    246   session = backend->gtls.session;
    247 
    248   connssl->io_need = CURL_SSL_IO_NEED_NONE;
    249   backend->gtls.io_result = CURLE_OK;
    250   rc = gnutls_handshake(session);
    251 
    252   if(!backend->gtls.shared_creds->trust_setup) {
    253     /* After having send off the ClientHello, we prepare the trust
    254      * store to verify the coming certificate from the server */
    255     CURLcode result = Curl_gtls_client_trust_setup(cf, data, &backend->gtls);
    256     if(result)
    257       return result;
    258   }
    259 
    260   if((rc == GNUTLS_E_AGAIN) || (rc == GNUTLS_E_INTERRUPTED)) {
    261     connssl->io_need =
    262       gnutls_record_get_direction(session) ?
    263       CURL_SSL_IO_NEED_SEND : CURL_SSL_IO_NEED_RECV;
    264     return CURLE_AGAIN;
    265   }
    266   else if((rc < 0) && !gnutls_error_is_fatal(rc)) {
    267     const char *strerr = NULL;
    268 
    269     if(rc == GNUTLS_E_WARNING_ALERT_RECEIVED) {
    270       gnutls_alert_description_t alert = gnutls_alert_get(session);
    271       strerr = gnutls_alert_get_name(alert);
    272     }
    273 
    274     if(!strerr)
    275       strerr = gnutls_strerror(rc);
    276 
    277     infof(data, "gnutls_handshake() warning: %s", strerr);
    278     return CURLE_AGAIN;
    279   }
    280   else if((rc < 0) && backend->gtls.io_result) {
    281     return backend->gtls.io_result;
    282   }
    283   else if(rc < 0) {
    284     const char *strerr = NULL;
    285 
    286     if(rc == GNUTLS_E_FATAL_ALERT_RECEIVED) {
    287       gnutls_alert_description_t alert = gnutls_alert_get(session);
    288       strerr = gnutls_alert_get_name(alert);
    289     }
    290 
    291     if(!strerr)
    292       strerr = gnutls_strerror(rc);
    293 
    294     failf(data, "GnuTLS, handshake failed: %s", strerr);
    295     return CURLE_SSL_CONNECT_ERROR;
    296   }
    297 
    298   return CURLE_OK;
    299 }
    300 
    301 static gnutls_x509_crt_fmt_t gnutls_do_file_type(const char *type)
    302 {
    303   if(!type || !type[0])
    304     return GNUTLS_X509_FMT_PEM;
    305   if(curl_strequal(type, "PEM"))
    306     return GNUTLS_X509_FMT_PEM;
    307   if(curl_strequal(type, "DER"))
    308     return GNUTLS_X509_FMT_DER;
    309   return GNUTLS_X509_FMT_PEM; /* default to PEM */
    310 }
    311 
    312 #define GNUTLS_CIPHERS "NORMAL:-ARCFOUR-128:-CTYPE-ALL:+CTYPE-X509"
    313 /* If GnuTLS was compiled without support for SRP it will error out if SRP is
    314    requested in the priority string, so treat it specially
    315  */
    316 #define GNUTLS_SRP "+SRP"
    317 
    318 #define QUIC_PRIORITY \
    319   "NORMAL:-VERS-ALL:+VERS-TLS1.3:-CIPHER-ALL:+AES-128-GCM:+AES-256-GCM:" \
    320   "+CHACHA20-POLY1305:+AES-128-CCM:-GROUP-ALL:+GROUP-SECP256R1:" \
    321   "+GROUP-X25519:+GROUP-SECP384R1:+GROUP-SECP521R1:" \
    322   "%DISABLE_TLS13_COMPAT_MODE"
    323 
    324 static CURLcode
    325 gnutls_set_ssl_version_min_max(struct Curl_easy *data,
    326                                struct ssl_peer *peer,
    327                                struct ssl_primary_config *conn_config,
    328                                const char **prioritylist,
    329                                bool tls13support)
    330 {
    331   long ssl_version = conn_config->version;
    332   long ssl_version_max = conn_config->version_max;
    333 
    334   if((ssl_version == CURL_SSLVERSION_DEFAULT) ||
    335      (ssl_version == CURL_SSLVERSION_TLSv1))
    336     ssl_version = CURL_SSLVERSION_TLSv1_0;
    337   if(ssl_version_max == CURL_SSLVERSION_MAX_NONE)
    338     ssl_version_max = CURL_SSLVERSION_MAX_DEFAULT;
    339 
    340   if(peer->transport == TRNSPRT_QUIC) {
    341     if((ssl_version_max != CURL_SSLVERSION_MAX_DEFAULT) &&
    342        (ssl_version_max < CURL_SSLVERSION_MAX_TLSv1_3)) {
    343       failf(data, "QUIC needs at least TLS version 1.3");
    344       return CURLE_SSL_CONNECT_ERROR;
    345      }
    346     *prioritylist = QUIC_PRIORITY;
    347     return CURLE_OK;
    348   }
    349 
    350   if(!tls13support) {
    351     /* If the running GnuTLS does not support TLS 1.3, we must not specify a
    352        prioritylist involving that since it will make GnuTLS return an en
    353        error back at us */
    354     if((ssl_version_max == CURL_SSLVERSION_MAX_TLSv1_3) ||
    355        (ssl_version_max == CURL_SSLVERSION_MAX_DEFAULT)) {
    356       ssl_version_max = CURL_SSLVERSION_MAX_TLSv1_2;
    357     }
    358   }
    359   else if(ssl_version_max == CURL_SSLVERSION_MAX_DEFAULT) {
    360     ssl_version_max = CURL_SSLVERSION_MAX_TLSv1_3;
    361   }
    362 
    363   switch(ssl_version | ssl_version_max) {
    364   case CURL_SSLVERSION_TLSv1_0 | CURL_SSLVERSION_MAX_TLSv1_0:
    365     *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
    366       "+VERS-TLS1.0";
    367     return CURLE_OK;
    368   case CURL_SSLVERSION_TLSv1_0 | CURL_SSLVERSION_MAX_TLSv1_1:
    369     *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
    370       "+VERS-TLS1.1:+VERS-TLS1.0";
    371     return CURLE_OK;
    372   case CURL_SSLVERSION_TLSv1_0 | CURL_SSLVERSION_MAX_TLSv1_2:
    373     *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
    374       "+VERS-TLS1.2:+VERS-TLS1.1:+VERS-TLS1.0";
    375     return CURLE_OK;
    376   case CURL_SSLVERSION_TLSv1_1 | CURL_SSLVERSION_MAX_TLSv1_1:
    377     *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
    378       "+VERS-TLS1.1";
    379     return CURLE_OK;
    380   case CURL_SSLVERSION_TLSv1_1 | CURL_SSLVERSION_MAX_TLSv1_2:
    381     *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
    382       "+VERS-TLS1.2:+VERS-TLS1.1";
    383     return CURLE_OK;
    384   case CURL_SSLVERSION_TLSv1_2 | CURL_SSLVERSION_MAX_TLSv1_2:
    385     *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
    386       "+VERS-TLS1.2";
    387     return CURLE_OK;
    388   case CURL_SSLVERSION_TLSv1_3 | CURL_SSLVERSION_MAX_TLSv1_3:
    389     *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
    390       "+VERS-TLS1.3";
    391     return CURLE_OK;
    392   case CURL_SSLVERSION_TLSv1_0 | CURL_SSLVERSION_MAX_TLSv1_3:
    393     *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0";
    394     return CURLE_OK;
    395   case CURL_SSLVERSION_TLSv1_1 | CURL_SSLVERSION_MAX_TLSv1_3:
    396     *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
    397       "+VERS-TLS1.3:+VERS-TLS1.2:+VERS-TLS1.1";
    398     return CURLE_OK;
    399   case CURL_SSLVERSION_TLSv1_2 | CURL_SSLVERSION_MAX_TLSv1_3:
    400     *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
    401       "+VERS-TLS1.3:+VERS-TLS1.2";
    402     return CURLE_OK;
    403   }
    404 
    405   failf(data, "GnuTLS: cannot set ssl protocol");
    406   return CURLE_SSL_CONNECT_ERROR;
    407 }
    408 
    409 CURLcode Curl_gtls_shared_creds_create(struct Curl_easy *data,
    410                                        struct gtls_shared_creds **pcreds)
    411 {
    412   struct gtls_shared_creds *shared;
    413   int rc;
    414 
    415   *pcreds = NULL;
    416   shared = calloc(1, sizeof(*shared));
    417   if(!shared)
    418     return CURLE_OUT_OF_MEMORY;
    419 
    420   rc = gnutls_certificate_allocate_credentials(&shared->creds);
    421   if(rc != GNUTLS_E_SUCCESS) {
    422     failf(data, "gnutls_cert_all_cred() failed: %s", gnutls_strerror(rc));
    423     free(shared);
    424     return CURLE_SSL_CONNECT_ERROR;
    425   }
    426 
    427   shared->refcount = 1;
    428   shared->time = curlx_now();
    429   *pcreds = shared;
    430   return CURLE_OK;
    431 }
    432 
    433 CURLcode Curl_gtls_shared_creds_up_ref(struct gtls_shared_creds *creds)
    434 {
    435   DEBUGASSERT(creds);
    436   if(creds->refcount < SIZE_T_MAX) {
    437     ++creds->refcount;
    438     return CURLE_OK;
    439   }
    440   return CURLE_BAD_FUNCTION_ARGUMENT;
    441 }
    442 
    443 void Curl_gtls_shared_creds_free(struct gtls_shared_creds **pcreds)
    444 {
    445   struct gtls_shared_creds *shared = *pcreds;
    446   *pcreds = NULL;
    447   if(shared) {
    448     --shared->refcount;
    449     if(!shared->refcount) {
    450       gnutls_certificate_free_credentials(shared->creds);
    451       free(shared->CAfile);
    452       free(shared);
    453     }
    454   }
    455 }
    456 
    457 static CURLcode gtls_populate_creds(struct Curl_cfilter *cf,
    458                                     struct Curl_easy *data,
    459                                     gnutls_certificate_credentials_t creds)
    460 {
    461   struct ssl_primary_config *config = Curl_ssl_cf_get_primary_config(cf);
    462   struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
    463   int rc;
    464 
    465   if(config->verifypeer) {
    466     bool imported_native_ca = FALSE;
    467 
    468     if(ssl_config->native_ca_store) {
    469       rc = gnutls_certificate_set_x509_system_trust(creds);
    470       if(rc < 0)
    471         infof(data, "error reading native ca store (%s), continuing anyway",
    472               gnutls_strerror(rc));
    473       else {
    474         infof(data, "found %d certificates in native ca store", rc);
    475         if(rc > 0)
    476           imported_native_ca = TRUE;
    477       }
    478     }
    479 
    480     if(config->CAfile) {
    481       /* set the trusted CA cert bundle file */
    482       gnutls_certificate_set_verify_flags(creds,
    483                                           GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT);
    484 
    485       rc = gnutls_certificate_set_x509_trust_file(creds,
    486                                                   config->CAfile,
    487                                                   GNUTLS_X509_FMT_PEM);
    488       if(rc < 0) {
    489         infof(data, "error reading ca cert file %s (%s)%s",
    490               config->CAfile, gnutls_strerror(rc),
    491               (imported_native_ca ? ", continuing anyway" : ""));
    492         if(!imported_native_ca) {
    493           ssl_config->certverifyresult = rc;
    494           return CURLE_SSL_CACERT_BADFILE;
    495         }
    496       }
    497       else
    498         infof(data, "found %d certificates in %s", rc, config->CAfile);
    499     }
    500 
    501     if(config->CApath) {
    502       /* set the trusted CA cert directory */
    503       rc = gnutls_certificate_set_x509_trust_dir(creds, config->CApath,
    504                                                  GNUTLS_X509_FMT_PEM);
    505       if(rc < 0) {
    506         infof(data, "error reading ca cert file %s (%s)%s",
    507               config->CApath, gnutls_strerror(rc),
    508               (imported_native_ca ? ", continuing anyway" : ""));
    509         if(!imported_native_ca) {
    510           ssl_config->certverifyresult = rc;
    511           return CURLE_SSL_CACERT_BADFILE;
    512         }
    513       }
    514       else
    515         infof(data, "found %d certificates in %s", rc, config->CApath);
    516     }
    517   }
    518 
    519   if(config->CRLfile) {
    520     /* set the CRL list file */
    521     rc = gnutls_certificate_set_x509_crl_file(creds, config->CRLfile,
    522                                               GNUTLS_X509_FMT_PEM);
    523     if(rc < 0) {
    524       failf(data, "error reading crl file %s (%s)",
    525             config->CRLfile, gnutls_strerror(rc));
    526       return CURLE_SSL_CRL_BADFILE;
    527     }
    528     else
    529       infof(data, "found %d CRL in %s", rc, config->CRLfile);
    530   }
    531 
    532   return CURLE_OK;
    533 }
    534 
    535 /* key to use at `multi->proto_hash` */
    536 #define MPROTO_GTLS_X509_KEY   "tls:gtls:x509:share"
    537 
    538 static bool gtls_shared_creds_expired(const struct Curl_easy *data,
    539                                       const struct gtls_shared_creds *sc)
    540 {
    541   const struct ssl_general_config *cfg = &data->set.general_ssl;
    542   struct curltime now = curlx_now();
    543   timediff_t elapsed_ms = curlx_timediff(now, sc->time);
    544   timediff_t timeout_ms = cfg->ca_cache_timeout * (timediff_t)1000;
    545 
    546   if(timeout_ms < 0)
    547     return FALSE;
    548 
    549   return elapsed_ms >= timeout_ms;
    550 }
    551 
    552 static bool gtls_shared_creds_different(struct Curl_cfilter *cf,
    553                                         const struct gtls_shared_creds *sc)
    554 {
    555   struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
    556   if(!sc->CAfile || !conn_config->CAfile)
    557     return sc->CAfile != conn_config->CAfile;
    558 
    559   return strcmp(sc->CAfile, conn_config->CAfile);
    560 }
    561 
    562 static struct gtls_shared_creds*
    563 gtls_get_cached_creds(struct Curl_cfilter *cf, struct Curl_easy *data)
    564 {
    565   struct gtls_shared_creds *shared_creds;
    566 
    567   if(data->multi) {
    568     shared_creds = Curl_hash_pick(&data->multi->proto_hash,
    569                                   CURL_UNCONST(MPROTO_GTLS_X509_KEY),
    570                                   sizeof(MPROTO_GTLS_X509_KEY)-1);
    571      if(shared_creds && shared_creds->creds &&
    572         !gtls_shared_creds_expired(data, shared_creds) &&
    573         !gtls_shared_creds_different(cf, shared_creds)) {
    574        return shared_creds;
    575      }
    576   }
    577   return NULL;
    578 }
    579 
    580 static void gtls_shared_creds_hash_free(void *key, size_t key_len, void *p)
    581 {
    582   struct gtls_shared_creds *sc = p;
    583   DEBUGASSERT(key_len == (sizeof(MPROTO_GTLS_X509_KEY)-1));
    584   DEBUGASSERT(!memcmp(MPROTO_GTLS_X509_KEY, key, key_len));
    585   (void)key;
    586   (void)key_len;
    587   Curl_gtls_shared_creds_free(&sc); /* down reference */
    588 }
    589 
    590 static void gtls_set_cached_creds(struct Curl_cfilter *cf,
    591                                   struct Curl_easy *data,
    592                                   struct gtls_shared_creds *sc)
    593 {
    594   struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
    595 
    596   DEBUGASSERT(sc);
    597   DEBUGASSERT(sc->creds);
    598   DEBUGASSERT(!sc->CAfile);
    599   DEBUGASSERT(sc->refcount == 1);
    600   if(!data->multi)
    601     return;
    602 
    603   if(conn_config->CAfile) {
    604     sc->CAfile = strdup(conn_config->CAfile);
    605     if(!sc->CAfile)
    606       return;
    607   }
    608 
    609   if(Curl_gtls_shared_creds_up_ref(sc))
    610     return;
    611 
    612   if(!Curl_hash_add2(&data->multi->proto_hash,
    613                     CURL_UNCONST(MPROTO_GTLS_X509_KEY),
    614                     sizeof(MPROTO_GTLS_X509_KEY)-1,
    615                     sc, gtls_shared_creds_hash_free)) {
    616     Curl_gtls_shared_creds_free(&sc); /* down reference again */
    617     return;
    618   }
    619 }
    620 
    621 CURLcode Curl_gtls_client_trust_setup(struct Curl_cfilter *cf,
    622                                       struct Curl_easy *data,
    623                                       struct gtls_ctx *gtls)
    624 {
    625   struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
    626   struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
    627   struct gtls_shared_creds *cached_creds = NULL;
    628   bool cache_criteria_met;
    629   CURLcode result;
    630   int rc;
    631 
    632 
    633   /* Consider the X509 store cacheable if it comes exclusively from a CAfile,
    634      or no source is provided and we are falling back to OpenSSL's built-in
    635      default. */
    636   cache_criteria_met = (data->set.general_ssl.ca_cache_timeout != 0) &&
    637     conn_config->verifypeer &&
    638     !conn_config->CApath &&
    639     !conn_config->ca_info_blob &&
    640     !ssl_config->primary.CRLfile &&
    641     !ssl_config->native_ca_store &&
    642     !conn_config->clientcert; /* GnuTLS adds client cert to its credentials! */
    643 
    644   if(cache_criteria_met)
    645     cached_creds = gtls_get_cached_creds(cf, data);
    646 
    647   if(cached_creds && !Curl_gtls_shared_creds_up_ref(cached_creds)) {
    648     CURL_TRC_CF(data, cf, "using shared trust anchors and CRLs");
    649     Curl_gtls_shared_creds_free(&gtls->shared_creds);
    650     gtls->shared_creds = cached_creds;
    651     rc = gnutls_credentials_set(gtls->session, GNUTLS_CRD_CERTIFICATE,
    652                                 gtls->shared_creds->creds);
    653     if(rc != GNUTLS_E_SUCCESS) {
    654       failf(data, "gnutls_credentials_set() failed: %s", gnutls_strerror(rc));
    655       return CURLE_SSL_CONNECT_ERROR;
    656     }
    657   }
    658   else {
    659     CURL_TRC_CF(data, cf, "loading trust anchors and CRLs");
    660     result = gtls_populate_creds(cf, data, gtls->shared_creds->creds);
    661     if(result)
    662       return result;
    663     gtls->shared_creds->trust_setup = TRUE;
    664     if(cache_criteria_met)
    665       gtls_set_cached_creds(cf, data, gtls->shared_creds);
    666   }
    667   return CURLE_OK;
    668 }
    669 
    670 CURLcode Curl_gtls_cache_session(struct Curl_cfilter *cf,
    671                                  struct Curl_easy *data,
    672                                  const char *ssl_peer_key,
    673                                  gnutls_session_t session,
    674                                  curl_off_t valid_until,
    675                                  const char *alpn,
    676                                  unsigned char *quic_tp,
    677                                  size_t quic_tp_len)
    678 {
    679   struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
    680   struct Curl_ssl_session *sc_session;
    681   unsigned char *sdata, *qtp_clone = NULL;
    682   size_t sdata_len = 0;
    683   size_t earlydata_max = 0;
    684   CURLcode result = CURLE_OK;
    685 
    686   if(!ssl_config->primary.cache_session)
    687     return CURLE_OK;
    688 
    689   /* we always unconditionally get the session id here, as even if we
    690      already got it from the cache and asked to use it in the connection, it
    691      might've been rejected and then a new one is in use now and we need to
    692      detect that. */
    693 
    694   /* get the session ID data size */
    695   gnutls_session_get_data(session, NULL, &sdata_len);
    696   if(!sdata_len) /* gnutls does this for some version combinations */
    697     return CURLE_OK;
    698 
    699   sdata = malloc(sdata_len); /* get a buffer for it */
    700   if(!sdata)
    701     return CURLE_OUT_OF_MEMORY;
    702 
    703   /* extract session ID to the allocated buffer */
    704   gnutls_session_get_data(session, sdata, &sdata_len);
    705   earlydata_max = gnutls_record_get_max_early_data_size(session);
    706 
    707   CURL_TRC_CF(data, cf, "get session id (len=%zu, alpn=%s, earlymax=%zu) "
    708               "and store in cache", sdata_len, alpn ? alpn : "-",
    709               earlydata_max);
    710   if(quic_tp && quic_tp_len) {
    711     qtp_clone = Curl_memdup0((char *)quic_tp, quic_tp_len);
    712     if(!qtp_clone) {
    713       free(sdata);
    714       return CURLE_OUT_OF_MEMORY;
    715     }
    716   }
    717 
    718   result = Curl_ssl_session_create2(sdata, sdata_len,
    719                                     Curl_glts_get_ietf_proto(session),
    720                                     alpn, valid_until, earlydata_max,
    721                                     qtp_clone, quic_tp_len,
    722                                     &sc_session);
    723   /* call took ownership of `sdata` and `qtp_clone` */
    724   if(!result) {
    725     result = Curl_ssl_scache_put(cf, data, ssl_peer_key, sc_session);
    726     /* took ownership of `sc_session` */
    727   }
    728   return result;
    729 }
    730 
    731 int Curl_glts_get_ietf_proto(gnutls_session_t session)
    732 {
    733   switch(gnutls_protocol_get_version(session)) {
    734   case GNUTLS_SSL3:
    735     return CURL_IETF_PROTO_SSL3;
    736   case GNUTLS_TLS1_0:
    737     return CURL_IETF_PROTO_TLS1;
    738   case GNUTLS_TLS1_1:
    739     return CURL_IETF_PROTO_TLS1_1;
    740   case GNUTLS_TLS1_2:
    741     return CURL_IETF_PROTO_TLS1_2;
    742   case GNUTLS_TLS1_3:
    743     return CURL_IETF_PROTO_TLS1_3;
    744   default:
    745     return CURL_IETF_PROTO_UNKNOWN;
    746   }
    747 }
    748 
    749 static CURLcode cf_gtls_update_session_id(struct Curl_cfilter *cf,
    750                                           struct Curl_easy *data,
    751                                           gnutls_session_t session)
    752 {
    753   struct ssl_connect_data *connssl = cf->ctx;
    754   return Curl_gtls_cache_session(cf, data, connssl->peer.scache_key,
    755                                  session, 0, connssl->negotiated.alpn,
    756                                  NULL, 0);
    757 }
    758 
    759 static int gtls_handshake_cb(gnutls_session_t session, unsigned int htype,
    760                              unsigned when, unsigned int incoming,
    761                              const gnutls_datum_t *msg)
    762 {
    763   struct Curl_cfilter *cf = gnutls_session_get_ptr(session);
    764 
    765   (void)msg;
    766   (void)incoming;
    767   if(when) { /* after message has been processed */
    768     struct Curl_easy *data = CF_DATA_CURRENT(cf);
    769     if(data) {
    770       CURL_TRC_CF(data, cf, "handshake: %s message type %d",
    771                   incoming ? "incoming" : "outgoing", htype);
    772       switch(htype) {
    773       case GNUTLS_HANDSHAKE_NEW_SESSION_TICKET: {
    774         cf_gtls_update_session_id(cf, data, session);
    775         break;
    776       }
    777       default:
    778         break;
    779       }
    780     }
    781   }
    782   return 0;
    783 }
    784 
    785 static CURLcode gtls_set_priority(struct Curl_cfilter *cf,
    786                                   struct Curl_easy *data,
    787                                   struct gtls_ctx *gtls,
    788                                   const char *priority)
    789 {
    790   struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
    791   struct dynbuf buf;
    792   const char *err = NULL;
    793   CURLcode result = CURLE_OK;
    794   int rc;
    795 
    796   curlx_dyn_init(&buf, 4096);
    797 
    798 #ifdef USE_GNUTLS_SRP
    799   if(conn_config->username) {
    800     /* Only add SRP to the cipher list if SRP is requested. Otherwise
    801      * GnuTLS will disable TLS 1.3 support. */
    802     result = curlx_dyn_add(&buf, priority);
    803     if(!result)
    804       result = curlx_dyn_add(&buf, ":" GNUTLS_SRP);
    805     if(result)
    806       goto out;
    807     priority = curlx_dyn_ptr(&buf);
    808   }
    809 #endif
    810 
    811   if(conn_config->cipher_list) {
    812     if((conn_config->cipher_list[0] == '+') ||
    813        (conn_config->cipher_list[0] == '-') ||
    814        (conn_config->cipher_list[0] == '!')) {
    815        /* add it to out own */
    816       if(!curlx_dyn_len(&buf)) {  /* not added yet */
    817         result = curlx_dyn_add(&buf, priority);
    818         if(result)
    819           goto out;
    820       }
    821       result = curlx_dyn_addf(&buf, ":%s", conn_config->cipher_list);
    822       if(result)
    823         goto out;
    824       priority = curlx_dyn_ptr(&buf);
    825     }
    826     else /* replace our own completely */
    827       priority = conn_config->cipher_list;
    828   }
    829 
    830   infof(data, "GnuTLS priority: %s", priority);
    831   rc = gnutls_priority_set_direct(gtls->session, priority, &err);
    832   if(rc != GNUTLS_E_SUCCESS) {
    833     failf(data, "Error %d setting GnuTLS priority: %s", rc, err);
    834     result = CURLE_SSL_CONNECT_ERROR;
    835   }
    836 
    837 out:
    838   curlx_dyn_free(&buf);
    839   return result;
    840 }
    841 
    842 static CURLcode gtls_client_init(struct Curl_cfilter *cf,
    843                                  struct Curl_easy *data,
    844                                  struct ssl_peer *peer,
    845                                  size_t earlydata_max,
    846                                  struct gtls_ctx *gtls)
    847 {
    848   struct ssl_primary_config *config = Curl_ssl_cf_get_primary_config(cf);
    849   struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
    850   unsigned int init_flags;
    851   int rc;
    852   bool sni = TRUE; /* default is SNI enabled */
    853   const char *prioritylist;
    854   bool tls13support;
    855   CURLcode result;
    856 
    857   if(!gtls_inited)
    858     gtls_init();
    859 
    860   if(config->version == CURL_SSLVERSION_SSLv2) {
    861     failf(data, "GnuTLS does not support SSLv2");
    862     return CURLE_SSL_CONNECT_ERROR;
    863   }
    864   else if(config->version == CURL_SSLVERSION_SSLv3)
    865     sni = FALSE; /* SSLv3 has no SNI */
    866 
    867   /* allocate a shared creds struct */
    868   result = Curl_gtls_shared_creds_create(data, &gtls->shared_creds);
    869   if(result)
    870     return result;
    871 
    872 #ifdef USE_GNUTLS_SRP
    873   if(config->username && Curl_auth_allowed_to_host(data)) {
    874     infof(data, "Using TLS-SRP username: %s", config->username);
    875 
    876     rc = gnutls_srp_allocate_client_credentials(&gtls->srp_client_cred);
    877     if(rc != GNUTLS_E_SUCCESS) {
    878       failf(data, "gnutls_srp_allocate_client_cred() failed: %s",
    879             gnutls_strerror(rc));
    880       return CURLE_OUT_OF_MEMORY;
    881     }
    882 
    883     rc = gnutls_srp_set_client_credentials(gtls->srp_client_cred,
    884                                            config->username,
    885                                            config->password);
    886     if(rc != GNUTLS_E_SUCCESS) {
    887       failf(data, "gnutls_srp_set_client_cred() failed: %s",
    888             gnutls_strerror(rc));
    889       return CURLE_BAD_FUNCTION_ARGUMENT;
    890     }
    891   }
    892 #endif
    893 
    894   ssl_config->certverifyresult = 0;
    895 
    896   /* Initialize TLS session as a client */
    897   init_flags = GNUTLS_CLIENT;
    898   if(peer->transport == TRNSPRT_QUIC && earlydata_max > 0)
    899     init_flags |= GNUTLS_ENABLE_EARLY_DATA | GNUTLS_NO_END_OF_EARLY_DATA;
    900   else if(earlydata_max > 0 && earlydata_max != 0xFFFFFFFFUL)
    901     /* See https://gitlab.com/gnutls/gnutls/-/issues/1619
    902      * We cannot differentiate between a session announcing no earldata
    903      * and one announcing 0xFFFFFFFFUL. On TCP+TLS, this is unlikely, but
    904      * on QUIC this is common. */
    905     init_flags |= GNUTLS_ENABLE_EARLY_DATA;
    906 
    907 #if defined(GNUTLS_FORCE_CLIENT_CERT)
    908   init_flags |= GNUTLS_FORCE_CLIENT_CERT;
    909 #endif
    910 
    911 #if defined(GNUTLS_NO_TICKETS_TLS12)
    912     init_flags |= GNUTLS_NO_TICKETS_TLS12;
    913 #elif defined(GNUTLS_NO_TICKETS)
    914   /* Disable TLS session tickets for non 1.3 connections */
    915   if((config->version != CURL_SSLVERSION_TLSv1_3) &&
    916      (config->version != CURL_SSLVERSION_DEFAULT))
    917     init_flags |= GNUTLS_NO_TICKETS;
    918 #endif
    919 
    920 #if defined(GNUTLS_NO_STATUS_REQUEST)
    921   if(!config->verifystatus)
    922     /* Disable the "status_request" TLS extension, enabled by default since
    923        GnuTLS 3.8.0. */
    924     init_flags |= GNUTLS_NO_STATUS_REQUEST;
    925 #endif
    926 
    927   CURL_TRC_CF(data, cf, "gnutls_init(flags=%x), earlydata=%zu",
    928               init_flags, earlydata_max);
    929   rc = gnutls_init(&gtls->session, init_flags);
    930   if(rc != GNUTLS_E_SUCCESS) {
    931     failf(data, "gnutls_init() failed: %d", rc);
    932     return CURLE_SSL_CONNECT_ERROR;
    933   }
    934 
    935   if(sni && peer->sni) {
    936     if(gnutls_server_name_set(gtls->session, GNUTLS_NAME_DNS,
    937                               peer->sni, strlen(peer->sni)) < 0) {
    938       failf(data, "Failed to set SNI");
    939       return CURLE_SSL_CONNECT_ERROR;
    940     }
    941   }
    942 
    943   /* Use default priorities */
    944   rc = gnutls_set_default_priority(gtls->session);
    945   if(rc != GNUTLS_E_SUCCESS)
    946     return CURLE_SSL_CONNECT_ERROR;
    947 
    948   /* "In GnuTLS 3.6.5, TLS 1.3 is enabled by default" */
    949   tls13support = !!gnutls_check_version("3.6.5");
    950 
    951   /* Ensure +SRP comes at the *end* of all relevant strings so that it can be
    952    * removed if a runtime error indicates that SRP is not supported by this
    953    * GnuTLS version */
    954 
    955   if(config->version == CURL_SSLVERSION_SSLv2 ||
    956      config->version == CURL_SSLVERSION_SSLv3) {
    957     failf(data, "GnuTLS does not support SSLv2 or SSLv3");
    958     return CURLE_SSL_CONNECT_ERROR;
    959   }
    960 
    961   if(config->version == CURL_SSLVERSION_TLSv1_3) {
    962     if(!tls13support) {
    963       failf(data, "This GnuTLS installation does not support TLS 1.3");
    964       return CURLE_SSL_CONNECT_ERROR;
    965     }
    966   }
    967 
    968   /* At this point we know we have a supported TLS version, so set it */
    969   result = gnutls_set_ssl_version_min_max(data, peer,
    970                                           config, &prioritylist, tls13support);
    971   if(result)
    972     return result;
    973 
    974   result = gtls_set_priority(cf, data, gtls, prioritylist);
    975   if(result)
    976     return result;
    977 
    978   if(config->clientcert) {
    979     if(!gtls->shared_creds->trust_setup) {
    980       result = Curl_gtls_client_trust_setup(cf, data, gtls);
    981       if(result)
    982         return result;
    983     }
    984     if(ssl_config->cert_type && curl_strequal(ssl_config->cert_type, "P12")) {
    985       rc = gnutls_certificate_set_x509_simple_pkcs12_file(
    986         gtls->shared_creds->creds, config->clientcert, GNUTLS_X509_FMT_DER,
    987         ssl_config->key_passwd ? ssl_config->key_passwd : "");
    988       if(rc != GNUTLS_E_SUCCESS) {
    989         failf(data,
    990               "error reading X.509 potentially-encrypted key or certificate "
    991               "file: %s",
    992               gnutls_strerror(rc));
    993         return CURLE_SSL_CONNECT_ERROR;
    994       }
    995     }
    996     else {
    997       const unsigned int supported_key_encryption_algorithms =
    998         GNUTLS_PKCS_USE_PKCS12_3DES | GNUTLS_PKCS_USE_PKCS12_ARCFOUR |
    999         GNUTLS_PKCS_USE_PKCS12_RC2_40 | GNUTLS_PKCS_USE_PBES2_3DES |
   1000         GNUTLS_PKCS_USE_PBES2_AES_128 | GNUTLS_PKCS_USE_PBES2_AES_192 |
   1001         GNUTLS_PKCS_USE_PBES2_AES_256;
   1002       rc = gnutls_certificate_set_x509_key_file2(
   1003            gtls->shared_creds->creds,
   1004            config->clientcert,
   1005            ssl_config->key ? ssl_config->key : config->clientcert,
   1006            gnutls_do_file_type(ssl_config->cert_type),
   1007            ssl_config->key_passwd,
   1008            supported_key_encryption_algorithms);
   1009       if(rc != GNUTLS_E_SUCCESS) {
   1010         failf(data,
   1011               "error reading X.509 %skey file: %s",
   1012               ssl_config->key_passwd ? "potentially-encrypted " : "",
   1013               gnutls_strerror(rc));
   1014         return CURLE_SSL_CONNECT_ERROR;
   1015       }
   1016     }
   1017   }
   1018 
   1019 #ifdef USE_GNUTLS_SRP
   1020   /* put the credentials to the current session */
   1021   if(config->username) {
   1022     rc = gnutls_credentials_set(gtls->session, GNUTLS_CRD_SRP,
   1023                                 gtls->srp_client_cred);
   1024     if(rc != GNUTLS_E_SUCCESS) {
   1025       failf(data, "gnutls_credentials_set() failed: %s", gnutls_strerror(rc));
   1026       return CURLE_SSL_CONNECT_ERROR;
   1027     }
   1028   }
   1029   else
   1030 #endif
   1031   {
   1032     rc = gnutls_credentials_set(gtls->session, GNUTLS_CRD_CERTIFICATE,
   1033                                 gtls->shared_creds->creds);
   1034     if(rc != GNUTLS_E_SUCCESS) {
   1035       failf(data, "gnutls_credentials_set() failed: %s", gnutls_strerror(rc));
   1036       return CURLE_SSL_CONNECT_ERROR;
   1037     }
   1038   }
   1039 
   1040   if(config->verifystatus) {
   1041     rc = gnutls_ocsp_status_request_enable_client(gtls->session,
   1042                                                   NULL, 0, NULL);
   1043     if(rc != GNUTLS_E_SUCCESS) {
   1044       failf(data, "gnutls_ocsp_status_request_enable_client() failed: %d", rc);
   1045       return CURLE_SSL_CONNECT_ERROR;
   1046     }
   1047   }
   1048 
   1049   return CURLE_OK;
   1050 }
   1051 
   1052 static int keylog_callback(gnutls_session_t session, const char *label,
   1053                            const gnutls_datum_t *secret)
   1054 {
   1055   gnutls_datum_t crandom;
   1056   gnutls_datum_t srandom;
   1057 
   1058   gnutls_session_get_random(session, &crandom, &srandom);
   1059   if(crandom.size != 32) {
   1060     return -1;
   1061   }
   1062 
   1063   Curl_tls_keylog_write(label, crandom.data, secret->data, secret->size);
   1064   return 0;
   1065 }
   1066 
   1067 static CURLcode gtls_on_session_reuse(struct Curl_cfilter *cf,
   1068                                       struct Curl_easy *data,
   1069                                       struct alpn_spec *alpns,
   1070                                       struct Curl_ssl_session *scs,
   1071                                       bool *do_early_data)
   1072 {
   1073   struct ssl_connect_data *connssl = cf->ctx;
   1074   struct gtls_ssl_backend_data *backend =
   1075     (struct gtls_ssl_backend_data *)connssl->backend;
   1076   CURLcode result = CURLE_OK;
   1077 
   1078   *do_early_data = FALSE;
   1079   connssl->earlydata_max =
   1080     gnutls_record_get_max_early_data_size(backend->gtls.session);
   1081   if((!connssl->earlydata_max || connssl->earlydata_max == 0xFFFFFFFFUL)) {
   1082     /* Seems to be no GnuTLS way to signal no EarlyData in session */
   1083     CURL_TRC_CF(data, cf, "SSL session does not allow earlydata");
   1084   }
   1085   else if(!Curl_alpn_contains_proto(alpns, scs->alpn)) {
   1086     CURL_TRC_CF(data, cf, "SSL session has different ALPN, no early data");
   1087   }
   1088   else {
   1089     infof(data, "SSL session allows %zu bytes of early data, "
   1090           "reusing ALPN '%s'", connssl->earlydata_max, scs->alpn);
   1091     connssl->earlydata_state = ssl_earlydata_await;
   1092     connssl->state = ssl_connection_deferred;
   1093     result = Curl_alpn_set_negotiated(cf, data, connssl,
   1094                     (const unsigned char *)scs->alpn,
   1095                     scs->alpn ? strlen(scs->alpn) : 0);
   1096     *do_early_data = !result;
   1097   }
   1098   return result;
   1099 }
   1100 
   1101 CURLcode Curl_gtls_ctx_init(struct gtls_ctx *gctx,
   1102                             struct Curl_cfilter *cf,
   1103                             struct Curl_easy *data,
   1104                             struct ssl_peer *peer,
   1105                             const struct alpn_spec *alpns_requested,
   1106                             Curl_gtls_ctx_setup_cb *cb_setup,
   1107                             void *cb_user_data,
   1108                             void *ssl_user_data,
   1109                             Curl_gtls_init_session_reuse_cb *sess_reuse_cb)
   1110 {
   1111   struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
   1112   struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
   1113   struct Curl_ssl_session *scs = NULL;
   1114   gnutls_datum_t gtls_alpns[ALPN_ENTRIES_MAX];
   1115   size_t gtls_alpns_count = 0;
   1116   bool gtls_session_setup = FALSE;
   1117   struct alpn_spec alpns;
   1118   CURLcode result = CURLE_OK;
   1119   int rc;
   1120 
   1121   DEBUGASSERT(gctx);
   1122   Curl_alpn_copy(&alpns, alpns_requested);
   1123 
   1124   /* This might be a reconnect, so we check for a session ID in the cache
   1125      to speed up things. We need to do this before constructing the gnutls
   1126      session since we need to set flags depending on the kind of reuse. */
   1127   if(conn_config->cache_session) {
   1128     result = Curl_ssl_scache_take(cf, data, peer->scache_key, &scs);
   1129     if(result)
   1130       goto out;
   1131 
   1132     if(scs && scs->sdata && scs->sdata_len &&
   1133        (!scs->alpn || Curl_alpn_contains_proto(&alpns, scs->alpn))) {
   1134       /* we got a cached session, use it! */
   1135 
   1136       result = gtls_client_init(cf, data, peer, scs->earlydata_max, gctx);
   1137       if(result)
   1138         goto out;
   1139       gtls_session_setup = TRUE;
   1140 
   1141       rc = gnutls_session_set_data(gctx->session, scs->sdata, scs->sdata_len);
   1142       if(rc < 0)
   1143         infof(data, "SSL session not accepted by GnuTLS, continuing without");
   1144       else {
   1145         infof(data, "SSL reusing session with ALPN '%s'",
   1146               scs->alpn ? scs->alpn : "-");
   1147         if(ssl_config->earlydata && scs->alpn &&
   1148            !cf->conn->connect_only &&
   1149            (gnutls_protocol_get_version(gctx->session) == GNUTLS_TLS1_3)) {
   1150           bool do_early_data = FALSE;
   1151           if(sess_reuse_cb) {
   1152             result = sess_reuse_cb(cf, data, &alpns, scs, &do_early_data);
   1153             if(result)
   1154               goto  out;
   1155           }
   1156           if(do_early_data) {
   1157             /* We only try the ALPN protocol the session used before,
   1158              * otherwise we might send early data for the wrong protocol */
   1159             Curl_alpn_restrict_to(&alpns, scs->alpn);
   1160           }
   1161         }
   1162       }
   1163     }
   1164   }
   1165 
   1166   if(!gtls_session_setup) {
   1167     result = gtls_client_init(cf, data, peer, 0, gctx);
   1168     if(result)
   1169       goto out;
   1170   }
   1171 
   1172   gnutls_session_set_ptr(gctx->session, ssl_user_data);
   1173 
   1174   if(cb_setup) {
   1175     result = cb_setup(cf, data, cb_user_data);
   1176     if(result)
   1177       goto out;
   1178   }
   1179 
   1180   /* Open the file if a TLS or QUIC backend has not done this before. */
   1181   Curl_tls_keylog_open();
   1182   if(Curl_tls_keylog_enabled()) {
   1183     gnutls_session_set_keylog_function(gctx->session, keylog_callback);
   1184   }
   1185 
   1186   /* convert the ALPN string from our arguments to a list of strings that
   1187    * gnutls wants and will convert internally back to this string for sending
   1188    * to the server. nice. */
   1189   if(!gtls_alpns_count && alpns.count) {
   1190     size_t i;
   1191     DEBUGASSERT(CURL_ARRAYSIZE(gtls_alpns) >= alpns.count);
   1192     for(i = 0; i < alpns.count; ++i) {
   1193       gtls_alpns[i].data = (unsigned char *)alpns.entries[i];
   1194       gtls_alpns[i].size = (unsigned int)strlen(alpns.entries[i]);
   1195     }
   1196     gtls_alpns_count = alpns.count;
   1197   }
   1198 
   1199   if(gtls_alpns_count &&
   1200      gnutls_alpn_set_protocols(gctx->session,
   1201                                gtls_alpns, (unsigned int)gtls_alpns_count,
   1202                                GNUTLS_ALPN_MANDATORY)) {
   1203     failf(data, "failed setting ALPN");
   1204     result = CURLE_SSL_CONNECT_ERROR;
   1205   }
   1206 
   1207 out:
   1208   Curl_ssl_scache_return(cf, data, peer->scache_key, scs);
   1209   return result;
   1210 }
   1211 
   1212 static CURLcode
   1213 gtls_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
   1214 {
   1215   struct ssl_connect_data *connssl = cf->ctx;
   1216   struct gtls_ssl_backend_data *backend =
   1217     (struct gtls_ssl_backend_data *)connssl->backend;
   1218   CURLcode result;
   1219 
   1220   DEBUGASSERT(backend);
   1221 
   1222   if(connssl->state == ssl_connection_complete)
   1223     /* to make us tolerant against being called more than once for the
   1224        same connection */
   1225     return CURLE_OK;
   1226 
   1227   result = Curl_gtls_ctx_init(&backend->gtls, cf, data, &connssl->peer,
   1228                               connssl->alpn, NULL, NULL, cf,
   1229                               gtls_on_session_reuse);
   1230   if(result)
   1231     return result;
   1232 
   1233   if(connssl->alpn && (connssl->state != ssl_connection_deferred)) {
   1234     struct alpn_proto_buf proto;
   1235     memset(&proto, 0, sizeof(proto));
   1236     Curl_alpn_to_proto_str(&proto, connssl->alpn);
   1237     infof(data, VTLS_INFOF_ALPN_OFFER_1STR, proto.data);
   1238   }
   1239 
   1240   gnutls_handshake_set_hook_function(backend->gtls.session,
   1241                                      GNUTLS_HANDSHAKE_ANY, GNUTLS_HOOK_POST,
   1242                                      gtls_handshake_cb);
   1243 
   1244   /* register callback functions and handle to send and receive data. */
   1245   gnutls_transport_set_ptr(backend->gtls.session, cf);
   1246   gnutls_transport_set_push_function(backend->gtls.session, gtls_push);
   1247   gnutls_transport_set_pull_function(backend->gtls.session, gtls_pull);
   1248 
   1249   return CURLE_OK;
   1250 }
   1251 
   1252 static CURLcode pkp_pin_peer_pubkey(struct Curl_easy *data,
   1253                                     gnutls_x509_crt_t cert,
   1254                                     const char *pinnedpubkey)
   1255 {
   1256   /* Scratch */
   1257   size_t len1 = 0, len2 = 0;
   1258   unsigned char *buff1 = NULL;
   1259 
   1260   gnutls_pubkey_t key = NULL;
   1261 
   1262   /* Result is returned to caller */
   1263   CURLcode result = CURLE_SSL_PINNEDPUBKEYNOTMATCH;
   1264 
   1265   /* if a path was not specified, do not pin */
   1266   if(!pinnedpubkey)
   1267     return CURLE_OK;
   1268 
   1269   if(!cert)
   1270     return result;
   1271 
   1272   do {
   1273     int ret;
   1274 
   1275     /* Begin Gyrations to get the public key     */
   1276     gnutls_pubkey_init(&key);
   1277 
   1278     ret = gnutls_pubkey_import_x509(key, cert, 0);
   1279     if(ret < 0)
   1280       break; /* failed */
   1281 
   1282     ret = gnutls_pubkey_export(key, GNUTLS_X509_FMT_DER, NULL, &len1);
   1283     if(ret != GNUTLS_E_SHORT_MEMORY_BUFFER || len1 == 0)
   1284       break; /* failed */
   1285 
   1286     buff1 = malloc(len1);
   1287     if(!buff1)
   1288       break; /* failed */
   1289 
   1290     len2 = len1;
   1291 
   1292     ret = gnutls_pubkey_export(key, GNUTLS_X509_FMT_DER, buff1, &len2);
   1293     if(ret < 0 || len1 != len2)
   1294       break; /* failed */
   1295 
   1296     /* End Gyrations */
   1297 
   1298     /* The one good exit point */
   1299     result = Curl_pin_peer_pubkey(data, pinnedpubkey, buff1, len1);
   1300   } while(0);
   1301 
   1302   if(key)
   1303     gnutls_pubkey_deinit(key);
   1304 
   1305   Curl_safefree(buff1);
   1306 
   1307   return result;
   1308 }
   1309 
   1310 void Curl_gtls_report_handshake(struct Curl_easy *data,
   1311                                 struct gtls_ctx *gctx)
   1312 {
   1313 #ifndef CURL_DISABLE_VERBOSE_STRINGS
   1314   if(Curl_trc_is_verbose(data)) {
   1315     const char *ptr;
   1316     gnutls_protocol_t version = gnutls_protocol_get_version(gctx->session);
   1317 
   1318     /* the name of the cipher suite used, e.g. ECDHE_RSA_AES_256_GCM_SHA384. */
   1319     ptr = gnutls_cipher_suite_get_name(gnutls_kx_get(gctx->session),
   1320                                        gnutls_cipher_get(gctx->session),
   1321                                        gnutls_mac_get(gctx->session));
   1322 
   1323     infof(data, "SSL connection using %s / %s",
   1324           gnutls_protocol_get_name(version), ptr);
   1325   }
   1326 #else
   1327   (void)data;
   1328   (void)gctx;
   1329 #endif
   1330 }
   1331 
   1332 CURLcode
   1333 Curl_gtls_verifyserver(struct Curl_easy *data,
   1334                        gnutls_session_t session,
   1335                        struct ssl_primary_config *config,
   1336                        struct ssl_config_data *ssl_config,
   1337                        struct ssl_peer *peer,
   1338                        const char *pinned_key)
   1339 {
   1340   unsigned int cert_list_size;
   1341   const gnutls_datum_t *chainp;
   1342   unsigned int verify_status = 0;
   1343   gnutls_x509_crt_t x509_cert, x509_issuer;
   1344   gnutls_datum_t issuerp;
   1345   gnutls_datum_t certfields;
   1346   char certname[65] = ""; /* limited to 64 chars by ASN.1 */
   1347   size_t size;
   1348   time_t certclock;
   1349   int rc;
   1350   CURLcode result = CURLE_OK;
   1351 #ifndef CURL_DISABLE_VERBOSE_STRINGS
   1352   int algo;
   1353   unsigned int bits;
   1354 #endif
   1355   long * const certverifyresult = &ssl_config->certverifyresult;
   1356 
   1357   /* This function will return the peer's raw certificate (chain) as sent by
   1358      the peer. These certificates are in raw format (DER encoded for
   1359      X.509). In case of a X.509 then a certificate list may be present. The
   1360      first certificate in the list is the peer's certificate, following the
   1361      issuer's certificate, then the issuer's issuer etc. */
   1362 
   1363   chainp = gnutls_certificate_get_peers(session, &cert_list_size);
   1364   if(!chainp) {
   1365     if(config->verifypeer ||
   1366        config->verifyhost ||
   1367        config->issuercert) {
   1368 #ifdef USE_GNUTLS_SRP
   1369       if(ssl_config->primary.username && !config->verifypeer &&
   1370          gnutls_cipher_get(session)) {
   1371         /* no peer cert, but auth is ok if we have SRP user and cipher and no
   1372            peer verify */
   1373       }
   1374       else {
   1375 #endif
   1376         failf(data, "failed to get server cert");
   1377         *certverifyresult = GNUTLS_E_NO_CERTIFICATE_FOUND;
   1378         return CURLE_PEER_FAILED_VERIFICATION;
   1379 #ifdef USE_GNUTLS_SRP
   1380       }
   1381 #endif
   1382     }
   1383     infof(data, " common name: WARNING could not obtain");
   1384   }
   1385 
   1386   if(data->set.ssl.certinfo && chainp) {
   1387     unsigned int i;
   1388 
   1389     result = Curl_ssl_init_certinfo(data, (int)cert_list_size);
   1390     if(result)
   1391       return result;
   1392 
   1393     for(i = 0; i < cert_list_size; i++) {
   1394       const char *beg = (const char *) chainp[i].data;
   1395       const char *end = beg + chainp[i].size;
   1396 
   1397       result = Curl_extract_certinfo(data, (int)i, beg, end);
   1398       if(result)
   1399         return result;
   1400     }
   1401   }
   1402 
   1403   if(config->verifypeer) {
   1404     /* This function will try to verify the peer's certificate and return its
   1405        status (trusted, invalid etc.). The value of status should be one or
   1406        more of the gnutls_certificate_status_t enumerated elements bitwise
   1407        or'd. To avoid denial of service attacks some default upper limits
   1408        regarding the certificate key size and chain size are set. To override
   1409        them use gnutls_certificate_set_verify_limits(). */
   1410 
   1411     rc = gnutls_certificate_verify_peers2(session, &verify_status);
   1412     if(rc < 0) {
   1413       failf(data, "server cert verify failed: %d", rc);
   1414       *certverifyresult = rc;
   1415       return CURLE_SSL_CONNECT_ERROR;
   1416     }
   1417 
   1418     *certverifyresult = verify_status;
   1419 
   1420     /* verify_status is a bitmask of gnutls_certificate_status bits */
   1421     if(verify_status & GNUTLS_CERT_INVALID) {
   1422       if(config->verifypeer) {
   1423         const char *cause = "certificate error, no details available";
   1424         if(verify_status & GNUTLS_CERT_EXPIRED)
   1425           cause = "certificate has expired";
   1426         else if(verify_status & GNUTLS_CERT_SIGNER_NOT_FOUND)
   1427           cause = "certificate signer not trusted";
   1428         else if(verify_status & GNUTLS_CERT_INSECURE_ALGORITHM)
   1429           cause = "certificate uses insecure algorithm";
   1430         else if(verify_status & GNUTLS_CERT_INVALID_OCSP_STATUS)
   1431           cause = "attached OCSP status response is invalid";
   1432         failf(data, "server verification failed: %s. (CAfile: %s "
   1433               "CRLfile: %s)", cause,
   1434               config->CAfile ? config->CAfile : "none",
   1435               ssl_config->primary.CRLfile ?
   1436               ssl_config->primary.CRLfile : "none");
   1437         return CURLE_PEER_FAILED_VERIFICATION;
   1438       }
   1439       else
   1440         infof(data, "  server certificate verification FAILED");
   1441     }
   1442     else
   1443       infof(data, "  server certificate verification OK");
   1444   }
   1445   else
   1446     infof(data, "  server certificate verification SKIPPED");
   1447 
   1448   if(config->verifystatus) {
   1449     gnutls_datum_t status_request;
   1450     gnutls_ocsp_resp_t ocsp_resp;
   1451     gnutls_ocsp_cert_status_t status;
   1452     gnutls_x509_crl_reason_t reason;
   1453 
   1454     rc = gnutls_ocsp_status_request_get(session, &status_request);
   1455 
   1456     if(rc == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
   1457       failf(data, "No OCSP response received");
   1458       return CURLE_SSL_INVALIDCERTSTATUS;
   1459     }
   1460 
   1461     if(rc < 0) {
   1462       failf(data, "Invalid OCSP response received");
   1463       return CURLE_SSL_INVALIDCERTSTATUS;
   1464     }
   1465 
   1466     gnutls_ocsp_resp_init(&ocsp_resp);
   1467 
   1468     rc = gnutls_ocsp_resp_import(ocsp_resp, &status_request);
   1469     if(rc < 0) {
   1470       failf(data, "Invalid OCSP response received");
   1471       return CURLE_SSL_INVALIDCERTSTATUS;
   1472     }
   1473 
   1474     (void)gnutls_ocsp_resp_get_single(ocsp_resp, 0, NULL, NULL, NULL, NULL,
   1475                                       &status, NULL, NULL, NULL, &reason);
   1476 
   1477     switch(status) {
   1478     case GNUTLS_OCSP_CERT_GOOD:
   1479       break;
   1480 
   1481     case GNUTLS_OCSP_CERT_REVOKED: {
   1482       const char *crl_reason;
   1483 
   1484       switch(reason) {
   1485       default:
   1486       case GNUTLS_X509_CRLREASON_UNSPECIFIED:
   1487         crl_reason = "unspecified reason";
   1488         break;
   1489 
   1490       case GNUTLS_X509_CRLREASON_KEYCOMPROMISE:
   1491         crl_reason = "private key compromised";
   1492         break;
   1493 
   1494       case GNUTLS_X509_CRLREASON_CACOMPROMISE:
   1495         crl_reason = "CA compromised";
   1496         break;
   1497 
   1498       case GNUTLS_X509_CRLREASON_AFFILIATIONCHANGED:
   1499         crl_reason = "affiliation has changed";
   1500         break;
   1501 
   1502       case GNUTLS_X509_CRLREASON_SUPERSEDED:
   1503         crl_reason = "certificate superseded";
   1504         break;
   1505 
   1506       case GNUTLS_X509_CRLREASON_CESSATIONOFOPERATION:
   1507         crl_reason = "operation has ceased";
   1508         break;
   1509 
   1510       case GNUTLS_X509_CRLREASON_CERTIFICATEHOLD:
   1511         crl_reason = "certificate is on hold";
   1512         break;
   1513 
   1514       case GNUTLS_X509_CRLREASON_REMOVEFROMCRL:
   1515         crl_reason = "will be removed from delta CRL";
   1516         break;
   1517 
   1518       case GNUTLS_X509_CRLREASON_PRIVILEGEWITHDRAWN:
   1519         crl_reason = "privilege withdrawn";
   1520         break;
   1521 
   1522       case GNUTLS_X509_CRLREASON_AACOMPROMISE:
   1523         crl_reason = "AA compromised";
   1524         break;
   1525       }
   1526 
   1527       failf(data, "Server certificate was revoked: %s", crl_reason);
   1528       break;
   1529     }
   1530 
   1531     default:
   1532     case GNUTLS_OCSP_CERT_UNKNOWN:
   1533       failf(data, "Server certificate status is unknown");
   1534       break;
   1535     }
   1536 
   1537     gnutls_ocsp_resp_deinit(ocsp_resp);
   1538     if(status != GNUTLS_OCSP_CERT_GOOD)
   1539       return CURLE_SSL_INVALIDCERTSTATUS;
   1540   }
   1541   else
   1542     infof(data, "  server certificate status verification SKIPPED");
   1543 
   1544   /* initialize an X.509 certificate structure. */
   1545   gnutls_x509_crt_init(&x509_cert);
   1546 
   1547   if(chainp)
   1548     /* convert the given DER or PEM encoded Certificate to the native
   1549        gnutls_x509_crt_t format */
   1550     gnutls_x509_crt_import(x509_cert, chainp, GNUTLS_X509_FMT_DER);
   1551 
   1552   if(config->issuercert) {
   1553     gnutls_x509_crt_init(&x509_issuer);
   1554     issuerp = load_file(config->issuercert);
   1555     gnutls_x509_crt_import(x509_issuer, &issuerp, GNUTLS_X509_FMT_PEM);
   1556     rc = (int)gnutls_x509_crt_check_issuer(x509_cert, x509_issuer);
   1557     gnutls_x509_crt_deinit(x509_issuer);
   1558     unload_file(issuerp);
   1559     if(rc <= 0) {
   1560       failf(data, "server certificate issuer check failed (IssuerCert: %s)",
   1561             config->issuercert ? config->issuercert : "none");
   1562       gnutls_x509_crt_deinit(x509_cert);
   1563       return CURLE_SSL_ISSUER_ERROR;
   1564     }
   1565     infof(data, "  server certificate issuer check OK (Issuer Cert: %s)",
   1566           config->issuercert ? config->issuercert : "none");
   1567   }
   1568 
   1569   size = sizeof(certname);
   1570   rc = gnutls_x509_crt_get_dn_by_oid(x509_cert, GNUTLS_OID_X520_COMMON_NAME,
   1571                                      0, /* the first and only one */
   1572                                      FALSE,
   1573                                      certname,
   1574                                      &size);
   1575   if(rc) {
   1576     infof(data, "error fetching CN from cert:%s",
   1577           gnutls_strerror(rc));
   1578   }
   1579 
   1580   /* This function will check if the given certificate's subject matches the
   1581      given hostname. This is a basic implementation of the matching described
   1582      in RFC2818 (HTTPS), which takes into account wildcards, and the subject
   1583      alternative name PKIX extension. Returns non zero on success, and zero on
   1584      failure. */
   1585 
   1586   /* This function does not handle trailing dots, so if we have an SNI name
   1587      use that and fallback to the hostname only if there is no SNI (like for
   1588      IP addresses) */
   1589   rc = (int)gnutls_x509_crt_check_hostname(x509_cert,
   1590                                            peer->sni ? peer->sni :
   1591                                            peer->hostname);
   1592 #if GNUTLS_VERSION_NUMBER < 0x030306
   1593   /* Before 3.3.6, gnutls_x509_crt_check_hostname() did not check IP
   1594      addresses. */
   1595   if(!rc) {
   1596 #ifdef USE_IPV6
   1597     #define use_addr in6_addr
   1598 #else
   1599     #define use_addr in_addr
   1600 #endif
   1601     unsigned char addrbuf[sizeof(struct use_addr)];
   1602     size_t addrlen = 0;
   1603 
   1604     if(curlx_inet_pton(AF_INET, peer->hostname, addrbuf) > 0)
   1605       addrlen = 4;
   1606 #ifdef USE_IPV6
   1607     else if(curlx_inet_pton(AF_INET6, peer->hostname, addrbuf) > 0)
   1608       addrlen = 16;
   1609 #endif
   1610 
   1611     if(addrlen) {
   1612       unsigned char certaddr[sizeof(struct use_addr)];
   1613       int i;
   1614 
   1615       for(i = 0; ; i++) {
   1616         size_t certaddrlen = sizeof(certaddr);
   1617         int ret = gnutls_x509_crt_get_subject_alt_name(x509_cert, i, certaddr,
   1618                                                        &certaddrlen, NULL);
   1619         /* If this happens, it was not an IP address. */
   1620         if(ret == GNUTLS_E_SHORT_MEMORY_BUFFER)
   1621           continue;
   1622         if(ret < 0)
   1623           break;
   1624         if(ret != GNUTLS_SAN_IPADDRESS)
   1625           continue;
   1626         if(certaddrlen == addrlen && !memcmp(addrbuf, certaddr, addrlen)) {
   1627           rc = 1;
   1628           break;
   1629         }
   1630       }
   1631     }
   1632   }
   1633 #endif
   1634   if(!rc) {
   1635     if(config->verifyhost) {
   1636       failf(data, "SSL: certificate subject name (%s) does not match "
   1637             "target hostname '%s'", certname, peer->dispname);
   1638       gnutls_x509_crt_deinit(x509_cert);
   1639       return CURLE_PEER_FAILED_VERIFICATION;
   1640     }
   1641     else
   1642       infof(data, "  common name: %s (does not match '%s')",
   1643             certname, peer->dispname);
   1644   }
   1645   else
   1646     infof(data, "  common name: %s (matched)", certname);
   1647 
   1648   /* Check for time-based validity */
   1649   certclock = gnutls_x509_crt_get_expiration_time(x509_cert);
   1650 
   1651   if(certclock == (time_t)-1) {
   1652     if(config->verifypeer) {
   1653       failf(data, "server cert expiration date verify failed");
   1654       *certverifyresult = GNUTLS_CERT_EXPIRED;
   1655       gnutls_x509_crt_deinit(x509_cert);
   1656       return CURLE_SSL_CONNECT_ERROR;
   1657     }
   1658     else
   1659       infof(data, "  server certificate expiration date verify FAILED");
   1660   }
   1661   else {
   1662     if(certclock < time(NULL)) {
   1663       if(config->verifypeer) {
   1664         failf(data, "server certificate expiration date has passed.");
   1665         *certverifyresult = GNUTLS_CERT_EXPIRED;
   1666         gnutls_x509_crt_deinit(x509_cert);
   1667         return CURLE_PEER_FAILED_VERIFICATION;
   1668       }
   1669       else
   1670         infof(data, "  server certificate expiration date FAILED");
   1671     }
   1672     else
   1673       infof(data, "  server certificate expiration date OK");
   1674   }
   1675 
   1676   certclock = gnutls_x509_crt_get_activation_time(x509_cert);
   1677 
   1678   if(certclock == (time_t)-1) {
   1679     if(config->verifypeer) {
   1680       failf(data, "server cert activation date verify failed");
   1681       *certverifyresult = GNUTLS_CERT_NOT_ACTIVATED;
   1682       gnutls_x509_crt_deinit(x509_cert);
   1683       return CURLE_SSL_CONNECT_ERROR;
   1684     }
   1685     else
   1686       infof(data, "  server certificate activation date verify FAILED");
   1687   }
   1688   else {
   1689     if(certclock > time(NULL)) {
   1690       if(config->verifypeer) {
   1691         failf(data, "server certificate not activated yet.");
   1692         *certverifyresult = GNUTLS_CERT_NOT_ACTIVATED;
   1693         gnutls_x509_crt_deinit(x509_cert);
   1694         return CURLE_PEER_FAILED_VERIFICATION;
   1695       }
   1696       else
   1697         infof(data, "  server certificate activation date FAILED");
   1698     }
   1699     else
   1700       infof(data, "  server certificate activation date OK");
   1701   }
   1702 
   1703   if(pinned_key) {
   1704     result = pkp_pin_peer_pubkey(data, x509_cert, pinned_key);
   1705     if(result != CURLE_OK) {
   1706       failf(data, "SSL: public key does not match pinned public key");
   1707       gnutls_x509_crt_deinit(x509_cert);
   1708       return result;
   1709     }
   1710   }
   1711 
   1712   /* Show:
   1713 
   1714   - subject
   1715   - start date
   1716   - expire date
   1717   - common name
   1718   - issuer
   1719 
   1720   */
   1721 
   1722 #ifndef CURL_DISABLE_VERBOSE_STRINGS
   1723   /* public key algorithm's parameters */
   1724   algo = gnutls_x509_crt_get_pk_algorithm(x509_cert, &bits);
   1725   infof(data, "  certificate public key: %s",
   1726         gnutls_pk_algorithm_get_name((gnutls_pk_algorithm_t)algo));
   1727 
   1728   /* version of the X.509 certificate. */
   1729   infof(data, "  certificate version: #%d",
   1730         gnutls_x509_crt_get_version(x509_cert));
   1731 
   1732 
   1733   rc = gnutls_x509_crt_get_dn2(x509_cert, &certfields);
   1734   if(rc)
   1735     infof(data, "Failed to get certificate name");
   1736   else {
   1737     infof(data, "  subject: %s", certfields.data);
   1738 
   1739     certclock = gnutls_x509_crt_get_activation_time(x509_cert);
   1740     showtime(data, "start date", certclock);
   1741 
   1742     certclock = gnutls_x509_crt_get_expiration_time(x509_cert);
   1743     showtime(data, "expire date", certclock);
   1744 
   1745     gnutls_free(certfields.data);
   1746   }
   1747 
   1748   rc = gnutls_x509_crt_get_issuer_dn2(x509_cert, &certfields);
   1749   if(rc)
   1750     infof(data, "Failed to get certificate issuer");
   1751   else {
   1752     infof(data, "  issuer: %s", certfields.data);
   1753 
   1754     gnutls_free(certfields.data);
   1755   }
   1756 #endif
   1757 
   1758   gnutls_x509_crt_deinit(x509_cert);
   1759 
   1760   return result;
   1761 }
   1762 
   1763 static CURLcode gtls_verifyserver(struct Curl_cfilter *cf,
   1764                                   struct Curl_easy *data,
   1765                                   gnutls_session_t session)
   1766 {
   1767   struct ssl_connect_data *connssl = cf->ctx;
   1768   struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
   1769   struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
   1770 #ifndef CURL_DISABLE_PROXY
   1771   const char *pinned_key = Curl_ssl_cf_is_proxy(cf) ?
   1772     data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] :
   1773     data->set.str[STRING_SSL_PINNEDPUBLICKEY];
   1774 #else
   1775   const char *pinned_key = data->set.str[STRING_SSL_PINNEDPUBLICKEY];
   1776 #endif
   1777   CURLcode result;
   1778 
   1779   result = Curl_gtls_verifyserver(data, session, conn_config, ssl_config,
   1780                                   &connssl->peer, pinned_key);
   1781   if(result)
   1782     goto out;
   1783 
   1784   /* Only on TLSv1.2 or lower do we have the session id now. For
   1785    * TLSv1.3 we get it via a SESSION_TICKET message that arrives later. */
   1786   if(gnutls_protocol_get_version(session) < GNUTLS_TLS1_3)
   1787     result = cf_gtls_update_session_id(cf, data, session);
   1788 
   1789 out:
   1790   return result;
   1791 }
   1792 
   1793 static CURLcode gtls_send_earlydata(struct Curl_cfilter *cf,
   1794                                     struct Curl_easy *data)
   1795 {
   1796   struct ssl_connect_data *connssl = cf->ctx;
   1797   struct gtls_ssl_backend_data *backend =
   1798       (struct gtls_ssl_backend_data *)connssl->backend;
   1799   CURLcode result = CURLE_OK;
   1800   const unsigned char *buf;
   1801   size_t blen;
   1802   ssize_t n;
   1803 
   1804   DEBUGASSERT(connssl->earlydata_state == ssl_earlydata_sending);
   1805   backend->gtls.io_result = CURLE_OK;
   1806   while(Curl_bufq_peek(&connssl->earlydata, &buf, &blen)) {
   1807     n = gnutls_record_send_early_data(backend->gtls.session, buf, blen);
   1808     CURL_TRC_CF(data, cf, "gtls_send_earlydata(len=%zu) -> %zd",
   1809                 blen, n);
   1810     if(n < 0) {
   1811       if(n == GNUTLS_E_AGAIN)
   1812         result = CURLE_AGAIN;
   1813       else
   1814         result = backend->gtls.io_result ?
   1815                  backend->gtls.io_result : CURLE_SEND_ERROR;
   1816       goto out;
   1817     }
   1818     else if(!n) {
   1819       /* gnutls is buggy, it *SHOULD* return the amount of bytes it took in.
   1820        * Instead it returns 0 if everything was written. */
   1821       n = (ssize_t)blen;
   1822     }
   1823 
   1824     Curl_bufq_skip(&connssl->earlydata, (size_t)n);
   1825   }
   1826   /* sent everything there was */
   1827   infof(data, "SSL sending %zu bytes of early data", connssl->earlydata_skip);
   1828 out:
   1829   return result;
   1830 }
   1831 
   1832 /*
   1833  * This function is called after the TCP connect has completed. Setup the TLS
   1834  * layer and do all necessary magic.
   1835  */
   1836 /* We use connssl->connecting_state to keep track of the connection status;
   1837    there are three states: 'ssl_connect_1' (not started yet or complete),
   1838    'ssl_connect_2' (doing handshake with the server), and
   1839    'ssl_connect_3' (verifying and getting stats).
   1840  */
   1841 static CURLcode gtls_connect_common(struct Curl_cfilter *cf,
   1842                                     struct Curl_easy *data,
   1843                                     bool *done) {
   1844   struct ssl_connect_data *connssl = cf->ctx;
   1845   struct gtls_ssl_backend_data *backend =
   1846       (struct gtls_ssl_backend_data *)connssl->backend;
   1847   CURLcode result = CURLE_OK;
   1848 
   1849   DEBUGASSERT(backend);
   1850   /* check if the connection has already been established */
   1851   if(ssl_connection_complete == connssl->state) {
   1852     *done = TRUE;
   1853     return CURLE_OK;
   1854   }
   1855 
   1856   *done = FALSE;
   1857 
   1858   /* Initiate the connection, if not already done */
   1859   if(connssl->connecting_state == ssl_connect_1) {
   1860     result = gtls_connect_step1(cf, data);
   1861     if(result)
   1862       goto out;
   1863     connssl->connecting_state = ssl_connect_2;
   1864   }
   1865 
   1866   if(connssl->connecting_state == ssl_connect_2) {
   1867     if(connssl->earlydata_state == ssl_earlydata_await) {
   1868       goto out;
   1869     }
   1870     else if(connssl->earlydata_state == ssl_earlydata_sending) {
   1871       result = gtls_send_earlydata(cf, data);
   1872       if(result)
   1873         goto out;
   1874       connssl->earlydata_state = ssl_earlydata_sent;
   1875     }
   1876     DEBUGASSERT((connssl->earlydata_state == ssl_earlydata_none) ||
   1877                 (connssl->earlydata_state == ssl_earlydata_sent));
   1878 
   1879     result = handshake(cf, data);
   1880     if(result)
   1881       goto out;
   1882     connssl->connecting_state = ssl_connect_3;
   1883   }
   1884 
   1885   /* Finish connecting once the handshake is done */
   1886   if(connssl->connecting_state == ssl_connect_3) {
   1887     gnutls_datum_t proto;
   1888     int rc;
   1889 
   1890     Curl_gtls_report_handshake(data, &backend->gtls);
   1891 
   1892     result = gtls_verifyserver(cf, data, backend->gtls.session);
   1893     if(result)
   1894       goto out;
   1895 
   1896     connssl->state = ssl_connection_complete;
   1897 
   1898     rc = gnutls_alpn_get_selected_protocol(backend->gtls.session, &proto);
   1899     if(rc) {  /* No ALPN from server */
   1900       proto.data = NULL;
   1901       proto.size = 0;
   1902     }
   1903 
   1904     result = Curl_alpn_set_negotiated(cf, data, connssl,
   1905                                       proto.data, proto.size);
   1906     if(result)
   1907       goto out;
   1908 
   1909     if(connssl->earlydata_state > ssl_earlydata_none) {
   1910       /* We should be in this state by now */
   1911       DEBUGASSERT(connssl->earlydata_state == ssl_earlydata_sent);
   1912       connssl->earlydata_state =
   1913         (gnutls_session_get_flags(backend->gtls.session) &
   1914          GNUTLS_SFLAGS_EARLY_DATA) ?
   1915         ssl_earlydata_accepted : ssl_earlydata_rejected;
   1916     }
   1917     connssl->connecting_state = ssl_connect_done;
   1918   }
   1919 
   1920   if(connssl->connecting_state == ssl_connect_done)
   1921     DEBUGASSERT(connssl->state == ssl_connection_complete);
   1922 
   1923 out:
   1924   if(result == CURLE_AGAIN) {
   1925     *done = FALSE;
   1926     return CURLE_OK;
   1927   }
   1928   *done = ((connssl->state == ssl_connection_complete) ||
   1929            (connssl->state == ssl_connection_deferred));
   1930   CURL_TRC_CF(data, cf, "gtls_connect_common() -> %d, done=%d", result, *done);
   1931   return result;
   1932 }
   1933 
   1934 static CURLcode gtls_connect(struct Curl_cfilter *cf,
   1935                              struct Curl_easy *data,
   1936                              bool *done)
   1937 {
   1938   struct ssl_connect_data *connssl = cf->ctx;
   1939   if((connssl->state == ssl_connection_deferred) &&
   1940      (connssl->earlydata_state == ssl_earlydata_await)) {
   1941     /* We refuse to be pushed, we are waiting for someone to send/recv. */
   1942     *done = TRUE;
   1943     return CURLE_OK;
   1944   }
   1945   return gtls_connect_common(cf, data, done);
   1946 }
   1947 
   1948 static bool gtls_data_pending(struct Curl_cfilter *cf,
   1949                               const struct Curl_easy *data)
   1950 {
   1951   struct ssl_connect_data *ctx = cf->ctx;
   1952   struct gtls_ssl_backend_data *backend;
   1953 
   1954   (void)data;
   1955   DEBUGASSERT(ctx && ctx->backend);
   1956   backend = (struct gtls_ssl_backend_data *)ctx->backend;
   1957   if(backend->gtls.session &&
   1958      0 != gnutls_record_check_pending(backend->gtls.session))
   1959     return TRUE;
   1960   return FALSE;
   1961 }
   1962 
   1963 static CURLcode gtls_send(struct Curl_cfilter *cf,
   1964                           struct Curl_easy *data,
   1965                           const void *buf,
   1966                           size_t blen,
   1967                           size_t *pnwritten)
   1968 {
   1969   struct ssl_connect_data *connssl = cf->ctx;
   1970   struct gtls_ssl_backend_data *backend =
   1971     (struct gtls_ssl_backend_data *)connssl->backend;
   1972   CURLcode result = CURLE_OK;
   1973   ssize_t nwritten;
   1974   size_t remain = blen;
   1975 
   1976   (void)data;
   1977   DEBUGASSERT(backend);
   1978   *pnwritten = 0;
   1979 
   1980   while(remain) {
   1981     backend->gtls.io_result = CURLE_OK;
   1982     nwritten = gnutls_record_send(backend->gtls.session, buf, remain);
   1983 
   1984     if(nwritten >= 0) {
   1985       *pnwritten += (size_t)nwritten;
   1986       DEBUGASSERT((size_t)nwritten <= remain);
   1987       buf = (char *)CURL_UNCONST(buf) + (size_t)nwritten;
   1988       remain -= (size_t)nwritten;
   1989     }
   1990     else {
   1991       if(*pnwritten && (nwritten == GNUTLS_E_AGAIN)) {
   1992         result = CURLE_OK;
   1993         goto out;
   1994       }
   1995       result = (nwritten == GNUTLS_E_AGAIN) ?
   1996         CURLE_AGAIN :
   1997         (backend->gtls.io_result ? backend->gtls.io_result : CURLE_SEND_ERROR);
   1998       goto out;
   1999     }
   2000   }
   2001 
   2002 out:
   2003   CURL_TRC_CF(data, cf, "gtls_send(len=%zu) -> %d, %zu",
   2004               blen, result, *pnwritten);
   2005   return result;
   2006 }
   2007 
   2008 /*
   2009  * This function is called to shut down the SSL layer but keep the
   2010  * socket open (CCC - Clear Command Channel)
   2011  */
   2012 static CURLcode gtls_shutdown(struct Curl_cfilter *cf,
   2013                               struct Curl_easy *data,
   2014                               bool send_shutdown, bool *done)
   2015 {
   2016   struct ssl_connect_data *connssl = cf->ctx;
   2017   struct gtls_ssl_backend_data *backend =
   2018     (struct gtls_ssl_backend_data *)connssl->backend;
   2019   char buf[1024];
   2020   CURLcode result = CURLE_OK;
   2021   ssize_t nread;
   2022   size_t i;
   2023 
   2024   DEBUGASSERT(backend);
   2025    /* If we have no handshaked connection or already shut down */
   2026   if(!backend->gtls.session || cf->shutdown ||
   2027      connssl->state != ssl_connection_complete) {
   2028     *done = TRUE;
   2029     goto out;
   2030   }
   2031 
   2032   connssl->io_need = CURL_SSL_IO_NEED_NONE;
   2033   *done = FALSE;
   2034 
   2035   if(!backend->gtls.sent_shutdown) {
   2036     /* do this only once */
   2037     backend->gtls.sent_shutdown = TRUE;
   2038     if(send_shutdown) {
   2039       int ret = gnutls_bye(backend->gtls.session, GNUTLS_SHUT_RDWR);
   2040       if((ret == GNUTLS_E_AGAIN) || (ret == GNUTLS_E_INTERRUPTED)) {
   2041         CURL_TRC_CF(data, cf, "SSL shutdown, gnutls_bye EAGAIN");
   2042         connssl->io_need = gnutls_record_get_direction(backend->gtls.session) ?
   2043           CURL_SSL_IO_NEED_SEND : CURL_SSL_IO_NEED_RECV;
   2044         backend->gtls.sent_shutdown = FALSE;
   2045         result = CURLE_OK;
   2046         goto out;
   2047       }
   2048       if(ret != GNUTLS_E_SUCCESS) {
   2049         CURL_TRC_CF(data, cf, "SSL shutdown, gnutls_bye error: '%s'(%d)",
   2050                     gnutls_strerror((int)ret), (int)ret);
   2051         result = CURLE_RECV_ERROR;
   2052         goto out;
   2053       }
   2054     }
   2055   }
   2056 
   2057   /* SSL should now have started the shutdown from our side. Since it
   2058    * was not complete, we are lacking the close notify from the server. */
   2059   for(i = 0; i < 10; ++i) {
   2060     nread = gnutls_record_recv(backend->gtls.session, buf, sizeof(buf));
   2061     if(nread <= 0)
   2062       break;
   2063   }
   2064   if(nread > 0) {
   2065     /* still data coming in? */
   2066   }
   2067   else if(nread == 0) {
   2068     /* We got the close notify alert and are done. */
   2069     *done = TRUE;
   2070   }
   2071   else if((nread == GNUTLS_E_AGAIN) || (nread == GNUTLS_E_INTERRUPTED)) {
   2072     connssl->io_need = gnutls_record_get_direction(backend->gtls.session) ?
   2073       CURL_SSL_IO_NEED_SEND : CURL_SSL_IO_NEED_RECV;
   2074   }
   2075   else {
   2076     CURL_TRC_CF(data, cf, "SSL shutdown, error: '%s'(%d)",
   2077                 gnutls_strerror((int)nread), (int)nread);
   2078     result = CURLE_RECV_ERROR;
   2079   }
   2080 
   2081 out:
   2082   cf->shutdown = (result || *done);
   2083   return result;
   2084 }
   2085 
   2086 static void gtls_close(struct Curl_cfilter *cf,
   2087                        struct Curl_easy *data)
   2088 {
   2089   struct ssl_connect_data *connssl = cf->ctx;
   2090   struct gtls_ssl_backend_data *backend =
   2091     (struct gtls_ssl_backend_data *)connssl->backend;
   2092 
   2093   (void) data;
   2094   DEBUGASSERT(backend);
   2095   CURL_TRC_CF(data, cf, "close");
   2096   if(backend->gtls.session) {
   2097     gnutls_deinit(backend->gtls.session);
   2098     backend->gtls.session = NULL;
   2099   }
   2100   if(backend->gtls.shared_creds) {
   2101     Curl_gtls_shared_creds_free(&backend->gtls.shared_creds);
   2102   }
   2103 #ifdef USE_GNUTLS_SRP
   2104   if(backend->gtls.srp_client_cred) {
   2105     gnutls_srp_free_client_credentials(backend->gtls.srp_client_cred);
   2106     backend->gtls.srp_client_cred = NULL;
   2107   }
   2108 #endif
   2109 }
   2110 
   2111 static CURLcode gtls_recv(struct Curl_cfilter *cf,
   2112                           struct Curl_easy *data,
   2113                           char *buf, size_t blen,
   2114                           size_t *pnread)
   2115 {
   2116   struct ssl_connect_data *connssl = cf->ctx;
   2117   struct gtls_ssl_backend_data *backend =
   2118     (struct gtls_ssl_backend_data *)connssl->backend;
   2119   CURLcode result = CURLE_OK;
   2120   ssize_t nread;
   2121 
   2122   (void)data;
   2123   DEBUGASSERT(backend);
   2124 
   2125   nread = gnutls_record_recv(backend->gtls.session, buf, blen);
   2126 
   2127   if(nread >= 0)
   2128     *pnread = (size_t)nread;
   2129   else {
   2130     if((nread == GNUTLS_E_AGAIN) || (nread == GNUTLS_E_INTERRUPTED)) {
   2131       result = CURLE_AGAIN;
   2132       goto out;
   2133     }
   2134     else if(nread == GNUTLS_E_REHANDSHAKE) {
   2135       /* BLOCKING call, this is bad but a work-around for now. Fixing this "the
   2136          proper way" takes a whole lot of work. */
   2137       result = handshake(cf, data);
   2138       if(!result)
   2139         result = CURLE_AGAIN; /* then return as if this was a wouldblock */
   2140       goto out;
   2141     }
   2142     else {
   2143       failf(data, "GnuTLS recv error (%d): %s",
   2144             (int)nread, gnutls_strerror((int)nread));
   2145       result = backend->gtls.io_result ?
   2146         backend->gtls.io_result : CURLE_RECV_ERROR;
   2147       goto out;
   2148     }
   2149   }
   2150 
   2151 out:
   2152   CURL_TRC_CF(data, cf, "gtls_recv(len=%zu) -> 0, %zu", blen, *pnread);
   2153   return result;
   2154 }
   2155 
   2156 size_t Curl_gtls_version(char *buffer, size_t size)
   2157 {
   2158   return msnprintf(buffer, size, "GnuTLS/%s", gnutls_check_version(NULL));
   2159 }
   2160 
   2161 /* data might be NULL! */
   2162 static CURLcode gtls_random(struct Curl_easy *data,
   2163                             unsigned char *entropy, size_t length)
   2164 {
   2165   int rc;
   2166   (void)data;
   2167   rc = gnutls_rnd(GNUTLS_RND_RANDOM, entropy, length);
   2168   return rc ? CURLE_FAILED_INIT : CURLE_OK;
   2169 }
   2170 
   2171 static CURLcode gtls_sha256sum(const unsigned char *tmp, /* input */
   2172                                size_t tmplen,
   2173                                unsigned char *sha256sum, /* output */
   2174                                size_t sha256len)
   2175 {
   2176   struct sha256_ctx SHA256pw;
   2177   sha256_init(&SHA256pw);
   2178   sha256_update(&SHA256pw, (unsigned int)tmplen, tmp);
   2179   sha256_digest(&SHA256pw, (unsigned int)sha256len, sha256sum);
   2180   return CURLE_OK;
   2181 }
   2182 
   2183 static bool gtls_cert_status_request(void)
   2184 {
   2185   return TRUE;
   2186 }
   2187 
   2188 static void *gtls_get_internals(struct ssl_connect_data *connssl,
   2189                                 CURLINFO info UNUSED_PARAM)
   2190 {
   2191   struct gtls_ssl_backend_data *backend =
   2192     (struct gtls_ssl_backend_data *)connssl->backend;
   2193   (void)info;
   2194   DEBUGASSERT(backend);
   2195   return backend->gtls.session;
   2196 }
   2197 
   2198 const struct Curl_ssl Curl_ssl_gnutls = {
   2199   { CURLSSLBACKEND_GNUTLS, "gnutls" }, /* info */
   2200 
   2201   SSLSUPP_CA_PATH  |
   2202   SSLSUPP_CERTINFO |
   2203   SSLSUPP_PINNEDPUBKEY |
   2204   SSLSUPP_HTTPS_PROXY |
   2205   SSLSUPP_CIPHER_LIST |
   2206   SSLSUPP_CA_CACHE,
   2207 
   2208   sizeof(struct gtls_ssl_backend_data),
   2209 
   2210   gtls_init,                     /* init */
   2211   gtls_cleanup,                  /* cleanup */
   2212   Curl_gtls_version,             /* version */
   2213   gtls_shutdown,                 /* shutdown */
   2214   gtls_data_pending,             /* data_pending */
   2215   gtls_random,                   /* random */
   2216   gtls_cert_status_request,      /* cert_status_request */
   2217   gtls_connect,                  /* connect */
   2218   Curl_ssl_adjust_pollset,       /* adjust_pollset */
   2219   gtls_get_internals,            /* get_internals */
   2220   gtls_close,                    /* close_one */
   2221   NULL,                          /* close_all */
   2222   NULL,                          /* set_engine */
   2223   NULL,                          /* set_engine_default */
   2224   NULL,                          /* engines_list */
   2225   gtls_sha256sum,                /* sha256sum */
   2226   gtls_recv,                     /* recv decrypted data */
   2227   gtls_send,                     /* send data to encrypt */
   2228   NULL,                          /* get_channel_binding */
   2229 };
   2230 
   2231 #endif /* USE_GNUTLS */