gtsocial-umbx

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

cipher.go (21758B)


      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 
     19 	"golang.org/x/crypto/chacha20"
     20 	"golang.org/x/crypto/internal/poly1305"
     21 )
     22 
     23 const (
     24 	packetSizeMultiple = 16 // TODO(huin) this should be determined by the cipher.
     25 
     26 	// RFC 4253 section 6.1 defines a minimum packet size of 32768 that implementations
     27 	// MUST be able to process (plus a few more kilobytes for padding and mac). The RFC
     28 	// indicates implementations SHOULD be able to handle larger packet sizes, but then
     29 	// waffles on about reasonable limits.
     30 	//
     31 	// OpenSSH caps their maxPacket at 256kB so we choose to do
     32 	// the same. maxPacket is also used to ensure that uint32
     33 	// length fields do not overflow, so it should remain well
     34 	// below 4G.
     35 	maxPacket = 256 * 1024
     36 )
     37 
     38 // noneCipher implements cipher.Stream and provides no encryption. It is used
     39 // by the transport before the first key-exchange.
     40 type noneCipher struct{}
     41 
     42 func (c noneCipher) XORKeyStream(dst, src []byte) {
     43 	copy(dst, src)
     44 }
     45 
     46 func newAESCTR(key, iv []byte) (cipher.Stream, error) {
     47 	c, err := aes.NewCipher(key)
     48 	if err != nil {
     49 		return nil, err
     50 	}
     51 	return cipher.NewCTR(c, iv), nil
     52 }
     53 
     54 func newRC4(key, iv []byte) (cipher.Stream, error) {
     55 	return rc4.NewCipher(key)
     56 }
     57 
     58 type cipherMode struct {
     59 	keySize int
     60 	ivSize  int
     61 	create  func(key, iv []byte, macKey []byte, algs directionAlgorithms) (packetCipher, error)
     62 }
     63 
     64 func streamCipherMode(skip int, createFunc func(key, iv []byte) (cipher.Stream, error)) func(key, iv []byte, macKey []byte, algs directionAlgorithms) (packetCipher, error) {
     65 	return func(key, iv, macKey []byte, algs directionAlgorithms) (packetCipher, error) {
     66 		stream, err := createFunc(key, iv)
     67 		if err != nil {
     68 			return nil, err
     69 		}
     70 
     71 		var streamDump []byte
     72 		if skip > 0 {
     73 			streamDump = make([]byte, 512)
     74 		}
     75 
     76 		for remainingToDump := skip; remainingToDump > 0; {
     77 			dumpThisTime := remainingToDump
     78 			if dumpThisTime > len(streamDump) {
     79 				dumpThisTime = len(streamDump)
     80 			}
     81 			stream.XORKeyStream(streamDump[:dumpThisTime], streamDump[:dumpThisTime])
     82 			remainingToDump -= dumpThisTime
     83 		}
     84 
     85 		mac := macModes[algs.MAC].new(macKey)
     86 		return &streamPacketCipher{
     87 			mac:       mac,
     88 			etm:       macModes[algs.MAC].etm,
     89 			macResult: make([]byte, mac.Size()),
     90 			cipher:    stream,
     91 		}, nil
     92 	}
     93 }
     94 
     95 // cipherModes documents properties of supported ciphers. Ciphers not included
     96 // are not supported and will not be negotiated, even if explicitly requested in
     97 // ClientConfig.Crypto.Ciphers.
     98 var cipherModes = map[string]*cipherMode{
     99 	// Ciphers from RFC 4344, which introduced many CTR-based ciphers. Algorithms
    100 	// are defined in the order specified in the RFC.
    101 	"aes128-ctr": {16, aes.BlockSize, streamCipherMode(0, newAESCTR)},
    102 	"aes192-ctr": {24, aes.BlockSize, streamCipherMode(0, newAESCTR)},
    103 	"aes256-ctr": {32, aes.BlockSize, streamCipherMode(0, newAESCTR)},
    104 
    105 	// Ciphers from RFC 4345, which introduces security-improved arcfour ciphers.
    106 	// They are defined in the order specified in the RFC.
    107 	"arcfour128": {16, 0, streamCipherMode(1536, newRC4)},
    108 	"arcfour256": {32, 0, streamCipherMode(1536, newRC4)},
    109 
    110 	// Cipher defined in RFC 4253, which describes SSH Transport Layer Protocol.
    111 	// Note that this cipher is not safe, as stated in RFC 4253: "Arcfour (and
    112 	// RC4) has problems with weak keys, and should be used with caution."
    113 	// RFC 4345 introduces improved versions of Arcfour.
    114 	"arcfour": {16, 0, streamCipherMode(0, newRC4)},
    115 
    116 	// AEAD ciphers
    117 	gcm128CipherID:     {16, 12, newGCMCipher},
    118 	gcm256CipherID:     {32, 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(io.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 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 }