diff options
Diffstat (limited to 'libs/libcurl/src/vtls/wolfssl.c')
| -rw-r--r-- | libs/libcurl/src/vtls/wolfssl.c | 174 |
1 files changed, 140 insertions, 34 deletions
diff --git a/libs/libcurl/src/vtls/wolfssl.c b/libs/libcurl/src/vtls/wolfssl.c index fe845c5752..53e7f0e895 100644 --- a/libs/libcurl/src/vtls/wolfssl.c +++ b/libs/libcurl/src/vtls/wolfssl.c @@ -74,6 +74,14 @@ #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 */
+
/* 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
in wolfSSL's settings.h, and the latter two are build time symbols in
@@ -409,11 +417,11 @@ wolfssl_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data) #if defined(WOLFSSL_ALLOW_TLSV10) && !defined(NO_OLD_TLS)
req_method = TLSv1_client_method();
use_sni(TRUE);
+ break;
#else
failf(data, "wolfSSL does not support TLS 1.0");
return CURLE_NOT_BUILT_IN;
#endif
- break;
case CURL_SSLVERSION_TLSv1_1:
#ifndef NO_OLD_TLS
req_method = TLSv1_1_client_method();
@@ -481,6 +489,7 @@ wolfssl_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data) return CURLE_SSL_CONNECT_ERROR;
}
#endif
+ FALLTHROUGH();
default:
break;
}
@@ -711,7 +720,8 @@ wolfssl_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data) void *ssl_sessionid = NULL;
Curl_ssl_sessionid_lock(data);
- if(!Curl_ssl_getsessionid(cf, data, &ssl_sessionid, NULL)) {
+ if(!Curl_ssl_getsessionid(cf, data, &connssl->peer,
+ &ssl_sessionid, NULL)) {
/* we got a session id, use it! */
if(!SSL_set_session(backend->handle, ssl_sessionid)) {
Curl_ssl_delsessionid(data, ssl_sessionid);
@@ -723,6 +733,82 @@ wolfssl_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data) Curl_ssl_sessionid_unlock(data);
}
+#ifdef USE_ECH
+ if(ECH_ENABLED(data)) {
+ int trying_ech_now = 0;
+
+ if(data->set.str[STRING_ECH_PUBLIC]) {
+ infof(data, "ECH: outername not (yet) supported with WolfSSL");
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+ if(data->set.tls_ech == CURLECH_GREASE) {
+ infof(data, "ECH: GREASE'd ECH not yet supported for wolfSSL");
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+ if(data->set.tls_ech & CURLECH_CLA_CFG
+ && data->set.str[STRING_ECH_CONFIG]) {
+ char *b64val = data->set.str[STRING_ECH_CONFIG];
+ word32 b64len = 0;
+
+ b64len = (word32) strlen(b64val);
+ if(b64len
+ && wolfSSL_SetEchConfigsBase64(backend->handle, b64val, b64len)
+ != WOLFSSL_SUCCESS) {
+ if(data->set.tls_ech & CURLECH_HARD)
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+ else {
+ trying_ech_now = 1;
+ infof(data, "ECH: ECHConfig from command line");
+ }
+ }
+ else {
+ struct Curl_dns_entry *dns = NULL;
+
+ dns = Curl_fetch_addr(data, connssl->peer.hostname, connssl->peer.port);
+ if(!dns) {
+ infof(data, "ECH: requested but no DNS info available");
+ if(data->set.tls_ech & CURLECH_HARD)
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+ else {
+ struct Curl_https_rrinfo *rinfo = NULL;
+
+ rinfo = dns->hinfo;
+ if(rinfo && rinfo->echconfiglist) {
+ unsigned char *ecl = rinfo->echconfiglist;
+ size_t elen = rinfo->echconfiglist_len;
+
+ infof(data, "ECH: ECHConfig from DoH HTTPS RR");
+ if(wolfSSL_SetEchConfigs(backend->handle, ecl, (word32) elen) !=
+ WOLFSSL_SUCCESS) {
+ infof(data, "ECH: wolfSSL_SetEchConfigs failed");
+ if(data->set.tls_ech & CURLECH_HARD)
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+ else {
+ trying_ech_now = 1;
+ infof(data, "ECH: imported ECHConfigList of length %ld", elen);
+ }
+ }
+ else {
+ infof(data, "ECH: requested but no ECHConfig available");
+ if(data->set.tls_ech & CURLECH_HARD)
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+ Curl_resolv_unlock(data, dns);
+ }
+ }
+
+ if(trying_ech_now
+ && SSL_set_min_proto_version(backend->handle, TLS1_3_VERSION) != 1) {
+ infof(data, "ECH: Can't force TLSv1.3 [ERROR]");
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+
+ }
+#endif /* USE_ECH */
+
#ifdef USE_BIO_CHAIN
{
WOLFSSL_BIO *bio;
@@ -756,9 +842,13 @@ wolfssl_connect_step2(struct Curl_cfilter *cf, struct Curl_easy *data) struct wolfssl_ssl_backend_data *backend =
(struct wolfssl_ssl_backend_data *)connssl->backend;
struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
+#ifndef CURL_DISABLE_PROXY
const char * const pinnedpubkey = Curl_ssl_cf_is_proxy(cf)?
data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY]:
data->set.str[STRING_SSL_PINNEDPUBLICKEY];
+#else
+ const char * const pinnedpubkey = data->set.str[STRING_SSL_PINNEDPUBLICKEY];
+#endif
DEBUGASSERT(backend);
@@ -853,6 +943,31 @@ wolfssl_connect_step2(struct Curl_cfilter *cf, struct Curl_easy *data) }
}
#endif
+#ifdef USE_ECH
+ else if(-1 == detail) {
+ /* try access a retry_config ECHConfigList for tracing */
+ byte echConfigs[1000];
+ word32 echConfigsLen = 1000;
+ int rv = 0;
+
+ /* this currently doesn't produce the retry_configs */
+ rv = wolfSSL_GetEchConfigs(backend->handle, echConfigs,
+ &echConfigsLen);
+ if(rv != WOLFSSL_SUCCESS) {
+ infof(data, "Failed to get ECHConfigs");
+ }
+ else {
+ char *b64str = NULL;
+ size_t blen = 0;
+
+ rv = Curl_base64_encode((const char *)echConfigs, echConfigsLen,
+ &b64str, &blen);
+ if(!rv && b64str)
+ infof(data, "ECH: (not yet) retry_configs %s", b64str);
+ free(b64str);
+ }
+ }
+#endif
else if(backend->io_result == CURLE_AGAIN) {
return CURLE_OK;
}
@@ -898,6 +1013,7 @@ wolfssl_connect_step2(struct Curl_cfilter *cf, struct Curl_easy *data) pinnedpubkey,
(const unsigned char *)pubkey->header,
(size_t)(pubkey->end - pubkey->header));
+ wolfSSL_FreeX509(x509);
if(result) {
failf(data, "SSL: public key does not match pinned public key");
return result;
@@ -942,6 +1058,13 @@ wolfssl_connect_step2(struct Curl_cfilter *cf, struct Curl_easy *data) }
+static void wolfssl_session_free(void *sessionid, size_t idsize)
+{
+ (void)idsize;
+ wolfSSL_SESSION_free(sessionid);
+}
+
+
static CURLcode
wolfssl_connect_step3(struct Curl_cfilter *cf, struct Curl_easy *data)
{
@@ -955,40 +1078,27 @@ wolfssl_connect_step3(struct Curl_cfilter *cf, struct Curl_easy *data) DEBUGASSERT(backend);
if(ssl_config->primary.sessionid) {
- bool incache;
- bool added = FALSE;
- void *old_ssl_sessionid = NULL;
/* wolfSSL_get1_session allocates memory that has to be freed. */
WOLFSSL_SESSION *our_ssl_sessionid = wolfSSL_get1_session(backend->handle);
if(our_ssl_sessionid) {
+ void *old_ssl_sessionid = NULL;
+ bool incache;
Curl_ssl_sessionid_lock(data);
- incache = !(Curl_ssl_getsessionid(cf, data, &old_ssl_sessionid, NULL));
+ incache = !(Curl_ssl_getsessionid(cf, data, &connssl->peer,
+ &old_ssl_sessionid, NULL));
if(incache) {
- if(old_ssl_sessionid != our_ssl_sessionid) {
- infof(data, "old SSL session ID is stale, removing");
- Curl_ssl_delsessionid(data, old_ssl_sessionid);
- incache = FALSE;
- }
+ Curl_ssl_delsessionid(data, old_ssl_sessionid);
}
- if(!incache) {
- result = Curl_ssl_addsessionid(cf, data, our_ssl_sessionid, 0, NULL);
- if(result) {
- Curl_ssl_sessionid_unlock(data);
- wolfSSL_SESSION_free(our_ssl_sessionid);
- failf(data, "failed to store ssl session");
- return result;
- }
- else {
- added = TRUE;
- }
- }
+ /* call takes ownership of `our_ssl_sessionid` */
+ result = Curl_ssl_addsessionid(cf, data, &connssl->peer,
+ our_ssl_sessionid, 0,
+ wolfssl_session_free);
Curl_ssl_sessionid_unlock(data);
-
- if(!added) {
- /* If the session info wasn't added to the cache, free our copy. */
- wolfSSL_SESSION_free(our_ssl_sessionid);
+ if(result) {
+ failf(data, "failed to store ssl session");
+ return result;
}
}
}
@@ -1122,12 +1232,6 @@ static ssize_t wolfssl_recv(struct Curl_cfilter *cf, }
-static void wolfssl_session_free(void *ptr)
-{
- wolfSSL_SESSION_free(ptr);
-}
-
-
static size_t wolfssl_version(char *buffer, size_t size)
{
#if LIBWOLFSSL_VERSION_HEX >= 0x03006000
@@ -1386,6 +1490,9 @@ const struct Curl_ssl Curl_ssl_wolfssl = { #endif
SSLSUPP_CA_PATH |
SSLSUPP_CAINFO_BLOB |
+#ifdef USE_ECH
+ SSLSUPP_ECH |
+#endif
SSLSUPP_SSL_CTX,
sizeof(struct wolfssl_ssl_backend_data),
@@ -1404,7 +1511,6 @@ const struct Curl_ssl Curl_ssl_wolfssl = { wolfssl_get_internals, /* get_internals */
wolfssl_close, /* close_one */
Curl_none_close_all, /* close_all */
- wolfssl_session_free, /* session_free */
Curl_none_set_engine, /* set_engine */
Curl_none_set_engine_default, /* set_engine_default */
Curl_none_engines_list, /* engines_list */
|
