tris: implement SSLKEYLOGFILE for TLS 1.3 server
This makes it easier to validate the handshake contents using Wireshark.
Este commit está contenido en:
padre
6f580251ca
commit
3107d575a8
27
13.go
27
13.go
@ -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()
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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())
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
Cargando…
Referencia en una nueva incidencia
Block a user