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