mirror of
https://github.com/vgough/encfs.git
synced 2024-11-25 09:23:13 +01:00
63c2d1c539
git-svn-id: http://encfs.googlecode.com/svn/trunk@97 db9cf616-1c43-0410-9cb8-a902689de0d6
188 lines
5.9 KiB
C++
188 lines
5.9 KiB
C++
/*****************************************************************************
|
|
* Author: Valient Gough <vgough@pobox.com>
|
|
*
|
|
*****************************************************************************
|
|
* Copyright (c) 2004-2013, Valient Gough
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify it
|
|
* under the terms of the GNU Lesser General Public License as published by the
|
|
* Free Software Foundation, either version 3 of the License, or (at your
|
|
* option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
|
* for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#ifndef _CipherV1_incl_
|
|
#define _CipherV1_incl_
|
|
|
|
#include "base/Interface.h"
|
|
#include "base/Mutex.h"
|
|
#include "base/shared_ptr.h"
|
|
|
|
#include "cipher/BlockCipher.h"
|
|
#include "cipher/StreamCipher.h"
|
|
#include "cipher/MAC.h"
|
|
#include "cipher/PBKDF.h"
|
|
|
|
namespace encfs {
|
|
|
|
class SecureMem;
|
|
|
|
/*
|
|
Implements Encfs V1.x ciphers support.
|
|
|
|
Design:
|
|
Variable algorithm, key size, and block size.
|
|
|
|
Partial blocks, keys, and names are encrypted using the cipher in a pseudo
|
|
stream mode (CFB).
|
|
|
|
Keys are encrypted with 2-4 (KEY_CHECKSUM_BYTES define) checksum bytes
|
|
derived from an HMAC over both they key data and the initial value vector
|
|
associated with the key. This allows a good chance at detecting an
|
|
incorrect password when we try and decrypt the master key.
|
|
|
|
File names are encrypted in the same way, with 2 checksum bytes derived
|
|
from an HMAC over the filename. This is done not to allow checking the
|
|
results, but to make the output much more random. Changing one letter in a
|
|
filename should result in a completely different encrypted filename, to
|
|
help frustrate any attempt to guess information about files from their
|
|
encrypted names.
|
|
|
|
Stream encryption involves two encryption passes over the data, implemented
|
|
as:
|
|
1. shuffle
|
|
2. encrypt
|
|
3. reverse
|
|
4. shuffle
|
|
5. encrypt
|
|
The reason for the shuffle and reverse steps (and the second encrypt pass)
|
|
is to try and propogate any changed bits to a larger set. If only a single
|
|
pass was made with the stream cipher in CFB mode, then a change to one byte
|
|
may only affect one byte of output, allowing some XOR attacks.
|
|
|
|
The shuffle/encrypt is used as above in filename encryption as well,
|
|
although it is not necessary as they have checksum bytes which augment the
|
|
initial value vector to randomize the output. But it makes the code
|
|
simpler to reuse the encryption algorithm as is.
|
|
*/
|
|
class CipherV1
|
|
{
|
|
Interface iface;
|
|
Interface realIface;
|
|
|
|
shared_ptr<BlockCipher> _blockCipher;
|
|
shared_ptr<StreamCipher> _streamCipher;
|
|
shared_ptr<PBKDF> _pbkdf;
|
|
|
|
// HMac is stateful, so access is controlled via mutex.
|
|
mutable Mutex _hmacMutex;
|
|
mutable shared_ptr<MAC> _hmac;
|
|
|
|
unsigned int _keySize; // in bytes
|
|
unsigned int _ivLength;
|
|
|
|
shared_ptr<SecureMem> _iv;
|
|
bool _keySet;
|
|
|
|
public:
|
|
|
|
struct CipherAlgorithm
|
|
{
|
|
std::string name;
|
|
std::string description;
|
|
Interface iface;
|
|
Range keyLength;
|
|
Range blockSize;
|
|
};
|
|
|
|
static void init(bool threaded);
|
|
static void shutdown(bool threaded);
|
|
|
|
// Returns a list of supported algorithms.
|
|
static std::list<CipherAlgorithm> GetAlgorithmList();
|
|
static shared_ptr<CipherV1> New(const std::string &name, int keyLen = -1);
|
|
static shared_ptr<CipherV1> New(const Interface &alg, int keyLen = -1);
|
|
|
|
// Password-based key derivation function which determines the
|
|
// number of iterations based on a desired execution time (in microseconds).
|
|
// Returns the number of iterations applied.
|
|
static int TimedPBKDF2(const char *pass, int passLen,
|
|
const byte *salt, int saltLen,
|
|
CipherKey *out, long desiredPDFTimeMicroseconds);
|
|
|
|
CipherV1();
|
|
~CipherV1();
|
|
|
|
bool initCiphers(const Interface &iface,
|
|
const Interface &realIface, int keyLength);
|
|
|
|
// returns the real interface, not the one we're emulating (if any)..
|
|
Interface interface() const;
|
|
|
|
// create a new key based on a password
|
|
CipherKey newKey(const char *password, int passwdLength,
|
|
int *iterationCount, long desiredDuration,
|
|
const byte *salt, int saltLen);
|
|
// deprecated - for backward compatibility
|
|
CipherKey newKey(const char *password, int passwdLength);
|
|
// create a new random key
|
|
CipherKey newRandomKey();
|
|
|
|
// Read and decrypt a key.
|
|
// data must be len keySize()
|
|
CipherKey readKey(const byte *data, bool checkKey);
|
|
|
|
// Encrypt and write the given key.
|
|
void writeKey(const CipherKey &key, byte *data);
|
|
|
|
// Encrypt and store a key as a string.
|
|
std::string encodeAsString(const CipherKey &key);
|
|
|
|
|
|
// meta-data about the cypher
|
|
int keySize() const;
|
|
int encodedKeySize() const;
|
|
int cipherBlockSize() const;
|
|
|
|
bool pseudoRandomize(byte *buf, int len);
|
|
|
|
// Sets the key used for encoding / decoding, and MAC operations.
|
|
bool setKey(const CipherKey &key);
|
|
|
|
uint64_t MAC_64(const byte *src, int len,
|
|
uint64_t *augment = NULL) const;
|
|
|
|
static unsigned int reduceMac32(uint64_t mac64);
|
|
static unsigned int reduceMac16(uint64_t mac64);
|
|
|
|
// functional interfaces
|
|
/*
|
|
Stream encoding in-place.
|
|
*/
|
|
bool streamEncode(byte *data, int len, uint64_t iv64) const;
|
|
bool streamDecode(byte *data, int len, uint64_t iv64) const;
|
|
|
|
/*
|
|
Block encoding is done in-place. Partial blocks are supported, but
|
|
blocks are always expected to begin on a block boundary. See
|
|
blockSize().
|
|
*/
|
|
bool blockEncode(byte *buf, int size, uint64_t iv64) const;
|
|
bool blockDecode(byte *buf, int size, uint64_t iv64) const;
|
|
|
|
private:
|
|
void setIVec(byte *out, uint64_t seed) const;
|
|
};
|
|
|
|
} // namespace encfs
|
|
|
|
#endif
|
|
|