crypto/tls: disable 3-DES by default

Fixes #66214

Change-Id: Iba8006a17fc7cd33c7485ab1a1ef8f56531c0ed1
Reviewed-on: https://go-review.googlesource.com/c/go/+/587295
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Roland Shoemaker <roland@golang.org>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
Auto-Submit: Filippo Valsorda <filippo@golang.org>
This commit is contained in:
Filippo Valsorda 2024-05-22 11:39:41 +02:00 committed by Gopher Robot
parent 5fee159bc2
commit 032660573c
10 changed files with 55 additions and 26 deletions

View File

@ -197,6 +197,10 @@ Go 1.23 re-enabled support in html/template for ECMAScript 6 template literals b
The [`jstmpllitinterp` setting](/pkg/html/template#hdr-Security_Model) no longer has The [`jstmpllitinterp` setting](/pkg/html/template#hdr-Security_Model) no longer has
any effect. any effect.
Go 1.23 changed the default TLS cipher suites used by clients and servers when
not explicitly configured, removing 3DES cipher suites. The default can be reverted
using the [`tls3des` setting](/pkg/crypto/tls/#Config.CipherSuites).
### Go 1.22 ### Go 1.22
Go 1.22 adds a configurable limit to control the maximum acceptable RSA key size Go 1.22 adds a configurable limit to control the maximum acceptable RSA key size

View File

@ -0,0 +1,3 @@
3DES cipher suites were removed from the default list used when
[Config.CipherSuites] is nil. The default can be reverted adding `tls3des=1` to
the GODEBUG environment variable.

View File

@ -17,7 +17,9 @@ import (
"fmt" "fmt"
"hash" "hash"
"internal/cpu" "internal/cpu"
"internal/godebug"
"runtime" "runtime"
"slices"
"golang.org/x/crypto/chacha20poly1305" "golang.org/x/crypto/chacha20poly1305"
) )
@ -334,6 +336,8 @@ var disabledCipherSuites = map[uint16]bool{
TLS_RSA_WITH_RC4_128_SHA: true, TLS_RSA_WITH_RC4_128_SHA: true,
} }
var tlsrsakex = godebug.New("tlsrsakex")
// rsaKexCiphers contains the ciphers which use RSA based key exchange, // rsaKexCiphers contains the ciphers which use RSA based key exchange,
// which we also disable by default unless a GODEBUG is set. // which we also disable by default unless a GODEBUG is set.
var rsaKexCiphers = map[uint16]bool{ var rsaKexCiphers = map[uint16]bool{
@ -346,21 +350,22 @@ var rsaKexCiphers = map[uint16]bool{
TLS_RSA_WITH_AES_256_GCM_SHA384: true, TLS_RSA_WITH_AES_256_GCM_SHA384: true,
} }
var defaultCipherSuites []uint16 var tls3des = godebug.New("tls3des")
var defaultCipherSuitesWithRSAKex []uint16
func init() { // tdesCiphers contains 3DES ciphers,
defaultCipherSuites = make([]uint16, 0, len(cipherSuitesPreferenceOrder)) // which we also disable by default unless a GODEBUG is set.
defaultCipherSuitesWithRSAKex = make([]uint16, 0, len(cipherSuitesPreferenceOrder)) var tdesCiphers = map[uint16]bool{
for _, c := range cipherSuitesPreferenceOrder { TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA: true,
if disabledCipherSuites[c] { TLS_RSA_WITH_3DES_EDE_CBC_SHA: true,
continue }
}
if !rsaKexCiphers[c] { func defaultCipherSuites() []uint16 {
defaultCipherSuites = append(defaultCipherSuites, c) suites := slices.Clone(cipherSuitesPreferenceOrder)
} return slices.DeleteFunc(suites, func(c uint16) bool {
defaultCipherSuitesWithRSAKex = append(defaultCipherSuitesWithRSAKex, c) return disabledCipherSuites[c] ||
} tlsrsakex.Value() != "1" && rsaKexCiphers[c] ||
tls3des.Value() != "1" && tdesCiphers[c]
})
} }
// defaultCipherSuitesTLS13 is also the preference order, since there are no // defaultCipherSuitesTLS13 is also the preference order, since there are no

View File

@ -687,7 +687,9 @@ type Config struct {
// If CipherSuites is nil, a safe default list is used. The default cipher // If CipherSuites is nil, a safe default list is used. The default cipher
// suites might change over time. In Go 1.22 RSA key exchange based cipher // 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 // suites were removed from the default list, but can be re-added with the
// GODEBUG setting tlsrsakex=1. // GODEBUG setting tlsrsakex=1. In Go 1.23 3DES cipher suites were removed
// from the default list, but can be re-added with the GODEBUG setting
// tls3des=1.
CipherSuites []uint16 CipherSuites []uint16
// PreferServerCipherSuites is a legacy field and has no effect. // PreferServerCipherSuites is a legacy field and has no effect.
@ -1025,8 +1027,6 @@ func (c *Config) time() time.Time {
return t() return t()
} }
var tlsrsakex = godebug.New("tlsrsakex")
func (c *Config) cipherSuites() []uint16 { func (c *Config) cipherSuites() []uint16 {
if needFIPS() { if needFIPS() {
return fipsCipherSuites(c) return fipsCipherSuites(c)
@ -1034,10 +1034,7 @@ func (c *Config) cipherSuites() []uint16 {
if c.CipherSuites != nil { if c.CipherSuites != nil {
return c.CipherSuites return c.CipherSuites
} }
if tlsrsakex.Value() == "1" { return defaultCipherSuites()
return defaultCipherSuitesWithRSAKex
}
return defaultCipherSuites
} }
var supportedVersions = []uint16{ var supportedVersions = []uint16{

View File

@ -551,6 +551,10 @@ func (hs *clientHandshakeState) pickCipherSuite() error {
tlsrsakex.Value() // ensure godebug is initialized tlsrsakex.Value() // ensure godebug is initialized
tlsrsakex.IncNonDefault() tlsrsakex.IncNonDefault()
} }
if hs.c.config.CipherSuites == nil && !needFIPS() && tdesCiphers[hs.suite.id] {
tls3des.Value() // ensure godebug is initialized
tls3des.IncNonDefault()
}
hs.c.cipherSuite = hs.suite.id hs.c.cipherSuite = hs.suite.id
return nil return nil

View File

@ -376,6 +376,10 @@ func (hs *serverHandshakeState) pickCipherSuite() error {
tlsrsakex.Value() // ensure godebug is initialized tlsrsakex.Value() // ensure godebug is initialized
tlsrsakex.IncNonDefault() tlsrsakex.IncNonDefault()
} }
if c.config.CipherSuites == nil && !needFIPS() && tdesCiphers[hs.suite.id] {
tls3des.Value() // ensure godebug is initialized
tls3des.IncNonDefault()
}
for _, id := range hs.clientHello.cipherSuites { for _, id := range hs.clientHello.cipherSuites {
if id == TLS_FALLBACK_SCSV { if id == TLS_FALLBACK_SCSV {

View File

@ -1458,6 +1458,16 @@ func TestCipherSuites(t *testing.T) {
t.Errorf("%#04x: suite TLS 1.0-1.2, but SupportedVersions is %v", c.id, cc.SupportedVersions) t.Errorf("%#04x: suite TLS 1.0-1.2, but SupportedVersions is %v", c.id, cc.SupportedVersions)
} }
if cc.Insecure {
if slices.Contains(defaultCipherSuites(), c.id) {
t.Errorf("%#04x: insecure suite in default list", c.id)
}
} else {
if !slices.Contains(defaultCipherSuites(), c.id) {
t.Errorf("%#04x: secure suite not in default list", c.id)
}
}
if got := CipherSuiteName(c.id); got != cc.Name { if got := CipherSuiteName(c.id); got != cc.Name {
t.Errorf("%#04x: unexpected CipherSuiteName: got %q, expected %q", c.id, got, cc.Name) t.Errorf("%#04x: unexpected CipherSuiteName: got %q, expected %q", c.id, got, cc.Name)
} }
@ -1491,9 +1501,6 @@ func TestCipherSuites(t *testing.T) {
if len(cipherSuitesPreferenceOrderNoAES) != len(cipherSuitesPreferenceOrder) { if len(cipherSuitesPreferenceOrderNoAES) != len(cipherSuitesPreferenceOrder) {
t.Errorf("cipherSuitesPreferenceOrderNoAES is not the same size as cipherSuitesPreferenceOrder") t.Errorf("cipherSuitesPreferenceOrderNoAES is not the same size as cipherSuitesPreferenceOrder")
} }
if len(defaultCipherSuites) >= len(defaultCipherSuitesWithRSAKex) {
t.Errorf("defaultCipherSuitesWithRSAKex should be longer than defaultCipherSuites")
}
// Check that disabled suites are marked insecure. // Check that disabled suites are marked insecure.
for _, badSuites := range []map[uint16]bool{disabledCipherSuites, rsaKexCiphers} { for _, badSuites := range []map[uint16]bool{disabledCipherSuites, rsaKexCiphers} {

View File

@ -47,6 +47,7 @@ var All = []Info{
{Name: "randautoseed", Package: "math/rand"}, {Name: "randautoseed", Package: "math/rand"},
{Name: "tarinsecurepath", Package: "archive/tar"}, {Name: "tarinsecurepath", Package: "archive/tar"},
{Name: "tls10server", Package: "crypto/tls", Changed: 22, Old: "1"}, {Name: "tls10server", Package: "crypto/tls", Changed: 22, Old: "1"},
{Name: "tls3des", Package: "crypto/tls", Changed: 23, Old: "1"},
{Name: "tlskyber", Package: "crypto/tls", Changed: 23, Old: "0", Opaque: true}, {Name: "tlskyber", Package: "crypto/tls", Changed: 23, Old: "0", Opaque: true},
{Name: "tlsmaxrsasize", Package: "crypto/tls"}, {Name: "tlsmaxrsasize", Package: "crypto/tls"},
{Name: "tlsrsakex", Package: "crypto/tls", Changed: 22, Old: "1"}, {Name: "tlsrsakex", Package: "crypto/tls", Changed: 22, Old: "1"},

View File

@ -946,7 +946,7 @@ func testResponseSetsTLSConnectionState(t *testing.T, mode testMode) {
c := ts.Client() c := ts.Client()
tr := c.Transport.(*Transport) tr := c.Transport.(*Transport)
tr.TLSClientConfig.CipherSuites = []uint16{tls.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA} tr.TLSClientConfig.CipherSuites = []uint16{tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256}
tr.TLSClientConfig.MaxVersion = tls.VersionTLS12 // to get to pick the cipher suite tr.TLSClientConfig.MaxVersion = tls.VersionTLS12 // to get to pick the cipher suite
tr.Dial = func(netw, addr string) (net.Conn, error) { tr.Dial = func(netw, addr string) (net.Conn, error) {
return net.Dial(netw, ts.Listener.Addr().String()) return net.Dial(netw, ts.Listener.Addr().String())
@ -959,7 +959,7 @@ func testResponseSetsTLSConnectionState(t *testing.T, mode testMode) {
if res.TLS == nil { if res.TLS == nil {
t.Fatal("Response didn't set TLS Connection State.") t.Fatal("Response didn't set TLS Connection State.")
} }
if got, want := res.TLS.CipherSuite, tls.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA; got != want { if got, want := res.TLS.CipherSuite, tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256; got != want {
t.Errorf("TLS Cipher Suite = %d; want %d", got, want) t.Errorf("TLS Cipher Suite = %d; want %d", got, want)
} }
} }

View File

@ -302,6 +302,10 @@ Below is the full list of supported metrics, ordered lexicographically.
The number of non-default behaviors executed by the crypto/tls The number of non-default behaviors executed by the crypto/tls
package due to a non-default GODEBUG=tls10server=... setting. package due to a non-default GODEBUG=tls10server=... setting.
/godebug/non-default-behavior/tls3des:events
The number of non-default behaviors executed by the crypto/tls
package due to a non-default GODEBUG=tls3des=... setting.
/godebug/non-default-behavior/tlsmaxrsasize:events /godebug/non-default-behavior/tlsmaxrsasize:events
The number of non-default behaviors executed by the crypto/tls The number of non-default behaviors executed by the crypto/tls
package due to a non-default GODEBUG=tlsmaxrsasize=... setting. package due to a non-default GODEBUG=tlsmaxrsasize=... setting.