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.
19 // Split a premaster secret in two as specified in RFC 4346, section 5.
20 func splitPreMasterSecret(secret
[]byte) (s1
, s2
[]byte) {
21 s1
= secret
[0 : (len(secret
)+1)/2]
22 s2
= secret
[len(secret
)/2:]
26 // pHash implements the P_hash function, as defined in RFC 4346, section 5.
27 func pHash(result
, secret
, seed
[]byte, hash
func() hash
.Hash
) {
28 h
:= hmac
.New(hash
, secret
)
47 // prf10 implements the TLS 1.0 pseudo-random function, as defined in RFC 2246, section 5.
48 func prf10(result
, secret
, label
, seed
[]byte) {
52 labelAndSeed
:= make([]byte, len(label
)+len(seed
))
53 copy(labelAndSeed
, label
)
54 copy(labelAndSeed
[len(label
):], seed
)
56 s1
, s2
:= splitPreMasterSecret(secret
)
57 pHash(result
, s1
, labelAndSeed
, hashMD5
)
58 result2
:= make([]byte, len(result
))
59 pHash(result2
, s2
, labelAndSeed
, hashSHA1
)
61 for i
, b
:= range result2
{
66 // prf12 implements the TLS 1.2 pseudo-random function, as defined in RFC 5246, section 5.
67 func prf12(hashFunc
func() hash
.Hash
) func(result
, secret
, label
, seed
[]byte) {
68 return func(result
, secret
, label
, seed
[]byte) {
69 labelAndSeed
:= make([]byte, len(label
)+len(seed
))
70 copy(labelAndSeed
, label
)
71 copy(labelAndSeed
[len(label
):], seed
)
73 pHash(result
, secret
, labelAndSeed
, hashFunc
)
77 // prf30 implements the SSL 3.0 pseudo-random function, as defined in
78 // www.mozilla.org/projects/security/pki/nss/ssl/draft302.txt section 6.
79 func prf30(result
, secret
, label
, seed
[]byte) {
80 hashSHA1
:= sha1
.New()
85 // RFC 5246 section 6.3 says that the largest PRF output needed is 128
86 // bytes. Since no more ciphersuites will be added to SSLv3, this will
87 // remain true. Each iteration gives us 16 bytes so 10 iterations will
90 for done
< len(result
) {
91 for j
:= 0; j
<= i
; j
++ {
96 hashSHA1
.Write(b
[:i
+1])
97 hashSHA1
.Write(secret
)
99 digest
:= hashSHA1
.Sum(nil)
102 hashMD5
.Write(secret
)
103 hashMD5
.Write(digest
)
105 done
+= copy(result
[done
:], hashMD5
.Sum(nil))
111 tlsRandomLength
= 32 // Length of a random nonce in TLS 1.1.
112 masterSecretLength
= 48 // Length of a master secret in TLS 1.1.
113 finishedVerifyLength
= 12 // Length of verify_data in a Finished message.
116 var masterSecretLabel
= []byte("master secret")
117 var keyExpansionLabel
= []byte("key expansion")
118 var clientFinishedLabel
= []byte("client finished")
119 var serverFinishedLabel
= []byte("server finished")
121 func prfAndHashForVersion(version
uint16, suite
*cipherSuite
) (func(result
, secret
, label
, seed
[]byte), crypto
.Hash
) {
124 return prf30
, crypto
.Hash(0)
125 case VersionTLS10
, VersionTLS11
:
126 return prf10
, crypto
.Hash(0)
128 if suite
.flags
&suiteSHA384
!= 0 {
129 return prf12(sha512
.New384
), crypto
.SHA384
131 return prf12(sha256
.New
), crypto
.SHA256
133 panic("unknown version")
137 func prfForVersion(version
uint16, suite
*cipherSuite
) func(result
, secret
, label
, seed
[]byte) {
138 prf
, _
:= prfAndHashForVersion(version
, suite
)
142 // masterFromPreMasterSecret generates the master secret from the pre-master
143 // secret. See https://tools.ietf.org/html/rfc5246#section-8.1
144 func masterFromPreMasterSecret(version
uint16, suite
*cipherSuite
, preMasterSecret
, clientRandom
, serverRandom
[]byte) []byte {
145 seed
:= make([]byte, 0, len(clientRandom
)+len(serverRandom
))
146 seed
= append(seed
, clientRandom
...)
147 seed
= append(seed
, serverRandom
...)
149 masterSecret
:= make([]byte, masterSecretLength
)
150 prfForVersion(version
, suite
)(masterSecret
, preMasterSecret
, masterSecretLabel
, seed
)
154 // keysFromMasterSecret generates the connection keys from the master
155 // secret, given the lengths of the MAC key, cipher key and IV, as defined in
156 // RFC 2246, section 6.3.
157 func keysFromMasterSecret(version
uint16, suite
*cipherSuite
, masterSecret
, clientRandom
, serverRandom
[]byte, macLen
, keyLen
, ivLen
int) (clientMAC
, serverMAC
, clientKey
, serverKey
, clientIV
, serverIV
[]byte) {
158 seed
:= make([]byte, 0, len(serverRandom
)+len(clientRandom
))
159 seed
= append(seed
, serverRandom
...)
160 seed
= append(seed
, clientRandom
...)
162 n
:= 2*macLen
+ 2*keyLen
+ 2*ivLen
163 keyMaterial
:= make([]byte, n
)
164 prfForVersion(version
, suite
)(keyMaterial
, masterSecret
, keyExpansionLabel
, seed
)
165 clientMAC
= keyMaterial
[:macLen
]
166 keyMaterial
= keyMaterial
[macLen
:]
167 serverMAC
= keyMaterial
[:macLen
]
168 keyMaterial
= keyMaterial
[macLen
:]
169 clientKey
= keyMaterial
[:keyLen
]
170 keyMaterial
= keyMaterial
[keyLen
:]
171 serverKey
= keyMaterial
[:keyLen
]
172 keyMaterial
= keyMaterial
[keyLen
:]
173 clientIV
= keyMaterial
[:ivLen
]
174 keyMaterial
= keyMaterial
[ivLen
:]
175 serverIV
= keyMaterial
[:ivLen
]
179 // lookupTLSHash looks up the corresponding crypto.Hash for a given
180 // hash from a TLS SignatureScheme.
181 func lookupTLSHash(signatureAlgorithm SignatureScheme
) (crypto
.Hash
, error
) {
182 switch signatureAlgorithm
{
183 case PKCS1WithSHA1
, ECDSAWithSHA1
:
184 return crypto
.SHA1
, nil
185 case PKCS1WithSHA256
, PSSWithSHA256
, ECDSAWithP256AndSHA256
:
186 return crypto
.SHA256
, nil
187 case PKCS1WithSHA384
, PSSWithSHA384
, ECDSAWithP384AndSHA384
:
188 return crypto
.SHA384
, nil
189 case PKCS1WithSHA512
, PSSWithSHA512
, ECDSAWithP521AndSHA512
:
190 return crypto
.SHA512
, nil
192 return 0, fmt
.Errorf("tls: unsupported signature algorithm: %#04x", signatureAlgorithm
)
196 func newFinishedHash(version
uint16, cipherSuite
*cipherSuite
) finishedHash
{
198 if version
== VersionSSL30 || version
>= VersionTLS12
{
202 prf
, hash
:= prfAndHashForVersion(version
, cipherSuite
)
204 return finishedHash
{hash
.New(), hash
.New(), nil, nil, buffer
, version
, prf
}
207 return finishedHash
{sha1
.New(), sha1
.New(), md5
.New(), md5
.New(), buffer
, version
, prf
}
210 // A finishedHash calculates the hash of a set of handshake messages suitable
211 // for including in a Finished message.
212 type finishedHash
struct {
216 // Prior to TLS 1.2, an additional MD5 hash is required.
220 // In TLS 1.2, a full buffer is sadly required.
224 prf
func(result
, secret
, label
, seed
[]byte)
227 func (h
*finishedHash
) Write(msg
[]byte) (n
int, err error
) {
231 if h
.version
< VersionTLS12
{
232 h
.clientMD5
.Write(msg
)
233 h
.serverMD5
.Write(msg
)
237 h
.buffer
= append(h
.buffer
, msg
...)
243 func (h finishedHash
) Sum() []byte {
244 if h
.version
>= VersionTLS12
{
245 return h
.client
.Sum(nil)
248 out
:= make([]byte, 0, md5
.Size
+sha1
.Size
)
249 out
= h
.clientMD5
.Sum(out
)
250 return h
.client
.Sum(out
)
253 // finishedSum30 calculates the contents of the verify_data member of a SSLv3
254 // Finished message given the MD5 and SHA1 hashes of a set of handshake
256 func finishedSum30(md5
, sha1 hash
.Hash
, masterSecret
[]byte, magic
[]byte) []byte {
258 md5
.Write(masterSecret
)
259 md5
.Write(ssl30Pad1
[:])
260 md5Digest
:= md5
.Sum(nil)
263 md5
.Write(masterSecret
)
264 md5
.Write(ssl30Pad2
[:])
266 md5Digest
= md5
.Sum(nil)
269 sha1
.Write(masterSecret
)
270 sha1
.Write(ssl30Pad1
[:40])
271 sha1Digest
:= sha1
.Sum(nil)
274 sha1
.Write(masterSecret
)
275 sha1
.Write(ssl30Pad2
[:40])
276 sha1
.Write(sha1Digest
)
277 sha1Digest
= sha1
.Sum(nil)
279 ret
:= make([]byte, len(md5Digest
)+len(sha1Digest
))
281 copy(ret
[len(md5Digest
):], sha1Digest
)
285 var ssl3ClientFinishedMagic
= [4]byte{0x43, 0x4c, 0x4e, 0x54}
286 var ssl3ServerFinishedMagic
= [4]byte{0x53, 0x52, 0x56, 0x52}
288 // clientSum returns the contents of the verify_data member of a client's
290 func (h finishedHash
) clientSum(masterSecret
[]byte) []byte {
291 if h
.version
== VersionSSL30
{
292 return finishedSum30(h
.clientMD5
, h
.client
, masterSecret
, ssl3ClientFinishedMagic
[:])
295 out
:= make([]byte, finishedVerifyLength
)
296 h
.prf(out
, masterSecret
, clientFinishedLabel
, h
.Sum())
300 // serverSum returns the contents of the verify_data member of a server's
302 func (h finishedHash
) serverSum(masterSecret
[]byte) []byte {
303 if h
.version
== VersionSSL30
{
304 return finishedSum30(h
.serverMD5
, h
.server
, masterSecret
, ssl3ServerFinishedMagic
[:])
307 out
:= make([]byte, finishedVerifyLength
)
308 h
.prf(out
, masterSecret
, serverFinishedLabel
, h
.Sum())
312 // hashForClientCertificate returns a digest over the handshake messages so far,
313 // suitable for signing by a TLS client certificate.
314 func (h finishedHash
) hashForClientCertificate(sigType
uint8, hashAlg crypto
.Hash
, masterSecret
[]byte) ([]byte, error
) {
315 if (h
.version
== VersionSSL30 || h
.version
>= VersionTLS12
) && h
.buffer
== nil {
316 panic("a handshake hash for a client-certificate was requested after discarding the handshake buffer")
319 if h
.version
== VersionSSL30
{
320 if sigType
!= signaturePKCS1v15
{
321 return nil, errors
.New("tls: unsupported signature type for client certificate")
325 md5Hash
.Write(h
.buffer
)
326 sha1Hash
:= sha1
.New()
327 sha1Hash
.Write(h
.buffer
)
328 return finishedSum30(md5Hash
, sha1Hash
, masterSecret
, nil), nil
330 if h
.version
>= VersionTLS12
{
331 hash
:= hashAlg
.New()
333 return hash
.Sum(nil), nil
336 if sigType
== signatureECDSA
{
337 return h
.server
.Sum(nil), nil
343 // discardHandshakeBuffer is called when there is no more need to
344 // buffer the entirety of the handshake messages.
345 func (h
*finishedHash
) discardHandshakeBuffer() {
349 // noExportedKeyingMaterial is used as a value of
350 // ConnectionState.ekm when renegotation is enabled and thus
351 // we wish to fail all key-material export requests.
352 func noExportedKeyingMaterial(label
string, context
[]byte, length
int) ([]byte, error
) {
353 return nil, errors
.New("crypto/tls: ExportKeyingMaterial is unavailable when renegotiation is enabled")
356 // ekmFromMasterSecret generates exported keying material as defined in
357 // https://tools.ietf.org/html/rfc5705.
358 func ekmFromMasterSecret(version
uint16, suite
*cipherSuite
, masterSecret
, clientRandom
, serverRandom
[]byte) func(string, []byte, int) ([]byte, error
) {
359 return func(label
string, context
[]byte, length
int) ([]byte, error
) {
361 case "client finished", "server finished", "master secret", "key expansion":
362 // These values are reserved and may not be used.
363 return nil, fmt
.Errorf("crypto/tls: reserved ExportKeyingMaterial label: %s", label
)
366 seedLen
:= len(serverRandom
) + len(clientRandom
)
368 seedLen
+= 2 + len(context
)
370 seed
:= make([]byte, 0, seedLen
)
372 seed
= append(seed
, clientRandom
...)
373 seed
= append(seed
, serverRandom
...)
376 if len(context
) >= 1<<16 {
377 return nil, fmt
.Errorf("crypto/tls: ExportKeyingMaterial context too long")
379 seed
= append(seed
, byte(len(context
)>>8), byte(len(context
)))
380 seed
= append(seed
, context
...)
383 keyMaterial
:= make([]byte, length
)
384 prfForVersion(version
, suite
)(keyMaterial
, masterSecret
, []byte(label
), seed
)
385 return keyMaterial
, nil