runner: Don't use the buffer in TLS 1.3.

All the comments say the buffer is only needed in TLS 1.2, but this
doesn't match the code. The code uses the buffer in one place, for ECH,
to avoid copying a hash.Hash. Go does support this, albeit in a *very*
roundabout way.

This is ugly but means we can now properly drop the handshake buffer in
TLS 1.3.

Change-Id: I4a1559a64fcb98ccfbab54de99402fe6f62725a1
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/46627
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 2ba29c1..478d402 100644
--- a/ssl/test/runner/prf.go
+++ b/ssl/test/runner/prf.go
@@ -10,11 +10,36 @@
 	"crypto/md5"
 	"crypto/sha1"
 	"crypto/sha256"
+	"encoding"
 	"hash"
 
 	"golang.org/x/crypto/hkdf"
 )
 
+// copyHash returns a copy of |h|, which must be an instance of |hashType|.
+func copyHash(h hash.Hash, hash crypto.Hash) hash.Hash {
+	// While hash.Hash is not copyable, the documentation says all standard
+	// library hash.Hash implementations implement BinaryMarshaler and
+	// BinaryUnmarshaler interfaces.
+	m, ok := h.(encoding.BinaryMarshaler)
+	if !ok {
+		panic("hash did not implement encoding.BinaryMarshaler")
+	}
+	data, err := m.MarshalBinary()
+	if err != nil {
+		panic(err)
+	}
+	ret := hash.New()
+	u, ok := ret.(encoding.BinaryUnmarshaler)
+	if !ok {
+		panic("hash did not implement BinaryUnmarshaler")
+	}
+	if err := u.UnmarshalBinary(data); err != nil {
+		panic(err)
+	}
+	return ret
+}
+
 // Split a premaster secret in two as specified in RFC 4346, section 5.
 func splitPreMasterSecret(secret []byte) (s1, s2 []byte) {
 	s1 = secret[0 : (len(secret)+1)/2]
@@ -384,8 +409,7 @@
 // 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.suite.hash().New()
-	hashPeek.Write(h.buffer)
+	hashPeek := copyHash(h.hash, h.suite.hash())
 	hashPeek.Write(extraMessages)
 	return hkdfExpandLabel(h.suite.hash(), h.secret, label, hashPeek.Sum(nil), h.hash.Size())
 }