diff --git a/common.go b/common.go index ddd3da5..6c86a71 100644 --- a/common.go +++ b/common.go @@ -853,14 +853,20 @@ func (c *Config) BuildNameToCertificate() { } } -// writeKeyLog logs client random and master secret if logging was enabled by -// setting c.KeyLogWriter. -func (c *Config) writeKeyLog(clientRandom, masterSecret []byte) error { +const ( + keyLogLabelTLS12 = "CLIENT_RANDOM" + 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 { 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() _, err := c.KeyLogWriter.Write(logLine) diff --git a/handshake_client.go b/handshake_client.go index 076a525..3092b1d 100644 --- a/handshake_client.go +++ b/handshake_client.go @@ -524,7 +524,7 @@ func (hs *clientHandshakeState) doFullHandshake() error { } 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) return errors.New("tls: failed to write to key log: " + err.Error()) } diff --git a/handshake_client_test.go b/handshake_client_test.go index dac7a23..745a12e 100644 --- a/handshake_client_test.go +++ b/handshake_client_test.go @@ -968,6 +968,49 @@ func TestKeyLog(t *testing.T) { 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) { config := testConfig.Clone() config.NextProtos = []string{"proto2", "proto1"} diff --git a/handshake_client_tls13.go b/handshake_client_tls13.go index 5f0cb6d..624ca4d 100644 --- a/handshake_client_tls13.go +++ b/handshake_client_tls13.go @@ -269,6 +269,17 @@ func (hs *clientHandshakeStateTLS13) establishHandshakeKeys() error { serverHandshakeTrafficLabel, hs.transcript) 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.suite.deriveSecret(handshakeSecret, "derived", nil)) @@ -409,6 +420,17 @@ func (hs *clientHandshakeStateTLS13) readServerFinished() error { serverApplicationTrafficLabel, hs.transcript) 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) return nil diff --git a/handshake_server.go b/handshake_server.go index d1f123c..61903bb 100644 --- a/handshake_server.go +++ b/handshake_server.go @@ -528,7 +528,7 @@ func (hs *serverHandshakeState) doFullHandshake() error { return err } 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) return err } diff --git a/handshake_server_test.go b/handshake_server_test.go index a02eae2..eb6bd2f 100644 --- a/handshake_server_test.go +++ b/handshake_server_test.go @@ -63,6 +63,13 @@ func init() { testConfig.Certificates[1].Certificate = [][]byte{testSNICertificate} testConfig.Certificates[1].PrivateKey = testRSAPrivateKey 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) { diff --git a/handshake_server_tls13.go b/handshake_server_tls13.go index 0ba74d5..9208cf9 100644 --- a/handshake_server_tls13.go +++ b/handshake_server_tls13.go @@ -336,6 +336,17 @@ func (hs *serverHandshakeStateTLS13) sendServerParameters() error { serverHandshakeTrafficLabel, hs.transcript) 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) if len(hs.clientHello.alpnProtocols) > 0 { @@ -426,6 +437,17 @@ func (hs *serverHandshakeStateTLS13) sendServerFinished() error { serverApplicationTrafficLabel, hs.transcript) 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) return nil