Replace boost::serialization.

Boost::serialization and the corresponding internal configuration structure are
replace with a protocol buffer message.

Dropped support for writing old configuration files. Only the new format can be
written. A password change will write a newly formatted configuration file, but
does not delete the old file.

Version bumped to 1.8


git-svn-id: http://encfs.googlecode.com/svn/trunk@80 db9cf616-1c43-0410-9cb8-a902689de0d6
This commit is contained in:
Valient Gough 2012-04-26 02:34:15 +00:00
parent 67821fb209
commit 67c72dfe99
40 changed files with 1028 additions and 960 deletions

View File

@ -1,3 +1,31 @@
Thu Mar 22 2012 Valient Gough <vgough@pobox.com>
* skip name collision test
* bump version to 1.8.0
* drop boost serialization from requirements
Sun Mar 4 2012 Valient Gough <vgough@pobox.com>
* bump ld version
* replace EncFSConfig with protocol buffer
Fri Mar 2 2012 Valient Gough <vgough@pobox.com>
* replace boost serialization with protocol buffer support
Wed Feb 29 2012 Valient Gough <vgough@pobox.com>
* switch to OpenSSL B64 decode to be comptible with boost serialization
* implement v6 config reader using XML reader based on tinyxml
Mon Jan 2 2012 Valient Gough <vgough@pobox.com>
* test for name case collisions in b64 coding
Thu Dec 29 2011 Valient Gough <vgough@pobox.com>
* add base32 support for name encoding
Thu Mar 3 2011 Valient Gough <vgough@pobox.com>
* update copyright on BlockNameIO
Thu Dec 29 2011 Valient Gough <vgough@pobox.com>
* revert fuse_unmount change, wasn't working
Wed Dec 28 2011 Valient Gough <vgough@pobox.com> Wed Dec 28 2011 Valient Gough <vgough@pobox.com>
* remove m4-local * remove m4-local
* bump version to 1.7.5 * bump version to 1.7.5

View File

@ -2,7 +2,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 AC_INIT(encfs/encfs.h) dnl a source file from your sub dir
AC_CONFIG_AUX_DIR([build-aux]) AC_CONFIG_AUX_DIR([build-aux])
AM_INIT_AUTOMAKE(encfs, 1.7.5) dnl searches for some needed programs AM_INIT_AUTOMAKE(encfs, 1.8.0) dnl searches for some needed programs
AC_CONFIG_MACRO_DIR([m4]) AC_CONFIG_MACRO_DIR([m4])
AC_CANONICAL_HOST AC_CANONICAL_HOST
@ -48,7 +48,6 @@ AX_PTHREAD
AX_BOOST_BASE([1.34]) AX_BOOST_BASE([1.34])
AX_BOOST_SYSTEM AX_BOOST_SYSTEM
AX_BOOST_SERIALIZATION
AX_BOOST_FILESYSTEM AX_BOOST_FILESYSTEM
dnl Need to include any user specified flags in the tests below, as they might dnl Need to include any user specified flags in the tests below, as they might
@ -203,6 +202,21 @@ if test "$with_rlog" = "test" && test "x$RLOG_LIBS" = "x"; then
[AC_MSG_ERROR([EncFS depends on librlog])]) [AC_MSG_ERROR([EncFS depends on librlog])])
fi fi
# find Protocol Buffers
PKG_CHECK_MODULES(PROTOBUF, protobuf >= 2.0)
AC_PATH_PROG(PROTOC, protoc, [no])
if test "$PROTOC" == "no"; then
AC_MSG_FAILURE([Protocol Buffers compiler 'protoc' is required to build.])
fi
# find TinyXML
AC_LANG_PUSH([C++])
CPPFLAGS="$CPPFLAGS -DTIXML_USE_STL"
AC_CHECK_HEADER([tinyxml.h],,[AC_MSG_ERROR([tinyxml.h not found])])
AC_CHECK_LIB([tinyxml],[main],,
[AC_MSG_ERROR([you must install libtinyxml dev])])
AC_LANG_POP([C++])
# look for pod2man program for building man pages # look for pod2man program for building man pages
AC_PATH_PROG(POD2MAN, pod2man, [no]) AC_PATH_PROG(POD2MAN, pod2man, [no])
AC_PATH_PROG(POD2HTML, pod2html, [no]) AC_PATH_PROG(POD2HTML, pod2html, [no])

View File

@ -18,6 +18,7 @@
#include "BlockFileIO.h" #include "BlockFileIO.h"
#include "MemoryPool.h" #include "MemoryPool.h"
#include "config.pb.h"
#include <cstring> #include <cstring>
#include <rlog/rlog.h> #include <rlog/rlog.h>
@ -38,7 +39,7 @@ static void clearCache( IORequest &req, int blockSize )
BlockFileIO::BlockFileIO( int blockSize, const FSConfigPtr &cfg ) BlockFileIO::BlockFileIO( int blockSize, const FSConfigPtr &cfg )
: _blockSize( blockSize ) : _blockSize( blockSize )
, _allowHoles( cfg->config->allowHoles ) , _allowHoles( cfg->config->allow_holes() )
{ {
rAssert( _blockSize > 1 ); rAssert( _blockSize > 1 );
_cache.data = new unsigned char [ _blockSize ]; _cache.data = new unsigned char [ _blockSize ];

View File

@ -31,7 +31,6 @@
#include "i18n.h" #include "i18n.h"
using namespace rlog; using namespace rlog;
using namespace rel;
using namespace boost; using namespace boost;
static RLogChannel * Info = DEF_CHANNEL( "info/nameio", Log_Info ); static RLogChannel * Info = DEF_CHANNEL( "info/nameio", Log_Info );
@ -94,16 +93,16 @@ Interface BlockNameIO::CurrentInterface(bool caseSensitive)
{ {
// implement major version 4 plus support for two prior versions // implement major version 4 plus support for two prior versions
if (caseSensitive) if (caseSensitive)
return Interface("nameio/block32", 4, 0, 2); return makeInterface("nameio/block32", 4, 0, 2);
else else
return Interface("nameio/block", 4, 0, 2); return makeInterface("nameio/block", 4, 0, 2);
} }
BlockNameIO::BlockNameIO( const rel::Interface &iface, BlockNameIO::BlockNameIO( const Interface &iface,
const shared_ptr<Cipher> &cipher, const shared_ptr<Cipher> &cipher,
const CipherKey &key, int blockSize, const CipherKey &key, int blockSize,
bool caseSensitiveEncoding ) bool caseSensitiveEncoding )
: _interface( iface.current() ) : _interface( iface.major() )
, _bs( blockSize ) , _bs( blockSize )
, _cipher( cipher ) , _cipher( cipher )
, _key( key ) , _key( key )

View File

@ -33,15 +33,15 @@ class Cipher;
class BlockNameIO : public NameIO class BlockNameIO : public NameIO
{ {
public: public:
static rel::Interface CurrentInterface(bool caseSensitive = false); static Interface CurrentInterface(bool caseSensitive = false);
BlockNameIO( const rel::Interface &iface, BlockNameIO( const Interface &iface,
const boost::shared_ptr<Cipher> &cipher, const boost::shared_ptr<Cipher> &cipher,
const CipherKey &key, int blockSize, const CipherKey &key, int blockSize,
bool caseSensitiveEncoding = false ); bool caseSensitiveEncoding = false );
virtual ~BlockNameIO(); virtual ~BlockNameIO();
virtual rel::Interface interface() const; virtual Interface interface() const;
virtual int maxEncodedNameLen( int plaintextNameLen ) const; virtual int maxEncodedNameLen( int plaintextNameLen ) const;
virtual int maxDecodedNameLen( int encodedNameLen ) const; virtual int maxDecodedNameLen( int encodedNameLen ) const;

View File

@ -34,7 +34,6 @@
#include "SSL_Cipher.h" #include "SSL_Cipher.h"
using namespace std; using namespace std;
using namespace rel;
using boost::shared_ptr; using boost::shared_ptr;
#define REF_MODULE(TYPE) \ #define REF_MODULE(TYPE) \
@ -150,7 +149,7 @@ shared_ptr<Cipher> Cipher::New( const Interface &iface, int keyLen )
for(it = gCipherMap->begin(); it != mapEnd; ++it) for(it = gCipherMap->begin(); it != mapEnd; ++it)
{ {
// TODO: we should look for the newest implementation.. // TODO: we should look for the newest implementation..
if( it->second.iface.implements( iface ) ) if( implements(it->second.iface, iface) )
{ {
CipherConstructor fn = it->second.constructor; CipherConstructor fn = it->second.constructor;
// pass in requested interface.. // pass in requested interface..

View File

@ -42,14 +42,14 @@ class Cipher
public: public:
// if no key length was indicated when cipher was registered, then keyLen // if no key length was indicated when cipher was registered, then keyLen
// <= 0 will be used. // <= 0 will be used.
typedef boost::shared_ptr<Cipher> (*CipherConstructor)( const rel::Interface &iface, typedef boost::shared_ptr<Cipher> (*CipherConstructor)( const Interface &iface,
int keyLenBits ); int keyLenBits );
struct CipherAlgorithm struct CipherAlgorithm
{ {
std::string name; std::string name;
std::string description; std::string description;
rel::Interface iface; Interface iface;
Range keyLength; Range keyLength;
Range blockSize; Range blockSize;
}; };
@ -59,7 +59,7 @@ public:
static AlgorithmList GetAlgorithmList( bool includeHidden = false ); static AlgorithmList GetAlgorithmList( bool includeHidden = false );
static boost::shared_ptr<Cipher> New( const rel::Interface &iface, static boost::shared_ptr<Cipher> New( const Interface &iface,
int keyLen = -1); int keyLen = -1);
static boost::shared_ptr<Cipher> New( const std::string &cipherName, static boost::shared_ptr<Cipher> New( const std::string &cipherName,
int keyLen = -1 ); int keyLen = -1 );
@ -67,12 +67,12 @@ public:
static bool Register(const char *cipherName, static bool Register(const char *cipherName,
const char *description, const char *description,
const rel::Interface &iface, const Interface &iface,
CipherConstructor constructor, CipherConstructor constructor,
bool hidden = false); bool hidden = false);
static bool Register(const char *cipherName, static bool Register(const char *cipherName,
const char *description, const char *description,
const rel::Interface &iface, const Interface &iface,
const Range &keyLength, const Range &blockSize, const Range &keyLength, const Range &blockSize,
CipherConstructor constructor, CipherConstructor constructor,
bool hidden = false); bool hidden = false);
@ -81,7 +81,7 @@ public:
Cipher(); Cipher();
virtual ~Cipher(); virtual ~Cipher();
virtual rel::Interface interface() const =0; virtual Interface interface() const =0;
// create a new key based on a password // create a new key based on a password
// if iterationCount == 0, then iteration count will be determined // if iterationCount == 0, then iteration count will be determined

View File

@ -19,6 +19,7 @@
#include "Cipher.h" #include "Cipher.h"
#include "MemoryPool.h" #include "MemoryPool.h"
#include "config.pb.h"
#include <rlog/rlog.h> #include <rlog/rlog.h>
#include <rlog/Error.h> #include <rlog/Error.h>
@ -34,7 +35,7 @@ using boost::shared_ptr;
filesystem at the filesystem configuration level. filesystem at the filesystem configuration level.
When headers are disabled, 2:0 is compatible with version 1:0. When headers are disabled, 2:0 is compatible with version 1:0.
*/ */
static rel::Interface CipherFileIO_iface("FileIO/Cipher", 2, 0, 1); static Interface CipherFileIO_iface = makeInterface("FileIO/Cipher", 2, 0, 1);
const int HEADER_SIZE = 8; // 64 bit initialization vector.. const int HEADER_SIZE = 8; // 64 bit initialization vector..
@ -51,9 +52,9 @@ static bool checkSize( int fsBlockSize, int cipherBlockSize )
CipherFileIO::CipherFileIO( const shared_ptr<FileIO> &_base, CipherFileIO::CipherFileIO( const shared_ptr<FileIO> &_base,
const FSConfigPtr &cfg) const FSConfigPtr &cfg)
: BlockFileIO( cfg->config->blockSize, cfg ) : BlockFileIO( cfg->config->block_size(), cfg )
, base( _base ) , base( _base )
, haveHeader( cfg->config->uniqueIV ) , haveHeader( cfg->config->unique_iv() )
, externalIV( 0 ) , externalIV( 0 )
, fileIV( 0 ) , fileIV( 0 )
, lastFlags( 0 ) , lastFlags( 0 )
@ -65,7 +66,7 @@ CipherFileIO::CipherFileIO( const shared_ptr<FileIO> &_base,
static bool warnOnce = false; static bool warnOnce = false;
if(!warnOnce) if(!warnOnce)
warnOnce = checkSize( fsConfig->config->blockSize, warnOnce = checkSize( fsConfig->config->block_size(),
fsConfig->cipher->cipherBlockSize() ); fsConfig->cipher->cipherBlockSize() );
} }
@ -73,7 +74,7 @@ CipherFileIO::~CipherFileIO()
{ {
} }
rel::Interface CipherFileIO::interface() const Interface CipherFileIO::interface() const
{ {
return CipherFileIO_iface; return CipherFileIO_iface;
} }

View File

@ -38,7 +38,7 @@ public:
const FSConfigPtr &cfg); const FSConfigPtr &cfg);
virtual ~CipherFileIO(); virtual ~CipherFileIO();
virtual rel::Interface interface() const; virtual Interface interface() const;
virtual void setFileName( const char *fileName ); virtual void setFileName( const char *fileName );
virtual const char *getFileName() const; virtual const char *getFileName() const;

View File

@ -690,7 +690,7 @@ int DirNode::link( const char *from, const char *to )
rLog(Info, "link %s -> %s", fromCName.c_str(), toCName.c_str()); rLog(Info, "link %s -> %s", fromCName.c_str(), toCName.c_str());
int res = -EPERM; int res = -EPERM;
if( fsConfig->config->externalIVChaining ) if( fsConfig->config->external_iv() )
{ {
rLog(Info, "hard links not supported with external IV chaining!"); rLog(Info, "hard links not supported with external IV chaining!");
} else } else
@ -756,7 +756,7 @@ shared_ptr<FileNode> DirNode::findOrCreate( const char *plainName)
plainName, plainName,
(rootDir + cipherName).c_str())); (rootDir + cipherName).c_str()));
if(fsConfig->config->externalIVChaining) if(fsConfig->config->external_iv())
node->setName(0, 0, iv); node->setName(0, 0, iv);
rLog(Info, "created FileNode for %s", node->cipherName()); rLog(Info, "created FileNode for %s", node->cipherName());

View File

@ -32,88 +32,37 @@ enum ConfigType
{ {
Config_None = 0, Config_None = 0,
Config_Prehistoric, Config_Prehistoric,
Config_V3, Config_V3 = 3,
Config_V4, Config_V4 = 4,
Config_V5, Config_V5 = 5,
Config_V6 Config_V6 = 6,
Config_V7 = 7
}; };
class EncFS_Opts; class EncFS_Opts;
class Cipher; class Cipher;
class NameIO; class NameIO;
class EncfsConfig;
struct EncFSConfig CipherKey getUserKey(const EncfsConfig &config, bool useStdin);
{ CipherKey getUserKey(const EncfsConfig &config,
ConfigType cfgType; const std::string &passwordProgram,
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); const std::string &rootDir);
CipherKey getNewUserKey();
boost::shared_ptr<Cipher> getCipher() const; CipherKey getNewUserKey(EncfsConfig &config, bool useStdin,
const std::string &program, const std::string &rootDir);
// deprecated boost::shared_ptr<Cipher> getCipher(const EncfsConfig &cfg);
void assignKeyData(const std::string &in); boost::shared_ptr<Cipher> getCipher(const Interface &iface, int keySize);
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 // helpers for serializing to/from a stream
std::ostream &operator << (std::ostream &os, const EncFSConfig &cfg); std::ostream &operator << (std::ostream &os, const EncfsConfig &cfg);
std::istream &operator >> (std::istream &os, EncFSConfig &cfg); std::istream &operator >> (std::istream &os, EncfsConfig &cfg);
// Filesystem state
struct FSConfig struct FSConfig
{ {
boost::shared_ptr<EncFSConfig> config; boost::shared_ptr<EncfsConfig> config;
boost::shared_ptr<EncFS_Opts> opts; boost::shared_ptr<EncFS_Opts> opts;
boost::shared_ptr<Cipher> cipher; boost::shared_ptr<Cipher> cipher;

View File

@ -48,7 +48,7 @@ public:
FileIO(); FileIO();
virtual ~FileIO(); virtual ~FileIO();
virtual rel::Interface interface() const =0; virtual Interface interface() const =0;
// default implementation returns 1, meaning this is not block oriented. // default implementation returns 1, meaning this is not block oriented.
virtual int blockSize() const; virtual int blockSize() const;

View File

@ -80,7 +80,7 @@ FileNode::FileNode(DirNode *parent_, const FSConfigPtr &cfg,
shared_ptr<FileIO> rawIO( new RawFileIO( _cname ) ); shared_ptr<FileIO> rawIO( new RawFileIO( _cname ) );
io = shared_ptr<FileIO>( new CipherFileIO( rawIO, fsConfig )); io = shared_ptr<FileIO>( new CipherFileIO( rawIO, fsConfig ));
if(cfg->config->blockMACBytes || cfg->config->blockMACRandBytes) if(cfg->config->block_mac_bytes() || cfg->config->block_mac_rand_bytes())
io = shared_ptr<FileIO>(new MACFileIO(io, fsConfig)); io = shared_ptr<FileIO>(new MACFileIO(io, fsConfig));
} }
@ -127,7 +127,7 @@ bool FileNode::setName( const char *plaintextName_, const char *cipherName_,
rDebug("calling setIV on %s", cipherName_); rDebug("calling setIV on %s", cipherName_);
if(setIVFirst) if(setIVFirst)
{ {
if(fsConfig->config->externalIVChaining && !setIV(io, iv)) if(fsConfig->config->external_iv() && !setIV(io, iv))
return false; return false;
// now change the name.. // now change the name..
@ -151,7 +151,7 @@ bool FileNode::setName( const char *plaintextName_, const char *cipherName_,
io->setFileName( cipherName_ ); io->setFileName( cipherName_ );
} }
if(fsConfig->config->externalIVChaining && !setIV(io, iv)) if(fsConfig->config->external_iv() && !setIV(io, iv))
{ {
_pname = oldPName; _pname = oldPName;
_cname = oldCName; _cname = oldCName;

File diff suppressed because it is too large Load Diff

View File

@ -99,41 +99,33 @@ struct EncFS_Opts
/* /*
Read existing config file. Looks for any supported configuration version. Read existing config file. Looks for any supported configuration version.
*/ */
ConfigType readConfig( const std::string &rootDir, ConfigType readConfig( const std::string &rootDir, EncfsConfig &config );
const boost::shared_ptr<EncFSConfig> &config );
/* /*
Save the configuration. Saves back as the same configuration type as was Save the configuration. Saves back as the same configuration type as was
read from. read from.
*/ */
bool saveConfig( ConfigType type, const std::string &rootdir, bool saveConfig( const std::string &rootdir, const EncfsConfig &config );
const boost::shared_ptr<EncFSConfig> &config );
class EncFS_Context; class EncFS_Context;
RootPtr initFS( EncFS_Context *ctx, const boost::shared_ptr<EncFS_Opts> &opts ); RootPtr initFS( EncFS_Context *ctx, const boost::shared_ptr<EncFS_Opts> &opts );
RootPtr createV6Config( EncFS_Context *ctx, RootPtr createConfig( EncFS_Context *ctx,
const boost::shared_ptr<EncFS_Opts> &opts ); const boost::shared_ptr<EncFS_Opts> &opts );
void showFSInfo( const boost::shared_ptr<EncFSConfig> &config ); void showFSInfo( const EncfsConfig &config );
bool readV4Config( const char *configFile, bool readV4Config( const char *configFile, EncfsConfig &config,
const boost::shared_ptr<EncFSConfig> &config,
struct ConfigInfo *); struct ConfigInfo *);
bool writeV4Config( const char *configFile,
const boost::shared_ptr<EncFSConfig> &config);
bool readV5Config( const char *configFile, bool readV5Config( const char *configFile, EncfsConfig &config,
const boost::shared_ptr<EncFSConfig> &config,
struct ConfigInfo *); struct ConfigInfo *);
bool writeV5Config( const char *configFile,
const boost::shared_ptr<EncFSConfig> &config);
bool readV6Config( const char *configFile, bool readV6Config( const char *configFile, EncfsConfig &config,
const boost::shared_ptr<EncFSConfig> &config, struct ConfigInfo *);
bool readProtoConfig( const char *configFile, EncfsConfig &config,
struct ConfigInfo *); struct ConfigInfo *);
bool writeV6Config( const char *configFile,
const boost::shared_ptr<EncFSConfig> &config);
#endif #endif

View File

@ -22,205 +22,69 @@
#include <rlog/rlog.h> #include <rlog/rlog.h>
#include <rlog/RLogChannel.h> #include <rlog/RLogChannel.h>
using namespace rel;
using namespace rlog; using namespace rlog;
static RLogChannel * Info = DEF_CHANNEL( "info/iface", Log_Info ); static RLogChannel * Info = DEF_CHANNEL( "info/iface", Log_Info );
Interface::Interface(const char *name_, int Current, int Revision, int Age) bool implements(const Interface &A, const Interface &B)
: _name( name_ )
, _current( Current )
, _revision( Revision )
, _age( Age )
{
}
Interface::Interface(const std::string &name_, int Current,
int Revision, int Age)
: _name( name_ )
, _current( Current )
, _revision( Revision )
, _age( Age )
{
}
Interface::Interface(const Interface &src)
: _name( src._name )
, _current( src._current )
, _revision( src._revision )
, _age( src._age )
{
}
Interface::Interface()
: _current( 0 )
, _revision( 0 )
, _age( 0 )
{
}
Interface &Interface::operator = (const Interface &src)
{
_name = src._name;
_current = src._current;
_revision = src._revision;
_age = src._age;
return *this;
}
const std::string & Interface::name() const
{
return _name;
}
std::string & Interface::name()
{
return _name;
}
int Interface::current() const
{
return _current;
}
int &Interface::current()
{
return _current;
}
int Interface::revision() const
{
return _revision;
}
int &Interface::revision()
{
return _revision;
}
int Interface::age() const
{
return _age;
}
int &Interface::age()
{
return _age;
}
bool operator == (const Interface &A, const Interface &B)
{
return ( A.name() == B.name()
&& A.current() == B.current()
&& A.revision() == B.revision()
&& A.age() == B.age() );
}
bool operator != (const Interface &A, const Interface &B)
{
return ( A.name() != B.name()
|| A.current() != B.current()
|| A.revision() != B.revision()
|| A.age() != B.age() );
}
// zero branch method of getting comparison sign..
// tricky.. makes assumptions
#if 0
static int sign( int a, int b )
{
unsigned int ab = ((unsigned int)(a - b)) >> 31;
unsigned int ba = ((unsigned int)(b - a)) >> 31;
return 1 + ba - ab;
}
#else
// simple, easy to check, unlikely to break due to unforseen events..
static int sign( int a, int b )
{
if(a < b)
return 0;
else if(a == b)
return 1;
else
return 2;
}
#endif
static int diffSum( const Interface &A, const Interface &B )
{
int cS = sign( A.current() , B.current() );
int aS = sign( A.age(), B.age() );
int rS = sign( A.revision(), B.revision() );
return (cS * 3 + aS) * 3 + rS;
}
const int EqualVersion = (1 * 3 + 1) * 3 + 1;
bool Interface::implements(const Interface &B) const
{ {
rLog(Info, "checking if %s(%i:%i:%i) implements %s(%i:%i:%i)", rLog(Info, "checking if %s(%i:%i:%i) implements %s(%i:%i:%i)",
name().c_str(), current(), revision(), age(), A.name().c_str(), A.major(), A.minor(), A.age(),
B.name().c_str(), B.current(), B.revision(), B.age()); B.name().c_str(), B.major(), B.minor(), B.age());
if( name() != B.name() ) if( A.name() != B.name() )
return false; return false;
int currentDiff = current() - B.current(); int currentDiff = A.major() - B.major();
return ( currentDiff >= 0 && currentDiff <= age() ); return ( currentDiff >= 0 && currentDiff <= (int)A.age() );
} }
Interface makeInterface(const char *name, int major, int minor, int age)
bool operator < (const Interface &A, const Interface &B)
{ {
if( A.name() == B.name() ) Interface iface;
{ iface.set_name(name);
return ( diffSum(A,B) < EqualVersion ); iface.set_major(major);
} else iface.set_minor(minor);
return A.name() < B.name(); iface.set_age(age);
return iface;
} }
bool operator > (const Interface &A, const Interface &B) ConfigVar & operator << (ConfigVar &dst, const Interface &iface)
{ {
if( A.name() == B.name() ) dst << iface.name() << (int)iface.major() << (int)iface.minor() << (int)iface.age();
{
return ( diffSum(A,B) > EqualVersion );
} else
return A.name() < B.name();
}
bool operator <= (const Interface &A, const Interface &B)
{
if( A.name() == B.name() )
{
return ( diffSum(A,B) <= EqualVersion );
} else
return A.name() < B.name();
}
bool operator >= (const Interface &A, const Interface &B)
{
if( A.name() == B.name() )
{
return ( diffSum(A,B) >= EqualVersion );
} else
return A.name() < B.name();
}
ConfigVar & operator << (ConfigVar &dst, const rel::Interface &iface)
{
dst << iface.name() << iface.current() << iface.revision() << iface.age();
return dst; return dst;
} }
const ConfigVar & operator >> (const ConfigVar &src, Interface &iface) const ConfigVar & operator >> (const ConfigVar &src, Interface &iface)
{ {
src >> iface.name(); src >> *iface.mutable_name();
src >> iface.current(); int major, minor, age;
src >> iface.revision(); src >> major >> minor >> age;
src >> iface.age(); iface.set_major(major);
iface.set_minor(minor);
iface.set_age(age);
return src; return src;
} }
const XmlValuePtr & operator >> (const XmlValuePtr &src, Interface &iface)
{
(*src)["name"] >> *iface.mutable_name();
int major, minor;
(*src)["major"] >> major;
(*src)["minor"] >> minor;
iface.set_major(major);
iface.set_minor(minor);
return src;
}
bool operator != (const Interface &a, const Interface &b)
{
if (a.major() != b.major())
return true;
if (a.minor() != b.minor())
return true;
return false;
}

View File

@ -19,66 +19,23 @@
#define _Interface_incl_ #define _Interface_incl_
#include <string> #include <string>
#include "XmlReader.h"
#include "config.pb.h"
// check if A implements the interface described by B.
// Note that implements(A, B) is not the same as implements(B, A)
// This checks the current() version and age() against B.current() for
// compatibility. Even if A.implements(B) is true, B > A may also be
// true, meaning B is a newer revision of the interface then A.
bool implements( const Interface &a, const Interface &b );
Interface makeInterface( const char *name, int major, int minor, int age );
// Reae operation
class ConfigVar; class ConfigVar;
const ConfigVar & operator >> (const ConfigVar &, Interface &);
const XmlValuePtr & operator >> (const XmlValuePtr &, Interface &);
// part of REL library.. bool operator != (const Interface &a, const Interface &b);
namespace rel
{
class Interface
{
public:
/*!
Version numbers as described by libtool: info://libtool/versioning
Current - the most recent interface api that is implemented.
Revision - the implementation number of the current interface.
Age - the difference between the newest and oldest interfaces that
are implemented.
*/
Interface( const char *name, int Current, int Revision, int Age );
Interface( const std::string &name, int Current, int Revision, int Age);
Interface(const Interface &src);
Interface();
// check if we implement the interface described by B.
// Note that A.implements(B) is not the same as B.implements(A)
// This checks the current() version and age() against B.current() for
// compatibility. Even if A.implements(B) is true, B > A may also be
// true, meaning B is a newer revision of the interface then A.
bool implements( const Interface &dst ) const;
const std::string &name() const;
int current() const;
int revision() const;
int age() const;
std::string &name();
int &current();
int &revision();
int &age();
Interface &operator = ( const Interface &src );
private:
std::string _name;
int _current;
int _revision;
int _age;
};
}
ConfigVar & operator << (ConfigVar &, const rel::Interface &);
const ConfigVar & operator >> (const ConfigVar &, rel::Interface &);
bool operator < (const rel::Interface &A, const rel::Interface &B);
bool operator > (const rel::Interface &A, const rel::Interface &B);
bool operator <= (const rel::Interface &A, const rel::Interface &B);
bool operator >= (const rel::Interface &A, const rel::Interface &B);
bool operator == (const rel::Interface &A, const rel::Interface &B);
bool operator != (const rel::Interface &A, const rel::Interface &B);
#endif #endif

View File

@ -19,6 +19,7 @@
#include "MemoryPool.h" #include "MemoryPool.h"
#include "FileUtils.h" #include "FileUtils.h"
#include "config.pb.h"
#include <rlog/rlog.h> #include <rlog/rlog.h>
#include <rlog/Error.h> #include <rlog/Error.h>
@ -29,7 +30,6 @@
#include "i18n.h" #include "i18n.h"
using namespace rlog; using namespace rlog;
using namespace rel;
using namespace std; using namespace std;
using boost::shared_ptr; using boost::shared_ptr;
using boost::dynamic_pointer_cast; using boost::dynamic_pointer_cast;
@ -48,13 +48,13 @@ static RLogChannel *Info = DEF_CHANNEL("info/MACFileIO", Log_Info);
// compatible, except at a high level by checking a revision number for the // compatible, except at a high level by checking a revision number for the
// filesystem... // filesystem...
// //
static rel::Interface MACFileIO_iface("FileIO/MAC", 2, 1, 0); static Interface MACFileIO_iface = makeInterface("FileIO/MAC", 2, 1, 0);
int dataBlockSize(const FSConfigPtr &cfg) int dataBlockSize(const FSConfigPtr &cfg)
{ {
return cfg->config->blockSize return cfg->config->block_size()
- cfg->config->blockMACBytes - cfg->config->block_mac_bytes()
- cfg->config->blockMACRandBytes; - cfg->config->block_mac_rand_bytes();
} }
MACFileIO::MACFileIO( const shared_ptr<FileIO> &_base, MACFileIO::MACFileIO( const shared_ptr<FileIO> &_base,
@ -63,23 +63,23 @@ MACFileIO::MACFileIO( const shared_ptr<FileIO> &_base,
, base( _base ) , base( _base )
, cipher( cfg->cipher ) , cipher( cfg->cipher )
, key( cfg->key ) , key( cfg->key )
, macBytes( cfg->config->blockMACBytes ) , macBytes( cfg->config->block_mac_bytes() )
, randBytes( cfg->config->blockMACRandBytes ) , randBytes( cfg->config->block_mac_rand_bytes() )
, warnOnly( cfg->opts->forceDecode ) , warnOnly( cfg->opts->forceDecode )
{ {
rAssert( macBytes >= 0 && macBytes <= 8 ); rAssert( macBytes >= 0 && macBytes <= 8 );
rAssert( randBytes >= 0 ); rAssert( randBytes >= 0 );
rLog(Info, "fs block size = %i, macBytes = %i, randBytes = %i", rLog(Info, "fs block size = %i, macBytes = %i, randBytes = %i",
cfg->config->blockSize, cfg->config->block_size(),
cfg->config->blockMACBytes, cfg->config->block_mac_bytes(),
cfg->config->blockMACRandBytes); cfg->config->block_mac_rand_bytes());
} }
MACFileIO::~MACFileIO() MACFileIO::~MACFileIO()
{ {
} }
rel::Interface MACFileIO::interface() const Interface MACFileIO::interface() const
{ {
return MACFileIO_iface; return MACFileIO_iface;
} }

View File

@ -36,7 +36,7 @@ public:
MACFileIO(); MACFileIO();
virtual ~MACFileIO(); virtual ~MACFileIO();
virtual rel::Interface interface() const; virtual Interface interface() const;
virtual void setFileName( const char *fileName ); virtual void setFileName( const char *fileName );
virtual const char *getFileName() const; virtual const char *getFileName() const;

View File

@ -2,8 +2,10 @@
include $(top_srcdir)/Makefile.common include $(top_srcdir)/Makefile.common
ALL_INCLUDES = @RLOG_CFLAGS@ @OPENSSL_CFLAGS@ @BOOST_CPPFLAGS@ ALL_INCLUDES = @RLOG_CFLAGS@ @OPENSSL_CFLAGS@ @BOOST_CPPFLAGS@
ALL_INCLUDES += @PROTOBUF_CFLAGS@
ALL_LDFLAGS = @RLOG_LIBS@ @OPENSSL_LIBS@ @BOOST_LDFLAGS@ ALL_LDFLAGS = @RLOG_LIBS@ @OPENSSL_LIBS@ @BOOST_LDFLAGS@
ALL_LDFLAGS += @BOOST_SERIALIZATION_LIB@ @BOOST_FILESYSTEM_LIB@ @BOOST_SYSTEM_LIB@ ALL_LDFLAGS += @BOOST_FILESYSTEM_LIB@ @BOOST_SYSTEM_LIB@
ALL_LDFLAGS += @PROTOBUF_LIBS@
INCLUDES = $(all_includes) -I../intl INCLUDES = $(all_includes) -I../intl
@ -47,10 +49,10 @@ endif
# : : 0 => no new interfaces, but breaks old apps # : : 0 => no new interfaces, but breaks old apps
# : +1 : => internal changes, nothing breaks # : +1 : => internal changes, nothing breaks
# #
libencfs_la_LDFLAGS = -version-info 6:2:0 libencfs_la_LDFLAGS = -version-info 7:0:0
libencfs_la_LIBADD = @RLOG_LIBS@ \ libencfs_la_LIBADD = @RLOG_LIBS@ \
@OPENSSL_LIBS@ \ @OPENSSL_LIBS@ \
@BOOST_SERIALIZATION_LIB@ @BOOST_FILESYSTEM_LIB@ @BOOST_SYSTEM_LIB@ @BOOST_FILESYSTEM_LIB@ @BOOST_SYSTEM_LIB@
EXTRASRC = ../intl/autosprintf.cpp EXTRASRC = ../intl/autosprintf.cpp
if BUILD_OPENSSL if BUILD_OPENSSL
@ -62,6 +64,7 @@ endif
libencfs_la_SOURCES = \ libencfs_la_SOURCES = \
readpassphrase.cpp \ readpassphrase.cpp \
base64.cpp \ base64.cpp \
config.pb.cc \
ConfigReader.cpp \ ConfigReader.cpp \
ConfigVar.cpp \ ConfigVar.cpp \
Context.cpp \ Context.cpp \
@ -83,6 +86,7 @@ libencfs_la_SOURCES = \
FileNode.cpp \ FileNode.cpp \
FileUtils.cpp \ FileUtils.cpp \
openssl.cpp \ openssl.cpp \
XmlReader.cpp \
${EXTRASRC} ${EXTRASRC}
@ -109,6 +113,7 @@ noinst_HEADERS = \
CipherKey.h \ CipherKey.h \
ConfigReader.h \ ConfigReader.h \
ConfigVar.h \ ConfigVar.h \
config.pb.h \
Context.h \ Context.h \
DirNode.h \ DirNode.h \
encfs.h \ encfs.h \
@ -134,8 +139,14 @@ noinst_HEADERS = \
man_MANS=encfs.1 encfsctl.1 man_MANS=encfs.1 encfsctl.1
EXTRA_DIST = encfs.pod encfsctl.pod encfs.1 encfsctl.1 encfs-man.html EXTRA_DIST = encfs.pod encfsctl.pod encfs.1 encfsctl.1 encfs-man.html
SUFFIXES = .1 .pod .proto
config.pb.cc: config.pb.h
config.pb.h: config.proto
@PROTOC@ --cpp_out=. config.proto
if BUILD_MAN if BUILD_MAN
SUFFIXES = .1 .pod
# since we have POD2MAN, we can specify how to rebuild encfs.1 if necessary # since we have POD2MAN, we can specify how to rebuild encfs.1 if necessary
.pod.1: .pod.1:
@POD2MAN@ --section=1 --release=@VERSION@ --center="Encrypted Filesystem" $< $@ @POD2MAN@ --section=1 --release=@VERSION@ --center="Encrypted Filesystem" $< $@

View File

@ -25,6 +25,8 @@
#include "config.h" #include "config.h"
#include <pthread.h> #include <pthread.h>
#include <sys/mman.h>
#ifdef HAVE_VALGRIND_MEMCHECK_H #ifdef HAVE_VALGRIND_MEMCHECK_H
#include <valgrind/memcheck.h> #include <valgrind/memcheck.h>
#else #else
@ -34,6 +36,7 @@
using namespace rlog; using namespace rlog;
# include <openssl/crypto.h>
# include <openssl/buffer.h> # include <openssl/buffer.h>
#define BLOCKDATA( BLOCK ) (unsigned char*)BLOCK->data->data #define BLOCKDATA( BLOCK ) (unsigned char*)BLOCK->data->data
@ -140,4 +143,34 @@ void MemoryPool::destroyAll()
} }
} }
SecureMem::SecureMem(int len)
{
data = (char *)OPENSSL_malloc(len);
if (data)
{
size = len;
mlock(data, size);
memset(data, '\0', size);
VALGRIND_MAKE_MEM_UNDEFINED( data, size );
} else
{
size = 0;
}
}
SecureMem::~SecureMem()
{
if (size)
{
memset(data, '\0', size);
munlock(data, size);
OPENSSL_free(data);
VALGRIND_MAKE_MEM_NOACCESS( data, size );
data = NULL;
size = 0;
}
}

View File

@ -50,5 +50,14 @@ namespace MemoryPool
void destroyAll(); void destroyAll();
} }
struct SecureMem
{
int size;
char *data;
SecureMem(int len);
~SecureMem();
};
#endif #endif

View File

@ -32,7 +32,6 @@
#include "NullNameIO.h" #include "NullNameIO.h"
using namespace std; using namespace std;
using namespace rel;
using namespace rlog; using namespace rlog;
#define REF_MODULE(TYPE) \ #define REF_MODULE(TYPE) \
@ -130,7 +129,7 @@ shared_ptr<NameIO> NameIO::New( const Interface &iface,
NameIOMap_t::const_iterator end = gNameIOMap->end(); NameIOMap_t::const_iterator end = gNameIOMap->end();
for(it = gNameIOMap->begin(); it != end; ++it) for(it = gNameIOMap->begin(); it != end; ++it)
{ {
if( it->second.iface.implements( iface )) if( implements(it->second.iface, iface ))
{ {
Constructor fn = it->second.constructor; Constructor fn = it->second.constructor;
result = (*fn)( iface, cipher, key ); result = (*fn)( iface, cipher, key );

View File

@ -32,33 +32,33 @@ class Cipher;
class NameIO class NameIO
{ {
public: public:
typedef shared_ptr<NameIO> (*Constructor)( const rel::Interface &iface, typedef shared_ptr<NameIO> (*Constructor)( const Interface &iface,
const shared_ptr<Cipher> &cipher, const CipherKey &key); const shared_ptr<Cipher> &cipher, const CipherKey &key);
struct Algorithm struct Algorithm
{ {
std::string name; std::string name;
std::string description; std::string description;
rel::Interface iface; Interface iface;
}; };
typedef std::list<Algorithm> AlgorithmList; typedef std::list<Algorithm> AlgorithmList;
static AlgorithmList GetAlgorithmList( bool includeHidden = false ); static AlgorithmList GetAlgorithmList( bool includeHidden = false );
static shared_ptr<NameIO> New( const rel::Interface &iface, static shared_ptr<NameIO> New( const Interface &iface,
const shared_ptr<Cipher> &cipher, const CipherKey &key); const shared_ptr<Cipher> &cipher, const CipherKey &key);
static shared_ptr<NameIO> New( const std::string &name, static shared_ptr<NameIO> New( const std::string &name,
const shared_ptr<Cipher> &cipher, const CipherKey &key); const shared_ptr<Cipher> &cipher, const CipherKey &key);
static bool Register( const char *name, const char *description, static bool Register( const char *name, const char *description,
const rel::Interface &iface, Constructor constructor, const Interface &iface, Constructor constructor,
bool hidden = false); bool hidden = false);
NameIO(); NameIO();
virtual ~NameIO(); virtual ~NameIO();
virtual rel::Interface interface() const =0; virtual Interface interface() const =0;
void setChainedNameIV( bool enable ); void setChainedNameIV( bool enable );
bool getChainedNameIV() const; bool getChainedNameIV() const;

View File

@ -26,13 +26,12 @@
#include <cstring> #include <cstring>
using namespace std; using namespace std;
using namespace rel;
using namespace rlog; using namespace rlog;
using boost::shared_ptr; using boost::shared_ptr;
using boost::dynamic_pointer_cast; using boost::dynamic_pointer_cast;
static Interface NullInterface( "nullCipher", 1, 0, 0 ); static Interface NullInterface = makeInterface( "nullCipher", 1, 0, 0 );
static Range NullKeyRange(0); static Range NullKeyRange(0);
static Range NullBlockRange(1,4096,1); static Range NullBlockRange(1,4096,1);

View File

@ -28,13 +28,13 @@
*/ */
class NullCipher : public Cipher class NullCipher : public Cipher
{ {
rel::Interface iface; Interface iface;
public: public:
NullCipher(const rel::Interface &iface); NullCipher(const Interface &iface);
virtual ~NullCipher(); virtual ~NullCipher();
virtual rel::Interface interface() const; virtual Interface interface() const;
// create a new key based on a password // create a new key based on a password
virtual CipherKey newKey(const char *password, int passwdLength, virtual CipherKey newKey(const char *password, int passwdLength,

View File

@ -22,7 +22,6 @@
#include <cstring> #include <cstring>
using namespace rel;
using boost::shared_ptr; using boost::shared_ptr;
static shared_ptr<NameIO> NewNNIO( const Interface &, static shared_ptr<NameIO> NewNNIO( const Interface &,
@ -31,7 +30,7 @@ static shared_ptr<NameIO> NewNNIO( const Interface &,
return shared_ptr<NameIO>( new NullNameIO() ); return shared_ptr<NameIO>( new NullNameIO() );
} }
static Interface NNIOIface("nameio/null", 1, 0, 0); static Interface NNIOIface = makeInterface("nameio/null", 1, 0, 0);
static bool NullNameIO_registered = NameIO::Register("Null", static bool NullNameIO_registered = NameIO::Register("Null",
"No encryption of filenames", NNIOIface, NewNNIO); "No encryption of filenames", NNIOIface, NewNNIO);

View File

@ -23,13 +23,13 @@
class NullNameIO : public NameIO class NullNameIO : public NameIO
{ {
public: public:
static rel::Interface CurrentInterface(); static Interface CurrentInterface();
NullNameIO( ); NullNameIO( );
virtual ~NullNameIO(); virtual ~NullNameIO();
virtual rel::Interface interface() const; virtual Interface interface() const;
virtual int maxEncodedNameLen( int plaintextNameLen ) const; virtual int maxEncodedNameLen( int plaintextNameLen ) const;
virtual int maxDecodedNameLen( int encodedNameLen ) const; virtual int maxDecodedNameLen( int encodedNameLen ) const;

View File

@ -33,9 +33,9 @@
using namespace std; using namespace std;
static rel::Interface RawFileIO_iface("FileIO/Raw", 1, 0, 0); static Interface RawFileIO_iface = makeInterface("FileIO/Raw", 1, 0, 0);
FileIO *NewRawFileIO( const rel::Interface &iface ) FileIO *NewRawFileIO( const Interface &iface )
{ {
(void)iface; (void)iface;
return new RawFileIO(); return new RawFileIO();
@ -82,7 +82,7 @@ RawFileIO::~RawFileIO()
close( _fd ); close( _fd );
} }
rel::Interface RawFileIO::interface() const Interface RawFileIO::interface() const
{ {
return RawFileIO_iface; return RawFileIO_iface;
} }

View File

@ -29,7 +29,7 @@ public:
RawFileIO( const std::string &fileName ); RawFileIO( const std::string &fileName );
virtual ~RawFileIO(); virtual ~RawFileIO();
virtual rel::Interface interface() const; virtual Interface interface() const;
virtual void setFileName( const char *fileName ); virtual void setFileName( const char *fileName );
virtual const char *getFileName() const; virtual const char *getFileName() const;

View File

@ -66,10 +66,7 @@ inline int MIN(int a, int b)
the state of EVP_CIPHER struct. EVP_BytesToKey will only produce 128 bit the state of EVP_CIPHER struct. EVP_BytesToKey will only produce 128 bit
keys for the EVP Blowfish interface, which is not what we want. keys for the EVP Blowfish interface, which is not what we want.
Eliminated the salt code, since we don't use it.. Reason is that we're DEPRECATED: this is here for backward compatibilty only. Use PBKDF
using the derived key to encode random data. Since there is no known
plaintext, there is no ability for an attacker to pre-compute known
password->data mappings, which is what the salt is meant to frustrate.
*/ */
int BytesToKey( int keyLen, int ivLen, const EVP_MD *md, int BytesToKey( int keyLen, int ivLen, const EVP_MD *md,
const unsigned char *data, int dataLen, const unsigned char *data, int dataLen,
@ -103,7 +100,7 @@ int BytesToKey( int keyLen, int ivLen, const EVP_MD *md,
} }
int offset = 0; int offset = 0;
int toCopy = MIN( nkey, mds - offset ); int toCopy = MIN( nkey, (int)mds - offset );
if( toCopy ) if( toCopy )
{ {
memcpy( key, mdBuf+offset, toCopy ); memcpy( key, mdBuf+offset, toCopy );
@ -111,7 +108,7 @@ int BytesToKey( int keyLen, int ivLen, const EVP_MD *md,
nkey -= toCopy; nkey -= toCopy;
offset += toCopy; offset += toCopy;
} }
toCopy = MIN( niv, mds - offset ); toCopy = MIN( niv, (int)mds - offset );
if( toCopy ) if( toCopy )
{ {
memcpy( iv, mdBuf+offset, toCopy ); memcpy( iv, mdBuf+offset, toCopy );
@ -174,8 +171,8 @@ int TimedPBKDF2(const char *pass, int passlen,
// - Version 2:1 adds support for Message Digest function interface // - Version 2:1 adds support for Message Digest function interface
// - Version 2:2 adds PBKDF2 for password derivation // - Version 2:2 adds PBKDF2 for password derivation
// - Version 3:0 adds a new IV mechanism // - Version 3:0 adds a new IV mechanism
static Interface BlowfishInterface( "ssl/blowfish", 3, 0, 2 ); static Interface BlowfishInterface = makeInterface( "ssl/blowfish", 3, 0, 2 );
static Interface AESInterface( "ssl/aes", 3, 0, 2 ); static Interface AESInterface = makeInterface( "ssl/aes", 3, 0, 2 );
#if defined(HAVE_EVP_BF) #if defined(HAVE_EVP_BF)
@ -275,19 +272,20 @@ SSLKey::SSLKey(int keySize_, int ivLength_)
this->ivLength = ivLength_; this->ivLength = ivLength_;
pthread_mutex_init( &mutex, 0 ); pthread_mutex_init( &mutex, 0 );
buffer = (unsigned char *)OPENSSL_malloc( keySize + ivLength ); buffer = (unsigned char *)OPENSSL_malloc( keySize + ivLength );
memset( buffer, 0, keySize + ivLength );
// most likely fails unless we're running as root, or a user-page-lock // most likely fails unless we're running as root, or a user-page-lock
// kernel patch is applied.. // kernel patch is applied..
mlock( buffer, keySize + ivLength ); mlock( buffer, keySize + ivLength );
memset( buffer, 0, keySize + ivLength );
} }
SSLKey::~SSLKey() SSLKey::~SSLKey()
{ {
memset( buffer, 0, keySize + ivLength ); memset( buffer, 0, keySize + ivLength );
OPENSSL_free( buffer );
munlock( buffer, keySize + ivLength ); munlock( buffer, keySize + ivLength );
OPENSSL_free( buffer );
keySize = 0; keySize = 0;
ivLength = 0; ivLength = 0;
@ -370,7 +368,7 @@ SSL_Cipher::SSL_Cipher(const Interface &iface_,
iface.name().c_str(), _keySize, _ivLength); iface.name().c_str(), _keySize, _ivLength);
if( (EVP_CIPHER_key_length( _blockCipher ) != (int )_keySize) if( (EVP_CIPHER_key_length( _blockCipher ) != (int )_keySize)
&& iface.current() == 1) && iface.major() == 1)
{ {
rWarning("Running in backward compatibilty mode for 1.0 - \n" rWarning("Running in backward compatibilty mode for 1.0 - \n"
"key is really %i bits, not %i.\n" "key is really %i bits, not %i.\n"
@ -438,7 +436,7 @@ CipherKey SSL_Cipher::newKey(const char *password, int passwdLength)
shared_ptr<SSLKey> key( new SSLKey( _keySize, _ivLength) ); shared_ptr<SSLKey> key( new SSLKey( _keySize, _ivLength) );
int bytes = 0; int bytes = 0;
if( iface.current() > 1 ) if( iface.major() > 1 )
{ {
// now we use BytesToKey, which can deal with Blowfish keys larger then // now we use BytesToKey, which can deal with Blowfish keys larger then
// 128 bits. // 128 bits.
@ -680,7 +678,7 @@ int SSL_Cipher::cipherBlockSize() const
void SSL_Cipher::setIVec( unsigned char *ivec, uint64_t seed, void SSL_Cipher::setIVec( unsigned char *ivec, uint64_t seed,
const shared_ptr<SSLKey> &key) const const shared_ptr<SSLKey> &key) const
{ {
if (iface.current() >= 3) if (iface.major() >= 3)
{ {
memcpy( ivec, IVData(key), _ivLength ); memcpy( ivec, IVData(key), _ivLength );
@ -707,7 +705,7 @@ void SSL_Cipher::setIVec( unsigned char *ivec, uint64_t seed,
} }
} }
/** For backward compatibility. /** Deprecated: For backward compatibility only.
A watermark attack was discovered against this IV setup. If an attacker 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 could get a victim to store a carefully crafted file, they could later
determine if the victim had the file in encrypted storage (without determine if the victim had the file in encrypted storage (without
@ -717,13 +715,6 @@ void SSL_Cipher::setIVec_old(unsigned char *ivec,
unsigned int seed, unsigned int seed,
const shared_ptr<SSLKey> &key) const 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
seed.
0x060a4011 : ruler length 26, 7 marks, 21 measurable lengths
0x0221040d : ruler length 25, 7 marks, 21 measurable lengths
*/
unsigned int var1 = 0x060a4011 * seed; unsigned int var1 = 0x060a4011 * seed;
unsigned int var2 = 0x0221040d * (seed ^ 0xD3FEA11C); unsigned int var2 = 0x0221040d * (seed ^ 0xD3FEA11C);

View File

@ -70,21 +70,21 @@ using boost::shared_ptr;
*/ */
class SSL_Cipher : public Cipher class SSL_Cipher : public Cipher
{ {
rel::Interface iface; Interface iface;
rel::Interface realIface; Interface realIface;
const EVP_CIPHER *_blockCipher; const EVP_CIPHER *_blockCipher;
const EVP_CIPHER *_streamCipher; const EVP_CIPHER *_streamCipher;
unsigned int _keySize; // in bytes unsigned int _keySize; // in bytes
unsigned int _ivLength; unsigned int _ivLength;
public: public:
SSL_Cipher(const rel::Interface &iface, const rel::Interface &realIface, SSL_Cipher(const Interface &iface, const Interface &realIface,
const EVP_CIPHER *blockCipher, const EVP_CIPHER *streamCipher, const EVP_CIPHER *blockCipher, const EVP_CIPHER *streamCipher,
int keyLength); int keyLength);
virtual ~SSL_Cipher(); virtual ~SSL_Cipher();
// returns the real interface, not the one we're emulating (if any).. // returns the real interface, not the one we're emulating (if any)..
virtual rel::Interface interface() const; virtual Interface interface() const;
// create a new key based on a password // create a new key based on a password
virtual CipherKey newKey(const char *password, int passwdLength, virtual CipherKey newKey(const char *password, int passwdLength,

View File

@ -26,7 +26,6 @@
#include "i18n.h" #include "i18n.h"
#include <cstring> #include <cstring>
using namespace rel;
using namespace std; using namespace std;
static shared_ptr<NameIO> NewStreamNameIO( const Interface &iface, static shared_ptr<NameIO> NewStreamNameIO( const Interface &iface,
@ -65,13 +64,13 @@ static bool StreamIO_registered = NameIO::Register("Stream",
Interface StreamNameIO::CurrentInterface() Interface StreamNameIO::CurrentInterface()
{ {
// implement major version 2, 1, and 0 // implement major version 2, 1, and 0
return Interface("nameio/stream", 2, 1, 2); return makeInterface("nameio/stream", 2, 1, 2);
} }
StreamNameIO::StreamNameIO( const rel::Interface &iface, StreamNameIO::StreamNameIO( const Interface &iface,
const shared_ptr<Cipher> &cipher, const shared_ptr<Cipher> &cipher,
const CipherKey &key ) const CipherKey &key )
: _interface( iface.current() ) : _interface( iface.major() )
, _cipher( cipher ) , _cipher( cipher )
, _key( key ) , _key( key )
{ {

View File

@ -27,14 +27,14 @@ using boost::shared_ptr;
class StreamNameIO : public NameIO class StreamNameIO : public NameIO
{ {
public: public:
static rel::Interface CurrentInterface(); static Interface CurrentInterface();
StreamNameIO( const rel::Interface &iface, StreamNameIO( const Interface &iface,
const shared_ptr<Cipher> &cipher, const shared_ptr<Cipher> &cipher,
const CipherKey &key ); const CipherKey &key );
virtual ~StreamNameIO(); virtual ~StreamNameIO();
virtual rel::Interface interface() const; virtual Interface interface() const;
virtual int maxEncodedNameLen( int plaintextNameLen ) const; virtual int maxEncodedNameLen( int plaintextNameLen ) const;
virtual int maxDecodedNameLen( int encodedNameLen ) const; virtual int maxDecodedNameLen( int encodedNameLen ) const;

191
encfs/XmlReader.cpp Normal file
View File

@ -0,0 +1,191 @@
/*****************************************************************************
* Author: Valient Gough <vgough@pobox.com>
*
*****************************************************************************
* Copyright (c) 2012, 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/>.
*/
#include "XmlReader.h"
#include "base64.h"
#include <rlog/rlog.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <cstring>
#include <map>
#include <tinyxml.h>
#include <openssl/evp.h>
#include <openssl/bio.h>
#include <openssl/buffer.h>
using namespace std;
using namespace rlog;
XmlValue::~XmlValue()
{
}
XmlValuePtr XmlValue::operator[] (const char *path) const
{
return this->find(path);
}
XmlValuePtr XmlValue::find(const char *name) const
{
rError("in XmlValue::operator[%s]", name);
return XmlValuePtr(new XmlValue());
}
const XmlValuePtr & operator >> (const XmlValuePtr &ptr, std::string &out)
{
out = ptr->text();
return ptr;
}
const XmlValuePtr & operator >> (const XmlValuePtr &ptr, int &out)
{
out = atoi(ptr->text().c_str());
return ptr;
}
const XmlValuePtr & operator >> (const XmlValuePtr &ptr, long &out)
{
out = atol(ptr->text().c_str());
return ptr;
}
const XmlValuePtr & operator >> (const XmlValuePtr &ptr, double &out)
{
out = atof(ptr->text().c_str());
return ptr;
}
const XmlValuePtr & operator >> (const XmlValuePtr &ptr, bool &out)
{
out = atoi(ptr->text().c_str());
return ptr;
}
bool XmlValue::readB64Data(unsigned char *data, int length) const
{
std::string s = value;
s.erase(std::remove_if(s.begin(), s.end(), ::isspace), s.end());
BIO *b64 = BIO_new(BIO_f_base64());
BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
BIO *bmem = BIO_new_mem_buf((void *)s.c_str(), s.size());
bmem = BIO_push(b64, bmem);
int decodedSize = BIO_read(bmem, data, length);
BIO_free_all(b64);
if (decodedSize != length)
{
rError("decoding bytes len %i, expecting output len %i, got %i",
(int)s.size(), length, decodedSize);
return false;
}
return true;
}
std::string safeValueForNode(TiXmlElement *element)
{
std::string value;
const TiXmlNode *child = element->FirstChild();
if (child)
{
const TiXmlText *childText = child->ToText();
if (childText)
value = childText->Value();
}
return value;
}
class XmlNode : virtual public XmlValue
{
TiXmlElement *element;
public:
XmlNode(TiXmlElement *element_)
: XmlValue(safeValueForNode(element_))
, element(element_)
{
}
virtual ~XmlNode()
{
}
virtual XmlValuePtr find(const char *name) const
{
if (name[0] == '@')
{
return XmlValuePtr(new XmlValue(element->Attribute(name+1)));
} else
{
return XmlValuePtr(new XmlNode(element->FirstChild(name)->ToElement()));
}
}
};
struct XmlReader::XmlReaderData
{
boost::shared_ptr<TiXmlDocument> doc;
};
XmlReader::XmlReader()
: pd(new XmlReaderData())
{
}
XmlReader::~XmlReader()
{
}
bool XmlReader::load(const char *fileName)
{
pd->doc.reset(new TiXmlDocument(fileName));
return pd->doc->LoadFile();
}
XmlValuePtr XmlReader::operator[] ( const char *name ) const
{
TiXmlNode *node = pd->doc->FirstChild(name);
if (node == NULL)
{
rError("Xml node %s not found", name);
return XmlValuePtr(new XmlValue());
}
TiXmlElement *element = node->ToElement();
if (element == NULL)
{
rError("Xml node %s not element, type = %i", name, node->Type());
return XmlValuePtr(new XmlValue());
}
return XmlValuePtr(new XmlNode(element));
}

78
encfs/XmlReader.h Normal file
View File

@ -0,0 +1,78 @@
/*****************************************************************************
* Author: Valient Gough <vgough@pobox.com>
*
*****************************************************************************
* Copyright (c) 2012, 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 _XmlReader_incl_
#define _XmlReader_incl_
#include <boost/shared_ptr.hpp>
#include <string>
class XmlValue;
typedef boost::shared_ptr<XmlValue> XmlValuePtr;
class XmlValue
{
std::string value;
public:
XmlValue()
{
}
XmlValue(const std::string &value)
{
this->value = value;
}
virtual ~XmlValue();
XmlValuePtr operator[] (const char *path) const;
bool readB64Data(unsigned char *data, int length) const;
const std::string &text() const
{
return value;
}
protected:
virtual XmlValuePtr find(const char *name) const;
};
const XmlValuePtr & operator >> (const XmlValuePtr &ptr, std::string &outStr);
const XmlValuePtr & operator >> (const XmlValuePtr &ptr, int &out);
const XmlValuePtr & operator >> (const XmlValuePtr &ptr, long &out);
const XmlValuePtr & operator >> (const XmlValuePtr &ptr, double &out);
const XmlValuePtr & operator >> (const XmlValuePtr &ptr, bool &out);
class XmlReader
{
public:
XmlReader();
~XmlReader();
bool load(const char *fileName);
XmlValuePtr operator[](const char *name) const;
private:
struct XmlReaderData;
boost::shared_ptr<XmlReaderData> pd;
};
#endif

36
encfs/config.proto Normal file
View File

@ -0,0 +1,36 @@
message EncfsConfig
{
optional string creator = 1;
optional int32 revision = 2 [default=0];
required Interface cipher = 3;
required bytes key = 4;
optional bytes salt = 41;
required int32 key_size = 42; // in bits
optional int32 kdf_iterations = 43 [default=0];
optional int32 kdf_duration = 44 [default=500];
optional Interface naming = 5;
optional bool unique_iv = 51 [default=false];
optional bool chained_iv = 52 [default=false];
optional bool external_iv = 53 [default=false];
required int32 block_size = 6;
optional int32 block_mac_bytes = 61 [default=0];
optional int32 block_mac_rand_bytes = 611 [default=0];
optional bool allow_holes = 62 [default = false];
}
message Interface
{
required string name = 1;
required uint32 major = 2; // major version number
required uint32 minor = 3; // minor version number
// Age indicates number of major versions supported. 0 means no backward
// compatibility. See libtool "updating version information" for more
// details on how major/minor/age are used for versioning libraries.
optional uint32 age = 4;
}

View File

@ -176,7 +176,7 @@ static int showInfo( int argc, char **argv )
if( !checkDir( rootDir )) if( !checkDir( rootDir ))
return EXIT_FAILURE; return EXIT_FAILURE;
boost::shared_ptr<EncFSConfig> config(new EncFSConfig); EncfsConfig config;
ConfigType type = readConfig( rootDir, config ); ConfigType type = readConfig( rootDir, config );
// show information stored in config.. // show information stored in config..
@ -194,24 +194,22 @@ static int showInfo( int argc, char **argv )
case Config_V3: case Config_V3:
// xgroup(diag) // xgroup(diag)
cout << "\n" << autosprintf(_("Version 3 configuration; " cout << "\n" << autosprintf(_("Version 3 configuration; "
"created by %s\n"), config->creator.c_str()); "created by %s\n"), config.creator().c_str());
break; break;
case Config_V4: case Config_V4:
// xgroup(diag) // xgroup(diag)
cout << "\n" << autosprintf(_("Version 4 configuration; " cout << "\n" << autosprintf(_("Version 4 configuration; "
"created by %s\n"), config->creator.c_str()); "created by %s\n"), config.creator().c_str());
break; break;
case Config_V5: case Config_V5:
// xgroup(diag)
cout << "\n" << autosprintf(_("Version 5 configuration; "
"created by %s (revision %i)\n"), config->creator.c_str(),
config->subVersion);
break;
case Config_V6: case Config_V6:
case Config_V7:
// xgroup(diag) // xgroup(diag)
cout << "\n" << autosprintf(_("Version 6 configuration; " cout << "\n" << autosprintf(_("Version %i configuration; "
"created by %s (revision %i)\n"), config->creator.c_str(), "created by %s (revision %i)\n"),
config->subVersion); type,
config.creator().c_str(),
config.revision());
break; break;
} }
@ -687,9 +685,7 @@ static int cmd_showcruft( int argc, char **argv )
int filesFound = showcruft( rootInfo, "/" ); int filesFound = showcruft( rootInfo, "/" );
cerr << autosprintf( cerr << autosprintf("Found %i invalid file(s).", filesFound) << "\n";
ngettext("Found %i invalid file.", "Found %i invalid files.",
filesFound), filesFound) << "\n";
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }
@ -701,7 +697,7 @@ static int do_chpasswd( bool useStdin, bool annotate, int argc, char **argv )
if( !checkDir( rootDir )) if( !checkDir( rootDir ))
return EXIT_FAILURE; return EXIT_FAILURE;
boost::shared_ptr<EncFSConfig> config(new EncFSConfig); EncfsConfig config;
ConfigType cfgType = readConfig( rootDir, config ); ConfigType cfgType = readConfig( rootDir, config );
if(cfgType == Config_None) if(cfgType == Config_None)
@ -711,12 +707,11 @@ static int do_chpasswd( bool useStdin, bool annotate, int argc, char **argv )
} }
// instanciate proper cipher // instanciate proper cipher
shared_ptr<Cipher> cipher = Cipher::New( shared_ptr<Cipher> cipher = getCipher(config);
config->cipherIface, config->keySize );
if(!cipher) if(!cipher)
{ {
cout << autosprintf(_("Unable to find specified cipher \"%s\"\n"), cout << autosprintf(_("Unable to find specified cipher \"%s\"\n"),
config->cipherIface.name().c_str()); config.cipher().name().c_str());
return EXIT_FAILURE; return EXIT_FAILURE;
} }
@ -724,13 +719,14 @@ static int do_chpasswd( bool useStdin, bool annotate, int argc, char **argv )
cout << _("Enter current Encfs password\n"); cout << _("Enter current Encfs password\n");
if (annotate) if (annotate)
cerr << "$PROMPT$ passwd" << endl; cerr << "$PROMPT$ passwd" << endl;
CipherKey userKey = config->getUserKey( useStdin ); CipherKey userKey = getUserKey( config, useStdin );
if(!userKey) if(!userKey)
return EXIT_FAILURE; return EXIT_FAILURE;
// decode volume key using user key -- at this point we detect an incorrect // 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). // password if the key checksum does not match (causing readKey to fail).
CipherKey volumeKey = cipher->readKey( config->getKeyData(), userKey ); CipherKey volumeKey = cipher->readKey(
(const unsigned char *)config.key().data(), userKey );
if(!volumeKey) if(!volumeKey)
{ {
@ -741,17 +737,15 @@ static int do_chpasswd( bool useStdin, bool annotate, int argc, char **argv )
// Now, get New user key.. // Now, get New user key..
userKey.reset(); userKey.reset();
cout << _("Enter new Encfs password\n"); cout << _("Enter new Encfs password\n");
// reinitialize salt and iteration count
config->kdfIterations = 0; // generate new
// create new key
if( useStdin ) if( useStdin )
{ {
if (annotate) if (annotate)
cerr << "$PROMPT$ new_passwd" << endl; cerr << "$PROMPT$ new_passwd" << endl;
userKey = config->getUserKey( true );
} }
else
userKey = config->getNewUserKey(); userKey = getNewUserKey( config, useStdin, string(), string() );
// re-encode the volume key using the new user key and write it out.. // re-encode the volume key using the new user key and write it out..
int result = EXIT_FAILURE; int result = EXIT_FAILURE;
@ -764,10 +758,10 @@ static int do_chpasswd( bool useStdin, bool annotate, int argc, char **argv )
cipher->writeKey( volumeKey, keyBuf, userKey ); cipher->writeKey( volumeKey, keyBuf, userKey );
userKey.reset(); userKey.reset();
config->assignKeyData( keyBuf, encodedKeySize ); config.set_key( keyBuf, encodedKeySize );
delete[] keyBuf; delete[] keyBuf;
if(saveConfig( cfgType, rootDir, config )) if(saveConfig( rootDir, config ))
{ {
// password modified -- changes volume key of filesystem.. // password modified -- changes volume key of filesystem..
cout << _("Volume Key successfully updated.\n"); cout << _("Volume Key successfully updated.\n");
@ -816,7 +810,7 @@ int main(int argc, char **argv)
slog->subscribeTo( GetGlobalChannel("error") ); slog->subscribeTo( GetGlobalChannel("error") );
slog->subscribeTo( GetGlobalChannel("warning") ); slog->subscribeTo( GetGlobalChannel("warning") );
#ifndef NO_DEBUG #ifndef NO_DEBUG
//slog->subscribeTo( GetGlobalChannel("debug") ); slog->subscribeTo( GetGlobalChannel("debug") );
#endif #endif
if(argc < 2) if(argc < 2)

View File

@ -69,7 +69,6 @@ inline static int MAX(int a, int b)
using namespace std; using namespace std;
using namespace rlog; using namespace rlog;
using namespace rel;
using namespace gnu; using namespace gnu;
using boost::shared_ptr; using boost::shared_ptr;
using boost::scoped_ptr; using boost::scoped_ptr;

View File

@ -47,11 +47,12 @@
#endif #endif
#endif #endif
#include <google/protobuf/text_format.h>
#include <tr1/unordered_set> #include <tr1/unordered_set>
using namespace std; using namespace std;
using namespace rel;
using namespace rlog; using namespace rlog;
using boost::shared_ptr; using boost::shared_ptr;
@ -235,35 +236,28 @@ bool runTests(const shared_ptr<Cipher> &cipher, bool verbose)
cipher->writeKey( key, keyBuf, encodingKey ); cipher->writeKey( key, keyBuf, encodingKey );
// store in config struct.. // store in config struct..
EncFSConfig cfg; EncfsConfig cfg;
cfg.cipherIface = cipher->interface(); cfg.mutable_cipher()->MergeFrom(cipher->interface());
cfg.keySize = 8 * cipher->keySize(); cfg.set_key_size(8 * cipher->keySize());
cfg.blockSize = FSBlockSize; cfg.set_block_size(FSBlockSize);
cfg.assignKeyData( keyBuf, encodedKeySize ); cfg.set_key( keyBuf, encodedKeySize );
// save config // save config
string data; string data;
{ google::protobuf::TextFormat::PrintToString(cfg, &data);
ostringstream st;
st << cfg;
data = st.str();
}
// read back in and check everything.. // read back in and check everything..
EncFSConfig cfg2; EncfsConfig cfg2;
{ google::protobuf::TextFormat::ParseFromString(data, &cfg2);
istringstream st(data);
st >> cfg2;
}
// check.. // check..
rAssert( cfg.cipherIface.implements(cfg2.cipherIface) ); rAssert( implements(cfg.cipher(),cfg2.cipher()) );
rAssert( cfg.keySize == cfg2.keySize ); rAssert( cfg.key_size() == cfg2.key_size() );
rAssert( cfg.blockSize == cfg2.blockSize ); rAssert( cfg.block_size() == cfg2.block_size() );
// try decoding key.. // try decoding key..
CipherKey key2 = cipher->readKey( cfg2.getKeyData(), encodingKey ); CipherKey key2 = cipher->readKey( (unsigned char *)cfg2.key().data(), encodingKey );
if(!key2) if(!key2)
{ {
if(verbose) if(verbose)
@ -286,15 +280,15 @@ bool runTests(const shared_ptr<Cipher> &cipher, bool verbose)
FSConfigPtr fsCfg = FSConfigPtr(new FSConfig); FSConfigPtr fsCfg = FSConfigPtr(new FSConfig);
fsCfg->cipher = cipher; fsCfg->cipher = cipher;
fsCfg->key = key; fsCfg->key = key;
fsCfg->config.reset(new EncFSConfig); fsCfg->config.reset(new EncfsConfig);
fsCfg->config->blockSize = FSBlockSize; fsCfg->config->set_block_size(FSBlockSize);
if(verbose) if(verbose)
cerr << "Testing name encode/decode (stream coding w/ IV chaining)\n"; cerr << "Testing name encode/decode (stream coding w/ IV chaining)\n";
{ {
fsCfg->opts.reset(new EncFS_Opts); fsCfg->opts.reset(new EncFS_Opts);
fsCfg->opts->idleTracking = false; fsCfg->opts->idleTracking = false;
fsCfg->config->uniqueIV = false; fsCfg->config->set_unique_iv(false);
fsCfg->nameCoding.reset( new StreamNameIO( fsCfg->nameCoding.reset( new StreamNameIO(
StreamNameIO::CurrentInterface(), cipher, key ) ); StreamNameIO::CurrentInterface(), cipher, key ) );
@ -310,7 +304,7 @@ bool runTests(const shared_ptr<Cipher> &cipher, bool verbose)
cerr << "Testing name encode/decode (block coding w/ IV chaining)\n"; cerr << "Testing name encode/decode (block coding w/ IV chaining)\n";
{ {
fsCfg->opts->idleTracking = false; fsCfg->opts->idleTracking = false;
fsCfg->config->uniqueIV = false; fsCfg->config->set_unique_iv(false);
fsCfg->nameCoding.reset( new BlockNameIO( fsCfg->nameCoding.reset( new BlockNameIO(
BlockNameIO::CurrentInterface(), cipher, key, BlockNameIO::CurrentInterface(), cipher, key,
cipher->cipherBlockSize() ) ); cipher->cipherBlockSize() ) );
@ -326,7 +320,7 @@ bool runTests(const shared_ptr<Cipher> &cipher, bool verbose)
cerr << "Testing name encode/decode (block coding w/ IV chaining, base32)\n"; cerr << "Testing name encode/decode (block coding w/ IV chaining, base32)\n";
{ {
fsCfg->opts->idleTracking = false; fsCfg->opts->idleTracking = false;
fsCfg->config->uniqueIV = false; fsCfg->config->set_unique_iv(false);
fsCfg->nameCoding.reset( new BlockNameIO( fsCfg->nameCoding.reset( new BlockNameIO(
BlockNameIO::CurrentInterface(), cipher, key, BlockNameIO::CurrentInterface(), cipher, key,
cipher->cipherBlockSize(), true ) ); cipher->cipherBlockSize(), true ) );
@ -503,8 +497,8 @@ int main(int argc, char *argv[])
{ {
cerr << it->name cerr << it->name
<< " ( " << it->iface.name() << " " << " ( " << it->iface.name() << " "
<< it->iface.current() << ":" << it->iface.major() << ":"
<< it->iface.revision() << ":" << it->iface.minor() << ":"
<< it->iface.age() << " ) : " << it->description << "\n"; << it->iface.age() << " ) : " << it->description << "\n";
cerr << " - key length " << it->keyLength.min() << " to " cerr << " - key length " << it->keyLength.min() << " to "
<< it->keyLength.max() << " , block size " << it->blockSize.min() << it->keyLength.max() << " , block size " << it->blockSize.min()