github.com/psiphon-labs/psiphon-tunnel-core@v2.0.28+incompatible/psiphon/common/crypto/ssh/kex.go (about) 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 "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 kexAlgoECDH256 = "ecdh-sha2-nistp256" 27 kexAlgoECDH384 = "ecdh-sha2-nistp384" 28 kexAlgoECDH521 = "ecdh-sha2-nistp521" 29 kexAlgoCurve25519SHA256 = "curve25519-sha256@libssh.org" 30 31 // For the following kex only the client half contains a production 32 // ready implementation. The server half only consists of a minimal 33 // implementation to satisfy the automated tests. 34 kexAlgoDHGEXSHA1 = "diffie-hellman-group-exchange-sha1" 35 kexAlgoDHGEXSHA256 = "diffie-hellman-group-exchange-sha256" 36 ) 37 38 // kexResult captures the outcome of a key exchange. 39 type kexResult struct { 40 // Session hash. See also RFC 4253, section 8. 41 H []byte 42 43 // Shared secret. See also RFC 4253, section 8. 44 K []byte 45 46 // Host key as hashed into H. 47 HostKey []byte 48 49 // Signature of H. 50 Signature []byte 51 52 // A cryptographic hash function that matches the security 53 // level of the key exchange algorithm. It is used for 54 // calculating H, and for deriving keys from H and K. 55 Hash crypto.Hash 56 57 // The session ID, which is the first H computed. This is used 58 // to derive key material inside the transport. 59 SessionID []byte 60 } 61 62 // handshakeMagics contains data that is always included in the 63 // session hash. 64 type handshakeMagics struct { 65 clientVersion, serverVersion []byte 66 clientKexInit, serverKexInit []byte 67 } 68 69 func (m *handshakeMagics) write(w io.Writer) { 70 writeString(w, m.clientVersion) 71 writeString(w, m.serverVersion) 72 writeString(w, m.clientKexInit) 73 writeString(w, m.serverKexInit) 74 } 75 76 // kexAlgorithm abstracts different key exchange algorithms. 77 type kexAlgorithm interface { 78 // Server runs server-side key agreement, signing the result 79 // with a hostkey. 80 Server(p packetConn, rand io.Reader, magics *handshakeMagics, s Signer) (*kexResult, error) 81 82 // Client runs the client-side key agreement. Caller is 83 // responsible for verifying the host key signature. 84 Client(p packetConn, rand io.Reader, magics *handshakeMagics) (*kexResult, error) 85 } 86 87 // dhGroup is a multiplicative group suitable for implementing Diffie-Hellman key agreement. 88 type dhGroup struct { 89 g, p, pMinus1 *big.Int 90 91 // [Psiphon] 92 hashFunc crypto.Hash 93 } 94 95 func (group *dhGroup) diffieHellman(theirPublic, myPrivate *big.Int) (*big.Int, error) { 96 if theirPublic.Cmp(bigOne) <= 0 || theirPublic.Cmp(group.pMinus1) >= 0 { 97 return nil, errors.New("ssh: DH parameter out of bounds") 98 } 99 return new(big.Int).Exp(theirPublic, myPrivate, group.p), nil 100 } 101 102 func (group *dhGroup) Client(c packetConn, randSource io.Reader, magics *handshakeMagics) (*kexResult, error) { 103 104 // [Psiphon] 105 hashFunc := group.hashFunc 106 107 var x *big.Int 108 for { 109 var err error 110 if x, err = rand.Int(randSource, group.pMinus1); err != nil { 111 return nil, err 112 } 113 if x.Sign() > 0 { 114 break 115 } 116 } 117 118 X := new(big.Int).Exp(group.g, x, group.p) 119 kexDHInit := kexDHInitMsg{ 120 X: X, 121 } 122 if err := c.writePacket(Marshal(&kexDHInit)); err != nil { 123 return nil, err 124 } 125 126 packet, err := c.readPacket() 127 if err != nil { 128 return nil, err 129 } 130 131 var kexDHReply kexDHReplyMsg 132 if err = Unmarshal(packet, &kexDHReply); err != nil { 133 return nil, err 134 } 135 136 ki, err := group.diffieHellman(kexDHReply.Y, x) 137 if err != nil { 138 return nil, err 139 } 140 141 h := hashFunc.New() 142 magics.write(h) 143 writeString(h, kexDHReply.HostKey) 144 writeInt(h, X) 145 writeInt(h, kexDHReply.Y) 146 K := make([]byte, intLength(ki)) 147 marshalInt(K, ki) 148 h.Write(K) 149 150 return &kexResult{ 151 H: h.Sum(nil), 152 K: K, 153 HostKey: kexDHReply.HostKey, 154 Signature: kexDHReply.Signature, 155 Hash: hashFunc, 156 }, nil 157 } 158 159 func (group *dhGroup) Server(c packetConn, randSource io.Reader, magics *handshakeMagics, priv Signer) (result *kexResult, err error) { 160 161 // [Psiphon] 162 hashFunc := group.hashFunc 163 164 packet, err := c.readPacket() 165 if err != nil { 166 return 167 } 168 var kexDHInit kexDHInitMsg 169 if err = Unmarshal(packet, &kexDHInit); err != nil { 170 return 171 } 172 173 var y *big.Int 174 for { 175 if y, err = rand.Int(randSource, group.pMinus1); err != nil { 176 return 177 } 178 if y.Sign() > 0 { 179 break 180 } 181 } 182 183 Y := new(big.Int).Exp(group.g, y, group.p) 184 ki, err := group.diffieHellman(kexDHInit.X, y) 185 if err != nil { 186 return nil, err 187 } 188 189 hostKeyBytes := priv.PublicKey().Marshal() 190 191 h := hashFunc.New() 192 magics.write(h) 193 writeString(h, hostKeyBytes) 194 writeInt(h, kexDHInit.X) 195 writeInt(h, Y) 196 197 K := make([]byte, intLength(ki)) 198 marshalInt(K, ki) 199 h.Write(K) 200 201 H := h.Sum(nil) 202 203 // H is already a hash, but the hostkey signing will apply its 204 // own key-specific hash algorithm. 205 sig, err := signAndMarshal(priv, randSource, H) 206 if err != nil { 207 return nil, err 208 } 209 210 kexDHReply := kexDHReplyMsg{ 211 HostKey: hostKeyBytes, 212 Y: Y, 213 Signature: sig, 214 } 215 packet = Marshal(&kexDHReply) 216 217 err = c.writePacket(packet) 218 return &kexResult{ 219 H: H, 220 K: K, 221 HostKey: hostKeyBytes, 222 Signature: sig, 223 Hash: hashFunc, 224 }, err 225 } 226 227 // ecdh performs Elliptic Curve Diffie-Hellman key exchange as 228 // described in RFC 5656, section 4. 229 type ecdh struct { 230 curve elliptic.Curve 231 } 232 233 func (kex *ecdh) Client(c packetConn, rand io.Reader, magics *handshakeMagics) (*kexResult, error) { 234 ephKey, err := ecdsa.GenerateKey(kex.curve, rand) 235 if err != nil { 236 return nil, err 237 } 238 239 kexInit := kexECDHInitMsg{ 240 ClientPubKey: elliptic.Marshal(kex.curve, ephKey.PublicKey.X, ephKey.PublicKey.Y), 241 } 242 243 serialized := Marshal(&kexInit) 244 if err := c.writePacket(serialized); err != nil { 245 return nil, err 246 } 247 248 packet, err := c.readPacket() 249 if err != nil { 250 return nil, err 251 } 252 253 var reply kexECDHReplyMsg 254 if err = Unmarshal(packet, &reply); err != nil { 255 return nil, err 256 } 257 258 x, y, err := unmarshalECKey(kex.curve, reply.EphemeralPubKey) 259 if err != nil { 260 return nil, err 261 } 262 263 // generate shared secret 264 secret, _ := kex.curve.ScalarMult(x, y, ephKey.D.Bytes()) 265 266 h := ecHash(kex.curve).New() 267 magics.write(h) 268 writeString(h, reply.HostKey) 269 writeString(h, kexInit.ClientPubKey) 270 writeString(h, reply.EphemeralPubKey) 271 K := make([]byte, intLength(secret)) 272 marshalInt(K, secret) 273 h.Write(K) 274 275 return &kexResult{ 276 H: h.Sum(nil), 277 K: K, 278 HostKey: reply.HostKey, 279 Signature: reply.Signature, 280 Hash: ecHash(kex.curve), 281 }, nil 282 } 283 284 // unmarshalECKey parses and checks an EC key. 285 func unmarshalECKey(curve elliptic.Curve, pubkey []byte) (x, y *big.Int, err error) { 286 x, y = elliptic.Unmarshal(curve, pubkey) 287 if x == nil { 288 return nil, nil, errors.New("ssh: elliptic.Unmarshal failure") 289 } 290 if !validateECPublicKey(curve, x, y) { 291 return nil, nil, errors.New("ssh: public key not on curve") 292 } 293 return x, y, nil 294 } 295 296 // validateECPublicKey checks that the point is a valid public key for 297 // the given curve. See [SEC1], 3.2.2 298 func validateECPublicKey(curve elliptic.Curve, x, y *big.Int) bool { 299 if x.Sign() == 0 && y.Sign() == 0 { 300 return false 301 } 302 303 if x.Cmp(curve.Params().P) >= 0 { 304 return false 305 } 306 307 if y.Cmp(curve.Params().P) >= 0 { 308 return false 309 } 310 311 if !curve.IsOnCurve(x, y) { 312 return false 313 } 314 315 // We don't check if N * PubKey == 0, since 316 // 317 // - the NIST curves have cofactor = 1, so this is implicit. 318 // (We don't foresee an implementation that supports non NIST 319 // curves) 320 // 321 // - for ephemeral keys, we don't need to worry about small 322 // subgroup attacks. 323 return true 324 } 325 326 func (kex *ecdh) Server(c packetConn, rand io.Reader, magics *handshakeMagics, priv Signer) (result *kexResult, err error) { 327 packet, err := c.readPacket() 328 if err != nil { 329 return nil, err 330 } 331 332 var kexECDHInit kexECDHInitMsg 333 if err = Unmarshal(packet, &kexECDHInit); err != nil { 334 return nil, err 335 } 336 337 clientX, clientY, err := unmarshalECKey(kex.curve, kexECDHInit.ClientPubKey) 338 if err != nil { 339 return nil, err 340 } 341 342 // We could cache this key across multiple users/multiple 343 // connection attempts, but the benefit is small. OpenSSH 344 // generates a new key for each incoming connection. 345 ephKey, err := ecdsa.GenerateKey(kex.curve, rand) 346 if err != nil { 347 return nil, err 348 } 349 350 hostKeyBytes := priv.PublicKey().Marshal() 351 352 serializedEphKey := elliptic.Marshal(kex.curve, ephKey.PublicKey.X, ephKey.PublicKey.Y) 353 354 // generate shared secret 355 secret, _ := kex.curve.ScalarMult(clientX, clientY, ephKey.D.Bytes()) 356 357 h := ecHash(kex.curve).New() 358 magics.write(h) 359 writeString(h, hostKeyBytes) 360 writeString(h, kexECDHInit.ClientPubKey) 361 writeString(h, serializedEphKey) 362 363 K := make([]byte, intLength(secret)) 364 marshalInt(K, secret) 365 h.Write(K) 366 367 H := h.Sum(nil) 368 369 // H is already a hash, but the hostkey signing will apply its 370 // own key-specific hash algorithm. 371 sig, err := signAndMarshal(priv, rand, H) 372 if err != nil { 373 return nil, err 374 } 375 376 reply := kexECDHReplyMsg{ 377 EphemeralPubKey: serializedEphKey, 378 HostKey: hostKeyBytes, 379 Signature: sig, 380 } 381 382 serialized := Marshal(&reply) 383 if err := c.writePacket(serialized); err != nil { 384 return nil, err 385 } 386 387 return &kexResult{ 388 H: H, 389 K: K, 390 HostKey: reply.HostKey, 391 Signature: sig, 392 Hash: ecHash(kex.curve), 393 }, nil 394 } 395 396 var kexAlgoMap = map[string]kexAlgorithm{} 397 398 func init() { 399 // This is the group called diffie-hellman-group1-sha1 in RFC 400 // 4253 and Oakley Group 2 in RFC 2409. 401 p, _ := new(big.Int).SetString("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381FFFFFFFFFFFFFFFF", 16) 402 kexAlgoMap[kexAlgoDH1SHA1] = &dhGroup{ 403 g: new(big.Int).SetInt64(2), 404 p: p, 405 pMinus1: new(big.Int).Sub(p, bigOne), 406 407 hashFunc: crypto.SHA1, 408 } 409 410 // This is the group called diffie-hellman-group14-sha1 in RFC 411 // 4253 and Oakley Group 14 in RFC 3526. 412 p, _ = new(big.Int).SetString("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF", 16) 413 414 kexAlgoMap[kexAlgoDH14SHA1] = &dhGroup{ 415 g: new(big.Int).SetInt64(2), 416 p: p, 417 pMinus1: new(big.Int).Sub(p, bigOne), 418 419 hashFunc: crypto.SHA1, 420 } 421 422 // [Psiphon] 423 // RFC 8268: 424 // > The method of key exchange used for the name "diffie-hellman- 425 // > group14-sha256" is the same as that for "diffie-hellman-group14-sha1" 426 // > except that the SHA256 hash algorithm is used. 427 428 kexAlgoMap[kexAlgoDH14SHA256] = &dhGroup{ 429 g: new(big.Int).SetInt64(2), 430 p: p, 431 pMinus1: new(big.Int).Sub(p, bigOne), 432 433 hashFunc: crypto.SHA256, 434 } 435 436 kexAlgoMap[kexAlgoECDH521] = &ecdh{elliptic.P521()} 437 kexAlgoMap[kexAlgoECDH384] = &ecdh{elliptic.P384()} 438 kexAlgoMap[kexAlgoECDH256] = &ecdh{elliptic.P256()} 439 kexAlgoMap[kexAlgoCurve25519SHA256] = &curve25519sha256{} 440 kexAlgoMap[kexAlgoDHGEXSHA1] = &dhGEXSHA{hashFunc: crypto.SHA1} 441 kexAlgoMap[kexAlgoDHGEXSHA256] = &dhGEXSHA{hashFunc: crypto.SHA256} 442 } 443 444 // curve25519sha256 implements the curve25519-sha256@libssh.org key 445 // agreement protocol, as described in 446 // https://git.libssh.org/projects/libssh.git/tree/doc/curve25519-sha256@libssh.org.txt 447 type curve25519sha256 struct{} 448 449 type curve25519KeyPair struct { 450 priv [32]byte 451 pub [32]byte 452 } 453 454 func (kp *curve25519KeyPair) generate(rand io.Reader) error { 455 if _, err := io.ReadFull(rand, kp.priv[:]); err != nil { 456 return err 457 } 458 curve25519.ScalarBaseMult(&kp.pub, &kp.priv) 459 return nil 460 } 461 462 // curve25519Zeros is just an array of 32 zero bytes so that we have something 463 // convenient to compare against in order to reject curve25519 points with the 464 // wrong order. 465 var curve25519Zeros [32]byte 466 467 func (kex *curve25519sha256) Client(c packetConn, rand io.Reader, magics *handshakeMagics) (*kexResult, error) { 468 var kp curve25519KeyPair 469 if err := kp.generate(rand); err != nil { 470 return nil, err 471 } 472 if err := c.writePacket(Marshal(&kexECDHInitMsg{kp.pub[:]})); err != nil { 473 return nil, err 474 } 475 476 packet, err := c.readPacket() 477 if err != nil { 478 return nil, err 479 } 480 481 var reply kexECDHReplyMsg 482 if err = Unmarshal(packet, &reply); err != nil { 483 return nil, err 484 } 485 if len(reply.EphemeralPubKey) != 32 { 486 return nil, errors.New("ssh: peer's curve25519 public value has wrong length") 487 } 488 489 var servPub, secret [32]byte 490 copy(servPub[:], reply.EphemeralPubKey) 491 curve25519.ScalarMult(&secret, &kp.priv, &servPub) 492 if subtle.ConstantTimeCompare(secret[:], curve25519Zeros[:]) == 1 { 493 return nil, errors.New("ssh: peer's curve25519 public value has wrong order") 494 } 495 496 h := crypto.SHA256.New() 497 magics.write(h) 498 writeString(h, reply.HostKey) 499 writeString(h, kp.pub[:]) 500 writeString(h, reply.EphemeralPubKey) 501 502 ki := new(big.Int).SetBytes(secret[:]) 503 K := make([]byte, intLength(ki)) 504 marshalInt(K, ki) 505 h.Write(K) 506 507 return &kexResult{ 508 H: h.Sum(nil), 509 K: K, 510 HostKey: reply.HostKey, 511 Signature: reply.Signature, 512 Hash: crypto.SHA256, 513 }, nil 514 } 515 516 func (kex *curve25519sha256) Server(c packetConn, rand io.Reader, magics *handshakeMagics, priv Signer) (result *kexResult, err error) { 517 packet, err := c.readPacket() 518 if err != nil { 519 return 520 } 521 var kexInit kexECDHInitMsg 522 if err = Unmarshal(packet, &kexInit); err != nil { 523 return 524 } 525 526 if len(kexInit.ClientPubKey) != 32 { 527 return nil, errors.New("ssh: peer's curve25519 public value has wrong length") 528 } 529 530 var kp curve25519KeyPair 531 if err := kp.generate(rand); err != nil { 532 return nil, err 533 } 534 535 var clientPub, secret [32]byte 536 copy(clientPub[:], kexInit.ClientPubKey) 537 curve25519.ScalarMult(&secret, &kp.priv, &clientPub) 538 if subtle.ConstantTimeCompare(secret[:], curve25519Zeros[:]) == 1 { 539 return nil, errors.New("ssh: peer's curve25519 public value has wrong order") 540 } 541 542 hostKeyBytes := priv.PublicKey().Marshal() 543 544 h := crypto.SHA256.New() 545 magics.write(h) 546 writeString(h, hostKeyBytes) 547 writeString(h, kexInit.ClientPubKey) 548 writeString(h, kp.pub[:]) 549 550 ki := new(big.Int).SetBytes(secret[:]) 551 K := make([]byte, intLength(ki)) 552 marshalInt(K, ki) 553 h.Write(K) 554 555 H := h.Sum(nil) 556 557 sig, err := signAndMarshal(priv, rand, H) 558 if err != nil { 559 return nil, err 560 } 561 562 reply := kexECDHReplyMsg{ 563 EphemeralPubKey: kp.pub[:], 564 HostKey: hostKeyBytes, 565 Signature: sig, 566 } 567 if err := c.writePacket(Marshal(&reply)); err != nil { 568 return nil, err 569 } 570 return &kexResult{ 571 H: H, 572 K: K, 573 HostKey: hostKeyBytes, 574 Signature: sig, 575 Hash: crypto.SHA256, 576 }, nil 577 } 578 579 // dhGEXSHA implements the diffie-hellman-group-exchange-sha1 and 580 // diffie-hellman-group-exchange-sha256 key agreement protocols, 581 // as described in RFC 4419 582 type dhGEXSHA struct { 583 g, p *big.Int 584 hashFunc crypto.Hash 585 } 586 587 const ( 588 dhGroupExchangeMinimumBits = 2048 589 dhGroupExchangePreferredBits = 2048 590 dhGroupExchangeMaximumBits = 8192 591 ) 592 593 func (gex *dhGEXSHA) diffieHellman(theirPublic, myPrivate *big.Int) (*big.Int, error) { 594 if theirPublic.Sign() <= 0 || theirPublic.Cmp(gex.p) >= 0 { 595 return nil, fmt.Errorf("ssh: DH parameter out of bounds") 596 } 597 return new(big.Int).Exp(theirPublic, myPrivate, gex.p), nil 598 } 599 600 func (gex dhGEXSHA) Client(c packetConn, randSource io.Reader, magics *handshakeMagics) (*kexResult, error) { 601 // Send GexRequest 602 kexDHGexRequest := kexDHGexRequestMsg{ 603 MinBits: dhGroupExchangeMinimumBits, 604 PreferedBits: dhGroupExchangePreferredBits, 605 MaxBits: dhGroupExchangeMaximumBits, 606 } 607 if err := c.writePacket(Marshal(&kexDHGexRequest)); err != nil { 608 return nil, err 609 } 610 611 // Receive GexGroup 612 packet, err := c.readPacket() 613 if err != nil { 614 return nil, err 615 } 616 617 var kexDHGexGroup kexDHGexGroupMsg 618 if err = Unmarshal(packet, &kexDHGexGroup); err != nil { 619 return nil, err 620 } 621 622 // reject if p's bit length < dhGroupExchangeMinimumBits or > dhGroupExchangeMaximumBits 623 if kexDHGexGroup.P.BitLen() < dhGroupExchangeMinimumBits || kexDHGexGroup.P.BitLen() > dhGroupExchangeMaximumBits { 624 return nil, fmt.Errorf("ssh: server-generated gex p is out of range (%d bits)", kexDHGexGroup.P.BitLen()) 625 } 626 627 gex.p = kexDHGexGroup.P 628 gex.g = kexDHGexGroup.G 629 630 // Check if g is safe by verifing that g > 1 and g < p - 1 631 one := big.NewInt(1) 632 var pMinusOne = &big.Int{} 633 pMinusOne.Sub(gex.p, one) 634 if gex.g.Cmp(one) != 1 && gex.g.Cmp(pMinusOne) != -1 { 635 return nil, fmt.Errorf("ssh: server provided gex g is not safe") 636 } 637 638 // Send GexInit 639 var pHalf = &big.Int{} 640 pHalf.Rsh(gex.p, 1) 641 x, err := rand.Int(randSource, pHalf) 642 if err != nil { 643 return nil, err 644 } 645 X := new(big.Int).Exp(gex.g, x, gex.p) 646 kexDHGexInit := kexDHGexInitMsg{ 647 X: X, 648 } 649 if err := c.writePacket(Marshal(&kexDHGexInit)); err != nil { 650 return nil, err 651 } 652 653 // Receive GexReply 654 packet, err = c.readPacket() 655 if err != nil { 656 return nil, err 657 } 658 659 var kexDHGexReply kexDHGexReplyMsg 660 if err = Unmarshal(packet, &kexDHGexReply); err != nil { 661 return nil, err 662 } 663 664 kInt, err := gex.diffieHellman(kexDHGexReply.Y, x) 665 if err != nil { 666 return nil, err 667 } 668 669 // Check if k is safe by verifing that k > 1 and k < p - 1 670 if kInt.Cmp(one) != 1 && kInt.Cmp(pMinusOne) != -1 { 671 return nil, fmt.Errorf("ssh: derived k is not safe") 672 } 673 674 h := gex.hashFunc.New() 675 magics.write(h) 676 writeString(h, kexDHGexReply.HostKey) 677 binary.Write(h, binary.BigEndian, uint32(dhGroupExchangeMinimumBits)) 678 binary.Write(h, binary.BigEndian, uint32(dhGroupExchangePreferredBits)) 679 binary.Write(h, binary.BigEndian, uint32(dhGroupExchangeMaximumBits)) 680 writeInt(h, gex.p) 681 writeInt(h, gex.g) 682 writeInt(h, X) 683 writeInt(h, kexDHGexReply.Y) 684 K := make([]byte, intLength(kInt)) 685 marshalInt(K, kInt) 686 h.Write(K) 687 688 return &kexResult{ 689 H: h.Sum(nil), 690 K: K, 691 HostKey: kexDHGexReply.HostKey, 692 Signature: kexDHGexReply.Signature, 693 Hash: gex.hashFunc, 694 }, nil 695 } 696 697 // Server half implementation of the Diffie Hellman Key Exchange with SHA1 and SHA256. 698 // 699 // This is a minimal implementation to satisfy the automated tests. 700 func (gex dhGEXSHA) Server(c packetConn, randSource io.Reader, magics *handshakeMagics, priv Signer) (result *kexResult, err error) { 701 // Receive GexRequest 702 packet, err := c.readPacket() 703 if err != nil { 704 return 705 } 706 var kexDHGexRequest kexDHGexRequestMsg 707 if err = Unmarshal(packet, &kexDHGexRequest); err != nil { 708 return 709 } 710 711 // smoosh the user's preferred size into our own limits 712 if kexDHGexRequest.PreferedBits > dhGroupExchangeMaximumBits { 713 kexDHGexRequest.PreferedBits = dhGroupExchangeMaximumBits 714 } 715 if kexDHGexRequest.PreferedBits < dhGroupExchangeMinimumBits { 716 kexDHGexRequest.PreferedBits = dhGroupExchangeMinimumBits 717 } 718 // fix min/max if they're inconsistent. technically, we could just pout 719 // and hang up, but there's no harm in giving them the benefit of the 720 // doubt and just picking a bitsize for them. 721 if kexDHGexRequest.MinBits > kexDHGexRequest.PreferedBits { 722 kexDHGexRequest.MinBits = kexDHGexRequest.PreferedBits 723 } 724 if kexDHGexRequest.MaxBits < kexDHGexRequest.PreferedBits { 725 kexDHGexRequest.MaxBits = kexDHGexRequest.PreferedBits 726 } 727 728 // Send GexGroup 729 // This is the group called diffie-hellman-group14-sha1 in RFC 730 // 4253 and Oakley Group 14 in RFC 3526. 731 p, _ := new(big.Int).SetString("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF", 16) 732 gex.p = p 733 gex.g = big.NewInt(2) 734 735 kexDHGexGroup := kexDHGexGroupMsg{ 736 P: gex.p, 737 G: gex.g, 738 } 739 if err := c.writePacket(Marshal(&kexDHGexGroup)); err != nil { 740 return nil, err 741 } 742 743 // Receive GexInit 744 packet, err = c.readPacket() 745 if err != nil { 746 return 747 } 748 var kexDHGexInit kexDHGexInitMsg 749 if err = Unmarshal(packet, &kexDHGexInit); err != nil { 750 return 751 } 752 753 var pHalf = &big.Int{} 754 pHalf.Rsh(gex.p, 1) 755 756 y, err := rand.Int(randSource, pHalf) 757 if err != nil { 758 return 759 } 760 761 Y := new(big.Int).Exp(gex.g, y, gex.p) 762 kInt, err := gex.diffieHellman(kexDHGexInit.X, y) 763 if err != nil { 764 return nil, err 765 } 766 767 hostKeyBytes := priv.PublicKey().Marshal() 768 769 h := gex.hashFunc.New() 770 magics.write(h) 771 writeString(h, hostKeyBytes) 772 binary.Write(h, binary.BigEndian, uint32(dhGroupExchangeMinimumBits)) 773 binary.Write(h, binary.BigEndian, uint32(dhGroupExchangePreferredBits)) 774 binary.Write(h, binary.BigEndian, uint32(dhGroupExchangeMaximumBits)) 775 writeInt(h, gex.p) 776 writeInt(h, gex.g) 777 writeInt(h, kexDHGexInit.X) 778 writeInt(h, Y) 779 780 K := make([]byte, intLength(kInt)) 781 marshalInt(K, kInt) 782 h.Write(K) 783 784 H := h.Sum(nil) 785 786 // H is already a hash, but the hostkey signing will apply its 787 // own key-specific hash algorithm. 788 sig, err := signAndMarshal(priv, randSource, H) 789 if err != nil { 790 return nil, err 791 } 792 793 kexDHGexReply := kexDHGexReplyMsg{ 794 HostKey: hostKeyBytes, 795 Y: Y, 796 Signature: sig, 797 } 798 packet = Marshal(&kexDHGexReply) 799 800 err = c.writePacket(packet) 801 802 return &kexResult{ 803 H: H, 804 K: K, 805 HostKey: hostKeyBytes, 806 Signature: sig, 807 Hash: gex.hashFunc, 808 }, err 809 }