tris: add new key schedule implementation
In order to reduce repetitive complexity (extract handshake context, pass the right secrets around to calculate a secret and build a cipher), create a new type that tracks the hash type, the handshake context and intermediate secrets. Advantages: facilitates reuse between client and server code, makes it easier to update labels for draft-19, makes it easier to add central KeyLogWriter functionality.
This commit is contained in:
parent
079992e500
commit
9f9f06de80
78
13.go
78
13.go
@ -28,6 +28,84 @@ import (
|
|||||||
// server sends to a TLS 1.3 client, who will use each only once.
|
// server sends to a TLS 1.3 client, who will use each only once.
|
||||||
const numSessionTickets = 2
|
const numSessionTickets = 2
|
||||||
|
|
||||||
|
type secretLabel int
|
||||||
|
|
||||||
|
const (
|
||||||
|
secretResumptionPskBinder secretLabel = iota
|
||||||
|
secretEarlyClient
|
||||||
|
secretHandshakeClient
|
||||||
|
secretHandshakeServer
|
||||||
|
secretApplicationClient
|
||||||
|
secretApplicationServer
|
||||||
|
secretResumption
|
||||||
|
)
|
||||||
|
|
||||||
|
type keySchedule13 struct {
|
||||||
|
suite *cipherSuite
|
||||||
|
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.
|
||||||
|
}
|
||||||
|
|
||||||
|
func newKeySchedule13(suite *cipherSuite) *keySchedule13 {
|
||||||
|
return &keySchedule13{
|
||||||
|
suite: suite,
|
||||||
|
transcriptHash: hashForSuite(suite).New(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// setSecret sets the early/handshake/master secret based on the given secret
|
||||||
|
// (IKM). The salt is based on previous secrets (nil for the early secret).
|
||||||
|
func (ks *keySchedule13) setSecret(secret []byte) {
|
||||||
|
hash := hashForSuite(ks.suite)
|
||||||
|
salt := ks.secret
|
||||||
|
ks.secret = hkdfExtract(hash, secret, salt)
|
||||||
|
}
|
||||||
|
|
||||||
|
// write appends the data to the transcript hash context.
|
||||||
|
func (ks *keySchedule13) write(data []byte) {
|
||||||
|
ks.handshakeCtx = nil
|
||||||
|
ks.transcriptHash.Write(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ks *keySchedule13) getLabel(secretLabel secretLabel) (label string) {
|
||||||
|
switch secretLabel {
|
||||||
|
case secretResumptionPskBinder:
|
||||||
|
label = "resumption psk binder key"
|
||||||
|
case secretEarlyClient:
|
||||||
|
label = "client early traffic secret"
|
||||||
|
case secretHandshakeClient:
|
||||||
|
label = "client handshake traffic secret"
|
||||||
|
case secretHandshakeServer:
|
||||||
|
label = "server handshake traffic secret"
|
||||||
|
case secretApplicationClient:
|
||||||
|
label = "client application traffic secret"
|
||||||
|
case secretApplicationServer:
|
||||||
|
label = "server application traffic secret"
|
||||||
|
case secretResumption:
|
||||||
|
label = "resumption master secret"
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// deriveSecret returns the secret derived from the handshake context and label.
|
||||||
|
func (ks *keySchedule13) deriveSecret(secretLabel secretLabel) []byte {
|
||||||
|
label := 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())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ks *keySchedule13) prepareCipher(secretLabel secretLabel) (interface{}, []byte) {
|
||||||
|
trafficSecret := ks.deriveSecret(secretLabel)
|
||||||
|
hash := hashForSuite(ks.suite)
|
||||||
|
key := hkdfExpandLabel(hash, trafficSecret, nil, "key", ks.suite.keyLen)
|
||||||
|
iv := hkdfExpandLabel(hash, trafficSecret, nil, "iv", 12)
|
||||||
|
return ks.suite.aead(key, iv), trafficSecret
|
||||||
|
}
|
||||||
|
|
||||||
func (hs *serverHandshakeState) doTLS13Handshake() error {
|
func (hs *serverHandshakeState) doTLS13Handshake() error {
|
||||||
config := hs.c.config
|
config := hs.c.config
|
||||||
c := hs.c
|
c := hs.c
|
||||||
|
Loading…
Reference in New Issue
Block a user