Cleanup option passing to make it simpler to pass options around.

Add new initialization vector setup mode for new filesystems.


git-svn-id: http://encfs.googlecode.com/svn/trunk@59 db9cf616-1c43-0410-9cb8-a902689de0d6
This commit is contained in:
Valient Gough 2010-08-30 06:32:05 +00:00
parent 460d04057b
commit 17071239d8
24 changed files with 478 additions and 471 deletions

View File

@ -1,3 +1,13 @@
Sun Aug 29 2010 Valient Gough <vgough@pobox.com>
* new IV initialization
* tag version 1.7
Sat Aug 28 2010 Valient Gough <vgough@pobox.com>
* fix component configuration to ease adding flags or config
Thu Jun 17 2010 Valient Gough <vgough@pobox.com>
* bump version to 1.6
Mon Jun 14 2010 Valient Gough <vgough@pobox.com>
* fix compile error for boost < 1.41 and change rWarning to rInfo
* fix compiler warnings about unused result from fgets

View File

@ -1,10 +1,7 @@
dnl Process this file with autoconf to produce a configure script.
AC_INIT(encfs/encfs.h) dnl a source file from your sub dir
AM_INIT_AUTOMAKE(encfs, 1.5.1) dnl searches for some needed programs
RELEASE=1
AC_SUBST(RELEASE)
AM_INIT_AUTOMAKE(encfs, 1.7) dnl searches for some needed programs
AC_CANONICAL_HOST
AM_CONDITIONAL([DARWIN],

View File

@ -36,9 +36,9 @@ static void clearCache( IORequest &req, int blockSize )
req.dataLen = 0;
}
BlockFileIO::BlockFileIO( int dataSize )
: _blockSize( dataSize )
, _allowHoles( false )
BlockFileIO::BlockFileIO( int blockSize, const FSConfigPtr &cfg )
: _blockSize( blockSize )
, _allowHoles( cfg->config->allowHoles )
{
rAssert( _blockSize > 1 );
_cache.data = new unsigned char [ _blockSize ];
@ -98,11 +98,6 @@ bool BlockFileIO::cacheWriteOneBlock( const IORequest &req )
return ok;
}
void BlockFileIO::allowHoles( bool allow )
{
_allowHoles = allow;
}
ssize_t BlockFileIO::read( const IORequest &req ) const
{
rAssert( _blockSize != 0 );

View File

@ -19,6 +19,7 @@
#define _BlockFileIO_incl_
#include "FileIO.h"
#include "FSConfig.h"
/*
Implements block scatter / gather interface. Requires derived classes to
@ -31,7 +32,7 @@
class BlockFileIO : public FileIO
{
public:
BlockFileIO(int blockDataSize);
BlockFileIO( int blockSize, const FSConfigPtr &cfg );
virtual ~BlockFileIO();
// implemented in terms of blocks.
@ -40,11 +41,6 @@ public:
virtual int blockSize() const;
// default is false, but setting this to true will allow holes to be stored
// in the file. Only works if supported by the underlying FileIO
// implementation..
virtual void allowHoles( bool allow );
protected:
int truncate( off_t size, FileIO *base );

View File

@ -50,23 +50,23 @@ static bool checkSize( int fsBlockSize, int cipherBlockSize )
}
CipherFileIO::CipherFileIO( const shared_ptr<FileIO> &_base,
const shared_ptr<Cipher> &_cipher,
const CipherKey &_key, int fsBlockSize,
bool uniqueIV, bool _reverseEncryption )
: BlockFileIO( fsBlockSize )
const FSConfigPtr &cfg)
: BlockFileIO( cfg->config->blockSize, cfg )
, base( _base )
, cipher( _cipher )
, key( _key )
, haveHeader( uniqueIV )
, haveHeader( cfg->config->uniqueIV )
, externalIV( 0 )
, fileIV( 0 )
, lastFlags( 0 )
, reverseEncryption( _reverseEncryption )
{
fsConfig = cfg;
cipher = cfg->cipher;
key = cfg->key;
static bool warnOnce = false;
if(!warnOnce)
warnOnce = checkSize( fsBlockSize, cipher->cipherBlockSize() );
warnOnce = checkSize( fsConfig->config->blockSize,
fsConfig->cipher->cipherBlockSize() );
}
CipherFileIO::~CipherFileIO()
@ -193,7 +193,8 @@ void CipherFileIO::initHeader( )
req.dataLen = 8;
base->read( req );
cipher->streamDecode( buf, sizeof(buf), externalIV, key );
cipher->streamDecode( buf, sizeof(buf),
externalIV, key );
fileIV = 0;
for(int i=0; i<8; ++i)
@ -277,13 +278,11 @@ ssize_t CipherFileIO::readOneBlock( const IORequest &req ) const
off_t blockNum = req.offset / bs;
ssize_t readSize = 0;
IORequest tmpReq = req;
if(haveHeader)
{
IORequest tmpReq = req;
tmpReq.offset += HEADER_SIZE;
readSize = base->read( tmpReq );
} else
readSize = base->read( req );
readSize = base->read( tmpReq );
bool ok;
if(readSize > 0)
@ -293,10 +292,10 @@ ssize_t CipherFileIO::readOneBlock( const IORequest &req ) const
if(readSize != bs)
{
ok = streamRead( req.data, (int)readSize, blockNum ^ fileIV);
ok = streamRead( tmpReq.data, (int)readSize, blockNum ^ fileIV);
} else
{
ok = blockRead( req.data, (int)readSize, blockNum ^ fileIV);
ok = blockRead( tmpReq.data, (int)readSize, blockNum ^ fileIV);
}
if(!ok)
@ -352,7 +351,7 @@ bool CipherFileIO::writeOneBlock( const IORequest &req )
bool CipherFileIO::blockWrite( unsigned char *buf, int size,
uint64_t _iv64 ) const
{
if (!reverseEncryption)
if (!fsConfig->reverseEncryption)
return cipher->blockEncode( buf, size, _iv64, key );
else
return cipher->blockDecode( buf, size, _iv64, key );
@ -361,7 +360,7 @@ bool CipherFileIO::blockWrite( unsigned char *buf, int size,
bool CipherFileIO::streamWrite( unsigned char *buf, int size,
uint64_t _iv64 ) const
{
if (!reverseEncryption)
if (!fsConfig->reverseEncryption)
return cipher->streamEncode( buf, size, _iv64, key );
else
return cipher->streamDecode( buf, size, _iv64, key );
@ -371,7 +370,7 @@ bool CipherFileIO::streamWrite( unsigned char *buf, int size,
bool CipherFileIO::blockRead( unsigned char *buf, int size,
uint64_t _iv64 ) const
{
if (reverseEncryption)
if (fsConfig->reverseEncryption)
return cipher->blockEncode( buf, size, _iv64, key );
else
{
@ -391,7 +390,7 @@ bool CipherFileIO::blockRead( unsigned char *buf, int size,
bool CipherFileIO::streamRead( unsigned char *buf, int size,
uint64_t _iv64 ) const
{
if (reverseEncryption)
if (fsConfig->reverseEncryption)
return cipher->streamEncode( buf, size, _iv64, key );
else
return cipher->streamDecode( buf, size, _iv64, key );

View File

@ -20,6 +20,7 @@
#include "BlockFileIO.h"
#include "CipherKey.h"
#include "FileUtils.h"
#include <inttypes.h>
@ -34,9 +35,7 @@ class CipherFileIO : public BlockFileIO
{
public:
CipherFileIO( const boost::shared_ptr<FileIO> &base,
const boost::shared_ptr<Cipher> &cipher,
const CipherKey &key, int blockSize,
bool uniqueIV, bool reverseEncryption );
const FSConfigPtr &cfg);
virtual ~CipherFileIO();
virtual rel::Interface interface() const;
@ -70,8 +69,9 @@ private:
uint64_t iv64 ) const;
boost::shared_ptr<FileIO> base;
boost::shared_ptr<Cipher> cipher;
CipherKey key;
FSConfigPtr fsConfig;
// if haveHeader is true, then we have a transparent file header which
// contains a 64 bit initialization vector.
bool haveHeader;
@ -79,7 +79,9 @@ private:
uint64_t externalIV;
uint64_t fileIV;
int lastFlags;
bool reverseEncryption;
boost::shared_ptr<Cipher> cipher;
CipherKey key;
};
#endif

View File

@ -22,6 +22,7 @@
#include "Context.h"
#include "Mutex.h"
#include "FileUtils.h"
#include "DirNode.h"
#include <rlog/rlog.h>

View File

@ -31,6 +31,8 @@
using boost::shared_ptr;
struct EncFS_Args;
struct EncFS_Opts;
class FileNode;
class DirNode;
class EncFS_Context
{

View File

@ -302,7 +302,8 @@ void RenameOp::undo()
}
DirNode::DirNode(EncFS_Context *_ctx,
const string &sourceDir, const shared_ptr<Config> &_config)
const string &sourceDir,
const FSConfigPtr &_config)
{
pthread_mutex_init( &mutex, 0 );
@ -310,14 +311,14 @@ DirNode::DirNode(EncFS_Context *_ctx,
ctx = _ctx;
rootDir = sourceDir;
config = _config;
fsConfig = _config;
// make sure rootDir ends in '/', so that we can form a path by appending
// the rest..
if( rootDir[ rootDir.length()-1 ] != '/' )
rootDir.append( 1, '/');
naming = config->nameCoding;
naming = fsConfig->nameCoding;
}
DirNode::~DirNode()
@ -689,7 +690,7 @@ int DirNode::link( const char *from, const char *to )
rLog(Info, "link %s -> %s", fromCName.c_str(), toCName.c_str());
int res = -EPERM;
if( config->externalIVChaining )
if( fsConfig->config->externalIVChaining )
{
rLog(Info, "hard links not supported with external IV chaining!");
} else
@ -745,16 +746,8 @@ shared_ptr<FileNode> DirNode::directLookup( const char *path )
{
return shared_ptr<FileNode>(
new FileNode( this,
config->fsSubVersion,
"unknown", path,
config->cipher, config->key,
config->blockSize, config->blockMACBytes,
config->blockMACRandBytes,
config->uniqueIV,
config->externalIVChaining,
config->forceDecode,
config->reverseEncryption,
config->allowHoles) );
fsConfig,
"unknown", path ));
}
shared_ptr<FileNode> DirNode::findOrCreate( const char *plainName)
@ -767,20 +760,11 @@ shared_ptr<FileNode> DirNode::findOrCreate( const char *plainName)
{
uint64_t iv = 0;
string cipherName = naming->encodePath( plainName, &iv );
node.reset( new FileNode( this,
config->fsSubVersion,
node.reset( new FileNode( this, fsConfig,
plainName,
(rootDir + cipherName).c_str(),
config->cipher, config->key,
config->blockSize, config->blockMACBytes,
config->blockMACRandBytes,
config->uniqueIV,
config->externalIVChaining,
config->forceDecode,
config->reverseEncryption,
config->allowHoles) );
(rootDir + cipherName).c_str()));
if(config->externalIVChaining)
if(fsConfig->config->externalIVChaining)
node->setName(0, 0, iv);
rLog(Info, "created FileNode for %s", node->cipherName());

View File

@ -30,6 +30,7 @@
#include "FileNode.h"
#include "NameIO.h"
#include "CipherKey.h"
#include "FSConfig.h"
using boost::shared_ptr;
@ -87,38 +88,10 @@ namespace __gnu_cxx
class DirNode
{
public:
struct Config
{
shared_ptr<Cipher> cipher; // cipher to use
CipherKey key; // cipher key to use
shared_ptr<NameIO> nameCoding; // filename encoding implementation
int fsSubVersion; // filesystem version number at creation
int blockSize; // file data block size
bool inactivityTimer; // enables inactivity tracking
int blockMACBytes; // >0 enables per-file-block MAC headers
int blockMACRandBytes; // random bytes in MAC headers
bool uniqueIV; // enable per-file initialization vectors
bool externalIVChaining;
bool forceDecode; // force decoding, even if errors are detected
bool reverseEncryption;
bool allowHoles; // allow holes in files
Config()
: fsSubVersion(0)
, blockSize(1)
, inactivityTimer( false )
, blockMACBytes( 0 )
, blockMACRandBytes( 0 )
, uniqueIV( false )
, externalIVChaining( false )
, forceDecode( false )
, reverseEncryption ( false )
, allowHoles( false )
{ }
};
// sourceDir points to where raw files are stored
DirNode( EncFS_Context *ctx,
const std::string &sourceDir, const shared_ptr<Config> &config );
DirNode(EncFS_Context *ctx,
const std::string &sourceDir,
const FSConfigPtr &config );
~DirNode();
// return the path to the root directory
@ -207,9 +180,8 @@ private:
// passed in as configuration
std::string rootDir;
shared_ptr<Config> config;
FSConfigPtr fsConfig;
// stored here to reduce access through config var..
shared_ptr<NameIO> naming;
};

132
encfs/FSConfig.h Normal file
View File

@ -0,0 +1,132 @@
/*****************************************************************************
* Author: Valient Gough <vgough@pobox.com>
*
*****************************************************************************
* Copyright (c) 2010 Valient Gough
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU 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 General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _FSConfig_incl_
#define _FSConfig_incl_
#include "encfs.h"
#include "Interface.h"
#include "CipherKey.h"
#include <vector>
#include <boost/shared_ptr.hpp>
enum ConfigType
{
Config_None = 0,
Config_Prehistoric,
Config_V3,
Config_V4,
Config_V5,
Config_V6
};
class EncFS_Opts;
class Cipher;
class NameIO;
struct EncFSConfig
{
ConfigType cfgType;
std::string creator;
int subVersion;
// interface of cipher
rel::Interface cipherIface;
// interface used for file name coding
rel::Interface nameIface;
int keySize; // reported in bits
int blockSize; // reported in bytes
std::vector<unsigned char> keyData;
std::vector<unsigned char> salt;
int kdfIterations;
long desiredKDFDuration;
int blockMACBytes; // MAC headers on blocks..
int blockMACRandBytes; // number of random bytes in the block header
bool uniqueIV; // per-file Initialization Vector
bool externalIVChaining; // IV seeding by filename IV chaining
bool chainedNameIV; // filename IV chaining
bool allowHoles; // allow holes in files (implicit zero blocks)
EncFSConfig()
: keyData()
, salt()
{
cfgType = Config_None;
subVersion = 0;
blockMACBytes = 0;
blockMACRandBytes = 0;
uniqueIV = false;
externalIVChaining = false;
chainedNameIV = false;
allowHoles = false;
kdfIterations = 0;
desiredKDFDuration = 500;
}
CipherKey getUserKey(bool useStdin);
CipherKey getUserKey(const std::string &passwordProgram,
const std::string &rootDir);
CipherKey getNewUserKey();
boost::shared_ptr<Cipher> getCipher() const;
// deprecated
void assignKeyData(const std::string &in);
void assignKeyData(unsigned char *data, int length);
void assignSaltData(unsigned char *data, int length);
unsigned char *getKeyData() const;
unsigned char *getSaltData() const;
private:
CipherKey makeKey(const char *password, int passwdLen);
};
// helpers for serializing to/from a stream
std::ostream &operator << (std::ostream &os, const EncFSConfig &cfg);
std::istream &operator >> (std::istream &os, EncFSConfig &cfg);
struct FSConfig
{
boost::shared_ptr<EncFSConfig> config;
boost::shared_ptr<EncFS_Opts> opts;
boost::shared_ptr<Cipher> cipher;
CipherKey key;
boost::shared_ptr<NameIO> nameCoding;
bool forceDecode; // force decode on MAC block failures
bool reverseEncryption; // reverse encryption operation
bool idleTracking; // turn on idle monitoring of filesystem
};
typedef boost::shared_ptr<FSConfig> FSConfigPtr;
#endif

View File

@ -63,13 +63,8 @@ using boost::dynamic_pointer_cast;
static RLogChannel *Info = DEF_CHANNEL("info/FileNode", Log_Info);
FileNode::FileNode(DirNode *parent_,
int fsSubVersion,
const char *plaintextName_, const char *cipherName_,
const shared_ptr<Cipher> &dataCipher, const CipherKey &key,
int blockSize, int blockMACBytes, int blockMACRandBytes, bool uniqueIV,
bool externalIVChaining_, bool forceDecode, bool reverseEncryption_,
bool allowHoles )
FileNode::FileNode(DirNode *parent_, const FSConfigPtr &cfg,
const char *plaintextName_, const char *cipherName_)
{
pthread_mutex_init( &mutex, 0 );
@ -78,23 +73,15 @@ FileNode::FileNode(DirNode *parent_,
this->_pname = plaintextName_;
this->_cname = cipherName_;
this->parent = parent_;
this->externalIVChaining = externalIVChaining_;
this->reverseEncryption = reverseEncryption_;
this->fsConfig = cfg;
// chain RawFileIO & CipherFileIO
shared_ptr<FileIO> rawIO( new RawFileIO( _cname ) );
io = shared_ptr<FileIO>(
new CipherFileIO( rawIO, dataCipher, key, blockSize,
uniqueIV, reverseEncryption ));
io = shared_ptr<FileIO>( new CipherFileIO( rawIO, fsConfig ));
if(blockMACBytes)
{
io = shared_ptr<FileIO>(new MACFileIO(io, dataCipher, key,
blockSize,blockMACBytes,blockMACRandBytes,forceDecode));
}
if(allowHoles)
dynamic_pointer_cast<BlockFileIO>(io)->allowHoles( allowHoles );
if(cfg->config->blockMACBytes)
io = shared_ptr<FileIO>(new MACFileIO(io, fsConfig));
}
FileNode::~FileNode()
@ -140,7 +127,7 @@ bool FileNode::setName( const char *plaintextName_, const char *cipherName_,
rDebug("calling setIV on %s", cipherName_);
if(setIVFirst)
{
if(externalIVChaining && !setIV(io, iv))
if(fsConfig->config->externalIVChaining && !setIV(io, iv))
return false;
// now change the name..
@ -164,7 +151,7 @@ bool FileNode::setName( const char *plaintextName_, const char *cipherName_,
io->setFileName( cipherName_ );
}
if(externalIVChaining && !setIV(io, iv))
if(fsConfig->config->externalIVChaining && !setIV(io, iv))
{
_pname = oldPName;
_cname = oldCName;

View File

@ -20,6 +20,7 @@
#include "encfs.h"
#include "CipherKey.h"
#include "FileUtils.h"
#include <inttypes.h>
#include <sys/types.h>
@ -33,18 +34,10 @@ using boost::shared_ptr;
class FileNode
{
public:
FileNode(DirNode *parent,
int fsSubVersion, // version number for the filesystem
const char *plaintextName,
const char *cipherName,
const shared_ptr<Cipher> &cipher, const CipherKey &key, int blockSize,
int blockMACBytes, // per-block random bytes in header
int blockMACRandBytes, // per-block random bytes in header
bool uniqueIV, // enable per-file initialization vectors
bool externalIVChaining,
bool forceDecode, // decode, even if decoding errors are detected
bool reverseEncryption,
bool allowHoles );
FileNode(DirNode *parent,
const FSConfigPtr &cfg,
const char *plaintextName,
const char *cipherName);
~FileNode();
const char *plaintextName() const;
@ -86,8 +79,8 @@ private:
// truncate() which may result in multiple calls down to the FileIO
// level.
mutable pthread_mutex_t mutex;
bool externalIVChaining;
bool reverseEncryption;
FSConfigPtr fsConfig;
shared_ptr<FileIO> io;
std::string _pname; // plaintext name

View File

@ -29,6 +29,7 @@
#include "FileUtils.h"
#include "ConfigReader.h"
#include "FSConfig.h"
#include "DirNode.h"
#include "Cipher.h"
@ -105,9 +106,11 @@ struct ConfigInfo
const char *fileName;
ConfigType type;
const char *environmentOverride;
bool (*loadFunc)(const char *fileName, EncFSConfig *config,
bool (*loadFunc)(const char *fileName,
const boost::shared_ptr<EncFSConfig> &config,
ConfigInfo *cfg);
bool (*saveFunc)(const char *fileName, EncFSConfig *config);
bool (*saveFunc)(const char *fileName,
const boost::shared_ptr<EncFSConfig> &config);
int currentSubVersion;
int defaultSubVersion;
} ConfigFileMapping[] = {
@ -338,7 +341,7 @@ bool userAllowMkdir( const char *path, mode_t mode )
}
ConfigType readConfig_load( ConfigInfo *nm, const char *path,
EncFSConfig *config )
const boost::shared_ptr<EncFSConfig> &config )
{
if( nm->loadFunc )
{
@ -364,7 +367,8 @@ ConfigType readConfig_load( ConfigInfo *nm, const char *path,
}
}
ConfigType readConfig( const string &rootDir, EncFSConfig *config )
ConfigType readConfig( const string &rootDir,
const boost::shared_ptr<EncFSConfig> &config )
{
ConfigInfo *nm = ConfigFileMapping;
while(nm->fileName)
@ -387,7 +391,8 @@ ConfigType readConfig( const string &rootDir, EncFSConfig *config )
return Config_None;
}
bool readV6Config( const char *configFile, EncFSConfig *config,
bool readV6Config( const char *configFile,
const boost::shared_ptr<EncFSConfig> &config,
ConfigInfo *info)
{
(void)info;
@ -413,7 +418,8 @@ bool readV6Config( const char *configFile, EncFSConfig *config,
}
}
bool readV5Config( const char *configFile, EncFSConfig *config,
bool readV5Config( const char *configFile,
const boost::shared_ptr<EncFSConfig> &config,
ConfigInfo *info)
{
bool ok = false;
@ -470,7 +476,8 @@ bool readV5Config( const char *configFile, EncFSConfig *config,
return ok;
}
bool readV4Config( const char *configFile, EncFSConfig *config,
bool readV4Config( const char *configFile,
const boost::shared_ptr<EncFSConfig> &config,
ConfigInfo *info)
{
bool ok = false;
@ -511,7 +518,7 @@ bool readV4Config( const char *configFile, EncFSConfig *config,
}
bool saveConfig( ConfigType type, const string &rootDir,
EncFSConfig *config )
const boost::shared_ptr<EncFSConfig> &config )
{
bool ok = false;
@ -545,15 +552,14 @@ bool saveConfig( ConfigType type, const string &rootDir,
return ok;
}
bool writeV6Config( const char *configFile, EncFSConfig *config )
bool writeV6Config( const char *configFile,
const boost::shared_ptr<EncFSConfig> &config )
{
fs::ofstream st( configFile );
if(!st.is_open())
return false;
boost::archive::xml_oarchive oa(st);
oa << BOOST_SERIALIZATION_NVP( config );
st << *config;
return true;
}
@ -573,7 +579,8 @@ std::istream &operator >> (std::istream &st, EncFSConfig &cfg)
return st;
}
bool writeV5Config( const char *configFile, EncFSConfig *config )
bool writeV5Config( const char *configFile,
const boost::shared_ptr<EncFSConfig> &config )
{
ConfigReader cfg;
@ -595,7 +602,8 @@ bool writeV5Config( const char *configFile, EncFSConfig *config )
return cfg.save( configFile );
}
bool writeV4Config( const char *configFile, EncFSConfig *config )
bool writeV4Config( const char *configFile,
const boost::shared_ptr<EncFSConfig> &config )
{
ConfigReader cfg;
@ -1114,25 +1122,25 @@ RootPtr createV6Config( EncFS_Context *ctx, const std::string &rootDir,
alg.name.c_str(), keySize, blockSize);
}
EncFSConfig config;
shared_ptr<EncFSConfig> config( new EncFSConfig );
config.cfgType = Config_V6;
config.cipherIface = cipher->interface();
config.keySize = keySize;
config.blockSize = blockSize;
config.nameIface = nameIOIface;
config.creator = "EncFS " VERSION;
config.subVersion = V6SubVersion;
config.blockMACBytes = blockMACBytes;
config.blockMACRandBytes = blockMACRandBytes;
config.uniqueIV = uniqueIV;
config.chainedNameIV = chainedIV;
config.externalIVChaining = externalIV;
config.allowHoles = allowHoles;
config->cfgType = Config_V6;
config->cipherIface = cipher->interface();
config->keySize = keySize;
config->blockSize = blockSize;
config->nameIface = nameIOIface;
config->creator = "EncFS " VERSION;
config->subVersion = V6SubVersion;
config->blockMACBytes = blockMACBytes;
config->blockMACRandBytes = blockMACRandBytes;
config->uniqueIV = uniqueIV;
config->chainedNameIV = chainedIV;
config->externalIVChaining = externalIV;
config->allowHoles = allowHoles;
config.salt.clear();
config.kdfIterations = 0; // filled in by keying function
config.desiredKDFDuration = desiredKDFDuration;
config->salt.clear();
config->kdfIterations = 0; // filled in by keying function
config->desiredKDFDuration = desiredKDFDuration;
cout << "\n";
// xgroup(setup)
@ -1140,7 +1148,7 @@ RootPtr createV6Config( EncFS_Context *ctx, const std::string &rootDir,
"the following properties:") << endl;
showFSInfo( config );
if( config.externalIVChaining )
if( config->externalIVChaining )
{
cout <<
_("-------------------------- WARNING --------------------------\n")
@ -1170,16 +1178,16 @@ RootPtr createV6Config( EncFS_Context *ctx, const std::string &rootDir,
CipherKey userKey;
rDebug( "useStdin: %i", useStdin );
if(useStdin)
userKey = config.getUserKey( useStdin );
userKey = config->getUserKey( useStdin );
else if(!passwordProgram.empty())
userKey = config.getUserKey( passwordProgram, rootDir );
userKey = config->getUserKey( passwordProgram, rootDir );
else
userKey = config.getNewUserKey();
userKey = config->getNewUserKey();
cipher->writeKey( volumeKey, encodedKey, userKey );
userKey.reset();
config.assignKeyData(encodedKey, encodedKeySize);
config->assignKeyData(encodedKey, encodedKeySize);
delete[] encodedKey;
if(!volumeKey)
@ -1189,11 +1197,11 @@ RootPtr createV6Config( EncFS_Context *ctx, const std::string &rootDir,
return rootInfo;
}
if(!saveConfig( Config_V6, rootDir, &config ))
if(!saveConfig( Config_V6, rootDir, config ))
return rootInfo;
// fill in config struct
shared_ptr<NameIO> nameCoder = NameIO::New( config.nameIface,
shared_ptr<NameIO> nameCoder = NameIO::New( config->nameIface,
cipher, volumeKey );
if(!nameCoder)
{
@ -1203,49 +1211,43 @@ RootPtr createV6Config( EncFS_Context *ctx, const std::string &rootDir,
return rootInfo;
}
nameCoder->setChainedNameIV( config.chainedNameIV );
nameCoder->setChainedNameIV( config->chainedNameIV );
nameCoder->setReverseEncryption( reverseEncryption );
shared_ptr<DirNode::Config> dirNodeConfig (new DirNode::Config);
dirNodeConfig->cipher = cipher;
dirNodeConfig->key = volumeKey;
dirNodeConfig->nameCoding = nameCoder;
dirNodeConfig->fsSubVersion = config.subVersion;
dirNodeConfig->blockSize = blockSize;
dirNodeConfig->inactivityTimer = enableIdleTracking;
dirNodeConfig->blockMACBytes = config.blockMACBytes;
dirNodeConfig->blockMACRandBytes = config.blockMACRandBytes;
dirNodeConfig->uniqueIV = config.uniqueIV;
dirNodeConfig->externalIVChaining = config.externalIVChaining;
dirNodeConfig->forceDecode = forceDecode;
dirNodeConfig->reverseEncryption = reverseEncryption;
dirNodeConfig->allowHoles = config.allowHoles;
FSConfigPtr fsConfig (new FSConfig);
fsConfig->cipher = cipher;
fsConfig->key = volumeKey;
fsConfig->nameCoding = nameCoder;
fsConfig->config = config;
fsConfig->forceDecode = forceDecode;
fsConfig->reverseEncryption = reverseEncryption;
fsConfig->idleTracking = enableIdleTracking;
rootInfo = RootPtr( new EncFS_Root );
rootInfo->cipher = cipher;
rootInfo->volumeKey = volumeKey;
rootInfo->root = shared_ptr<DirNode>(
new DirNode( ctx, rootDir, dirNodeConfig ));
new DirNode( ctx, rootDir, fsConfig ));
return rootInfo;
}
void showFSInfo( const EncFSConfig &config )
void showFSInfo( const boost::shared_ptr<EncFSConfig> &config )
{
shared_ptr<Cipher> cipher = Cipher::New( config.cipherIface, -1 );
shared_ptr<Cipher> cipher = Cipher::New( config->cipherIface, -1 );
{
cout << autosprintf(
// xgroup(diag)
_("Filesystem cipher: \"%s\", version %i:%i:%i"),
config.cipherIface.name().c_str(), config.cipherIface.current(),
config.cipherIface.revision(), config.cipherIface.age());
config->cipherIface.name().c_str(), config->cipherIface.current(),
config->cipherIface.revision(), config->cipherIface.age());
// check if we support this interface..
if(!cipher)
cout << _(" (NOT supported)\n");
else
{
// if we're using a newer interface, show the version number
if( config.cipherIface != cipher->interface() )
if( config->cipherIface != cipher->interface() )
{
Interface iface = cipher->interface();
// xgroup(diag)
@ -1258,11 +1260,11 @@ void showFSInfo( const EncFSConfig &config )
{
// xgroup(diag)
cout << autosprintf(_("Filename encoding: \"%s\", version %i:%i:%i"),
config.nameIface.name().c_str(), config.nameIface.current(),
config.nameIface.revision(), config.nameIface.age());
config->nameIface.name().c_str(), config->nameIface.current(),
config->nameIface.revision(), config->nameIface.age());
// check if we support the filename encoding interface..
shared_ptr<NameIO> nameCoder = NameIO::New( config.nameIface,
shared_ptr<NameIO> nameCoder = NameIO::New( config->nameIface,
cipher, CipherKey() );
if(!nameCoder)
{
@ -1271,7 +1273,7 @@ void showFSInfo( const EncFSConfig &config )
} else
{
// if we're using a newer interface, show the version number
if( config.nameIface != nameCoder->interface() )
if( config->nameIface != nameCoder->interface() )
{
Interface iface = nameCoder->interface();
cout << autosprintf(_(" (using %i:%i:%i)\n"),
@ -1281,8 +1283,8 @@ void showFSInfo( const EncFSConfig &config )
}
}
{
cout << autosprintf(_("Key Size: %i bits"), config.keySize);
cipher = config.getCipher();
cout << autosprintf(_("Key Size: %i bits"), config->keySize);
cipher = config->getCipher();
if(!cipher)
{
// xgroup(diag)
@ -1290,54 +1292,54 @@ void showFSInfo( const EncFSConfig &config )
} else
cout << "\n";
}
if(config.kdfIterations > 0 && config.salt.size() > 0)
if(config->kdfIterations > 0 && config->salt.size() > 0)
{
cout << autosprintf(_("Using PBKDF2, with %i iterations"),
config.kdfIterations) << "\n";
config->kdfIterations) << "\n";
cout << autosprintf(_("Salt Size: %i bits"),
8*(int)config.salt.size()) << "\n";
8*(int)config->salt.size()) << "\n";
}
if(config.blockMACBytes)
if(config->blockMACBytes)
{
if(config.subVersion < 20040813)
if(config->subVersion < 20040813)
{
cout << autosprintf(
// xgroup(diag)
_("Block Size: %i bytes + %i byte MAC header"),
config.blockSize,
config.blockMACBytes + config.blockMACRandBytes) << endl;
config->blockSize,
config->blockMACBytes + config->blockMACRandBytes) << endl;
} else
{
// new version stores the header as part of that block size..
cout << autosprintf(
// xgroup(diag)
_("Block Size: %i bytes, including %i byte MAC header"),
config.blockSize,
config.blockMACBytes + config.blockMACRandBytes) << endl;
config->blockSize,
config->blockMACBytes + config->blockMACRandBytes) << endl;
}
} else
{
// xgroup(diag)
cout << autosprintf(_("Block Size: %i bytes"), config.blockSize);
cout << autosprintf(_("Block Size: %i bytes"), config->blockSize);
cout << "\n";
}
if(config.uniqueIV)
if(config->uniqueIV)
{
// xgroup(diag)
cout << _("Each file contains 8 byte header with unique IV data.\n");
}
if(config.chainedNameIV)
if(config->chainedNameIV)
{
// xgroup(diag)
cout << _("Filenames encoded using IV chaining mode.\n");
}
if(config.externalIVChaining)
if(config->externalIVChaining)
{
// xgroup(diag)
cout << _("File data IV is chained to filename IV.\n");
}
if(config.allowHoles)
if(config->allowHoles)
{
// xgroup(diag)
cout << _("File holes passed through to ciphertext.\n");
@ -1359,16 +1361,12 @@ void EncFSConfig::assignKeyData(const std::string &in)
void EncFSConfig::assignKeyData(unsigned char *data, int len)
{
keyData.resize(len);
for(int i=0; i<len; ++i)
keyData[i] = data[i];
keyData.assign(data, data+len);
}
void EncFSConfig::assignSaltData(unsigned char *data, int len)
{
salt.resize(len);
for(int i=0; i<len; ++i)
salt[i] = data[i];
salt.assign(data, data+len);
}
unsigned char *EncFSConfig::getKeyData() const
@ -1585,15 +1583,15 @@ CipherKey EncFSConfig::getNewUserKey()
RootPtr initFS( EncFS_Context *ctx, const shared_ptr<EncFS_Opts> &opts )
{
RootPtr rootInfo;
EncFSConfig config;
boost::shared_ptr<EncFSConfig> config(new EncFSConfig);
if(readConfig( opts->rootDir, &config ) != Config_None)
if(readConfig( opts->rootDir, config ) != Config_None)
{
if(opts->reverseEncryption)
{
if (config.blockMACBytes != 0 || config.blockMACRandBytes != 0
|| config.uniqueIV == true || config.externalIVChaining == true
|| config.chainedNameIV == true )
if (config->blockMACBytes != 0 || config->blockMACRandBytes != 0
|| config->uniqueIV || config->externalIVChaining
|| config->chainedNameIV )
{
cout << _("The configuration loaded is not compatible with --reverse\n");
return rootInfo;
@ -1601,14 +1599,14 @@ RootPtr initFS( EncFS_Context *ctx, const shared_ptr<EncFS_Opts> &opts )
}
// first, instanciate the cipher.
shared_ptr<Cipher> cipher = config.getCipher();
shared_ptr<Cipher> cipher = config->getCipher();
if(!cipher)
{
rError(_("Unable to find cipher %s, version %i:%i:%i"),
config.cipherIface.name().c_str(),
config.cipherIface.current(),
config.cipherIface.revision(),
config.cipherIface.age());
config->cipherIface.name().c_str(),
config->cipherIface.current(),
config->cipherIface.revision(),
config->cipherIface.age());
// xgroup(diag)
cout << _("The requested cipher interface is not available\n");
return rootInfo;
@ -1620,9 +1618,9 @@ RootPtr initFS( EncFS_Context *ctx, const shared_ptr<EncFS_Opts> &opts )
if(opts->passwordProgram.empty())
{
rDebug( "useStdin: %i", opts->useStdin );
userKey = config.getUserKey( opts->useStdin );
userKey = config->getUserKey( opts->useStdin );
} else
userKey = config.getUserKey( opts->passwordProgram, opts->rootDir );
userKey = config->getUserKey( opts->passwordProgram, opts->rootDir );
if(!userKey)
return rootInfo;
@ -1630,7 +1628,7 @@ RootPtr initFS( EncFS_Context *ctx, const shared_ptr<EncFS_Opts> &opts )
rDebug("cipher key size = %i", cipher->encodedKeySize());
// decode volume key..
CipherKey volumeKey = cipher->readKey(
config.getKeyData(), userKey, opts->checkKey);
config->getKeyData(), userKey, opts->checkKey);
userKey.reset();
if(!volumeKey)
@ -1640,43 +1638,37 @@ RootPtr initFS( EncFS_Context *ctx, const shared_ptr<EncFS_Opts> &opts )
return rootInfo;
}
shared_ptr<NameIO> nameCoder = NameIO::New( config.nameIface,
shared_ptr<NameIO> nameCoder = NameIO::New( config->nameIface,
cipher, volumeKey );
if(!nameCoder)
{
rError(_("Unable to find nameio interface %s, version %i:%i:%i"),
config.nameIface.name().c_str(),
config.nameIface.current(),
config.nameIface.revision(),
config.nameIface.age());
config->nameIface.name().c_str(),
config->nameIface.current(),
config->nameIface.revision(),
config->nameIface.age());
// xgroup(diag)
cout << _("The requested filename coding interface is "
"not available\n");
return rootInfo;
}
nameCoder->setChainedNameIV( config.chainedNameIV );
nameCoder->setChainedNameIV( config->chainedNameIV );
nameCoder->setReverseEncryption( opts->reverseEncryption );
shared_ptr<DirNode::Config> dirNodeConfig (new DirNode::Config);
dirNodeConfig->cipher = cipher;
dirNodeConfig->key = volumeKey;
dirNodeConfig->nameCoding = nameCoder;
dirNodeConfig->fsSubVersion = config.subVersion;
dirNodeConfig->blockSize = config.blockSize;
dirNodeConfig->inactivityTimer = opts->idleTracking;
dirNodeConfig->blockMACBytes = config.blockMACBytes;
dirNodeConfig->blockMACRandBytes = config.blockMACRandBytes;
dirNodeConfig->uniqueIV = config.uniqueIV;
dirNodeConfig->externalIVChaining = config.externalIVChaining;
dirNodeConfig->forceDecode = opts->forceDecode;
dirNodeConfig->reverseEncryption = opts->reverseEncryption;
FSConfigPtr fsConfig( new FSConfig );
fsConfig->cipher = cipher;
fsConfig->key = volumeKey;
fsConfig->nameCoding = nameCoder;
fsConfig->config = config;
fsConfig->forceDecode = opts->forceDecode;
fsConfig->reverseEncryption = opts->forceDecode;
rootInfo = RootPtr( new EncFS_Root );
rootInfo->cipher = cipher;
rootInfo->volumeKey = volumeKey;
rootInfo->root = shared_ptr<DirNode>(
new DirNode( ctx, opts->rootDir, dirNodeConfig ));
new DirNode( ctx, opts->rootDir, fsConfig ));
} else
{
if(opts->createIfNotFound)

View File

@ -20,8 +20,8 @@
#include "encfs.h"
#include "Interface.h"
#include "DirNode.h"
#include "CipherKey.h"
#include "FSConfig.h"
// true if the path points to an existing node (of any type)
bool fileExists( const char *fileName );
@ -38,85 +38,8 @@ std::string parentDirectory( const std::string &path );
// do it and return true.
bool userAllowMkdir( const char *dirPath, mode_t mode );
enum ConfigType
{
Config_None = 0,
Config_Prehistoric,
Config_V3,
Config_V4,
Config_V5,
Config_V6
};
struct EncFSConfig
{
ConfigType cfgType;
std::string creator;
int subVersion;
// interface of cipher
rel::Interface cipherIface;
// interface used for file name coding
rel::Interface nameIface;
int keySize; // reported in bits
int blockSize; // reported in bytes
std::vector<unsigned char> keyData;
std::vector<unsigned char> salt;
int kdfIterations;
long desiredKDFDuration;
int blockMACBytes; // MAC headers on blocks..
int blockMACRandBytes; // number of random bytes in the block header
bool uniqueIV; // per-file Initialization Vector
bool externalIVChaining; // IV seeding by filename IV chaining
bool chainedNameIV; // filename IV chaining
bool allowHoles; // allow holes in files (implicit zero blocks)
EncFSConfig()
: keyData()
, salt()
{
cfgType = Config_None;
subVersion = 0;
blockMACBytes = 0;
blockMACRandBytes = 0;
uniqueIV = false;
externalIVChaining = false;
chainedNameIV = false;
allowHoles = false;
kdfIterations = 0;
desiredKDFDuration = 500;
}
CipherKey getUserKey(bool useStdin);
CipherKey getUserKey(const std::string &passwordProgram,
const std::string &rootDir);
CipherKey getNewUserKey();
shared_ptr<Cipher> getCipher() const;
// deprecated
void assignKeyData(const std::string &in);
void assignKeyData(unsigned char *data, int length);
void assignSaltData(unsigned char *data, int length);
unsigned char *getKeyData() const;
unsigned char *getSaltData() const;
private:
CipherKey makeKey(const char *password, int passwdLen);
};
std::ostream &operator << (std::ostream &os, const EncFSConfig &cfg);
std::istream &operator >> (std::istream &os, EncFSConfig &cfg);
class Cipher;
class DirNode;
struct EncFS_Root
{
@ -130,18 +53,6 @@ struct EncFS_Root
typedef boost::shared_ptr<EncFS_Root> RootPtr;
/*
Read existing config file. Looks for any supported configuration version.
*/
ConfigType readConfig( const std::string &rootDir, EncFSConfig *config );
/*
Save the configuration. Saves back as the same configuration type as was
read from.
*/
bool saveConfig( ConfigType type, const std::string &rootdir,
EncFSConfig *config );
enum ConfigMode
{
Config_Prompt,
@ -170,21 +81,34 @@ struct EncFS_Opts
EncFS_Opts()
{
createIfNotFound = true;
idleTracking = false;
mountOnDemand = false;
checkKey = true;
forceDecode = false;
useStdin = false;
ownerCreate = false;
reverseEncryption = false;
createIfNotFound = true;
idleTracking = false;
mountOnDemand = false;
checkKey = true;
forceDecode = false;
useStdin = false;
ownerCreate = false;
reverseEncryption = false;
configMode = Config_Prompt;
}
};
/*
Read existing config file. Looks for any supported configuration version.
*/
ConfigType readConfig( const std::string &rootDir,
const boost::shared_ptr<EncFSConfig> &config );
/*
Save the configuration. Saves back as the same configuration type as was
read from.
*/
bool saveConfig( ConfigType type, const std::string &rootdir,
const boost::shared_ptr<EncFSConfig> &config );
class EncFS_Context;
RootPtr initFS( EncFS_Context *ctx, const shared_ptr<EncFS_Opts> &opts );
RootPtr initFS( EncFS_Context *ctx, const boost::shared_ptr<EncFS_Opts> &opts );
RootPtr createV6Config( EncFS_Context *ctx, const std::string &rootDir,
bool enableIdleTracking,
@ -193,18 +117,24 @@ RootPtr createV6Config( EncFS_Context *ctx, const std::string &rootDir,
bool allowHoles, ConfigMode mode );
void showFSInfo( const EncFSConfig &config );
void showFSInfo( const boost::shared_ptr<EncFSConfig> &config );
bool readV4Config( const char *configFile, EncFSConfig *config,
bool readV4Config( const char *configFile,
const boost::shared_ptr<EncFSConfig> &config,
struct ConfigInfo *);
bool writeV4Config( const char *configFile, EncFSConfig *config);
bool writeV4Config( const char *configFile,
const boost::shared_ptr<EncFSConfig> &config);
bool readV5Config( const char *configFile, EncFSConfig *config,
bool readV5Config( const char *configFile,
const boost::shared_ptr<EncFSConfig> &config,
struct ConfigInfo *);
bool writeV5Config( const char *configFile, EncFSConfig *config);
bool writeV5Config( const char *configFile,
const boost::shared_ptr<EncFSConfig> &config);
bool readV6Config( const char *configFile, EncFSConfig *config,
bool readV6Config( const char *configFile,
const boost::shared_ptr<EncFSConfig> &config,
struct ConfigInfo *);
bool writeV6Config( const char *configFile, EncFSConfig *config);
bool writeV6Config( const char *configFile,
const boost::shared_ptr<EncFSConfig> &config);
#endif

View File

@ -18,6 +18,7 @@
#include "MACFileIO.h"
#include "MemoryPool.h"
#include "FileUtils.h"
#include <rlog/rlog.h>
#include <rlog/Error.h>
@ -48,23 +49,29 @@ static RLogChannel *Info = DEF_CHANNEL("info/MACFileIO", Log_Info);
//
static rel::Interface MACFileIO_iface("FileIO/MAC", 2, 0, 0);
int dataBlockSize(const FSConfigPtr &cfg)
{
return cfg->config->blockSize
- cfg->config->blockMACBytes
- cfg->config->blockMACRandBytes;
}
MACFileIO::MACFileIO( const shared_ptr<FileIO> &_base,
const shared_ptr<Cipher> &_cipher,
const CipherKey &_key, int fsBlockSize,
int _macBytes, int _randBytes,
bool warnOnlyMode )
: BlockFileIO( fsBlockSize - _macBytes - _randBytes )
const FSConfigPtr &cfg )
: BlockFileIO( dataBlockSize( cfg ), cfg )
, base( _base )
, cipher( _cipher )
, key( _key )
, macBytes( _macBytes )
, randBytes( _randBytes )
, warnOnly( warnOnlyMode )
, cipher( cfg->cipher )
, key( cfg->key )
, macBytes( cfg->config->blockMACBytes )
, randBytes( cfg->config->blockMACRandBytes )
, warnOnly( cfg->opts->forceDecode )
{
rAssert( macBytes > 0 && macBytes <= 8 );
rAssert( randBytes >= 0 );
rLog(Info, "fs block size = %i, macBytes = %i, randBytes = %i",
fsBlockSize, macBytes, randBytes);
cfg->config->blockSize,
cfg->config->blockMACBytes,
cfg->config->blockMACRandBytes);
}
MACFileIO::~MACFileIO()
@ -159,14 +166,6 @@ off_t MACFileIO::getSize() const
return size;
}
void MACFileIO::allowHoles( bool allow )
{
BlockFileIO::allowHoles( allow );
shared_ptr<BlockFileIO> bf = dynamic_pointer_cast<BlockFileIO>( base );
if(bf)
bf->allowHoles( allow );
}
ssize_t MACFileIO::readOneBlock( const IORequest &req ) const
{
int headerSize = macBytes + randBytes;

View File

@ -32,10 +32,7 @@ public:
be made available..
*/
MACFileIO( const shared_ptr<FileIO> &base,
const shared_ptr<Cipher> &cipher,
const CipherKey &key, int blockSize,
int macBytes, int randBytes,
bool warnOnlyMode );
const FSConfigPtr &cfg );
MACFileIO();
virtual ~MACFileIO();
@ -53,8 +50,6 @@ public:
virtual bool isWritable() const;
virtual void allowHoles( bool allow );
private:
virtual ssize_t readOneBlock( const IORequest &req ) const;
virtual bool writeOneBlock( const IORequest &req );

View File

@ -47,7 +47,7 @@ endif
# : : 0 => no new interfaces, but breaks old apps
# : +1 : => internal changes, nothing breaks
#
libencfs_la_LDFLAGS = -version-info 5:0:2
libencfs_la_LDFLAGS = -version-info 6:0:0
libencfs_la_LIBADD = @RLOG_LIBS@ \
@OPENSSL_LIBS@ \
@BOOST_SERIALIZATION_LIB@ @BOOST_FILESYSTEM_LIB@ @BOOST_SYSTEM_LIB@
@ -101,6 +101,7 @@ encfsctl_SOURCES = \
noinst_HEADERS = \
base64.h \
boost-versioning.h \
BlockFileIO.h \
BlockNameIO.h \
CipherFileIO.h \

View File

@ -173,8 +173,9 @@ int TimedPBKDF2(const char *pass, int passlen,
// We support both 2:0 and 1:0, hence current:revision:age = 2:0:1
// - Version 2:1 adds support for Message Digest function interface
// - Version 2:2 adds PBKDF2 for password derivation
static Interface BlowfishInterface( "ssl/blowfish", 2, 2, 1 );
static Interface AESInterface( "ssl/aes", 2, 2, 1 );
// - Version 3:0 adds a new IV mechanism
static Interface BlowfishInterface( "ssl/blowfish", 3, 0, 2 );
static Interface AESInterface( "ssl/aes", 3, 0, 2 );
#if defined(HAVE_EVP_BF)
@ -399,13 +400,6 @@ CipherKey SSL_Cipher::newKey(const char *password, int passwdLength,
int &iterationCount, long desiredDuration,
const unsigned char *salt, int saltLen)
{
const EVP_MD *md = EVP_sha1();
if(!md)
{
rError("Unknown digest SHA1");
return CipherKey();
}
shared_ptr<SSLKey> key( new SSLKey( _keySize, _ivLength) );
if(iterationCount == 0)
@ -441,13 +435,6 @@ CipherKey SSL_Cipher::newKey(const char *password, int passwdLength,
CipherKey SSL_Cipher::newKey(const char *password, int passwdLength)
{
const EVP_MD *md = EVP_sha1();
if(!md)
{
rError("Unknown digest SHA1");
return CipherKey();
}
shared_ptr<SSLKey> key( new SSLKey( _keySize, _ivLength) );
int bytes = 0;
@ -545,7 +532,7 @@ static uint64_t _checksum_64( SSLKey *key,
HMAC_Final( &key->mac_ctx, md, &mdLen );
rAssert(mdLen != 0);
rAssert(mdLen >= 8);
// chop this down to a 64bit value..
unsigned char h[8] = {0,0,0,0,0,0,0,0};
@ -690,8 +677,45 @@ int SSL_Cipher::cipherBlockSize() const
return EVP_CIPHER_block_size( _blockCipher );
}
void SSL_Cipher::setIVec( unsigned char *ivec, unsigned int seed,
void SSL_Cipher::setIVec( unsigned char *ivec, uint64_t seed,
const shared_ptr<SSLKey> &key) const
{
if (iface.current() >= 3)
{
memcpy( ivec, IVData(key), _ivLength );
unsigned char md[EVP_MAX_MD_SIZE];
unsigned int mdLen = EVP_MAX_MD_SIZE;
for(int i=0; i<8; ++i)
{
md[i] = (unsigned char)(seed & 0xff);
seed >>= 8;
}
// combine ivec and seed with HMAC
HMAC_Init_ex( &key->mac_ctx, 0, 0, 0, 0 );
HMAC_Update( &key->mac_ctx, ivec, _ivLength );
HMAC_Update( &key->mac_ctx, md, 8 );
HMAC_Final( &key->mac_ctx, md, &mdLen );
rAssert(mdLen >= _ivLength);
memcpy( ivec, md, _ivLength );
} else
{
setIVec_old(ivec, seed, key);
}
}
/** For backward compatibility.
A watermark attack was discovered against this IV setup. If an attacker
could get a victim to store a carefully crafted file, they could later
determine if the victim had the file in encrypted storage (without
decrypting the file).
*/
void SSL_Cipher::setIVec_old(unsigned char *ivec,
unsigned int seed,
const shared_ptr<SSLKey> &key) const
{
/* These multiplication constants chosen as they represent (non optimal)
Golumb rulers, the idea being to spread around the information in the

View File

@ -137,8 +137,12 @@ public:
// hack to help with static builds
static bool Enabled();
private:
void setIVec( unsigned char *ivec, unsigned int seed,
void setIVec( unsigned char *ivec, uint64_t seed,
const shared_ptr<SSLKey> &key ) const;
// deprecated - for backward compatibility
void setIVec_old( unsigned char *ivec, unsigned int seed,
const shared_ptr<SSLKey> &key ) const;
};

View File

@ -25,6 +25,8 @@
#include "Cipher.h"
#include "Context.h"
#include "FileNode.h"
#include "DirNode.h"
#include <rlog/rlog.h>
#include <rlog/StdioNode.h>
@ -174,8 +176,8 @@ static int showInfo( int argc, char **argv )
if( !checkDir( rootDir ))
return EXIT_FAILURE;
EncFSConfig config;
ConfigType type = readConfig( rootDir, &config );
boost::shared_ptr<EncFSConfig> config(new EncFSConfig);
ConfigType type = readConfig( rootDir, config );
// show information stored in config..
switch(type)
@ -192,24 +194,24 @@ static int showInfo( int argc, char **argv )
case Config_V3:
// xgroup(diag)
cout << "\n" << autosprintf(_("Version 3 configuration; "
"created by %s\n"), config.creator.c_str());
"created by %s\n"), config->creator.c_str());
break;
case Config_V4:
// xgroup(diag)
cout << "\n" << autosprintf(_("Version 4 configuration; "
"created by %s\n"), config.creator.c_str());
"created by %s\n"), config->creator.c_str());
break;
case Config_V5:
// xgroup(diag)
cout << "\n" << autosprintf(_("Version 5 configuration; "
"created by %s (revision %i)\n"), config.creator.c_str(),
config.subVersion);
"created by %s (revision %i)\n"), config->creator.c_str(),
config->subVersion);
break;
case Config_V6:
// xgroup(diag)
cout << "\n" << autosprintf(_("Version 6 configuration; "
"created by %s (revision %i)\n"), config.creator.c_str(),
config.subVersion);
"created by %s (revision %i)\n"), config->creator.c_str(),
config->subVersion);
break;
}
@ -698,8 +700,8 @@ static int do_chpasswd( bool useStdin, int argc, char **argv )
if( !checkDir( rootDir ))
return EXIT_FAILURE;
EncFSConfig config;
ConfigType cfgType = readConfig( rootDir, &config );
boost::shared_ptr<EncFSConfig> config(new EncFSConfig);
ConfigType cfgType = readConfig( rootDir, config );
if(cfgType == Config_None)
{
@ -709,23 +711,23 @@ static int do_chpasswd( bool useStdin, int argc, char **argv )
// instanciate proper cipher
shared_ptr<Cipher> cipher = Cipher::New(
config.cipherIface, config.keySize );
config->cipherIface, config->keySize );
if(!cipher)
{
cout << autosprintf(_("Unable to find specified cipher \"%s\"\n"),
config.cipherIface.name().c_str());
config->cipherIface.name().c_str());
return EXIT_FAILURE;
}
// ask for existing password
cout << _("Enter current Encfs password\n");
CipherKey userKey = config.getUserKey( useStdin );
CipherKey userKey = config->getUserKey( useStdin );
if(!userKey)
return EXIT_FAILURE;
// decode volume key using user key -- at this point we detect an incorrect
// password if the key checksum does not match (causing readKey to fail).
CipherKey volumeKey = cipher->readKey( config.getKeyData(), userKey );
CipherKey volumeKey = cipher->readKey( config->getKeyData(), userKey );
if(!volumeKey)
{
@ -737,12 +739,12 @@ static int do_chpasswd( bool useStdin, int argc, char **argv )
userKey.reset();
cout << _("Enter new Encfs password\n");
// reinitialize salt and iteration count
config.kdfIterations = 0; // generate new
config->kdfIterations = 0; // generate new
if( useStdin )
userKey = config.getUserKey( true );
userKey = config->getUserKey( true );
else
userKey = config.getNewUserKey();
userKey = config->getNewUserKey();
// re-encode the volume key using the new user key and write it out..
int result = EXIT_FAILURE;
@ -755,10 +757,10 @@ static int do_chpasswd( bool useStdin, int argc, char **argv )
cipher->writeKey( volumeKey, keyBuf, userKey );
userKey.reset();
config.assignKeyData( keyBuf, encodedKeySize );
config->assignKeyData( keyBuf, encodedKeySize );
delete[] keyBuf;
if(saveConfig( cfgType, rootDir, &config ))
if(saveConfig( cfgType, rootDir, config ))
{
// password modified -- changes volume key of filesystem..
cout << _("Volume Key successfully updated.\n");

View File

@ -257,23 +257,24 @@ bool runTests(const shared_ptr<Cipher> &cipher, bool verbose)
}
}
shared_ptr<DirNode::Config> dnConfig( new DirNode::Config );
dnConfig->cipher = cipher;
dnConfig->key = key;
dnConfig->blockSize = FSBlockSize;
FSConfigPtr fsCfg = FSConfigPtr(new FSConfig);
fsCfg->cipher = cipher;
fsCfg->key = key;
fsCfg->config.reset(new EncFSConfig);
fsCfg->config->blockSize = FSBlockSize;
if(verbose)
cerr << "Testing name encode/decode (stream coding w/ IV chaining)\n";
{
dnConfig->inactivityTimer = false;
dnConfig->blockMACBytes = 0;
dnConfig->blockMACRandBytes = 0;
dnConfig->uniqueIV = false;
dnConfig->nameCoding = shared_ptr<NameIO>( new StreamNameIO(
StreamNameIO::CurrentInterface(), cipher, key ) );
dnConfig->nameCoding->setChainedNameIV( true );
fsCfg->opts.reset(new EncFS_Opts);
fsCfg->opts->idleTracking = false;
fsCfg->config->uniqueIV = false;
DirNode dirNode( NULL, TEST_ROOTDIR, dnConfig );
fsCfg->nameCoding.reset( new StreamNameIO(
StreamNameIO::CurrentInterface(), cipher, key ) );
fsCfg->nameCoding->setChainedNameIV( true );
DirNode dirNode( NULL, TEST_ROOTDIR, fsCfg );
if(!testNameCoding( dirNode, verbose ))
return false;
@ -282,16 +283,14 @@ bool runTests(const shared_ptr<Cipher> &cipher, bool verbose)
if(verbose)
cerr << "Testing name encode/decode (block coding w/ IV chaining)\n";
{
dnConfig->inactivityTimer = false;
dnConfig->blockMACBytes = 0;
dnConfig->blockMACRandBytes = 0;
dnConfig->uniqueIV = false;
dnConfig->nameCoding = shared_ptr<NameIO>( new BlockNameIO(
fsCfg->opts->idleTracking = false;
fsCfg->config->uniqueIV = false;
fsCfg->nameCoding.reset( new BlockNameIO(
BlockNameIO::CurrentInterface(), cipher, key,
cipher->cipherBlockSize() ) );
dnConfig->nameCoding->setChainedNameIV( true );
fsCfg->nameCoding->setChainedNameIV( true );
DirNode dirNode( NULL, TEST_ROOTDIR, dnConfig );
DirNode dirNode( NULL, TEST_ROOTDIR, fsCfg );
if(!testNameCoding( dirNode, verbose ))
return false;
@ -301,16 +300,12 @@ bool runTests(const shared_ptr<Cipher> &cipher, bool verbose)
{
{
// test stream mode, this time without IV chaining
dnConfig->inactivityTimer = false;
dnConfig->blockMACBytes = 0;
dnConfig->blockMACRandBytes = 0;
dnConfig->uniqueIV = false;
dnConfig->nameCoding =
fsCfg->nameCoding =
shared_ptr<NameIO>( new StreamNameIO(
StreamNameIO::CurrentInterface(), cipher, key ) );
dnConfig->nameCoding->setChainedNameIV( false );
fsCfg->nameCoding->setChainedNameIV( false );
DirNode dirNode( NULL, TEST_ROOTDIR, dnConfig );
DirNode dirNode( NULL, TEST_ROOTDIR, fsCfg );
if(!testNameCoding( dirNode, verbose ))
return false;
@ -318,16 +313,12 @@ bool runTests(const shared_ptr<Cipher> &cipher, bool verbose)
{
// test block mode, this time without IV chaining
dnConfig->inactivityTimer = false;
dnConfig->blockMACBytes = 0;
dnConfig->blockMACRandBytes = 0;
dnConfig->uniqueIV = false;
dnConfig->nameCoding = shared_ptr<NameIO>( new BlockNameIO(
fsCfg->nameCoding = shared_ptr<NameIO>( new BlockNameIO(
BlockNameIO::CurrentInterface(), cipher, key,
cipher->cipherBlockSize() ) );
dnConfig->nameCoding->setChainedNameIV( false );
fsCfg->nameCoding->setChainedNameIV( false );
DirNode dirNode( NULL, TEST_ROOTDIR, dnConfig );
DirNode dirNode( NULL, TEST_ROOTDIR, fsCfg );
if(!testNameCoding( dirNode, verbose ))
return false;

View File

@ -1,9 +1,8 @@
EXTRA_DIST = \
codeset.m4 inttypes_h.m4 lib-link.m4 printf-posix.m4 \
ulonglong.m4 gettext.m4 inttypes.m4 lib-prefix.m4 \
progtest.m4 wchar_t.m4 glibc21.m4 inttypes-pri.m4 \
longdouble.m4 signed.m4 wint_t.m4 iconv.m4 isc-posix.m4 \
longlong.m4 size_max.m4 xsize.m4 intdiv0.m4 lcmessage.m4 \
nls.m4 stdint_h.m4 intmax.m4 lib-ld.m4 po.m4 uintmax_t.m4 \
acx_pthread.m4
acx_pthread.m4 intl.m4 lib-ld.m4 ltsugar.m4 size_max.m4 \
codeset.m4 intldir.m4 lib-link.m4 ltversion.m4 stdint_h.m4 \
gettext.m4 intlmacosx.m4 lib-prefix.m4 lt~obsolete.m4 uintmax_t.m4 \
glibc2.m4 intmax.m4 libtool.m4 nls.m4 visibility.m4 \
glibc21.m4 inttypes-pri.m4 lock.m4 po.m4 wchar_t.m4 \
iconv.m4 inttypes_h.m4 longlong.m4 printf-posix.m4 wint_t.m4 \
intdiv0.m4 lcmessage.m4 ltoptions.m4 progtest.m4 xsize.m4

View File

@ -4,7 +4,7 @@
make dist
# create tar archive and signature
tarArchive=@PACKAGE@-@VERSION@-@RELEASE@.tgz
tarArchive=@PACKAGE@-@VERSION@.tgz
mv @PACKAGE@-@VERSION@.tar.gz $tarArchive
# let the user know why they're being asked for a passpharse
echo "Signing tar archive - enter GPG password";