Source file src/pkg/crypto/tls/key_schedule.go
1
2
3
4
5 package tls
6
7 import (
8 "crypto/elliptic"
9 "crypto/hmac"
10 "crypto/subtle"
11 "errors"
12 "golang.org/x/crypto/cryptobyte"
13 "golang.org/x/crypto/curve25519"
14 "golang.org/x/crypto/hkdf"
15 "hash"
16 "io"
17 "math/big"
18 )
19
20
21
22
23 const (
24 resumptionBinderLabel = "res binder"
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 out := make([]byte, length)
46 n, err := hkdf.Expand(c.hash.New, secret, hkdfLabel.BytesOrPanic()).Read(out)
47 if err != nil || n != length {
48 panic("tls: HKDF-Expand-Label invocation failed unexpectedly")
49 }
50 return out
51 }
52
53
54 func (c *cipherSuiteTLS13) deriveSecret(secret []byte, label string, transcript hash.Hash) []byte {
55 if transcript == nil {
56 transcript = c.hash.New()
57 }
58 return c.expandLabel(secret, label, transcript.Sum(nil), c.hash.Size())
59 }
60
61
62 func (c *cipherSuiteTLS13) extract(newSecret, currentSecret []byte) []byte {
63 if newSecret == nil {
64 newSecret = make([]byte, c.hash.Size())
65 }
66 return hkdf.Extract(c.hash.New, newSecret, currentSecret)
67 }
68
69
70
71 func (c *cipherSuiteTLS13) nextTrafficSecret(trafficSecret []byte) []byte {
72 return c.expandLabel(trafficSecret, trafficUpdateLabel, nil, c.hash.Size())
73 }
74
75
76 func (c *cipherSuiteTLS13) trafficKey(trafficSecret []byte) (key, iv []byte) {
77 key = c.expandLabel(trafficSecret, "key", nil, c.keyLen)
78 iv = c.expandLabel(trafficSecret, "iv", nil, aeadNonceLength)
79 return
80 }
81
82
83
84
85 func (c *cipherSuiteTLS13) finishedHash(baseKey []byte, transcript hash.Hash) []byte {
86 finishedKey := c.expandLabel(baseKey, "finished", nil, c.hash.Size())
87 verifyData := hmac.New(c.hash.New, finishedKey)
88 verifyData.Write(transcript.Sum(nil))
89 return verifyData.Sum(nil)
90 }
91
92
93
94 func (c *cipherSuiteTLS13) exportKeyingMaterial(masterSecret []byte, transcript hash.Hash) func(string, []byte, int) ([]byte, error) {
95 expMasterSecret := c.deriveSecret(masterSecret, exporterLabel, transcript)
96 return func(label string, context []byte, length int) ([]byte, error) {
97 secret := c.deriveSecret(expMasterSecret, label, nil)
98 h := c.hash.New()
99 h.Write(context)
100 return c.expandLabel(secret, "exporter", h.Sum(nil), length), nil
101 }
102 }
103
104
105
106 type ecdheParameters interface {
107 CurveID() CurveID
108 PublicKey() []byte
109 SharedKey(peerPublicKey []byte) []byte
110 }
111
112 func generateECDHEParameters(rand io.Reader, curveID CurveID) (ecdheParameters, error) {
113 if curveID == X25519 {
114 p := &x25519Parameters{}
115 if _, err := io.ReadFull(rand, p.privateKey[:]); err != nil {
116 return nil, err
117 }
118 curve25519.ScalarBaseMult(&p.publicKey, &p.privateKey)
119 return p, nil
120 }
121
122 curve, ok := curveForCurveID(curveID)
123 if !ok {
124 return nil, errors.New("tls: internal error: unsupported curve")
125 }
126
127 p := &nistParameters{curveID: curveID}
128 var err error
129 p.privateKey, p.x, p.y, err = elliptic.GenerateKey(curve, rand)
130 if err != nil {
131 return nil, err
132 }
133 return p, nil
134 }
135
136 func curveForCurveID(id CurveID) (elliptic.Curve, bool) {
137 switch id {
138 case CurveP256:
139 return elliptic.P256(), true
140 case CurveP384:
141 return elliptic.P384(), true
142 case CurveP521:
143 return elliptic.P521(), true
144 default:
145 return nil, false
146 }
147 }
148
149 type nistParameters struct {
150 privateKey []byte
151 x, y *big.Int
152 curveID CurveID
153 }
154
155 func (p *nistParameters) CurveID() CurveID {
156 return p.curveID
157 }
158
159 func (p *nistParameters) PublicKey() []byte {
160 curve, _ := curveForCurveID(p.curveID)
161 return elliptic.Marshal(curve, p.x, p.y)
162 }
163
164 func (p *nistParameters) SharedKey(peerPublicKey []byte) []byte {
165 curve, _ := curveForCurveID(p.curveID)
166
167 x, y := elliptic.Unmarshal(curve, peerPublicKey)
168 if x == nil {
169 return nil
170 }
171
172 xShared, _ := curve.ScalarMult(x, y, p.privateKey)
173 sharedKey := make([]byte, (curve.Params().BitSize+7)>>3)
174 xBytes := xShared.Bytes()
175 copy(sharedKey[len(sharedKey)-len(xBytes):], xBytes)
176
177 return sharedKey
178 }
179
180 type x25519Parameters struct {
181 privateKey [32]byte
182 publicKey [32]byte
183 }
184
185 func (p *x25519Parameters) CurveID() CurveID {
186 return X25519
187 }
188
189 func (p *x25519Parameters) PublicKey() []byte {
190 return p.publicKey[:]
191 }
192
193 func (p *x25519Parameters) SharedKey(peerPublicKey []byte) []byte {
194 if len(peerPublicKey) != 32 {
195 return nil
196 }
197
198 var theirPublicKey, sharedKey [32]byte
199 copy(theirPublicKey[:], peerPublicKey)
200 curve25519.ScalarMult(&sharedKey, &p.privateKey, &theirPublicKey)
201
202
203 var allZeroes [32]byte
204 if subtle.ConstantTimeCompare(allZeroes[:], sharedKey[:]) == 1 {
205 return nil
206 }
207
208 return sharedKey[:]
209 }
210
View as plain text