]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
multissl: make openssl + wolfssl builds work
authorViktor Szakats <commit@vsz.me>
Sat, 16 Nov 2024 20:24:17 +0000 (21:24 +0100)
committerViktor Szakats <commit@vsz.me>
Tue, 17 Dec 2024 11:34:34 +0000 (12:34 +0100)
- 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

CMakeLists.txt
lib/curl_config.h.cmake
lib/vtls/openssl.c
lib/vtls/vtls.h
lib/vtls/wolfssl.c

index 997c879898a39706930124115b070d500311d30d..47b03d60db2b34248d65dda9b4319289746aa17a 100644 (file)
@@ -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")
index f0438f8024446c8b1c081f4b21055e135b9e1e6e..8676e7b27bb0739415ca6a31855c74c0d41d1b99 100644 (file)
@@ -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
index 1b0e8dd5f0e867001868d49468673b82c7ef2697..166dd585d6889e969f99e4492b78ee180ebeec5b 100644 (file)
 #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>
@@ -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 |
index 7a223f6fead32cdacf84c940fe48ef47695e75a1..8e8ced044f79d6c87eebab78fa59fbaad8b13428 100644 (file)
@@ -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            \
index 3394cb2748c51341e33fdfd604529078cc4ba3fc..268eb0cdab5321c4b1bd03fc8af71e0a671a68b4 100644 (file)
@@ -69,7 +69,6 @@
 #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
@@ -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 |