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  }