]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
schannel: remove TLS 1.3 ciphersuite-list support
authorWyatt O'Day <wyatt@wyday.com>
Thu, 21 Nov 2024 14:08:31 +0000 (09:08 -0500)
committerJay Satiro <raysatiro@yahoo.com>
Thu, 21 Nov 2024 22:09:24 +0000 (17:09 -0500)
Drop TLS 1.3 ciphersuite-list support from SChannel because of the
number of bugs in SChannel itself (a closed-source TLS library). TLS 1.3
with SChannel still works, however the ciphersuite negotiation is left
entirely to SChannel.

Bug: https://hackerone.com/reports/2792484
Reported-by: newfunction on hackerone
Fixes https://github.com/curl/curl/issues/15482
Closes https://github.com/curl/curl/pull/15621

docs/CIPHERS.md
docs/cmdline-opts/tls13-ciphers.md
docs/libcurl/opts/CURLOPT_PROXY_TLS13_CIPHERS.md
docs/libcurl/opts/CURLOPT_TLS13_CIPHERS.md
lib/vtls/schannel.c

index 6e899e52dfad3794bac585795b0cebc0935134f8..2ceae3b36159c97236efd92b8641ca06199a23b0 100644 (file)
@@ -42,8 +42,7 @@ common cipher suite in the list sent by curl is chosen.
 
 Setting TLS 1.3 cipher suites is supported by curl with
 OpenSSL (1.1.1+, curl 7.61.0+), LibreSSL (3.4.1+, curl 8.3.0+),
-wolfSSL (curl 8.10.0+), mbedTLS (3.6.0+, curl 8.10.0+) and
-Schannel (curl 7.85.0+).
+wolfSSL (curl 8.10.0+) and mbedTLS (3.6.0+, curl 8.10.0+).
 
 The list of cipher suites that can be used for the `--tls13-ciphers` option:
 ```
@@ -61,13 +60,6 @@ In addition to above list the following cipher suites can be used:
 Usage of these cipher suites is not recommended. (The last two cipher suites
 are NULL ciphers, offering no encryption whatsoever.)
 
-### Schannel notes
-
-Schannel does not support setting individual TLS 1.3 cipher suites directly.
-To support `--tls13-ciphers` curl emulates it by adding or restricting
-algorithms to use. Due to this the specified order of preference of the
-cipher suites is not taken into account.
-
 ## TLS 1.2 (1.1, 1.0) cipher suites
 
 Setting TLS 1.2 cipher suites is supported by curl with OpenSSL, LibreSSL,
index 43220af4da73f00694db8ef4c93dcba0c59d7759..94ea6c775d0b9041cdd70eacb74827ff569ccd71 100644 (file)
@@ -25,7 +25,7 @@ cipher suite details on this URL:
 https://curl.se/docs/ssl-ciphers.html
 
 This option is used when curl is built to use OpenSSL 1.1.1 or later,
-Schannel, wolfSSL, or mbedTLS 3.6.0 or later.
+wolfSSL, or mbedTLS 3.6.0 or later.
 
 Before curl 8.10.0 with mbedTLS or wolfSSL, TLS 1.3 cipher suites were set
 by using the --ciphers option.
index ba5d97edbc25bb6d496ef2af717256a482267db2..214c24574c61206a9504e8ba97ac64663c03b5be 100644 (file)
@@ -14,7 +14,6 @@ Protocol:
   - TLS
 TLS-backend:
   - OpenSSL
-  - Schannel
   - wolfSSL
   - mbedTLS
   - rustls
@@ -84,7 +83,6 @@ int main(void)
 # HISTORY
 
 OpenSSL support added in 7.61.0, available when built with OpenSSL \>= 1.1.1.
-Schannel support added in 7.87.0.
 LibreSSL support added in 8.3.0, available when built with LibreSSL \>= 3.4.1.
 wolfSSL support added in 8.10.0.
 mbedTLS support added in 8.10.0, available when built with mbedTLS \>= 3.6.0.
index d2c6226d5c62d475a38fe1cd5f00c5802abdd6ca..9876424bda1e4ed806010fb015de92a87e641551 100644 (file)
@@ -15,7 +15,6 @@ Protocol:
   - TLS
 TLS-backend:
   - OpenSSL
-  - Schannel
   - wolfSSL
   - mbedTLS
   - rustls
@@ -84,7 +83,6 @@ int main(void)
 # HISTORY
 
 OpenSSL support added in 7.61.0, available when built with OpenSSL \>= 1.1.1.
-Schannel support added in 7.85.0.
 LibreSSL support added in 8.3.0, available when built with LibreSSL \>= 3.4.1.
 wolfSSL support added in 8.10.0.
 mbedTLS support added in 8.10.0, available when built with mbedTLS \>= 3.6.0.
index 2085f7094673c39ab79cdb753e76affee2835843..f4bbe4e8325f8a1ccc1e9db7312b4502507bf2e1 100644 (file)
@@ -451,11 +451,6 @@ get_cert_location(TCHAR *path, DWORD *store_name, TCHAR **store_path,
 }
 #endif
 
-static bool algo(const char *check, char *namep, size_t nlen)
-{
-  return (strlen(check) == nlen) && !strncmp(check, namep, nlen);
-}
-
 static CURLcode
 schannel_acquire_credential_handle(struct Curl_cfilter *cf,
                                    struct Curl_easy *data)
@@ -781,187 +776,14 @@ schannel_acquire_credential_handle(struct Curl_cfilter *cf,
      curlx_verify_windows_version(10, 0, 17763, PLATFORM_WINNT,
                                   VERSION_GREATER_THAN_EQUAL)) {
 
-    char *ciphers13 = 0;
-
-    bool disable_aes_gcm_sha384 = FALSE;
-    bool disable_aes_gcm_sha256 = FALSE;
-    bool disable_chacha_poly = FALSE;
-    bool disable_aes_ccm_8_sha256 = FALSE;
-    bool disable_aes_ccm_sha256 = FALSE;
-
     SCH_CREDENTIALS credentials = { 0 };
     TLS_PARAMETERS tls_parameters = { 0 };
-    CRYPTO_SETTINGS crypto_settings[4] = { { 0 } };
-    UNICODE_STRING blocked_ccm_modes[1] = { { 0 } };
-    UNICODE_STRING blocked_gcm_modes[1] = { { 0 } };
-
-    int crypto_settings_idx = 0;
-
-
-    /* If TLS 1.3 ciphers are explicitly listed, then
-     * disable all the ciphers and re-enable which
-     * ciphers the user has provided.
-     */
-    ciphers13 = conn_config->cipher_list13;
-    if(ciphers13) {
-      const int remaining_ciphers = 5;
-
-      /* detect which remaining ciphers to enable
-         and then disable everything else.
-      */
-
-      char *startCur = ciphers13;
-      int algCount = 0;
-      char *nameEnd;
-
-      disable_aes_gcm_sha384 = TRUE;
-      disable_aes_gcm_sha256 = TRUE;
-      disable_chacha_poly = TRUE;
-      disable_aes_ccm_8_sha256 = TRUE;
-      disable_aes_ccm_sha256 = TRUE;
-
-      while(startCur && (0 != *startCur) && (algCount < remaining_ciphers)) {
-        size_t n;
-        char *namep;
-        nameEnd = strchr(startCur, ':');
-        n = nameEnd ? (size_t)(nameEnd - startCur) : strlen(startCur);
-        namep = startCur;
-
-        if(disable_aes_gcm_sha384 &&
-           algo("TLS_AES_256_GCM_SHA384", namep, n)) {
-          disable_aes_gcm_sha384 = FALSE;
-        }
-        else if(disable_aes_gcm_sha256
-                && algo("TLS_AES_128_GCM_SHA256", namep, n)) {
-          disable_aes_gcm_sha256 = FALSE;
-        }
-        else if(disable_chacha_poly
-                && algo("TLS_CHACHA20_POLY1305_SHA256", namep, n)) {
-          disable_chacha_poly = FALSE;
-        }
-        else if(disable_aes_ccm_8_sha256
-                && algo("TLS_AES_128_CCM_8_SHA256", namep, n)) {
-          disable_aes_ccm_8_sha256 = FALSE;
-        }
-        else if(disable_aes_ccm_sha256
-                && algo("TLS_AES_128_CCM_SHA256", namep, n)) {
-          disable_aes_ccm_sha256 = FALSE;
-        }
-        else {
-          failf(data, "schannel: Unknown TLS 1.3 cipher: %.*s", (int)n, namep);
-          return CURLE_SSL_CIPHER;
-        }
-
-        startCur = nameEnd;
-        if(startCur)
-          startCur++;
-
-        algCount++;
-      }
-    }
-
-    if(disable_aes_gcm_sha384 && disable_aes_gcm_sha256
-       && disable_chacha_poly && disable_aes_ccm_8_sha256
-       && disable_aes_ccm_sha256) {
-      failf(data, "schannel: All available TLS 1.3 ciphers were disabled");
-      return CURLE_SSL_CIPHER;
-    }
-
-    /* Disable TLS_AES_128_CCM_8_SHA256 and/or TLS_AES_128_CCM_SHA256 */
-    if(disable_aes_ccm_8_sha256 || disable_aes_ccm_sha256) {
-      /*
-        Disallow AES_CCM algorithm.
-      */
-      blocked_ccm_modes[0].Length = sizeof(BCRYPT_CHAIN_MODE_CCM);
-      blocked_ccm_modes[0].MaximumLength = sizeof(BCRYPT_CHAIN_MODE_CCM);
-      blocked_ccm_modes[0].Buffer = (PWSTR)BCRYPT_CHAIN_MODE_CCM;
-
-      crypto_settings[crypto_settings_idx].eAlgorithmUsage =
-        TlsParametersCngAlgUsageCipher;
-      crypto_settings[crypto_settings_idx].rgstrChainingModes =
-        blocked_ccm_modes;
-      crypto_settings[crypto_settings_idx].cChainingModes =
-        ARRAYSIZE(blocked_ccm_modes);
-      crypto_settings[crypto_settings_idx].strCngAlgId.Length =
-        sizeof(BCRYPT_AES_ALGORITHM);
-      crypto_settings[crypto_settings_idx].strCngAlgId.MaximumLength =
-        sizeof(BCRYPT_AES_ALGORITHM);
-      crypto_settings[crypto_settings_idx].strCngAlgId.Buffer =
-        (PWSTR)BCRYPT_AES_ALGORITHM;
-
-      /* only disabling one of the CCM modes */
-      if(disable_aes_ccm_8_sha256 != disable_aes_ccm_sha256) {
-        if(disable_aes_ccm_8_sha256)
-          crypto_settings[crypto_settings_idx].dwMinBitLength = 128;
-        else /* disable_aes_ccm_sha256 */
-          crypto_settings[crypto_settings_idx].dwMaxBitLength = 64;
-      }
-
-      crypto_settings_idx++;
-    }
-
-    /* Disable TLS_AES_256_GCM_SHA384 and/or TLS_AES_128_GCM_SHA256 */
-    if(disable_aes_gcm_sha384 || disable_aes_gcm_sha256) {
-
-      /*
-        Disallow AES_GCM algorithm
-      */
-      blocked_gcm_modes[0].Length = sizeof(BCRYPT_CHAIN_MODE_GCM);
-      blocked_gcm_modes[0].MaximumLength = sizeof(BCRYPT_CHAIN_MODE_GCM);
-      blocked_gcm_modes[0].Buffer = (PWSTR)BCRYPT_CHAIN_MODE_GCM;
-
-      /* if only one is disabled, then explicitly disable the
-         digest cipher suite (sha384 or sha256) */
-      if(disable_aes_gcm_sha384 != disable_aes_gcm_sha256) {
-        crypto_settings[crypto_settings_idx].eAlgorithmUsage =
-          TlsParametersCngAlgUsageDigest;
-        crypto_settings[crypto_settings_idx].strCngAlgId.Length =
-          sizeof(disable_aes_gcm_sha384 ?
-                 BCRYPT_SHA384_ALGORITHM : BCRYPT_SHA256_ALGORITHM);
-        crypto_settings[crypto_settings_idx].strCngAlgId.MaximumLength =
-          sizeof(disable_aes_gcm_sha384 ?
-                 BCRYPT_SHA384_ALGORITHM : BCRYPT_SHA256_ALGORITHM);
-        crypto_settings[crypto_settings_idx].strCngAlgId.Buffer =
-          (PWSTR)(disable_aes_gcm_sha384 ?
-                  BCRYPT_SHA384_ALGORITHM : BCRYPT_SHA256_ALGORITHM);
-      }
-      else { /* Disable both AES_GCM ciphers */
-        crypto_settings[crypto_settings_idx].eAlgorithmUsage =
-          TlsParametersCngAlgUsageCipher;
-        crypto_settings[crypto_settings_idx].strCngAlgId.Length =
-          sizeof(BCRYPT_AES_ALGORITHM);
-        crypto_settings[crypto_settings_idx].strCngAlgId.MaximumLength =
-          sizeof(BCRYPT_AES_ALGORITHM);
-        crypto_settings[crypto_settings_idx].strCngAlgId.Buffer =
-          (PWSTR)BCRYPT_AES_ALGORITHM;
-      }
-
-      crypto_settings[crypto_settings_idx].rgstrChainingModes =
-        blocked_gcm_modes;
-      crypto_settings[crypto_settings_idx].cChainingModes = 1;
-
-      crypto_settings_idx++;
-    }
-
-    /*
-      Disable ChaCha20-Poly1305.
-    */
-    if(disable_chacha_poly) {
-      crypto_settings[crypto_settings_idx].eAlgorithmUsage =
-        TlsParametersCngAlgUsageCipher;
-      crypto_settings[crypto_settings_idx].strCngAlgId.Length =
-        sizeof(BCRYPT_CHACHA20_POLY1305_ALGORITHM);
-      crypto_settings[crypto_settings_idx].strCngAlgId.MaximumLength =
-        sizeof(BCRYPT_CHACHA20_POLY1305_ALGORITHM);
-      crypto_settings[crypto_settings_idx].strCngAlgId.Buffer =
-        (PWSTR)BCRYPT_CHACHA20_POLY1305_ALGORITHM;
-      crypto_settings_idx++;
-    }
+    CRYPTO_SETTINGS crypto_settings[1] = { { 0 } };
 
     tls_parameters.pDisabledCrypto = crypto_settings;
 
     /* The number of blocked suites */
-    tls_parameters.cDisabledCrypto = (DWORD)crypto_settings_idx;
+    tls_parameters.cDisabledCrypto = (DWORD)0;
     credentials.pTlsParameters = &tls_parameters;
     credentials.cTlsParameters = 1;
 
@@ -986,9 +808,8 @@ schannel_acquire_credential_handle(struct Curl_cfilter *cf,
                                          &backend->cred->time_stamp);
   }
   else {
-    /* Pre-Windows 10 1809 or the user set a legacy algorithm list. Although MS
-       does not document it, currently Schannel will not negotiate TLS 1.3 when
-       SCHANNEL_CRED is used. */
+    /* Pre-Windows 10 1809 or the user set a legacy algorithm list.
+       Schannel will not negotiate TLS 1.3 when SCHANNEL_CRED is used. */
     ALG_ID algIds[NUM_CIPHERS];
     char *ciphers = conn_config->cipher_list;
     SCHANNEL_CRED schannel_cred = { 0 };
@@ -998,16 +819,10 @@ schannel_acquire_credential_handle(struct Curl_cfilter *cf,
 
     if(ciphers) {
       if((enabled_protocols & SP_PROT_TLS1_3_CLIENT)) {
-        infof(data, "schannel: WARNING: This version of Schannel may "
-              "negotiate a less-secure TLS version than TLS 1.3 because the "
+        infof(data, "schannel: WARNING: This version of Schannel "
+              "negotiates a less-secure TLS version than TLS 1.3 because the "
               "user set an algorithm cipher list.");
       }
-      if(conn_config->cipher_list13) {
-        failf(data, "schannel: This version of Schannel does not support "
-              "setting an algorithm cipher list and TLS 1.3 cipher list at "
-              "the same time");
-        return CURLE_SSL_CIPHER;
-      }
       result = set_ssl_ciphers(&schannel_cred, ciphers, algIds);
       if(CURLE_OK != result) {
         failf(data, "schannel: Failed setting algorithm cipher list");
@@ -2974,7 +2789,6 @@ const struct Curl_ssl Curl_ssl_schannel = {
 #ifndef CURL_WINDOWS_UWP
   SSLSUPP_PINNEDPUBKEY |
 #endif
-  SSLSUPP_TLS13_CIPHERSUITES |
   SSLSUPP_CA_CACHE |
   SSLSUPP_HTTPS_PROXY |
   SSLSUPP_CIPHER_LIST,