tris: implement SSLKEYLOGFILE for TLS 1.3 server

This makes it easier to validate the handshake contents using Wireshark.
Este commit está contenido en:
Peter Wu 2017-09-18 16:50:43 +01:00
padre 6f580251ca
commit 3107d575a8
Se han modificado 5 ficheros con 36 adiciones y 9 borrados

27
13.go
Ver fichero

@ -45,12 +45,20 @@ type keySchedule13 struct {
transcriptHash hash.Hash // uses the cipher suite hash algo
secret []byte // Current secret as used for Derive-Secret
handshakeCtx []byte // cached handshake context, invalidated on updates.
clientRandom []byte // Used for keylogging, nil if keylogging is disabled.
config *Config // Used for KeyLogWriter callback, nil if keylogging is disabled.
}
func newKeySchedule13(suite *cipherSuite) *keySchedule13 {
func newKeySchedule13(suite *cipherSuite, config *Config, clientRandom []byte) *keySchedule13 {
if config.KeyLogWriter == nil {
clientRandom = nil
config = nil
}
return &keySchedule13{
suite: suite,
transcriptHash: hashForSuite(suite).New(),
clientRandom: clientRandom,
config: config,
}
}
@ -68,20 +76,25 @@ func (ks *keySchedule13) write(data []byte) {
ks.transcriptHash.Write(data)
}
func (ks *keySchedule13) getLabel(secretLabel secretLabel) (label string) {
func (ks *keySchedule13) getLabel(secretLabel secretLabel) (label, keylogType string) {
switch secretLabel {
case secretResumptionPskBinder:
label = "resumption psk binder key"
case secretEarlyClient:
label = "client early traffic secret"
keylogType = "CLIENT_EARLY_TRAFFIC_SECRET"
case secretHandshakeClient:
label = "client handshake traffic secret"
keylogType = "CLIENT_HANDSHAKE_TRAFFIC_SECRET"
case secretHandshakeServer:
label = "server handshake traffic secret"
keylogType = "SERVER_HANDSHAKE_TRAFFIC_SECRET"
case secretApplicationClient:
label = "client application traffic secret"
keylogType = "CLIENT_TRAFFIC_SECRET_0"
case secretApplicationServer:
label = "server application traffic secret"
keylogType = "SERVER_TRAFFIC_SECRET_0"
case secretResumption:
label = "resumption master secret"
}
@ -90,12 +103,16 @@ func (ks *keySchedule13) getLabel(secretLabel secretLabel) (label string) {
// deriveSecret returns the secret derived from the handshake context and label.
func (ks *keySchedule13) deriveSecret(secretLabel secretLabel) []byte {
label := ks.getLabel(secretLabel)
label, keylogType := ks.getLabel(secretLabel)
if ks.handshakeCtx == nil {
ks.handshakeCtx = ks.transcriptHash.Sum(nil)
}
hash := hashForSuite(ks.suite)
return hkdfExpandLabel(hash, ks.secret, ks.handshakeCtx, label, hash.Size())
secret := hkdfExpandLabel(hash, ks.secret, ks.handshakeCtx, label, hash.Size())
if keylogType != "" && ks.config != nil {
ks.config.writeKeyLog(keylogType, ks.clientRandom, secret)
}
return secret
}
func (ks *keySchedule13) prepareCipher(secretLabel secretLabel) (interface{}, []byte) {
@ -146,7 +163,7 @@ CurvePreferenceLoop:
hash := hashForSuite(hs.suite)
hashSize := hash.Size()
hs.keySchedule = newKeySchedule13(hs.suite)
hs.keySchedule = newKeySchedule13(hs.suite, config, hs.clientHello.random)
// Check for PSK and update key schedule with new early secret key
isResumed, pskAlert := hs.checkPSK()

Ver fichero

@ -4,6 +4,7 @@ import (
"crypto/tls"
"encoding/hex"
"fmt"
"io"
"log"
"net/http"
"os"
@ -30,12 +31,21 @@ func startServer(addr string, rsa, offer0RTT, accept0RTT bool) {
if offer0RTT {
Max0RTTDataSize = 100 * 1024
}
var keyLogWriter io.Writer
if keyLogFile := os.Getenv("SSLKEYLOGFILE"); keyLogFile != "" {
keyLogWriter, err = os.OpenFile(keyLogFile, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0600)
if err != nil {
log.Fatalf("Cannot open keylog file: %v", err)
}
log.Println("Enabled keylog")
}
s := &http.Server{
Addr: addr,
TLSConfig: &tls.Config{
Certificates: []tls.Certificate{cert},
Max0RTTDataSize: Max0RTTDataSize,
Accept0RTTData: accept0RTT,
KeyLogWriter: keyLogWriter,
GetConfigForClient: func(*tls.ClientHelloInfo) (*tls.Config, error) {
// If we send the first flight too fast, NSS sends empty early data.
time.Sleep(500 * time.Millisecond)

Ver fichero

@ -907,12 +907,12 @@ 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 {
func (c *Config) writeKeyLog(what string, clientRandom, masterSecret []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", what, clientRandom, masterSecret))
writerMutex.Lock()
_, err := c.KeyLogWriter.Write(logLine)

Ver fichero

@ -469,7 +469,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("CLIENT_RANDOM", hs.hello.random, hs.masterSecret); err != nil {
c.sendAlert(alertInternalError)
return errors.New("tls: failed to write to key log: " + err.Error())
}

Ver fichero

@ -573,7 +573,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("CLIENT_RANDOM", hs.clientHello.random, hs.masterSecret); err != nil {
c.sendAlert(alertInternalError)
return err
}