1 // Copyright 2009 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
18 // Split a premaster secret in two as specified in RFC 4346, section 5.
19 func splitPreMasterSecret(secret []byte) (s1, s2 []byte) {
20 s1 = secret[0 : (len(secret)+1)/2]
21 s2 = secret[len(secret)/2:]
25 // pHash implements the P_hash function, as defined in RFC 4346, section 5.
26 func pHash(result, secret, seed []byte, hash func() hash.Hash) {
27 h := hmac.New(hash, secret)
38 if j+todo > len(result) {
39 todo = len(result) - j
41 copy(result[j:j+todo], b)
50 // prf10 implements the TLS 1.0 pseudo-random function, as defined in RFC 2246, section 5.
51 func prf10(result, secret, label, seed []byte) {
55 labelAndSeed := make([]byte, len(label)+len(seed))
56 copy(labelAndSeed, label)
57 copy(labelAndSeed[len(label):], seed)
59 s1, s2 := splitPreMasterSecret(secret)
60 pHash(result, s1, labelAndSeed, hashMD5)
61 result2 := make([]byte, len(result))
62 pHash(result2, s2, labelAndSeed, hashSHA1)
64 for i, b := range result2 {
69 // prf12 implements the TLS 1.2 pseudo-random function, as defined in RFC 5246, section 5.
70 func prf12(hashFunc func() hash.Hash) func(result, secret, label, seed []byte) {
71 return func(result, secret, label, seed []byte) {
72 labelAndSeed := make([]byte, len(label)+len(seed))
73 copy(labelAndSeed, label)
74 copy(labelAndSeed[len(label):], seed)
76 pHash(result, secret, labelAndSeed, hashFunc)
80 // prf30 implements the SSL 3.0 pseudo-random function, as defined in
81 // www.mozilla.org/projects/security/pki/nss/ssl/draft302.txt section 6.
82 func prf30(result, secret, label, seed []byte) {
83 hashSHA1 := sha1.New()
88 // RFC5246 section 6.3 says that the largest PRF output needed is 128
89 // bytes. Since no more ciphersuites will be added to SSLv3, this will
90 // remain true. Each iteration gives us 16 bytes so 10 iterations will
93 for done < len(result) {
94 for j := 0; j <= i; j++ {
99 hashSHA1.Write(b[:i+1])
100 hashSHA1.Write(secret)
102 digest := hashSHA1.Sum(nil)
105 hashMD5.Write(secret)
106 hashMD5.Write(digest)
108 done += copy(result[done:], hashMD5.Sum(nil))
114 tlsRandomLength = 32 // Length of a random nonce in TLS 1.1.
115 masterSecretLength = 48 // Length of a master secret in TLS 1.1.
116 finishedVerifyLength = 12 // Length of verify_data in a Finished message.
119 var masterSecretLabel = []byte("master secret")
120 var keyExpansionLabel = []byte("key expansion")
121 var clientFinishedLabel = []byte("client finished")
122 var serverFinishedLabel = []byte("server finished")
124 func prfForVersion(version uint16, suite *cipherSuite) func(result, secret, label, seed []byte) {
128 case VersionTLS10, VersionTLS11:
131 if suite.flags&suiteSHA384 != 0 {
132 return prf12(sha512.New384)
134 return prf12(sha256.New)
136 panic("unknown version")
140 // masterFromPreMasterSecret generates the master secret from the pre-master
141 // secret. See http://tools.ietf.org/html/rfc5246#section-8.1
142 func masterFromPreMasterSecret(version uint16, suite *cipherSuite, preMasterSecret, clientRandom, serverRandom []byte) []byte {
143 var seed [tlsRandomLength * 2]byte
144 copy(seed[0:len(clientRandom)], clientRandom)
145 copy(seed[len(clientRandom):], serverRandom)
146 masterSecret := make([]byte, masterSecretLength)
147 prfForVersion(version, suite)(masterSecret, preMasterSecret, masterSecretLabel, seed[0:])
151 // keysFromMasterSecret generates the connection keys from the master
152 // secret, given the lengths of the MAC key, cipher key and IV, as defined in
153 // RFC 2246, section 6.3.
154 func keysFromMasterSecret(version uint16, suite *cipherSuite, masterSecret, clientRandom, serverRandom []byte, macLen, keyLen, ivLen int) (clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV []byte) {
155 var seed [tlsRandomLength * 2]byte
156 copy(seed[0:len(clientRandom)], serverRandom)
157 copy(seed[len(serverRandom):], clientRandom)
159 n := 2*macLen + 2*keyLen + 2*ivLen
160 keyMaterial := make([]byte, n)
161 prfForVersion(version, suite)(keyMaterial, masterSecret, keyExpansionLabel, seed[0:])
162 clientMAC = keyMaterial[:macLen]
163 keyMaterial = keyMaterial[macLen:]
164 serverMAC = keyMaterial[:macLen]
165 keyMaterial = keyMaterial[macLen:]
166 clientKey = keyMaterial[:keyLen]
167 keyMaterial = keyMaterial[keyLen:]
168 serverKey = keyMaterial[:keyLen]
169 keyMaterial = keyMaterial[keyLen:]
170 clientIV = keyMaterial[:ivLen]
171 keyMaterial = keyMaterial[ivLen:]
172 serverIV = keyMaterial[:ivLen]
176 func newFinishedHash(version uint16, cipherSuite *cipherSuite) finishedHash {
177 if version >= VersionTLS12 {
178 newHash := sha256.New
179 if cipherSuite.flags&suiteSHA384 != 0 {
180 newHash = sha512.New384
183 return finishedHash{newHash(), newHash(), nil, nil, version, prf12(newHash)}
185 return finishedHash{sha1.New(), sha1.New(), md5.New(), md5.New(), version, prf10}
188 // A finishedHash calculates the hash of a set of handshake messages suitable
189 // for including in a Finished message.
190 type finishedHash struct {
194 // Prior to TLS 1.2, an additional MD5 hash is required.
199 prf func(result, secret, label, seed []byte)
202 func (h finishedHash) Write(msg []byte) (n int, err error) {
206 if h.version < VersionTLS12 {
207 h.clientMD5.Write(msg)
208 h.serverMD5.Write(msg)
213 // finishedSum30 calculates the contents of the verify_data member of a SSLv3
214 // Finished message given the MD5 and SHA1 hashes of a set of handshake
216 func finishedSum30(md5, sha1 hash.Hash, masterSecret []byte, magic [4]byte) []byte {
218 md5.Write(masterSecret)
219 md5.Write(ssl30Pad1[:])
220 md5Digest := md5.Sum(nil)
223 md5.Write(masterSecret)
224 md5.Write(ssl30Pad2[:])
226 md5Digest = md5.Sum(nil)
229 sha1.Write(masterSecret)
230 sha1.Write(ssl30Pad1[:40])
231 sha1Digest := sha1.Sum(nil)
234 sha1.Write(masterSecret)
235 sha1.Write(ssl30Pad2[:40])
236 sha1.Write(sha1Digest)
237 sha1Digest = sha1.Sum(nil)
239 ret := make([]byte, len(md5Digest)+len(sha1Digest))
241 copy(ret[len(md5Digest):], sha1Digest)
245 var ssl3ClientFinishedMagic = [4]byte{0x43, 0x4c, 0x4e, 0x54}
246 var ssl3ServerFinishedMagic = [4]byte{0x53, 0x52, 0x56, 0x52}
248 // clientSum returns the contents of the verify_data member of a client's
250 func (h finishedHash) clientSum(masterSecret []byte) []byte {
251 if h.version == VersionSSL30 {
252 return finishedSum30(h.clientMD5, h.client, masterSecret, ssl3ClientFinishedMagic)
255 out := make([]byte, finishedVerifyLength)
256 if h.version >= VersionTLS12 {
257 seed := h.client.Sum(nil)
258 h.prf(out, masterSecret, clientFinishedLabel, seed)
260 seed := make([]byte, 0, md5.Size+sha1.Size)
261 seed = h.clientMD5.Sum(seed)
262 seed = h.client.Sum(seed)
263 h.prf(out, masterSecret, clientFinishedLabel, seed)
268 // serverSum returns the contents of the verify_data member of a server's
270 func (h finishedHash) serverSum(masterSecret []byte) []byte {
271 if h.version == VersionSSL30 {
272 return finishedSum30(h.serverMD5, h.server, masterSecret, ssl3ServerFinishedMagic)
275 out := make([]byte, finishedVerifyLength)
276 if h.version >= VersionTLS12 {
277 seed := h.server.Sum(nil)
278 h.prf(out, masterSecret, serverFinishedLabel, seed)
280 seed := make([]byte, 0, md5.Size+sha1.Size)
281 seed = h.serverMD5.Sum(seed)
282 seed = h.server.Sum(seed)
283 h.prf(out, masterSecret, serverFinishedLabel, seed)
288 // selectClientCertSignatureAlgorithm returns a signatureAndHash to sign a
289 // client's CertificateVerify with, or an error if none can be found.
290 func (h finishedHash) selectClientCertSignatureAlgorithm(serverList []signatureAndHash, sigType uint8) (signatureAndHash, error) {
291 if h.version < VersionTLS12 {
292 // Nothing to negotiate before TLS 1.2.
293 return signatureAndHash{sigType, 0}, nil
296 for _, v := range serverList {
297 if v.signature == sigType && v.hash == hashSHA256 {
301 return signatureAndHash{}, errors.New("tls: no supported signature algorithm found for signing client certificate")
304 // hashForClientCertificate returns a digest, hash function, and TLS 1.2 hash
305 // id suitable for signing by a TLS client certificate.
306 func (h finishedHash) hashForClientCertificate(signatureAndHash signatureAndHash) ([]byte, crypto.Hash, error) {
307 if h.version >= VersionTLS12 {
308 if signatureAndHash.hash != hashSHA256 {
309 return nil, 0, errors.New("tls: unsupported hash function for client certificate")
311 digest := h.server.Sum(nil)
312 return digest, crypto.SHA256, nil
314 if signatureAndHash.signature == signatureECDSA {
315 digest := h.server.Sum(nil)
316 return digest, crypto.SHA1, nil
319 digest := make([]byte, 0, 36)
320 digest = h.serverMD5.Sum(digest)
321 digest = h.server.Sum(digest)
322 return digest, crypto.MD5SHA1, nil