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.
```
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
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
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
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.
#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"
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) {
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)
}
# 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;
}
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;
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]");
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;
/* 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);
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;
#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)) {
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;
else {
infof(data, "ECH: result: status is not attempted");
}
-# endif /* BORING */
+# endif /* !OPENSSL_IS_BORINGSSL && !OPENSSL_IS_AWSLC */
#endif /* USE_ECH */
#ifdef HAS_ALPN