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