Source file
src/crypto/tls/key_schedule.go
1
2
3
4
5 package tls
6
7 import (
8 "crypto/ecdh"
9 "crypto/hmac"
10 "errors"
11 "fmt"
12 "hash"
13 "io"
14
15 "golang.org/x/crypto/cryptobyte"
16 "golang.org/x/crypto/hkdf"
17 )
18
19
20
21
22 const (
23 resumptionBinderLabel = "res binder"
24 clientEarlyTrafficLabel = "c e traffic"
25 clientHandshakeTrafficLabel = "c hs traffic"
26 serverHandshakeTrafficLabel = "s hs traffic"
27 clientApplicationTrafficLabel = "c ap traffic"
28 serverApplicationTrafficLabel = "s ap traffic"
29 exporterLabel = "exp master"
30 resumptionLabel = "res master"
31 trafficUpdateLabel = "traffic upd"
32 )
33
34
35 func (c *cipherSuiteTLS13) expandLabel(secret []byte, label string, context []byte, length int) []byte {
36 var hkdfLabel cryptobyte.Builder
37 hkdfLabel.AddUint16(uint16(length))
38 hkdfLabel.AddUint8LengthPrefixed(func(b *cryptobyte.Builder) {
39 b.AddBytes([]byte("tls13 "))
40 b.AddBytes([]byte(label))
41 })
42 hkdfLabel.AddUint8LengthPrefixed(func(b *cryptobyte.Builder) {
43 b.AddBytes(context)
44 })
45 hkdfLabelBytes, err := hkdfLabel.Bytes()
46 if err != nil {
47
48
49
50
51
52
53
54
55
56
57
58
59 panic(fmt.Errorf("failed to construct HKDF label: %s", err))
60 }
61 out := make([]byte, length)
62 n, err := hkdf.Expand(c.hash.New, secret, hkdfLabelBytes).Read(out)
63 if err != nil || n != length {
64 panic("tls: HKDF-Expand-Label invocation failed unexpectedly")
65 }
66 return out
67 }
68
69
70 func (c *cipherSuiteTLS13) deriveSecret(secret []byte, label string, transcript hash.Hash) []byte {
71 if transcript == nil {
72 transcript = c.hash.New()
73 }
74 return c.expandLabel(secret, label, transcript.Sum(nil), c.hash.Size())
75 }
76
77
78 func (c *cipherSuiteTLS13) extract(newSecret, currentSecret []byte) []byte {
79 if newSecret == nil {
80 newSecret = make([]byte, c.hash.Size())
81 }
82 return hkdf.Extract(c.hash.New, newSecret, currentSecret)
83 }
84
85
86
87 func (c *cipherSuiteTLS13) nextTrafficSecret(trafficSecret []byte) []byte {
88 return c.expandLabel(trafficSecret, trafficUpdateLabel, nil, c.hash.Size())
89 }
90
91
92 func (c *cipherSuiteTLS13) trafficKey(trafficSecret []byte) (key, iv []byte) {
93 key = c.expandLabel(trafficSecret, "key", nil, c.keyLen)
94 iv = c.expandLabel(trafficSecret, "iv", nil, aeadNonceLength)
95 return
96 }
97
98
99
100
101 func (c *cipherSuiteTLS13) finishedHash(baseKey []byte, transcript hash.Hash) []byte {
102 finishedKey := c.expandLabel(baseKey, "finished", nil, c.hash.Size())
103 verifyData := hmac.New(c.hash.New, finishedKey)
104 verifyData.Write(transcript.Sum(nil))
105 return verifyData.Sum(nil)
106 }
107
108
109
110 func (c *cipherSuiteTLS13) exportKeyingMaterial(masterSecret []byte, transcript hash.Hash) func(string, []byte, int) ([]byte, error) {
111 expMasterSecret := c.deriveSecret(masterSecret, exporterLabel, transcript)
112 return func(label string, context []byte, length int) ([]byte, error) {
113 secret := c.deriveSecret(expMasterSecret, label, nil)
114 h := c.hash.New()
115 h.Write(context)
116 return c.expandLabel(secret, "exporter", h.Sum(nil), length), nil
117 }
118 }
119
120
121
122 func generateECDHEKey(rand io.Reader, curveID CurveID) (*ecdh.PrivateKey, error) {
123 curve, ok := curveForCurveID(curveID)
124 if !ok {
125 return nil, errors.New("tls: internal error: unsupported curve")
126 }
127
128 return curve.GenerateKey(rand)
129 }
130
131 func curveForCurveID(id CurveID) (ecdh.Curve, bool) {
132 switch id {
133 case X25519:
134 return ecdh.X25519(), true
135 case CurveP256:
136 return ecdh.P256(), true
137 case CurveP384:
138 return ecdh.P384(), true
139 case CurveP521:
140 return ecdh.P521(), true
141 default:
142 return nil, false
143 }
144 }
145
146 func curveIDForCurve(curve ecdh.Curve) (CurveID, bool) {
147 switch curve {
148 case ecdh.X25519():
149 return X25519, true
150 case ecdh.P256():
151 return CurveP256, true
152 case ecdh.P384():
153 return CurveP384, true
154 case ecdh.P521():
155 return CurveP521, true
156 default:
157 return 0, false
158 }
159 }
160
View as plain text