about summary refs log tree commit diff
path: root/pkgs/tools/networking/curl
diff options
context:
space:
mode:
authorRobert Scott <code@humanleg.org.uk>2021-05-30 18:12:53 +0100
committerRobert Scott <code@humanleg.org.uk>2021-05-30 18:19:19 +0100
commit742c60f6f839e23822d29b668071baa653253656 (patch)
tree3348a4fdb88759deb2f02b09dd5b66ffc9944438 /pkgs/tools/networking/curl
parent1d817f8f5d4f8b5cf285ccc9f943e7d4b8be045d (diff)
curl: add patches for CVE-2021-22897, CVE-2021-22898 & CVE-2021-22901
Diffstat (limited to 'pkgs/tools/networking/curl')
-rw-r--r--pkgs/tools/networking/curl/CVE-2021-22897.patch64
-rw-r--r--pkgs/tools/networking/curl/CVE-2021-22898.patch25
-rw-r--r--pkgs/tools/networking/curl/CVE-2021-22901.patch437
-rw-r--r--pkgs/tools/networking/curl/default.nix6
4 files changed, 532 insertions, 0 deletions
diff --git a/pkgs/tools/networking/curl/CVE-2021-22897.patch b/pkgs/tools/networking/curl/CVE-2021-22897.patch
new file mode 100644
index 0000000000000..a488887950369
--- /dev/null
+++ b/pkgs/tools/networking/curl/CVE-2021-22897.patch
@@ -0,0 +1,64 @@
+From bbb71507b7bab52002f9b1e0880bed6a32834511 Mon Sep 17 00:00:00 2001
+From: Daniel Stenberg <daniel@haxx.se>
+Date: Fri, 23 Apr 2021 10:54:10 +0200
+Subject: [PATCH] schannel: don't use static to store selected ciphers
+
+CVE-2021-22897
+
+Bug: https://curl.se/docs/CVE-2021-22897.html
+---
+ lib/vtls/schannel.c | 9 +++++----
+ lib/vtls/schannel.h | 3 +++
+ 2 files changed, 8 insertions(+), 4 deletions(-)
+
+diff --git a/lib/vtls/schannel.c b/lib/vtls/schannel.c
+index 8c25ac5dd5a5..dba7072273a9 100644
+--- a/lib/vtls/schannel.c
++++ b/lib/vtls/schannel.c
+@@ -328,12 +328,12 @@ get_alg_id_by_name(char *name)
+ }
+ 
+ static CURLcode
+-set_ssl_ciphers(SCHANNEL_CRED *schannel_cred, char *ciphers)
++set_ssl_ciphers(SCHANNEL_CRED *schannel_cred, char *ciphers,
++                int *algIds)
+ {
+   char *startCur = ciphers;
+   int algCount = 0;
+-  static ALG_ID algIds[45]; /*There are 45 listed in the MS headers*/
+-  while(startCur && (0 != *startCur) && (algCount < 45)) {
++  while(startCur && (0 != *startCur) && (algCount < NUMOF_CIPHERS)) {
+     long alg = strtol(startCur, 0, 0);
+     if(!alg)
+       alg = get_alg_id_by_name(startCur);
+@@ -593,7 +593,8 @@ schannel_connect_step1(struct Curl_easy *data, struct connectdata *conn,
+     }
+ 
+     if(SSL_CONN_CONFIG(cipher_list)) {
+-      result = set_ssl_ciphers(&schannel_cred, SSL_CONN_CONFIG(cipher_list));
++      result = set_ssl_ciphers(&schannel_cred, SSL_CONN_CONFIG(cipher_list),
++                               BACKEND->algIds);
+       if(CURLE_OK != result) {
+         failf(data, "Unable to set ciphers to passed via SSL_CONN_CONFIG");
+         return result;
+diff --git a/lib/vtls/schannel.h b/lib/vtls/schannel.h
+index 2952caa1a5a1..77853aa30f96 100644
+--- a/lib/vtls/schannel.h
++++ b/lib/vtls/schannel.h
+@@ -71,6 +71,8 @@ CURLcode Curl_verify_certificate(struct Curl_easy *data,
+ #endif
+ #endif
+ 
++#define NUMOF_CIPHERS 45 /* There are 45 listed in the MS headers */
++
+ struct Curl_schannel_cred {
+   CredHandle cred_handle;
+   TimeStamp time_stamp;
+@@ -102,6 +104,7 @@ struct ssl_backend_data {
+ #ifdef HAS_MANUAL_VERIFY_API
+   bool use_manual_cred_validation; /* true if manual cred validation is used */
+ #endif
++  ALG_ID algIds[NUMOF_CIPHERS];
+ };
+ #endif /* EXPOSE_SCHANNEL_INTERNAL_STRUCTS */
+ 
diff --git a/pkgs/tools/networking/curl/CVE-2021-22898.patch b/pkgs/tools/networking/curl/CVE-2021-22898.patch
new file mode 100644
index 0000000000000..ea4d2cb37e87d
--- /dev/null
+++ b/pkgs/tools/networking/curl/CVE-2021-22898.patch
@@ -0,0 +1,25 @@
+From 39ce47f219b09c380b81f89fe54ac586c8db6bde Mon Sep 17 00:00:00 2001
+From: Harry Sintonen <sintonen@iki.fi>
+Date: Fri, 7 May 2021 13:09:57 +0200
+Subject: [PATCH] telnet: check sscanf() for correct number of matches
+
+CVE-2021-22898
+
+Bug: https://curl.se/docs/CVE-2021-22898.html
+---
+ lib/telnet.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/lib/telnet.c b/lib/telnet.c
+index 26e0658ba9cc..fdd137fb0c04 100644
+--- a/lib/telnet.c
++++ b/lib/telnet.c
+@@ -922,7 +922,7 @@ static void suboption(struct Curl_easy *data)
+         size_t tmplen = (strlen(v->data) + 1);
+         /* Add the variable only if it fits */
+         if(len + tmplen < (int)sizeof(temp)-6) {
+-          if(sscanf(v->data, "%127[^,],%127s", varname, varval)) {
++          if(sscanf(v->data, "%127[^,],%127s", varname, varval) == 2) {
+             msnprintf((char *)&temp[len], sizeof(temp) - len,
+                       "%c%s%c%s", CURL_NEW_ENV_VAR, varname,
+                       CURL_NEW_ENV_VALUE, varval);
diff --git a/pkgs/tools/networking/curl/CVE-2021-22901.patch b/pkgs/tools/networking/curl/CVE-2021-22901.patch
new file mode 100644
index 0000000000000..6bd70aa41b1ec
--- /dev/null
+++ b/pkgs/tools/networking/curl/CVE-2021-22901.patch
@@ -0,0 +1,437 @@
+Based on upstream 7f4a9a9b2a49547eae24d2e19bc5c346e9026479, modified by ris to
+apply without 0c55fbab45bedb761766109d41c3da49c4bc66c6
+
+diff --git a/lib/multi.c b/lib/multi.c
+index 54365f399e9b..1b3e261c682a 100644
+--- a/lib/multi.c
++++ b/lib/multi.c
+@@ -878,8 +878,10 @@ bool Curl_multiplex_wanted(const struct Curl_multi *multi)
+ void Curl_detach_connnection(struct Curl_easy *data)
+ {
+   struct connectdata *conn = data->conn;
+-  if(conn)
++  if(conn) {
+     Curl_llist_remove(&conn->easyq, &data->conn_queue, NULL);
++    Curl_ssl_detach_conn(data, conn);
++  }
+   data->conn = NULL;
+ }
+ 
+@@ -896,6 +898,7 @@ void Curl_attach_connnection(struct Curl_easy *data,
+   data->conn = conn;
+   Curl_llist_insert_next(&conn->easyq, conn->easyq.tail, data,
+                          &data->conn_queue);
++  Curl_ssl_associate_conn(data, conn);
+ }
+ 
+ static int waitconnect_getsock(struct connectdata *conn,
+diff --git a/lib/vtls/gskit.c b/lib/vtls/gskit.c
+index c648f624579b..ca953769d1ba 100644
+--- a/lib/vtls/gskit.c
++++ b/lib/vtls/gskit.c
+@@ -1304,7 +1304,9 @@ const struct Curl_ssl Curl_ssl_gskit = {
+   Curl_none_set_engine_default,   /* set_engine_default */
+   Curl_none_engines_list,         /* engines_list */
+   Curl_none_false_start,          /* false_start */
+-  NULL                            /* sha256sum */
++  NULL,                           /* sha256sum */
++  NULL,                           /* associate_connection */
++  NULL                            /* disassociate_connection */
+ };
+ 
+ #endif /* USE_GSKIT */
+diff --git a/lib/vtls/gtls.c b/lib/vtls/gtls.c
+index a10c0dbcca05..ecde5c44deeb 100644
+--- a/lib/vtls/gtls.c
++++ b/lib/vtls/gtls.c
+@@ -1656,7 +1656,9 @@ const struct Curl_ssl Curl_ssl_gnutls = {
+   Curl_none_set_engine_default,  /* set_engine_default */
+   Curl_none_engines_list,        /* engines_list */
+   Curl_none_false_start,         /* false_start */
+-  gtls_sha256sum                 /* sha256sum */
++  gtls_sha256sum,                /* sha256sum */
++  NULL,                          /* associate_connection */
++  NULL                           /* disassociate_connection */
+ };
+ 
+ #endif /* USE_GNUTLS */
+diff --git a/lib/vtls/mbedtls.c b/lib/vtls/mbedtls.c
+index ca77de58667c..3a0be0f04b4f 100644
+--- a/lib/vtls/mbedtls.c
++++ b/lib/vtls/mbedtls.c
+@@ -1093,7 +1093,9 @@ const struct Curl_ssl Curl_ssl_mbedtls = {
+   Curl_none_set_engine_default,     /* set_engine_default */
+   Curl_none_engines_list,           /* engines_list */
+   Curl_none_false_start,            /* false_start */
+-  mbedtls_sha256sum                 /* sha256sum */
++  mbedtls_sha256sum,                /* sha256sum */
++  NULL,                             /* associate_connection */
++  NULL                              /* disassociate_connection */
+ };
+ 
+ #endif /* USE_MBEDTLS */
+diff --git a/lib/vtls/mesalink.c b/lib/vtls/mesalink.c
+index f16c77c27fe0..bf8600d3230b 100644
+--- a/lib/vtls/mesalink.c
++++ b/lib/vtls/mesalink.c
+@@ -666,7 +666,9 @@ const struct Curl_ssl Curl_ssl_mesalink = {
+   Curl_none_set_engine_default,  /* set_engine_default */
+   Curl_none_engines_list,        /* engines_list */
+   Curl_none_false_start,         /* false_start */
+-  NULL                           /* sha256sum */
++  NULL,                          /* sha256sum */
++  NULL,                          /* associate_connection */
++  NULL                           /* disassociate_connection */
+ };
+ 
+ #endif
+diff --git a/lib/vtls/nss.c b/lib/vtls/nss.c
+index 2aa4bdaa134f..1582b1e580a9 100644
+--- a/lib/vtls/nss.c
++++ b/lib/vtls/nss.c
+@@ -2465,7 +2465,9 @@ const struct Curl_ssl Curl_ssl_nss = {
+   Curl_none_set_engine_default, /* set_engine_default */
+   Curl_none_engines_list,       /* engines_list */
+   nss_false_start,              /* false_start */
+-  nss_sha256sum                 /* sha256sum */
++  nss_sha256sum,                /* sha256sum */
++  NULL,                         /* associate_connection */
++  NULL                          /* disassociate_connection */
+ };
+ 
+ #endif /* USE_NSS */
+diff --git a/lib/vtls/openssl.c b/lib/vtls/openssl.c
+index 1521600dd5f6..ebd7abc3b4ac 100644
+--- a/lib/vtls/openssl.c
++++ b/lib/vtls/openssl.c
+@@ -240,6 +240,10 @@ struct ssl_backend_data {
+ #endif
+ };
+ 
++static void ossl_associate_connection(struct Curl_easy *data,
++                                      struct connectdata *conn,
++                                      int sockindex);
++
+ /*
+  * Number of bytes to read from the random number seed file. This must be
+  * a finite value (because some entropy "files" like /dev/urandom have
+@@ -2581,6 +2585,7 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data,
+   curl_socket_t sockfd = conn->sock[sockindex];
+   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+   ctx_option_t ctx_options = 0;
++  void *ssl_sessionid = NULL;
+ 
+ #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
+   bool sni;
+@@ -3225,46 +3230,23 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data,
+   }
+ #endif
+ 
+-  /* Check if there's a cached ID we can/should use here! */
+-  if(SSL_SET_OPTION(primary.sessionid)) {
+-    void *ssl_sessionid = NULL;
+-    int data_idx = ossl_get_ssl_data_index();
+-    int connectdata_idx = ossl_get_ssl_conn_index();
+-    int sockindex_idx = ossl_get_ssl_sockindex_index();
+-    int proxy_idx = ossl_get_proxy_index();
+-
+-    if(data_idx >= 0 && connectdata_idx >= 0 && sockindex_idx >= 0 &&
+-       proxy_idx >= 0) {
+-      /* Store the data needed for the "new session" callback.
+-       * The sockindex is stored as a pointer to an array element. */
+-      SSL_set_ex_data(backend->handle, data_idx, data);
+-      SSL_set_ex_data(backend->handle, connectdata_idx, conn);
+-      SSL_set_ex_data(backend->handle, sockindex_idx, conn->sock + sockindex);
+-#ifndef CURL_DISABLE_PROXY
+-      SSL_set_ex_data(backend->handle, proxy_idx, SSL_IS_PROXY() ? (void *) 1:
+-                      NULL);
+-#else
+-      SSL_set_ex_data(backend->handle, proxy_idx, NULL);
+-#endif
+-
+-    }
++  ossl_associate_connection(data, conn, sockindex);
+ 
+-    Curl_ssl_sessionid_lock(data);
+-    if(!Curl_ssl_getsessionid(data, conn, SSL_IS_PROXY() ? TRUE : FALSE,
+-                              &ssl_sessionid, NULL, sockindex)) {
+-      /* we got a session id, use it! */
+-      if(!SSL_set_session(backend->handle, ssl_sessionid)) {
+-        Curl_ssl_sessionid_unlock(data);
+-        failf(data, "SSL: SSL_set_session failed: %s",
+-              ossl_strerror(ERR_get_error(), error_buffer,
+-                            sizeof(error_buffer)));
+-        return CURLE_SSL_CONNECT_ERROR;
+-      }
+-      /* Informational message */
+-      infof(data, "SSL re-using session ID\n");
++  Curl_ssl_sessionid_lock(data);
++  if(!Curl_ssl_getsessionid(data, conn, SSL_IS_PROXY() ? TRUE : FALSE,
++                            &ssl_sessionid, NULL, sockindex)) {
++    /* we got a session id, use it! */
++    if(!SSL_set_session(backend->handle, ssl_sessionid)) {
++      Curl_ssl_sessionid_unlock(data);
++      failf(data, "SSL: SSL_set_session failed: %s",
++            ossl_strerror(ERR_get_error(), error_buffer,
++                          sizeof(error_buffer)));
++      return CURLE_SSL_CONNECT_ERROR;
+     }
+-    Curl_ssl_sessionid_unlock(data);
++    /* Informational message */
++    infof(data, "SSL re-using session ID\n");
+   }
++  Curl_ssl_sessionid_unlock(data);
+ 
+ #ifndef CURL_DISABLE_PROXY
+   if(conn->proxy_ssl[sockindex].use) {
+@@ -4498,6 +4480,90 @@ static void *ossl_get_internals(struct ssl_connect_data *connssl,
+          (void *)backend->ctx : (void *)backend->handle;
+ }
+ 
++static void ossl_associate_connection(struct Curl_easy *data,
++                                      struct connectdata *conn,
++                                      int sockindex)
++{
++  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
++  struct ssl_backend_data *backend = connssl->backend;
++
++  /* If we don't have SSL context, do nothing. */
++  if(!backend->handle)
++    return;
++
++  if(SSL_SET_OPTION(primary.sessionid)) {
++    int data_idx = ossl_get_ssl_data_index();
++    int connectdata_idx = ossl_get_ssl_conn_index();
++    int sockindex_idx = ossl_get_ssl_sockindex_index();
++    int proxy_idx = ossl_get_proxy_index();
++
++    if(data_idx >= 0 && connectdata_idx >= 0 && sockindex_idx >= 0 &&
++       proxy_idx >= 0) {
++      /* Store the data needed for the "new session" callback.
++       * The sockindex is stored as a pointer to an array element. */
++      SSL_set_ex_data(backend->handle, data_idx, data);
++      SSL_set_ex_data(backend->handle, connectdata_idx, conn);
++      SSL_set_ex_data(backend->handle, sockindex_idx, conn->sock + sockindex);
++#ifndef CURL_DISABLE_PROXY
++      SSL_set_ex_data(backend->handle, proxy_idx, SSL_IS_PROXY() ? (void *) 1:
++                      NULL);
++#else
++      SSL_set_ex_data(backend->handle, proxy_idx, NULL);
++#endif
++    }
++  }
++}
++
++/*
++ * Starting with TLS 1.3, the ossl_new_session_cb callback gets called after
++ * the handshake. If the transfer that sets up the callback gets killed before
++ * this callback arrives, we must make sure to properly clear the data to
++ * avoid UAF problems. A future optimization could be to instead store another
++ * transfer that might still be using the same connection.
++ */
++
++static void ossl_disassociate_connection(struct Curl_easy *data,
++                                         int sockindex)
++{
++  struct connectdata *conn = data->conn;
++  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
++  struct ssl_backend_data *backend = connssl->backend;
++
++  /* If we don't have SSL context, do nothing. */
++  if(!backend->handle)
++    return;
++
++  if(SSL_SET_OPTION(primary.sessionid)) {
++    bool isproxy = FALSE;
++    bool incache;
++    void *old_ssl_sessionid = NULL;
++    int data_idx = ossl_get_ssl_data_index();
++    int connectdata_idx = ossl_get_ssl_conn_index();
++    int sockindex_idx = ossl_get_ssl_sockindex_index();
++    int proxy_idx = ossl_get_proxy_index();
++
++    if(data_idx >= 0 && connectdata_idx >= 0 && sockindex_idx >= 0 &&
++       proxy_idx >= 0) {
++      /* Invalidate the session cache entry, if any */
++      isproxy = SSL_get_ex_data(backend->handle, proxy_idx) ? TRUE : FALSE;
++
++      /* Disable references to data in "new session" callback to avoid
++       * accessing a stale pointer. */
++      SSL_set_ex_data(backend->handle, data_idx, NULL);
++      SSL_set_ex_data(backend->handle, connectdata_idx, NULL);
++      SSL_set_ex_data(backend->handle, sockindex_idx, NULL);
++      SSL_set_ex_data(backend->handle, proxy_idx, NULL);
++    }
++
++    Curl_ssl_sessionid_lock(data);
++    incache = !(Curl_ssl_getsessionid(data, conn, isproxy,
++                                      &old_ssl_sessionid, NULL, sockindex));
++    if(incache)
++      Curl_ssl_delsessionid(data, old_ssl_sessionid);
++    Curl_ssl_sessionid_unlock(data);
++  }
++}
++
+ const struct Curl_ssl Curl_ssl_openssl = {
+   { CURLSSLBACKEND_OPENSSL, "openssl" }, /* info */
+ 
+@@ -4533,10 +4599,12 @@ const struct Curl_ssl Curl_ssl_openssl = {
+   ossl_engines_list,        /* engines_list */
+   Curl_none_false_start,    /* false_start */
+ #if (OPENSSL_VERSION_NUMBER >= 0x0090800fL) && !defined(OPENSSL_NO_SHA256)
+-  ossl_sha256sum            /* sha256sum */
++  ossl_sha256sum,           /* sha256sum */
+ #else
+-  NULL                      /* sha256sum */
++  NULL,                     /* sha256sum */
+ #endif
++  ossl_associate_connection, /* associate_connection */
++  ossl_disassociate_connection /* disassociate_connection */
+ };
+ 
+ #endif /* USE_OPENSSL */
+diff --git a/lib/vtls/rustls.c b/lib/vtls/rustls.c
+index 9dfbd2c3c4c2..161f3bf51d75 100644
+--- a/lib/vtls/rustls.c
++++ b/lib/vtls/rustls.c
+@@ -604,7 +604,9 @@ const struct Curl_ssl Curl_ssl_rustls = {
+   Curl_none_set_engine_default,    /* set_engine_default */
+   Curl_none_engines_list,          /* engines_list */
+   Curl_none_false_start,           /* false_start */
+-  NULL                             /* sha256sum */
++  NULL,                            /* sha256sum */
++  NULL,                            /* associate_connection */
++  NULL                             /* disassociate_connection */
+ };
+ 
+ #endif /* USE_RUSTLS */
+diff --git a/lib/vtls/schannel.c b/lib/vtls/schannel.c
+index dba7072273a9..2bcf11db2576 100644
+--- a/lib/vtls/schannel.c
++++ b/lib/vtls/schannel.c
+@@ -329,7 +329,7 @@ get_alg_id_by_name(char *name)
+ 
+ static CURLcode
+ set_ssl_ciphers(SCHANNEL_CRED *schannel_cred, char *ciphers,
+-                int *algIds)
++                ALG_ID *algIds)
+ {
+   char *startCur = ciphers;
+   int algCount = 0;
+@@ -2433,7 +2433,9 @@ const struct Curl_ssl Curl_ssl_schannel = {
+   Curl_none_set_engine_default,      /* set_engine_default */
+   Curl_none_engines_list,            /* engines_list */
+   Curl_none_false_start,             /* false_start */
+-  schannel_sha256sum                 /* sha256sum */
++  schannel_sha256sum,                /* sha256sum */
++  NULL,                              /* associate_connection */
++  NULL                               /* disassociate_connection */
+ };
+ 
+ #endif /* USE_SCHANNEL */
+diff --git a/lib/vtls/sectransp.c b/lib/vtls/sectransp.c
+index 4276b89cfb3a..8b1e84ed7715 100644
+--- a/lib/vtls/sectransp.c
++++ b/lib/vtls/sectransp.c
+@@ -3453,6 +3453,8 @@ const struct Curl_ssl Curl_ssl_sectransp = {
+   Curl_none_engines_list,             /* engines_list */
+   sectransp_false_start,              /* false_start */
+   sectransp_sha256sum                 /* sha256sum */
++  NULL,                               /* associate_connection */
++  NULL                                /* disassociate_connection */
+ };
+ 
+ #ifdef __clang__
+diff --git a/lib/vtls/vtls.c b/lib/vtls/vtls.c
+index d63fd5c76386..65f4f773dd63 100644
+--- a/lib/vtls/vtls.c
++++ b/lib/vtls/vtls.c
+@@ -586,6 +586,25 @@ CURLcode Curl_ssl_addsessionid(struct Curl_easy *data,
+   return CURLE_OK;
+ }
+ 
++void Curl_ssl_associate_conn(struct Curl_easy *data,
++                             struct connectdata *conn)
++{
++  if(Curl_ssl->associate_connection) {
++    Curl_ssl->associate_connection(data, conn, FIRSTSOCKET);
++    if(conn->sock[SECONDARYSOCKET] && conn->bits.sock_accepted)
++      Curl_ssl->associate_connection(data, conn, SECONDARYSOCKET);
++  }
++}
++
++void Curl_ssl_detach_conn(struct Curl_easy *data,
++                          struct connectdata *conn)
++{
++  if(Curl_ssl->disassociate_connection) {
++    Curl_ssl->disassociate_connection(data, FIRSTSOCKET);
++    if(conn->sock[SECONDARYSOCKET] && conn->bits.sock_accepted)
++      Curl_ssl->disassociate_connection(data, SECONDARYSOCKET);
++  }
++}
+ 
+ void Curl_ssl_close_all(struct Curl_easy *data)
+ {
+@@ -1214,7 +1233,9 @@ static const struct Curl_ssl Curl_ssl_multi = {
+   Curl_none_set_engine_default,      /* set_engine_default */
+   Curl_none_engines_list,            /* engines_list */
+   Curl_none_false_start,             /* false_start */
+-  NULL                               /* sha256sum */
++  NULL,                              /* sha256sum */
++  NULL,                              /* associate_connection */
++  NULL                               /* disassociate_connection */
+ };
+ 
+ const struct Curl_ssl *Curl_ssl =
+diff --git a/lib/vtls/vtls.h b/lib/vtls/vtls.h
+index a22d526ca810..7f93e7aedb21 100644
+--- a/lib/vtls/vtls.h
++++ b/lib/vtls/vtls.h
+@@ -84,6 +84,11 @@ struct Curl_ssl {
+   bool (*false_start)(void);
+   CURLcode (*sha256sum)(const unsigned char *input, size_t inputlen,
+                     unsigned char *sha256sum, size_t sha256sumlen);
++
++  void (*associate_connection)(struct Curl_easy *data,
++                               struct connectdata *conn,
++                               int sockindex);
++  void (*disassociate_connection)(struct Curl_easy *data, int sockindex);
+ };
+ 
+ #ifdef USE_SSL
+@@ -283,6 +288,11 @@ bool Curl_ssl_cert_status_request(void);
+ 
+ bool Curl_ssl_false_start(void);
+ 
++void Curl_ssl_associate_conn(struct Curl_easy *data,
++                             struct connectdata *conn);
++void Curl_ssl_detach_conn(struct Curl_easy *data,
++                          struct connectdata *conn);
++
+ #define SSL_SHUTDOWN_TIMEOUT 10000 /* ms */
+ 
+ #else /* if not USE_SSL */
+@@ -309,6 +319,8 @@ bool Curl_ssl_false_start(void);
+ #define Curl_ssl_cert_status_request() FALSE
+ #define Curl_ssl_false_start() FALSE
+ #define Curl_ssl_tls13_ciphersuites() FALSE
++#define Curl_ssl_associate_conn(a,b) Curl_nop_stmt
++#define Curl_ssl_detach_conn(a,b) Curl_nop_stmt
+ #endif
+ 
+ #endif /* HEADER_CURL_VTLS_H */
+diff --git a/lib/vtls/wolfssl.c b/lib/vtls/wolfssl.c
+index 02fcd236697e..60e27e366252 100644
+--- a/lib/vtls/wolfssl.c
++++ b/lib/vtls/wolfssl.c
+@@ -1125,7 +1125,9 @@ const struct Curl_ssl Curl_ssl_wolfssl = {
+   Curl_none_set_engine_default,    /* set_engine_default */
+   Curl_none_engines_list,          /* engines_list */
+   Curl_none_false_start,           /* false_start */
+-  wolfssl_sha256sum                /* sha256sum */
++  wolfssl_sha256sum,               /* sha256sum */
++  NULL,                            /* associate_connection */
++  NULL                             /* disassociate_connection */
+ };
+ 
+ #endif
diff --git a/pkgs/tools/networking/curl/default.nix b/pkgs/tools/networking/curl/default.nix
index 05b91bfba0556..984a6ecaaef8b 100644
--- a/pkgs/tools/networking/curl/default.nix
+++ b/pkgs/tools/networking/curl/default.nix
@@ -52,6 +52,12 @@ stdenv.mkDerivation rec {
     sha256 = "1scmfrp0c27pkd7yva9k50miprjpsyfbb33apx72qc9igm6ii3ks";
   };
 
+  patches = [
+    ./CVE-2021-22897.patch
+    ./CVE-2021-22898.patch
+    ./CVE-2021-22901.patch
+  ];
+
   outputs = [ "bin" "dev" "out" "man" "devdoc" ];
   separateDebugInfo = stdenv.isLinux;