]> Cypherpunks repositories - gostls13.git/commitdiff
crypto/tls: implement TLS 1.3 KeyLogWriter support
authorFilippo Valsorda <filippo@golang.org>
Sat, 3 Nov 2018 22:13:05 +0000 (18:13 -0400)
committerFilippo Valsorda <filippo@golang.org>
Mon, 12 Nov 2018 20:42:20 +0000 (20:42 +0000)
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>
src/crypto/tls/common.go
src/crypto/tls/handshake_client.go
src/crypto/tls/handshake_client_test.go
src/crypto/tls/handshake_client_tls13.go
src/crypto/tls/handshake_server.go
src/crypto/tls/handshake_server_test.go
src/crypto/tls/handshake_server_tls13.go

index ddd3da5216acfcbef1b4317e58e71296577409e4..6c86a71363739b9983f6ea30a88b44a49844924d 100644 (file)
@@ -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)
index 076a525bf8936a46b8b17e763d092dec50c4df9e..3092b1d671d9db00c0d43369ee754cca5d550ee2 100644 (file)
@@ -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())
        }
index dac7a2338e5578708ee0b102f54dc704642844e0..745a12e268e57e279e7246e094f1d360a0aa8a0e 100644 (file)
@@ -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"}
index 5f0cb6d22b7b4ce9a48d68fa3c9c23ade4900b7b..624ca4dacbe98934fafdbd72d50f512657847154 100644 (file)
@@ -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
index d1f123cec38fc5b8773dcda3771c233f843cd6fb..61903bb03adc8cfa6cc3d853c1ccc1e299d9f997 100644 (file)
@@ -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
        }
index a02eae24b3aa157ded7c89d990424c2900de9479..eb6bd2f13adab1d0e952df0a780b8109c271382f 100644 (file)
@@ -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) {
index 0ba74d5ff8f516fb006d93bd663176679e067226..9208cf953964a3a41bbf4b45b379103278cb7b5a 100644 (file)
@@ -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