Commit 2dbfad5c authored by Filippo Valsorda's avatar Filippo Valsorda Committed by Gopher Robot
Browse files

crypto/tls: disable ExportKeyingMaterial without EMS

Fixes #43922

Change-Id: Idaad7daa6784807ae3a5e4d944e88e13d01fd0b2
Reviewed-on: https://go-review.googlesource.com/c/go/+/544155


Reviewed-by: default avatarMichael Knyszek <mknyszek@google.com>
Reviewed-by: default avatarRoland Shoemaker <roland@golang.org>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Auto-Submit: Filippo Valsorda <filippo@golang.org>
parent ae820c6a
Loading
Loading
Loading
Loading
+6 −4
Original line number Diff line number Diff line
@@ -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)
}
+12 −1
Original line number Diff line number Diff line
@@ -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
	}
+9 −2
Original line number Diff line number Diff line
@@ -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) {