- make colliding vtls static function names unique.
- wolfssl: stop including an unused compatibility header.
- cmake: adapt detection logic for openssl+wolfssl coexist.
- wolfssl: fix to use native wolfSSL API in ECH codepath.
- openssl+wolfssl: fix ECH code to coexist.
Requires a post wolfSSL v5.7.4, recent master for `OPENSSL_COEXIST`
feature, and `CPPFLAGS=-DOPENSSL_COEXIST`.
Ref: https://github.com/wolfSSL/wolfssl/issues/8194
Closes #15596
list(APPEND CMAKE_REQUIRED_LIBRARIES "ws2_32")
list(APPEND CMAKE_REQUIRED_LIBRARIES "bcrypt") # for OpenSSL/LibreSSL
endif()
- elseif(USE_WOLFSSL)
+ endif()
+ if(USE_WOLFSSL)
list(APPEND CMAKE_REQUIRED_INCLUDES "${WOLFSSL_INCLUDE_DIRS}")
list(APPEND CMAKE_REQUIRED_LIBRARIES "${WOLFSSL_LIBRARIES}")
curl_required_libpaths("${WOLFSSL_LIBRARY_DIRS}")
if(NOT DEFINED HAVE_SSL_CTX_SET_QUIC_METHOD)
if(USE_OPENSSL)
curl_openssl_check_symbol_exists("SSL_CTX_set_quic_method" "openssl/ssl.h" HAVE_SSL_CTX_SET_QUIC_METHOD "")
- elseif(USE_WOLFSSL)
+ endif()
+ if(USE_WOLFSSL)
curl_openssl_check_symbol_exists("wolfSSL_set_quic_method" "wolfssl/options.h;wolfssl/openssl/ssl.h"
HAVE_SSL_CTX_SET_QUIC_METHOD "")
endif()
if(USE_ECH)
if(USE_OPENSSL OR USE_WOLFSSL)
# Be sure that the TLS library actually supports ECH.
- if(NOT DEFINED HAVE_ECH)
- if(USE_OPENSSL AND (HAVE_BORINGSSL OR HAVE_AWSLC))
- curl_openssl_check_symbol_exists("SSL_set1_ech_config_list" "openssl/ssl.h" HAVE_ECH "")
- elseif(USE_OPENSSL)
- curl_openssl_check_symbol_exists("SSL_ech_set1_echconfig" "openssl/ech.h" HAVE_ECH "")
- elseif(USE_WOLFSSL)
- curl_openssl_check_symbol_exists("wolfSSL_CTX_GenerateEchConfig" "wolfssl/options.h;wolfssl/ssl.h" HAVE_ECH "")
- endif()
+ if(USE_WOLFSSL)
+ curl_openssl_check_symbol_exists("wolfSSL_CTX_GenerateEchConfig" "wolfssl/options.h;wolfssl/ssl.h"
+ HAVE_WOLFSSL_CTX_GENERATEECHCONFIG "")
+ endif()
+ if(HAVE_BORINGSSL OR HAVE_AWSLC)
+ curl_openssl_check_symbol_exists("SSL_set1_ech_config_list" "openssl/ssl.h"
+ HAVE_SSL_SET1_ECH_CONFIG_LIST "")
+ elseif(HAVE_OPENSSL)
+ curl_openssl_check_symbol_exists("SSL_ech_set1_echconfig" "openssl/ech.h"
+ HAVE_SSL_ECH_SET1_ECHCONFIG "")
+ endif()
+ if(HAVE_WOLFSSL_CTX_GENERATEECHCONFIG OR
+ HAVE_SSL_SET1_ECH_CONFIG_LIST OR
+ HAVE_SSL_ECH_SET1_ECHCONFIG)
+ set(HAVE_ECH 1)
endif()
if(NOT HAVE_ECH)
message(FATAL_ERROR "ECH support missing in OpenSSL/BoringSSL/AWS-LC/wolfSSL")
/* if ECH support is available */
#cmakedefine USE_ECH 1
+
+/* Define to 1 if you have the wolfSSL_CTX_GenerateEchConfig function. */
+#cmakedefine HAVE_WOLFSSL_CTX_GENERATEECHCONFIG
+
+/* Define to 1 if you have the SSL_set1_ech_config_list function. */
+#cmakedefine HAVE_SSL_SET1_ECH_CONFIG_LIST
+
+/* Define to 1 if you have the SSL_ech_set1_echconfig function. */
+#cmakedefine HAVE_SSL_ECH_SET1_ECHCONFIG
#include <openssl/tls1.h>
#include <openssl/evp.h>
-#ifdef USE_ECH
+#if defined(HAVE_SSL_SET1_ECH_CONFIG_LIST) || \
+ defined(HAVE_SSL_ECH_SET1_ECHCONFIG)
+#define USE_ECH_OPENSSL
+#endif
+
+#ifdef USE_ECH_OPENSSL
# if !defined(OPENSSL_IS_BORINGSSL) && !defined(OPENSSL_IS_AWSLC)
# include <openssl/ech.h>
# endif
-# include "curl_base64.h"
-# define ECH_ENABLED(__data__) \
- (__data__->set.tls_ech && \
- !(__data__->set.tls_ech & CURLECH_DISABLE)\
- )
-#endif /* USE_ECH */
+#endif /* USE_ECH_OPENSSL */
#if (OPENSSL_VERSION_NUMBER >= 0x0090808fL) && !defined(OPENSSL_NO_OCSP)
#include <openssl/ocsp.h>
}
#endif
-static CURLcode populate_x509_store(struct Curl_cfilter *cf,
- struct Curl_easy *data,
- X509_STORE *store)
+static CURLcode ossl_populate_x509_store(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ X509_STORE *store)
{
struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
bool imported_native_ca = FALSE;
bool imported_ca_info_blob = FALSE;
- CURL_TRC_CF(data, cf, "populate_x509_store, path=%s, blob=%d",
+ CURL_TRC_CF(data, cf, "ossl_populate_x509_store, path=%s, blob=%d",
ssl_cafile ? ssl_cafile : "none", !!ca_info_blob);
if(!store)
return CURLE_OUT_OF_MEMORY;
}
static bool
-cached_x509_store_expired(const struct Curl_easy *data,
- const struct ossl_x509_share *mb)
+ossl_cached_x509_store_expired(const struct Curl_easy *data,
+ const struct ossl_x509_share *mb)
{
const struct ssl_general_config *cfg = &data->set.general_ssl;
if(cfg->ca_cache_timeout < 0)
}
static bool
-cached_x509_store_different(struct Curl_cfilter *cf,
- const struct ossl_x509_share *mb)
+ossl_cached_x509_store_different(struct Curl_cfilter *cf,
+ const struct ossl_x509_share *mb)
{
struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
if(!mb->CAfile || !conn_config->CAfile)
return strcmp(mb->CAfile, conn_config->CAfile);
}
-static X509_STORE *get_cached_x509_store(struct Curl_cfilter *cf,
- const struct Curl_easy *data)
+static X509_STORE *ossl_get_cached_x509_store(struct Curl_cfilter *cf,
+ const struct Curl_easy *data)
{
struct Curl_multi *multi = data->multi;
struct ossl_x509_share *share;
(void *)MPROTO_OSSL_X509_KEY,
sizeof(MPROTO_OSSL_X509_KEY)-1) : NULL;
if(share && share->store &&
- !cached_x509_store_expired(data, share) &&
- !cached_x509_store_different(cf, share)) {
+ !ossl_cached_x509_store_expired(data, share) &&
+ !ossl_cached_x509_store_different(cf, share)) {
store = share->store;
}
return store;
}
-static void set_cached_x509_store(struct Curl_cfilter *cf,
- const struct Curl_easy *data,
- X509_STORE *store)
+static void ossl_set_cached_x509_store(struct Curl_cfilter *cf,
+ const struct Curl_easy *data,
+ X509_STORE *store)
{
struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
struct Curl_multi *multi = data->multi;
!ssl_config->primary.CRLfile &&
!ssl_config->native_ca_store;
- cached_store = get_cached_x509_store(cf, data);
+ cached_store = ossl_get_cached_x509_store(cf, data);
if(cached_store && cache_criteria_met && X509_STORE_up_ref(cached_store)) {
SSL_CTX_set_cert_store(ssl_ctx, cached_store);
}
else {
X509_STORE *store = SSL_CTX_get_cert_store(ssl_ctx);
- result = populate_x509_store(cf, data, store);
+ result = ossl_populate_x509_store(cf, data, store);
if(result == CURLE_OK && cache_criteria_met) {
- set_cached_x509_store(cf, data, store);
+ ossl_set_cached_x509_store(cf, data, store);
}
}
{
X509_STORE *store = SSL_CTX_get_cert_store(ssl_ctx);
- return populate_x509_store(cf, data, store);
+ return ossl_populate_x509_store(cf, data, store);
}
#endif /* HAVE_SSL_X509_STORE_SHARE */
}
}
-#ifdef USE_ECH
+#ifdef USE_ECH_OPENSSL
if(ECH_ENABLED(data)) {
unsigned char *ech_config = NULL;
size_t ech_config_len = 0;
return CURLE_SSL_CONNECT_ERROR;
}
}
-#endif /* USE_ECH */
+#endif /* USE_ECH_OPENSSL */
#endif
return CURLE_OK;
}
-#ifdef USE_ECH
+#ifdef USE_ECH_OPENSSL
/* If we have retry configs, then trace those out */
static void ossl_trace_ech_retry_configs(struct Curl_easy *data, SSL* ssl,
int reason)
ossl_strerror(errdetail, error_buffer, sizeof(error_buffer)));
}
#endif
-#ifdef USE_ECH
+#ifdef USE_ECH_OPENSSL
else if((lib == ERR_LIB_SSL) &&
# if !defined(OPENSSL_IS_BORINGSSL) && !defined(OPENSSL_IS_AWSLC)
(reason == SSL_R_ECH_REQUIRED)) {
negotiated_group_name ? negotiated_group_name : "[blank]",
OBJ_nid2sn(psigtype_nid));
-#ifdef USE_ECH
+#ifdef USE_ECH_OPENSSL
# if !defined(OPENSSL_IS_BORINGSSL) && !defined(OPENSSL_IS_AWSLC)
if(ECH_ENABLED(data)) {
char *inner = NULL, *outer = NULL;
infof(data, "ECH: result: status is not attempted");
}
# endif /* !OPENSSL_IS_BORINGSSL && !OPENSSL_IS_AWSLC */
-#endif /* USE_ECH */
+#endif /* USE_ECH_OPENSSL */
#ifdef HAS_ALPN
/* Sets data and len to negotiated protocol, len is 0 if no protocol was
#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
SSLSUPP_TLS13_CIPHERSUITES |
#endif
-#ifdef USE_ECH
+#ifdef USE_ECH_OPENSSL
SSLSUPP_ECH |
#endif
SSLSUPP_CA_CACHE |
#define SSLSUPP_CA_CACHE (1<<8)
#define SSLSUPP_CIPHER_LIST (1<<9) /* supports TLS 1.0-1.2 ciphersuites */
+#ifdef USE_ECH
+# include "curl_base64.h"
+# define ECH_ENABLED(__data__) \
+ (__data__->set.tls_ech && \
+ !(__data__->set.tls_ech & CURLECH_DISABLE)\
+ )
+#endif /* USE_ECH */
+
#define ALPN_ACCEPTED "ALPN: server accepted "
#define VTLS_INFOF_NO_ALPN \
#include "curl_printf.h"
#include "multiif.h"
-#include <wolfssl/openssl/ssl.h>
#include <wolfssl/ssl.h>
#include <wolfssl/error-ssl.h>
#include "wolfssl.h"
#include "curl_memory.h"
#include "memdebug.h"
-#ifdef USE_ECH
-# include "curl_base64.h"
-# define ECH_ENABLED(__data__) \
- (__data__->set.tls_ech && \
- !(__data__->set.tls_ech & CURLECH_DISABLE)\
- )
-#endif /* USE_ECH */
+#ifdef HAVE_WOLFSSL_CTX_GENERATEECHCONFIG
+#define USE_ECH_WOLFSSL
+#endif
/* KEEP_PEER_CERT is a product of the presence of build time symbol
OPENSSL_EXTRA without NO_CERTS, depending on the version. KEEP_PEER_CERT is
return result;
}
-static CURLcode populate_x509_store(struct Curl_cfilter *cf,
- struct Curl_easy *data,
- WOLFSSL_X509_STORE *store,
- struct wolfssl_ctx *wssl)
+static CURLcode wssl_populate_x509_store(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ WOLFSSL_X509_STORE *store,
+ struct wolfssl_ctx *wssl)
{
struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
const struct curl_blob *ca_info_blob = conn_config->ca_info_blob;
#ifndef NO_FILESYSTEM
/* load trusted cacert from file if not blob */
- CURL_TRC_CF(data, cf, "populate_x509_store, path=%s, blob=%d",
+ CURL_TRC_CF(data, cf, "wssl_populate_x509_store, path=%s, blob=%d",
ssl_cafile ? ssl_cafile : "none", !!ca_info_blob);
if(!store)
return CURLE_OUT_OF_MEMORY;
}
static bool
-cached_x509_store_expired(const struct Curl_easy *data,
- const struct wssl_x509_share *mb)
+wssl_cached_x509_store_expired(const struct Curl_easy *data,
+ const struct wssl_x509_share *mb)
{
const struct ssl_general_config *cfg = &data->set.general_ssl;
struct curltime now = Curl_now();
}
static bool
-cached_x509_store_different(struct Curl_cfilter *cf,
- const struct wssl_x509_share *mb)
+wssl_cached_x509_store_different(struct Curl_cfilter *cf,
+ const struct wssl_x509_share *mb)
{
struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
if(!mb->CAfile || !conn_config->CAfile)
return strcmp(mb->CAfile, conn_config->CAfile);
}
-static WOLFSSL_X509_STORE *get_cached_x509_store(struct Curl_cfilter *cf,
- const struct Curl_easy *data)
+static WOLFSSL_X509_STORE *wssl_get_cached_x509_store(struct Curl_cfilter *cf,
+ const struct Curl_easy *data)
{
struct Curl_multi *multi = data->multi;
struct wssl_x509_share *share;
(void *)MPROTO_WSSL_X509_KEY,
sizeof(MPROTO_WSSL_X509_KEY)-1) : NULL;
if(share && share->store &&
- !cached_x509_store_expired(data, share) &&
- !cached_x509_store_different(cf, share)) {
+ !wssl_cached_x509_store_expired(data, share) &&
+ !wssl_cached_x509_store_different(cf, share)) {
store = share->store;
}
return store;
}
-static void set_cached_x509_store(struct Curl_cfilter *cf,
- const struct Curl_easy *data,
- WOLFSSL_X509_STORE *store)
+static void wssl_set_cached_x509_store(struct Curl_cfilter *cf,
+ const struct Curl_easy *data,
+ WOLFSSL_X509_STORE *store)
{
struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
struct Curl_multi *multi = data->multi;
!ssl_config->primary.CRLfile &&
!ssl_config->native_ca_store;
- cached_store = cache_criteria_met ? get_cached_x509_store(cf, data) : NULL;
+ cached_store = cache_criteria_met ? wssl_get_cached_x509_store(cf, data)
+ : NULL;
if(cached_store && wolfSSL_CTX_get_cert_store(wssl->ctx) == cached_store) {
/* The cached store is already in use, do nothing. */
}
}
wolfSSL_CTX_set_cert_store(wssl->ctx, store);
- result = populate_x509_store(cf, data, store, wssl);
+ result = wssl_populate_x509_store(cf, data, store, wssl);
if(!result) {
- set_cached_x509_store(cf, data, store);
+ wssl_set_cached_x509_store(cf, data, store);
}
}
else {
/* We never share the CTX's store, use it. */
WOLFSSL_X509_STORE *store = wolfSSL_CTX_get_cert_store(wssl->ctx);
- result = populate_x509_store(cf, data, store, wssl);
+ result = wssl_populate_x509_store(cf, data, store, wssl);
}
return result;
wolfSSL_CTX_sess_set_new_cb(backend->ctx, wssl_vtls_new_session_cb);
}
-#ifdef USE_ECH
+#ifdef USE_ECH_WOLFSSL
if(ECH_ENABLED(data)) {
int trying_ech_now = 0;
}
}
- if(trying_ech_now
- && SSL_set_min_proto_version(backend->handle, TLS1_3_VERSION) != 1) {
+ if(trying_ech_now && wolfSSL_set_min_proto_version(backend->handle,
+ TLS1_3_VERSION) != 1) {
infof(data, "ECH: cannot force TLSv1.3 [ERROR]");
return CURLE_SSL_CONNECT_ERROR;
}
}
-#endif /* USE_ECH */
+#endif /* USE_ECH_WOLFSSL */
#ifdef USE_BIO_CHAIN
{
failf(data, "server verification failed: certificate not valid yet.");
return CURLE_PEER_FAILED_VERIFICATION;
}
-#ifdef USE_ECH
+#ifdef USE_ECH_WOLFSSL
else if(-1 == detail) {
/* try access a retry_config ECHConfigList for tracing */
byte echConfigs[1000];
#endif
SSLSUPP_CA_PATH |
SSLSUPP_CAINFO_BLOB |
-#ifdef USE_ECH
+#ifdef USE_ECH_WOLFSSL
SSLSUPP_ECH |
#endif
SSLSUPP_SSL_CTX |