crypto/tls: add KeyLogWriter for debugging

Add support for writing TLS client random and master secret
in NSS key log format.

https://developer.mozilla.org/en-US/docs/Mozilla/Projects/NSS/Key_Log_Format

Normally this is enabled by a developer debugging TLS based
applications, especially HTTP/2, by setting the KeyLogWriter
to an open file. The keys negotiated in handshake are then
logged and can be used to decrypt TLS sessions e.g. in Wireshark.

Applications may choose to add support similar to NSS where this
is enabled by environment variable, but no such mechanism is
built in to Go. Instead each application must explicitly enable.

Fixes #13057.

Change-Id: If6edd2d58999903e8390b1674ba4257ecc747ae1
Reviewed-on: https://go-review.googlesource.com/27434
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
This commit is contained in:
Joonas Kuorilehto 2016-08-20 14:41:42 +03:00 committed by Brad Fitzpatrick
parent 3427f16642
commit 320bd562cb
9 changed files with 281 additions and 0 deletions

View file

@ -747,6 +747,43 @@ func TestHandshakeServerECDHEECDSAAES(t *testing.T) {
runServerTestTLS12(t, test)
}
func TestHandshakeServerKeyLog(t *testing.T) {
config := testConfig.clone()
buf := &bytes.Buffer{}
config.KeyLogWriter = buf
test := &serverTest{
name: "KeyLogWriter",
command: []string{"openssl", "s_client"},
config: config,
validate: func(state ConnectionState) error {
var format, clientRandom, masterSecret string
if _, err := fmt.Fscanf(buf, "%s %s %s\n", &format, &clientRandom, &masterSecret); err != nil {
return fmt.Errorf("failed to parse KeyLogWriter: " + err.Error())
}
if format != "CLIENT_RANDOM" {
return fmt.Errorf("got key log format %q, wanted CLIENT_RANDOM", format)
}
// Both clientRandom and masterSecret are unpredictable in server handshake test
if len(clientRandom) != 64 {
return fmt.Errorf("got wrong length client random in key log %v, wanted 64", len(clientRandom))
}
if len(masterSecret) != 96 {
return fmt.Errorf("got wrong length master secret in key log %v, want 96", len(masterSecret))
}
// buf should contain no more lines
var trailingGarbage string
if _, err := fmt.Fscanln(buf, &trailingGarbage); err == nil {
return fmt.Errorf("expected exactly one key in log, got trailing garbage %q", trailingGarbage)
}
return nil
},
}
runServerTestTLS10(t, test)
}
func TestHandshakeServerALPN(t *testing.T) {
config := testConfig.clone()
config.NextProtos = []string{"proto1", "proto2"}