From 67d555e089180aaa39993729b7f9693ea12d6ea6 Mon Sep 17 00:00:00 2001 From: Roland Shoemaker Date: Fri, 10 Nov 2023 10:42:42 -0800 Subject: [PATCH] crypto/tls: remove RSA KEX ciphers from the default list Removes the RSA KEX based ciphers from the default list. This can be reverted using the tlsrsakex GODEBUG. Fixes #63413 Change-Id: Id221be3eb2f6c24b91039d380313f0c87d339f98 Reviewed-on: https://go-review.googlesource.com/c/go/+/541517 LUCI-TryBot-Result: Go LUCI Reviewed-by: Damien Neil --- doc/godebug.md | 4 ++++ src/crypto/tls/cipher_suites.go | 30 ++++++++++++++++++++++++++++-- src/crypto/tls/common.go | 4 +++- src/crypto/tls/tls_test.go | 6 +++++- src/internal/godebugs/table.go | 1 + src/net/http/client_test.go | 4 ++-- src/runtime/metrics/doc.go | 4 ++++ 7 files changed, 47 insertions(+), 6 deletions(-) diff --git a/doc/godebug.md b/doc/godebug.md index 2ca27a640d..9235635bdd 100644 --- a/doc/godebug.md +++ b/doc/godebug.md @@ -155,6 +155,10 @@ Go 1.22 changed the default minimum TLS version supported by both servers and clients to TLS 1.2. The default can be reverted to TLS 1.0 using the [`tls10server` setting](/pkg/crypto/tls/#Config). +Go 1.22 changed the default TLS cipher suites used by clients and servers when +not explicitly configured, removing the cipher suites which used RSA based key +exchange. The default can be revert using the [`tlsrsakex` setting](/pkg/crypto/tls/#Config). + ### Go 1.21 Go 1.21 made it a run-time error to call `panic` with a nil interface value, diff --git a/src/crypto/tls/cipher_suites.go b/src/crypto/tls/cipher_suites.go index 3f976c9c58..eaeb7e04e6 100644 --- a/src/crypto/tls/cipher_suites.go +++ b/src/crypto/tls/cipher_suites.go @@ -17,6 +17,7 @@ import ( "fmt" "hash" "internal/cpu" + "internal/godebug" "runtime" "golang.org/x/crypto/chacha20poly1305" @@ -335,10 +336,35 @@ var disabledCipherSuites = []uint16{ } var ( - defaultCipherSuitesLen = len(cipherSuitesPreferenceOrder) - len(disabledCipherSuites) - defaultCipherSuites = cipherSuitesPreferenceOrder[:defaultCipherSuitesLen] + defaultCipherSuitesLen int + defaultCipherSuites []uint16 ) +// rsaKexCiphers contains the ciphers which use RSA based key exchange, +// which we disable by default. +var rsaKexCiphers = map[uint16]bool{ + TLS_RSA_WITH_RC4_128_SHA: true, + TLS_RSA_WITH_3DES_EDE_CBC_SHA: true, + TLS_RSA_WITH_AES_128_CBC_SHA: true, + TLS_RSA_WITH_AES_256_CBC_SHA: true, + TLS_RSA_WITH_AES_128_CBC_SHA256: true, + TLS_RSA_WITH_AES_128_GCM_SHA256: true, + TLS_RSA_WITH_AES_256_GCM_SHA384: true, +} + +var rsaKEXgodebug = godebug.New("tlsrsakex") + +func init() { + rsaKexEnabled := rsaKEXgodebug.Value() == "1" + for _, c := range cipherSuitesPreferenceOrder[:len(cipherSuitesPreferenceOrder)-len(disabledCipherSuites)] { + if !rsaKexEnabled && rsaKexCiphers[c] { + continue + } + defaultCipherSuites = append(defaultCipherSuites, c) + } + defaultCipherSuitesLen = len(defaultCipherSuites) +} + // defaultCipherSuitesTLS13 is also the preference order, since there are no // disabled by default TLS 1.3 cipher suites. The same AES vs ChaCha20 logic as // cipherSuitesPreferenceOrder applies. diff --git a/src/crypto/tls/common.go b/src/crypto/tls/common.go index 69b0ee6ede..6058824ded 100644 --- a/src/crypto/tls/common.go +++ b/src/crypto/tls/common.go @@ -670,7 +670,9 @@ type Config struct { // the list is ignored. Note that TLS 1.3 ciphersuites are not configurable. // // If CipherSuites is nil, a safe default list is used. The default cipher - // suites might change over time. + // suites might change over time. In Go 1.22 RSA key exchange based cipher + // suites were removed from the default list, but can be re-added with the + // GODEBUG setting tlsrsakex=1. CipherSuites []uint16 // PreferServerCipherSuites is a legacy field and has no effect. diff --git a/src/crypto/tls/tls_test.go b/src/crypto/tls/tls_test.go index 16f655dd93..5b09e53524 100644 --- a/src/crypto/tls/tls_test.go +++ b/src/crypto/tls/tls_test.go @@ -1288,7 +1288,8 @@ func TestClientHelloInfo_SupportsCertificate(t *testing.T) { SignatureSchemes: []SignatureScheme{PKCS1WithSHA1}, SupportedVersions: []uint16{VersionTLS13, VersionTLS12}, config: &Config{ - MaxVersion: VersionTLS12, + CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256}, + MaxVersion: VersionTLS12, }, }, ""}, // Check that mutual version selection works. @@ -1385,6 +1386,9 @@ func TestClientHelloInfo_SupportsCertificate(t *testing.T) { {rsaCert, &ClientHelloInfo{ CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256}, SupportedVersions: []uint16{VersionTLS12}, + config: &Config{ + CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256}, + }, }, ""}, // static RSA fallback } for i, tt := range tests { diff --git a/src/internal/godebugs/table.go b/src/internal/godebugs/table.go index 6ec039f7b7..92a0d089ca 100644 --- a/src/internal/godebugs/table.go +++ b/src/internal/godebugs/table.go @@ -47,6 +47,7 @@ var All = []Info{ {Name: "tarinsecurepath", Package: "archive/tar"}, {Name: "tls10server", Package: "crypto/tls", Changed: 22, Old: "1"}, {Name: "tlsmaxrsasize", Package: "crypto/tls"}, + {Name: "tlsrsakex", Package: "crypto/tls", Changed: 22, Old: "1"}, {Name: "x509sha1", Package: "crypto/x509"}, {Name: "x509usefallbackroots", Package: "crypto/x509"}, {Name: "zipinsecurepath", Package: "archive/zip"}, diff --git a/src/net/http/client_test.go b/src/net/http/client_test.go index df2a670aee..7459b9cb6e 100644 --- a/src/net/http/client_test.go +++ b/src/net/http/client_test.go @@ -946,7 +946,7 @@ func testResponseSetsTLSConnectionState(t *testing.T, mode testMode) { c := ts.Client() tr := c.Transport.(*Transport) - tr.TLSClientConfig.CipherSuites = []uint16{tls.TLS_RSA_WITH_3DES_EDE_CBC_SHA} + tr.TLSClientConfig.CipherSuites = []uint16{tls.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA} tr.TLSClientConfig.MaxVersion = tls.VersionTLS12 // to get to pick the cipher suite tr.Dial = func(netw, addr string) (net.Conn, error) { return net.Dial(netw, ts.Listener.Addr().String()) @@ -959,7 +959,7 @@ func testResponseSetsTLSConnectionState(t *testing.T, mode testMode) { if res.TLS == nil { t.Fatal("Response didn't set TLS Connection State.") } - if got, want := res.TLS.CipherSuite, tls.TLS_RSA_WITH_3DES_EDE_CBC_SHA; got != want { + if got, want := res.TLS.CipherSuite, tls.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA; got != want { t.Errorf("TLS Cipher Suite = %d; want %d", got, want) } } diff --git a/src/runtime/metrics/doc.go b/src/runtime/metrics/doc.go index a89f6dca65..78b2e6c3bc 100644 --- a/src/runtime/metrics/doc.go +++ b/src/runtime/metrics/doc.go @@ -311,6 +311,10 @@ Below is the full list of supported metrics, ordered lexicographically. The number of non-default behaviors executed by the crypto/tls package due to a non-default GODEBUG=tlsmaxrsasize=... setting. + /godebug/non-default-behavior/tlsrsakex:events + The number of non-default behaviors executed by the crypto/tls + package due to a non-default GODEBUG=tlsrsakex=... setting. + /godebug/non-default-behavior/x509sha1:events The number of non-default behaviors executed by the crypto/x509 package due to a non-default GODEBUG=x509sha1=... setting. -- 2.44.0