github.com/ncw/rclone@v1.48.1-0.20190724201158-a35aa1360e3e/backend/crypt/cipher.go (about)

     1  package crypt
     2  
     3  import (
     4  	"bytes"
     5  	"context"
     6  	"crypto/aes"
     7  	gocipher "crypto/cipher"
     8  	"crypto/rand"
     9  	"encoding/base32"
    10  	"fmt"
    11  	"io"
    12  	"strconv"
    13  	"strings"
    14  	"sync"
    15  	"unicode/utf8"
    16  
    17  	"github.com/ncw/rclone/backend/crypt/pkcs7"
    18  	"github.com/ncw/rclone/fs"
    19  	"github.com/ncw/rclone/fs/accounting"
    20  	"github.com/pkg/errors"
    21  	"github.com/rfjakob/eme"
    22  	"golang.org/x/crypto/nacl/secretbox"
    23  	"golang.org/x/crypto/scrypt"
    24  )
    25  
    26  // Constants
    27  const (
    28  	nameCipherBlockSize = aes.BlockSize
    29  	fileMagic           = "RCLONE\x00\x00"
    30  	fileMagicSize       = len(fileMagic)
    31  	fileNonceSize       = 24
    32  	fileHeaderSize      = fileMagicSize + fileNonceSize
    33  	blockHeaderSize     = secretbox.Overhead
    34  	blockDataSize       = 64 * 1024
    35  	blockSize           = blockHeaderSize + blockDataSize
    36  	encryptedSuffix     = ".bin" // when file name encryption is off we add this suffix to make sure the cloud provider doesn't process the file
    37  )
    38  
    39  // Errors returned by cipher
    40  var (
    41  	ErrorBadDecryptUTF8          = errors.New("bad decryption - utf-8 invalid")
    42  	ErrorBadDecryptControlChar   = errors.New("bad decryption - contains control chars")
    43  	ErrorNotAMultipleOfBlocksize = errors.New("not a multiple of blocksize")
    44  	ErrorTooShortAfterDecode     = errors.New("too short after base32 decode")
    45  	ErrorTooLongAfterDecode      = errors.New("too long after base32 decode")
    46  	ErrorEncryptedFileTooShort   = errors.New("file is too short to be encrypted")
    47  	ErrorEncryptedFileBadHeader  = errors.New("file has truncated block header")
    48  	ErrorEncryptedBadMagic       = errors.New("not an encrypted file - bad magic string")
    49  	ErrorEncryptedBadBlock       = errors.New("failed to authenticate decrypted block - bad password?")
    50  	ErrorBadBase32Encoding       = errors.New("bad base32 filename encoding")
    51  	ErrorFileClosed              = errors.New("file already closed")
    52  	ErrorNotAnEncryptedFile      = errors.New("not an encrypted file - no \"" + encryptedSuffix + "\" suffix")
    53  	ErrorBadSeek                 = errors.New("Seek beyond end of file")
    54  	defaultSalt                  = []byte{0xA8, 0x0D, 0xF4, 0x3A, 0x8F, 0xBD, 0x03, 0x08, 0xA7, 0xCA, 0xB8, 0x3E, 0x58, 0x1F, 0x86, 0xB1}
    55  	obfuscQuoteRune              = '!'
    56  )
    57  
    58  // Global variables
    59  var (
    60  	fileMagicBytes = []byte(fileMagic)
    61  )
    62  
    63  // ReadSeekCloser is the interface of the read handles
    64  type ReadSeekCloser interface {
    65  	io.Reader
    66  	io.Seeker
    67  	io.Closer
    68  	fs.RangeSeeker
    69  }
    70  
    71  // OpenRangeSeek opens the file handle at the offset with the limit given
    72  type OpenRangeSeek func(ctx context.Context, offset, limit int64) (io.ReadCloser, error)
    73  
    74  // Cipher is used to swap out the encryption implementations
    75  type Cipher interface {
    76  	// EncryptFileName encrypts a file path
    77  	EncryptFileName(string) string
    78  	// DecryptFileName decrypts a file path, returns error if decrypt was invalid
    79  	DecryptFileName(string) (string, error)
    80  	// EncryptDirName encrypts a directory path
    81  	EncryptDirName(string) string
    82  	// DecryptDirName decrypts a directory path, returns error if decrypt was invalid
    83  	DecryptDirName(string) (string, error)
    84  	// EncryptData
    85  	EncryptData(io.Reader) (io.Reader, error)
    86  	// DecryptData
    87  	DecryptData(io.ReadCloser) (io.ReadCloser, error)
    88  	// DecryptDataSeek decrypt at a given position
    89  	DecryptDataSeek(ctx context.Context, open OpenRangeSeek, offset, limit int64) (ReadSeekCloser, error)
    90  	// EncryptedSize calculates the size of the data when encrypted
    91  	EncryptedSize(int64) int64
    92  	// DecryptedSize calculates the size of the data when decrypted
    93  	DecryptedSize(int64) (int64, error)
    94  	// NameEncryptionMode returns the used mode for name handling
    95  	NameEncryptionMode() NameEncryptionMode
    96  }
    97  
    98  // NameEncryptionMode is the type of file name encryption in use
    99  type NameEncryptionMode int
   100  
   101  // NameEncryptionMode levels
   102  const (
   103  	NameEncryptionOff NameEncryptionMode = iota
   104  	NameEncryptionStandard
   105  	NameEncryptionObfuscated
   106  )
   107  
   108  // NewNameEncryptionMode turns a string into a NameEncryptionMode
   109  func NewNameEncryptionMode(s string) (mode NameEncryptionMode, err error) {
   110  	s = strings.ToLower(s)
   111  	switch s {
   112  	case "off":
   113  		mode = NameEncryptionOff
   114  	case "standard":
   115  		mode = NameEncryptionStandard
   116  	case "obfuscate":
   117  		mode = NameEncryptionObfuscated
   118  	default:
   119  		err = errors.Errorf("Unknown file name encryption mode %q", s)
   120  	}
   121  	return mode, err
   122  }
   123  
   124  // String turns mode into a human readable string
   125  func (mode NameEncryptionMode) String() (out string) {
   126  	switch mode {
   127  	case NameEncryptionOff:
   128  		out = "off"
   129  	case NameEncryptionStandard:
   130  		out = "standard"
   131  	case NameEncryptionObfuscated:
   132  		out = "obfuscate"
   133  	default:
   134  		out = fmt.Sprintf("Unknown mode #%d", mode)
   135  	}
   136  	return out
   137  }
   138  
   139  type cipher struct {
   140  	dataKey        [32]byte                  // Key for secretbox
   141  	nameKey        [32]byte                  // 16,24 or 32 bytes
   142  	nameTweak      [nameCipherBlockSize]byte // used to tweak the name crypto
   143  	block          gocipher.Block
   144  	mode           NameEncryptionMode
   145  	buffers        sync.Pool // encrypt/decrypt buffers
   146  	cryptoRand     io.Reader // read crypto random numbers from here
   147  	dirNameEncrypt bool
   148  }
   149  
   150  // newCipher initialises the cipher.  If salt is "" then it uses a built in salt val
   151  func newCipher(mode NameEncryptionMode, password, salt string, dirNameEncrypt bool) (*cipher, error) {
   152  	c := &cipher{
   153  		mode:           mode,
   154  		cryptoRand:     rand.Reader,
   155  		dirNameEncrypt: dirNameEncrypt,
   156  	}
   157  	c.buffers.New = func() interface{} {
   158  		return make([]byte, blockSize)
   159  	}
   160  	err := c.Key(password, salt)
   161  	if err != nil {
   162  		return nil, err
   163  	}
   164  	return c, nil
   165  }
   166  
   167  // Key creates all the internal keys from the password passed in using
   168  // scrypt.
   169  //
   170  // If salt is "" we use a fixed salt just to make attackers lives
   171  // slighty harder than using no salt.
   172  //
   173  // Note that empty passsword makes all 0x00 keys which is used in the
   174  // tests.
   175  func (c *cipher) Key(password, salt string) (err error) {
   176  	const keySize = len(c.dataKey) + len(c.nameKey) + len(c.nameTweak)
   177  	var saltBytes = defaultSalt
   178  	if salt != "" {
   179  		saltBytes = []byte(salt)
   180  	}
   181  	var key []byte
   182  	if password == "" {
   183  		key = make([]byte, keySize)
   184  	} else {
   185  		key, err = scrypt.Key([]byte(password), saltBytes, 16384, 8, 1, keySize)
   186  		if err != nil {
   187  			return err
   188  		}
   189  	}
   190  	copy(c.dataKey[:], key)
   191  	copy(c.nameKey[:], key[len(c.dataKey):])
   192  	copy(c.nameTweak[:], key[len(c.dataKey)+len(c.nameKey):])
   193  	// Key the name cipher
   194  	c.block, err = aes.NewCipher(c.nameKey[:])
   195  	return err
   196  }
   197  
   198  // getBlock gets a block from the pool of size blockSize
   199  func (c *cipher) getBlock() []byte {
   200  	return c.buffers.Get().([]byte)
   201  }
   202  
   203  // putBlock returns a block to the pool of size blockSize
   204  func (c *cipher) putBlock(buf []byte) {
   205  	if len(buf) != blockSize {
   206  		panic("bad blocksize returned to pool")
   207  	}
   208  	c.buffers.Put(buf)
   209  }
   210  
   211  // check to see if the byte string is valid with no control characters
   212  // from 0x00 to 0x1F and is a valid UTF-8 string
   213  func checkValidString(buf []byte) error {
   214  	for i := range buf {
   215  		c := buf[i]
   216  		if c >= 0x00 && c < 0x20 || c == 0x7F {
   217  			return ErrorBadDecryptControlChar
   218  		}
   219  	}
   220  	if !utf8.Valid(buf) {
   221  		return ErrorBadDecryptUTF8
   222  	}
   223  	return nil
   224  }
   225  
   226  // encodeFileName encodes a filename using a modified version of
   227  // standard base32 as described in RFC4648
   228  //
   229  // The standard encoding is modified in two ways
   230  //  * it becomes lower case (no-one likes upper case filenames!)
   231  //  * we strip the padding character `=`
   232  func encodeFileName(in []byte) string {
   233  	encoded := base32.HexEncoding.EncodeToString(in)
   234  	encoded = strings.TrimRight(encoded, "=")
   235  	return strings.ToLower(encoded)
   236  }
   237  
   238  // decodeFileName decodes a filename as encoded by encodeFileName
   239  func decodeFileName(in string) ([]byte, error) {
   240  	if strings.HasSuffix(in, "=") {
   241  		return nil, ErrorBadBase32Encoding
   242  	}
   243  	// First figure out how many padding characters to add
   244  	roundUpToMultipleOf8 := (len(in) + 7) &^ 7
   245  	equals := roundUpToMultipleOf8 - len(in)
   246  	in = strings.ToUpper(in) + "========"[:equals]
   247  	return base32.HexEncoding.DecodeString(in)
   248  }
   249  
   250  // encryptSegment encrypts a path segment
   251  //
   252  // This uses EME with AES
   253  //
   254  // EME (ECB-Mix-ECB) is a wide-block encryption mode presented in the
   255  // 2003 paper "A Parallelizable Enciphering Mode" by Halevi and
   256  // Rogaway.
   257  //
   258  // This makes for determinstic encryption which is what we want - the
   259  // same filename must encrypt to the same thing.
   260  //
   261  // This means that
   262  //  * filenames with the same name will encrypt the same
   263  //  * filenames which start the same won't have a common prefix
   264  func (c *cipher) encryptSegment(plaintext string) string {
   265  	if plaintext == "" {
   266  		return ""
   267  	}
   268  	paddedPlaintext := pkcs7.Pad(nameCipherBlockSize, []byte(plaintext))
   269  	ciphertext := eme.Transform(c.block, c.nameTweak[:], paddedPlaintext, eme.DirectionEncrypt)
   270  	return encodeFileName(ciphertext)
   271  }
   272  
   273  // decryptSegment decrypts a path segment
   274  func (c *cipher) decryptSegment(ciphertext string) (string, error) {
   275  	if ciphertext == "" {
   276  		return "", nil
   277  	}
   278  	rawCiphertext, err := decodeFileName(ciphertext)
   279  	if err != nil {
   280  		return "", err
   281  	}
   282  	if len(rawCiphertext)%nameCipherBlockSize != 0 {
   283  		return "", ErrorNotAMultipleOfBlocksize
   284  	}
   285  	if len(rawCiphertext) == 0 {
   286  		// not possible if decodeFilename() working correctly
   287  		return "", ErrorTooShortAfterDecode
   288  	}
   289  	if len(rawCiphertext) > 2048 {
   290  		return "", ErrorTooLongAfterDecode
   291  	}
   292  	paddedPlaintext := eme.Transform(c.block, c.nameTweak[:], rawCiphertext, eme.DirectionDecrypt)
   293  	plaintext, err := pkcs7.Unpad(nameCipherBlockSize, paddedPlaintext)
   294  	if err != nil {
   295  		return "", err
   296  	}
   297  	err = checkValidString(plaintext)
   298  	if err != nil {
   299  		return "", err
   300  	}
   301  	return string(plaintext), err
   302  }
   303  
   304  // Simple obfuscation routines
   305  func (c *cipher) obfuscateSegment(plaintext string) string {
   306  	if plaintext == "" {
   307  		return ""
   308  	}
   309  
   310  	// If the string isn't valid UTF8 then don't rotate; just
   311  	// prepend a !.
   312  	if !utf8.ValidString(plaintext) {
   313  		return "!." + plaintext
   314  	}
   315  
   316  	// Calculate a simple rotation based on the filename and
   317  	// the nameKey
   318  	var dir int
   319  	for _, runeValue := range plaintext {
   320  		dir += int(runeValue)
   321  	}
   322  	dir = dir % 256
   323  
   324  	// We'll use this number to store in the result filename...
   325  	var result bytes.Buffer
   326  	_, _ = result.WriteString(strconv.Itoa(dir) + ".")
   327  
   328  	// but we'll augment it with the nameKey for real calculation
   329  	for i := 0; i < len(c.nameKey); i++ {
   330  		dir += int(c.nameKey[i])
   331  	}
   332  
   333  	// Now for each character, depending on the range it is in
   334  	// we will actually rotate a different amount
   335  	for _, runeValue := range plaintext {
   336  		switch {
   337  		case runeValue == obfuscQuoteRune:
   338  			// Quote the Quote character
   339  			_, _ = result.WriteRune(obfuscQuoteRune)
   340  			_, _ = result.WriteRune(obfuscQuoteRune)
   341  
   342  		case runeValue >= '0' && runeValue <= '9':
   343  			// Number
   344  			thisdir := (dir % 9) + 1
   345  			newRune := '0' + (int(runeValue)-'0'+thisdir)%10
   346  			_, _ = result.WriteRune(rune(newRune))
   347  
   348  		case (runeValue >= 'A' && runeValue <= 'Z') ||
   349  			(runeValue >= 'a' && runeValue <= 'z'):
   350  			// ASCII letter.  Try to avoid trivial A->a mappings
   351  			thisdir := dir%25 + 1
   352  			// Calculate the offset of this character in A-Za-z
   353  			pos := int(runeValue - 'A')
   354  			if pos >= 26 {
   355  				pos -= 6 // It's lower case
   356  			}
   357  			// Rotate the character to the new location
   358  			pos = (pos + thisdir) % 52
   359  			if pos >= 26 {
   360  				pos += 6 // and handle lower case offset again
   361  			}
   362  			_, _ = result.WriteRune(rune('A' + pos))
   363  
   364  		case runeValue >= 0xA0 && runeValue <= 0xFF:
   365  			// Latin 1 supplement
   366  			thisdir := (dir % 95) + 1
   367  			newRune := 0xA0 + (int(runeValue)-0xA0+thisdir)%96
   368  			_, _ = result.WriteRune(rune(newRune))
   369  
   370  		case runeValue >= 0x100:
   371  			// Some random Unicode range; we have no good rules here
   372  			thisdir := (dir % 127) + 1
   373  			base := int(runeValue - runeValue%256)
   374  			newRune := rune(base + (int(runeValue)-base+thisdir)%256)
   375  			// If the new character isn't a valid UTF8 char
   376  			// then don't rotate it.  Quote it instead
   377  			if !utf8.ValidRune(newRune) {
   378  				_, _ = result.WriteRune(obfuscQuoteRune)
   379  				_, _ = result.WriteRune(runeValue)
   380  			} else {
   381  				_, _ = result.WriteRune(newRune)
   382  			}
   383  
   384  		default:
   385  			// Leave character untouched
   386  			_, _ = result.WriteRune(runeValue)
   387  		}
   388  	}
   389  	return result.String()
   390  }
   391  
   392  func (c *cipher) deobfuscateSegment(ciphertext string) (string, error) {
   393  	if ciphertext == "" {
   394  		return "", nil
   395  	}
   396  	pos := strings.Index(ciphertext, ".")
   397  	if pos == -1 {
   398  		return "", ErrorNotAnEncryptedFile
   399  	} // No .
   400  	num := ciphertext[:pos]
   401  	if num == "!" {
   402  		// No rotation; probably original was not valid unicode
   403  		return ciphertext[pos+1:], nil
   404  	}
   405  	dir, err := strconv.Atoi(num)
   406  	if err != nil {
   407  		return "", ErrorNotAnEncryptedFile // Not a number
   408  	}
   409  
   410  	// add the nameKey to get the real rotate distance
   411  	for i := 0; i < len(c.nameKey); i++ {
   412  		dir += int(c.nameKey[i])
   413  	}
   414  
   415  	var result bytes.Buffer
   416  
   417  	inQuote := false
   418  	for _, runeValue := range ciphertext[pos+1:] {
   419  		switch {
   420  		case inQuote:
   421  			_, _ = result.WriteRune(runeValue)
   422  			inQuote = false
   423  
   424  		case runeValue == obfuscQuoteRune:
   425  			inQuote = true
   426  
   427  		case runeValue >= '0' && runeValue <= '9':
   428  			// Number
   429  			thisdir := (dir % 9) + 1
   430  			newRune := '0' + int(runeValue) - '0' - thisdir
   431  			if newRune < '0' {
   432  				newRune += 10
   433  			}
   434  			_, _ = result.WriteRune(rune(newRune))
   435  
   436  		case (runeValue >= 'A' && runeValue <= 'Z') ||
   437  			(runeValue >= 'a' && runeValue <= 'z'):
   438  			thisdir := dir%25 + 1
   439  			pos := int(runeValue - 'A')
   440  			if pos >= 26 {
   441  				pos -= 6
   442  			}
   443  			pos = pos - thisdir
   444  			if pos < 0 {
   445  				pos += 52
   446  			}
   447  			if pos >= 26 {
   448  				pos += 6
   449  			}
   450  			_, _ = result.WriteRune(rune('A' + pos))
   451  
   452  		case runeValue >= 0xA0 && runeValue <= 0xFF:
   453  			thisdir := (dir % 95) + 1
   454  			newRune := 0xA0 + int(runeValue) - 0xA0 - thisdir
   455  			if newRune < 0xA0 {
   456  				newRune += 96
   457  			}
   458  			_, _ = result.WriteRune(rune(newRune))
   459  
   460  		case runeValue >= 0x100:
   461  			thisdir := (dir % 127) + 1
   462  			base := int(runeValue - runeValue%256)
   463  			newRune := rune(base + (int(runeValue) - base - thisdir))
   464  			if int(newRune) < base {
   465  				newRune += 256
   466  			}
   467  			_, _ = result.WriteRune(newRune)
   468  
   469  		default:
   470  			_, _ = result.WriteRune(runeValue)
   471  
   472  		}
   473  	}
   474  
   475  	return result.String(), nil
   476  }
   477  
   478  // encryptFileName encrypts a file path
   479  func (c *cipher) encryptFileName(in string) string {
   480  	segments := strings.Split(in, "/")
   481  	for i := range segments {
   482  		// Skip directory name encryption if the user chose to
   483  		// leave them intact
   484  		if !c.dirNameEncrypt && i != (len(segments)-1) {
   485  			continue
   486  		}
   487  		if c.mode == NameEncryptionStandard {
   488  			segments[i] = c.encryptSegment(segments[i])
   489  		} else {
   490  			segments[i] = c.obfuscateSegment(segments[i])
   491  		}
   492  	}
   493  	return strings.Join(segments, "/")
   494  }
   495  
   496  // EncryptFileName encrypts a file path
   497  func (c *cipher) EncryptFileName(in string) string {
   498  	if c.mode == NameEncryptionOff {
   499  		return in + encryptedSuffix
   500  	}
   501  	return c.encryptFileName(in)
   502  }
   503  
   504  // EncryptDirName encrypts a directory path
   505  func (c *cipher) EncryptDirName(in string) string {
   506  	if c.mode == NameEncryptionOff || !c.dirNameEncrypt {
   507  		return in
   508  	}
   509  	return c.encryptFileName(in)
   510  }
   511  
   512  // decryptFileName decrypts a file path
   513  func (c *cipher) decryptFileName(in string) (string, error) {
   514  	segments := strings.Split(in, "/")
   515  	for i := range segments {
   516  		var err error
   517  		// Skip directory name decryption if the user chose to
   518  		// leave them intact
   519  		if !c.dirNameEncrypt && i != (len(segments)-1) {
   520  			continue
   521  		}
   522  		if c.mode == NameEncryptionStandard {
   523  			segments[i], err = c.decryptSegment(segments[i])
   524  		} else {
   525  			segments[i], err = c.deobfuscateSegment(segments[i])
   526  		}
   527  
   528  		if err != nil {
   529  			return "", err
   530  		}
   531  	}
   532  	return strings.Join(segments, "/"), nil
   533  }
   534  
   535  // DecryptFileName decrypts a file path
   536  func (c *cipher) DecryptFileName(in string) (string, error) {
   537  	if c.mode == NameEncryptionOff {
   538  		remainingLength := len(in) - len(encryptedSuffix)
   539  		if remainingLength > 0 && strings.HasSuffix(in, encryptedSuffix) {
   540  			return in[:remainingLength], nil
   541  		}
   542  		return "", ErrorNotAnEncryptedFile
   543  	}
   544  	return c.decryptFileName(in)
   545  }
   546  
   547  // DecryptDirName decrypts a directory path
   548  func (c *cipher) DecryptDirName(in string) (string, error) {
   549  	if c.mode == NameEncryptionOff || !c.dirNameEncrypt {
   550  		return in, nil
   551  	}
   552  	return c.decryptFileName(in)
   553  }
   554  
   555  func (c *cipher) NameEncryptionMode() NameEncryptionMode {
   556  	return c.mode
   557  }
   558  
   559  // nonce is an NACL secretbox nonce
   560  type nonce [fileNonceSize]byte
   561  
   562  // pointer returns the nonce as a *[24]byte for secretbox
   563  func (n *nonce) pointer() *[fileNonceSize]byte {
   564  	return (*[fileNonceSize]byte)(n)
   565  }
   566  
   567  // fromReader fills the nonce from an io.Reader - normally the OSes
   568  // crypto random number generator
   569  func (n *nonce) fromReader(in io.Reader) error {
   570  	read, err := io.ReadFull(in, (*n)[:])
   571  	if read != fileNonceSize {
   572  		return errors.Wrap(err, "short read of nonce")
   573  	}
   574  	return nil
   575  }
   576  
   577  // fromBuf fills the nonce from the buffer passed in
   578  func (n *nonce) fromBuf(buf []byte) {
   579  	read := copy((*n)[:], buf)
   580  	if read != fileNonceSize {
   581  		panic("buffer to short to read nonce")
   582  	}
   583  }
   584  
   585  // carry 1 up the nonce from position i
   586  func (n *nonce) carry(i int) {
   587  	for ; i < len(*n); i++ {
   588  		digit := (*n)[i]
   589  		newDigit := digit + 1
   590  		(*n)[i] = newDigit
   591  		if newDigit >= digit {
   592  			// exit if no carry
   593  			break
   594  		}
   595  	}
   596  }
   597  
   598  // increment to add 1 to the nonce
   599  func (n *nonce) increment() {
   600  	n.carry(0)
   601  }
   602  
   603  // add an uint64 to the nonce
   604  func (n *nonce) add(x uint64) {
   605  	carry := uint16(0)
   606  	for i := 0; i < 8; i++ {
   607  		digit := (*n)[i]
   608  		xDigit := byte(x)
   609  		x >>= 8
   610  		carry += uint16(digit) + uint16(xDigit)
   611  		(*n)[i] = byte(carry)
   612  		carry >>= 8
   613  	}
   614  	if carry != 0 {
   615  		n.carry(8)
   616  	}
   617  }
   618  
   619  // encrypter encrypts an io.Reader on the fly
   620  type encrypter struct {
   621  	mu       sync.Mutex
   622  	in       io.Reader
   623  	c        *cipher
   624  	nonce    nonce
   625  	buf      []byte
   626  	readBuf  []byte
   627  	bufIndex int
   628  	bufSize  int
   629  	err      error
   630  }
   631  
   632  // newEncrypter creates a new file handle encrypting on the fly
   633  func (c *cipher) newEncrypter(in io.Reader, nonce *nonce) (*encrypter, error) {
   634  	fh := &encrypter{
   635  		in:      in,
   636  		c:       c,
   637  		buf:     c.getBlock(),
   638  		readBuf: c.getBlock(),
   639  		bufSize: fileHeaderSize,
   640  	}
   641  	// Initialise nonce
   642  	if nonce != nil {
   643  		fh.nonce = *nonce
   644  	} else {
   645  		err := fh.nonce.fromReader(c.cryptoRand)
   646  		if err != nil {
   647  			return nil, err
   648  		}
   649  	}
   650  	// Copy magic into buffer
   651  	copy(fh.buf, fileMagicBytes)
   652  	// Copy nonce into buffer
   653  	copy(fh.buf[fileMagicSize:], fh.nonce[:])
   654  	return fh, nil
   655  }
   656  
   657  // Read as per io.Reader
   658  func (fh *encrypter) Read(p []byte) (n int, err error) {
   659  	fh.mu.Lock()
   660  	defer fh.mu.Unlock()
   661  
   662  	if fh.err != nil {
   663  		return 0, fh.err
   664  	}
   665  	if fh.bufIndex >= fh.bufSize {
   666  		// Read data
   667  		// FIXME should overlap the reads with a go-routine and 2 buffers?
   668  		readBuf := fh.readBuf[:blockDataSize]
   669  		n, err = io.ReadFull(fh.in, readBuf)
   670  		if n == 0 {
   671  			// err can't be nil since:
   672  			// n == len(buf) if and only if err == nil.
   673  			return fh.finish(err)
   674  		}
   675  		// possibly err != nil here, but we will process the
   676  		// data and the next call to ReadFull will return 0, err
   677  		// Write nonce to start of block
   678  		copy(fh.buf, fh.nonce[:])
   679  		// Encrypt the block using the nonce
   680  		block := fh.buf
   681  		secretbox.Seal(block[:0], readBuf[:n], fh.nonce.pointer(), &fh.c.dataKey)
   682  		fh.bufIndex = 0
   683  		fh.bufSize = blockHeaderSize + n
   684  		fh.nonce.increment()
   685  	}
   686  	n = copy(p, fh.buf[fh.bufIndex:fh.bufSize])
   687  	fh.bufIndex += n
   688  	return n, nil
   689  }
   690  
   691  // finish sets the final error and tidies up
   692  func (fh *encrypter) finish(err error) (int, error) {
   693  	if fh.err != nil {
   694  		return 0, fh.err
   695  	}
   696  	fh.err = err
   697  	fh.c.putBlock(fh.buf)
   698  	fh.buf = nil
   699  	fh.c.putBlock(fh.readBuf)
   700  	fh.readBuf = nil
   701  	return 0, err
   702  }
   703  
   704  // Encrypt data encrypts the data stream
   705  func (c *cipher) EncryptData(in io.Reader) (io.Reader, error) {
   706  	in, wrap := accounting.UnWrap(in) // unwrap the accounting off the Reader
   707  	out, err := c.newEncrypter(in, nil)
   708  	if err != nil {
   709  		return nil, err
   710  	}
   711  	return wrap(out), nil // and wrap the accounting back on
   712  }
   713  
   714  // decrypter decrypts an io.ReaderCloser on the fly
   715  type decrypter struct {
   716  	mu           sync.Mutex
   717  	rc           io.ReadCloser
   718  	nonce        nonce
   719  	initialNonce nonce
   720  	c            *cipher
   721  	buf          []byte
   722  	readBuf      []byte
   723  	bufIndex     int
   724  	bufSize      int
   725  	err          error
   726  	limit        int64 // limit of bytes to read, -1 for unlimited
   727  	open         OpenRangeSeek
   728  }
   729  
   730  // newDecrypter creates a new file handle decrypting on the fly
   731  func (c *cipher) newDecrypter(rc io.ReadCloser) (*decrypter, error) {
   732  	fh := &decrypter{
   733  		rc:      rc,
   734  		c:       c,
   735  		buf:     c.getBlock(),
   736  		readBuf: c.getBlock(),
   737  		limit:   -1,
   738  	}
   739  	// Read file header (magic + nonce)
   740  	readBuf := fh.readBuf[:fileHeaderSize]
   741  	_, err := io.ReadFull(fh.rc, readBuf)
   742  	if err == io.EOF || err == io.ErrUnexpectedEOF {
   743  		// This read from 0..fileHeaderSize-1 bytes
   744  		return nil, fh.finishAndClose(ErrorEncryptedFileTooShort)
   745  	} else if err != nil {
   746  		return nil, fh.finishAndClose(err)
   747  	}
   748  	// check the magic
   749  	if !bytes.Equal(readBuf[:fileMagicSize], fileMagicBytes) {
   750  		return nil, fh.finishAndClose(ErrorEncryptedBadMagic)
   751  	}
   752  	// retrieve the nonce
   753  	fh.nonce.fromBuf(readBuf[fileMagicSize:])
   754  	fh.initialNonce = fh.nonce
   755  	return fh, nil
   756  }
   757  
   758  // newDecrypterSeek creates a new file handle decrypting on the fly
   759  func (c *cipher) newDecrypterSeek(ctx context.Context, open OpenRangeSeek, offset, limit int64) (fh *decrypter, err error) {
   760  	var rc io.ReadCloser
   761  	doRangeSeek := false
   762  	setLimit := false
   763  	// Open initially with no seek
   764  	if offset == 0 && limit < 0 {
   765  		// If no offset or limit then open whole file
   766  		rc, err = open(ctx, 0, -1)
   767  	} else if offset == 0 {
   768  		// If no offset open the header + limit worth of the file
   769  		_, underlyingLimit, _, _ := calculateUnderlying(offset, limit)
   770  		rc, err = open(ctx, 0, int64(fileHeaderSize)+underlyingLimit)
   771  		setLimit = true
   772  	} else {
   773  		// Otherwise just read the header to start with
   774  		rc, err = open(ctx, 0, int64(fileHeaderSize))
   775  		doRangeSeek = true
   776  	}
   777  	if err != nil {
   778  		return nil, err
   779  	}
   780  	// Open the stream which fills in the nonce
   781  	fh, err = c.newDecrypter(rc)
   782  	if err != nil {
   783  		return nil, err
   784  	}
   785  	fh.open = open // will be called by fh.RangeSeek
   786  	if doRangeSeek {
   787  		_, err = fh.RangeSeek(ctx, offset, io.SeekStart, limit)
   788  		if err != nil {
   789  			_ = fh.Close()
   790  			return nil, err
   791  		}
   792  	}
   793  	if setLimit {
   794  		fh.limit = limit
   795  	}
   796  	return fh, nil
   797  }
   798  
   799  // read data into internal buffer - call with fh.mu held
   800  func (fh *decrypter) fillBuffer() (err error) {
   801  	// FIXME should overlap the reads with a go-routine and 2 buffers?
   802  	readBuf := fh.readBuf
   803  	n, err := io.ReadFull(fh.rc, readBuf)
   804  	if n == 0 {
   805  		// err can't be nil since:
   806  		// n == len(buf) if and only if err == nil.
   807  		return err
   808  	}
   809  	// possibly err != nil here, but we will process the data and
   810  	// the next call to ReadFull will return 0, err
   811  
   812  	// Check header + 1 byte exists
   813  	if n <= blockHeaderSize {
   814  		if err != nil {
   815  			return err // return pending error as it is likely more accurate
   816  		}
   817  		return ErrorEncryptedFileBadHeader
   818  	}
   819  	// Decrypt the block using the nonce
   820  	block := fh.buf
   821  	_, ok := secretbox.Open(block[:0], readBuf[:n], fh.nonce.pointer(), &fh.c.dataKey)
   822  	if !ok {
   823  		if err != nil {
   824  			return err // return pending error as it is likely more accurate
   825  		}
   826  		return ErrorEncryptedBadBlock
   827  	}
   828  	fh.bufIndex = 0
   829  	fh.bufSize = n - blockHeaderSize
   830  	fh.nonce.increment()
   831  	return nil
   832  }
   833  
   834  // Read as per io.Reader
   835  func (fh *decrypter) Read(p []byte) (n int, err error) {
   836  	fh.mu.Lock()
   837  	defer fh.mu.Unlock()
   838  
   839  	if fh.err != nil {
   840  		return 0, fh.err
   841  	}
   842  	if fh.bufIndex >= fh.bufSize {
   843  		err = fh.fillBuffer()
   844  		if err != nil {
   845  			return 0, fh.finish(err)
   846  		}
   847  	}
   848  	toCopy := fh.bufSize - fh.bufIndex
   849  	if fh.limit >= 0 && fh.limit < int64(toCopy) {
   850  		toCopy = int(fh.limit)
   851  	}
   852  	n = copy(p, fh.buf[fh.bufIndex:fh.bufIndex+toCopy])
   853  	fh.bufIndex += n
   854  	if fh.limit >= 0 {
   855  		fh.limit -= int64(n)
   856  		if fh.limit == 0 {
   857  			return n, fh.finish(io.EOF)
   858  		}
   859  	}
   860  	return n, nil
   861  }
   862  
   863  // calculateUnderlying converts an (offset, limit) in a crypted file
   864  // into an (underlyingOffset, underlyingLimit) for the underlying
   865  // file.
   866  //
   867  // It also returns number of bytes to discard after reading the first
   868  // block and number of blocks this is from the start so the nonce can
   869  // be incremented.
   870  func calculateUnderlying(offset, limit int64) (underlyingOffset, underlyingLimit, discard, blocks int64) {
   871  	// blocks we need to seek, plus bytes we need to discard
   872  	blocks, discard = offset/blockDataSize, offset%blockDataSize
   873  
   874  	// Offset in underlying stream we need to seek
   875  	underlyingOffset = int64(fileHeaderSize) + blocks*(blockHeaderSize+blockDataSize)
   876  
   877  	// work out how many blocks we need to read
   878  	underlyingLimit = int64(-1)
   879  	if limit >= 0 {
   880  		// bytes to read beyond the first block
   881  		bytesToRead := limit - (blockDataSize - discard)
   882  
   883  		// Read the first block
   884  		blocksToRead := int64(1)
   885  
   886  		if bytesToRead > 0 {
   887  			// Blocks that need to be read plus left over blocks
   888  			extraBlocksToRead, endBytes := bytesToRead/blockDataSize, bytesToRead%blockDataSize
   889  			if endBytes != 0 {
   890  				// If left over bytes must read another block
   891  				extraBlocksToRead++
   892  			}
   893  			blocksToRead += extraBlocksToRead
   894  		}
   895  
   896  		// Must read a whole number of blocks
   897  		underlyingLimit = blocksToRead * (blockHeaderSize + blockDataSize)
   898  	}
   899  	return
   900  }
   901  
   902  // RangeSeek behaves like a call to Seek(offset int64, whence
   903  // int) with the output wrapped in an io.LimitedReader
   904  // limiting the total length to limit.
   905  //
   906  // RangeSeek with a limit of < 0 is equivalent to a regular Seek.
   907  func (fh *decrypter) RangeSeek(ctx context.Context, offset int64, whence int, limit int64) (int64, error) {
   908  	fh.mu.Lock()
   909  	defer fh.mu.Unlock()
   910  
   911  	if fh.open == nil {
   912  		return 0, fh.finish(errors.New("can't seek - not initialised with newDecrypterSeek"))
   913  	}
   914  	if whence != io.SeekStart {
   915  		return 0, fh.finish(errors.New("can only seek from the start"))
   916  	}
   917  
   918  	// Reset error or return it if not EOF
   919  	if fh.err == io.EOF {
   920  		fh.unFinish()
   921  	} else if fh.err != nil {
   922  		return 0, fh.err
   923  	}
   924  
   925  	underlyingOffset, underlyingLimit, discard, blocks := calculateUnderlying(offset, limit)
   926  
   927  	// Move the nonce on the correct number of blocks from the start
   928  	fh.nonce = fh.initialNonce
   929  	fh.nonce.add(uint64(blocks))
   930  
   931  	// Can we seek underlying stream directly?
   932  	if do, ok := fh.rc.(fs.RangeSeeker); ok {
   933  		// Seek underlying stream directly
   934  		_, err := do.RangeSeek(ctx, underlyingOffset, 0, underlyingLimit)
   935  		if err != nil {
   936  			return 0, fh.finish(err)
   937  		}
   938  	} else {
   939  		// if not reopen with seek
   940  		_ = fh.rc.Close() // close underlying file
   941  		fh.rc = nil
   942  
   943  		// Re-open the underlying object with the offset given
   944  		rc, err := fh.open(ctx, underlyingOffset, underlyingLimit)
   945  		if err != nil {
   946  			return 0, fh.finish(errors.Wrap(err, "couldn't reopen file with offset and limit"))
   947  		}
   948  
   949  		// Set the file handle
   950  		fh.rc = rc
   951  	}
   952  
   953  	// Fill the buffer
   954  	err := fh.fillBuffer()
   955  	if err != nil {
   956  		return 0, fh.finish(err)
   957  	}
   958  
   959  	// Discard bytes from the buffer
   960  	if int(discard) > fh.bufSize {
   961  		return 0, fh.finish(ErrorBadSeek)
   962  	}
   963  	fh.bufIndex = int(discard)
   964  
   965  	// Set the limit
   966  	fh.limit = limit
   967  
   968  	return offset, nil
   969  }
   970  
   971  // Seek implements the io.Seeker interface
   972  func (fh *decrypter) Seek(offset int64, whence int) (int64, error) {
   973  	return fh.RangeSeek(context.TODO(), offset, whence, -1)
   974  }
   975  
   976  // finish sets the final error and tidies up
   977  func (fh *decrypter) finish(err error) error {
   978  	if fh.err != nil {
   979  		return fh.err
   980  	}
   981  	fh.err = err
   982  	fh.c.putBlock(fh.buf)
   983  	fh.buf = nil
   984  	fh.c.putBlock(fh.readBuf)
   985  	fh.readBuf = nil
   986  	return err
   987  }
   988  
   989  // unFinish undoes the effects of finish
   990  func (fh *decrypter) unFinish() {
   991  	// Clear error
   992  	fh.err = nil
   993  
   994  	// reinstate the buffers
   995  	fh.buf = fh.c.getBlock()
   996  	fh.readBuf = fh.c.getBlock()
   997  
   998  	// Empty the buffer
   999  	fh.bufIndex = 0
  1000  	fh.bufSize = 0
  1001  }
  1002  
  1003  // Close
  1004  func (fh *decrypter) Close() error {
  1005  	fh.mu.Lock()
  1006  	defer fh.mu.Unlock()
  1007  
  1008  	// Check already closed
  1009  	if fh.err == ErrorFileClosed {
  1010  		return fh.err
  1011  	}
  1012  	// Closed before reading EOF so not finish()ed yet
  1013  	if fh.err == nil {
  1014  		_ = fh.finish(io.EOF)
  1015  	}
  1016  	// Show file now closed
  1017  	fh.err = ErrorFileClosed
  1018  	if fh.rc == nil {
  1019  		return nil
  1020  	}
  1021  	return fh.rc.Close()
  1022  }
  1023  
  1024  // finishAndClose does finish then Close()
  1025  //
  1026  // Used when we are returning a nil fh from new
  1027  func (fh *decrypter) finishAndClose(err error) error {
  1028  	_ = fh.finish(err)
  1029  	_ = fh.Close()
  1030  	return err
  1031  }
  1032  
  1033  // DecryptData decrypts the data stream
  1034  func (c *cipher) DecryptData(rc io.ReadCloser) (io.ReadCloser, error) {
  1035  	out, err := c.newDecrypter(rc)
  1036  	if err != nil {
  1037  		return nil, err
  1038  	}
  1039  	return out, nil
  1040  }
  1041  
  1042  // DecryptDataSeek decrypts the data stream from offset
  1043  //
  1044  // The open function must return a ReadCloser opened to the offset supplied
  1045  //
  1046  // You must use this form of DecryptData if you might want to Seek the file handle
  1047  func (c *cipher) DecryptDataSeek(ctx context.Context, open OpenRangeSeek, offset, limit int64) (ReadSeekCloser, error) {
  1048  	out, err := c.newDecrypterSeek(ctx, open, offset, limit)
  1049  	if err != nil {
  1050  		return nil, err
  1051  	}
  1052  	return out, nil
  1053  }
  1054  
  1055  // EncryptedSize calculates the size of the data when encrypted
  1056  func (c *cipher) EncryptedSize(size int64) int64 {
  1057  	blocks, residue := size/blockDataSize, size%blockDataSize
  1058  	encryptedSize := int64(fileHeaderSize) + blocks*(blockHeaderSize+blockDataSize)
  1059  	if residue != 0 {
  1060  		encryptedSize += blockHeaderSize + residue
  1061  	}
  1062  	return encryptedSize
  1063  }
  1064  
  1065  // DecryptedSize calculates the size of the data when decrypted
  1066  func (c *cipher) DecryptedSize(size int64) (int64, error) {
  1067  	size -= int64(fileHeaderSize)
  1068  	if size < 0 {
  1069  		return 0, ErrorEncryptedFileTooShort
  1070  	}
  1071  	blocks, residue := size/blockSize, size%blockSize
  1072  	decryptedSize := blocks * blockDataSize
  1073  	if residue != 0 {
  1074  		residue -= blockHeaderSize
  1075  		if residue <= 0 {
  1076  			return 0, ErrorEncryptedFileBadHeader
  1077  		}
  1078  	}
  1079  	decryptedSize += residue
  1080  	return decryptedSize, nil
  1081  }
  1082  
  1083  // check interfaces
  1084  var (
  1085  	_ Cipher         = (*cipher)(nil)
  1086  	_ io.ReadCloser  = (*decrypter)(nil)
  1087  	_ io.Seeker      = (*decrypter)(nil)
  1088  	_ fs.RangeSeeker = (*decrypter)(nil)
  1089  	_ io.Reader      = (*encrypter)(nil)
  1090  )