1
0
mirror of https://github.com/golang/go synced 2024-11-12 08:50:22 -07:00

crypto/tls: implement TLS 1.3 KeyLogWriter support

Also, add support for the SSLKEYLOGFILE environment variable to the
tests, to simplify debugging of unexpected failures.

Updates #9671

Change-Id: I20a34a5824f083da93097b793d51e796d6eb302b
Reviewed-on: https://go-review.googlesource.com/c/147417
Run-TryBot: Filippo Valsorda <filippo@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Adam Langley <agl@golang.org>
This commit is contained in:
Filippo Valsorda 2018-11-03 18:13:05 -04:00
parent 14560da7e4
commit 29b01d556d
7 changed files with 106 additions and 6 deletions

View File

@ -853,14 +853,20 @@ func (c *Config) BuildNameToCertificate() {
} }
} }
// writeKeyLog logs client random and master secret if logging was enabled by const (
// setting c.KeyLogWriter. keyLogLabelTLS12 = "CLIENT_RANDOM"
func (c *Config) writeKeyLog(clientRandom, masterSecret []byte) error { keyLogLabelClientHandshake = "CLIENT_HANDSHAKE_TRAFFIC_SECRET"
keyLogLabelServerHandshake = "SERVER_HANDSHAKE_TRAFFIC_SECRET"
keyLogLabelClientTraffic = "CLIENT_TRAFFIC_SECRET_0"
keyLogLabelServerTraffic = "SERVER_TRAFFIC_SECRET_0"
)
func (c *Config) writeKeyLog(label string, clientRandom, secret []byte) error {
if c.KeyLogWriter == nil { if c.KeyLogWriter == nil {
return nil return nil
} }
logLine := []byte(fmt.Sprintf("CLIENT_RANDOM %x %x\n", clientRandom, masterSecret)) logLine := []byte(fmt.Sprintf("%s %x %x\n", label, clientRandom, secret))
writerMutex.Lock() writerMutex.Lock()
_, err := c.KeyLogWriter.Write(logLine) _, err := c.KeyLogWriter.Write(logLine)

View File

@ -524,7 +524,7 @@ func (hs *clientHandshakeState) doFullHandshake() error {
} }
hs.masterSecret = masterFromPreMasterSecret(c.vers, hs.suite, preMasterSecret, hs.hello.random, hs.serverHello.random) hs.masterSecret = masterFromPreMasterSecret(c.vers, hs.suite, preMasterSecret, hs.hello.random, hs.serverHello.random)
if err := c.config.writeKeyLog(hs.hello.random, hs.masterSecret); err != nil { if err := c.config.writeKeyLog(keyLogLabelTLS12, hs.hello.random, hs.masterSecret); err != nil {
c.sendAlert(alertInternalError) c.sendAlert(alertInternalError)
return errors.New("tls: failed to write to key log: " + err.Error()) return errors.New("tls: failed to write to key log: " + err.Error())
} }

View File

@ -968,6 +968,49 @@ func TestKeyLog(t *testing.T) {
checkKeylogLine("server", serverBuf.String()) checkKeylogLine("server", serverBuf.String())
} }
func TestKeyLogTLS13(t *testing.T) {
var serverBuf, clientBuf bytes.Buffer
clientConfig := testConfig.Clone()
clientConfig.KeyLogWriter = &clientBuf
clientConfig.MaxVersion = VersionTLS13
serverConfig := testConfig.Clone()
serverConfig.KeyLogWriter = &serverBuf
serverConfig.MaxVersion = VersionTLS13
c, s := localPipe(t)
done := make(chan bool)
go func() {
defer close(done)
if err := Server(s, serverConfig).Handshake(); err != nil {
t.Errorf("server: %s", err)
return
}
s.Close()
}()
if err := Client(c, clientConfig).Handshake(); err != nil {
t.Fatalf("client: %s", err)
}
c.Close()
<-done
checkKeylogLines := func(side, loggedLines string) {
loggedLines = strings.TrimSpace(loggedLines)
lines := strings.Split(loggedLines, "\n")
if len(lines) != 4 {
t.Errorf("Expected the %s to log 4 lines, got %d", side, len(lines))
}
}
checkKeylogLines("client", clientBuf.String())
checkKeylogLines("server", serverBuf.String())
}
func TestHandshakeClientALPNMatch(t *testing.T) { func TestHandshakeClientALPNMatch(t *testing.T) {
config := testConfig.Clone() config := testConfig.Clone()
config.NextProtos = []string{"proto2", "proto1"} config.NextProtos = []string{"proto2", "proto1"}

View File

@ -269,6 +269,17 @@ func (hs *clientHandshakeStateTLS13) establishHandshakeKeys() error {
serverHandshakeTrafficLabel, hs.transcript) serverHandshakeTrafficLabel, hs.transcript)
c.in.setTrafficSecret(hs.suite, serverSecret) c.in.setTrafficSecret(hs.suite, serverSecret)
err := c.config.writeKeyLog(keyLogLabelClientHandshake, hs.hello.random, clientSecret)
if err != nil {
c.sendAlert(alertInternalError)
return err
}
err = c.config.writeKeyLog(keyLogLabelServerHandshake, hs.hello.random, serverSecret)
if err != nil {
c.sendAlert(alertInternalError)
return err
}
hs.masterSecret = hs.suite.extract(nil, hs.masterSecret = hs.suite.extract(nil,
hs.suite.deriveSecret(handshakeSecret, "derived", nil)) hs.suite.deriveSecret(handshakeSecret, "derived", nil))
@ -409,6 +420,17 @@ func (hs *clientHandshakeStateTLS13) readServerFinished() error {
serverApplicationTrafficLabel, hs.transcript) serverApplicationTrafficLabel, hs.transcript)
c.in.setTrafficSecret(hs.suite, serverSecret) c.in.setTrafficSecret(hs.suite, serverSecret)
err = c.config.writeKeyLog(keyLogLabelClientTraffic, hs.hello.random, hs.trafficSecret)
if err != nil {
c.sendAlert(alertInternalError)
return err
}
err = c.config.writeKeyLog(keyLogLabelServerTraffic, hs.hello.random, serverSecret)
if err != nil {
c.sendAlert(alertInternalError)
return err
}
c.ekm = hs.suite.exportKeyingMaterial(hs.masterSecret, hs.transcript) c.ekm = hs.suite.exportKeyingMaterial(hs.masterSecret, hs.transcript)
return nil return nil

View File

@ -528,7 +528,7 @@ func (hs *serverHandshakeState) doFullHandshake() error {
return err return err
} }
hs.masterSecret = masterFromPreMasterSecret(c.vers, hs.suite, preMasterSecret, hs.clientHello.random, hs.hello.random) hs.masterSecret = masterFromPreMasterSecret(c.vers, hs.suite, preMasterSecret, hs.clientHello.random, hs.hello.random)
if err := c.config.writeKeyLog(hs.clientHello.random, hs.masterSecret); err != nil { if err := c.config.writeKeyLog(keyLogLabelTLS12, hs.clientHello.random, hs.masterSecret); err != nil {
c.sendAlert(alertInternalError) c.sendAlert(alertInternalError)
return err return err
} }

View File

@ -63,6 +63,13 @@ func init() {
testConfig.Certificates[1].Certificate = [][]byte{testSNICertificate} testConfig.Certificates[1].Certificate = [][]byte{testSNICertificate}
testConfig.Certificates[1].PrivateKey = testRSAPrivateKey testConfig.Certificates[1].PrivateKey = testRSAPrivateKey
testConfig.BuildNameToCertificate() testConfig.BuildNameToCertificate()
if keyFile := os.Getenv("SSLKEYLOGFILE"); keyFile != "" {
f, err := os.OpenFile(keyFile, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
panic("failed to open SSLKEYLOGFILE: " + err.Error())
}
testConfig.KeyLogWriter = f
}
} }
func testClientHello(t *testing.T, serverConfig *Config, m handshakeMessage) { func testClientHello(t *testing.T, serverConfig *Config, m handshakeMessage) {

View File

@ -336,6 +336,17 @@ func (hs *serverHandshakeStateTLS13) sendServerParameters() error {
serverHandshakeTrafficLabel, hs.transcript) serverHandshakeTrafficLabel, hs.transcript)
c.out.setTrafficSecret(hs.suite, serverSecret) c.out.setTrafficSecret(hs.suite, serverSecret)
err := c.config.writeKeyLog(keyLogLabelClientHandshake, hs.clientHello.random, clientSecret)
if err != nil {
c.sendAlert(alertInternalError)
return err
}
err = c.config.writeKeyLog(keyLogLabelServerHandshake, hs.clientHello.random, serverSecret)
if err != nil {
c.sendAlert(alertInternalError)
return err
}
encryptedExtensions := new(encryptedExtensionsMsg) encryptedExtensions := new(encryptedExtensionsMsg)
if len(hs.clientHello.alpnProtocols) > 0 { if len(hs.clientHello.alpnProtocols) > 0 {
@ -426,6 +437,17 @@ func (hs *serverHandshakeStateTLS13) sendServerFinished() error {
serverApplicationTrafficLabel, hs.transcript) serverApplicationTrafficLabel, hs.transcript)
c.out.setTrafficSecret(hs.suite, serverSecret) c.out.setTrafficSecret(hs.suite, serverSecret)
err := c.config.writeKeyLog(keyLogLabelClientTraffic, hs.clientHello.random, hs.trafficSecret)
if err != nil {
c.sendAlert(alertInternalError)
return err
}
err = c.config.writeKeyLog(keyLogLabelServerTraffic, hs.clientHello.random, serverSecret)
if err != nil {
c.sendAlert(alertInternalError)
return err
}
c.ekm = hs.suite.exportKeyingMaterial(masterSecret, hs.transcript) c.ekm = hs.suite.exportKeyingMaterial(masterSecret, hs.transcript)
return nil return nil