From: Wyatt O'Day Date: Thu, 21 Nov 2024 14:08:31 +0000 (-0500) Subject: schannel: remove TLS 1.3 ciphersuite-list support X-Git-Tag: curl-8_11_1~56 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=6238888ca7f0e473e9713a7c372fac8f025db569;p=thirdparty%2Fcurl.git schannel: remove TLS 1.3 ciphersuite-list support 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 --- diff --git a/docs/CIPHERS.md b/docs/CIPHERS.md index 6e899e52df..2ceae3b361 100644 --- a/docs/CIPHERS.md +++ b/docs/CIPHERS.md @@ -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, diff --git a/docs/cmdline-opts/tls13-ciphers.md b/docs/cmdline-opts/tls13-ciphers.md index 43220af4da..94ea6c775d 100644 --- a/docs/cmdline-opts/tls13-ciphers.md +++ b/docs/cmdline-opts/tls13-ciphers.md @@ -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. diff --git a/docs/libcurl/opts/CURLOPT_PROXY_TLS13_CIPHERS.md b/docs/libcurl/opts/CURLOPT_PROXY_TLS13_CIPHERS.md index ba5d97edbc..214c24574c 100644 --- a/docs/libcurl/opts/CURLOPT_PROXY_TLS13_CIPHERS.md +++ b/docs/libcurl/opts/CURLOPT_PROXY_TLS13_CIPHERS.md @@ -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. diff --git a/docs/libcurl/opts/CURLOPT_TLS13_CIPHERS.md b/docs/libcurl/opts/CURLOPT_TLS13_CIPHERS.md index d2c6226d5c..9876424bda 100644 --- a/docs/libcurl/opts/CURLOPT_TLS13_CIPHERS.md +++ b/docs/libcurl/opts/CURLOPT_TLS13_CIPHERS.md @@ -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. diff --git a/lib/vtls/schannel.c b/lib/vtls/schannel.c index 2085f70946..f4bbe4e832 100644 --- a/lib/vtls/schannel.c +++ b/lib/vtls/schannel.c @@ -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,