]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
ECH: enable support for the AWS-LC backend
authorViktor Szakats <commit@vsz.me>
Wed, 6 Nov 2024 15:37:07 +0000 (16:37 +0100)
committerViktor Szakats <commit@vsz.me>
Fri, 8 Nov 2024 12:59:39 +0000 (13:59 +0100)
Extend existing ECH support for BoringSSL to its AWS-LC fork.

Also enable ECH in AWS-LC CI jobs.

```
curl 8.11.0-DEV (x86_64-pc-linux-gnu) libcurl/8.11.0-DEV AWS-LC/1.37.0 zlib/1.3 brotli/1.1.0 zstd/1.5.5 libpsl/0.21.2
Release-Date: [unreleased]
Protocols: dict file ftp ftps gopher gophers http https imap imaps ipfs ipns mqtt pop3 pop3s rtsp smb smbs smtp smtps telnet tftp ws wss
Features: alt-svc AsynchDNS brotli ECH HSTS HTTPS-proxy IPv6 Largefile libz NTLM PSL SSL threadsafe UnixSockets zstd
```

Closes #15499

.github/workflows/linux.yml
CMakeLists.txt
docs/ECH.md
lib/vtls/openssl.c

index d00b731ebed97367315c6071e1e1c352b7d4e08d..9d3e589d02b0c6ed5a4c065d83d7d11ad0b83b72 100644 (file)
@@ -140,12 +140,12 @@ jobs:
           - name: awslc
             install_packages: zlib1g-dev
             install_steps: awslc
-            configure: LDFLAGS="-Wl,-rpath,$HOME/awslc/lib" --with-openssl=$HOME/awslc
+            configure: LDFLAGS="-Wl,-rpath,$HOME/awslc/lib" --with-openssl=$HOME/awslc --enable-httpsrr --enable-ech
 
           - name: awslc
             install_packages: zlib1g-dev
             install_steps: awslc
-            generate: -DOPENSSL_ROOT_DIR=$HOME/awslc -DCMAKE_UNITY_BUILD=OFF
+            generate: -DOPENSSL_ROOT_DIR=$HOME/awslc -DUSE_HTTPSRR=ON -DUSE_ECH=ON -DCMAKE_UNITY_BUILD=OFF
 
           - name: openssl default
             install_steps: pytest
index be1a2b292a4975502dc59067907bd27dd59e8719..4dbd2df2ad57512056841cfdbec3fda19f4c01fa 100644 (file)
@@ -834,7 +834,7 @@ 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)
+      if(USE_OPENSSL AND (HAVE_BORINGSSL OR HAVE_AWSLC))
         openssl_check_symbol_exists("SSL_set1_ech_config_list" "openssl/ssl.h" HAVE_ECH "")
       elseif(USE_OPENSSL)
         openssl_check_symbol_exists("SSL_ech_set1_echconfig" "openssl/ech.h" HAVE_ECH "")
@@ -843,12 +843,12 @@ if(USE_ECH)
       endif()
     endif()
     if(NOT HAVE_ECH)
-      message(FATAL_ERROR "ECH support missing in OpenSSL/BoringSSL/wolfSSL")
+      message(FATAL_ERROR "ECH support missing in OpenSSL/BoringSSL/AWS-LC/wolfSSL")
     else()
       message(STATUS "ECH enabled.")
     endif()
   else()
-    message(FATAL_ERROR "ECH requires ECH-enablded OpenSSL, BoringSSL or wolfSSL")
+    message(FATAL_ERROR "ECH requires ECH-enablded OpenSSL, BoringSSL, AWS-LC or wolfSSL")
   endif()
 endif()
 
index 572292dbc048592015032908a4deaed15475983f..cf15314bd84be830005d6592b1e5a1ef01317b55 100644 (file)
@@ -8,8 +8,8 @@ SPDX-License-Identifier: curl
 
 We have added support for ECH to curl. It can use HTTPS RRs published in the
 DNS if curl uses DoH, or else can accept the relevant ECHConfigList values
-from the command line. This works with OpenSSL, wolfSSL or BoringSSL as the
-TLS provider.
+from the command line. This works with OpenSSL, wolfSSL, BoringSSL or AWS-LC as
+the TLS provider.
 
 This feature is EXPERIMENTAL. DO NOT USE IN PRODUCTION.
 
@@ -149,7 +149,7 @@ the verbose output, e.g.:
 ```
 
 At that point, you could copy the base64 encoded value above and try again.
-For now, this only works for the OpenSSL and BoringSSL builds.
+For now, this only works for the OpenSSL and BoringSSL/AWS-LC builds.
 
 ## Default settings
 
@@ -334,12 +334,12 @@ Then:
     make
 ```
 
-The BoringSSL APIs are fairly similar to those in our ECH-enabled OpenSSL
-fork, so code changes are also in ``lib/vtls/openssl.c``, protected
+The BoringSSL/AWS-LC APIs are fairly similar to those in our ECH-enabled
+OpenSSL fork, so code changes are also in ``lib/vtls/openssl.c``, protected
 via ``#ifdef OPENSSL_IS_BORINGSSL`` and are mostly obvious API variations.
 
-The BoringSSL APIs however do not support the ``--ech pn:`` command line
-variant as of now.
+The BoringSSL/AWS-LC APIs however do not support the ``--ech pn:`` command
+line variant as of now.
 
 ## wolfSSL build
 
@@ -401,7 +401,7 @@ Then there are some functional code changes:
 The lack of support for ``--ech false`` is because wolfSSL has decided to
 always at least GREASE if built to support ECH. In other words, GREASE is
 a compile time choice for wolfSSL, but a runtime choice for OpenSSL or
-BoringSSL. (Both are reasonable.)
+BoringSSL/AWS-LC. (Both are reasonable.)
 
 ## Additional notes
 
@@ -474,5 +474,5 @@ to get the HTTPS RR and pass the ECHConfigList from that on the command line,
 if needed, or one can access the value from command line output in verbose more
 and then reuse that in another invocation.
 
-Both our OpenSSL fork and BoringSSL have APIs for both controlling GREASE and
-accessing and logging ``retry_configs``, it seems wolfSSL has neither.
+Both our OpenSSL fork and BoringSSL/AWS-LC have APIs for both controlling GREASE
+and accessing and logging ``retry_configs``, it seems wolfSSL has neither.
index f94e941b11b00ec8ab35d4075ca749976e36d26f..0643ba046efa368cb5a2d14e028ca85876796619 100644 (file)
@@ -83,7 +83,7 @@
 #include <openssl/evp.h>
 
 #ifdef USE_ECH
-# ifndef OPENSSL_IS_BORINGSSL
+# if !defined(OPENSSL_IS_BORINGSSL) && !defined(OPENSSL_IS_AWSLC)
 #  include <openssl/ech.h>
 # endif
 # include "curl_base64.h"
@@ -3849,15 +3849,15 @@ CURLcode Curl_ossl_ctx_init(struct ossl_ctx *octx,
 
     if(data->set.tls_ech & CURLECH_GREASE) {
       infof(data, "ECH: will GREASE ClientHello");
-# ifdef OPENSSL_IS_BORINGSSL
+# if defined(OPENSSL_IS_BORINGSSL) || defined(OPENSSL_IS_AWSLC)
       SSL_set_enable_ech_grease(octx->ssl, 1);
 # else
       SSL_set_options(octx->ssl, SSL_OP_ECH_GREASE);
 # endif
     }
     else if(data->set.tls_ech & CURLECH_CLA_CFG) {
-# ifdef OPENSSL_IS_BORINGSSL
-      /* have to do base64 decode here for boring */
+# if defined(OPENSSL_IS_BORINGSSL) || defined(OPENSSL_IS_AWSLC)
+      /* have to do base64 decode here for BoringSSL */
       const char *b64 = data->set.str[STRING_ECH_CONFIG];
 
       if(!b64) {
@@ -3917,7 +3917,7 @@ CURLcode Curl_ossl_ctx_init(struct ossl_ctx *octx,
           size_t elen = rinfo->echconfiglist_len;
 
           infof(data, "ECH: ECHConfig from DoH HTTPS RR");
-# ifndef OPENSSL_IS_BORINGSSL
+# if !defined(OPENSSL_IS_BORINGSSL) && !defined(OPENSSL_IS_AWSLC)
           if(SSL_ech_set1_echconfig(octx->ssl, ecl, elen) != 1) {
             infof(data, "ECH: SSL_ECH_set1_echconfig failed");
             if(data->set.tls_ech & CURLECH_HARD)
@@ -3925,7 +3925,7 @@ CURLcode Curl_ossl_ctx_init(struct ossl_ctx *octx,
           }
 # else
           if(SSL_set1_ech_config_list(octx->ssl, ecl, elen) != 1) {
-            infof(data, "ECH: SSL_set1_ech_config_list failed (boring)");
+            infof(data, "ECH: SSL_set1_ech_config_list failed (BoringSSL)");
             if(data->set.tls_ech & CURLECH_HARD)
               return CURLE_SSL_CONNECT_ERROR;
           }
@@ -3943,7 +3943,7 @@ CURLcode Curl_ossl_ctx_init(struct ossl_ctx *octx,
         Curl_resolv_unlink(data, &dns);
       }
     }
-# ifdef OPENSSL_IS_BORINGSSL
+# if defined(OPENSSL_IS_BORINGSSL) || defined(OPENSSL_IS_AWSLC)
     if(trying_ech_now && outername) {
       infof(data, "ECH: setting public_name not supported with BoringSSL");
       return CURLE_SSL_CONNECT_ERROR;
@@ -3960,7 +3960,7 @@ CURLcode Curl_ossl_ctx_init(struct ossl_ctx *octx,
         return CURLE_SSL_CONNECT_ERROR;
       }
     }
-# endif  /* not BORING */
+# endif  /* OPENSSL_IS_BORINGSSL || OPENSSL_IS_AWSLC */
     if(trying_ech_now
        && SSL_set_min_proto_version(octx->ssl, TLS1_3_VERSION) != 1) {
       infof(data, "ECH: cannot force TLSv1.3 [ERROR]");
@@ -4071,7 +4071,7 @@ static void ossl_trace_ech_retry_configs(struct Curl_easy *data, SSL* ssl,
   CURLcode result = CURLE_OK;
   size_t rcl = 0;
   int rv = 1;
-# ifndef OPENSSL_IS_BORINGSSL
+# if !defined(OPENSSL_IS_BORINGSSL) && !defined(OPENSSL_IS_AWSLC)
   char *inner = NULL;
   unsigned char *rcs = NULL;
   char *outer = NULL;
@@ -4086,7 +4086,7 @@ static void ossl_trace_ech_retry_configs(struct Curl_easy *data, SSL* ssl,
   /* nothing to trace if not doing ECH */
   if(!ECH_ENABLED(data))
     return;
-# ifndef OPENSSL_IS_BORINGSSL
+# if !defined(OPENSSL_IS_BORINGSSL) && !defined(OPENSSL_IS_AWSLC)
   rv = SSL_ech_get_retry_config(ssl, &rcs, &rcl);
 # else
   SSL_get0_ech_retry_configs(ssl, &rcs, &rcl);
@@ -4103,23 +4103,23 @@ static void ossl_trace_ech_retry_configs(struct Curl_easy *data, SSL* ssl,
     if(!result && b64str)
       infof(data, "ECH: retry_configs %s", b64str);
     free(b64str);
-# ifndef OPENSSL_IS_BORINGSSL
+# if !defined(OPENSSL_IS_BORINGSSL) && !defined(OPENSSL_IS_AWSLC)
     rv = SSL_ech_get_status(ssl, &inner, &outer);
     infof(data, "ECH: retry_configs for %s from %s, %d %d",
           inner ? inner : "NULL", outer ? outer : "NULL", reason, rv);
-#else
+# else
     rv = SSL_ech_accepted(ssl);
     servername_type = SSL_get_servername_type(ssl);
     inner = SSL_get_servername(ssl, servername_type);
     SSL_get0_ech_name_override(ssl, &outer, &out_name_len);
-    /* TODO: get the inner from boring */
+    /* TODO: get the inner from BoringSSL */
     infof(data, "ECH: retry_configs for %s from %s, %d %d",
           inner ? inner : "NULL", outer ? outer : "NULL", reason, rv);
-#endif
+# endif
   }
   else
     infof(data, "ECH: no retry_configs (rv = %d)", rv);
-# ifndef OPENSSL_IS_BORINGSSL
+# if !defined(OPENSSL_IS_BORINGSSL) && !defined(OPENSSL_IS_AWSLC)
   OPENSSL_free((void *)rcs);
 # endif
   return;
@@ -4243,7 +4243,7 @@ static CURLcode ossl_connect_step2(struct Curl_cfilter *cf,
 #endif
 #ifdef USE_ECH
       else if((lib == ERR_LIB_SSL) &&
-# ifndef OPENSSL_IS_BORINGSSL
+# if !defined(OPENSSL_IS_BORINGSSL) && !defined(OPENSSL_IS_AWSLC)
               (reason == SSL_R_ECH_REQUIRED)) {
 # else
               (reason == SSL_R_ECH_REJECTED)) {
@@ -4309,7 +4309,7 @@ static CURLcode ossl_connect_step2(struct Curl_cfilter *cf,
           OBJ_nid2sn(psigtype_nid));
 
 #ifdef USE_ECH
-# ifndef OPENSSL_IS_BORINGSSL
+# if !defined(OPENSSL_IS_BORINGSSL) && !defined(OPENSSL_IS_AWSLC)
     if(ECH_ENABLED(data)) {
       char *inner = NULL, *outer = NULL;
       const char *status = NULL;
@@ -4367,7 +4367,7 @@ static CURLcode ossl_connect_step2(struct Curl_cfilter *cf,
    else {
       infof(data, "ECH: result: status is not attempted");
    }
-# endif  /* BORING */
+# endif  /* !OPENSSL_IS_BORINGSSL && !OPENSSL_IS_AWSLC */
 #endif  /* USE_ECH */
 
 #ifdef HAS_ALPN