# HAVE_GNUTLS_SRP: `gnutls_srp_verifier` present in GnuTLS
# HAVE_SSL_SET_QUIC_USE_LEGACY_CODEPOINT: `SSL_set_quic_use_legacy_codepoint` present in OpenSSL/wolfSSL
# HAVE_QUICHE_CONN_SET_QLOG_FD: `quiche_conn_set_qlog_fd` present in quiche
-# HAVE_ECH: ECH API checks for OpenSSL, BoringSSL or wolfSSL
+# HAVE_ECH: ECH API checks for OpenSSL, BoringSSL, wolfSSL or rustls-ffi
#
# For each of the above variables, if the variable is DEFINED (either
# to ON or OFF), the symbol detection is skipped. If the variable is
option(USE_HTTPSRR "Enable HTTPS RR support" OFF)
option(USE_ECH "Enable ECH support" OFF)
if(USE_ECH)
- if(USE_OPENSSL OR USE_WOLFSSL)
+ if(USE_OPENSSL OR USE_WOLFSSL OR USE_RUSTLS)
# Be sure that the TLS library actually supports ECH.
if(USE_WOLFSSL)
curl_openssl_check_exists("wolfSSL_CTX_GenerateEchConfig" HAVE_WOLFSSL_CTX_GENERATEECHCONFIG)
curl_openssl_check_exists("SSL_set1_ech_config_list" HAVE_SSL_SET1_ECH_CONFIG_LIST)
endif()
if(HAVE_WOLFSSL_CTX_GENERATEECHCONFIG OR
- HAVE_SSL_SET1_ECH_CONFIG_LIST)
+ HAVE_SSL_SET1_ECH_CONFIG_LIST OR
+ USE_RUSTLS)
set(HAVE_ECH 1)
endif()
if(NOT HAVE_ECH)
- message(FATAL_ERROR "ECH support missing in OpenSSL/BoringSSL/AWS-LC/wolfSSL")
+ message(FATAL_ERROR "ECH support missing in OpenSSL/BoringSSL/AWS-LC/wolfSSL/rustls-ffi")
else()
message(STATUS "ECH enabled")
# ECH wants HTTPSRR
message(STATUS "HTTPSRR enabled")
endif()
else()
- message(FATAL_ERROR "ECH requires ECH-enabled OpenSSL, BoringSSL, AWS-LC or wolfSSL")
+ message(FATAL_ERROR "ECH requires ECH-enabled OpenSSL, BoringSSL, AWS-LC, wolfSSL or rustls-ffi")
endif()
endif()
ECH_ENABLED=0
ECH_ENABLED_OPENSSL=0
ECH_ENABLED_WOLFSSL=0
+ ECH_ENABLED_RUSTLS=0
ECH_SUPPORT=''
dnl check for OpenSSL equivalent
ECH_SUPPORT="$ECH_SUPPORT wolfSSL"
ECH_ENABLED_WOLFSSL=1)
fi
+ if test "x$RUSTLS_ENABLED" = "x1"; then
+ ECH_SUPPORT="$ECH_SUPPORT rustls-ffi"
+ ECH_ENABLED_RUSTLS=1
+ fi
dnl now deal with whatever we found
if test "x$ECH_ENABLED_OPENSSL" = "x1" -o \
- "x$ECH_ENABLED_WOLFSSL" = "x1"; then
+ "x$ECH_ENABLED_WOLFSSL" = "x1" -o \
+ "x$ECH_ENABLED_RUSTLS" = "x1"; then
AC_DEFINE(USE_ECH, 1, [if ECH support is available])
AC_MSG_RESULT(ECH support available via:$ECH_SUPPORT)
experimental="$experimental ECH"
goto cleanup;
}
+#if defined(USE_ECH)
+ if(ECH_ENABLED(data)) {
+ tls_versions[0] = RUSTLS_TLS_VERSION_TLSV1_3;
+ tls_versions_len = 1;
+ infof(data, "rustls: ECH enabled, forcing TLSv1.3");
+ }
+#endif /* USE_ECH */
+
cipher_suites = malloc(sizeof(cipher_suites) * (cipher_suites_len));
if(!cipher_suites) {
result = CURLE_OUT_OF_MEMORY;
return result;
}
+#if defined(USE_ECH)
+static CURLcode
+init_config_builder_ech(struct Curl_easy *data,
+ struct rustls_client_config_builder *builder)
+{
+ const rustls_hpke *hpke = rustls_supported_hpke();
+
+ if(!hpke) {
+ failf(data,
+ "rustls: ECH unavailable, rustls-ffi built without "
+ "HPKE compatible crypto provider");
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+
+ if(data->set.str[STRING_ECH_PUBLIC]) {
+ failf(data, "rustls: ECH outername not supported");
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+
+ if(data->set.tls_ech == CURLECH_GREASE) {
+ rustls_result rr;
+ rr = rustls_client_config_builder_enable_ech_grease(builder, hpke);
+ if(rr != RUSTLS_RESULT_OK) {
+ rustls_failf(data, rr, "rustls: failed to configure ECH GREASE");
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+ }
+
+ return CURLE_OK;
+}
+#endif /* USE_ECH */
+
static CURLcode
cr_init_backend(struct Curl_cfilter *cf, struct Curl_easy *data,
struct rustls_ssl_backend_data *const backend)
}
}
+#if defined(USE_ECH)
+ if(ECH_ENABLED(data)) {
+ result = init_config_builder_ech(data, config_builder);
+ if(result != CURLE_OK && data->set.tls_ech & CURLECH_HARD) {
+ rustls_client_config_builder_free(config_builder);
+ return result;
+ }
+ }
+#endif /* USE_ECH */
+
result = init_config_builder_keylog(data, config_builder);
if(result != CURLE_OK) {
rustls_client_config_builder_free(config_builder);
SSLSUPP_HTTPS_PROXY |
SSLSUPP_CIPHER_LIST |
SSLSUPP_TLS13_CIPHERSUITES |
- SSLSUPP_CERTINFO,
+ SSLSUPP_CERTINFO |
+ SSLSUPP_ECH,
sizeof(struct rustls_ssl_backend_data),
NULL, /* init */