1
2
3
4
5 package ssh
6
7 import (
8 "crypto"
9 "crypto/ecdsa"
10 "crypto/elliptic"
11 "crypto/rand"
12 "crypto/subtle"
13 "encoding/binary"
14 "errors"
15 "fmt"
16 "io"
17 "math/big"
18
19 "golang.org/x/crypto/curve25519"
20 )
21
22 const (
23 kexAlgoDH1SHA1 = "diffie-hellman-group1-sha1"
24 kexAlgoDH14SHA1 = "diffie-hellman-group14-sha1"
25 kexAlgoDH14SHA256 = "diffie-hellman-group14-sha256"
26 kexAlgoDH16SHA512 = "diffie-hellman-group16-sha512"
27 kexAlgoECDH256 = "ecdh-sha2-nistp256"
28 kexAlgoECDH384 = "ecdh-sha2-nistp384"
29 kexAlgoECDH521 = "ecdh-sha2-nistp521"
30 kexAlgoCurve25519SHA256LibSSH = "curve25519-sha256@libssh.org"
31 kexAlgoCurve25519SHA256 = "curve25519-sha256"
32
33
34
35
36 kexAlgoDHGEXSHA1 = "diffie-hellman-group-exchange-sha1"
37 kexAlgoDHGEXSHA256 = "diffie-hellman-group-exchange-sha256"
38 )
39
40
41 type kexResult struct {
42
43 H []byte
44
45
46 K []byte
47
48
49 HostKey []byte
50
51
52 Signature []byte
53
54
55
56
57 Hash crypto.Hash
58
59
60
61 SessionID []byte
62 }
63
64
65
66 type handshakeMagics struct {
67 clientVersion, serverVersion []byte
68 clientKexInit, serverKexInit []byte
69 }
70
71 func (m *handshakeMagics) write(w io.Writer) {
72 writeString(w, m.clientVersion)
73 writeString(w, m.serverVersion)
74 writeString(w, m.clientKexInit)
75 writeString(w, m.serverKexInit)
76 }
77
78
79 type kexAlgorithm interface {
80
81
82
83 Server(p packetConn, rand io.Reader, magics *handshakeMagics, s AlgorithmSigner, algo string) (*kexResult, error)
84
85
86
87 Client(p packetConn, rand io.Reader, magics *handshakeMagics) (*kexResult, error)
88 }
89
90
91 type dhGroup struct {
92 g, p, pMinus1 *big.Int
93 hashFunc crypto.Hash
94 }
95
96 func (group *dhGroup) diffieHellman(theirPublic, myPrivate *big.Int) (*big.Int, error) {
97 if theirPublic.Cmp(bigOne) <= 0 || theirPublic.Cmp(group.pMinus1) >= 0 {
98 return nil, errors.New("ssh: DH parameter out of bounds")
99 }
100 return new(big.Int).Exp(theirPublic, myPrivate, group.p), nil
101 }
102
103 func (group *dhGroup) Client(c packetConn, randSource io.Reader, magics *handshakeMagics) (*kexResult, error) {
104 var x *big.Int
105 for {
106 var err error
107 if x, err = rand.Int(randSource, group.pMinus1); err != nil {
108 return nil, err
109 }
110 if x.Sign() > 0 {
111 break
112 }
113 }
114
115 X := new(big.Int).Exp(group.g, x, group.p)
116 kexDHInit := kexDHInitMsg{
117 X: X,
118 }
119 if err := c.writePacket(Marshal(&kexDHInit)); err != nil {
120 return nil, err
121 }
122
123 packet, err := c.readPacket()
124 if err != nil {
125 return nil, err
126 }
127
128 var kexDHReply kexDHReplyMsg
129 if err = Unmarshal(packet, &kexDHReply); err != nil {
130 return nil, err
131 }
132
133 ki, err := group.diffieHellman(kexDHReply.Y, x)
134 if err != nil {
135 return nil, err
136 }
137
138 h := group.hashFunc.New()
139 magics.write(h)
140 writeString(h, kexDHReply.HostKey)
141 writeInt(h, X)
142 writeInt(h, kexDHReply.Y)
143 K := make([]byte, intLength(ki))
144 marshalInt(K, ki)
145 h.Write(K)
146
147 return &kexResult{
148 H: h.Sum(nil),
149 K: K,
150 HostKey: kexDHReply.HostKey,
151 Signature: kexDHReply.Signature,
152 Hash: group.hashFunc,
153 }, nil
154 }
155
156 func (group *dhGroup) Server(c packetConn, randSource io.Reader, magics *handshakeMagics, priv AlgorithmSigner, algo string) (result *kexResult, err error) {
157 packet, err := c.readPacket()
158 if err != nil {
159 return
160 }
161 var kexDHInit kexDHInitMsg
162 if err = Unmarshal(packet, &kexDHInit); err != nil {
163 return
164 }
165
166 var y *big.Int
167 for {
168 if y, err = rand.Int(randSource, group.pMinus1); err != nil {
169 return
170 }
171 if y.Sign() > 0 {
172 break
173 }
174 }
175
176 Y := new(big.Int).Exp(group.g, y, group.p)
177 ki, err := group.diffieHellman(kexDHInit.X, y)
178 if err != nil {
179 return nil, err
180 }
181
182 hostKeyBytes := priv.PublicKey().Marshal()
183
184 h := group.hashFunc.New()
185 magics.write(h)
186 writeString(h, hostKeyBytes)
187 writeInt(h, kexDHInit.X)
188 writeInt(h, Y)
189
190 K := make([]byte, intLength(ki))
191 marshalInt(K, ki)
192 h.Write(K)
193
194 H := h.Sum(nil)
195
196
197
198 sig, err := signAndMarshal(priv, randSource, H, algo)
199 if err != nil {
200 return nil, err
201 }
202
203 kexDHReply := kexDHReplyMsg{
204 HostKey: hostKeyBytes,
205 Y: Y,
206 Signature: sig,
207 }
208 packet = Marshal(&kexDHReply)
209
210 err = c.writePacket(packet)
211 return &kexResult{
212 H: H,
213 K: K,
214 HostKey: hostKeyBytes,
215 Signature: sig,
216 Hash: group.hashFunc,
217 }, err
218 }
219
220
221
222 type ecdh struct {
223 curve elliptic.Curve
224 }
225
226 func (kex *ecdh) Client(c packetConn, rand io.Reader, magics *handshakeMagics) (*kexResult, error) {
227 ephKey, err := ecdsa.GenerateKey(kex.curve, rand)
228 if err != nil {
229 return nil, err
230 }
231
232 kexInit := kexECDHInitMsg{
233 ClientPubKey: elliptic.Marshal(kex.curve, ephKey.PublicKey.X, ephKey.PublicKey.Y),
234 }
235
236 serialized := Marshal(&kexInit)
237 if err := c.writePacket(serialized); err != nil {
238 return nil, err
239 }
240
241 packet, err := c.readPacket()
242 if err != nil {
243 return nil, err
244 }
245
246 var reply kexECDHReplyMsg
247 if err = Unmarshal(packet, &reply); err != nil {
248 return nil, err
249 }
250
251 x, y, err := unmarshalECKey(kex.curve, reply.EphemeralPubKey)
252 if err != nil {
253 return nil, err
254 }
255
256
257 secret, _ := kex.curve.ScalarMult(x, y, ephKey.D.Bytes())
258
259 h := ecHash(kex.curve).New()
260 magics.write(h)
261 writeString(h, reply.HostKey)
262 writeString(h, kexInit.ClientPubKey)
263 writeString(h, reply.EphemeralPubKey)
264 K := make([]byte, intLength(secret))
265 marshalInt(K, secret)
266 h.Write(K)
267
268 return &kexResult{
269 H: h.Sum(nil),
270 K: K,
271 HostKey: reply.HostKey,
272 Signature: reply.Signature,
273 Hash: ecHash(kex.curve),
274 }, nil
275 }
276
277
278 func unmarshalECKey(curve elliptic.Curve, pubkey []byte) (x, y *big.Int, err error) {
279 x, y = elliptic.Unmarshal(curve, pubkey)
280 if x == nil {
281 return nil, nil, errors.New("ssh: elliptic.Unmarshal failure")
282 }
283 if !validateECPublicKey(curve, x, y) {
284 return nil, nil, errors.New("ssh: public key not on curve")
285 }
286 return x, y, nil
287 }
288
289
290
291 func validateECPublicKey(curve elliptic.Curve, x, y *big.Int) bool {
292 if x.Sign() == 0 && y.Sign() == 0 {
293 return false
294 }
295
296 if x.Cmp(curve.Params().P) >= 0 {
297 return false
298 }
299
300 if y.Cmp(curve.Params().P) >= 0 {
301 return false
302 }
303
304 if !curve.IsOnCurve(x, y) {
305 return false
306 }
307
308
309
310
311
312
313
314
315
316 return true
317 }
318
319 func (kex *ecdh) Server(c packetConn, rand io.Reader, magics *handshakeMagics, priv AlgorithmSigner, algo string) (result *kexResult, err error) {
320 packet, err := c.readPacket()
321 if err != nil {
322 return nil, err
323 }
324
325 var kexECDHInit kexECDHInitMsg
326 if err = Unmarshal(packet, &kexECDHInit); err != nil {
327 return nil, err
328 }
329
330 clientX, clientY, err := unmarshalECKey(kex.curve, kexECDHInit.ClientPubKey)
331 if err != nil {
332 return nil, err
333 }
334
335
336
337
338 ephKey, err := ecdsa.GenerateKey(kex.curve, rand)
339 if err != nil {
340 return nil, err
341 }
342
343 hostKeyBytes := priv.PublicKey().Marshal()
344
345 serializedEphKey := elliptic.Marshal(kex.curve, ephKey.PublicKey.X, ephKey.PublicKey.Y)
346
347
348 secret, _ := kex.curve.ScalarMult(clientX, clientY, ephKey.D.Bytes())
349
350 h := ecHash(kex.curve).New()
351 magics.write(h)
352 writeString(h, hostKeyBytes)
353 writeString(h, kexECDHInit.ClientPubKey)
354 writeString(h, serializedEphKey)
355
356 K := make([]byte, intLength(secret))
357 marshalInt(K, secret)
358 h.Write(K)
359
360 H := h.Sum(nil)
361
362
363
364 sig, err := signAndMarshal(priv, rand, H, algo)
365 if err != nil {
366 return nil, err
367 }
368
369 reply := kexECDHReplyMsg{
370 EphemeralPubKey: serializedEphKey,
371 HostKey: hostKeyBytes,
372 Signature: sig,
373 }
374
375 serialized := Marshal(&reply)
376 if err := c.writePacket(serialized); err != nil {
377 return nil, err
378 }
379
380 return &kexResult{
381 H: H,
382 K: K,
383 HostKey: reply.HostKey,
384 Signature: sig,
385 Hash: ecHash(kex.curve),
386 }, nil
387 }
388
389
390
391 func ecHash(curve elliptic.Curve) crypto.Hash {
392 bitSize := curve.Params().BitSize
393 switch {
394 case bitSize <= 256:
395 return crypto.SHA256
396 case bitSize <= 384:
397 return crypto.SHA384
398 }
399 return crypto.SHA512
400 }
401
402 var kexAlgoMap = map[string]kexAlgorithm{}
403
404 func init() {
405
406
407 p, _ := new(big.Int).SetString("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381FFFFFFFFFFFFFFFF", 16)
408 kexAlgoMap[kexAlgoDH1SHA1] = &dhGroup{
409 g: new(big.Int).SetInt64(2),
410 p: p,
411 pMinus1: new(big.Int).Sub(p, bigOne),
412 hashFunc: crypto.SHA1,
413 }
414
415
416
417
418 p, _ = new(big.Int).SetString("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF", 16)
419 group14 := &dhGroup{
420 g: new(big.Int).SetInt64(2),
421 p: p,
422 pMinus1: new(big.Int).Sub(p, bigOne),
423 }
424
425 kexAlgoMap[kexAlgoDH14SHA1] = &dhGroup{
426 g: group14.g, p: group14.p, pMinus1: group14.pMinus1,
427 hashFunc: crypto.SHA1,
428 }
429 kexAlgoMap[kexAlgoDH14SHA256] = &dhGroup{
430 g: group14.g, p: group14.p, pMinus1: group14.pMinus1,
431 hashFunc: crypto.SHA256,
432 }
433
434
435
436 p, _ = new(big.Int).SetString("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D788719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA993B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934063199FFFFFFFFFFFFFFFF", 16)
437
438 kexAlgoMap[kexAlgoDH16SHA512] = &dhGroup{
439 g: new(big.Int).SetInt64(2),
440 p: p,
441 pMinus1: new(big.Int).Sub(p, bigOne),
442 hashFunc: crypto.SHA512,
443 }
444
445 kexAlgoMap[kexAlgoECDH521] = &ecdh{elliptic.P521()}
446 kexAlgoMap[kexAlgoECDH384] = &ecdh{elliptic.P384()}
447 kexAlgoMap[kexAlgoECDH256] = &ecdh{elliptic.P256()}
448 kexAlgoMap[kexAlgoCurve25519SHA256] = &curve25519sha256{}
449 kexAlgoMap[kexAlgoCurve25519SHA256LibSSH] = &curve25519sha256{}
450 kexAlgoMap[kexAlgoDHGEXSHA1] = &dhGEXSHA{hashFunc: crypto.SHA1}
451 kexAlgoMap[kexAlgoDHGEXSHA256] = &dhGEXSHA{hashFunc: crypto.SHA256}
452 }
453
454
455
456 type curve25519sha256 struct{}
457
458 type curve25519KeyPair struct {
459 priv [32]byte
460 pub [32]byte
461 }
462
463 func (kp *curve25519KeyPair) generate(rand io.Reader) error {
464 if _, err := io.ReadFull(rand, kp.priv[:]); err != nil {
465 return err
466 }
467 curve25519.ScalarBaseMult(&kp.pub, &kp.priv)
468 return nil
469 }
470
471
472
473
474 var curve25519Zeros [32]byte
475
476 func (kex *curve25519sha256) Client(c packetConn, rand io.Reader, magics *handshakeMagics) (*kexResult, error) {
477 var kp curve25519KeyPair
478 if err := kp.generate(rand); err != nil {
479 return nil, err
480 }
481 if err := c.writePacket(Marshal(&kexECDHInitMsg{kp.pub[:]})); err != nil {
482 return nil, err
483 }
484
485 packet, err := c.readPacket()
486 if err != nil {
487 return nil, err
488 }
489
490 var reply kexECDHReplyMsg
491 if err = Unmarshal(packet, &reply); err != nil {
492 return nil, err
493 }
494 if len(reply.EphemeralPubKey) != 32 {
495 return nil, errors.New("ssh: peer's curve25519 public value has wrong length")
496 }
497
498 var servPub, secret [32]byte
499 copy(servPub[:], reply.EphemeralPubKey)
500 curve25519.ScalarMult(&secret, &kp.priv, &servPub)
501 if subtle.ConstantTimeCompare(secret[:], curve25519Zeros[:]) == 1 {
502 return nil, errors.New("ssh: peer's curve25519 public value has wrong order")
503 }
504
505 h := crypto.SHA256.New()
506 magics.write(h)
507 writeString(h, reply.HostKey)
508 writeString(h, kp.pub[:])
509 writeString(h, reply.EphemeralPubKey)
510
511 ki := new(big.Int).SetBytes(secret[:])
512 K := make([]byte, intLength(ki))
513 marshalInt(K, ki)
514 h.Write(K)
515
516 return &kexResult{
517 H: h.Sum(nil),
518 K: K,
519 HostKey: reply.HostKey,
520 Signature: reply.Signature,
521 Hash: crypto.SHA256,
522 }, nil
523 }
524
525 func (kex *curve25519sha256) Server(c packetConn, rand io.Reader, magics *handshakeMagics, priv AlgorithmSigner, algo string) (result *kexResult, err error) {
526 packet, err := c.readPacket()
527 if err != nil {
528 return
529 }
530 var kexInit kexECDHInitMsg
531 if err = Unmarshal(packet, &kexInit); err != nil {
532 return
533 }
534
535 if len(kexInit.ClientPubKey) != 32 {
536 return nil, errors.New("ssh: peer's curve25519 public value has wrong length")
537 }
538
539 var kp curve25519KeyPair
540 if err := kp.generate(rand); err != nil {
541 return nil, err
542 }
543
544 var clientPub, secret [32]byte
545 copy(clientPub[:], kexInit.ClientPubKey)
546 curve25519.ScalarMult(&secret, &kp.priv, &clientPub)
547 if subtle.ConstantTimeCompare(secret[:], curve25519Zeros[:]) == 1 {
548 return nil, errors.New("ssh: peer's curve25519 public value has wrong order")
549 }
550
551 hostKeyBytes := priv.PublicKey().Marshal()
552
553 h := crypto.SHA256.New()
554 magics.write(h)
555 writeString(h, hostKeyBytes)
556 writeString(h, kexInit.ClientPubKey)
557 writeString(h, kp.pub[:])
558
559 ki := new(big.Int).SetBytes(secret[:])
560 K := make([]byte, intLength(ki))
561 marshalInt(K, ki)
562 h.Write(K)
563
564 H := h.Sum(nil)
565
566 sig, err := signAndMarshal(priv, rand, H, algo)
567 if err != nil {
568 return nil, err
569 }
570
571 reply := kexECDHReplyMsg{
572 EphemeralPubKey: kp.pub[:],
573 HostKey: hostKeyBytes,
574 Signature: sig,
575 }
576 if err := c.writePacket(Marshal(&reply)); err != nil {
577 return nil, err
578 }
579 return &kexResult{
580 H: H,
581 K: K,
582 HostKey: hostKeyBytes,
583 Signature: sig,
584 Hash: crypto.SHA256,
585 }, nil
586 }
587
588
589
590
591 type dhGEXSHA struct {
592 hashFunc crypto.Hash
593 }
594
595 const (
596 dhGroupExchangeMinimumBits = 2048
597 dhGroupExchangePreferredBits = 2048
598 dhGroupExchangeMaximumBits = 8192
599 )
600
601 func (gex *dhGEXSHA) Client(c packetConn, randSource io.Reader, magics *handshakeMagics) (*kexResult, error) {
602
603 kexDHGexRequest := kexDHGexRequestMsg{
604 MinBits: dhGroupExchangeMinimumBits,
605 PreferedBits: dhGroupExchangePreferredBits,
606 MaxBits: dhGroupExchangeMaximumBits,
607 }
608 if err := c.writePacket(Marshal(&kexDHGexRequest)); err != nil {
609 return nil, err
610 }
611
612
613 packet, err := c.readPacket()
614 if err != nil {
615 return nil, err
616 }
617
618 var msg kexDHGexGroupMsg
619 if err = Unmarshal(packet, &msg); err != nil {
620 return nil, err
621 }
622
623
624 if msg.P.BitLen() < dhGroupExchangeMinimumBits || msg.P.BitLen() > dhGroupExchangeMaximumBits {
625 return nil, fmt.Errorf("ssh: server-generated gex p is out of range (%d bits)", msg.P.BitLen())
626 }
627
628
629 pMinusOne := new(big.Int).Sub(msg.P, bigOne)
630 if msg.G.Cmp(bigOne) <= 0 || msg.G.Cmp(pMinusOne) >= 0 {
631 return nil, fmt.Errorf("ssh: server provided gex g is not safe")
632 }
633
634
635 pHalf := new(big.Int).Rsh(msg.P, 1)
636 x, err := rand.Int(randSource, pHalf)
637 if err != nil {
638 return nil, err
639 }
640 X := new(big.Int).Exp(msg.G, x, msg.P)
641 kexDHGexInit := kexDHGexInitMsg{
642 X: X,
643 }
644 if err := c.writePacket(Marshal(&kexDHGexInit)); err != nil {
645 return nil, err
646 }
647
648
649 packet, err = c.readPacket()
650 if err != nil {
651 return nil, err
652 }
653
654 var kexDHGexReply kexDHGexReplyMsg
655 if err = Unmarshal(packet, &kexDHGexReply); err != nil {
656 return nil, err
657 }
658
659 if kexDHGexReply.Y.Cmp(bigOne) <= 0 || kexDHGexReply.Y.Cmp(pMinusOne) >= 0 {
660 return nil, errors.New("ssh: DH parameter out of bounds")
661 }
662 kInt := new(big.Int).Exp(kexDHGexReply.Y, x, msg.P)
663
664
665 if kInt.Cmp(bigOne) <= 0 || kInt.Cmp(pMinusOne) >= 0 {
666 return nil, fmt.Errorf("ssh: derived k is not safe")
667 }
668
669 h := gex.hashFunc.New()
670 magics.write(h)
671 writeString(h, kexDHGexReply.HostKey)
672 binary.Write(h, binary.BigEndian, uint32(dhGroupExchangeMinimumBits))
673 binary.Write(h, binary.BigEndian, uint32(dhGroupExchangePreferredBits))
674 binary.Write(h, binary.BigEndian, uint32(dhGroupExchangeMaximumBits))
675 writeInt(h, msg.P)
676 writeInt(h, msg.G)
677 writeInt(h, X)
678 writeInt(h, kexDHGexReply.Y)
679 K := make([]byte, intLength(kInt))
680 marshalInt(K, kInt)
681 h.Write(K)
682
683 return &kexResult{
684 H: h.Sum(nil),
685 K: K,
686 HostKey: kexDHGexReply.HostKey,
687 Signature: kexDHGexReply.Signature,
688 Hash: gex.hashFunc,
689 }, nil
690 }
691
692
693
694
695 func (gex dhGEXSHA) Server(c packetConn, randSource io.Reader, magics *handshakeMagics, priv AlgorithmSigner, algo string) (result *kexResult, err error) {
696
697 packet, err := c.readPacket()
698 if err != nil {
699 return
700 }
701 var kexDHGexRequest kexDHGexRequestMsg
702 if err = Unmarshal(packet, &kexDHGexRequest); err != nil {
703 return
704 }
705
706
707
708
709 p, _ := new(big.Int).SetString("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF", 16)
710 g := big.NewInt(2)
711
712 msg := &kexDHGexGroupMsg{
713 P: p,
714 G: g,
715 }
716 if err := c.writePacket(Marshal(msg)); err != nil {
717 return nil, err
718 }
719
720
721 packet, err = c.readPacket()
722 if err != nil {
723 return
724 }
725 var kexDHGexInit kexDHGexInitMsg
726 if err = Unmarshal(packet, &kexDHGexInit); err != nil {
727 return
728 }
729
730 pHalf := new(big.Int).Rsh(p, 1)
731
732 y, err := rand.Int(randSource, pHalf)
733 if err != nil {
734 return
735 }
736 Y := new(big.Int).Exp(g, y, p)
737
738 pMinusOne := new(big.Int).Sub(p, bigOne)
739 if kexDHGexInit.X.Cmp(bigOne) <= 0 || kexDHGexInit.X.Cmp(pMinusOne) >= 0 {
740 return nil, errors.New("ssh: DH parameter out of bounds")
741 }
742 kInt := new(big.Int).Exp(kexDHGexInit.X, y, p)
743
744 hostKeyBytes := priv.PublicKey().Marshal()
745
746 h := gex.hashFunc.New()
747 magics.write(h)
748 writeString(h, hostKeyBytes)
749 binary.Write(h, binary.BigEndian, uint32(dhGroupExchangeMinimumBits))
750 binary.Write(h, binary.BigEndian, uint32(dhGroupExchangePreferredBits))
751 binary.Write(h, binary.BigEndian, uint32(dhGroupExchangeMaximumBits))
752 writeInt(h, p)
753 writeInt(h, g)
754 writeInt(h, kexDHGexInit.X)
755 writeInt(h, Y)
756
757 K := make([]byte, intLength(kInt))
758 marshalInt(K, kInt)
759 h.Write(K)
760
761 H := h.Sum(nil)
762
763
764
765 sig, err := signAndMarshal(priv, randSource, H, algo)
766 if err != nil {
767 return nil, err
768 }
769
770 kexDHGexReply := kexDHGexReplyMsg{
771 HostKey: hostKeyBytes,
772 Y: Y,
773 Signature: sig,
774 }
775 packet = Marshal(&kexDHGexReply)
776
777 err = c.writePacket(packet)
778
779 return &kexResult{
780 H: H,
781 K: K,
782 HostKey: hostKeyBytes,
783 Signature: sig,
784 Hash: gex.hashFunc,
785 }, err
786 }
787
View as plain text