runner: Don't maintain two copies of the same transcript hash.
The 'client' and 'server' halves are remnants of SSL 3.0 and Go
(originally) lacking a way to clone hash.Hash. The Go limitation meant
that computing SSL 3.0's proto-HMAC construction mutated the running
hash on Finished, so crypto/tls just maintained two of them.
Without SSL 3.0, this is no longer needed. That, however, leaves us with
having both a crypto.Hash and a hash.Hash, and both can't be named
'hash'. I stepped around this by storing the cipher suite itself and
using cipherSuite.hash().
Change-Id: Ia38880ae446949baa2181d33136c748cf5374664
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/46626
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
diff --git a/ssl/test/runner/prf.go b/ssl/test/runner/prf.go
index 66674c0..2ba29c1 100644
--- a/ssl/test/runner/prf.go
+++ b/ssl/test/runner/prf.go
@@ -148,35 +148,28 @@
}
func newFinishedHash(wireVersion uint16, isDTLS bool, cipherSuite *cipherSuite) finishedHash {
- var ret finishedHash
-
version, ok := wireToVersion(wireVersion, isDTLS)
if !ok {
panic("unknown version")
}
+ var ret finishedHash
if version >= VersionTLS12 {
- ret.hash = cipherSuite.hash()
-
- ret.client = ret.hash.New()
- ret.server = ret.hash.New()
+ ret.hash = cipherSuite.hash().New()
if version == VersionTLS12 {
- ret.prf = prf12(ret.hash.New)
+ ret.prf = prf12(cipherSuite.hash().New)
} else {
ret.secret = make([]byte, ret.hash.Size())
}
} else {
- ret.hash = crypto.MD5SHA1
-
- ret.client = sha1.New()
- ret.server = sha1.New()
- ret.clientMD5 = md5.New()
- ret.serverMD5 = md5.New()
+ ret.hash = sha1.New()
+ ret.md5 = md5.New()
ret.prf = prf10
}
+ ret.suite = cipherSuite
ret.buffer = []byte{}
ret.version = version
ret.wireVersion = wireVersion
@@ -187,14 +180,15 @@
// A finishedHash calculates the hash of a set of handshake messages suitable
// for including in a Finished message.
type finishedHash struct {
- hash crypto.Hash
+ suite *cipherSuite
- client hash.Hash
- server hash.Hash
+ // hash maintains a running hash of handshake messages. In TLS 1.2 and up,
+ // the hash is determined from suite.hash(). In TLS 1.0 and 1.1, this is the
+ // SHA-1 half of the MD5/SHA-1 concatenation.
+ hash hash.Hash
- // Prior to TLS 1.2, an additional MD5 hash is required.
- clientMD5 hash.Hash
- serverMD5 hash.Hash
+ // md5 is the MD5 half of the TLS 1.0 and 1.1 MD5/SHA1 concatenation.
+ md5 hash.Hash
// In TLS 1.2, a full buffer is required.
buffer []byte
@@ -213,8 +207,7 @@
data.addU8(typeMessageHash)
data.addU24(h.hash.Size())
data.addBytes(h.Sum())
- h.client = h.hash.New()
- h.server = h.hash.New()
+ h.hash = h.suite.hash().New()
if h.buffer != nil {
h.buffer = []byte{}
}
@@ -223,12 +216,10 @@
}
func (h *finishedHash) Write(msg []byte) (n int, err error) {
- h.client.Write(msg)
- h.server.Write(msg)
+ h.hash.Write(msg)
if h.version < VersionTLS12 {
- h.clientMD5.Write(msg)
- h.serverMD5.Write(msg)
+ h.md5.Write(msg)
}
if h.buffer != nil {
@@ -259,12 +250,12 @@
func (h finishedHash) Sum() []byte {
if h.version >= VersionTLS12 {
- return h.client.Sum(nil)
+ return h.hash.Sum(nil)
}
out := make([]byte, 0, md5.Size+sha1.Size)
- out = h.clientMD5.Sum(out)
- return h.client.Sum(out)
+ out = h.md5.Sum(out)
+ return h.hash.Sum(out)
}
// clientSum returns the contents of the verify_data member of a client's
@@ -276,8 +267,8 @@
return out
}
- clientFinishedKey := hkdfExpandLabel(h.hash, baseKey, finishedLabel, nil, h.hash.Size())
- finishedHMAC := hmac.New(h.hash.New, clientFinishedKey)
+ clientFinishedKey := hkdfExpandLabel(h.suite.hash(), baseKey, finishedLabel, nil, h.hash.Size())
+ finishedHMAC := hmac.New(h.suite.hash().New, clientFinishedKey)
finishedHMAC.Write(h.appendContextHashes(nil))
return finishedHMAC.Sum(nil)
}
@@ -291,8 +282,8 @@
return out
}
- serverFinishedKey := hkdfExpandLabel(h.hash, baseKey, finishedLabel, nil, h.hash.Size())
- finishedHMAC := hmac.New(h.hash.New, serverFinishedKey)
+ serverFinishedKey := hkdfExpandLabel(h.suite.hash(), baseKey, finishedLabel, nil, h.hash.Size())
+ finishedHMAC := hmac.New(h.suite.hash().New, serverFinishedKey)
finishedHMAC.Write(h.appendContextHashes(nil))
return finishedHMAC.Sum(nil)
}
@@ -325,11 +316,11 @@
// addEntropy incorporates ikm into the running TLS 1.3 secret with HKDF-Expand.
func (h *finishedHash) addEntropy(ikm []byte) {
- h.secret = hkdf.Extract(h.hash.New, ikm, h.secret)
+ h.secret = hkdf.Extract(h.suite.hash().New, ikm, h.secret)
}
func (h *finishedHash) nextSecret() {
- h.secret = hkdfExpandLabel(h.hash, h.secret, []byte("derived"), h.hash.New().Sum(nil), h.hash.Size())
+ h.secret = hkdfExpandLabel(h.suite.hash(), h.secret, []byte("derived"), h.suite.hash().New().Sum(nil), h.hash.Size())
}
// hkdfExpandLabel implements TLS 1.3's HKDF-Expand-Label function, as defined
@@ -362,7 +353,7 @@
// appendContextHashes returns the concatenation of the handshake hash and the
// resumption context hash, as used in TLS 1.3.
func (h *finishedHash) appendContextHashes(b []byte) []byte {
- b = h.client.Sum(b)
+ b = h.hash.Sum(b)
return b
}
@@ -386,17 +377,17 @@
// deriveSecret implements TLS 1.3's Derive-Secret function, as defined in
// section 7.1 of draft ietf-tls-tls13-16.
func (h *finishedHash) deriveSecret(label []byte) []byte {
- return hkdfExpandLabel(h.hash, h.secret, label, h.appendContextHashes(nil), h.hash.Size())
+ return hkdfExpandLabel(h.suite.hash(), h.secret, label, h.appendContextHashes(nil), h.hash.Size())
}
// deriveSecretPeek is the same as deriveSecret, but it enables the caller to
// tentatively append messages to the transcript. The |extraMessages| parameter
// contains the bytes of these tentative messages.
func (h *finishedHash) deriveSecretPeek(label []byte, extraMessages []byte) []byte {
- hashPeek := h.hash.New()
+ hashPeek := h.suite.hash().New()
hashPeek.Write(h.buffer)
hashPeek.Write(extraMessages)
- return hkdfExpandLabel(h.hash, h.secret, label, hashPeek.Sum(nil), h.hash.Size())
+ return hkdfExpandLabel(h.suite.hash(), h.secret, label, hashPeek.Sum(nil), h.hash.Size())
}
// The following are context strings for CertificateVerify in TLS 1.3.