OSDN Git Service

Hulk did something
[bytom/vapor.git] / vendor / golang.org / x / crypto / ssh / kex.go
1 // Copyright 2013 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 ssh
6
7 import (
8         "crypto"
9         "crypto/ecdsa"
10         "crypto/elliptic"
11         "crypto/rand"
12         "crypto/subtle"
13         "errors"
14         "io"
15         "math/big"
16
17         "golang.org/x/crypto/curve25519"
18 )
19
20 const (
21         kexAlgoDH1SHA1          = "diffie-hellman-group1-sha1"
22         kexAlgoDH14SHA1         = "diffie-hellman-group14-sha1"
23         kexAlgoECDH256          = "ecdh-sha2-nistp256"
24         kexAlgoECDH384          = "ecdh-sha2-nistp384"
25         kexAlgoECDH521          = "ecdh-sha2-nistp521"
26         kexAlgoCurve25519SHA256 = "curve25519-sha256@libssh.org"
27 )
28
29 // kexResult captures the outcome of a key exchange.
30 type kexResult struct {
31         // Session hash. See also RFC 4253, section 8.
32         H []byte
33
34         // Shared secret. See also RFC 4253, section 8.
35         K []byte
36
37         // Host key as hashed into H.
38         HostKey []byte
39
40         // Signature of H.
41         Signature []byte
42
43         // A cryptographic hash function that matches the security
44         // level of the key exchange algorithm. It is used for
45         // calculating H, and for deriving keys from H and K.
46         Hash crypto.Hash
47
48         // The session ID, which is the first H computed. This is used
49         // to derive key material inside the transport.
50         SessionID []byte
51 }
52
53 // handshakeMagics contains data that is always included in the
54 // session hash.
55 type handshakeMagics struct {
56         clientVersion, serverVersion []byte
57         clientKexInit, serverKexInit []byte
58 }
59
60 func (m *handshakeMagics) write(w io.Writer) {
61         writeString(w, m.clientVersion)
62         writeString(w, m.serverVersion)
63         writeString(w, m.clientKexInit)
64         writeString(w, m.serverKexInit)
65 }
66
67 // kexAlgorithm abstracts different key exchange algorithms.
68 type kexAlgorithm interface {
69         // Server runs server-side key agreement, signing the result
70         // with a hostkey.
71         Server(p packetConn, rand io.Reader, magics *handshakeMagics, s Signer) (*kexResult, error)
72
73         // Client runs the client-side key agreement. Caller is
74         // responsible for verifying the host key signature.
75         Client(p packetConn, rand io.Reader, magics *handshakeMagics) (*kexResult, error)
76 }
77
78 // dhGroup is a multiplicative group suitable for implementing Diffie-Hellman key agreement.
79 type dhGroup struct {
80         g, p, pMinus1 *big.Int
81 }
82
83 func (group *dhGroup) diffieHellman(theirPublic, myPrivate *big.Int) (*big.Int, error) {
84         if theirPublic.Cmp(bigOne) <= 0 || theirPublic.Cmp(group.pMinus1) >= 0 {
85                 return nil, errors.New("ssh: DH parameter out of bounds")
86         }
87         return new(big.Int).Exp(theirPublic, myPrivate, group.p), nil
88 }
89
90 func (group *dhGroup) Client(c packetConn, randSource io.Reader, magics *handshakeMagics) (*kexResult, error) {
91         hashFunc := crypto.SHA1
92
93         var x *big.Int
94         for {
95                 var err error
96                 if x, err = rand.Int(randSource, group.pMinus1); err != nil {
97                         return nil, err
98                 }
99                 if x.Sign() > 0 {
100                         break
101                 }
102         }
103
104         X := new(big.Int).Exp(group.g, x, group.p)
105         kexDHInit := kexDHInitMsg{
106                 X: X,
107         }
108         if err := c.writePacket(Marshal(&kexDHInit)); err != nil {
109                 return nil, err
110         }
111
112         packet, err := c.readPacket()
113         if err != nil {
114                 return nil, err
115         }
116
117         var kexDHReply kexDHReplyMsg
118         if err = Unmarshal(packet, &kexDHReply); err != nil {
119                 return nil, err
120         }
121
122         kInt, err := group.diffieHellman(kexDHReply.Y, x)
123         if err != nil {
124                 return nil, err
125         }
126
127         h := hashFunc.New()
128         magics.write(h)
129         writeString(h, kexDHReply.HostKey)
130         writeInt(h, X)
131         writeInt(h, kexDHReply.Y)
132         K := make([]byte, intLength(kInt))
133         marshalInt(K, kInt)
134         h.Write(K)
135
136         return &kexResult{
137                 H:         h.Sum(nil),
138                 K:         K,
139                 HostKey:   kexDHReply.HostKey,
140                 Signature: kexDHReply.Signature,
141                 Hash:      crypto.SHA1,
142         }, nil
143 }
144
145 func (group *dhGroup) Server(c packetConn, randSource io.Reader, magics *handshakeMagics, priv Signer) (result *kexResult, err error) {
146         hashFunc := crypto.SHA1
147         packet, err := c.readPacket()
148         if err != nil {
149                 return
150         }
151         var kexDHInit kexDHInitMsg
152         if err = Unmarshal(packet, &kexDHInit); err != nil {
153                 return
154         }
155
156         var y *big.Int
157         for {
158                 if y, err = rand.Int(randSource, group.pMinus1); err != nil {
159                         return
160                 }
161                 if y.Sign() > 0 {
162                         break
163                 }
164         }
165
166         Y := new(big.Int).Exp(group.g, y, group.p)
167         kInt, err := group.diffieHellman(kexDHInit.X, y)
168         if err != nil {
169                 return nil, err
170         }
171
172         hostKeyBytes := priv.PublicKey().Marshal()
173
174         h := hashFunc.New()
175         magics.write(h)
176         writeString(h, hostKeyBytes)
177         writeInt(h, kexDHInit.X)
178         writeInt(h, Y)
179
180         K := make([]byte, intLength(kInt))
181         marshalInt(K, kInt)
182         h.Write(K)
183
184         H := h.Sum(nil)
185
186         // H is already a hash, but the hostkey signing will apply its
187         // own key-specific hash algorithm.
188         sig, err := signAndMarshal(priv, randSource, H)
189         if err != nil {
190                 return nil, err
191         }
192
193         kexDHReply := kexDHReplyMsg{
194                 HostKey:   hostKeyBytes,
195                 Y:         Y,
196                 Signature: sig,
197         }
198         packet = Marshal(&kexDHReply)
199
200         err = c.writePacket(packet)
201         return &kexResult{
202                 H:         H,
203                 K:         K,
204                 HostKey:   hostKeyBytes,
205                 Signature: sig,
206                 Hash:      crypto.SHA1,
207         }, nil
208 }
209
210 // ecdh performs Elliptic Curve Diffie-Hellman key exchange as
211 // described in RFC 5656, section 4.
212 type ecdh struct {
213         curve elliptic.Curve
214 }
215
216 func (kex *ecdh) Client(c packetConn, rand io.Reader, magics *handshakeMagics) (*kexResult, error) {
217         ephKey, err := ecdsa.GenerateKey(kex.curve, rand)
218         if err != nil {
219                 return nil, err
220         }
221
222         kexInit := kexECDHInitMsg{
223                 ClientPubKey: elliptic.Marshal(kex.curve, ephKey.PublicKey.X, ephKey.PublicKey.Y),
224         }
225
226         serialized := Marshal(&kexInit)
227         if err := c.writePacket(serialized); err != nil {
228                 return nil, err
229         }
230
231         packet, err := c.readPacket()
232         if err != nil {
233                 return nil, err
234         }
235
236         var reply kexECDHReplyMsg
237         if err = Unmarshal(packet, &reply); err != nil {
238                 return nil, err
239         }
240
241         x, y, err := unmarshalECKey(kex.curve, reply.EphemeralPubKey)
242         if err != nil {
243                 return nil, err
244         }
245
246         // generate shared secret
247         secret, _ := kex.curve.ScalarMult(x, y, ephKey.D.Bytes())
248
249         h := ecHash(kex.curve).New()
250         magics.write(h)
251         writeString(h, reply.HostKey)
252         writeString(h, kexInit.ClientPubKey)
253         writeString(h, reply.EphemeralPubKey)
254         K := make([]byte, intLength(secret))
255         marshalInt(K, secret)
256         h.Write(K)
257
258         return &kexResult{
259                 H:         h.Sum(nil),
260                 K:         K,
261                 HostKey:   reply.HostKey,
262                 Signature: reply.Signature,
263                 Hash:      ecHash(kex.curve),
264         }, nil
265 }
266
267 // unmarshalECKey parses and checks an EC key.
268 func unmarshalECKey(curve elliptic.Curve, pubkey []byte) (x, y *big.Int, err error) {
269         x, y = elliptic.Unmarshal(curve, pubkey)
270         if x == nil {
271                 return nil, nil, errors.New("ssh: elliptic.Unmarshal failure")
272         }
273         if !validateECPublicKey(curve, x, y) {
274                 return nil, nil, errors.New("ssh: public key not on curve")
275         }
276         return x, y, nil
277 }
278
279 // validateECPublicKey checks that the point is a valid public key for
280 // the given curve. See [SEC1], 3.2.2
281 func validateECPublicKey(curve elliptic.Curve, x, y *big.Int) bool {
282         if x.Sign() == 0 && y.Sign() == 0 {
283                 return false
284         }
285
286         if x.Cmp(curve.Params().P) >= 0 {
287                 return false
288         }
289
290         if y.Cmp(curve.Params().P) >= 0 {
291                 return false
292         }
293
294         if !curve.IsOnCurve(x, y) {
295                 return false
296         }
297
298         // We don't check if N * PubKey == 0, since
299         //
300         // - the NIST curves have cofactor = 1, so this is implicit.
301         // (We don't foresee an implementation that supports non NIST
302         // curves)
303         //
304         // - for ephemeral keys, we don't need to worry about small
305         // subgroup attacks.
306         return true
307 }
308
309 func (kex *ecdh) Server(c packetConn, rand io.Reader, magics *handshakeMagics, priv Signer) (result *kexResult, err error) {
310         packet, err := c.readPacket()
311         if err != nil {
312                 return nil, err
313         }
314
315         var kexECDHInit kexECDHInitMsg
316         if err = Unmarshal(packet, &kexECDHInit); err != nil {
317                 return nil, err
318         }
319
320         clientX, clientY, err := unmarshalECKey(kex.curve, kexECDHInit.ClientPubKey)
321         if err != nil {
322                 return nil, err
323         }
324
325         // We could cache this key across multiple users/multiple
326         // connection attempts, but the benefit is small. OpenSSH
327         // generates a new key for each incoming connection.
328         ephKey, err := ecdsa.GenerateKey(kex.curve, rand)
329         if err != nil {
330                 return nil, err
331         }
332
333         hostKeyBytes := priv.PublicKey().Marshal()
334
335         serializedEphKey := elliptic.Marshal(kex.curve, ephKey.PublicKey.X, ephKey.PublicKey.Y)
336
337         // generate shared secret
338         secret, _ := kex.curve.ScalarMult(clientX, clientY, ephKey.D.Bytes())
339
340         h := ecHash(kex.curve).New()
341         magics.write(h)
342         writeString(h, hostKeyBytes)
343         writeString(h, kexECDHInit.ClientPubKey)
344         writeString(h, serializedEphKey)
345
346         K := make([]byte, intLength(secret))
347         marshalInt(K, secret)
348         h.Write(K)
349
350         H := h.Sum(nil)
351
352         // H is already a hash, but the hostkey signing will apply its
353         // own key-specific hash algorithm.
354         sig, err := signAndMarshal(priv, rand, H)
355         if err != nil {
356                 return nil, err
357         }
358
359         reply := kexECDHReplyMsg{
360                 EphemeralPubKey: serializedEphKey,
361                 HostKey:         hostKeyBytes,
362                 Signature:       sig,
363         }
364
365         serialized := Marshal(&reply)
366         if err := c.writePacket(serialized); err != nil {
367                 return nil, err
368         }
369
370         return &kexResult{
371                 H:         H,
372                 K:         K,
373                 HostKey:   reply.HostKey,
374                 Signature: sig,
375                 Hash:      ecHash(kex.curve),
376         }, nil
377 }
378
379 var kexAlgoMap = map[string]kexAlgorithm{}
380
381 func init() {
382         // This is the group called diffie-hellman-group1-sha1 in RFC
383         // 4253 and Oakley Group 2 in RFC 2409.
384         p, _ := new(big.Int).SetString("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381FFFFFFFFFFFFFFFF", 16)
385         kexAlgoMap[kexAlgoDH1SHA1] = &dhGroup{
386                 g:       new(big.Int).SetInt64(2),
387                 p:       p,
388                 pMinus1: new(big.Int).Sub(p, bigOne),
389         }
390
391         // This is the group called diffie-hellman-group14-sha1 in RFC
392         // 4253 and Oakley Group 14 in RFC 3526.
393         p, _ = new(big.Int).SetString("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF", 16)
394
395         kexAlgoMap[kexAlgoDH14SHA1] = &dhGroup{
396                 g:       new(big.Int).SetInt64(2),
397                 p:       p,
398                 pMinus1: new(big.Int).Sub(p, bigOne),
399         }
400
401         kexAlgoMap[kexAlgoECDH521] = &ecdh{elliptic.P521()}
402         kexAlgoMap[kexAlgoECDH384] = &ecdh{elliptic.P384()}
403         kexAlgoMap[kexAlgoECDH256] = &ecdh{elliptic.P256()}
404         kexAlgoMap[kexAlgoCurve25519SHA256] = &curve25519sha256{}
405 }
406
407 // curve25519sha256 implements the curve25519-sha256@libssh.org key
408 // agreement protocol, as described in
409 // https://git.libssh.org/projects/libssh.git/tree/doc/curve25519-sha256@libssh.org.txt
410 type curve25519sha256 struct{}
411
412 type curve25519KeyPair struct {
413         priv [32]byte
414         pub  [32]byte
415 }
416
417 func (kp *curve25519KeyPair) generate(rand io.Reader) error {
418         if _, err := io.ReadFull(rand, kp.priv[:]); err != nil {
419                 return err
420         }
421         curve25519.ScalarBaseMult(&kp.pub, &kp.priv)
422         return nil
423 }
424
425 // curve25519Zeros is just an array of 32 zero bytes so that we have something
426 // convenient to compare against in order to reject curve25519 points with the
427 // wrong order.
428 var curve25519Zeros [32]byte
429
430 func (kex *curve25519sha256) Client(c packetConn, rand io.Reader, magics *handshakeMagics) (*kexResult, error) {
431         var kp curve25519KeyPair
432         if err := kp.generate(rand); err != nil {
433                 return nil, err
434         }
435         if err := c.writePacket(Marshal(&kexECDHInitMsg{kp.pub[:]})); err != nil {
436                 return nil, err
437         }
438
439         packet, err := c.readPacket()
440         if err != nil {
441                 return nil, err
442         }
443
444         var reply kexECDHReplyMsg
445         if err = Unmarshal(packet, &reply); err != nil {
446                 return nil, err
447         }
448         if len(reply.EphemeralPubKey) != 32 {
449                 return nil, errors.New("ssh: peer's curve25519 public value has wrong length")
450         }
451
452         var servPub, secret [32]byte
453         copy(servPub[:], reply.EphemeralPubKey)
454         curve25519.ScalarMult(&secret, &kp.priv, &servPub)
455         if subtle.ConstantTimeCompare(secret[:], curve25519Zeros[:]) == 1 {
456                 return nil, errors.New("ssh: peer's curve25519 public value has wrong order")
457         }
458
459         h := crypto.SHA256.New()
460         magics.write(h)
461         writeString(h, reply.HostKey)
462         writeString(h, kp.pub[:])
463         writeString(h, reply.EphemeralPubKey)
464
465         kInt := new(big.Int).SetBytes(secret[:])
466         K := make([]byte, intLength(kInt))
467         marshalInt(K, kInt)
468         h.Write(K)
469
470         return &kexResult{
471                 H:         h.Sum(nil),
472                 K:         K,
473                 HostKey:   reply.HostKey,
474                 Signature: reply.Signature,
475                 Hash:      crypto.SHA256,
476         }, nil
477 }
478
479 func (kex *curve25519sha256) Server(c packetConn, rand io.Reader, magics *handshakeMagics, priv Signer) (result *kexResult, err error) {
480         packet, err := c.readPacket()
481         if err != nil {
482                 return
483         }
484         var kexInit kexECDHInitMsg
485         if err = Unmarshal(packet, &kexInit); err != nil {
486                 return
487         }
488
489         if len(kexInit.ClientPubKey) != 32 {
490                 return nil, errors.New("ssh: peer's curve25519 public value has wrong length")
491         }
492
493         var kp curve25519KeyPair
494         if err := kp.generate(rand); err != nil {
495                 return nil, err
496         }
497
498         var clientPub, secret [32]byte
499         copy(clientPub[:], kexInit.ClientPubKey)
500         curve25519.ScalarMult(&secret, &kp.priv, &clientPub)
501         if subtle.ConstantTimeCompare(secret[:], curve25519Zeros[:]) == 1 {
502                 return nil, errors.New("ssh: peer's curve25519 public value has wrong order")
503         }
504
505         hostKeyBytes := priv.PublicKey().Marshal()
506
507         h := crypto.SHA256.New()
508         magics.write(h)
509         writeString(h, hostKeyBytes)
510         writeString(h, kexInit.ClientPubKey)
511         writeString(h, kp.pub[:])
512
513         kInt := new(big.Int).SetBytes(secret[:])
514         K := make([]byte, intLength(kInt))
515         marshalInt(K, kInt)
516         h.Write(K)
517
518         H := h.Sum(nil)
519
520         sig, err := signAndMarshal(priv, rand, H)
521         if err != nil {
522                 return nil, err
523         }
524
525         reply := kexECDHReplyMsg{
526                 EphemeralPubKey: kp.pub[:],
527                 HostKey:         hostKeyBytes,
528                 Signature:       sig,
529         }
530         if err := c.writePacket(Marshal(&reply)); err != nil {
531                 return nil, err
532         }
533         return &kexResult{
534                 H:         H,
535                 K:         K,
536                 HostKey:   hostKeyBytes,
537                 Signature: sig,
538                 Hash:      crypto.SHA256,
539         }, nil
540 }