blob: fb8b3ab4d1e398045b6cdde4c48ed7b8618dfc5a [file] [log] [blame]
Colin Cross7bb052a2015-02-03 12:59:37 -08001// 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.
4
5package tls
6
7import (
8 "crypto"
9 "crypto/hmac"
10 "crypto/md5"
11 "crypto/sha1"
12 "crypto/sha256"
13 "hash"
14)
15
16// Split a premaster secret in two as specified in RFC 4346, section 5.
17func splitPreMasterSecret(secret []byte) (s1, s2 []byte) {
18 s1 = secret[0 : (len(secret)+1)/2]
19 s2 = secret[len(secret)/2:]
20 return
21}
22
23// pHash implements the P_hash function, as defined in RFC 4346, section 5.
24func pHash(result, secret, seed []byte, hash func() hash.Hash) {
25 h := hmac.New(hash, secret)
26 h.Write(seed)
27 a := h.Sum(nil)
28
29 j := 0
30 for j < len(result) {
31 h.Reset()
32 h.Write(a)
33 h.Write(seed)
34 b := h.Sum(nil)
35 todo := len(b)
36 if j+todo > len(result) {
37 todo = len(result) - j
38 }
39 copy(result[j:j+todo], b)
40 j += todo
41
42 h.Reset()
43 h.Write(a)
44 a = h.Sum(nil)
45 }
46}
47
48// prf10 implements the TLS 1.0 pseudo-random function, as defined in RFC 2246, section 5.
49func prf10(result, secret, label, seed []byte) {
50 hashSHA1 := sha1.New
51 hashMD5 := md5.New
52
53 labelAndSeed := make([]byte, len(label)+len(seed))
54 copy(labelAndSeed, label)
55 copy(labelAndSeed[len(label):], seed)
56
57 s1, s2 := splitPreMasterSecret(secret)
58 pHash(result, s1, labelAndSeed, hashMD5)
59 result2 := make([]byte, len(result))
60 pHash(result2, s2, labelAndSeed, hashSHA1)
61
62 for i, b := range result2 {
63 result[i] ^= b
64 }
65}
66
67// prf12 implements the TLS 1.2 pseudo-random function, as defined in RFC 5246, section 5.
68func prf12(result, secret, label, seed []byte) {
69 labelAndSeed := make([]byte, len(label)+len(seed))
70 copy(labelAndSeed, label)
71 copy(labelAndSeed[len(label):], seed)
72
73 pHash(result, secret, labelAndSeed, sha256.New)
74}
75
76// prf30 implements the SSL 3.0 pseudo-random function, as defined in
77// www.mozilla.org/projects/security/pki/nss/ssl/draft302.txt section 6.
78func prf30(result, secret, label, seed []byte) {
79 hashSHA1 := sha1.New()
80 hashMD5 := md5.New()
81
82 done := 0
83 i := 0
84 // RFC5246 section 6.3 says that the largest PRF output needed is 128
85 // bytes. Since no more ciphersuites will be added to SSLv3, this will
86 // remain true. Each iteration gives us 16 bytes so 10 iterations will
87 // be sufficient.
88 var b [11]byte
89 for done < len(result) {
90 for j := 0; j <= i; j++ {
91 b[j] = 'A' + byte(i)
92 }
93
94 hashSHA1.Reset()
95 hashSHA1.Write(b[:i+1])
96 hashSHA1.Write(secret)
97 hashSHA1.Write(seed)
98 digest := hashSHA1.Sum(nil)
99
100 hashMD5.Reset()
101 hashMD5.Write(secret)
102 hashMD5.Write(digest)
103
104 done += copy(result[done:], hashMD5.Sum(nil))
105 i++
106 }
107}
108
109const (
110 tlsRandomLength = 32 // Length of a random nonce in TLS 1.1.
111 masterSecretLength = 48 // Length of a master secret in TLS 1.1.
112 finishedVerifyLength = 12 // Length of verify_data in a Finished message.
113)
114
115var masterSecretLabel = []byte("master secret")
116var keyExpansionLabel = []byte("key expansion")
117var clientFinishedLabel = []byte("client finished")
118var serverFinishedLabel = []byte("server finished")
119
120func prfForVersion(version uint16) func(result, secret, label, seed []byte) {
121 switch version {
122 case VersionSSL30:
123 return prf30
124 case VersionTLS10, VersionTLS11:
125 return prf10
126 case VersionTLS12:
127 return prf12
128 default:
129 panic("unknown version")
130 }
131}
132
133// masterFromPreMasterSecret generates the master secret from the pre-master
134// secret. See http://tools.ietf.org/html/rfc5246#section-8.1
135func masterFromPreMasterSecret(version uint16, preMasterSecret, clientRandom, serverRandom []byte) []byte {
136 var seed [tlsRandomLength * 2]byte
137 copy(seed[0:len(clientRandom)], clientRandom)
138 copy(seed[len(clientRandom):], serverRandom)
139 masterSecret := make([]byte, masterSecretLength)
140 prfForVersion(version)(masterSecret, preMasterSecret, masterSecretLabel, seed[0:])
141 return masterSecret
142}
143
144// keysFromMasterSecret generates the connection keys from the master
145// secret, given the lengths of the MAC key, cipher key and IV, as defined in
146// RFC 2246, section 6.3.
147func keysFromMasterSecret(version uint16, masterSecret, clientRandom, serverRandom []byte, macLen, keyLen, ivLen int) (clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV []byte) {
148 var seed [tlsRandomLength * 2]byte
149 copy(seed[0:len(clientRandom)], serverRandom)
150 copy(seed[len(serverRandom):], clientRandom)
151
152 n := 2*macLen + 2*keyLen + 2*ivLen
153 keyMaterial := make([]byte, n)
154 prfForVersion(version)(keyMaterial, masterSecret, keyExpansionLabel, seed[0:])
155 clientMAC = keyMaterial[:macLen]
156 keyMaterial = keyMaterial[macLen:]
157 serverMAC = keyMaterial[:macLen]
158 keyMaterial = keyMaterial[macLen:]
159 clientKey = keyMaterial[:keyLen]
160 keyMaterial = keyMaterial[keyLen:]
161 serverKey = keyMaterial[:keyLen]
162 keyMaterial = keyMaterial[keyLen:]
163 clientIV = keyMaterial[:ivLen]
164 keyMaterial = keyMaterial[ivLen:]
165 serverIV = keyMaterial[:ivLen]
166 return
167}
168
169func newFinishedHash(version uint16) finishedHash {
170 if version >= VersionTLS12 {
171 return finishedHash{sha256.New(), sha256.New(), nil, nil, version}
172 }
173 return finishedHash{sha1.New(), sha1.New(), md5.New(), md5.New(), version}
174}
175
176// A finishedHash calculates the hash of a set of handshake messages suitable
177// for including in a Finished message.
178type finishedHash struct {
179 client hash.Hash
180 server hash.Hash
181
182 // Prior to TLS 1.2, an additional MD5 hash is required.
183 clientMD5 hash.Hash
184 serverMD5 hash.Hash
185
186 version uint16
187}
188
189func (h finishedHash) Write(msg []byte) (n int, err error) {
190 h.client.Write(msg)
191 h.server.Write(msg)
192
193 if h.version < VersionTLS12 {
194 h.clientMD5.Write(msg)
195 h.serverMD5.Write(msg)
196 }
197 return len(msg), nil
198}
199
200// finishedSum30 calculates the contents of the verify_data member of a SSLv3
201// Finished message given the MD5 and SHA1 hashes of a set of handshake
202// messages.
203func finishedSum30(md5, sha1 hash.Hash, masterSecret []byte, magic [4]byte) []byte {
204 md5.Write(magic[:])
205 md5.Write(masterSecret)
206 md5.Write(ssl30Pad1[:])
207 md5Digest := md5.Sum(nil)
208
209 md5.Reset()
210 md5.Write(masterSecret)
211 md5.Write(ssl30Pad2[:])
212 md5.Write(md5Digest)
213 md5Digest = md5.Sum(nil)
214
215 sha1.Write(magic[:])
216 sha1.Write(masterSecret)
217 sha1.Write(ssl30Pad1[:40])
218 sha1Digest := sha1.Sum(nil)
219
220 sha1.Reset()
221 sha1.Write(masterSecret)
222 sha1.Write(ssl30Pad2[:40])
223 sha1.Write(sha1Digest)
224 sha1Digest = sha1.Sum(nil)
225
226 ret := make([]byte, len(md5Digest)+len(sha1Digest))
227 copy(ret, md5Digest)
228 copy(ret[len(md5Digest):], sha1Digest)
229 return ret
230}
231
232var ssl3ClientFinishedMagic = [4]byte{0x43, 0x4c, 0x4e, 0x54}
233var ssl3ServerFinishedMagic = [4]byte{0x53, 0x52, 0x56, 0x52}
234
235// clientSum returns the contents of the verify_data member of a client's
236// Finished message.
237func (h finishedHash) clientSum(masterSecret []byte) []byte {
238 if h.version == VersionSSL30 {
239 return finishedSum30(h.clientMD5, h.client, masterSecret, ssl3ClientFinishedMagic)
240 }
241
242 out := make([]byte, finishedVerifyLength)
243 if h.version >= VersionTLS12 {
244 seed := h.client.Sum(nil)
245 prf12(out, masterSecret, clientFinishedLabel, seed)
246 } else {
247 seed := make([]byte, 0, md5.Size+sha1.Size)
248 seed = h.clientMD5.Sum(seed)
249 seed = h.client.Sum(seed)
250 prf10(out, masterSecret, clientFinishedLabel, seed)
251 }
252 return out
253}
254
255// serverSum returns the contents of the verify_data member of a server's
256// Finished message.
257func (h finishedHash) serverSum(masterSecret []byte) []byte {
258 if h.version == VersionSSL30 {
259 return finishedSum30(h.serverMD5, h.server, masterSecret, ssl3ServerFinishedMagic)
260 }
261
262 out := make([]byte, finishedVerifyLength)
263 if h.version >= VersionTLS12 {
264 seed := h.server.Sum(nil)
265 prf12(out, masterSecret, serverFinishedLabel, seed)
266 } else {
267 seed := make([]byte, 0, md5.Size+sha1.Size)
268 seed = h.serverMD5.Sum(seed)
269 seed = h.server.Sum(seed)
270 prf10(out, masterSecret, serverFinishedLabel, seed)
271 }
272 return out
273}
274
275// hashForClientCertificate returns a digest, hash function, and TLS 1.2 hash
276// id suitable for signing by a TLS client certificate.
277func (h finishedHash) hashForClientCertificate(sigType uint8) ([]byte, crypto.Hash, uint8) {
278 if h.version >= VersionTLS12 {
279 digest := h.server.Sum(nil)
280 return digest, crypto.SHA256, hashSHA256
281 }
282 if sigType == signatureECDSA {
283 digest := h.server.Sum(nil)
284 return digest, crypto.SHA1, hashSHA1
285 }
286
287 digest := make([]byte, 0, 36)
288 digest = h.serverMD5.Sum(digest)
289 digest = h.server.Sum(digest)
290 return digest, crypto.MD5SHA1, 0 /* not specified in TLS 1.2. */
291}