]> Cypherpunks.ru repositories - gostls13.git/blob - src/crypto/tls/key_agreement.go
[dev.boringcrypto] all: merge master into dev.boringcrypto
[gostls13.git] / src / crypto / tls / key_agreement.go
1 // Copyright 2010 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
5 package tls
6
7 import (
8         "crypto"
9         "crypto/md5"
10         "crypto/rsa"
11         "crypto/sha1"
12         "crypto/x509"
13         "errors"
14         "io"
15 )
16
17 var errClientKeyExchange = errors.New("tls: invalid ClientKeyExchange message")
18 var errServerKeyExchange = errors.New("tls: invalid ServerKeyExchange message")
19
20 // rsaKeyAgreement implements the standard TLS key agreement where the client
21 // encrypts the pre-master secret to the server's public key.
22 type rsaKeyAgreement struct{}
23
24 func (ka rsaKeyAgreement) generateServerKeyExchange(config *Config, cert *Certificate, clientHello *clientHelloMsg, hello *serverHelloMsg) (*serverKeyExchangeMsg, error) {
25         return nil, nil
26 }
27
28 func (ka rsaKeyAgreement) processClientKeyExchange(config *Config, cert *Certificate, ckx *clientKeyExchangeMsg, version uint16) ([]byte, error) {
29         if len(ckx.ciphertext) < 2 {
30                 return nil, errClientKeyExchange
31         }
32
33         ciphertext := ckx.ciphertext
34         if version != VersionSSL30 {
35                 ciphertextLen := int(ckx.ciphertext[0])<<8 | int(ckx.ciphertext[1])
36                 if ciphertextLen != len(ckx.ciphertext)-2 {
37                         return nil, errClientKeyExchange
38                 }
39                 ciphertext = ckx.ciphertext[2:]
40         }
41         priv, ok := cert.PrivateKey.(crypto.Decrypter)
42         if !ok {
43                 return nil, errors.New("tls: certificate private key does not implement crypto.Decrypter")
44         }
45         // Perform constant time RSA PKCS#1 v1.5 decryption
46         preMasterSecret, err := priv.Decrypt(config.rand(), ciphertext, &rsa.PKCS1v15DecryptOptions{SessionKeyLen: 48})
47         if err != nil {
48                 return nil, err
49         }
50         // We don't check the version number in the premaster secret. For one,
51         // by checking it, we would leak information about the validity of the
52         // encrypted pre-master secret. Secondly, it provides only a small
53         // benefit against a downgrade attack and some implementations send the
54         // wrong version anyway. See the discussion at the end of section
55         // 7.4.7.1 of RFC 4346.
56         return preMasterSecret, nil
57 }
58
59 func (ka rsaKeyAgreement) processServerKeyExchange(config *Config, clientHello *clientHelloMsg, serverHello *serverHelloMsg, cert *x509.Certificate, skx *serverKeyExchangeMsg) error {
60         return errors.New("tls: unexpected ServerKeyExchange")
61 }
62
63 func (ka rsaKeyAgreement) generateClientKeyExchange(config *Config, clientHello *clientHelloMsg, cert *x509.Certificate) ([]byte, *clientKeyExchangeMsg, error) {
64         preMasterSecret := make([]byte, 48)
65         preMasterSecret[0] = byte(clientHello.vers >> 8)
66         preMasterSecret[1] = byte(clientHello.vers)
67         _, err := io.ReadFull(config.rand(), preMasterSecret[2:])
68         if err != nil {
69                 return nil, nil, err
70         }
71
72         encrypted, err := rsa.EncryptPKCS1v15(config.rand(), cert.PublicKey.(*rsa.PublicKey), preMasterSecret)
73         if err != nil {
74                 return nil, nil, err
75         }
76         ckx := new(clientKeyExchangeMsg)
77         ckx.ciphertext = make([]byte, len(encrypted)+2)
78         ckx.ciphertext[0] = byte(len(encrypted) >> 8)
79         ckx.ciphertext[1] = byte(len(encrypted))
80         copy(ckx.ciphertext[2:], encrypted)
81         return preMasterSecret, ckx, nil
82 }
83
84 // sha1Hash calculates a SHA1 hash over the given byte slices.
85 func sha1Hash(slices [][]byte) []byte {
86         hsha1 := sha1.New()
87         for _, slice := range slices {
88                 hsha1.Write(slice)
89         }
90         return hsha1.Sum(nil)
91 }
92
93 // md5SHA1Hash implements TLS 1.0's hybrid hash function which consists of the
94 // concatenation of an MD5 and SHA1 hash.
95 func md5SHA1Hash(slices [][]byte) []byte {
96         md5sha1 := make([]byte, md5.Size+sha1.Size)
97         hmd5 := md5.New()
98         for _, slice := range slices {
99                 hmd5.Write(slice)
100         }
101         copy(md5sha1, hmd5.Sum(nil))
102         copy(md5sha1[md5.Size:], sha1Hash(slices))
103         return md5sha1
104 }
105
106 // hashForServerKeyExchange hashes the given slices and returns their digest
107 // using the given hash function (for >= TLS 1.2) or using a default based on
108 // the sigType (for earlier TLS versions). For Ed25519 signatures, which don't
109 // do pre-hashing, it returns the concatenation of the slices.
110 func hashForServerKeyExchange(sigType uint8, hashFunc crypto.Hash, version uint16, slices ...[]byte) []byte {
111         if sigType == signatureEd25519 {
112                 var signed []byte
113                 for _, slice := range slices {
114                         signed = append(signed, slice...)
115                 }
116                 return signed
117         }
118         if version >= VersionTLS12 {
119                 h := hashFunc.New()
120                 for _, slice := range slices {
121                         h.Write(slice)
122                 }
123                 digest := h.Sum(nil)
124                 return digest
125         }
126         if sigType == signatureECDSA {
127                 return sha1Hash(slices)
128         }
129         return md5SHA1Hash(slices)
130 }
131
132 // ecdheKeyAgreement implements a TLS key agreement where the server
133 // generates an ephemeral EC public/private key pair and signs it. The
134 // pre-master secret is then calculated using ECDH. The signature may
135 // be ECDSA, Ed25519 or RSA.
136 type ecdheKeyAgreement struct {
137         version uint16
138         isRSA   bool
139         params  ecdheParameters
140
141         // ckx and preMasterSecret are generated in processServerKeyExchange
142         // and returned in generateClientKeyExchange.
143         ckx             *clientKeyExchangeMsg
144         preMasterSecret []byte
145 }
146
147 func (ka *ecdheKeyAgreement) generateServerKeyExchange(config *Config, cert *Certificate, clientHello *clientHelloMsg, hello *serverHelloMsg) (*serverKeyExchangeMsg, error) {
148         preferredCurves := config.curvePreferences()
149
150         var curveID CurveID
151 NextCandidate:
152         for _, candidate := range preferredCurves {
153                 for _, c := range clientHello.supportedCurves {
154                         if candidate == c {
155                                 curveID = c
156                                 break NextCandidate
157                         }
158                 }
159         }
160
161         if curveID == 0 {
162                 return nil, errors.New("tls: no supported elliptic curves offered")
163         }
164         if _, ok := curveForCurveID(curveID); curveID != X25519 && !ok {
165                 return nil, errors.New("tls: CurvePreferences includes unsupported curve")
166         }
167
168         params, err := generateECDHEParameters(config.rand(), curveID)
169         if err != nil {
170                 return nil, err
171         }
172         ka.params = params
173
174         // See RFC 4492, Section 5.4.
175         ecdhePublic := params.PublicKey()
176         serverECDHParams := make([]byte, 1+2+1+len(ecdhePublic))
177         serverECDHParams[0] = 3 // named curve
178         serverECDHParams[1] = byte(curveID >> 8)
179         serverECDHParams[2] = byte(curveID)
180         serverECDHParams[3] = byte(len(ecdhePublic))
181         copy(serverECDHParams[4:], ecdhePublic)
182
183         priv, ok := cert.PrivateKey.(crypto.Signer)
184         if !ok {
185                 return nil, errors.New("tls: certificate private key does not implement crypto.Signer")
186         }
187
188         signatureAlgorithm, sigType, hashFunc, err := pickSignatureAlgorithm(priv.Public(), clientHello.supportedSignatureAlgorithms, supportedSignatureAlgorithmsTLS12(), ka.version)
189         if err != nil {
190                 return nil, err
191         }
192         if (sigType == signaturePKCS1v15 || sigType == signatureRSAPSS) != ka.isRSA {
193                 return nil, errors.New("tls: certificate cannot be used with the selected cipher suite")
194         }
195
196         signed := hashForServerKeyExchange(sigType, hashFunc, ka.version, clientHello.random, hello.random, serverECDHParams)
197
198         signOpts := crypto.SignerOpts(hashFunc)
199         if sigType == signatureRSAPSS {
200                 signOpts = &rsa.PSSOptions{SaltLength: rsa.PSSSaltLengthEqualsHash, Hash: hashFunc}
201         }
202         sig, err := priv.Sign(config.rand(), signed, signOpts)
203         if err != nil {
204                 return nil, errors.New("tls: failed to sign ECDHE parameters: " + err.Error())
205         }
206
207         skx := new(serverKeyExchangeMsg)
208         sigAndHashLen := 0
209         if ka.version >= VersionTLS12 {
210                 sigAndHashLen = 2
211         }
212         skx.key = make([]byte, len(serverECDHParams)+sigAndHashLen+2+len(sig))
213         copy(skx.key, serverECDHParams)
214         k := skx.key[len(serverECDHParams):]
215         if ka.version >= VersionTLS12 {
216                 k[0] = byte(signatureAlgorithm >> 8)
217                 k[1] = byte(signatureAlgorithm)
218                 k = k[2:]
219         }
220         k[0] = byte(len(sig) >> 8)
221         k[1] = byte(len(sig))
222         copy(k[2:], sig)
223
224         return skx, nil
225 }
226
227 func (ka *ecdheKeyAgreement) processClientKeyExchange(config *Config, cert *Certificate, ckx *clientKeyExchangeMsg, version uint16) ([]byte, error) {
228         if len(ckx.ciphertext) == 0 || int(ckx.ciphertext[0]) != len(ckx.ciphertext)-1 {
229                 return nil, errClientKeyExchange
230         }
231
232         preMasterSecret := ka.params.SharedKey(ckx.ciphertext[1:])
233         if preMasterSecret == nil {
234                 return nil, errClientKeyExchange
235         }
236
237         return preMasterSecret, nil
238 }
239
240 func (ka *ecdheKeyAgreement) processServerKeyExchange(config *Config, clientHello *clientHelloMsg, serverHello *serverHelloMsg, cert *x509.Certificate, skx *serverKeyExchangeMsg) error {
241         if len(skx.key) < 4 {
242                 return errServerKeyExchange
243         }
244         if skx.key[0] != 3 { // named curve
245                 return errors.New("tls: server selected unsupported curve")
246         }
247         curveID := CurveID(skx.key[1])<<8 | CurveID(skx.key[2])
248
249         publicLen := int(skx.key[3])
250         if publicLen+4 > len(skx.key) {
251                 return errServerKeyExchange
252         }
253         serverECDHParams := skx.key[:4+publicLen]
254         publicKey := serverECDHParams[4:]
255
256         sig := skx.key[4+publicLen:]
257         if len(sig) < 2 {
258                 return errServerKeyExchange
259         }
260
261         if _, ok := curveForCurveID(curveID); curveID != X25519 && !ok {
262                 return errors.New("tls: server selected unsupported curve")
263         }
264
265         params, err := generateECDHEParameters(config.rand(), curveID)
266         if err != nil {
267                 return err
268         }
269         ka.params = params
270
271         ka.preMasterSecret = params.SharedKey(publicKey)
272         if ka.preMasterSecret == nil {
273                 return errServerKeyExchange
274         }
275
276         ourPublicKey := params.PublicKey()
277         ka.ckx = new(clientKeyExchangeMsg)
278         ka.ckx.ciphertext = make([]byte, 1+len(ourPublicKey))
279         ka.ckx.ciphertext[0] = byte(len(ourPublicKey))
280         copy(ka.ckx.ciphertext[1:], ourPublicKey)
281
282         var signatureAlgorithm SignatureScheme
283         if ka.version >= VersionTLS12 {
284                 // handle SignatureAndHashAlgorithm
285                 signatureAlgorithm = SignatureScheme(sig[0])<<8 | SignatureScheme(sig[1])
286                 sig = sig[2:]
287                 if len(sig) < 2 {
288                         return errServerKeyExchange
289                 }
290         }
291         _, sigType, hashFunc, err := pickSignatureAlgorithm(cert.PublicKey, []SignatureScheme{signatureAlgorithm}, clientHello.supportedSignatureAlgorithms, ka.version)
292         if err != nil {
293                 return err
294         }
295         if (sigType == signaturePKCS1v15 || sigType == signatureRSAPSS) != ka.isRSA {
296                 return errServerKeyExchange
297         }
298
299         sigLen := int(sig[0])<<8 | int(sig[1])
300         if sigLen+2 != len(sig) {
301                 return errServerKeyExchange
302         }
303         sig = sig[2:]
304
305         signed := hashForServerKeyExchange(sigType, hashFunc, ka.version, clientHello.random, serverHello.random, serverECDHParams)
306         return verifyHandshakeSignature(sigType, cert.PublicKey, hashFunc, signed, sig)
307 }
308
309 func (ka *ecdheKeyAgreement) generateClientKeyExchange(config *Config, clientHello *clientHelloMsg, cert *x509.Certificate) ([]byte, *clientKeyExchangeMsg, error) {
310         if ka.ckx == nil {
311                 return nil, nil, errors.New("tls: missing ServerKeyExchange message")
312         }
313
314         return ka.preMasterSecret, ka.ckx, nil
315 }