github.com/glycerine/xcryptossh@v7.0.4+incompatible/cipher.go (about)

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