Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for KeyLogWriter #344

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions config.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,14 @@ import (
"crypto/ed25519"
"crypto/tls"
"crypto/x509"
"io"
"time"

"github.com/pion/logging"
)

const keyLogLabelTLS12 = "CLIENT_RANDOM"

// Config is used to configure a DTLS client or server.
// After a Config is passed to a DTLS function it must not be modified.
type Config struct {
Expand Down Expand Up @@ -112,6 +115,14 @@ type Config struct {
// Packet with sequence number older than this value compared to the latest
// accepted packet will be discarded. (default is 64)
ReplayProtectionWindow int

// KeyLogWriter optionally specifies a destination for TLS master secrets
// in NSS key log format that can be used to allow external programs
// such as Wireshark to decrypt TLS connections.
// See https://developer.mozilla.org/en-US/docs/Mozilla/Projects/NSS/Key_Log_Format.
// Use of KeyLogWriter compromises security and should only be
// used for debugging.
KeyLogWriter io.Writer
}

func defaultConnectContextMaker() (context.Context, func()) {
Expand Down
1 change: 1 addition & 0 deletions conn.go
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,7 @@ func createConn(ctx context.Context, nextConn net.Conn, config *Config, isClient
retransmitInterval: workerInterval,
log: logger,
initialEpoch: 0,
keyLogWriter: config.KeyLogWriter,
}

var initialFlight flightVal
Expand Down
1 change: 1 addition & 0 deletions flight4handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ func flight4Parse(ctx context.Context, c flightConn, state *State, cache *handsh
if err := state.cipherSuite.Init(state.masterSecret, clientRandom[:], serverRandom[:], false); err != nil {
return 0, &alert.Alert{Level: alert.Fatal, Description: alert.InternalError}, err
}
cfg.writeKeyLog(keyLogLabelTLS12, clientRandom[:], state.masterSecret)
}

// Now, encrypted packets can be handled
Expand Down
3 changes: 3 additions & 0 deletions flight5handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -316,5 +316,8 @@ func initalizeCipherSuite(state *State, cache *handshakeCache, cfg *handshakeCon
if err = state.cipherSuite.Init(state.masterSecret, clientRandom[:], serverRandom[:], true); err != nil {
return &alert.Alert{Level: alert.Fatal, Description: alert.InternalError}, err
}

cfg.writeKeyLog(keyLogLabelTLS12, clientRandom[:], state.masterSecret)

return nil, nil
}
15 changes: 15 additions & 0 deletions handshaker.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import (
"context"
"crypto/tls"
"crypto/x509"
"fmt"
"io"
"sync"
"time"

Expand Down Expand Up @@ -105,6 +107,7 @@ type handshakeConfig struct {

onFlightState func(flightVal, handshakeState)
log logging.LeveledLogger
keyLogWriter io.Writer

initialEpoch uint16

Expand All @@ -119,6 +122,18 @@ type flightConn interface {
handleQueuedPackets(context.Context) error
}

func (c *handshakeConfig) writeKeyLog(label string, clientRandom, secret []byte) {
if c.keyLogWriter == nil {
return
}
c.mu.Lock()
defer c.mu.Unlock()
_, err := c.keyLogWriter.Write([]byte(fmt.Sprintf("%s %x %x\n", label, clientRandom, secret)))
if err != nil {
c.log.Debugf("failed to write key log file: %s", err)
}
}

func srvCliStr(isClient bool) string {
if isClient {
return "client"
Expand Down
22 changes: 22 additions & 0 deletions handshaker_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package dtls

import (
"bytes"
"context"
"crypto/tls"
"sync"
Expand All @@ -18,6 +19,27 @@ import (

const nonZeroRetransmitInterval = 100 * time.Millisecond

// Test that writes to the key log are in the correct format and only applies
// when a key log writer is given.
func TestWriteKeyLog(t *testing.T) {
var buf bytes.Buffer
cfg := handshakeConfig{
keyLogWriter: &buf,
}
cfg.writeKeyLog("LABEL", []byte{0xAA, 0xBB, 0xCC}, []byte{0xDD, 0xEE, 0xFF})

// Secrets follow the format <Label> <space> <ClientRandom> <space> <Secret>
// https://developer.mozilla.org/en-US/docs/Mozilla/Projects/NSS/Key_Log_Format
want := "LABEL aabbcc ddeeff\n"
if buf.String() != want {
t.Fatalf("Got %s want %s", buf.String(), want)
}

// no key log writer = no writes
cfg = handshakeConfig{}
cfg.writeKeyLog("LABEL", []byte{0xAA, 0xBB, 0xCC}, []byte{0xDD, 0xEE, 0xFF})
}

func TestHandshaker(t *testing.T) {
// Check for leaking routines
report := test.CheckRoutines(t)
Expand Down