summaryrefslogtreecommitdiff
path: root/ssl/test/runner/prf.go
diff options
context:
space:
mode:
Diffstat (limited to 'ssl/test/runner/prf.go')
-rw-r--r--ssl/test/runner/prf.go66
1 files changed, 54 insertions, 12 deletions
diff --git a/ssl/test/runner/prf.go b/ssl/test/runner/prf.go
index 991196f..6d0db97 100644
--- a/ssl/test/runner/prf.go
+++ b/ssl/test/runner/prf.go
@@ -120,6 +120,8 @@ var masterSecretLabel = []byte("master secret")
var keyExpansionLabel = []byte("key expansion")
var clientFinishedLabel = []byte("client finished")
var serverFinishedLabel = []byte("server finished")
+var channelIDLabel = []byte("TLS Channel ID signature\x00")
+var channelIDResumeLabel = []byte("Resumption\x00")
func prfForVersion(version uint16, suite *cipherSuite) func(result, secret, label, seed []byte) {
switch version {
@@ -180,9 +182,9 @@ func newFinishedHash(version uint16, cipherSuite *cipherSuite) finishedHash {
newHash = sha512.New384
}
- return finishedHash{newHash(), newHash(), nil, nil, version, prf12(newHash)}
+ return finishedHash{newHash(), newHash(), nil, nil, []byte{}, version, prf12(newHash)}
}
- return finishedHash{sha1.New(), sha1.New(), md5.New(), md5.New(), version, prf10}
+ return finishedHash{sha1.New(), sha1.New(), md5.New(), md5.New(), []byte{}, version, prf10}
}
// A finishedHash calculates the hash of a set of handshake messages suitable
@@ -195,11 +197,15 @@ type finishedHash struct {
clientMD5 hash.Hash
serverMD5 hash.Hash
+ // In TLS 1.2 (and SSL 3 for implementation convenience), a
+ // full buffer is required.
+ buffer []byte
+
version uint16
prf func(result, secret, label, seed []byte)
}
-func (h finishedHash) Write(msg []byte) (n int, err error) {
+func (h *finishedHash) Write(msg []byte) (n int, err error) {
h.client.Write(msg)
h.server.Write(msg)
@@ -207,14 +213,19 @@ func (h finishedHash) Write(msg []byte) (n int, err error) {
h.clientMD5.Write(msg)
h.serverMD5.Write(msg)
}
+
+ if h.buffer != nil {
+ h.buffer = append(h.buffer, msg...)
+ }
+
return len(msg), nil
}
// finishedSum30 calculates the contents of the verify_data member of a SSLv3
// Finished message given the MD5 and SHA1 hashes of a set of handshake
// messages.
-func finishedSum30(md5, sha1 hash.Hash, masterSecret []byte, magic [4]byte) []byte {
- md5.Write(magic[:])
+func finishedSum30(md5, sha1 hash.Hash, masterSecret []byte, magic []byte) []byte {
+ md5.Write(magic)
md5.Write(masterSecret)
md5.Write(ssl30Pad1[:])
md5Digest := md5.Sum(nil)
@@ -225,7 +236,7 @@ func finishedSum30(md5, sha1 hash.Hash, masterSecret []byte, magic [4]byte) []by
md5.Write(md5Digest)
md5Digest = md5.Sum(nil)
- sha1.Write(magic[:])
+ sha1.Write(magic)
sha1.Write(masterSecret)
sha1.Write(ssl30Pad1[:40])
sha1Digest := sha1.Sum(nil)
@@ -249,7 +260,7 @@ var ssl3ServerFinishedMagic = [4]byte{0x53, 0x52, 0x56, 0x52}
// Finished message.
func (h finishedHash) clientSum(masterSecret []byte) []byte {
if h.version == VersionSSL30 {
- return finishedSum30(h.clientMD5, h.client, masterSecret, ssl3ClientFinishedMagic)
+ return finishedSum30(h.clientMD5, h.client, masterSecret, ssl3ClientFinishedMagic[:])
}
out := make([]byte, finishedVerifyLength)
@@ -269,7 +280,7 @@ func (h finishedHash) clientSum(masterSecret []byte) []byte {
// Finished message.
func (h finishedHash) serverSum(masterSecret []byte) []byte {
if h.version == VersionSSL30 {
- return finishedSum30(h.serverMD5, h.server, masterSecret, ssl3ServerFinishedMagic)
+ return finishedSum30(h.serverMD5, h.server, masterSecret, ssl3ServerFinishedMagic[:])
}
out := make([]byte, finishedVerifyLength)
@@ -290,7 +301,7 @@ func (h finishedHash) serverSum(masterSecret []byte) []byte {
func (h finishedHash) selectClientCertSignatureAlgorithm(serverList []signatureAndHash, sigType uint8) (signatureAndHash, error) {
if h.version < VersionTLS12 {
// Nothing to negotiate before TLS 1.2.
- return signatureAndHash{sigType, 0}, nil
+ return signatureAndHash{signature: sigType}, nil
}
for _, v := range serverList {
@@ -303,13 +314,24 @@ func (h finishedHash) selectClientCertSignatureAlgorithm(serverList []signatureA
// hashForClientCertificate returns a digest, hash function, and TLS 1.2 hash
// id suitable for signing by a TLS client certificate.
-func (h finishedHash) hashForClientCertificate(signatureAndHash signatureAndHash) ([]byte, crypto.Hash, error) {
+func (h finishedHash) hashForClientCertificate(signatureAndHash signatureAndHash, masterSecret []byte) ([]byte, crypto.Hash, error) {
+ if h.version == VersionSSL30 {
+ if signatureAndHash.signature != signatureRSA {
+ return nil, 0, errors.New("tls: unsupported signature type for client certificate")
+ }
+
+ md5Hash := md5.New()
+ md5Hash.Write(h.buffer)
+ sha1Hash := sha1.New()
+ sha1Hash.Write(h.buffer)
+ return finishedSum30(md5Hash, sha1Hash, masterSecret, nil), crypto.MD5SHA1, nil
+ }
if h.version >= VersionTLS12 {
if signatureAndHash.hash != hashSHA256 {
return nil, 0, errors.New("tls: unsupported hash function for client certificate")
}
- digest := h.server.Sum(nil)
- return digest, crypto.SHA256, nil
+ digest := sha256.Sum256(h.buffer)
+ return digest[:], crypto.SHA256, nil
}
if signatureAndHash.signature == signatureECDSA {
digest := h.server.Sum(nil)
@@ -321,3 +343,23 @@ func (h finishedHash) hashForClientCertificate(signatureAndHash signatureAndHash
digest = h.server.Sum(digest)
return digest, crypto.MD5SHA1, nil
}
+
+// hashForChannelID returns the hash to be signed for TLS Channel
+// ID. If a resumption, resumeHash has the previous handshake
+// hash. Otherwise, it is nil.
+func (h finishedHash) hashForChannelID(resumeHash []byte) []byte {
+ hash := sha256.New()
+ hash.Write(channelIDLabel)
+ if resumeHash != nil {
+ hash.Write(channelIDResumeLabel)
+ hash.Write(resumeHash)
+ }
+ hash.Write(h.server.Sum(nil))
+ return hash.Sum(nil)
+}
+
+// discardHandshakeBuffer is called when there is no more need to
+// buffer the entirety of the handshake messages.
+func (h *finishedHash) discardHandshakeBuffer() {
+ h.buffer = nil
+}