cipher.go raw

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