Source file
src/crypto/tls/key_schedule.go
1
2
3
4
5 package tls
6
7 import (
8 "crypto"
9 "crypto/ecdh"
10 "crypto/fips140"
11 "crypto/hmac"
12 "crypto/internal/fips140/tls13"
13 "crypto/mlkem"
14 "errors"
15 "hash"
16 "io"
17 )
18
19
20
21
22
23
24 func (c *cipherSuiteTLS13) nextTrafficSecret(trafficSecret []byte) []byte {
25 return tls13.ExpandLabel(c.hash.New, trafficSecret, "traffic upd", nil, c.hash.Size())
26 }
27
28
29 func (c *cipherSuiteTLS13) trafficKey(trafficSecret []byte) (key, iv []byte) {
30 key = tls13.ExpandLabel(c.hash.New, trafficSecret, "key", nil, c.keyLen)
31 iv = tls13.ExpandLabel(c.hash.New, trafficSecret, "iv", nil, aeadNonceLength)
32 return
33 }
34
35
36
37
38 func (c *cipherSuiteTLS13) finishedHash(baseKey []byte, transcript hash.Hash) []byte {
39 finishedKey := tls13.ExpandLabel(c.hash.New, baseKey, "finished", nil, c.hash.Size())
40 verifyData := hmac.New(c.hash.New, finishedKey)
41 verifyData.Write(transcript.Sum(nil))
42 return verifyData.Sum(nil)
43 }
44
45
46
47 func (c *cipherSuiteTLS13) exportKeyingMaterial(s *tls13.MasterSecret, transcript hash.Hash) func(string, []byte, int) ([]byte, error) {
48 expMasterSecret := s.ExporterMasterSecret(transcript)
49 return func(label string, context []byte, length int) ([]byte, error) {
50 return expMasterSecret.Exporter(label, context, length), nil
51 }
52 }
53
54 type keySharePrivateKeys struct {
55 ecdhe *ecdh.PrivateKey
56 mlkem crypto.Decapsulator
57 }
58
59
60 type keyExchange interface {
61
62
63
64
65
66 keyShares(rand io.Reader) (*keySharePrivateKeys, []keyShare, error)
67
68
69 serverSharedSecret(rand io.Reader, clientKeyShare []byte) ([]byte, keyShare, error)
70
71
72
73 clientSharedSecret(priv *keySharePrivateKeys, serverKeyShare []byte) ([]byte, error)
74 }
75
76 func keyExchangeForCurveID(id CurveID) (keyExchange, error) {
77 newMLKEMPrivateKey768 := func(b []byte) (crypto.Decapsulator, error) {
78 return mlkem.NewDecapsulationKey768(b)
79 }
80 newMLKEMPrivateKey1024 := func(b []byte) (crypto.Decapsulator, error) {
81 return mlkem.NewDecapsulationKey1024(b)
82 }
83 newMLKEMPublicKey768 := func(b []byte) (crypto.Encapsulator, error) {
84 return mlkem.NewEncapsulationKey768(b)
85 }
86 newMLKEMPublicKey1024 := func(b []byte) (crypto.Encapsulator, error) {
87 return mlkem.NewEncapsulationKey1024(b)
88 }
89 switch id {
90 case X25519:
91 return &ecdhKeyExchange{id, ecdh.X25519()}, nil
92 case CurveP256:
93 return &ecdhKeyExchange{id, ecdh.P256()}, nil
94 case CurveP384:
95 return &ecdhKeyExchange{id, ecdh.P384()}, nil
96 case CurveP521:
97 return &ecdhKeyExchange{id, ecdh.P521()}, nil
98 case X25519MLKEM768:
99 return &hybridKeyExchange{id, ecdhKeyExchange{X25519, ecdh.X25519()},
100 32, mlkem.EncapsulationKeySize768, mlkem.CiphertextSize768,
101 newMLKEMPrivateKey768, newMLKEMPublicKey768}, nil
102 case SecP256r1MLKEM768:
103 return &hybridKeyExchange{id, ecdhKeyExchange{CurveP256, ecdh.P256()},
104 65, mlkem.EncapsulationKeySize768, mlkem.CiphertextSize768,
105 newMLKEMPrivateKey768, newMLKEMPublicKey768}, nil
106 case SecP384r1MLKEM1024:
107 return &hybridKeyExchange{id, ecdhKeyExchange{CurveP384, ecdh.P384()},
108 97, mlkem.EncapsulationKeySize1024, mlkem.CiphertextSize1024,
109 newMLKEMPrivateKey1024, newMLKEMPublicKey1024}, nil
110 default:
111 return nil, errors.New("tls: unsupported key exchange")
112 }
113 }
114
115 type ecdhKeyExchange struct {
116 id CurveID
117 curve ecdh.Curve
118 }
119
120 func (ke *ecdhKeyExchange) keyShares(rand io.Reader) (*keySharePrivateKeys, []keyShare, error) {
121 priv, err := ke.curve.GenerateKey(rand)
122 if err != nil {
123 return nil, nil, err
124 }
125 return &keySharePrivateKeys{ecdhe: priv}, []keyShare{{ke.id, priv.PublicKey().Bytes()}}, nil
126 }
127
128 func (ke *ecdhKeyExchange) serverSharedSecret(rand io.Reader, clientKeyShare []byte) ([]byte, keyShare, error) {
129 key, err := ke.curve.GenerateKey(rand)
130 if err != nil {
131 return nil, keyShare{}, err
132 }
133 peerKey, err := ke.curve.NewPublicKey(clientKeyShare)
134 if err != nil {
135 return nil, keyShare{}, err
136 }
137 sharedKey, err := key.ECDH(peerKey)
138 if err != nil {
139 return nil, keyShare{}, err
140 }
141 return sharedKey, keyShare{ke.id, key.PublicKey().Bytes()}, nil
142 }
143
144 func (ke *ecdhKeyExchange) clientSharedSecret(priv *keySharePrivateKeys, serverKeyShare []byte) ([]byte, error) {
145 peerKey, err := ke.curve.NewPublicKey(serverKeyShare)
146 if err != nil {
147 return nil, err
148 }
149 sharedKey, err := priv.ecdhe.ECDH(peerKey)
150 if err != nil {
151 return nil, err
152 }
153 return sharedKey, nil
154 }
155
156 type hybridKeyExchange struct {
157 id CurveID
158 ecdh ecdhKeyExchange
159
160 ecdhElementSize int
161 mlkemPublicKeySize int
162 mlkemCiphertextSize int
163
164 newMLKEMPrivateKey func([]byte) (crypto.Decapsulator, error)
165 newMLKEMPublicKey func([]byte) (crypto.Encapsulator, error)
166 }
167
168 func (ke *hybridKeyExchange) keyShares(rand io.Reader) (*keySharePrivateKeys, []keyShare, error) {
169 var (
170 priv *keySharePrivateKeys
171 ecdhShares []keyShare
172 err error
173 )
174 fips140.WithoutEnforcement(func() {
175 priv, ecdhShares, err = ke.ecdh.keyShares(rand)
176 })
177 if err != nil {
178 return nil, nil, err
179 }
180 seed := make([]byte, mlkem.SeedSize)
181 if _, err := io.ReadFull(rand, seed); err != nil {
182 return nil, nil, err
183 }
184 priv.mlkem, err = ke.newMLKEMPrivateKey(seed)
185 if err != nil {
186 return nil, nil, err
187 }
188 var shareData []byte
189
190
191
192 if ke.id == X25519MLKEM768 {
193 shareData = append(priv.mlkem.Encapsulator().Bytes(), ecdhShares[0].data...)
194 } else {
195 shareData = append(ecdhShares[0].data, priv.mlkem.Encapsulator().Bytes()...)
196 }
197 return priv, []keyShare{{ke.id, shareData}, ecdhShares[0]}, nil
198 }
199
200 func (ke *hybridKeyExchange) serverSharedSecret(rand io.Reader, clientKeyShare []byte) ([]byte, keyShare, error) {
201 if len(clientKeyShare) != ke.ecdhElementSize+ke.mlkemPublicKeySize {
202 return nil, keyShare{}, errors.New("tls: invalid client key share length for hybrid key exchange")
203 }
204 var ecdhShareData, mlkemShareData []byte
205 if ke.id == X25519MLKEM768 {
206 mlkemShareData = clientKeyShare[:ke.mlkemPublicKeySize]
207 ecdhShareData = clientKeyShare[ke.mlkemPublicKeySize:]
208 } else {
209 ecdhShareData = clientKeyShare[:ke.ecdhElementSize]
210 mlkemShareData = clientKeyShare[ke.ecdhElementSize:]
211 }
212 var (
213 ecdhSharedSecret []byte
214 ks keyShare
215 err error
216 )
217 fips140.WithoutEnforcement(func() {
218 ecdhSharedSecret, ks, err = ke.ecdh.serverSharedSecret(rand, ecdhShareData)
219 })
220 if err != nil {
221 return nil, keyShare{}, err
222 }
223 mlkemPeerKey, err := ke.newMLKEMPublicKey(mlkemShareData)
224 if err != nil {
225 return nil, keyShare{}, err
226 }
227 mlkemSharedSecret, mlkemKeyShare := mlkemPeerKey.Encapsulate()
228 var sharedKey []byte
229 if ke.id == X25519MLKEM768 {
230 sharedKey = append(mlkemSharedSecret, ecdhSharedSecret...)
231 ks.data = append(mlkemKeyShare, ks.data...)
232 } else {
233 sharedKey = append(ecdhSharedSecret, mlkemSharedSecret...)
234 ks.data = append(ks.data, mlkemKeyShare...)
235 }
236 ks.group = ke.id
237 return sharedKey, ks, nil
238 }
239
240 func (ke *hybridKeyExchange) clientSharedSecret(priv *keySharePrivateKeys, serverKeyShare []byte) ([]byte, error) {
241 if len(serverKeyShare) != ke.ecdhElementSize+ke.mlkemCiphertextSize {
242 return nil, errors.New("tls: invalid server key share length for hybrid key exchange")
243 }
244 var ecdhShareData, mlkemShareData []byte
245 if ke.id == X25519MLKEM768 {
246 mlkemShareData = serverKeyShare[:ke.mlkemCiphertextSize]
247 ecdhShareData = serverKeyShare[ke.mlkemCiphertextSize:]
248 } else {
249 ecdhShareData = serverKeyShare[:ke.ecdhElementSize]
250 mlkemShareData = serverKeyShare[ke.ecdhElementSize:]
251 }
252 var (
253 ecdhSharedSecret []byte
254 err error
255 )
256 fips140.WithoutEnforcement(func() {
257 ecdhSharedSecret, err = ke.ecdh.clientSharedSecret(priv, ecdhShareData)
258 })
259 if err != nil {
260 return nil, err
261 }
262 mlkemSharedSecret, err := priv.mlkem.Decapsulate(mlkemShareData)
263 if err != nil {
264 return nil, err
265 }
266 var sharedKey []byte
267 if ke.id == X25519MLKEM768 {
268 sharedKey = append(mlkemSharedSecret, ecdhSharedSecret...)
269 } else {
270 sharedKey = append(ecdhSharedSecret, mlkemSharedSecret...)
271 }
272 return sharedKey, nil
273 }
274
View as plain text