xref: /third_party/curl/lib/vquic/vquic-tls.c (revision 13498266)
113498266Sopenharmony_ci/***************************************************************************
213498266Sopenharmony_ci *                                  _   _ ____  _
313498266Sopenharmony_ci *  Project                     ___| | | |  _ \| |
413498266Sopenharmony_ci *                             / __| | | | |_) | |
513498266Sopenharmony_ci *                            | (__| |_| |  _ <| |___
613498266Sopenharmony_ci *                             \___|\___/|_| \_\_____|
713498266Sopenharmony_ci *
813498266Sopenharmony_ci * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
913498266Sopenharmony_ci *
1013498266Sopenharmony_ci * This software is licensed as described in the file COPYING, which
1113498266Sopenharmony_ci * you should have received as part of this distribution. The terms
1213498266Sopenharmony_ci * are also available at https://curl.se/docs/copyright.html.
1313498266Sopenharmony_ci *
1413498266Sopenharmony_ci * You may opt to use, copy, modify, merge, publish, distribute and/or sell
1513498266Sopenharmony_ci * copies of the Software, and permit persons to whom the Software is
1613498266Sopenharmony_ci * furnished to do so, under the terms of the COPYING file.
1713498266Sopenharmony_ci *
1813498266Sopenharmony_ci * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
1913498266Sopenharmony_ci * KIND, either express or implied.
2013498266Sopenharmony_ci *
2113498266Sopenharmony_ci * SPDX-License-Identifier: curl
2213498266Sopenharmony_ci *
2313498266Sopenharmony_ci ***************************************************************************/
2413498266Sopenharmony_ci
2513498266Sopenharmony_ci#include "curl_setup.h"
2613498266Sopenharmony_ci
2713498266Sopenharmony_ci#if defined(ENABLE_QUIC) && \
2813498266Sopenharmony_ci  (defined(USE_OPENSSL) || defined(USE_GNUTLS) || defined(USE_WOLFSSL))
2913498266Sopenharmony_ci
3013498266Sopenharmony_ci#ifdef USE_OPENSSL
3113498266Sopenharmony_ci#include <openssl/err.h>
3213498266Sopenharmony_ci#include "vtls/openssl.h"
3313498266Sopenharmony_ci#elif defined(USE_GNUTLS)
3413498266Sopenharmony_ci#include <gnutls/abstract.h>
3513498266Sopenharmony_ci#include <gnutls/gnutls.h>
3613498266Sopenharmony_ci#include <gnutls/x509.h>
3713498266Sopenharmony_ci#include <gnutls/crypto.h>
3813498266Sopenharmony_ci#include <nettle/sha2.h>
3913498266Sopenharmony_ci#include "vtls/gtls.h"
4013498266Sopenharmony_ci#elif defined(USE_WOLFSSL)
4113498266Sopenharmony_ci#include <wolfssl/options.h>
4213498266Sopenharmony_ci#include <wolfssl/ssl.h>
4313498266Sopenharmony_ci#include <wolfssl/quic.h>
4413498266Sopenharmony_ci#include "vtls/wolfssl.h"
4513498266Sopenharmony_ci#endif
4613498266Sopenharmony_ci
4713498266Sopenharmony_ci#include "urldata.h"
4813498266Sopenharmony_ci#include "curl_trc.h"
4913498266Sopenharmony_ci#include "cfilters.h"
5013498266Sopenharmony_ci#include "multiif.h"
5113498266Sopenharmony_ci#include "vtls/keylog.h"
5213498266Sopenharmony_ci#include "vtls/vtls.h"
5313498266Sopenharmony_ci#include "vquic-tls.h"
5413498266Sopenharmony_ci
5513498266Sopenharmony_ci/* The last 3 #include files should be in this order */
5613498266Sopenharmony_ci#include "curl_printf.h"
5713498266Sopenharmony_ci#include "curl_memory.h"
5813498266Sopenharmony_ci#include "memdebug.h"
5913498266Sopenharmony_ci
6013498266Sopenharmony_ci#ifndef ARRAYSIZE
6113498266Sopenharmony_ci#define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0]))
6213498266Sopenharmony_ci#endif
6313498266Sopenharmony_ci
6413498266Sopenharmony_ci#ifdef USE_OPENSSL
6513498266Sopenharmony_ci#define QUIC_CIPHERS                                                          \
6613498266Sopenharmony_ci  "TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_"               \
6713498266Sopenharmony_ci  "POLY1305_SHA256:TLS_AES_128_CCM_SHA256"
6813498266Sopenharmony_ci#define QUIC_GROUPS "P-256:X25519:P-384:P-521"
6913498266Sopenharmony_ci#elif defined(USE_GNUTLS)
7013498266Sopenharmony_ci#define QUIC_PRIORITY \
7113498266Sopenharmony_ci  "NORMAL:-VERS-ALL:+VERS-TLS1.3:-CIPHER-ALL:+AES-128-GCM:+AES-256-GCM:" \
7213498266Sopenharmony_ci  "+CHACHA20-POLY1305:+AES-128-CCM:-GROUP-ALL:+GROUP-SECP256R1:" \
7313498266Sopenharmony_ci  "+GROUP-X25519:+GROUP-SECP384R1:+GROUP-SECP521R1:" \
7413498266Sopenharmony_ci  "%DISABLE_TLS13_COMPAT_MODE"
7513498266Sopenharmony_ci#elif defined(USE_WOLFSSL)
7613498266Sopenharmony_ci#define QUIC_CIPHERS                                                          \
7713498266Sopenharmony_ci  "TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_"               \
7813498266Sopenharmony_ci  "POLY1305_SHA256:TLS_AES_128_CCM_SHA256"
7913498266Sopenharmony_ci#define QUIC_GROUPS "P-256:P-384:P-521"
8013498266Sopenharmony_ci#endif
8113498266Sopenharmony_ci
8213498266Sopenharmony_ci
8313498266Sopenharmony_ci#ifdef USE_OPENSSL
8413498266Sopenharmony_ci
8513498266Sopenharmony_cistatic void keylog_callback(const SSL *ssl, const char *line)
8613498266Sopenharmony_ci{
8713498266Sopenharmony_ci  (void)ssl;
8813498266Sopenharmony_ci  Curl_tls_keylog_write_line(line);
8913498266Sopenharmony_ci}
9013498266Sopenharmony_ci
9113498266Sopenharmony_cistatic CURLcode curl_ossl_init_ctx(struct quic_tls_ctx *ctx,
9213498266Sopenharmony_ci                                   struct Curl_cfilter *cf,
9313498266Sopenharmony_ci                                   struct Curl_easy *data,
9413498266Sopenharmony_ci                                   Curl_vquic_tls_ctx_setup *ctx_setup)
9513498266Sopenharmony_ci{
9613498266Sopenharmony_ci  struct ssl_primary_config *conn_config;
9713498266Sopenharmony_ci  CURLcode result = CURLE_FAILED_INIT;
9813498266Sopenharmony_ci
9913498266Sopenharmony_ci  DEBUGASSERT(!ctx->ssl_ctx);
10013498266Sopenharmony_ci#ifdef USE_OPENSSL_QUIC
10113498266Sopenharmony_ci  ctx->ssl_ctx = SSL_CTX_new(OSSL_QUIC_client_method());
10213498266Sopenharmony_ci#else
10313498266Sopenharmony_ci  ctx->ssl_ctx = SSL_CTX_new(TLS_method());
10413498266Sopenharmony_ci#endif
10513498266Sopenharmony_ci  if(!ctx->ssl_ctx) {
10613498266Sopenharmony_ci    result = CURLE_OUT_OF_MEMORY;
10713498266Sopenharmony_ci    goto out;
10813498266Sopenharmony_ci  }
10913498266Sopenharmony_ci  conn_config = Curl_ssl_cf_get_primary_config(cf);
11013498266Sopenharmony_ci  if(!conn_config) {
11113498266Sopenharmony_ci    result = CURLE_FAILED_INIT;
11213498266Sopenharmony_ci    goto out;
11313498266Sopenharmony_ci  }
11413498266Sopenharmony_ci
11513498266Sopenharmony_ci  if(ctx_setup) {
11613498266Sopenharmony_ci    result = ctx_setup(ctx, cf, data);
11713498266Sopenharmony_ci    if(result)
11813498266Sopenharmony_ci      goto out;
11913498266Sopenharmony_ci  }
12013498266Sopenharmony_ci
12113498266Sopenharmony_ci  SSL_CTX_set_default_verify_paths(ctx->ssl_ctx);
12213498266Sopenharmony_ci
12313498266Sopenharmony_ci  {
12413498266Sopenharmony_ci    const char *curves = conn_config->curves ?
12513498266Sopenharmony_ci      conn_config->curves : QUIC_GROUPS;
12613498266Sopenharmony_ci    if(!SSL_CTX_set1_curves_list(ctx->ssl_ctx, curves)) {
12713498266Sopenharmony_ci      failf(data, "failed setting curves list for QUIC: '%s'", curves);
12813498266Sopenharmony_ci      return CURLE_SSL_CIPHER;
12913498266Sopenharmony_ci    }
13013498266Sopenharmony_ci  }
13113498266Sopenharmony_ci
13213498266Sopenharmony_ci#ifndef OPENSSL_IS_BORINGSSL
13313498266Sopenharmony_ci  {
13413498266Sopenharmony_ci    const char *ciphers13 = conn_config->cipher_list13 ?
13513498266Sopenharmony_ci      conn_config->cipher_list13 : QUIC_CIPHERS;
13613498266Sopenharmony_ci    if(SSL_CTX_set_ciphersuites(ctx->ssl_ctx, ciphers13) != 1) {
13713498266Sopenharmony_ci      failf(data, "failed setting QUIC cipher suite: %s", ciphers13);
13813498266Sopenharmony_ci      return CURLE_SSL_CIPHER;
13913498266Sopenharmony_ci    }
14013498266Sopenharmony_ci    infof(data, "QUIC cipher selection: %s", ciphers13);
14113498266Sopenharmony_ci  }
14213498266Sopenharmony_ci#endif
14313498266Sopenharmony_ci
14413498266Sopenharmony_ci  /* Open the file if a TLS or QUIC backend has not done this before. */
14513498266Sopenharmony_ci  Curl_tls_keylog_open();
14613498266Sopenharmony_ci  if(Curl_tls_keylog_enabled()) {
14713498266Sopenharmony_ci    SSL_CTX_set_keylog_callback(ctx->ssl_ctx, keylog_callback);
14813498266Sopenharmony_ci  }
14913498266Sopenharmony_ci
15013498266Sopenharmony_ci  /* OpenSSL always tries to verify the peer, this only says whether it should
15113498266Sopenharmony_ci   * fail to connect if the verification fails, or if it should continue
15213498266Sopenharmony_ci   * anyway. In the latter case the result of the verification is checked with
15313498266Sopenharmony_ci   * SSL_get_verify_result() below. */
15413498266Sopenharmony_ci  SSL_CTX_set_verify(ctx->ssl_ctx, conn_config->verifypeer ?
15513498266Sopenharmony_ci                     SSL_VERIFY_PEER : SSL_VERIFY_NONE, NULL);
15613498266Sopenharmony_ci
15713498266Sopenharmony_ci  /* give application a chance to interfere with SSL set up. */
15813498266Sopenharmony_ci  if(data->set.ssl.fsslctx) {
15913498266Sopenharmony_ci    /* When a user callback is installed to modify the SSL_CTX,
16013498266Sopenharmony_ci     * we need to do the full initialization before calling it.
16113498266Sopenharmony_ci     * See: #11800 */
16213498266Sopenharmony_ci    if(!ctx->x509_store_setup) {
16313498266Sopenharmony_ci      result = Curl_ssl_setup_x509_store(cf, data, ctx->ssl_ctx);
16413498266Sopenharmony_ci      if(result)
16513498266Sopenharmony_ci        goto out;
16613498266Sopenharmony_ci      ctx->x509_store_setup = TRUE;
16713498266Sopenharmony_ci    }
16813498266Sopenharmony_ci    Curl_set_in_callback(data, true);
16913498266Sopenharmony_ci    result = (*data->set.ssl.fsslctx)(data, ctx->ssl_ctx,
17013498266Sopenharmony_ci                                      data->set.ssl.fsslctxp);
17113498266Sopenharmony_ci    Curl_set_in_callback(data, false);
17213498266Sopenharmony_ci    if(result) {
17313498266Sopenharmony_ci      failf(data, "error signaled by ssl ctx callback");
17413498266Sopenharmony_ci      goto out;
17513498266Sopenharmony_ci    }
17613498266Sopenharmony_ci  }
17713498266Sopenharmony_ci  result = CURLE_OK;
17813498266Sopenharmony_ci
17913498266Sopenharmony_ciout:
18013498266Sopenharmony_ci  if(result && ctx->ssl_ctx) {
18113498266Sopenharmony_ci    SSL_CTX_free(ctx->ssl_ctx);
18213498266Sopenharmony_ci    ctx->ssl_ctx = NULL;
18313498266Sopenharmony_ci  }
18413498266Sopenharmony_ci  return result;
18513498266Sopenharmony_ci}
18613498266Sopenharmony_ci
18713498266Sopenharmony_cistatic CURLcode curl_ossl_set_client_cert(struct quic_tls_ctx *ctx,
18813498266Sopenharmony_ci                                     struct Curl_cfilter *cf,
18913498266Sopenharmony_ci                                     struct Curl_easy *data)
19013498266Sopenharmony_ci{
19113498266Sopenharmony_ci  SSL_CTX *ssl_ctx = ctx->ssl_ctx;
19213498266Sopenharmony_ci  const struct ssl_config_data *ssl_config;
19313498266Sopenharmony_ci
19413498266Sopenharmony_ci  ssl_config = Curl_ssl_cf_get_config(cf, data);
19513498266Sopenharmony_ci  DEBUGASSERT(ssl_config);
19613498266Sopenharmony_ci
19713498266Sopenharmony_ci  if(ssl_config->primary.clientcert ||
19813498266Sopenharmony_ci     ssl_config->primary.cert_blob ||
19913498266Sopenharmony_ci     ssl_config->cert_type) {
20013498266Sopenharmony_ci    return Curl_ossl_set_client_cert(
20113498266Sopenharmony_ci        data, ssl_ctx, ssl_config->primary.clientcert,
20213498266Sopenharmony_ci        ssl_config->primary.cert_blob, ssl_config->cert_type,
20313498266Sopenharmony_ci        ssl_config->key, ssl_config->key_blob,
20413498266Sopenharmony_ci        ssl_config->key_type, ssl_config->key_passwd);
20513498266Sopenharmony_ci  }
20613498266Sopenharmony_ci
20713498266Sopenharmony_ci  return CURLE_OK;
20813498266Sopenharmony_ci}
20913498266Sopenharmony_ci
21013498266Sopenharmony_ci/** SSL callbacks ***/
21113498266Sopenharmony_ci
21213498266Sopenharmony_cistatic CURLcode curl_ossl_init_ssl(struct quic_tls_ctx *ctx,
21313498266Sopenharmony_ci                                   struct Curl_easy *data,
21413498266Sopenharmony_ci                                   struct ssl_peer *peer,
21513498266Sopenharmony_ci                                   const char *alpn, size_t alpn_len,
21613498266Sopenharmony_ci                                   void *user_data)
21713498266Sopenharmony_ci{
21813498266Sopenharmony_ci  DEBUGASSERT(!ctx->ssl);
21913498266Sopenharmony_ci  ctx->ssl = SSL_new(ctx->ssl_ctx);
22013498266Sopenharmony_ci
22113498266Sopenharmony_ci  SSL_set_app_data(ctx->ssl, user_data);
22213498266Sopenharmony_ci  SSL_set_connect_state(ctx->ssl);
22313498266Sopenharmony_ci#ifndef USE_OPENSSL_QUIC
22413498266Sopenharmony_ci  SSL_set_quic_use_legacy_codepoint(ctx->ssl, 0);
22513498266Sopenharmony_ci#endif
22613498266Sopenharmony_ci
22713498266Sopenharmony_ci  if(alpn)
22813498266Sopenharmony_ci    SSL_set_alpn_protos(ctx->ssl, (const uint8_t *)alpn, (int)alpn_len);
22913498266Sopenharmony_ci
23013498266Sopenharmony_ci  if(peer->sni) {
23113498266Sopenharmony_ci    if(!SSL_set_tlsext_host_name(ctx->ssl, peer->sni)) {
23213498266Sopenharmony_ci      failf(data, "Failed set SNI");
23313498266Sopenharmony_ci      SSL_free(ctx->ssl);
23413498266Sopenharmony_ci      ctx->ssl = NULL;
23513498266Sopenharmony_ci      return CURLE_QUIC_CONNECT_ERROR;
23613498266Sopenharmony_ci    }
23713498266Sopenharmony_ci  }
23813498266Sopenharmony_ci  return CURLE_OK;
23913498266Sopenharmony_ci}
24013498266Sopenharmony_ci
24113498266Sopenharmony_ci#elif defined(USE_GNUTLS)
24213498266Sopenharmony_cistatic int keylog_callback(gnutls_session_t session, const char *label,
24313498266Sopenharmony_ci                    const gnutls_datum_t *secret)
24413498266Sopenharmony_ci{
24513498266Sopenharmony_ci  gnutls_datum_t crandom;
24613498266Sopenharmony_ci  gnutls_datum_t srandom;
24713498266Sopenharmony_ci
24813498266Sopenharmony_ci  gnutls_session_get_random(session, &crandom, &srandom);
24913498266Sopenharmony_ci  if(crandom.size != 32) {
25013498266Sopenharmony_ci    return -1;
25113498266Sopenharmony_ci  }
25213498266Sopenharmony_ci
25313498266Sopenharmony_ci  Curl_tls_keylog_write(label, crandom.data, secret->data, secret->size);
25413498266Sopenharmony_ci  return 0;
25513498266Sopenharmony_ci}
25613498266Sopenharmony_ci
25713498266Sopenharmony_cistatic CURLcode curl_gtls_init_ctx(struct quic_tls_ctx *ctx,
25813498266Sopenharmony_ci                                   struct Curl_cfilter *cf,
25913498266Sopenharmony_ci                                   struct Curl_easy *data,
26013498266Sopenharmony_ci                                   struct ssl_peer *peer,
26113498266Sopenharmony_ci                                   const char *alpn, size_t alpn_len,
26213498266Sopenharmony_ci                                   Curl_vquic_tls_ctx_setup *ctx_setup,
26313498266Sopenharmony_ci                                   void *user_data)
26413498266Sopenharmony_ci{
26513498266Sopenharmony_ci  struct ssl_primary_config *conn_config;
26613498266Sopenharmony_ci  CURLcode result;
26713498266Sopenharmony_ci  gnutls_datum_t alpns[5];
26813498266Sopenharmony_ci  /* this will need some attention when HTTPS proxy over QUIC get fixed */
26913498266Sopenharmony_ci  long * const pverifyresult = &data->set.ssl.certverifyresult;
27013498266Sopenharmony_ci  int rc;
27113498266Sopenharmony_ci
27213498266Sopenharmony_ci  conn_config = Curl_ssl_cf_get_primary_config(cf);
27313498266Sopenharmony_ci  if(!conn_config)
27413498266Sopenharmony_ci    return CURLE_FAILED_INIT;
27513498266Sopenharmony_ci
27613498266Sopenharmony_ci  DEBUGASSERT(ctx->gtls == NULL);
27713498266Sopenharmony_ci  ctx->gtls = calloc(1, sizeof(*(ctx->gtls)));
27813498266Sopenharmony_ci  if(!ctx->gtls)
27913498266Sopenharmony_ci    return CURLE_OUT_OF_MEMORY;
28013498266Sopenharmony_ci
28113498266Sopenharmony_ci  result = gtls_client_init(data, conn_config, &data->set.ssl,
28213498266Sopenharmony_ci                            peer, ctx->gtls, pverifyresult);
28313498266Sopenharmony_ci  if(result)
28413498266Sopenharmony_ci    return result;
28513498266Sopenharmony_ci
28613498266Sopenharmony_ci  gnutls_session_set_ptr(ctx->gtls->session, user_data);
28713498266Sopenharmony_ci
28813498266Sopenharmony_ci  if(ctx_setup) {
28913498266Sopenharmony_ci    result = ctx_setup(ctx, cf, data);
29013498266Sopenharmony_ci    if(result)
29113498266Sopenharmony_ci      return result;
29213498266Sopenharmony_ci  }
29313498266Sopenharmony_ci
29413498266Sopenharmony_ci  rc = gnutls_priority_set_direct(ctx->gtls->session, QUIC_PRIORITY, NULL);
29513498266Sopenharmony_ci  if(rc < 0) {
29613498266Sopenharmony_ci    CURL_TRC_CF(data, cf, "gnutls_priority_set_direct failed: %s\n",
29713498266Sopenharmony_ci                gnutls_strerror(rc));
29813498266Sopenharmony_ci    return CURLE_QUIC_CONNECT_ERROR;
29913498266Sopenharmony_ci  }
30013498266Sopenharmony_ci
30113498266Sopenharmony_ci  /* Open the file if a TLS or QUIC backend has not done this before. */
30213498266Sopenharmony_ci  Curl_tls_keylog_open();
30313498266Sopenharmony_ci  if(Curl_tls_keylog_enabled()) {
30413498266Sopenharmony_ci    gnutls_session_set_keylog_function(ctx->gtls->session, keylog_callback);
30513498266Sopenharmony_ci  }
30613498266Sopenharmony_ci
30713498266Sopenharmony_ci  /* convert the ALPN string from our arguments to a list of strings
30813498266Sopenharmony_ci   * that gnutls wants and will convert internally back to this very
30913498266Sopenharmony_ci   * string for sending to the server. nice. */
31013498266Sopenharmony_ci  if(alpn) {
31113498266Sopenharmony_ci    size_t i, alen = alpn_len;
31213498266Sopenharmony_ci    unsigned char *s = (unsigned char *)alpn;
31313498266Sopenharmony_ci    unsigned char slen;
31413498266Sopenharmony_ci    for(i = 0; (i < ARRAYSIZE(alpns)) && alen; ++i) {
31513498266Sopenharmony_ci      slen = s[0];
31613498266Sopenharmony_ci      if(slen >= alen)
31713498266Sopenharmony_ci        return CURLE_FAILED_INIT;
31813498266Sopenharmony_ci      alpns[i].data = s + 1;
31913498266Sopenharmony_ci      alpns[i].size = slen;
32013498266Sopenharmony_ci      s += slen + 1;
32113498266Sopenharmony_ci      alen -= (size_t)slen + 1;
32213498266Sopenharmony_ci    }
32313498266Sopenharmony_ci    if(alen) /* not all alpn chars used, wrong format or too many */
32413498266Sopenharmony_ci        return CURLE_FAILED_INIT;
32513498266Sopenharmony_ci    if(i) {
32613498266Sopenharmony_ci      gnutls_alpn_set_protocols(ctx->gtls->session,
32713498266Sopenharmony_ci                                alpns, (unsigned int)i,
32813498266Sopenharmony_ci                                GNUTLS_ALPN_MANDATORY);
32913498266Sopenharmony_ci    }
33013498266Sopenharmony_ci  }
33113498266Sopenharmony_ci
33213498266Sopenharmony_ci  return CURLE_OK;
33313498266Sopenharmony_ci}
33413498266Sopenharmony_ci#elif defined(USE_WOLFSSL)
33513498266Sopenharmony_ci
33613498266Sopenharmony_ci#if defined(HAVE_SECRET_CALLBACK)
33713498266Sopenharmony_cistatic void keylog_callback(const WOLFSSL *ssl, const char *line)
33813498266Sopenharmony_ci{
33913498266Sopenharmony_ci  (void)ssl;
34013498266Sopenharmony_ci  Curl_tls_keylog_write_line(line);
34113498266Sopenharmony_ci}
34213498266Sopenharmony_ci#endif
34313498266Sopenharmony_ci
34413498266Sopenharmony_cistatic CURLcode curl_wssl_init_ctx(struct quic_tls_ctx *ctx,
34513498266Sopenharmony_ci                                   struct Curl_cfilter *cf,
34613498266Sopenharmony_ci                                   struct Curl_easy *data,
34713498266Sopenharmony_ci                                   Curl_vquic_tls_ctx_setup *ctx_setup)
34813498266Sopenharmony_ci{
34913498266Sopenharmony_ci  struct ssl_primary_config *conn_config;
35013498266Sopenharmony_ci  CURLcode result = CURLE_FAILED_INIT;
35113498266Sopenharmony_ci
35213498266Sopenharmony_ci  conn_config = Curl_ssl_cf_get_primary_config(cf);
35313498266Sopenharmony_ci  if(!conn_config) {
35413498266Sopenharmony_ci    result = CURLE_FAILED_INIT;
35513498266Sopenharmony_ci    goto out;
35613498266Sopenharmony_ci  }
35713498266Sopenharmony_ci
35813498266Sopenharmony_ci  ctx->ssl_ctx = wolfSSL_CTX_new(wolfTLSv1_3_client_method());
35913498266Sopenharmony_ci  if(!ctx->ssl_ctx) {
36013498266Sopenharmony_ci    result = CURLE_OUT_OF_MEMORY;
36113498266Sopenharmony_ci    goto out;
36213498266Sopenharmony_ci  }
36313498266Sopenharmony_ci
36413498266Sopenharmony_ci  if(ctx_setup) {
36513498266Sopenharmony_ci    result = ctx_setup(ctx, cf, data);
36613498266Sopenharmony_ci    if(result)
36713498266Sopenharmony_ci      goto out;
36813498266Sopenharmony_ci  }
36913498266Sopenharmony_ci
37013498266Sopenharmony_ci  wolfSSL_CTX_set_default_verify_paths(ctx->ssl_ctx);
37113498266Sopenharmony_ci
37213498266Sopenharmony_ci  if(wolfSSL_CTX_set_cipher_list(ctx->ssl_ctx, conn_config->cipher_list13 ?
37313498266Sopenharmony_ci                                 conn_config->cipher_list13 :
37413498266Sopenharmony_ci                                 QUIC_CIPHERS) != 1) {
37513498266Sopenharmony_ci    char error_buffer[256];
37613498266Sopenharmony_ci    ERR_error_string_n(ERR_get_error(), error_buffer, sizeof(error_buffer));
37713498266Sopenharmony_ci    failf(data, "wolfSSL failed to set ciphers: %s", error_buffer);
37813498266Sopenharmony_ci    result = CURLE_BAD_FUNCTION_ARGUMENT;
37913498266Sopenharmony_ci    goto out;
38013498266Sopenharmony_ci  }
38113498266Sopenharmony_ci
38213498266Sopenharmony_ci  if(wolfSSL_CTX_set1_groups_list(ctx->ssl_ctx, conn_config->curves ?
38313498266Sopenharmony_ci                                  conn_config->curves :
38413498266Sopenharmony_ci                                  (char *)QUIC_GROUPS) != 1) {
38513498266Sopenharmony_ci    failf(data, "wolfSSL failed to set curves");
38613498266Sopenharmony_ci    result = CURLE_BAD_FUNCTION_ARGUMENT;
38713498266Sopenharmony_ci    goto out;
38813498266Sopenharmony_ci  }
38913498266Sopenharmony_ci
39013498266Sopenharmony_ci  /* Open the file if a TLS or QUIC backend has not done this before. */
39113498266Sopenharmony_ci  Curl_tls_keylog_open();
39213498266Sopenharmony_ci  if(Curl_tls_keylog_enabled()) {
39313498266Sopenharmony_ci#if defined(HAVE_SECRET_CALLBACK)
39413498266Sopenharmony_ci    wolfSSL_CTX_set_keylog_callback(ctx->ssl_ctx, keylog_callback);
39513498266Sopenharmony_ci#else
39613498266Sopenharmony_ci    failf(data, "wolfSSL was built without keylog callback");
39713498266Sopenharmony_ci    result = CURLE_NOT_BUILT_IN;
39813498266Sopenharmony_ci    goto out;
39913498266Sopenharmony_ci#endif
40013498266Sopenharmony_ci  }
40113498266Sopenharmony_ci
40213498266Sopenharmony_ci  if(conn_config->verifypeer) {
40313498266Sopenharmony_ci    const char * const ssl_cafile = conn_config->CAfile;
40413498266Sopenharmony_ci    const char * const ssl_capath = conn_config->CApath;
40513498266Sopenharmony_ci
40613498266Sopenharmony_ci    wolfSSL_CTX_set_verify(ctx->ssl_ctx, SSL_VERIFY_PEER, NULL);
40713498266Sopenharmony_ci    if(ssl_cafile || ssl_capath) {
40813498266Sopenharmony_ci      /* tell wolfSSL where to find CA certificates that are used to verify
40913498266Sopenharmony_ci         the server's certificate. */
41013498266Sopenharmony_ci      int rc =
41113498266Sopenharmony_ci        wolfSSL_CTX_load_verify_locations_ex(ctx->ssl_ctx, ssl_cafile,
41213498266Sopenharmony_ci                                             ssl_capath,
41313498266Sopenharmony_ci                                             WOLFSSL_LOAD_FLAG_IGNORE_ERR);
41413498266Sopenharmony_ci      if(SSL_SUCCESS != rc) {
41513498266Sopenharmony_ci        /* Fail if we insist on successfully verifying the server. */
41613498266Sopenharmony_ci        failf(data, "error setting certificate verify locations:"
41713498266Sopenharmony_ci              "  CAfile: %s CApath: %s",
41813498266Sopenharmony_ci              ssl_cafile ? ssl_cafile : "none",
41913498266Sopenharmony_ci              ssl_capath ? ssl_capath : "none");
42013498266Sopenharmony_ci        result = CURLE_SSL_CACERT;
42113498266Sopenharmony_ci        goto out;
42213498266Sopenharmony_ci      }
42313498266Sopenharmony_ci      infof(data, " CAfile: %s", ssl_cafile ? ssl_cafile : "none");
42413498266Sopenharmony_ci      infof(data, " CApath: %s", ssl_capath ? ssl_capath : "none");
42513498266Sopenharmony_ci    }
42613498266Sopenharmony_ci#ifdef CURL_CA_FALLBACK
42713498266Sopenharmony_ci    else {
42813498266Sopenharmony_ci      /* verifying the peer without any CA certificates won't work so
42913498266Sopenharmony_ci         use wolfssl's built-in default as fallback */
43013498266Sopenharmony_ci      wolfSSL_CTX_set_default_verify_paths(ctx->ssl_ctx);
43113498266Sopenharmony_ci    }
43213498266Sopenharmony_ci#endif
43313498266Sopenharmony_ci  }
43413498266Sopenharmony_ci  else {
43513498266Sopenharmony_ci    wolfSSL_CTX_set_verify(ctx->ssl_ctx, SSL_VERIFY_NONE, NULL);
43613498266Sopenharmony_ci  }
43713498266Sopenharmony_ci
43813498266Sopenharmony_ci  /* give application a chance to interfere with SSL set up. */
43913498266Sopenharmony_ci  if(data->set.ssl.fsslctx) {
44013498266Sopenharmony_ci    Curl_set_in_callback(data, true);
44113498266Sopenharmony_ci    result = (*data->set.ssl.fsslctx)(data, ctx->ssl_ctx,
44213498266Sopenharmony_ci                                      data->set.ssl.fsslctxp);
44313498266Sopenharmony_ci    Curl_set_in_callback(data, false);
44413498266Sopenharmony_ci    if(result) {
44513498266Sopenharmony_ci      failf(data, "error signaled by ssl ctx callback");
44613498266Sopenharmony_ci      goto out;
44713498266Sopenharmony_ci    }
44813498266Sopenharmony_ci  }
44913498266Sopenharmony_ci  result = CURLE_OK;
45013498266Sopenharmony_ci
45113498266Sopenharmony_ciout:
45213498266Sopenharmony_ci  if(result && ctx->ssl_ctx) {
45313498266Sopenharmony_ci    SSL_CTX_free(ctx->ssl_ctx);
45413498266Sopenharmony_ci    ctx->ssl_ctx = NULL;
45513498266Sopenharmony_ci  }
45613498266Sopenharmony_ci  return result;
45713498266Sopenharmony_ci}
45813498266Sopenharmony_ci
45913498266Sopenharmony_ci/** SSL callbacks ***/
46013498266Sopenharmony_ci
46113498266Sopenharmony_cistatic CURLcode curl_wssl_init_ssl(struct quic_tls_ctx *ctx,
46213498266Sopenharmony_ci                                   struct Curl_easy *data,
46313498266Sopenharmony_ci                                   struct ssl_peer *peer,
46413498266Sopenharmony_ci                                   const char *alpn, size_t alpn_len,
46513498266Sopenharmony_ci                                   void *user_data)
46613498266Sopenharmony_ci{
46713498266Sopenharmony_ci  (void)data;
46813498266Sopenharmony_ci  DEBUGASSERT(!ctx->ssl);
46913498266Sopenharmony_ci  DEBUGASSERT(ctx->ssl_ctx);
47013498266Sopenharmony_ci  ctx->ssl = wolfSSL_new(ctx->ssl_ctx);
47113498266Sopenharmony_ci
47213498266Sopenharmony_ci  wolfSSL_set_app_data(ctx->ssl, user_data);
47313498266Sopenharmony_ci  wolfSSL_set_connect_state(ctx->ssl);
47413498266Sopenharmony_ci  wolfSSL_set_quic_use_legacy_codepoint(ctx->ssl, 0);
47513498266Sopenharmony_ci
47613498266Sopenharmony_ci  if(alpn)
47713498266Sopenharmony_ci    wolfSSL_set_alpn_protos(ctx->ssl, (const unsigned char *)alpn,
47813498266Sopenharmony_ci                            (int)alpn_len);
47913498266Sopenharmony_ci
48013498266Sopenharmony_ci  if(peer->sni) {
48113498266Sopenharmony_ci    wolfSSL_UseSNI(ctx->ssl, WOLFSSL_SNI_HOST_NAME,
48213498266Sopenharmony_ci                   peer->sni, (unsigned short)strlen(peer->sni));
48313498266Sopenharmony_ci  }
48413498266Sopenharmony_ci
48513498266Sopenharmony_ci  return CURLE_OK;
48613498266Sopenharmony_ci}
48713498266Sopenharmony_ci#endif /* defined(USE_WOLFSSL) */
48813498266Sopenharmony_ci
48913498266Sopenharmony_ciCURLcode Curl_vquic_tls_init(struct quic_tls_ctx *ctx,
49013498266Sopenharmony_ci                             struct Curl_cfilter *cf,
49113498266Sopenharmony_ci                             struct Curl_easy *data,
49213498266Sopenharmony_ci                             struct ssl_peer *peer,
49313498266Sopenharmony_ci                             const char *alpn, size_t alpn_len,
49413498266Sopenharmony_ci                             Curl_vquic_tls_ctx_setup *ctx_setup,
49513498266Sopenharmony_ci                             void *user_data)
49613498266Sopenharmony_ci{
49713498266Sopenharmony_ci  CURLcode result;
49813498266Sopenharmony_ci
49913498266Sopenharmony_ci#ifdef USE_OPENSSL
50013498266Sopenharmony_ci  result = curl_ossl_init_ctx(ctx, cf, data, ctx_setup);
50113498266Sopenharmony_ci  if(result)
50213498266Sopenharmony_ci    return result;
50313498266Sopenharmony_ci
50413498266Sopenharmony_ci  result = curl_ossl_set_client_cert(ctx, cf, data);
50513498266Sopenharmony_ci  if(result)
50613498266Sopenharmony_ci    return result;
50713498266Sopenharmony_ci
50813498266Sopenharmony_ci  return curl_ossl_init_ssl(ctx, data, peer, alpn, alpn_len, user_data);
50913498266Sopenharmony_ci#elif defined(USE_GNUTLS)
51013498266Sopenharmony_ci  (void)result;
51113498266Sopenharmony_ci  return curl_gtls_init_ctx(ctx, cf, data, peer, alpn, alpn_len,
51213498266Sopenharmony_ci                            ctx_setup, user_data);
51313498266Sopenharmony_ci#elif defined(USE_WOLFSSL)
51413498266Sopenharmony_ci  result = curl_wssl_init_ctx(ctx, cf, data, ctx_setup);
51513498266Sopenharmony_ci  if(result)
51613498266Sopenharmony_ci    return result;
51713498266Sopenharmony_ci
51813498266Sopenharmony_ci  return curl_wssl_init_ssl(ctx, data, peer, alpn, alpn_len, user_data);
51913498266Sopenharmony_ci#else
52013498266Sopenharmony_ci#error "no TLS lib in used, should not happen"
52113498266Sopenharmony_ci  return CURLE_FAILED_INIT;
52213498266Sopenharmony_ci#endif
52313498266Sopenharmony_ci}
52413498266Sopenharmony_ci
52513498266Sopenharmony_civoid Curl_vquic_tls_cleanup(struct quic_tls_ctx *ctx)
52613498266Sopenharmony_ci{
52713498266Sopenharmony_ci#ifdef USE_OPENSSL
52813498266Sopenharmony_ci  if(ctx->ssl)
52913498266Sopenharmony_ci    SSL_free(ctx->ssl);
53013498266Sopenharmony_ci  if(ctx->ssl_ctx)
53113498266Sopenharmony_ci    SSL_CTX_free(ctx->ssl_ctx);
53213498266Sopenharmony_ci#elif defined(USE_GNUTLS)
53313498266Sopenharmony_ci  if(ctx->gtls) {
53413498266Sopenharmony_ci    if(ctx->gtls->cred)
53513498266Sopenharmony_ci      gnutls_certificate_free_credentials(ctx->gtls->cred);
53613498266Sopenharmony_ci    if(ctx->gtls->session)
53713498266Sopenharmony_ci      gnutls_deinit(ctx->gtls->session);
53813498266Sopenharmony_ci    free(ctx->gtls);
53913498266Sopenharmony_ci  }
54013498266Sopenharmony_ci#elif defined(USE_WOLFSSL)
54113498266Sopenharmony_ci  if(ctx->ssl)
54213498266Sopenharmony_ci    wolfSSL_free(ctx->ssl);
54313498266Sopenharmony_ci  if(ctx->ssl_ctx)
54413498266Sopenharmony_ci    wolfSSL_CTX_free(ctx->ssl_ctx);
54513498266Sopenharmony_ci#endif
54613498266Sopenharmony_ci  memset(ctx, 0, sizeof(*ctx));
54713498266Sopenharmony_ci}
54813498266Sopenharmony_ci
54913498266Sopenharmony_ciCURLcode Curl_vquic_tls_before_recv(struct quic_tls_ctx *ctx,
55013498266Sopenharmony_ci                                    struct Curl_cfilter *cf,
55113498266Sopenharmony_ci                                    struct Curl_easy *data)
55213498266Sopenharmony_ci{
55313498266Sopenharmony_ci#ifdef USE_OPENSSL
55413498266Sopenharmony_ci  if(!ctx->x509_store_setup) {
55513498266Sopenharmony_ci    CURLcode result = Curl_ssl_setup_x509_store(cf, data, ctx->ssl_ctx);
55613498266Sopenharmony_ci    if(result)
55713498266Sopenharmony_ci      return result;
55813498266Sopenharmony_ci    ctx->x509_store_setup = TRUE;
55913498266Sopenharmony_ci  }
56013498266Sopenharmony_ci#else
56113498266Sopenharmony_ci  (void)ctx; (void)cf; (void)data;
56213498266Sopenharmony_ci#endif
56313498266Sopenharmony_ci  return CURLE_OK;
56413498266Sopenharmony_ci}
56513498266Sopenharmony_ci
56613498266Sopenharmony_ciCURLcode Curl_vquic_tls_verify_peer(struct quic_tls_ctx *ctx,
56713498266Sopenharmony_ci                                    struct Curl_cfilter *cf,
56813498266Sopenharmony_ci                                    struct Curl_easy *data,
56913498266Sopenharmony_ci                                    struct ssl_peer *peer)
57013498266Sopenharmony_ci{
57113498266Sopenharmony_ci  struct ssl_primary_config *conn_config;
57213498266Sopenharmony_ci  CURLcode result = CURLE_OK;
57313498266Sopenharmony_ci
57413498266Sopenharmony_ci  conn_config = Curl_ssl_cf_get_primary_config(cf);
57513498266Sopenharmony_ci  if(!conn_config)
57613498266Sopenharmony_ci    return CURLE_FAILED_INIT;
57713498266Sopenharmony_ci
57813498266Sopenharmony_ci  if(conn_config->verifyhost) {
57913498266Sopenharmony_ci#ifdef USE_OPENSSL
58013498266Sopenharmony_ci    X509 *server_cert;
58113498266Sopenharmony_ci    server_cert = SSL_get1_peer_certificate(ctx->ssl);
58213498266Sopenharmony_ci    if(!server_cert) {
58313498266Sopenharmony_ci      return CURLE_PEER_FAILED_VERIFICATION;
58413498266Sopenharmony_ci    }
58513498266Sopenharmony_ci    result = Curl_ossl_verifyhost(data, cf->conn, peer, server_cert);
58613498266Sopenharmony_ci    X509_free(server_cert);
58713498266Sopenharmony_ci    if(result)
58813498266Sopenharmony_ci      return result;
58913498266Sopenharmony_ci#elif defined(USE_GNUTLS)
59013498266Sopenharmony_ci    result = Curl_gtls_verifyserver(data, ctx->gtls->session,
59113498266Sopenharmony_ci                                    conn_config, &data->set.ssl, peer,
59213498266Sopenharmony_ci                                    data->set.str[STRING_SSL_PINNEDPUBLICKEY]);
59313498266Sopenharmony_ci    if(result)
59413498266Sopenharmony_ci      return result;
59513498266Sopenharmony_ci#elif defined(USE_WOLFSSL)
59613498266Sopenharmony_ci    if(!peer->sni ||
59713498266Sopenharmony_ci       wolfSSL_check_domain_name(ctx->ssl, peer->sni) == SSL_FAILURE)
59813498266Sopenharmony_ci      return CURLE_PEER_FAILED_VERIFICATION;
59913498266Sopenharmony_ci#endif
60013498266Sopenharmony_ci    infof(data, "Verified certificate just fine");
60113498266Sopenharmony_ci  }
60213498266Sopenharmony_ci  else
60313498266Sopenharmony_ci    infof(data, "Skipped certificate verification");
60413498266Sopenharmony_ci#ifdef USE_OPENSSL
60513498266Sopenharmony_ci  if(data->set.ssl.certinfo)
60613498266Sopenharmony_ci    /* asked to gather certificate info */
60713498266Sopenharmony_ci    (void)Curl_ossl_certchain(data, ctx->ssl);
60813498266Sopenharmony_ci#endif
60913498266Sopenharmony_ci  return result;
61013498266Sopenharmony_ci}
61113498266Sopenharmony_ci
61213498266Sopenharmony_ci
61313498266Sopenharmony_ci#endif /* !ENABLE_QUIC && (USE_OPENSSL || USE_GNUTLS || USE_WOLFSSL) */
614