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