github.com/psiphon-labs/psiphon-tunnel-core@v2.0.28+incompatible/psiphon/common/crypto/ssh/cipher.go (about)

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