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
  5package ssh
  6
  7import (
  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
 25const (
 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.
 42type noneCipher struct{}
 43
 44func (c noneCipher) XORKeyStream(dst, src []byte) {
 45	copy(dst, src)
 46}
 47
 48func 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
 56func newRC4(key, iv []byte) (cipher.Stream, error) {
 57	return rc4.NewCipher(key)
 58}
 59
 60type cipherMode struct {
 61	keySize int
 62	ivSize  int
 63	create  func(key, iv []byte, macKey []byte, algs DirectionAlgorithms) (packetCipher, error)
 64}
 65
 66func 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.
100var cipherModes = map[string]*cipherMode{}
101
102func 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.
137const prefixLen = 5
138
139// streamPacketCipher is a packetCipher using a stream cipher.
140type 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.
154func (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
226func (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
305type gcmCipher struct {
306	aead   cipher.AEAD
307	prefix [4]byte
308	iv     []byte
309	buf    []byte
310}
311
312func 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
329const gcmTagSize = 16
330
331func (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
365func (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
374func (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
418type 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
434func 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
448func 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
462func 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
476func maxUInt32(a, b int) uint32 {
477	if a > b {
478		return uint32(a)
479	}
480	return uint32(b)
481}
482
483const (
484	cbcMinPacketSizeMultiple = 8
485	cbcMinPacketSize         = 16
486	cbcMinPaddingSize        = 4
487)
488
489// cbcError represents a verification error that may leak information.
490type cbcError string
491
492func (e cbcError) Error() string { return string(e) }
493
494func (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
508func (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
584func (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, cbcMinPacketSize)
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.
647type chacha20Poly1305Cipher struct {
648	lengthKey  [32]byte
649	contentKey [32]byte
650	buf        []byte
651}
652
653func 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
667func (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
737func (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}