本站源代码
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

771 lines
21KB

  1. // Copyright 2011 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/aes"
  7. "crypto/cipher"
  8. "crypto/des"
  9. "crypto/rc4"
  10. "crypto/subtle"
  11. "encoding/binary"
  12. "errors"
  13. "fmt"
  14. "hash"
  15. "io"
  16. "io/ioutil"
  17. "math/bits"
  18. "golang.org/x/crypto/internal/chacha20"
  19. "golang.org/x/crypto/poly1305"
  20. )
  21. const (
  22. packetSizeMultiple = 16 // TODO(huin) this should be determined by the cipher.
  23. // RFC 4253 section 6.1 defines a minimum packet size of 32768 that implementations
  24. // MUST be able to process (plus a few more kilobytes for padding and mac). The RFC
  25. // indicates implementations SHOULD be able to handle larger packet sizes, but then
  26. // waffles on about reasonable limits.
  27. //
  28. // OpenSSH caps their maxPacket at 256kB so we choose to do
  29. // the same. maxPacket is also used to ensure that uint32
  30. // length fields do not overflow, so it should remain well
  31. // below 4G.
  32. maxPacket = 256 * 1024
  33. )
  34. // noneCipher implements cipher.Stream and provides no encryption. It is used
  35. // by the transport before the first key-exchange.
  36. type noneCipher struct{}
  37. func (c noneCipher) XORKeyStream(dst, src []byte) {
  38. copy(dst, src)
  39. }
  40. func newAESCTR(key, iv []byte) (cipher.Stream, error) {
  41. c, err := aes.NewCipher(key)
  42. if err != nil {
  43. return nil, err
  44. }
  45. return cipher.NewCTR(c, iv), nil
  46. }
  47. func newRC4(key, iv []byte) (cipher.Stream, error) {
  48. return rc4.NewCipher(key)
  49. }
  50. type cipherMode struct {
  51. keySize int
  52. ivSize int
  53. create func(key, iv []byte, macKey []byte, algs directionAlgorithms) (packetCipher, error)
  54. }
  55. func streamCipherMode(skip int, createFunc func(key, iv []byte) (cipher.Stream, error)) func(key, iv []byte, macKey []byte, algs directionAlgorithms) (packetCipher, error) {
  56. return func(key, iv, macKey []byte, algs directionAlgorithms) (packetCipher, error) {
  57. stream, err := createFunc(key, iv)
  58. if err != nil {
  59. return nil, err
  60. }
  61. var streamDump []byte
  62. if skip > 0 {
  63. streamDump = make([]byte, 512)
  64. }
  65. for remainingToDump := skip; remainingToDump > 0; {
  66. dumpThisTime := remainingToDump
  67. if dumpThisTime > len(streamDump) {
  68. dumpThisTime = len(streamDump)
  69. }
  70. stream.XORKeyStream(streamDump[:dumpThisTime], streamDump[:dumpThisTime])
  71. remainingToDump -= dumpThisTime
  72. }
  73. mac := macModes[algs.MAC].new(macKey)
  74. return &streamPacketCipher{
  75. mac: mac,
  76. etm: macModes[algs.MAC].etm,
  77. macResult: make([]byte, mac.Size()),
  78. cipher: stream,
  79. }, nil
  80. }
  81. }
  82. // cipherModes documents properties of supported ciphers. Ciphers not included
  83. // are not supported and will not be negotiated, even if explicitly requested in
  84. // ClientConfig.Crypto.Ciphers.
  85. var cipherModes = map[string]*cipherMode{
  86. // Ciphers from RFC4344, which introduced many CTR-based ciphers. Algorithms
  87. // are defined in the order specified in the RFC.
  88. "aes128-ctr": {16, aes.BlockSize, streamCipherMode(0, newAESCTR)},
  89. "aes192-ctr": {24, aes.BlockSize, streamCipherMode(0, newAESCTR)},
  90. "aes256-ctr": {32, aes.BlockSize, streamCipherMode(0, newAESCTR)},
  91. // Ciphers from RFC4345, which introduces security-improved arcfour ciphers.
  92. // They are defined in the order specified in the RFC.
  93. "arcfour128": {16, 0, streamCipherMode(1536, newRC4)},
  94. "arcfour256": {32, 0, streamCipherMode(1536, newRC4)},
  95. // Cipher defined in RFC 4253, which describes SSH Transport Layer Protocol.
  96. // Note that this cipher is not safe, as stated in RFC 4253: "Arcfour (and
  97. // RC4) has problems with weak keys, and should be used with caution."
  98. // RFC4345 introduces improved versions of Arcfour.
  99. "arcfour": {16, 0, streamCipherMode(0, newRC4)},
  100. // AEAD ciphers
  101. gcmCipherID: {16, 12, newGCMCipher},
  102. chacha20Poly1305ID: {64, 0, newChaCha20Cipher},
  103. // CBC mode is insecure and so is not included in the default config.
  104. // (See http://www.isg.rhul.ac.uk/~kp/SandPfinal.pdf). If absolutely
  105. // needed, it's possible to specify a custom Config to enable it.
  106. // You should expect that an active attacker can recover plaintext if
  107. // you do.
  108. aes128cbcID: {16, aes.BlockSize, newAESCBCCipher},
  109. // 3des-cbc is insecure and is not included in the default
  110. // config.
  111. tripledescbcID: {24, des.BlockSize, newTripleDESCBCCipher},
  112. }
  113. // prefixLen is the length of the packet prefix that contains the packet length
  114. // and number of padding bytes.
  115. const prefixLen = 5
  116. // streamPacketCipher is a packetCipher using a stream cipher.
  117. type streamPacketCipher struct {
  118. mac hash.Hash
  119. cipher cipher.Stream
  120. etm bool
  121. // The following members are to avoid per-packet allocations.
  122. prefix [prefixLen]byte
  123. seqNumBytes [4]byte
  124. padding [2 * packetSizeMultiple]byte
  125. packetData []byte
  126. macResult []byte
  127. }
  128. // readCipherPacket reads and decrypt a single packet from the reader argument.
  129. func (s *streamPacketCipher) readCipherPacket(seqNum uint32, r io.Reader) ([]byte, error) {
  130. if _, err := io.ReadFull(r, s.prefix[:]); err != nil {
  131. return nil, err
  132. }
  133. var encryptedPaddingLength [1]byte
  134. if s.mac != nil && s.etm {
  135. copy(encryptedPaddingLength[:], s.prefix[4:5])
  136. s.cipher.XORKeyStream(s.prefix[4:5], s.prefix[4:5])
  137. } else {
  138. s.cipher.XORKeyStream(s.prefix[:], s.prefix[:])
  139. }
  140. length := binary.BigEndian.Uint32(s.prefix[0:4])
  141. paddingLength := uint32(s.prefix[4])
  142. var macSize uint32
  143. if s.mac != nil {
  144. s.mac.Reset()
  145. binary.BigEndian.PutUint32(s.seqNumBytes[:], seqNum)
  146. s.mac.Write(s.seqNumBytes[:])
  147. if s.etm {
  148. s.mac.Write(s.prefix[:4])
  149. s.mac.Write(encryptedPaddingLength[:])
  150. } else {
  151. s.mac.Write(s.prefix[:])
  152. }
  153. macSize = uint32(s.mac.Size())
  154. }
  155. if length <= paddingLength+1 {
  156. return nil, errors.New("ssh: invalid packet length, packet too small")
  157. }
  158. if length > maxPacket {
  159. return nil, errors.New("ssh: invalid packet length, packet too large")
  160. }
  161. // the maxPacket check above ensures that length-1+macSize
  162. // does not overflow.
  163. if uint32(cap(s.packetData)) < length-1+macSize {
  164. s.packetData = make([]byte, length-1+macSize)
  165. } else {
  166. s.packetData = s.packetData[:length-1+macSize]
  167. }
  168. if _, err := io.ReadFull(r, s.packetData); err != nil {
  169. return nil, err
  170. }
  171. mac := s.packetData[length-1:]
  172. data := s.packetData[:length-1]
  173. if s.mac != nil && s.etm {
  174. s.mac.Write(data)
  175. }
  176. s.cipher.XORKeyStream(data, data)
  177. if s.mac != nil {
  178. if !s.etm {
  179. s.mac.Write(data)
  180. }
  181. s.macResult = s.mac.Sum(s.macResult[:0])
  182. if subtle.ConstantTimeCompare(s.macResult, mac) != 1 {
  183. return nil, errors.New("ssh: MAC failure")
  184. }
  185. }
  186. return s.packetData[:length-paddingLength-1], nil
  187. }
  188. // writeCipherPacket encrypts and sends a packet of data to the writer argument
  189. func (s *streamPacketCipher) writeCipherPacket(seqNum uint32, w io.Writer, rand io.Reader, packet []byte) error {
  190. if len(packet) > maxPacket {
  191. return errors.New("ssh: packet too large")
  192. }
  193. aadlen := 0
  194. if s.mac != nil && s.etm {
  195. // packet length is not encrypted for EtM modes
  196. aadlen = 4
  197. }
  198. paddingLength := packetSizeMultiple - (prefixLen+len(packet)-aadlen)%packetSizeMultiple
  199. if paddingLength < 4 {
  200. paddingLength += packetSizeMultiple
  201. }
  202. length := len(packet) + 1 + paddingLength
  203. binary.BigEndian.PutUint32(s.prefix[:], uint32(length))
  204. s.prefix[4] = byte(paddingLength)
  205. padding := s.padding[:paddingLength]
  206. if _, err := io.ReadFull(rand, padding); err != nil {
  207. return err
  208. }
  209. if s.mac != nil {
  210. s.mac.Reset()
  211. binary.BigEndian.PutUint32(s.seqNumBytes[:], seqNum)
  212. s.mac.Write(s.seqNumBytes[:])
  213. if s.etm {
  214. // For EtM algorithms, the packet length must stay unencrypted,
  215. // but the following data (padding length) must be encrypted
  216. s.cipher.XORKeyStream(s.prefix[4:5], s.prefix[4:5])
  217. }
  218. s.mac.Write(s.prefix[:])
  219. if !s.etm {
  220. // For non-EtM algorithms, the algorithm is applied on unencrypted data
  221. s.mac.Write(packet)
  222. s.mac.Write(padding)
  223. }
  224. }
  225. if !(s.mac != nil && s.etm) {
  226. // For EtM algorithms, the padding length has already been encrypted
  227. // and the packet length must remain unencrypted
  228. s.cipher.XORKeyStream(s.prefix[:], s.prefix[:])
  229. }
  230. s.cipher.XORKeyStream(packet, packet)
  231. s.cipher.XORKeyStream(padding, padding)
  232. if s.mac != nil && s.etm {
  233. // For EtM algorithms, packet and padding must be encrypted
  234. s.mac.Write(packet)
  235. s.mac.Write(padding)
  236. }
  237. if _, err := w.Write(s.prefix[:]); err != nil {
  238. return err
  239. }
  240. if _, err := w.Write(packet); err != nil {
  241. return err
  242. }
  243. if _, err := w.Write(padding); err != nil {
  244. return err
  245. }
  246. if s.mac != nil {
  247. s.macResult = s.mac.Sum(s.macResult[:0])
  248. if _, err := w.Write(s.macResult); err != nil {
  249. return err
  250. }
  251. }
  252. return nil
  253. }
  254. type gcmCipher struct {
  255. aead cipher.AEAD
  256. prefix [4]byte
  257. iv []byte
  258. buf []byte
  259. }
  260. func newGCMCipher(key, iv, unusedMacKey []byte, unusedAlgs directionAlgorithms) (packetCipher, error) {
  261. c, err := aes.NewCipher(key)
  262. if err != nil {
  263. return nil, err
  264. }
  265. aead, err := cipher.NewGCM(c)
  266. if err != nil {
  267. return nil, err
  268. }
  269. return &gcmCipher{
  270. aead: aead,
  271. iv: iv,
  272. }, nil
  273. }
  274. const gcmTagSize = 16
  275. func (c *gcmCipher) writeCipherPacket(seqNum uint32, w io.Writer, rand io.Reader, packet []byte) error {
  276. // Pad out to multiple of 16 bytes. This is different from the
  277. // stream cipher because that encrypts the length too.
  278. padding := byte(packetSizeMultiple - (1+len(packet))%packetSizeMultiple)
  279. if padding < 4 {
  280. padding += packetSizeMultiple
  281. }
  282. length := uint32(len(packet) + int(padding) + 1)
  283. binary.BigEndian.PutUint32(c.prefix[:], length)
  284. if _, err := w.Write(c.prefix[:]); err != nil {
  285. return err
  286. }
  287. if cap(c.buf) < int(length) {
  288. c.buf = make([]byte, length)
  289. } else {
  290. c.buf = c.buf[:length]
  291. }
  292. c.buf[0] = padding
  293. copy(c.buf[1:], packet)
  294. if _, err := io.ReadFull(rand, c.buf[1+len(packet):]); err != nil {
  295. return err
  296. }
  297. c.buf = c.aead.Seal(c.buf[:0], c.iv, c.buf, c.prefix[:])
  298. if _, err := w.Write(c.buf); err != nil {
  299. return err
  300. }
  301. c.incIV()
  302. return nil
  303. }
  304. func (c *gcmCipher) incIV() {
  305. for i := 4 + 7; i >= 4; i-- {
  306. c.iv[i]++
  307. if c.iv[i] != 0 {
  308. break
  309. }
  310. }
  311. }
  312. func (c *gcmCipher) readCipherPacket(seqNum uint32, r io.Reader) ([]byte, error) {
  313. if _, err := io.ReadFull(r, c.prefix[:]); err != nil {
  314. return nil, err
  315. }
  316. length := binary.BigEndian.Uint32(c.prefix[:])
  317. if length > maxPacket {
  318. return nil, errors.New("ssh: max packet length exceeded")
  319. }
  320. if cap(c.buf) < int(length+gcmTagSize) {
  321. c.buf = make([]byte, length+gcmTagSize)
  322. } else {
  323. c.buf = c.buf[:length+gcmTagSize]
  324. }
  325. if _, err := io.ReadFull(r, c.buf); err != nil {
  326. return nil, err
  327. }
  328. plain, err := c.aead.Open(c.buf[:0], c.iv, c.buf, c.prefix[:])
  329. if err != nil {
  330. return nil, err
  331. }
  332. c.incIV()
  333. padding := plain[0]
  334. if padding < 4 {
  335. // padding is a byte, so it automatically satisfies
  336. // the maximum size, which is 255.
  337. return nil, fmt.Errorf("ssh: illegal padding %d", padding)
  338. }
  339. if int(padding+1) >= len(plain) {
  340. return nil, fmt.Errorf("ssh: padding %d too large", padding)
  341. }
  342. plain = plain[1 : length-uint32(padding)]
  343. return plain, nil
  344. }
  345. // cbcCipher implements aes128-cbc cipher defined in RFC 4253 section 6.1
  346. type cbcCipher struct {
  347. mac hash.Hash
  348. macSize uint32
  349. decrypter cipher.BlockMode
  350. encrypter cipher.BlockMode
  351. // The following members are to avoid per-packet allocations.
  352. seqNumBytes [4]byte
  353. packetData []byte
  354. macResult []byte
  355. // Amount of data we should still read to hide which
  356. // verification error triggered.
  357. oracleCamouflage uint32
  358. }
  359. func newCBCCipher(c cipher.Block, key, iv, macKey []byte, algs directionAlgorithms) (packetCipher, error) {
  360. cbc := &cbcCipher{
  361. mac: macModes[algs.MAC].new(macKey),
  362. decrypter: cipher.NewCBCDecrypter(c, iv),
  363. encrypter: cipher.NewCBCEncrypter(c, iv),
  364. packetData: make([]byte, 1024),
  365. }
  366. if cbc.mac != nil {
  367. cbc.macSize = uint32(cbc.mac.Size())
  368. }
  369. return cbc, nil
  370. }
  371. func newAESCBCCipher(key, iv, macKey []byte, algs directionAlgorithms) (packetCipher, error) {
  372. c, err := aes.NewCipher(key)
  373. if err != nil {
  374. return nil, err
  375. }
  376. cbc, err := newCBCCipher(c, key, iv, macKey, algs)
  377. if err != nil {
  378. return nil, err
  379. }
  380. return cbc, nil
  381. }
  382. func newTripleDESCBCCipher(key, iv, macKey []byte, algs directionAlgorithms) (packetCipher, error) {
  383. c, err := des.NewTripleDESCipher(key)
  384. if err != nil {
  385. return nil, err
  386. }
  387. cbc, err := newCBCCipher(c, key, iv, macKey, algs)
  388. if err != nil {
  389. return nil, err
  390. }
  391. return cbc, nil
  392. }
  393. func maxUInt32(a, b int) uint32 {
  394. if a > b {
  395. return uint32(a)
  396. }
  397. return uint32(b)
  398. }
  399. const (
  400. cbcMinPacketSizeMultiple = 8
  401. cbcMinPacketSize = 16
  402. cbcMinPaddingSize = 4
  403. )
  404. // cbcError represents a verification error that may leak information.
  405. type cbcError string
  406. func (e cbcError) Error() string { return string(e) }
  407. func (c *cbcCipher) readCipherPacket(seqNum uint32, r io.Reader) ([]byte, error) {
  408. p, err := c.readCipherPacketLeaky(seqNum, r)
  409. if err != nil {
  410. if _, ok := err.(cbcError); ok {
  411. // Verification error: read a fixed amount of
  412. // data, to make distinguishing between
  413. // failing MAC and failing length check more
  414. // difficult.
  415. io.CopyN(ioutil.Discard, r, int64(c.oracleCamouflage))
  416. }
  417. }
  418. return p, err
  419. }
  420. func (c *cbcCipher) readCipherPacketLeaky(seqNum uint32, r io.Reader) ([]byte, error) {
  421. blockSize := c.decrypter.BlockSize()
  422. // Read the header, which will include some of the subsequent data in the
  423. // case of block ciphers - this is copied back to the payload later.
  424. // How many bytes of payload/padding will be read with this first read.
  425. firstBlockLength := uint32((prefixLen + blockSize - 1) / blockSize * blockSize)
  426. firstBlock := c.packetData[:firstBlockLength]
  427. if _, err := io.ReadFull(r, firstBlock); err != nil {
  428. return nil, err
  429. }
  430. c.oracleCamouflage = maxPacket + 4 + c.macSize - firstBlockLength
  431. c.decrypter.CryptBlocks(firstBlock, firstBlock)
  432. length := binary.BigEndian.Uint32(firstBlock[:4])
  433. if length > maxPacket {
  434. return nil, cbcError("ssh: packet too large")
  435. }
  436. if length+4 < maxUInt32(cbcMinPacketSize, blockSize) {
  437. // The minimum size of a packet is 16 (or the cipher block size, whichever
  438. // is larger) bytes.
  439. return nil, cbcError("ssh: packet too small")
  440. }
  441. // The length of the packet (including the length field but not the MAC) must
  442. // be a multiple of the block size or 8, whichever is larger.
  443. if (length+4)%maxUInt32(cbcMinPacketSizeMultiple, blockSize) != 0 {
  444. return nil, cbcError("ssh: invalid packet length multiple")
  445. }
  446. paddingLength := uint32(firstBlock[4])
  447. if paddingLength < cbcMinPaddingSize || length <= paddingLength+1 {
  448. return nil, cbcError("ssh: invalid packet length")
  449. }
  450. // Positions within the c.packetData buffer:
  451. macStart := 4 + length
  452. paddingStart := macStart - paddingLength
  453. // Entire packet size, starting before length, ending at end of mac.
  454. entirePacketSize := macStart + c.macSize
  455. // Ensure c.packetData is large enough for the entire packet data.
  456. if uint32(cap(c.packetData)) < entirePacketSize {
  457. // Still need to upsize and copy, but this should be rare at runtime, only
  458. // on upsizing the packetData buffer.
  459. c.packetData = make([]byte, entirePacketSize)
  460. copy(c.packetData, firstBlock)
  461. } else {
  462. c.packetData = c.packetData[:entirePacketSize]
  463. }
  464. n, err := io.ReadFull(r, c.packetData[firstBlockLength:])
  465. if err != nil {
  466. return nil, err
  467. }
  468. c.oracleCamouflage -= uint32(n)
  469. remainingCrypted := c.packetData[firstBlockLength:macStart]
  470. c.decrypter.CryptBlocks(remainingCrypted, remainingCrypted)
  471. mac := c.packetData[macStart:]
  472. if c.mac != nil {
  473. c.mac.Reset()
  474. binary.BigEndian.PutUint32(c.seqNumBytes[:], seqNum)
  475. c.mac.Write(c.seqNumBytes[:])
  476. c.mac.Write(c.packetData[:macStart])
  477. c.macResult = c.mac.Sum(c.macResult[:0])
  478. if subtle.ConstantTimeCompare(c.macResult, mac) != 1 {
  479. return nil, cbcError("ssh: MAC failure")
  480. }
  481. }
  482. return c.packetData[prefixLen:paddingStart], nil
  483. }
  484. func (c *cbcCipher) writeCipherPacket(seqNum uint32, w io.Writer, rand io.Reader, packet []byte) error {
  485. effectiveBlockSize := maxUInt32(cbcMinPacketSizeMultiple, c.encrypter.BlockSize())
  486. // Length of encrypted portion of the packet (header, payload, padding).
  487. // Enforce minimum padding and packet size.
  488. encLength := maxUInt32(prefixLen+len(packet)+cbcMinPaddingSize, cbcMinPaddingSize)
  489. // Enforce block size.
  490. encLength = (encLength + effectiveBlockSize - 1) / effectiveBlockSize * effectiveBlockSize
  491. length := encLength - 4
  492. paddingLength := int(length) - (1 + len(packet))
  493. // Overall buffer contains: header, payload, padding, mac.
  494. // Space for the MAC is reserved in the capacity but not the slice length.
  495. bufferSize := encLength + c.macSize
  496. if uint32(cap(c.packetData)) < bufferSize {
  497. c.packetData = make([]byte, encLength, bufferSize)
  498. } else {
  499. c.packetData = c.packetData[:encLength]
  500. }
  501. p := c.packetData
  502. // Packet header.
  503. binary.BigEndian.PutUint32(p, length)
  504. p = p[4:]
  505. p[0] = byte(paddingLength)
  506. // Payload.
  507. p = p[1:]
  508. copy(p, packet)
  509. // Padding.
  510. p = p[len(packet):]
  511. if _, err := io.ReadFull(rand, p); err != nil {
  512. return err
  513. }
  514. if c.mac != nil {
  515. c.mac.Reset()
  516. binary.BigEndian.PutUint32(c.seqNumBytes[:], seqNum)
  517. c.mac.Write(c.seqNumBytes[:])
  518. c.mac.Write(c.packetData)
  519. // The MAC is now appended into the capacity reserved for it earlier.
  520. c.packetData = c.mac.Sum(c.packetData)
  521. }
  522. c.encrypter.CryptBlocks(c.packetData[:encLength], c.packetData[:encLength])
  523. if _, err := w.Write(c.packetData); err != nil {
  524. return err
  525. }
  526. return nil
  527. }
  528. const chacha20Poly1305ID = "chacha20-poly1305@openssh.com"
  529. // chacha20Poly1305Cipher implements the chacha20-poly1305@openssh.com
  530. // AEAD, which is described here:
  531. //
  532. // https://tools.ietf.org/html/draft-josefsson-ssh-chacha20-poly1305-openssh-00
  533. //
  534. // the methods here also implement padding, which RFC4253 Section 6
  535. // also requires of stream ciphers.
  536. type chacha20Poly1305Cipher struct {
  537. lengthKey [8]uint32
  538. contentKey [8]uint32
  539. buf []byte
  540. }
  541. func newChaCha20Cipher(key, unusedIV, unusedMACKey []byte, unusedAlgs directionAlgorithms) (packetCipher, error) {
  542. if len(key) != 64 {
  543. panic(len(key))
  544. }
  545. c := &chacha20Poly1305Cipher{
  546. buf: make([]byte, 256),
  547. }
  548. for i := range c.contentKey {
  549. c.contentKey[i] = binary.LittleEndian.Uint32(key[i*4 : (i+1)*4])
  550. }
  551. for i := range c.lengthKey {
  552. c.lengthKey[i] = binary.LittleEndian.Uint32(key[(i+8)*4 : (i+9)*4])
  553. }
  554. return c, nil
  555. }
  556. func (c *chacha20Poly1305Cipher) readCipherPacket(seqNum uint32, r io.Reader) ([]byte, error) {
  557. nonce := [3]uint32{0, 0, bits.ReverseBytes32(seqNum)}
  558. s := chacha20.New(c.contentKey, nonce)
  559. var polyKey [32]byte
  560. s.XORKeyStream(polyKey[:], polyKey[:])
  561. s.Advance() // skip next 32 bytes
  562. encryptedLength := c.buf[:4]
  563. if _, err := io.ReadFull(r, encryptedLength); err != nil {
  564. return nil, err
  565. }
  566. var lenBytes [4]byte
  567. chacha20.New(c.lengthKey, nonce).XORKeyStream(lenBytes[:], encryptedLength)
  568. length := binary.BigEndian.Uint32(lenBytes[:])
  569. if length > maxPacket {
  570. return nil, errors.New("ssh: invalid packet length, packet too large")
  571. }
  572. contentEnd := 4 + length
  573. packetEnd := contentEnd + poly1305.TagSize
  574. if uint32(cap(c.buf)) < packetEnd {
  575. c.buf = make([]byte, packetEnd)
  576. copy(c.buf[:], encryptedLength)
  577. } else {
  578. c.buf = c.buf[:packetEnd]
  579. }
  580. if _, err := io.ReadFull(r, c.buf[4:packetEnd]); err != nil {
  581. return nil, err
  582. }
  583. var mac [poly1305.TagSize]byte
  584. copy(mac[:], c.buf[contentEnd:packetEnd])
  585. if !poly1305.Verify(&mac, c.buf[:contentEnd], &polyKey) {
  586. return nil, errors.New("ssh: MAC failure")
  587. }
  588. plain := c.buf[4:contentEnd]
  589. s.XORKeyStream(plain, plain)
  590. padding := plain[0]
  591. if padding < 4 {
  592. // padding is a byte, so it automatically satisfies
  593. // the maximum size, which is 255.
  594. return nil, fmt.Errorf("ssh: illegal padding %d", padding)
  595. }
  596. if int(padding)+1 >= len(plain) {
  597. return nil, fmt.Errorf("ssh: padding %d too large", padding)
  598. }
  599. plain = plain[1 : len(plain)-int(padding)]
  600. return plain, nil
  601. }
  602. func (c *chacha20Poly1305Cipher) writeCipherPacket(seqNum uint32, w io.Writer, rand io.Reader, payload []byte) error {
  603. nonce := [3]uint32{0, 0, bits.ReverseBytes32(seqNum)}
  604. s := chacha20.New(c.contentKey, nonce)
  605. var polyKey [32]byte
  606. s.XORKeyStream(polyKey[:], polyKey[:])
  607. s.Advance() // skip next 32 bytes
  608. // There is no blocksize, so fall back to multiple of 8 byte
  609. // padding, as described in RFC 4253, Sec 6.
  610. const packetSizeMultiple = 8
  611. padding := packetSizeMultiple - (1+len(payload))%packetSizeMultiple
  612. if padding < 4 {
  613. padding += packetSizeMultiple
  614. }
  615. // size (4 bytes), padding (1), payload, padding, tag.
  616. totalLength := 4 + 1 + len(payload) + padding + poly1305.TagSize
  617. if cap(c.buf) < totalLength {
  618. c.buf = make([]byte, totalLength)
  619. } else {
  620. c.buf = c.buf[:totalLength]
  621. }
  622. binary.BigEndian.PutUint32(c.buf, uint32(1+len(payload)+padding))
  623. chacha20.New(c.lengthKey, nonce).XORKeyStream(c.buf, c.buf[:4])
  624. c.buf[4] = byte(padding)
  625. copy(c.buf[5:], payload)
  626. packetEnd := 5 + len(payload) + padding
  627. if _, err := io.ReadFull(rand, c.buf[5+len(payload):packetEnd]); err != nil {
  628. return err
  629. }
  630. s.XORKeyStream(c.buf[4:], c.buf[4:packetEnd])
  631. var mac [poly1305.TagSize]byte
  632. poly1305.Sum(&mac, c.buf[:packetEnd], &polyKey)
  633. copy(c.buf[packetEnd:], mac[:])
  634. if _, err := w.Write(c.buf); err != nil {
  635. return err
  636. }
  637. return nil
  638. }
上海开阖软件有限公司 沪ICP备12045867号-1