• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
4
5package runner
6
7import (
8	"crypto"
9	"crypto/hmac"
10	"crypto/md5"
11	"crypto/sha1"
12	"crypto/sha256"
13	"encoding"
14	"hash"
15
16	"golang.org/x/crypto/hkdf"
17)
18
19// copyHash returns a copy of |h|, which must be an instance of |hashType|.
20func copyHash(h hash.Hash, hash crypto.Hash) hash.Hash {
21	// While hash.Hash is not copyable, the documentation says all standard
22	// library hash.Hash implementations implement BinaryMarshaler and
23	// BinaryUnmarshaler interfaces.
24	m, ok := h.(encoding.BinaryMarshaler)
25	if !ok {
26		panic("hash did not implement encoding.BinaryMarshaler")
27	}
28	data, err := m.MarshalBinary()
29	if err != nil {
30		panic(err)
31	}
32	ret := hash.New()
33	u, ok := ret.(encoding.BinaryUnmarshaler)
34	if !ok {
35		panic("hash did not implement BinaryUnmarshaler")
36	}
37	if err := u.UnmarshalBinary(data); err != nil {
38		panic(err)
39	}
40	return ret
41}
42
43// Split a premaster secret in two as specified in RFC 4346, section 5.
44func splitPreMasterSecret(secret []byte) (s1, s2 []byte) {
45	s1 = secret[0 : (len(secret)+1)/2]
46	s2 = secret[len(secret)/2:]
47	return
48}
49
50// pHash implements the P_hash function, as defined in RFC 4346, section 5.
51func pHash(result, secret, seed []byte, hash func() hash.Hash) {
52	h := hmac.New(hash, secret)
53	h.Write(seed)
54	a := h.Sum(nil)
55
56	j := 0
57	for j < len(result) {
58		h.Reset()
59		h.Write(a)
60		h.Write(seed)
61		b := h.Sum(nil)
62		todo := len(b)
63		if j+todo > len(result) {
64			todo = len(result) - j
65		}
66		copy(result[j:j+todo], b)
67		j += todo
68
69		h.Reset()
70		h.Write(a)
71		a = h.Sum(nil)
72	}
73}
74
75// prf10 implements the TLS 1.0 pseudo-random function, as defined in RFC 2246, section 5.
76func prf10(result, secret, label, seed []byte) {
77	hashSHA1 := sha1.New
78	hashMD5 := md5.New
79
80	labelAndSeed := make([]byte, len(label)+len(seed))
81	copy(labelAndSeed, label)
82	copy(labelAndSeed[len(label):], seed)
83
84	s1, s2 := splitPreMasterSecret(secret)
85	pHash(result, s1, labelAndSeed, hashMD5)
86	result2 := make([]byte, len(result))
87	pHash(result2, s2, labelAndSeed, hashSHA1)
88
89	for i, b := range result2 {
90		result[i] ^= b
91	}
92}
93
94// prf12 implements the TLS 1.2 pseudo-random function, as defined in RFC 5246, section 5.
95func prf12(hashFunc func() hash.Hash) func(result, secret, label, seed []byte) {
96	return func(result, secret, label, seed []byte) {
97		labelAndSeed := make([]byte, len(label)+len(seed))
98		copy(labelAndSeed, label)
99		copy(labelAndSeed[len(label):], seed)
100
101		pHash(result, secret, labelAndSeed, hashFunc)
102	}
103}
104
105const (
106	tlsRandomLength      = 32 // Length of a random nonce in TLS 1.1.
107	masterSecretLength   = 48 // Length of a master secret in TLS 1.1.
108	finishedVerifyLength = 12 // Length of verify_data in a Finished message.
109)
110
111var masterSecretLabel = []byte("master secret")
112var extendedMasterSecretLabel = []byte("extended master secret")
113var keyExpansionLabel = []byte("key expansion")
114var clientFinishedLabel = []byte("client finished")
115var serverFinishedLabel = []byte("server finished")
116var finishedLabel = []byte("finished")
117var channelIDLabel = []byte("TLS Channel ID signature\x00")
118var channelIDResumeLabel = []byte("Resumption\x00")
119
120func prfForVersion(version uint16, suite *cipherSuite) func(result, secret, label, seed []byte) {
121	switch version {
122	case VersionTLS10, VersionTLS11:
123		return prf10
124	case VersionTLS12:
125		return prf12(suite.hash().New)
126	}
127	panic("unknown version")
128}
129
130// masterFromPreMasterSecret generates the master secret from the pre-master
131// secret. See http://tools.ietf.org/html/rfc5246#section-8.1
132func masterFromPreMasterSecret(version uint16, suite *cipherSuite, preMasterSecret, clientRandom, serverRandom []byte) []byte {
133	var seed [tlsRandomLength * 2]byte
134	copy(seed[0:len(clientRandom)], clientRandom)
135	copy(seed[len(clientRandom):], serverRandom)
136	masterSecret := make([]byte, masterSecretLength)
137	prfForVersion(version, suite)(masterSecret, preMasterSecret, masterSecretLabel, seed[0:])
138	return masterSecret
139}
140
141// extendedMasterFromPreMasterSecret generates the master secret from the
142// pre-master secret when the Triple Handshake fix is in effect. See
143// https://tools.ietf.org/html/rfc7627
144func extendedMasterFromPreMasterSecret(version uint16, suite *cipherSuite, preMasterSecret []byte, h finishedHash) []byte {
145	masterSecret := make([]byte, masterSecretLength)
146	prfForVersion(version, suite)(masterSecret, preMasterSecret, extendedMasterSecretLabel, h.Sum())
147	return masterSecret
148}
149
150// keysFromMasterSecret generates the connection keys from the master
151// secret, given the lengths of the MAC key, cipher key and IV, as defined in
152// RFC 2246, section 6.3.
153func keysFromMasterSecret(version uint16, suite *cipherSuite, masterSecret, clientRandom, serverRandom []byte, macLen, keyLen, ivLen int) (clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV []byte) {
154	var seed [tlsRandomLength * 2]byte
155	copy(seed[0:len(clientRandom)], serverRandom)
156	copy(seed[len(serverRandom):], clientRandom)
157
158	n := 2*macLen + 2*keyLen + 2*ivLen
159	keyMaterial := make([]byte, n)
160	prfForVersion(version, suite)(keyMaterial, masterSecret, keyExpansionLabel, seed[0:])
161	clientMAC = keyMaterial[:macLen]
162	keyMaterial = keyMaterial[macLen:]
163	serverMAC = keyMaterial[:macLen]
164	keyMaterial = keyMaterial[macLen:]
165	clientKey = keyMaterial[:keyLen]
166	keyMaterial = keyMaterial[keyLen:]
167	serverKey = keyMaterial[:keyLen]
168	keyMaterial = keyMaterial[keyLen:]
169	clientIV = keyMaterial[:ivLen]
170	keyMaterial = keyMaterial[ivLen:]
171	serverIV = keyMaterial[:ivLen]
172	return
173}
174
175func newFinishedHash(wireVersion uint16, isDTLS bool, cipherSuite *cipherSuite) finishedHash {
176	version, ok := wireToVersion(wireVersion, isDTLS)
177	if !ok {
178		panic("unknown version")
179	}
180
181	var ret finishedHash
182	if version >= VersionTLS12 {
183		ret.hash = cipherSuite.hash().New()
184
185		if version == VersionTLS12 {
186			ret.prf = prf12(cipherSuite.hash().New)
187		} else {
188			ret.secret = make([]byte, ret.hash.Size())
189		}
190	} else {
191		ret.hash = sha1.New()
192		ret.md5 = md5.New()
193
194		ret.prf = prf10
195	}
196
197	ret.suite = cipherSuite
198	ret.buffer = []byte{}
199	ret.version = version
200	ret.wireVersion = wireVersion
201	ret.isDTLS = isDTLS
202	return ret
203}
204
205// A finishedHash calculates the hash of a set of handshake messages suitable
206// for including in a Finished message.
207type finishedHash struct {
208	suite *cipherSuite
209
210	// hash maintains a running hash of handshake messages. In TLS 1.2 and up,
211	// the hash is determined from suite.hash(). In TLS 1.0 and 1.1, this is the
212	// SHA-1 half of the MD5/SHA-1 concatenation.
213	hash hash.Hash
214
215	// md5 is the MD5 half of the TLS 1.0 and 1.1 MD5/SHA1 concatenation.
216	md5 hash.Hash
217
218	// In TLS 1.2, a full buffer is required.
219	buffer []byte
220
221	version     uint16
222	wireVersion uint16
223	isDTLS      bool
224	prf         func(result, secret, label, seed []byte)
225
226	// secret, in TLS 1.3, is the running input secret.
227	secret []byte
228}
229
230func (h *finishedHash) UpdateForHelloRetryRequest() {
231	data := newByteBuilder()
232	data.addU8(typeMessageHash)
233	data.addU24(h.hash.Size())
234	data.addBytes(h.Sum())
235	h.hash = h.suite.hash().New()
236	if h.buffer != nil {
237		h.buffer = []byte{}
238	}
239	h.Write(data.finish())
240}
241
242func (h *finishedHash) Write(msg []byte) (n int, err error) {
243	h.hash.Write(msg)
244
245	if h.version < VersionTLS12 {
246		h.md5.Write(msg)
247	}
248
249	if h.buffer != nil {
250		h.buffer = append(h.buffer, msg...)
251	}
252
253	return len(msg), nil
254}
255
256// WriteHandshake appends |msg| to the hash, which must be a serialized
257// handshake message with a TLS header. In DTLS, the header is rewritten to a
258// DTLS header with |seqno| as the sequence number.
259func (h *finishedHash) WriteHandshake(msg []byte, seqno uint16) {
260	if h.isDTLS {
261		// This is somewhat hacky. DTLS hashes a slightly different format.
262		// First, the TLS header.
263		h.Write(msg[:4])
264		// Then the sequence number and reassembled fragment offset (always 0).
265		h.Write([]byte{byte(seqno >> 8), byte(seqno), 0, 0, 0})
266		// Then the reassembled fragment (always equal to the message length).
267		h.Write(msg[1:4])
268		// And then the message body.
269		h.Write(msg[4:])
270	} else {
271		h.Write(msg)
272	}
273}
274
275func (h finishedHash) Sum() []byte {
276	if h.version >= VersionTLS12 {
277		return h.hash.Sum(nil)
278	}
279
280	out := make([]byte, 0, md5.Size+sha1.Size)
281	out = h.md5.Sum(out)
282	return h.hash.Sum(out)
283}
284
285// clientSum returns the contents of the verify_data member of a client's
286// Finished message.
287func (h finishedHash) clientSum(baseKey []byte) []byte {
288	if h.version < VersionTLS13 {
289		out := make([]byte, finishedVerifyLength)
290		h.prf(out, baseKey, clientFinishedLabel, h.Sum())
291		return out
292	}
293
294	clientFinishedKey := hkdfExpandLabel(h.suite.hash(), baseKey, finishedLabel, nil, h.hash.Size())
295	finishedHMAC := hmac.New(h.suite.hash().New, clientFinishedKey)
296	finishedHMAC.Write(h.appendContextHashes(nil))
297	return finishedHMAC.Sum(nil)
298}
299
300// serverSum returns the contents of the verify_data member of a server's
301// Finished message.
302func (h finishedHash) serverSum(baseKey []byte) []byte {
303	if h.version < VersionTLS13 {
304		out := make([]byte, finishedVerifyLength)
305		h.prf(out, baseKey, serverFinishedLabel, h.Sum())
306		return out
307	}
308
309	serverFinishedKey := hkdfExpandLabel(h.suite.hash(), baseKey, finishedLabel, nil, h.hash.Size())
310	finishedHMAC := hmac.New(h.suite.hash().New, serverFinishedKey)
311	finishedHMAC.Write(h.appendContextHashes(nil))
312	return finishedHMAC.Sum(nil)
313}
314
315// hashForChannelID returns the hash to be signed for TLS Channel
316// ID. If a resumption, resumeHash has the previous handshake
317// hash. Otherwise, it is nil.
318func (h finishedHash) hashForChannelID(resumeHash []byte) []byte {
319	hash := sha256.New()
320	hash.Write(channelIDLabel)
321	if resumeHash != nil {
322		hash.Write(channelIDResumeLabel)
323		hash.Write(resumeHash)
324	}
325	hash.Write(h.Sum())
326	return hash.Sum(nil)
327}
328
329// discardHandshakeBuffer is called when there is no more need to
330// buffer the entirety of the handshake messages.
331func (h *finishedHash) discardHandshakeBuffer() {
332	h.buffer = nil
333}
334
335// zeroSecretTLS13 returns the default all zeros secret for TLS 1.3, used when a
336// given secret is not available in the handshake. See RFC 8446, section 7.1.
337func (h *finishedHash) zeroSecret() []byte {
338	return make([]byte, h.hash.Size())
339}
340
341// addEntropy incorporates ikm into the running TLS 1.3 secret with HKDF-Expand.
342func (h *finishedHash) addEntropy(ikm []byte) {
343	h.secret = hkdf.Extract(h.suite.hash().New, ikm, h.secret)
344}
345
346func (h *finishedHash) nextSecret() {
347	h.secret = hkdfExpandLabel(h.suite.hash(), h.secret, []byte("derived"), h.suite.hash().New().Sum(nil), h.hash.Size())
348}
349
350// hkdfExpandLabel implements TLS 1.3's HKDF-Expand-Label function, as defined
351// in section 7.1 of RFC 8446.
352func hkdfExpandLabel(hash crypto.Hash, secret, label, hashValue []byte, length int) []byte {
353	if len(label) > 255 || len(hashValue) > 255 {
354		panic("hkdfExpandLabel: label or hashValue too long")
355	}
356
357	versionLabel := []byte("tls13 ")
358	hkdfLabel := make([]byte, 3+len(versionLabel)+len(label)+1+len(hashValue))
359	x := hkdfLabel
360	x[0] = byte(length >> 8)
361	x[1] = byte(length)
362	x[2] = byte(len(versionLabel) + len(label))
363	x = x[3:]
364	copy(x, versionLabel)
365	x = x[len(versionLabel):]
366	copy(x, label)
367	x = x[len(label):]
368	x[0] = byte(len(hashValue))
369	copy(x[1:], hashValue)
370	ret := make([]byte, length)
371	if n, err := hkdf.Expand(hash.New, secret, hkdfLabel).Read(ret); err != nil || n != length {
372		panic("hkdfExpandLabel: hkdf.Expand unexpectedly failed")
373	}
374	return ret
375}
376
377// appendContextHashes returns the concatenation of the handshake hash and the
378// resumption context hash, as used in TLS 1.3.
379func (h *finishedHash) appendContextHashes(b []byte) []byte {
380	b = h.hash.Sum(b)
381	return b
382}
383
384var (
385	externalPSKBinderLabel        = []byte("ext binder")
386	resumptionPSKBinderLabel      = []byte("res binder")
387	earlyTrafficLabel             = []byte("c e traffic")
388	clientHandshakeTrafficLabel   = []byte("c hs traffic")
389	serverHandshakeTrafficLabel   = []byte("s hs traffic")
390	clientApplicationTrafficLabel = []byte("c ap traffic")
391	serverApplicationTrafficLabel = []byte("s ap traffic")
392	applicationTrafficLabel       = []byte("traffic upd")
393	earlyExporterLabel            = []byte("e exp master")
394	exporterLabel                 = []byte("exp master")
395	resumptionLabel               = []byte("res master")
396
397	resumptionPSKLabel = []byte("resumption")
398
399	echAcceptConfirmationLabel    = []byte("ech accept confirmation")
400	echAcceptConfirmationHRRLabel = []byte("hrr ech accept confirmation")
401)
402
403// deriveSecret implements TLS 1.3's Derive-Secret function, as defined in
404// section 7.1 of RFC8446.
405func (h *finishedHash) deriveSecret(label []byte) []byte {
406	return hkdfExpandLabel(h.suite.hash(), h.secret, label, h.appendContextHashes(nil), h.hash.Size())
407}
408
409// echConfirmation computes the ECH accept confirmation signal, as defined in
410// sections 7.2 and 7.2.1 of draft-ietf-tls-esni-13. The transcript hash is
411// computed by concatenating |h| with |extraMessages|.
412func (h *finishedHash) echAcceptConfirmation(clientRandom, label, extraMessages []byte) []byte {
413	secret := hkdf.Extract(h.suite.hash().New, clientRandom, h.zeroSecret())
414	hashCopy := copyHash(h.hash, h.suite.hash())
415	hashCopy.Write(extraMessages)
416	return hkdfExpandLabel(h.suite.hash(), secret, label, hashCopy.Sum(nil), echAcceptConfirmationLength)
417}
418
419// The following are context strings for CertificateVerify in TLS 1.3.
420var (
421	clientCertificateVerifyContextTLS13 = []byte("TLS 1.3, client CertificateVerify")
422	serverCertificateVerifyContextTLS13 = []byte("TLS 1.3, server CertificateVerify")
423	channelIDContextTLS13               = []byte("TLS 1.3, Channel ID")
424)
425
426// certificateVerifyMessage returns the input to be signed for CertificateVerify
427// in TLS 1.3.
428func (h *finishedHash) certificateVerifyInput(context []byte) []byte {
429	const paddingLen = 64
430	b := make([]byte, paddingLen, paddingLen+len(context)+1+2*h.hash.Size())
431	for i := 0; i < paddingLen; i++ {
432		b[i] = 32
433	}
434	b = append(b, context...)
435	b = append(b, 0)
436	b = h.appendContextHashes(b)
437	return b
438}
439
440type trafficDirection int
441
442const (
443	clientWrite trafficDirection = iota
444	serverWrite
445)
446
447var (
448	keyTLS13 = []byte("key")
449	ivTLS13  = []byte("iv")
450)
451
452// deriveTrafficAEAD derives traffic keys and constructs an AEAD given a traffic
453// secret.
454func deriveTrafficAEAD(version uint16, suite *cipherSuite, secret []byte, side trafficDirection) interface{} {
455	key := hkdfExpandLabel(suite.hash(), secret, keyTLS13, nil, suite.keyLen)
456	iv := hkdfExpandLabel(suite.hash(), secret, ivTLS13, nil, suite.ivLen(version))
457
458	return suite.aead(version, key, iv)
459}
460
461func updateTrafficSecret(hash crypto.Hash, version uint16, secret []byte) []byte {
462	return hkdfExpandLabel(hash, secret, applicationTrafficLabel, nil, hash.Size())
463}
464
465func computePSKBinder(psk []byte, version uint16, label []byte, cipherSuite *cipherSuite, clientHello, helloRetryRequest, truncatedHello []byte) []byte {
466	finishedHash := newFinishedHash(version, false, cipherSuite)
467	finishedHash.addEntropy(psk)
468	binderKey := finishedHash.deriveSecret(label)
469	finishedHash.Write(clientHello)
470	if len(helloRetryRequest) != 0 {
471		finishedHash.UpdateForHelloRetryRequest()
472	}
473	finishedHash.Write(helloRetryRequest)
474	finishedHash.Write(truncatedHello)
475	return finishedHash.clientSum(binderKey)
476}
477
478func deriveSessionPSK(suite *cipherSuite, version uint16, masterSecret []byte, nonce []byte) []byte {
479	hash := suite.hash()
480	return hkdfExpandLabel(hash, masterSecret, resumptionPSKLabel, nonce, hash.Size())
481}
482