diff --git a/ChangeLog b/ChangeLog index 75d4fef..95b35d6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,13 +1,65 @@ + +Sat Aug 16 2008 Valient Gough + * use PBKDF2 for new keys with salt and variable iteration count. + When creating a new key, adjusts iteration count to take + approximatly 1/2 a second of CPU time to test key. + +Tue Aug 5 2008 Valient Gough + * bump version to 1.4.3 + +Fri Aug 1 2008 Valient Gough + * fix xattr support for Mac + +Tue Jul 1 2008 Valient Gough + * add patch info to Changelog + * separate RenameOp definition from implementation to avoid gcc 4.3 + errors + +Sat Jun 28 2008 Valient Gough + * remove logs in Context, which displayed plaintext names + +Mon Jun 2 2008 Valient Gough + * fix defaultYes/defaultNo functions + Tue Jul 1 2008 Valient Gough * patch to fix compile errors in w/ gcc 4.3 from Anthony Shipman. -2008-05-22 gettextize +Thu May 22 2008 Valient Gough + * use autoreconf in reconfig.sh + * update autoconf and gettext tools + * remove AM_MKINSTALLDIRS from configure.ac - * m4/gettext.m4: Upgrade to gettext-0.17. - * m4/iconv.m4: Upgrade to gettext-0.17. - * m4/lib-link.m4: Upgrade to gettext-0.17. - * m4/po.m4: Upgrade to gettext-0.17. - * configure.ac (AM_GNU_GETTEXT_VERSION): Bump to 0.17. +Sun May 18 2008 Valient Gough + * add makeKey program and showKey option to encfsctl + * replace C header includes with C++ versions + +Sat May 17 2008 Valient Gough + * fix EVP initialization + +Thu May 15 2008 Valient Gough + * include cstring in several files, patch by A.Klitzing + * improve return code check on RAND_bytes call + +Wed May 14 2008 Valient Gough + * include binary_object header in FuseUtils + +Sat May 10 2008 Valient Gough + * explicit namespace for make_binary_object calls + +Wed May 7 2008 Valient Gough + * add string.h to ConfigVar + +Sun May 4 2008 Valient Gough + * change boost requirement to 1.34+, to eliminate fs::native usage + requirement + * ensure boost::filesystem::path is created with native option" + +Sat Apr 19 2008 Valient Gough + * add direct-load method so that encfsctl cat can work with direct + cipher paths + +Tue Apr 15 2008 Valient Gough + * add boost filesystem lib check Sun Apr 13 2008 Valient Gough * fix bug in export - wasn't able to export symlinks. diff --git a/encfs/Cipher.h b/encfs/Cipher.h index 83dea10..e7eeaca 100644 --- a/encfs/Cipher.h +++ b/encfs/Cipher.h @@ -84,7 +84,10 @@ public: virtual rel::Interface interface() const =0; // create a new key based on a password - virtual CipherKey newKey(const char *password, int passwdLength) =0; + // if iterationCount == 0, then iteration count will be determined + // by newKey function and filled in. + virtual CipherKey newKey(const char *password, int passwdLength, + int &iterationCount, const unsigned char *salt, int saltLen) =0; // create a new random key virtual CipherKey newRandomKey() =0; @@ -109,7 +112,9 @@ public: // fill the supplied buffer with random data // The data may be pseudo random and might not be suitable for key // generation. For generating keys, uses newRandomKey() instead. - virtual void randomize( unsigned char *buf, int len ) const =0; + // Returns true on success, false on failure. + virtual bool randomize( unsigned char *buf, int len, + bool strongRandom ) const =0; // 64 bit MAC of the data with the given key virtual uint64_t MAC_64( const unsigned char *src, int len, diff --git a/encfs/CipherFileIO.cpp b/encfs/CipherFileIO.cpp index 88e9269..19c58b6 100644 --- a/encfs/CipherFileIO.cpp +++ b/encfs/CipherFileIO.cpp @@ -21,6 +21,7 @@ #include "MemoryPool.h" #include +#include #include #include @@ -206,7 +207,8 @@ void CipherFileIO::initHeader( ) unsigned char buf[8] = {0}; do { - cipher->randomize( buf, 8 ); + if(!cipher->randomize( buf, 8, false )) + throw ERROR("Unable to generate a random file IV"); fileIV = 0; for(int i=0; i<8; ++i) diff --git a/encfs/FileUtils.cpp b/encfs/FileUtils.cpp index a4d7f1f..886cbd4 100644 --- a/encfs/FileUtils.cpp +++ b/encfs/FileUtils.cpp @@ -87,7 +87,9 @@ static const char ENCFS_ENV_STDERR[] = "encfs_stderr"; static int V5SubVersion = 20040813; // fix MACFileIO block size issues static int V5SubVersionDefault = 0; -const int V6SubVersion = 20080813; // switch to v6/XML, add allowHoles option +// 20080813 was really made on 20080413 -- typo on date.. +//const int V6SubVersion = 20080813; // switch to v6/XML, add allowHoles option +const int V6SubVersion = 20080816; // add salt and iteration count struct ConfigInfo { @@ -118,6 +120,35 @@ namespace boost { namespace serialization { + template + void encodeBinary(Archive &ar, + const char *id, const std::string &in) + { + int encodedSize = in.length(); + std::string name = std::string("encoded") + id + "Size"; + ar << make_nvp(name.c_str(), encodedSize); + + char data[encodedSize]; + memcpy(data, in.data(), encodedSize); + name = std::string("encoded") + id + "Data"; + ar << make_nvp(name.c_str(), + serial::make_binary_object(data, encodedSize)); + } + + template + void decodeBinary(Archive &ar, const char *id, std::string &out) + { + int encodedSize; + std::string name = std::string("encoded") + id + "Size"; + ar >> make_nvp(name.c_str(), encodedSize); + + char data[encodedSize]; + name = std::string("encoded") + id + "Data"; + ar >> make_nvp(name.c_str(), + serial::make_binary_object(data, encodedSize)); + out.assign( (char*)data, encodedSize ); + } + template void save(Archive &ar, const EncFSConfig &cfg, unsigned int version) @@ -135,18 +166,18 @@ namespace boost ar << make_nvp("blockMACRandBytes", cfg.blockMACRandBytes); ar << make_nvp("allowHoles", cfg.allowHoles); - int keyLen = cfg.keyData.length(); - ar << make_nvp("encodedKeySize", keyLen); - char key[keyLen]; - memcpy(key, cfg.keyData.data(), keyLen); - ar << make_nvp("encodedKeyData", - serial::make_binary_object(key, keyLen)); + encodeBinary(ar, "Key", cfg.keyData); + + // version 20080816 + ar << make_nvp("saltSize", cfg.saltSize); + ar << make_nvp("saltData", + serial::make_binary_object(cfg.saltData, cfg.saltSize)); + ar << make_nvp("kdfIterations", cfg.kdfIterations); } template void load(Archive &ar, EncFSConfig &cfg, unsigned int version) { - (void)version; cfg.subVersion = version; ar >> make_nvp("creator", cfg.creator); ar >> make_nvp("cipherAlg", cfg.cipherIface); @@ -159,13 +190,22 @@ namespace boost ar >> make_nvp("blockMACBytes", cfg.blockMACBytes); ar >> make_nvp("blockMACRandBytes", cfg.blockMACRandBytes); ar >> make_nvp("allowHoles", cfg.allowHoles); - - int encodedKeySize; - ar >> make_nvp("encodedKeySize", encodedKeySize); - char key[encodedKeySize]; - ar >> make_nvp("encodedKeyData", - serial::make_binary_object(key, encodedKeySize)); - cfg.keyData.assign( (char*)key, encodedKeySize ); + + decodeBinary(ar, "Key", cfg.keyData); + + if(version >= 20080816) + { + ar >> make_nvp("saltSize", cfg.saltSize); + cfg.saltData = new unsigned char[cfg.saltSize]; + ar >> make_nvp("saltData", + serial::make_binary_object(cfg.saltData, cfg.saltSize)); + ar >> make_nvp("kdfIterations", cfg.kdfIterations); + } else + { + cfg.saltSize = 0; + cfg.saltData = NULL; + cfg.kdfIterations = 0; + } } template @@ -1027,6 +1067,17 @@ RootPtr createV6Config( EncFS_Context *ctx, const std::string &rootDir, config.externalIVChaining = externalIV; config.allowHoles = allowHoles; + config.saltSize = 20; + config.saltData = new unsigned char[config.saltSize]; + config.kdfIterations = 0; // filled in by keying function + + if(!cipher->randomize(config.saltData, config.saltSize, true)) + { + cout << _("Unable to generate random data for key derivation\n"); + return rootInfo; + } + + cout << "\n"; // xgroup(setup) cout << _("Configuration finished. The filesystem to be created has\n" @@ -1063,11 +1114,17 @@ RootPtr createV6Config( EncFS_Context *ctx, const std::string &rootDir, CipherKey userKey; rDebug( "useStdin: %i", useStdin ); if(useStdin) - userKey = getUserKey( cipher, useStdin ); + userKey = getUserKey( cipher, useStdin, + config.saltData, config.saltSize, + config.kdfIterations); else if(passwordProgram.empty()) - userKey = getNewUserKey( cipher ); + userKey = getNewUserKey( cipher, + config.saltData, config.saltSize, + config.kdfIterations ); else - userKey = getUserKey( passwordProgram, cipher, rootDir ); + userKey = getUserKey( passwordProgram, cipher, rootDir, + config.saltData, config.saltSize, + config.kdfIterations ); cipher->writeKey( volumeKey, encodedKey, userKey ); userKey.reset(); @@ -1231,7 +1288,8 @@ void showFSInfo( const EncFSConfig &config ) cout << "\n"; } -CipherKey getUserKey( const shared_ptr &cipher, bool useStdin ) +CipherKey getUserKey( const shared_ptr &cipher, bool useStdin, + const unsigned char *salt, int saltSize, int &iterations) { char passBuf[MaxPassBuf]; char *res; @@ -1253,7 +1311,8 @@ CipherKey getUserKey( const shared_ptr &cipher, bool useStdin ) if(!res) cerr << _("Zero length password not allowed\n"); else - userKey = cipher->newKey( passBuf, strlen(passBuf) ); + userKey = cipher->newKey( passBuf, strlen(passBuf), + iterations, salt, saltSize); memset( passBuf, 0, sizeof(passBuf) ); @@ -1287,7 +1346,8 @@ std::string readPassword( int FD ) } CipherKey getUserKey( const std::string &passProg, - const shared_ptr &cipher, const std::string &rootDir ) + const shared_ptr &cipher, const std::string &rootDir, + const unsigned char *salt, int saltSize, int &iterations) { // have a child process run the command and get the result back to us. int fds[2], pid; @@ -1358,7 +1418,8 @@ CipherKey getUserKey( const std::string &passProg, waitpid(pid, NULL, 0); // convert to key.. - result = cipher->newKey( password.c_str(), password.length() ); + result = cipher->newKey( password.c_str(), password.length(), + iterations, salt, saltSize ); // clear buffer.. password.assign( password.length(), '\0' ); @@ -1366,7 +1427,8 @@ CipherKey getUserKey( const std::string &passProg, return result; } -CipherKey getNewUserKey( const shared_ptr &cipher ) +CipherKey getNewUserKey( const shared_ptr &cipher, + const unsigned char *salt, int saltSize, int &iterations ) { CipherKey userKey; char passBuf[MaxPassBuf]; @@ -1382,7 +1444,8 @@ CipherKey getNewUserKey( const shared_ptr &cipher ) sizeof(passBuf2)-1, RPP_ECHO_OFF); if(res1 && res2 && !strcmp(passBuf, passBuf2)) - userKey = cipher->newKey( passBuf, strlen(passBuf) ); + userKey = cipher->newKey( passBuf, strlen(passBuf), + iterations, salt, saltSize ); else { // xgroup(common) -- probably not common, but group with the others @@ -1433,10 +1496,12 @@ RootPtr initFS( EncFS_Context *ctx, const shared_ptr &opts ) CipherKey userKey; rDebug( "useStdin: %i", opts->useStdin ); if(opts->passwordProgram.empty()) - userKey = getUserKey( cipher, opts->useStdin ); + userKey = getUserKey( cipher, opts->useStdin, + config.saltData, config.saltSize, config.kdfIterations); else userKey = getUserKey( opts->passwordProgram, - cipher, opts->rootDir ); + cipher, opts->rootDir, + config.saltData, config.saltSize, config.kdfIterations); if(!userKey) return rootInfo; diff --git a/encfs/FileUtils.h b/encfs/FileUtils.h index 3a857b5..1fe779a 100644 --- a/encfs/FileUtils.h +++ b/encfs/FileUtils.h @@ -51,6 +51,10 @@ struct EncFSConfig int blockSize; // reported in bytes std::string keyData; + int saltSize; // in bytes + unsigned char *saltData; + int kdfIterations; + int blockMACBytes; // MAC headers on blocks.. int blockMACRandBytes; // number of random bytes in the block header @@ -69,6 +73,16 @@ struct EncFSConfig externalIVChaining = false; chainedNameIV = false; allowHoles = false; + + saltSize = 0; + saltData = NULL; + kdfIterations = 0; + } + + ~EncFSConfig() + { + if(saltData != NULL) + delete[] saltData; } }; @@ -165,10 +179,13 @@ bool writeV6Config( const char *configFile, EncFSConfig *config); -CipherKey getUserKey(const boost::shared_ptr &cipher, bool useStdin); +CipherKey getUserKey(const boost::shared_ptr &cipher, bool useStdin, + const unsigned char *salt, int saltLen, int &iterations); CipherKey getUserKey(const std::string &passwordProgram, const boost::shared_ptr &cipher, - const std::string &rootDir ); -CipherKey getNewUserKey(const boost::shared_ptr &cipher); + const std::string &rootDir, + const unsigned char *salt, int saltLen, int &iterations); +CipherKey getNewUserKey(const boost::shared_ptr &cipher, + const unsigned char *salt, int saltLen, int &iterations); #endif diff --git a/encfs/MACFileIO.cpp b/encfs/MACFileIO.cpp index e744bd1..bb34760 100644 --- a/encfs/MACFileIO.cpp +++ b/encfs/MACFileIO.cpp @@ -259,7 +259,10 @@ bool MACFileIO::writeOneBlock( const IORequest &req ) memset( newReq.data, 0, headerSize ); memcpy( newReq.data + headerSize, req.data, req.dataLen ); if(randBytes) - cipher->randomize( newReq.data+macBytes, randBytes ); + { + if(!cipher->randomize( newReq.data+macBytes, randBytes, false )) + return false; + } // compute the mac (which includes the random data) and fill it in uint64_t mac = cipher->MAC_64( newReq.data+macBytes, diff --git a/encfs/NullCipher.cpp b/encfs/NullCipher.cpp index e426124..1e35e4d 100644 --- a/encfs/NullCipher.cpp +++ b/encfs/NullCipher.cpp @@ -83,7 +83,8 @@ Interface NullCipher::interface() const return iface; } -CipherKey NullCipher::newKey(const char *, int ) +CipherKey NullCipher::newKey(const char *, int, + int &, const unsigned char *, int ) { return gNullKey; } @@ -93,9 +94,10 @@ CipherKey NullCipher::newRandomKey() return gNullKey; } -void NullCipher::randomize( unsigned char *buf, int len ) const +bool NullCipher::randomize( unsigned char *buf, int len, bool ) const { memset( buf, 0, len ); + return true; } uint64_t NullCipher::MAC_64(const unsigned char *, int , diff --git a/encfs/NullCipher.h b/encfs/NullCipher.h index 3236103..e05e3a0 100644 --- a/encfs/NullCipher.h +++ b/encfs/NullCipher.h @@ -37,7 +37,8 @@ public: virtual rel::Interface interface() const; // create a new key based on a password - virtual CipherKey newKey(const char *password, int passwdLength); + virtual CipherKey newKey(const char *password, int passwdLength, + int &iterationCount, const unsigned char *salt, int saltLen); // create a new random key virtual CipherKey newRandomKey(); @@ -55,7 +56,8 @@ public: virtual int encodedKeySize() const; virtual int cipherBlockSize() const; - virtual void randomize( unsigned char *buf, int len ) const; + virtual bool randomize( unsigned char *buf, int len, + bool strongRandom ) const; virtual uint64_t MAC_64(const unsigned char *data, int len, const CipherKey &key, uint64_t *chainedIV) const; diff --git a/encfs/SSL_Cipher.cpp b/encfs/SSL_Cipher.cpp index cd8fcd8..763762e 100644 --- a/encfs/SSL_Cipher.cpp +++ b/encfs/SSL_Cipher.cpp @@ -32,8 +32,10 @@ #include "Mutex.h" #include +#include #include +#include #include #include @@ -51,6 +53,9 @@ const int MAX_KEYLENGTH = 32; // in bytes (256 bit) const int MAX_IVLENGTH = 16; const int KEY_CHECKSUM_BYTES = 4; +// how long we'd like the PDF function to take, in micro seconds +const long DesiredPDFTime = 500 * 1000; // 1/2 second + #ifndef MIN inline int MIN(int a, int b) { @@ -125,13 +130,57 @@ int BytesToKey( int keyLen, int ivLen, const EVP_MD *md, return keyLen; } +long time_diff(const timeval &end, const timeval &start) +{ + return (end.tv_sec - start.tv_sec) * 1000 * 1000 + + (end.tv_usec - start.tv_usec); +} + +int TimedPBKDF2(const char *pass, int passlen, + const unsigned char *salt, int saltlen, + int keylen, unsigned char *out, + int &numIterations) +{ + int iter = 1000; + timeval start, end; + + for(;;) + { + gettimeofday( &start, 0 ); + int res = PKCS5_PBKDF2_HMAC_SHA1(pass, passlen, salt, saltlen, + iter, keylen, out); + if(res != 1) + return res; + + gettimeofday( &end, 0 ); + + long delta = time_diff(end, start); + if(delta < DesiredPDFTime / 8) + { + iter *= 4; + } else if(delta < (5 * DesiredPDFTime / 6)) + { + // estimate number of iterations to get close to desired time + iter = (int)((double)iter * (double)DesiredPDFTime + / (double)delta); + } else + { + // done.. + numIterations = iter; + return 1; + } + } +} + + // - Version 1:0 used EVP_BytesToKey, which didn't do the right thing for // Blowfish key lengths > 128 bit. // - Version 2:0 uses BytesToKey. // 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 -static Interface BlowfishInterface( "ssl/blowfish", 2, 1, 1 ); -static Interface AESInterface( "ssl/aes", 2, 1, 1 ); +// - Version 3:0 uses PBKDF2 for password derivation +static Interface BlowfishInterface( "ssl/blowfish", 3, 0, 2 ); +static Interface AESInterface( "ssl/aes", 3, 0, 2 ); #if defined(HAVE_EVP_BF) @@ -210,8 +259,8 @@ public: unsigned int keySize; // in bytes unsigned int ivLength; - // key data is first _keySize bytes, followed by _ivLength length bytes for - // iv + // key data is first _keySize bytes, + // followed by iv of _ivLength bytes, unsigned char *buffer; EVP_CIPHER_CTX block_enc; @@ -232,6 +281,7 @@ SSLKey::SSLKey(int keySize_, int ivLength_) pthread_mutex_init( &mutex, 0 ); 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 // kernel patch is applied.. mlock( buffer, keySize + ivLength ); @@ -351,7 +401,8 @@ Interface SSL_Cipher::interface() const This algorithm must remain constant for backward compatibility, as this key is used to encipher/decipher the master key. */ -CipherKey SSL_Cipher::newKey(const char *password, int passwdLength) +CipherKey SSL_Cipher::newKey(const char *password, int passwdLength, + int &iterationCount, const unsigned char *salt, int saltLen) { const EVP_MD *md = EVP_sha1(); if(!md) @@ -363,7 +414,35 @@ CipherKey SSL_Cipher::newKey(const char *password, int passwdLength) shared_ptr key( new SSLKey( _keySize, _ivLength) ); int bytes = 0; - if( iface.current() > 1 ) + if( iface.current() > 2 ) + { + if(iterationCount == 0) + { + // timed run, fills in iteration count + if(TimedPBKDF2(password, passwdLength, + salt, saltLen, + _keySize+_ivLength, KeyData(key), + iterationCount) != 1) + { + rWarning("openssl error, PBKDF2 failed"); + return CipherKey(); + } else if(iterationCount == 0) + { + rWarning("TimedPBKDF2 failed to fill in iteration count"); + return CipherKey(); + } + } else + { + // known iteration length + if(PKCS5_PBKDF2_HMAC_SHA1(password, passwdLength, salt, saltLen, + iterationCount, _keySize + _ivLength, + KeyData(key)) != 1) + { + rWarning("openssl error, PBKDF2 failed"); + return CipherKey(); + } + } + } else if( iface.current() > 1 ) { // now we use BytesToKey, which can deal with Blowfish keys larger then // 128 bits. @@ -402,32 +481,25 @@ CipherKey SSL_Cipher::newRandomKey() { const int bufLen = MAX_KEYLENGTH; unsigned char tmpBuf[ bufLen ]; - // to avoid warnings of uninitialized data from valgrind - memset(tmpBuf, 0, sizeof(tmpBuf)); - if(RAND_bytes( tmpBuf, bufLen ) != 1) - { - char errStr[120]; // specs require string at least 120 bytes long.. - unsigned long errVal = 0; - if((errVal = ERR_get_error()) != 0) - { - rWarning("openssl error: %s", ERR_error_string( errVal, errStr )); - return CipherKey(); - } - } + int saltLen = 20; + unsigned char saltBuf[ saltLen ]; + + if(!randomize(tmpBuf, bufLen, true) || + !randomize(saltBuf, saltLen, true)) + return CipherKey(); shared_ptr key( new SSLKey( _keySize, _ivLength) ); // doesn't need to be versioned, because a random key is a random key.. // Doesn't need to be reproducable.. - int bytes = BytesToKey( _keySize, _ivLength, EVP_sha1(), tmpBuf, - bufLen, 16, KeyData(key), IVData(key) ); - if(bytes != (int)_keySize) + if(PKCS5_PBKDF2_HMAC_SHA1((char*)tmpBuf, bufLen, saltBuf, saltLen, + 1000, _keySize + _ivLength, KeyData(key)) != 1) { - rWarning("newKey: BytesToKey returned %i, expecting %i key bytes", - bytes, _keySize); + rWarning("openssl error, PBKDF2 failed"); + return CipherKey(); } - memset( tmpBuf, 0, bufLen ); + OPENSSL_cleanse(tmpBuf, bufLen); initKey( key, _blockCipher, _streamCipher, _keySize ); @@ -478,11 +550,27 @@ static uint64_t _checksum_64( SSLKey *key, return value; } -void SSL_Cipher::randomize( unsigned char *buf, int len ) const +bool SSL_Cipher::randomize( unsigned char *buf, int len, + bool strongRandom ) const { + // to avoid warnings of uninitialized data from valgrind memset(buf, 0, len); - int result = RAND_pseudo_bytes( buf, len ); - rAssert( result >= 0 ); + int result; + if(strongRandom) + result = RAND_bytes( buf, len ); + else + result = RAND_pseudo_bytes( buf, len ); + + if(result != 1) + { + char errStr[120]; // specs require string at least 120 bytes long.. + unsigned long errVal = 0; + if((errVal = ERR_get_error()) != 0) + rWarning("openssl error: %s", ERR_error_string( errVal, errStr )); + + return false; + } else + return true; } uint64_t SSL_Cipher::MAC_64( const unsigned char *data, int len, diff --git a/encfs/SSL_Cipher.h b/encfs/SSL_Cipher.h index 664c0f4..b3a4f14 100644 --- a/encfs/SSL_Cipher.h +++ b/encfs/SSL_Cipher.h @@ -87,7 +87,8 @@ public: virtual rel::Interface interface() const; // create a new key based on a password - virtual CipherKey newKey(const char *password, int passwdLength); + virtual CipherKey newKey(const char *password, int passwdLength, + int &iterationCount, const unsigned char *salt, int saltLen); // create a new random key virtual CipherKey newRandomKey(); @@ -105,7 +106,8 @@ public: virtual int encodedKeySize() const; virtual int cipherBlockSize() const; - virtual void randomize( unsigned char *buf, int len ) const; + virtual bool randomize( unsigned char *buf, int len, + bool strongRandom ) const; virtual uint64_t MAC_64( const unsigned char *src, int len, const CipherKey &key, uint64_t *augment ) const; diff --git a/encfs/encfsctl.cpp b/encfs/encfsctl.cpp index 9449095..332e94d 100644 --- a/encfs/encfsctl.cpp +++ b/encfs/encfsctl.cpp @@ -669,7 +669,9 @@ static int do_chpasswd( bool useStdin, int argc, char **argv ) // ask for existing password cout << _("Enter current Encfs password\n"); - CipherKey userKey = getUserKey( cipher, useStdin ); + CipherKey userKey = getUserKey( cipher, useStdin, + config.saltData, config.saltSize, + config.kdfIterations ); if(!userKey) return EXIT_FAILURE; @@ -691,9 +693,13 @@ static int do_chpasswd( bool useStdin, int argc, char **argv ) userKey.reset(); cout << _("Enter new Encfs password\n"); if( useStdin ) - userKey = getUserKey( cipher, true ); + userKey = getUserKey( cipher, true, + config.saltData, config.saltSize, + config.kdfIterations ); else - userKey = getNewUserKey( cipher ); + userKey = getNewUserKey( cipher, + config.saltData, config.saltSize, + config.kdfIterations ); // re-encode the volume key using the new user key and write it out.. int result = EXIT_FAILURE;