Source file
src/crypto/tls/key_agreement.go
1
2
3
4
5 package tls
6
7 import (
8 "crypto"
9 "crypto/ecdh"
10 "crypto/md5"
11 "crypto/rsa"
12 "crypto/sha1"
13 "crypto/x509"
14 "errors"
15 "fmt"
16 "io"
17 "slices"
18 )
19
20
21
22 type keyAgreement interface {
23
24
25
26
27
28 generateServerKeyExchange(*Config, *Certificate, *clientHelloMsg, *serverHelloMsg) (*serverKeyExchangeMsg, error)
29 processClientKeyExchange(*Config, *Certificate, *clientKeyExchangeMsg, uint16) ([]byte, error)
30
31
32
33
34
35 processServerKeyExchange(*Config, *clientHelloMsg, *serverHelloMsg, *x509.Certificate, *serverKeyExchangeMsg) error
36 generateClientKeyExchange(*Config, *clientHelloMsg, *x509.Certificate) ([]byte, *clientKeyExchangeMsg, error)
37 }
38
39 var errClientKeyExchange = errors.New("tls: invalid ClientKeyExchange message")
40 var errServerKeyExchange = errors.New("tls: invalid ServerKeyExchange message")
41
42
43
44 type rsaKeyAgreement struct{}
45
46 func (ka rsaKeyAgreement) generateServerKeyExchange(config *Config, cert *Certificate, clientHello *clientHelloMsg, hello *serverHelloMsg) (*serverKeyExchangeMsg, error) {
47 return nil, nil
48 }
49
50 func (ka rsaKeyAgreement) processClientKeyExchange(config *Config, cert *Certificate, ckx *clientKeyExchangeMsg, version uint16) ([]byte, error) {
51 if len(ckx.ciphertext) < 2 {
52 return nil, errClientKeyExchange
53 }
54 ciphertextLen := int(ckx.ciphertext[0])<<8 | int(ckx.ciphertext[1])
55 if ciphertextLen != len(ckx.ciphertext)-2 {
56 return nil, errClientKeyExchange
57 }
58 ciphertext := ckx.ciphertext[2:]
59
60 priv, ok := cert.PrivateKey.(crypto.Decrypter)
61 if !ok {
62 return nil, errors.New("tls: certificate private key does not implement crypto.Decrypter")
63 }
64
65 preMasterSecret, err := priv.Decrypt(config.rand(), ciphertext, &rsa.PKCS1v15DecryptOptions{SessionKeyLen: 48})
66 if err != nil {
67 return nil, err
68 }
69
70
71
72
73
74
75 return preMasterSecret, nil
76 }
77
78 func (ka rsaKeyAgreement) processServerKeyExchange(config *Config, clientHello *clientHelloMsg, serverHello *serverHelloMsg, cert *x509.Certificate, skx *serverKeyExchangeMsg) error {
79 return errors.New("tls: unexpected ServerKeyExchange")
80 }
81
82 func (ka rsaKeyAgreement) generateClientKeyExchange(config *Config, clientHello *clientHelloMsg, cert *x509.Certificate) ([]byte, *clientKeyExchangeMsg, error) {
83 preMasterSecret := make([]byte, 48)
84 preMasterSecret[0] = byte(clientHello.vers >> 8)
85 preMasterSecret[1] = byte(clientHello.vers)
86 _, err := io.ReadFull(config.rand(), preMasterSecret[2:])
87 if err != nil {
88 return nil, nil, err
89 }
90
91 rsaKey, ok := cert.PublicKey.(*rsa.PublicKey)
92 if !ok {
93 return nil, nil, errors.New("tls: server certificate contains incorrect key type for selected ciphersuite")
94 }
95 encrypted, err := rsa.EncryptPKCS1v15(config.rand(), rsaKey, preMasterSecret)
96 if err != nil {
97 return nil, nil, err
98 }
99 ckx := new(clientKeyExchangeMsg)
100 ckx.ciphertext = make([]byte, len(encrypted)+2)
101 ckx.ciphertext[0] = byte(len(encrypted) >> 8)
102 ckx.ciphertext[1] = byte(len(encrypted))
103 copy(ckx.ciphertext[2:], encrypted)
104 return preMasterSecret, ckx, nil
105 }
106
107
108 func sha1Hash(slices [][]byte) []byte {
109 hsha1 := sha1.New()
110 for _, slice := range slices {
111 hsha1.Write(slice)
112 }
113 return hsha1.Sum(nil)
114 }
115
116
117
118 func md5SHA1Hash(slices [][]byte) []byte {
119 md5sha1 := make([]byte, md5.Size+sha1.Size)
120 hmd5 := md5.New()
121 for _, slice := range slices {
122 hmd5.Write(slice)
123 }
124 copy(md5sha1, hmd5.Sum(nil))
125 copy(md5sha1[md5.Size:], sha1Hash(slices))
126 return md5sha1
127 }
128
129
130
131
132
133 func hashForServerKeyExchange(sigType uint8, hashFunc crypto.Hash, version uint16, slices ...[]byte) []byte {
134 if sigType == signatureEd25519 {
135 var signed []byte
136 for _, slice := range slices {
137 signed = append(signed, slice...)
138 }
139 return signed
140 }
141 if version >= VersionTLS12 {
142 h := hashFunc.New()
143 for _, slice := range slices {
144 h.Write(slice)
145 }
146 digest := h.Sum(nil)
147 return digest
148 }
149 if sigType == signatureECDSA {
150 return sha1Hash(slices)
151 }
152 return md5SHA1Hash(slices)
153 }
154
155
156
157
158
159 type ecdheKeyAgreement struct {
160 version uint16
161 isRSA bool
162 key *ecdh.PrivateKey
163
164
165
166 ckx *clientKeyExchangeMsg
167 preMasterSecret []byte
168
169
170
171 curveID CurveID
172 signatureAlgorithm SignatureScheme
173 }
174
175 func (ka *ecdheKeyAgreement) generateServerKeyExchange(config *Config, cert *Certificate, clientHello *clientHelloMsg, hello *serverHelloMsg) (*serverKeyExchangeMsg, error) {
176 for _, c := range clientHello.supportedCurves {
177 if config.supportsCurve(ka.version, c) {
178 ka.curveID = c
179 break
180 }
181 }
182
183 if ka.curveID == 0 {
184 return nil, errors.New("tls: no supported elliptic curves offered")
185 }
186 if _, ok := curveForCurveID(ka.curveID); !ok {
187 return nil, errors.New("tls: CurvePreferences includes unsupported curve")
188 }
189
190 key, err := generateECDHEKey(config.rand(), ka.curveID)
191 if err != nil {
192 return nil, err
193 }
194 ka.key = key
195
196
197 ecdhePublic := key.PublicKey().Bytes()
198 serverECDHEParams := make([]byte, 1+2+1+len(ecdhePublic))
199 serverECDHEParams[0] = 3
200 serverECDHEParams[1] = byte(ka.curveID >> 8)
201 serverECDHEParams[2] = byte(ka.curveID)
202 serverECDHEParams[3] = byte(len(ecdhePublic))
203 copy(serverECDHEParams[4:], ecdhePublic)
204
205 priv, ok := cert.PrivateKey.(crypto.Signer)
206 if !ok {
207 return nil, fmt.Errorf("tls: certificate private key of type %T does not implement crypto.Signer", cert.PrivateKey)
208 }
209
210 var sigType uint8
211 var sigHash crypto.Hash
212 if ka.version >= VersionTLS12 {
213 ka.signatureAlgorithm, err = selectSignatureScheme(ka.version, cert, clientHello.supportedSignatureAlgorithms)
214 if err != nil {
215 return nil, err
216 }
217 sigType, sigHash, err = typeAndHashFromSignatureScheme(ka.signatureAlgorithm)
218 if err != nil {
219 return nil, err
220 }
221 if sigHash == crypto.SHA1 {
222 tlssha1.Value()
223 tlssha1.IncNonDefault()
224 }
225 } else {
226 sigType, sigHash, err = legacyTypeAndHashFromPublicKey(priv.Public())
227 if err != nil {
228 return nil, err
229 }
230 }
231 if (sigType == signaturePKCS1v15 || sigType == signatureRSAPSS) != ka.isRSA {
232 return nil, errors.New("tls: certificate cannot be used with the selected cipher suite")
233 }
234
235 signed := hashForServerKeyExchange(sigType, sigHash, ka.version, clientHello.random, hello.random, serverECDHEParams)
236
237 signOpts := crypto.SignerOpts(sigHash)
238 if sigType == signatureRSAPSS {
239 signOpts = &rsa.PSSOptions{SaltLength: rsa.PSSSaltLengthEqualsHash, Hash: sigHash}
240 }
241 sig, err := priv.Sign(config.rand(), signed, signOpts)
242 if err != nil {
243 return nil, errors.New("tls: failed to sign ECDHE parameters: " + err.Error())
244 }
245
246 skx := new(serverKeyExchangeMsg)
247 sigAndHashLen := 0
248 if ka.version >= VersionTLS12 {
249 sigAndHashLen = 2
250 }
251 skx.key = make([]byte, len(serverECDHEParams)+sigAndHashLen+2+len(sig))
252 copy(skx.key, serverECDHEParams)
253 k := skx.key[len(serverECDHEParams):]
254 if ka.version >= VersionTLS12 {
255 k[0] = byte(ka.signatureAlgorithm >> 8)
256 k[1] = byte(ka.signatureAlgorithm)
257 k = k[2:]
258 }
259 k[0] = byte(len(sig) >> 8)
260 k[1] = byte(len(sig))
261 copy(k[2:], sig)
262
263 return skx, nil
264 }
265
266 func (ka *ecdheKeyAgreement) processClientKeyExchange(config *Config, cert *Certificate, ckx *clientKeyExchangeMsg, version uint16) ([]byte, error) {
267 if len(ckx.ciphertext) == 0 || int(ckx.ciphertext[0]) != len(ckx.ciphertext)-1 {
268 return nil, errClientKeyExchange
269 }
270
271 peerKey, err := ka.key.Curve().NewPublicKey(ckx.ciphertext[1:])
272 if err != nil {
273 return nil, errClientKeyExchange
274 }
275 preMasterSecret, err := ka.key.ECDH(peerKey)
276 if err != nil {
277 return nil, errClientKeyExchange
278 }
279
280 return preMasterSecret, nil
281 }
282
283 func (ka *ecdheKeyAgreement) processServerKeyExchange(config *Config, clientHello *clientHelloMsg, serverHello *serverHelloMsg, cert *x509.Certificate, skx *serverKeyExchangeMsg) error {
284 if len(skx.key) < 4 {
285 return errServerKeyExchange
286 }
287 if skx.key[0] != 3 {
288 return errors.New("tls: server selected unsupported curve")
289 }
290 ka.curveID = CurveID(skx.key[1])<<8 | CurveID(skx.key[2])
291
292 publicLen := int(skx.key[3])
293 if publicLen+4 > len(skx.key) {
294 return errServerKeyExchange
295 }
296 serverECDHEParams := skx.key[:4+publicLen]
297 publicKey := serverECDHEParams[4:]
298
299 sig := skx.key[4+publicLen:]
300 if len(sig) < 2 {
301 return errServerKeyExchange
302 }
303
304 if !slices.Contains(clientHello.supportedCurves, ka.curveID) {
305 return errors.New("tls: server selected unoffered curve")
306 }
307
308 if _, ok := curveForCurveID(ka.curveID); !ok {
309 return errors.New("tls: server selected unsupported curve")
310 }
311
312 key, err := generateECDHEKey(config.rand(), ka.curveID)
313 if err != nil {
314 return err
315 }
316 ka.key = key
317
318 peerKey, err := key.Curve().NewPublicKey(publicKey)
319 if err != nil {
320 return errServerKeyExchange
321 }
322 ka.preMasterSecret, err = key.ECDH(peerKey)
323 if err != nil {
324 return errServerKeyExchange
325 }
326
327 ourPublicKey := key.PublicKey().Bytes()
328 ka.ckx = new(clientKeyExchangeMsg)
329 ka.ckx.ciphertext = make([]byte, 1+len(ourPublicKey))
330 ka.ckx.ciphertext[0] = byte(len(ourPublicKey))
331 copy(ka.ckx.ciphertext[1:], ourPublicKey)
332
333 var sigType uint8
334 var sigHash crypto.Hash
335 if ka.version >= VersionTLS12 {
336 ka.signatureAlgorithm = SignatureScheme(sig[0])<<8 | SignatureScheme(sig[1])
337 sig = sig[2:]
338 if len(sig) < 2 {
339 return errServerKeyExchange
340 }
341
342 if !isSupportedSignatureAlgorithm(ka.signatureAlgorithm, clientHello.supportedSignatureAlgorithms) {
343 return errors.New("tls: certificate used with invalid signature algorithm")
344 }
345 sigType, sigHash, err = typeAndHashFromSignatureScheme(ka.signatureAlgorithm)
346 if err != nil {
347 return err
348 }
349 if sigHash == crypto.SHA1 {
350 tlssha1.Value()
351 tlssha1.IncNonDefault()
352 }
353 } else {
354 sigType, sigHash, err = legacyTypeAndHashFromPublicKey(cert.PublicKey)
355 if err != nil {
356 return err
357 }
358 }
359 if (sigType == signaturePKCS1v15 || sigType == signatureRSAPSS) != ka.isRSA {
360 return errServerKeyExchange
361 }
362
363 sigLen := int(sig[0])<<8 | int(sig[1])
364 if sigLen+2 != len(sig) {
365 return errServerKeyExchange
366 }
367 sig = sig[2:]
368
369 signed := hashForServerKeyExchange(sigType, sigHash, ka.version, clientHello.random, serverHello.random, serverECDHEParams)
370 if err := verifyHandshakeSignature(sigType, cert.PublicKey, sigHash, signed, sig); err != nil {
371 return errors.New("tls: invalid signature by the server certificate: " + err.Error())
372 }
373 return nil
374 }
375
376 func (ka *ecdheKeyAgreement) generateClientKeyExchange(config *Config, clientHello *clientHelloMsg, cert *x509.Certificate) ([]byte, *clientKeyExchangeMsg, error) {
377 if ka.ckx == nil {
378 return nil, nil, errors.New("tls: missing ServerKeyExchange message")
379 }
380
381 return ka.preMasterSecret, ka.ckx, nil
382 }
383
View as plain text