gtsocial-umbx

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

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 }