From: Viktor Szakats Date: Sat, 16 Nov 2024 20:24:17 +0000 (+0100) Subject: multissl: make openssl + wolfssl builds work X-Git-Tag: curl-8_12_0~326 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=fd067bfb5b028ac41660decc5abb87f1cd093b6b;p=thirdparty%2Fcurl.git multissl: make openssl + wolfssl builds work - 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 --- diff --git a/CMakeLists.txt b/CMakeLists.txt index 997c879898..47b03d60db 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -879,7 +879,8 @@ macro(curl_openssl_check_symbol_exists _symbol _files _variable _extra_libs) 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}") @@ -902,7 +903,8 @@ macro(curl_openssl_check_quic) 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() @@ -933,14 +935,21 @@ option(USE_ECH "Enable ECH support" OFF) 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") diff --git a/lib/curl_config.h.cmake b/lib/curl_config.h.cmake index f0438f8024..8676e7b27b 100644 --- a/lib/curl_config.h.cmake +++ b/lib/curl_config.h.cmake @@ -841,3 +841,12 @@ ${SIZEOF_TIME_T_CODE} /* 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 diff --git a/lib/vtls/openssl.c b/lib/vtls/openssl.c index 1b0e8dd5f0..166dd585d6 100644 --- a/lib/vtls/openssl.c +++ b/lib/vtls/openssl.c @@ -82,16 +82,16 @@ #include #include -#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 # 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 @@ -3133,9 +3133,9 @@ static CURLcode import_windows_cert_store(struct Curl_easy *data, } #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); @@ -3151,7 +3151,7 @@ static CURLcode populate_x509_store(struct Curl_cfilter *cf, 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; @@ -3322,8 +3322,8 @@ static void oss_x509_share_free(void *key, size_t key_len, void *p) } 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) @@ -3338,8 +3338,8 @@ cached_x509_store_expired(const struct Curl_easy *data, } 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) @@ -3348,8 +3348,8 @@ cached_x509_store_different(struct Curl_cfilter *cf, 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; @@ -3360,17 +3360,17 @@ static X509_STORE *get_cached_x509_store(struct Curl_cfilter *cf, (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; @@ -3438,16 +3438,16 @@ CURLcode Curl_ssl_setup_x509_store(struct Curl_cfilter *cf, !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); } } @@ -3460,7 +3460,7 @@ CURLcode Curl_ssl_setup_x509_store(struct Curl_cfilter *cf, { 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 */ @@ -3832,7 +3832,7 @@ CURLcode Curl_ossl_ctx_init(struct ossl_ctx *octx, } } -#ifdef USE_ECH +#ifdef USE_ECH_OPENSSL if(ECH_ENABLED(data)) { unsigned char *ech_config = NULL; size_t ech_config_len = 0; @@ -3959,7 +3959,7 @@ CURLcode Curl_ossl_ctx_init(struct ossl_ctx *octx, return CURLE_SSL_CONNECT_ERROR; } } -#endif /* USE_ECH */ +#endif /* USE_ECH_OPENSSL */ #endif @@ -4055,7 +4055,7 @@ static CURLcode ossl_connect_step1(struct Curl_cfilter *cf, 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) @@ -4230,7 +4230,7 @@ static CURLcode ossl_connect_step2(struct Curl_cfilter *cf, 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)) { @@ -4296,7 +4296,7 @@ static CURLcode ossl_connect_step2(struct Curl_cfilter *cf, 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; @@ -4356,7 +4356,7 @@ static CURLcode ossl_connect_step2(struct Curl_cfilter *cf, 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 @@ -5325,7 +5325,7 @@ const struct Curl_ssl Curl_ssl_openssl = { #ifdef HAVE_SSL_CTX_SET_CIPHERSUITES SSLSUPP_TLS13_CIPHERSUITES | #endif -#ifdef USE_ECH +#ifdef USE_ECH_OPENSSL SSLSUPP_ECH | #endif SSLSUPP_CA_CACHE | diff --git a/lib/vtls/vtls.h b/lib/vtls/vtls.h index 7a223f6fea..8e8ced044f 100644 --- a/lib/vtls/vtls.h +++ b/lib/vtls/vtls.h @@ -41,6 +41,14 @@ struct Curl_ssl_session; #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 \ diff --git a/lib/vtls/wolfssl.c b/lib/vtls/wolfssl.c index 3394cb2748..268eb0cdab 100644 --- a/lib/vtls/wolfssl.c +++ b/lib/vtls/wolfssl.c @@ -69,7 +69,6 @@ #include "curl_printf.h" #include "multiif.h" -#include #include #include #include "wolfssl.h" @@ -78,13 +77,9 @@ #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 @@ -505,10 +500,10 @@ CURLcode wssl_setup_session(struct Curl_cfilter *cf, 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; @@ -556,7 +551,7 @@ static CURLcode populate_x509_store(struct Curl_cfilter *cf, #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; @@ -620,8 +615,8 @@ static void wssl_x509_share_free(void *key, size_t key_len, void *p) } 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(); @@ -635,8 +630,8 @@ cached_x509_store_expired(const struct Curl_easy *data, } 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) @@ -645,8 +640,8 @@ cached_x509_store_different(struct Curl_cfilter *cf, 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; @@ -657,17 +652,17 @@ static WOLFSSL_X509_STORE *get_cached_x509_store(struct Curl_cfilter *cf, (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; @@ -735,7 +730,8 @@ CURLcode Curl_wssl_setup_x509_store(struct Curl_cfilter *cf, !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. */ } @@ -752,15 +748,15 @@ CURLcode Curl_wssl_setup_x509_store(struct Curl_cfilter *cf, } 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; @@ -1198,7 +1194,7 @@ wolfssl_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data) 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; @@ -1265,14 +1261,14 @@ wolfssl_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data) } } - 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 { @@ -1441,7 +1437,7 @@ wolfssl_connect_step2(struct Curl_cfilter *cf, struct Curl_easy *data) 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]; @@ -2020,7 +2016,7 @@ const struct Curl_ssl Curl_ssl_wolfssl = { #endif SSLSUPP_CA_PATH | SSLSUPP_CAINFO_BLOB | -#ifdef USE_ECH +#ifdef USE_ECH_WOLFSSL SSLSUPP_ECH | #endif SSLSUPP_SSL_CTX |