]> Cypherpunks repositories - gostls13.git/commitdiff
crypto/tls: disable ExportKeyingMaterial without EMS
authorFilippo Valsorda <filippo@golang.org>
Tue, 21 Nov 2023 15:37:07 +0000 (16:37 +0100)
committerGopher Robot <gobot@golang.org>
Tue, 21 Nov 2023 16:29:49 +0000 (16:29 +0000)
Fixes #43922

Change-Id: Idaad7daa6784807ae3a5e4d944e88e13d01fd0b2
Reviewed-on: https://go-review.googlesource.com/c/go/+/544155
Reviewed-by: Michael Knyszek <mknyszek@google.com>
Reviewed-by: Roland Shoemaker <roland@golang.org>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Auto-Submit: Filippo Valsorda <filippo@golang.org>

doc/godebug.md
src/crypto/tls/common.go
src/crypto/tls/conn.go
src/crypto/tls/prf.go
src/internal/godebugs/table.go
src/runtime/metrics/doc.go

index 9235635bdd0958789c4a847793c59b7e2d7131b5..50033b6f1770b8e49ff0446f36a75429c0bdb10b 100644 (file)
@@ -159,6 +159,12 @@ 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.22 disabled
+[`ConnectionState.ExportKeyingMaterial`](/pkg/crypto/tls/#ConnectionState.ExportKeyingMaterial)
+when the connection supports neither TLS 1.3 nor Extended Master Secret
+(implemented in Go 1.21). It can be reenabled with the [`tlsunsafeekm`
+setting](/pkg/crypto/tls/#ConnectionState.ExportKeyingMaterial).
+
 ### Go 1.21
 
 Go 1.21 made it a run-time error to call `panic` with a nil interface value,
index 6058824dede742951a5d4f877b2489159b746f55..faa460e7fa0e1adb5d2be5b555d1b3b913dea80e 100644 (file)
@@ -304,11 +304,13 @@ type ConnectionState struct {
 // ExportKeyingMaterial returns length bytes of exported key material in a new
 // slice as defined in RFC 5705. If context is nil, it is not used as part of
 // the seed. If the connection was set to allow renegotiation via
-// Config.Renegotiation, this function will return an error.
+// Config.Renegotiation, or if the connections supports neither TLS 1.3 nor
+// Extended Master Secret, this function will return an error.
 //
-// There are conditions in which the returned values might not be unique to a
-// connection. See the Security Considerations sections of RFC 5705 and RFC 7627,
-// and https://mitls.org/pages/attacks/3SHAKE#channelbindings.
+// Exporting key material without Extended Master Secret or TLS 1.3 was disabled
+// in Go 1.22 due to security issues (see the Security Considerations sections
+// of RFC 5705 and RFC 7627), but can be re-enabled with the GODEBUG setting
+// tlsunsafeekm=1.
 func (cs *ConnectionState) ExportKeyingMaterial(label string, context []byte, length int) ([]byte, error) {
        return cs.ekm(label, context, length)
 }
index 647e5b85b68a991249e00f1724f837d5116ef89a..3e8832f94758fc15b746ec8ae2191bfc1072eeff 100644 (file)
@@ -15,6 +15,7 @@ import (
        "errors"
        "fmt"
        "hash"
+       "internal/godebug"
        "io"
        "net"
        "sync"
@@ -1599,6 +1600,8 @@ func (c *Conn) ConnectionState() ConnectionState {
        return c.connectionStateLocked()
 }
 
+var ekmgodebug = godebug.New("tlsunsafeekm")
+
 func (c *Conn) connectionStateLocked() ConnectionState {
        var state ConnectionState
        state.HandshakeComplete = c.isHandshakeComplete.Load()
@@ -1620,7 +1623,15 @@ func (c *Conn) connectionStateLocked() ConnectionState {
                }
        }
        if c.config.Renegotiation != RenegotiateNever {
-               state.ekm = noExportedKeyingMaterial
+               state.ekm = noEKMBecauseRenegotiation
+       } else if c.vers != VersionTLS13 && !c.extMasterSecret {
+               state.ekm = func(label string, context []byte, length int) ([]byte, error) {
+                       if ekmgodebug.Value() == "1" {
+                               ekmgodebug.IncNonDefault()
+                               return c.ekm(label, context, length)
+                       }
+                       return noEKMBecauseNoEMS(label, context, length)
+               }
        } else {
                state.ekm = c.ekm
        }
index 20bac96e86703bf9bc8d887245d2f10d43f63131..a7fa3370e66c825c74e0d8e6262cdfe21a6c4b78 100644 (file)
@@ -252,13 +252,20 @@ func (h *finishedHash) discardHandshakeBuffer() {
        h.buffer = nil
 }
 
-// noExportedKeyingMaterial is used as a value of
+// noEKMBecauseRenegotiation is used as a value of
 // ConnectionState.ekm when renegotiation is enabled and thus
 // we wish to fail all key-material export requests.
-func noExportedKeyingMaterial(label string, context []byte, length int) ([]byte, error) {
+func noEKMBecauseRenegotiation(label string, context []byte, length int) ([]byte, error) {
        return nil, errors.New("crypto/tls: ExportKeyingMaterial is unavailable when renegotiation is enabled")
 }
 
+// noEKMBecauseNoEMS is used as a value of ConnectionState.ekm when Extended
+// Master Secret is not negotiated and thus we wish to fail all key-material
+// export requests.
+func noEKMBecauseNoEMS(label string, context []byte, length int) ([]byte, error) {
+       return nil, errors.New("crypto/tls: ExportKeyingMaterial is unavailable when neither TLS 1.3 nor Extended Master Secret are negotiated; override with GODEBUG=tlsunsafeekm=1")
+}
+
 // ekmFromMasterSecret generates exported keying material as defined in RFC 5705.
 func ekmFromMasterSecret(version uint16, suite *cipherSuite, masterSecret, clientRandom, serverRandom []byte) func(string, []byte, int) ([]byte, error) {
        return func(label string, context []byte, length int) ([]byte, error) {
index 92a0d089ca3f43b50fdc24a1b442d8f2e4711042..3a76214b39100dcfdcd345b29624cd54c3b76da4 100644 (file)
@@ -48,6 +48,7 @@ var All = []Info{
        {Name: "tls10server", Package: "crypto/tls", Changed: 22, Old: "1"},
        {Name: "tlsmaxrsasize", Package: "crypto/tls"},
        {Name: "tlsrsakex", Package: "crypto/tls", Changed: 22, Old: "1"},
+       {Name: "tlsunsafeekm", Package: "crypto/tls", Changed: 22, Old: "1"},
        {Name: "x509sha1", Package: "crypto/x509"},
        {Name: "x509usefallbackroots", Package: "crypto/x509"},
        {Name: "zipinsecurepath", Package: "archive/zip"},
index 5be6c32bfa0c3654f21257a81335a7d1b4217d4e..8df475666e5903d1eda18a840c85169b114dd8e7 100644 (file)
@@ -314,6 +314,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=tlsrsakex=... setting.
 
+       /godebug/non-default-behavior/tlsunsafeekm:events
+               The number of non-default behaviors executed by the crypto/tls
+               package due to a non-default GODEBUG=tlsunsafeekm=... 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.