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