kex.go 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567
  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. package ssh
  5. import (
  6. "crypto"
  7. "crypto/ecdsa"
  8. "crypto/elliptic"
  9. "crypto/rand"
  10. "crypto/subtle"
  11. "errors"
  12. "io"
  13. "math/big"
  14. "golang.org/x/crypto/curve25519"
  15. )
  16. const (
  17. kexAlgoDH1SHA1 = "diffie-hellman-group1-sha1"
  18. kexAlgoDH14SHA1 = "diffie-hellman-group14-sha1"
  19. kexAlgoDH14SHA256 = "diffie-hellman-group14-sha256"
  20. kexAlgoECDH256 = "ecdh-sha2-nistp256"
  21. kexAlgoECDH384 = "ecdh-sha2-nistp384"
  22. kexAlgoECDH521 = "ecdh-sha2-nistp521"
  23. kexAlgoCurve25519SHA256 = "[email protected]"
  24. )
  25. // kexResult captures the outcome of a key exchange.
  26. type kexResult struct {
  27. // Session hash. See also RFC 4253, section 8.
  28. H []byte
  29. // Shared secret. See also RFC 4253, section 8.
  30. K []byte
  31. // Host key as hashed into H.
  32. HostKey []byte
  33. // Signature of H.
  34. Signature []byte
  35. // A cryptographic hash function that matches the security
  36. // level of the key exchange algorithm. It is used for
  37. // calculating H, and for deriving keys from H and K.
  38. Hash crypto.Hash
  39. // The session ID, which is the first H computed. This is used
  40. // to derive key material inside the transport.
  41. SessionID []byte
  42. }
  43. // handshakeMagics contains data that is always included in the
  44. // session hash.
  45. type handshakeMagics struct {
  46. clientVersion, serverVersion []byte
  47. clientKexInit, serverKexInit []byte
  48. }
  49. func (m *handshakeMagics) write(w io.Writer) {
  50. writeString(w, m.clientVersion)
  51. writeString(w, m.serverVersion)
  52. writeString(w, m.clientKexInit)
  53. writeString(w, m.serverKexInit)
  54. }
  55. // kexAlgorithm abstracts different key exchange algorithms.
  56. type kexAlgorithm interface {
  57. // Server runs server-side key agreement, signing the result
  58. // with a hostkey.
  59. Server(p packetConn, rand io.Reader, magics *handshakeMagics, s Signer) (*kexResult, error)
  60. // Client runs the client-side key agreement. Caller is
  61. // responsible for verifying the host key signature.
  62. Client(p packetConn, rand io.Reader, magics *handshakeMagics) (*kexResult, error)
  63. }
  64. // dhGroup is a multiplicative group suitable for implementing Diffie-Hellman key agreement.
  65. type dhGroup struct {
  66. g, p, pMinus1 *big.Int
  67. // [Psiphon]
  68. hashFunc crypto.Hash
  69. }
  70. func (group *dhGroup) diffieHellman(theirPublic, myPrivate *big.Int) (*big.Int, error) {
  71. if theirPublic.Cmp(bigOne) <= 0 || theirPublic.Cmp(group.pMinus1) >= 0 {
  72. return nil, errors.New("ssh: DH parameter out of bounds")
  73. }
  74. return new(big.Int).Exp(theirPublic, myPrivate, group.p), nil
  75. }
  76. func (group *dhGroup) Client(c packetConn, randSource io.Reader, magics *handshakeMagics) (*kexResult, error) {
  77. // [Psiphon]
  78. hashFunc := group.hashFunc
  79. var x *big.Int
  80. for {
  81. var err error
  82. if x, err = rand.Int(randSource, group.pMinus1); err != nil {
  83. return nil, err
  84. }
  85. if x.Sign() > 0 {
  86. break
  87. }
  88. }
  89. X := new(big.Int).Exp(group.g, x, group.p)
  90. kexDHInit := kexDHInitMsg{
  91. X: X,
  92. }
  93. if err := c.writePacket(Marshal(&kexDHInit)); err != nil {
  94. return nil, err
  95. }
  96. packet, err := c.readPacket()
  97. if err != nil {
  98. return nil, err
  99. }
  100. var kexDHReply kexDHReplyMsg
  101. if err = Unmarshal(packet, &kexDHReply); err != nil {
  102. return nil, err
  103. }
  104. ki, err := group.diffieHellman(kexDHReply.Y, x)
  105. if err != nil {
  106. return nil, err
  107. }
  108. h := hashFunc.New()
  109. magics.write(h)
  110. writeString(h, kexDHReply.HostKey)
  111. writeInt(h, X)
  112. writeInt(h, kexDHReply.Y)
  113. K := make([]byte, intLength(ki))
  114. marshalInt(K, ki)
  115. h.Write(K)
  116. return &kexResult{
  117. H: h.Sum(nil),
  118. K: K,
  119. HostKey: kexDHReply.HostKey,
  120. Signature: kexDHReply.Signature,
  121. Hash: hashFunc,
  122. }, nil
  123. }
  124. func (group *dhGroup) Server(c packetConn, randSource io.Reader, magics *handshakeMagics, priv Signer) (result *kexResult, err error) {
  125. // [Psiphon]
  126. hashFunc := group.hashFunc
  127. packet, err := c.readPacket()
  128. if err != nil {
  129. return
  130. }
  131. var kexDHInit kexDHInitMsg
  132. if err = Unmarshal(packet, &kexDHInit); err != nil {
  133. return
  134. }
  135. var y *big.Int
  136. for {
  137. if y, err = rand.Int(randSource, group.pMinus1); err != nil {
  138. return
  139. }
  140. if y.Sign() > 0 {
  141. break
  142. }
  143. }
  144. Y := new(big.Int).Exp(group.g, y, group.p)
  145. ki, err := group.diffieHellman(kexDHInit.X, y)
  146. if err != nil {
  147. return nil, err
  148. }
  149. hostKeyBytes := priv.PublicKey().Marshal()
  150. h := hashFunc.New()
  151. magics.write(h)
  152. writeString(h, hostKeyBytes)
  153. writeInt(h, kexDHInit.X)
  154. writeInt(h, Y)
  155. K := make([]byte, intLength(ki))
  156. marshalInt(K, ki)
  157. h.Write(K)
  158. H := h.Sum(nil)
  159. // H is already a hash, but the hostkey signing will apply its
  160. // own key-specific hash algorithm.
  161. sig, err := signAndMarshal(priv, randSource, H)
  162. if err != nil {
  163. return nil, err
  164. }
  165. kexDHReply := kexDHReplyMsg{
  166. HostKey: hostKeyBytes,
  167. Y: Y,
  168. Signature: sig,
  169. }
  170. packet = Marshal(&kexDHReply)
  171. err = c.writePacket(packet)
  172. return &kexResult{
  173. H: H,
  174. K: K,
  175. HostKey: hostKeyBytes,
  176. Signature: sig,
  177. Hash: hashFunc,
  178. }, nil
  179. }
  180. // ecdh performs Elliptic Curve Diffie-Hellman key exchange as
  181. // described in RFC 5656, section 4.
  182. type ecdh struct {
  183. curve elliptic.Curve
  184. }
  185. func (kex *ecdh) Client(c packetConn, rand io.Reader, magics *handshakeMagics) (*kexResult, error) {
  186. ephKey, err := ecdsa.GenerateKey(kex.curve, rand)
  187. if err != nil {
  188. return nil, err
  189. }
  190. kexInit := kexECDHInitMsg{
  191. ClientPubKey: elliptic.Marshal(kex.curve, ephKey.PublicKey.X, ephKey.PublicKey.Y),
  192. }
  193. serialized := Marshal(&kexInit)
  194. if err := c.writePacket(serialized); err != nil {
  195. return nil, err
  196. }
  197. packet, err := c.readPacket()
  198. if err != nil {
  199. return nil, err
  200. }
  201. var reply kexECDHReplyMsg
  202. if err = Unmarshal(packet, &reply); err != nil {
  203. return nil, err
  204. }
  205. x, y, err := unmarshalECKey(kex.curve, reply.EphemeralPubKey)
  206. if err != nil {
  207. return nil, err
  208. }
  209. // generate shared secret
  210. secret, _ := kex.curve.ScalarMult(x, y, ephKey.D.Bytes())
  211. h := ecHash(kex.curve).New()
  212. magics.write(h)
  213. writeString(h, reply.HostKey)
  214. writeString(h, kexInit.ClientPubKey)
  215. writeString(h, reply.EphemeralPubKey)
  216. K := make([]byte, intLength(secret))
  217. marshalInt(K, secret)
  218. h.Write(K)
  219. return &kexResult{
  220. H: h.Sum(nil),
  221. K: K,
  222. HostKey: reply.HostKey,
  223. Signature: reply.Signature,
  224. Hash: ecHash(kex.curve),
  225. }, nil
  226. }
  227. // unmarshalECKey parses and checks an EC key.
  228. func unmarshalECKey(curve elliptic.Curve, pubkey []byte) (x, y *big.Int, err error) {
  229. x, y = elliptic.Unmarshal(curve, pubkey)
  230. if x == nil {
  231. return nil, nil, errors.New("ssh: elliptic.Unmarshal failure")
  232. }
  233. if !validateECPublicKey(curve, x, y) {
  234. return nil, nil, errors.New("ssh: public key not on curve")
  235. }
  236. return x, y, nil
  237. }
  238. // validateECPublicKey checks that the point is a valid public key for
  239. // the given curve. See [SEC1], 3.2.2
  240. func validateECPublicKey(curve elliptic.Curve, x, y *big.Int) bool {
  241. if x.Sign() == 0 && y.Sign() == 0 {
  242. return false
  243. }
  244. if x.Cmp(curve.Params().P) >= 0 {
  245. return false
  246. }
  247. if y.Cmp(curve.Params().P) >= 0 {
  248. return false
  249. }
  250. if !curve.IsOnCurve(x, y) {
  251. return false
  252. }
  253. // We don't check if N * PubKey == 0, since
  254. //
  255. // - the NIST curves have cofactor = 1, so this is implicit.
  256. // (We don't foresee an implementation that supports non NIST
  257. // curves)
  258. //
  259. // - for ephemeral keys, we don't need to worry about small
  260. // subgroup attacks.
  261. return true
  262. }
  263. func (kex *ecdh) Server(c packetConn, rand io.Reader, magics *handshakeMagics, priv Signer) (result *kexResult, err error) {
  264. packet, err := c.readPacket()
  265. if err != nil {
  266. return nil, err
  267. }
  268. var kexECDHInit kexECDHInitMsg
  269. if err = Unmarshal(packet, &kexECDHInit); err != nil {
  270. return nil, err
  271. }
  272. clientX, clientY, err := unmarshalECKey(kex.curve, kexECDHInit.ClientPubKey)
  273. if err != nil {
  274. return nil, err
  275. }
  276. // We could cache this key across multiple users/multiple
  277. // connection attempts, but the benefit is small. OpenSSH
  278. // generates a new key for each incoming connection.
  279. ephKey, err := ecdsa.GenerateKey(kex.curve, rand)
  280. if err != nil {
  281. return nil, err
  282. }
  283. hostKeyBytes := priv.PublicKey().Marshal()
  284. serializedEphKey := elliptic.Marshal(kex.curve, ephKey.PublicKey.X, ephKey.PublicKey.Y)
  285. // generate shared secret
  286. secret, _ := kex.curve.ScalarMult(clientX, clientY, ephKey.D.Bytes())
  287. h := ecHash(kex.curve).New()
  288. magics.write(h)
  289. writeString(h, hostKeyBytes)
  290. writeString(h, kexECDHInit.ClientPubKey)
  291. writeString(h, serializedEphKey)
  292. K := make([]byte, intLength(secret))
  293. marshalInt(K, secret)
  294. h.Write(K)
  295. H := h.Sum(nil)
  296. // H is already a hash, but the hostkey signing will apply its
  297. // own key-specific hash algorithm.
  298. sig, err := signAndMarshal(priv, rand, H)
  299. if err != nil {
  300. return nil, err
  301. }
  302. reply := kexECDHReplyMsg{
  303. EphemeralPubKey: serializedEphKey,
  304. HostKey: hostKeyBytes,
  305. Signature: sig,
  306. }
  307. serialized := Marshal(&reply)
  308. if err := c.writePacket(serialized); err != nil {
  309. return nil, err
  310. }
  311. return &kexResult{
  312. H: H,
  313. K: K,
  314. HostKey: reply.HostKey,
  315. Signature: sig,
  316. Hash: ecHash(kex.curve),
  317. }, nil
  318. }
  319. var kexAlgoMap = map[string]kexAlgorithm{}
  320. func init() {
  321. // This is the group called diffie-hellman-group1-sha1 in RFC
  322. // 4253 and Oakley Group 2 in RFC 2409.
  323. p, _ := new(big.Int).SetString("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381FFFFFFFFFFFFFFFF", 16)
  324. kexAlgoMap[kexAlgoDH1SHA1] = &dhGroup{
  325. g: new(big.Int).SetInt64(2),
  326. p: p,
  327. pMinus1: new(big.Int).Sub(p, bigOne),
  328. hashFunc: crypto.SHA1,
  329. }
  330. // This is the group called diffie-hellman-group14-sha1 in RFC
  331. // 4253 and Oakley Group 14 in RFC 3526.
  332. p, _ = new(big.Int).SetString("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF", 16)
  333. kexAlgoMap[kexAlgoDH14SHA1] = &dhGroup{
  334. g: new(big.Int).SetInt64(2),
  335. p: p,
  336. pMinus1: new(big.Int).Sub(p, bigOne),
  337. hashFunc: crypto.SHA1,
  338. }
  339. // [Psiphon]
  340. // RFC 8268:
  341. // > The method of key exchange used for the name "diffie-hellman-
  342. // > group14-sha256" is the same as that for "diffie-hellman-group14-sha1"
  343. // > except that the SHA256 hash algorithm is used.
  344. kexAlgoMap[kexAlgoDH14SHA256] = &dhGroup{
  345. g: new(big.Int).SetInt64(2),
  346. p: p,
  347. pMinus1: new(big.Int).Sub(p, bigOne),
  348. hashFunc: crypto.SHA256,
  349. }
  350. kexAlgoMap[kexAlgoECDH521] = &ecdh{elliptic.P521()}
  351. kexAlgoMap[kexAlgoECDH384] = &ecdh{elliptic.P384()}
  352. kexAlgoMap[kexAlgoECDH256] = &ecdh{elliptic.P256()}
  353. kexAlgoMap[kexAlgoCurve25519SHA256] = &curve25519sha256{}
  354. }
  355. // curve25519sha256 implements the [email protected] key
  356. // agreement protocol, as described in
  357. // https://git.libssh.org/projects/libssh.git/tree/doc/[email protected]
  358. type curve25519sha256 struct{}
  359. type curve25519KeyPair struct {
  360. priv [32]byte
  361. pub [32]byte
  362. }
  363. func (kp *curve25519KeyPair) generate(rand io.Reader) error {
  364. if _, err := io.ReadFull(rand, kp.priv[:]); err != nil {
  365. return err
  366. }
  367. curve25519.ScalarBaseMult(&kp.pub, &kp.priv)
  368. return nil
  369. }
  370. // curve25519Zeros is just an array of 32 zero bytes so that we have something
  371. // convenient to compare against in order to reject curve25519 points with the
  372. // wrong order.
  373. var curve25519Zeros [32]byte
  374. func (kex *curve25519sha256) Client(c packetConn, rand io.Reader, magics *handshakeMagics) (*kexResult, error) {
  375. var kp curve25519KeyPair
  376. if err := kp.generate(rand); err != nil {
  377. return nil, err
  378. }
  379. if err := c.writePacket(Marshal(&kexECDHInitMsg{kp.pub[:]})); err != nil {
  380. return nil, err
  381. }
  382. packet, err := c.readPacket()
  383. if err != nil {
  384. return nil, err
  385. }
  386. var reply kexECDHReplyMsg
  387. if err = Unmarshal(packet, &reply); err != nil {
  388. return nil, err
  389. }
  390. if len(reply.EphemeralPubKey) != 32 {
  391. return nil, errors.New("ssh: peer's curve25519 public value has wrong length")
  392. }
  393. var servPub, secret [32]byte
  394. copy(servPub[:], reply.EphemeralPubKey)
  395. curve25519.ScalarMult(&secret, &kp.priv, &servPub)
  396. if subtle.ConstantTimeCompare(secret[:], curve25519Zeros[:]) == 1 {
  397. return nil, errors.New("ssh: peer's curve25519 public value has wrong order")
  398. }
  399. h := crypto.SHA256.New()
  400. magics.write(h)
  401. writeString(h, reply.HostKey)
  402. writeString(h, kp.pub[:])
  403. writeString(h, reply.EphemeralPubKey)
  404. ki := new(big.Int).SetBytes(secret[:])
  405. K := make([]byte, intLength(ki))
  406. marshalInt(K, ki)
  407. h.Write(K)
  408. return &kexResult{
  409. H: h.Sum(nil),
  410. K: K,
  411. HostKey: reply.HostKey,
  412. Signature: reply.Signature,
  413. Hash: crypto.SHA256,
  414. }, nil
  415. }
  416. func (kex *curve25519sha256) Server(c packetConn, rand io.Reader, magics *handshakeMagics, priv Signer) (result *kexResult, err error) {
  417. packet, err := c.readPacket()
  418. if err != nil {
  419. return
  420. }
  421. var kexInit kexECDHInitMsg
  422. if err = Unmarshal(packet, &kexInit); err != nil {
  423. return
  424. }
  425. if len(kexInit.ClientPubKey) != 32 {
  426. return nil, errors.New("ssh: peer's curve25519 public value has wrong length")
  427. }
  428. var kp curve25519KeyPair
  429. if err := kp.generate(rand); err != nil {
  430. return nil, err
  431. }
  432. var clientPub, secret [32]byte
  433. copy(clientPub[:], kexInit.ClientPubKey)
  434. curve25519.ScalarMult(&secret, &kp.priv, &clientPub)
  435. if subtle.ConstantTimeCompare(secret[:], curve25519Zeros[:]) == 1 {
  436. return nil, errors.New("ssh: peer's curve25519 public value has wrong order")
  437. }
  438. hostKeyBytes := priv.PublicKey().Marshal()
  439. h := crypto.SHA256.New()
  440. magics.write(h)
  441. writeString(h, hostKeyBytes)
  442. writeString(h, kexInit.ClientPubKey)
  443. writeString(h, kp.pub[:])
  444. ki := new(big.Int).SetBytes(secret[:])
  445. K := make([]byte, intLength(ki))
  446. marshalInt(K, ki)
  447. h.Write(K)
  448. H := h.Sum(nil)
  449. sig, err := signAndMarshal(priv, rand, H)
  450. if err != nil {
  451. return nil, err
  452. }
  453. reply := kexECDHReplyMsg{
  454. EphemeralPubKey: kp.pub[:],
  455. HostKey: hostKeyBytes,
  456. Signature: sig,
  457. }
  458. if err := c.writePacket(Marshal(&reply)); err != nil {
  459. return nil, err
  460. }
  461. return &kexResult{
  462. H: H,
  463. K: K,
  464. HostKey: hostKeyBytes,
  465. Signature: sig,
  466. Hash: crypto.SHA256,
  467. }, nil
  468. }