move encrypted key into separate config block

git-svn-id: http://encfs.googlecode.com/svn/trunk@85 db9cf616-1c43-0410-9cb8-a902689de0d6
This commit is contained in:
Valient Gough 2012-08-20 05:05:16 +00:00
parent 183dca787f
commit 36946fdea7
4 changed files with 58 additions and 42 deletions

View File

@ -344,16 +344,17 @@ bool readV6Config( const char *configFile,
cfg.set_block_mac_rand_bytes(blockMacRandBytes); cfg.set_block_mac_rand_bytes(blockMacRandBytes);
cfg.set_allow_holes(allowHoles); cfg.set_allow_holes(allowHoles);
EncryptedKey *encryptedKey = cfg.mutable_key();
int encodedSize; int encodedSize;
(*config)["encodedKeySize"] >> encodedSize; (*config)["encodedKeySize"] >> encodedSize;
unsigned char *key = new unsigned char[encodedSize]; unsigned char *key = new unsigned char[encodedSize];
(*config)["encodedKeyData"]->readB64Data(key, encodedSize); (*config)["encodedKeyData"]->readB64Data(key, encodedSize);
cfg.set_key(key, encodedSize); encryptedKey->set_ciphertext(key, encodedSize);
delete[] key; delete[] key;
int keySize; int keySize;
(*config)["keySize"] >> keySize; (*config)["keySize"] >> keySize;
cfg.set_key_size(keySize); encryptedKey->set_size(keySize / 8); // save as size in bytes
if(cfg.revision() >= 20080816) if(cfg.revision() >= 20080816)
{ {
@ -361,19 +362,19 @@ bool readV6Config( const char *configFile,
(*config)["saltLen"] >> saltLen; (*config)["saltLen"] >> saltLen;
unsigned char *salt = new unsigned char[saltLen]; unsigned char *salt = new unsigned char[saltLen];
(*config)["saltData"]->readB64Data(salt, saltLen); (*config)["saltData"]->readB64Data(salt, saltLen);
cfg.set_salt(salt, saltLen); encryptedKey->set_salt(salt, saltLen);
delete[] salt; delete[] salt;
int kdfIterations, desiredKDFDuration; int kdfIterations, desiredKDFDuration;
(*config)["kdfIterations"] >> kdfIterations; (*config)["kdfIterations"] >> kdfIterations;
(*config)["desiredKDFDuration"] >> desiredKDFDuration; (*config)["desiredKDFDuration"] >> desiredKDFDuration;
cfg.set_kdf_iterations(kdfIterations); encryptedKey->set_kdf_iterations(kdfIterations);
cfg.set_kdf_duration(desiredKDFDuration); encryptedKey->set_kdf_duration(desiredKDFDuration);
} else } else
{ {
cfg.clear_salt(); encryptedKey->clear_salt();
cfg.set_kdf_iterations(16); encryptedKey->set_kdf_iterations(16);
cfg.set_kdf_duration(NormalKDFDuration); encryptedKey->clear_kdf_duration();
} }
return true; return true;
@ -416,10 +417,11 @@ bool readV5Config( const char *configFile,
cfgRdr["blockSize"] >> blockSize; cfgRdr["blockSize"] >> blockSize;
config.set_block_size(blockSize); config.set_block_size(blockSize);
EncryptedKey *encryptedKey = config.mutable_key();
int keySize; int keySize;
cfgRdr["keySize"] >> keySize; cfgRdr["keySize"] >> keySize;
config.set_key_size(keySize); encryptedKey->set_size(keySize / 8);
cfgRdr["keyData"] >> (*config.mutable_key()); cfgRdr["keyData"] >> (*encryptedKey->mutable_ciphertext());
config.set_unique_iv( cfgRdr["uniqueIV"].readBool( false ) ); config.set_unique_iv( cfgRdr["uniqueIV"].readBool( false ) );
config.set_chained_iv( cfgRdr["chainedIV"].readBool( false ) ); config.set_chained_iv( cfgRdr["chainedIV"].readBool( false ) );
@ -455,7 +457,8 @@ bool readV4Config( const char *configFile,
cfgRdr["blockSize"] >> blockSize; cfgRdr["blockSize"] >> blockSize;
config.set_block_size(blockSize); config.set_block_size(blockSize);
cfgRdr["keyData"] >> (*config.mutable_key()); EncryptedKey *key = config.mutable_key();
cfgRdr["keyData"] >> (*key->mutable_ciphertext());
// fill in default for V4 // fill in default for V4
config.mutable_naming()->MergeFrom( makeInterface("nameio/stream", 1, 0, 0) ); config.mutable_naming()->MergeFrom( makeInterface("nameio/stream", 1, 0, 0) );
@ -1058,9 +1061,10 @@ RootPtr createConfig( EncFS_Context *ctx,
config.set_external_iv( externalIV ); config.set_external_iv( externalIV );
config.set_allow_holes( allowHoles ); config.set_allow_holes( allowHoles );
config.clear_salt(); EncryptedKey *key = config.mutable_key();
config.clear_kdf_iterations(); // filled in by keying function key->clear_salt();
config.set_kdf_duration( desiredKDFDuration ); key->clear_kdf_iterations(); // filled in by keying function
key->set_kdf_duration( desiredKDFDuration );
cout << "\n"; cout << "\n";
// xgroup(setup) // xgroup(setup)
@ -1107,7 +1111,7 @@ RootPtr createConfig( EncFS_Context *ctx,
cipher->writeKey( volumeKey, encodedKey, userKey ); cipher->writeKey( volumeKey, encodedKey, userKey );
userKey.reset(); userKey.reset();
config.set_key(encodedKey, encodedKeySize); key->set_ciphertext(encodedKey, encodedKeySize);
delete[] encodedKey; delete[] encodedKey;
if(!volumeKey) if(!volumeKey)
@ -1203,8 +1207,9 @@ void showFSInfo( const EncfsConfig &config )
cout << "\n"; cout << "\n";
} }
} }
const EncryptedKey &key = config.key();
{ {
cout << autosprintf(_("Key Size: %i bits"), config.key_size()); cout << autosprintf(_("Key Size: %i bits"), 8 * key.size());
cipher = getCipher(config); cipher = getCipher(config);
if(!cipher) if(!cipher)
{ {
@ -1213,12 +1218,12 @@ void showFSInfo( const EncfsConfig &config )
} else } else
cout << "\n"; cout << "\n";
} }
if(config.kdf_iterations() > 0 && config.salt().size() > 0) if(key.kdf_iterations() > 0 && key.salt().size() > 0)
{ {
cout << autosprintf(_("Using PBKDF2, with %i iterations"), cout << autosprintf(_("Using PBKDF2, with %i iterations"),
config.kdf_iterations()) << "\n"; key.kdf_iterations()) << "\n";
cout << autosprintf(_("Salt Size: %i bits"), cout << autosprintf(_("Salt Size: %i bits"),
8*(int)config.salt().size()) << "\n"; 8*(int)key.salt().size()) << "\n";
} }
if(config.block_mac_bytes() || config.block_mac_rand_bytes()) if(config.block_mac_bytes() || config.block_mac_rand_bytes())
{ {
@ -1270,7 +1275,7 @@ void showFSInfo( const EncfsConfig &config )
shared_ptr<Cipher> getCipher(const EncfsConfig &config) shared_ptr<Cipher> getCipher(const EncfsConfig &config)
{ {
return getCipher(config.cipher(), config.key_size()); return getCipher(config.cipher(), 8 * config.key().size());
} }
shared_ptr<Cipher> getCipher(const Interface &iface, int keySize) shared_ptr<Cipher> getCipher(const Interface &iface, int keySize)
@ -1289,30 +1294,32 @@ CipherKey makeNewKey(EncfsConfig &config, const char *password, int passwdLen)
cout << _("Error creating salt\n"); cout << _("Error creating salt\n");
return userKey; return userKey;
} }
config.set_salt(salt, sizeof(salt)); EncryptedKey *key = config.mutable_key();
key->set_salt(salt, sizeof(salt));
int iterations = config.kdf_iterations(); int iterations = key->kdf_iterations();
userKey = cipher->newKey( password, passwdLen, userKey = cipher->newKey( password, passwdLen,
iterations, config.kdf_duration(), iterations, key->kdf_duration(),
salt, sizeof(salt)); salt, sizeof(salt));
config.set_kdf_iterations(iterations); key->set_kdf_iterations(iterations);
return userKey; return userKey;
} }
CipherKey decryptKey(const EncfsConfig &config, const char *password, int passwdLen) CipherKey decryptKey(const EncfsConfig &config, const char *password, int passwdLen)
{ {
const EncryptedKey &key = config.key();
CipherKey userKey; CipherKey userKey;
shared_ptr<Cipher> cipher = getCipher(config.cipher(), config.key_size()); shared_ptr<Cipher> cipher = getCipher(config.cipher(), 8 * key.size());
if(!config.salt().empty()) if(!key.salt().empty())
{ {
int iterations = config.kdf_iterations(); int iterations = key.kdf_iterations();
userKey = cipher->newKey( password, passwdLen, userKey = cipher->newKey( password, passwdLen,
iterations, config.kdf_duration(), iterations, key.kdf_duration(),
(const unsigned char *)config.salt().data(), config.salt().size()); (const unsigned char *)key.salt().data(), key.salt().size());
if (iterations != config.kdf_iterations()) { if (iterations != key.kdf_iterations()) {
rError("Error in KDF, iteration mismatch"); rError("Error in KDF, iteration mismatch");
return userKey; return userKey;
} }
@ -1597,7 +1604,7 @@ RootPtr initFS( EncFS_Context *ctx, const shared_ptr<EncFS_Opts> &opts )
rDebug("cipher key size = %i", cipher->encodedKeySize()); rDebug("cipher key size = %i", cipher->encodedKeySize());
// decode volume key.. // decode volume key..
CipherKey volumeKey = cipher->readKey( CipherKey volumeKey = cipher->readKey(
(const unsigned char *)config.key().data(), userKey, opts->checkKey); (const unsigned char *)config.key().ciphertext().data(), userKey, opts->checkKey);
userKey.reset(); userKey.reset();
if(!volumeKey) if(!volumeKey)

View File

@ -5,11 +5,7 @@ message EncfsConfig
optional int32 revision = 2 [default=0]; optional int32 revision = 2 [default=0];
required Interface cipher = 3; required Interface cipher = 3;
required bytes key = 4; required EncryptedKey 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 Interface naming = 5;
optional bool unique_iv = 51 [default=false]; optional bool unique_iv = 51 [default=false];
@ -22,6 +18,17 @@ message EncfsConfig
optional bool allow_holes = 62 [default = false]; optional bool allow_holes = 62 [default = false];
} }
message EncryptedKey
{
required bytes ciphertext = 1;
required int32 size = 2; // Size of data in bytes
optional bytes salt = 6;
optional int32 kdf_iterations = 10;
optional int32 kdf_duration = 11 [default=500];
}
message Interface message Interface
{ {
required string name = 1; required string name = 1;

View File

@ -726,7 +726,7 @@ static int do_chpasswd( bool useStdin, bool annotate, int argc, char **argv )
// 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( CipherKey volumeKey = cipher->readKey(
(const unsigned char *)config.key().data(), userKey ); (const unsigned char *)config.key().ciphertext().data(), userKey );
if(!volumeKey) if(!volumeKey)
{ {
@ -758,7 +758,8 @@ 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.set_key( keyBuf, encodedKeySize ); EncryptedKey *key = config.mutable_key();
key->set_ciphertext( keyBuf, encodedKeySize );
delete[] keyBuf; delete[] keyBuf;
if(saveConfig( rootDir, config )) if(saveConfig( rootDir, config ))

View File

@ -238,9 +238,10 @@ bool runTests(const shared_ptr<Cipher> &cipher, bool verbose)
// store in config struct.. // store in config struct..
EncfsConfig cfg; EncfsConfig cfg;
cfg.mutable_cipher()->MergeFrom(cipher->interface()); cfg.mutable_cipher()->MergeFrom(cipher->interface());
cfg.set_key_size(8 * cipher->keySize()); EncryptedKey *encryptedKey = cfg.mutable_key();
encryptedKey->set_size(8 * cipher->keySize());
encryptedKey->set_ciphertext( keyBuf, encodedKeySize );
cfg.set_block_size(FSBlockSize); cfg.set_block_size(FSBlockSize);
cfg.set_key( keyBuf, encodedKeySize );
// save config // save config
string data; string data;
@ -252,12 +253,12 @@ bool runTests(const shared_ptr<Cipher> &cipher, bool verbose)
// check.. // check..
rAssert( implements(cfg.cipher(),cfg2.cipher()) ); rAssert( implements(cfg.cipher(),cfg2.cipher()) );
rAssert( cfg.key_size() == cfg2.key_size() ); rAssert( cfg.key().size() == cfg2.key().size() );
rAssert( cfg.block_size() == cfg2.block_size() ); rAssert( cfg.block_size() == cfg2.block_size() );
// try decoding key.. // try decoding key..
CipherKey key2 = cipher->readKey( (unsigned char *)cfg2.key().data(), encodingKey ); CipherKey key2 = cipher->readKey( (unsigned char *)cfg2.key().ciphertext().data(), encodingKey );
if(!key2) if(!key2)
{ {
if(verbose) if(verbose)