Merge branch 'feature/keyprovider' into develop
This commit is contained in:
commit
e395248f70
@ -9,22 +9,17 @@ namespace cpputils {
|
|||||||
|
|
||||||
class PasswordBasedKDF {
|
class PasswordBasedKDF {
|
||||||
public:
|
public:
|
||||||
virtual ~PasswordBasedKDF() {}
|
virtual ~PasswordBasedKDF() = default;
|
||||||
|
|
||||||
template<size_t KEYSIZE> EncryptionKey<KEYSIZE> deriveKey(const std::string &password);
|
struct KeyResult final {
|
||||||
virtual const Data &kdfParameters() const = 0;
|
cpputils::EncryptionKey key;
|
||||||
|
cpputils::Data kdfParameters;
|
||||||
|
};
|
||||||
|
|
||||||
protected:
|
virtual EncryptionKey deriveExistingKey(size_t keySize, const std::string& password, const Data& kdfParameters) = 0;
|
||||||
virtual void derive(void *destination, size_t size, const std::string &password) = 0;
|
virtual KeyResult deriveNewKey(size_t keySize, const std::string& password) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<size_t KEYSIZE> EncryptionKey<KEYSIZE>
|
|
||||||
inline PasswordBasedKDF::deriveKey(const std::string &password) {
|
|
||||||
auto result = EncryptionKey<KEYSIZE>::Null();
|
|
||||||
derive(result.data(), result.BINARY_LENGTH, password);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -52,7 +52,6 @@ namespace cpputils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
cpputils::Data serialize() const;
|
cpputils::Data serialize() const;
|
||||||
|
|
||||||
static SCryptParameters deserialize(const cpputils::Data &data);
|
static SCryptParameters deserialize(const cpputils::Data &data);
|
||||||
|
|
||||||
#ifndef CRYFS_NO_COMPATIBILITY
|
#ifndef CRYFS_NO_COMPATIBILITY
|
||||||
|
@ -5,45 +5,48 @@ using std::string;
|
|||||||
|
|
||||||
namespace cpputils {
|
namespace cpputils {
|
||||||
|
|
||||||
constexpr SCryptSettings SCrypt::ParanoidSettings;
|
constexpr SCryptSettings SCrypt::ParanoidSettings;
|
||||||
constexpr SCryptSettings SCrypt::DefaultSettings;
|
constexpr SCryptSettings SCrypt::DefaultSettings;
|
||||||
constexpr SCryptSettings SCrypt::TestSettings;
|
constexpr SCryptSettings SCrypt::TestSettings;
|
||||||
|
|
||||||
unique_ref<SCrypt> SCrypt::forNewKey(const SCryptSettings &settings) {
|
namespace {
|
||||||
SCryptParameters kdfParameters(Random::PseudoRandom().get(settings.SALT_LEN), settings.N, settings.r, settings.p);
|
EncryptionKey _derive(size_t keySize, const std::string& password, const SCryptParameters& kdfParameters) {
|
||||||
return make_unique_ref<SCrypt>(std::move(kdfParameters));
|
auto result = EncryptionKey::Null(keySize);
|
||||||
|
|
||||||
|
size_t status = CryptoPP::Scrypt().DeriveKey(
|
||||||
|
static_cast<uint8_t*>(result.data()), result.binaryLength(),
|
||||||
|
reinterpret_cast<const uint8_t*>(password.c_str()), password.size(),
|
||||||
|
static_cast<const uint8_t*>(kdfParameters.salt().data()), kdfParameters.salt().size(),
|
||||||
|
kdfParameters.N(), kdfParameters.r(), kdfParameters.p()
|
||||||
|
);
|
||||||
|
if (status != 1) {
|
||||||
|
throw std::runtime_error("Error running scrypt key derivation. Error code: "+std::to_string(status));
|
||||||
}
|
}
|
||||||
|
|
||||||
unique_ref<SCrypt> SCrypt::forExistingKey(const Data ¶meters) {
|
return result;
|
||||||
return make_unique_ref<SCrypt>(SCryptParameters::deserialize(parameters));
|
}
|
||||||
}
|
|
||||||
|
SCryptParameters _createNewSCryptParameters(const SCryptSettings& settings) {
|
||||||
SCrypt::SCrypt(SCryptParameters config)
|
return SCryptParameters(Random::PseudoRandom().get(settings.SALT_LEN), settings.N, settings.r, settings.p);
|
||||||
:_config(std::move(config)), _serializedConfig(_config.serialize()), _wasGeneratedBefore(false) {
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SCrypt::derive(void *destination, size_t size, const string &password) {
|
SCrypt::SCrypt(const SCryptSettings& settingsForNewKeys)
|
||||||
_checkCallOnlyOnce();
|
:_settingsForNewKeys(settingsForNewKeys) {
|
||||||
|
}
|
||||||
size_t status = CryptoPP::Scrypt().DeriveKey(
|
|
||||||
static_cast<uint8_t*>(destination), size,
|
EncryptionKey SCrypt::deriveExistingKey(size_t keySize, const std::string& password, const Data& kdfParameters) {
|
||||||
reinterpret_cast<const uint8_t*>(password.c_str()), password.size(),
|
SCryptParameters parameters = SCryptParameters::deserialize(kdfParameters);
|
||||||
static_cast<const uint8_t*>(_config.salt().data()), _config.salt().size(),
|
auto key = _derive(keySize, password, parameters);
|
||||||
_config.N(), _config.r(), _config.p()
|
return key;
|
||||||
);
|
}
|
||||||
if (status != 1) {
|
|
||||||
throw std::runtime_error("Error running scrypt key derivation. Error code: "+std::to_string(status));
|
SCrypt::KeyResult SCrypt::deriveNewKey(size_t keySize, const std::string& password) {
|
||||||
}
|
SCryptParameters kdfParameters = _createNewSCryptParameters(_settingsForNewKeys);
|
||||||
}
|
auto key = _derive(keySize, password, kdfParameters);
|
||||||
|
return SCrypt::KeyResult {
|
||||||
const Data &SCrypt::kdfParameters() const {
|
key,
|
||||||
return _serializedConfig;
|
kdfParameters.serialize()
|
||||||
}
|
};
|
||||||
|
}
|
||||||
void SCrypt::_checkCallOnlyOnce() {
|
|
||||||
if (_wasGeneratedBefore) {
|
|
||||||
throw std::runtime_error("An SCrypt instance can only generate exactly one key. Generating multiple keys would be insecure because we would use the same salt.");
|
|
||||||
}
|
|
||||||
_wasGeneratedBefore = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -25,22 +25,13 @@ namespace cpputils {
|
|||||||
static constexpr SCryptSettings DefaultSettings = SCryptSettings {32, 1048576, 4, 8};
|
static constexpr SCryptSettings DefaultSettings = SCryptSettings {32, 1048576, 4, 8};
|
||||||
static constexpr SCryptSettings TestSettings = SCryptSettings {32, 1024, 1, 1};
|
static constexpr SCryptSettings TestSettings = SCryptSettings {32, 1024, 1, 1};
|
||||||
|
|
||||||
static unique_ref<SCrypt> forNewKey(const SCryptSettings &settings);
|
explicit SCrypt(const SCryptSettings& settingsForNewKeys);
|
||||||
static unique_ref<SCrypt> forExistingKey(const Data ¶meters);
|
|
||||||
|
|
||||||
const Data &kdfParameters() const override;
|
EncryptionKey deriveExistingKey(size_t keySize, const std::string& password, const Data& kdfParameters) override;
|
||||||
|
KeyResult deriveNewKey(size_t keySize, const std::string& password) override;
|
||||||
SCrypt(SCryptParameters config);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void derive(void *destination, size_t size, const std::string &password) override;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void _checkCallOnlyOnce();
|
SCryptSettings _settingsForNewKeys;
|
||||||
|
|
||||||
SCryptParameters _config;
|
|
||||||
Data _serializedConfig;
|
|
||||||
bool _wasGeneratedBefore;
|
|
||||||
|
|
||||||
DISALLOW_COPY_AND_ASSIGN(SCrypt);
|
DISALLOW_COPY_AND_ASSIGN(SCrypt);
|
||||||
};
|
};
|
||||||
|
@ -16,7 +16,10 @@ namespace cpputils {
|
|||||||
template<typename BlockCipher, unsigned int KeySize>
|
template<typename BlockCipher, unsigned int KeySize>
|
||||||
class CFB_Cipher {
|
class CFB_Cipher {
|
||||||
public:
|
public:
|
||||||
using EncryptionKey = cpputils::EncryptionKey<KeySize>;
|
using EncryptionKey = cpputils::EncryptionKey;
|
||||||
|
|
||||||
|
static constexpr unsigned int KEYSIZE = KeySize;
|
||||||
|
static constexpr unsigned int STRING_KEYSIZE = 2 * KEYSIZE;
|
||||||
|
|
||||||
static constexpr unsigned int ciphertextSize(unsigned int plaintextBlockSize) {
|
static constexpr unsigned int ciphertextSize(unsigned int plaintextBlockSize) {
|
||||||
return plaintextBlockSize + IV_SIZE;
|
return plaintextBlockSize + IV_SIZE;
|
||||||
@ -33,10 +36,17 @@ private:
|
|||||||
static constexpr unsigned int IV_SIZE = BlockCipher::BLOCKSIZE;
|
static constexpr unsigned int IV_SIZE = BlockCipher::BLOCKSIZE;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<class BlockCipher, unsigned int KeySize>
|
||||||
|
constexpr unsigned int CFB_Cipher<BlockCipher, KeySize>::KEYSIZE;
|
||||||
|
template<class BlockCipher, unsigned int KeySize>
|
||||||
|
constexpr unsigned int CFB_Cipher<BlockCipher, KeySize>::STRING_KEYSIZE;
|
||||||
|
|
||||||
template<typename BlockCipher, unsigned int KeySize>
|
template<typename BlockCipher, unsigned int KeySize>
|
||||||
Data CFB_Cipher<BlockCipher, KeySize>::encrypt(const CryptoPP::byte *plaintext, unsigned int plaintextSize, const EncryptionKey &encKey) {
|
Data CFB_Cipher<BlockCipher, KeySize>::encrypt(const CryptoPP::byte *plaintext, unsigned int plaintextSize, const EncryptionKey &encKey) {
|
||||||
|
ASSERT(encKey.binaryLength() == KeySize, "Wrong key size");
|
||||||
|
|
||||||
FixedSizeData<IV_SIZE> iv = Random::PseudoRandom().getFixedSize<IV_SIZE>();
|
FixedSizeData<IV_SIZE> iv = Random::PseudoRandom().getFixedSize<IV_SIZE>();
|
||||||
auto encryption = typename CryptoPP::CFB_Mode<BlockCipher>::Encryption(static_cast<const CryptoPP::byte*>(encKey.data()), encKey.BINARY_LENGTH, iv.data());
|
auto encryption = typename CryptoPP::CFB_Mode<BlockCipher>::Encryption(static_cast<const CryptoPP::byte*>(encKey.data()), encKey.binaryLength(), iv.data());
|
||||||
Data ciphertext(ciphertextSize(plaintextSize));
|
Data ciphertext(ciphertextSize(plaintextSize));
|
||||||
iv.ToBinary(ciphertext.data());
|
iv.ToBinary(ciphertext.data());
|
||||||
if (plaintextSize > 0) {
|
if (plaintextSize > 0) {
|
||||||
@ -47,13 +57,15 @@ Data CFB_Cipher<BlockCipher, KeySize>::encrypt(const CryptoPP::byte *plaintext,
|
|||||||
|
|
||||||
template<typename BlockCipher, unsigned int KeySize>
|
template<typename BlockCipher, unsigned int KeySize>
|
||||||
boost::optional<Data> CFB_Cipher<BlockCipher, KeySize>::decrypt(const CryptoPP::byte *ciphertext, unsigned int ciphertextSize, const EncryptionKey &encKey) {
|
boost::optional<Data> CFB_Cipher<BlockCipher, KeySize>::decrypt(const CryptoPP::byte *ciphertext, unsigned int ciphertextSize, const EncryptionKey &encKey) {
|
||||||
|
ASSERT(encKey.binaryLength() == KeySize, "Wrong key size");
|
||||||
|
|
||||||
if (ciphertextSize < IV_SIZE) {
|
if (ciphertextSize < IV_SIZE) {
|
||||||
return boost::none;
|
return boost::none;
|
||||||
}
|
}
|
||||||
|
|
||||||
const CryptoPP::byte *ciphertextIV = ciphertext;
|
const CryptoPP::byte *ciphertextIV = ciphertext;
|
||||||
const CryptoPP::byte *ciphertextData = ciphertext + IV_SIZE;
|
const CryptoPP::byte *ciphertextData = ciphertext + IV_SIZE;
|
||||||
auto decryption = typename CryptoPP::CFB_Mode<BlockCipher>::Decryption(static_cast<const CryptoPP::byte*>(encKey.data()), encKey.BINARY_LENGTH, ciphertextIV);
|
auto decryption = typename CryptoPP::CFB_Mode<BlockCipher>::Decryption(static_cast<const CryptoPP::byte*>(encKey.data()), encKey.binaryLength(), ciphertextIV);
|
||||||
Data plaintext(plaintextSize(ciphertextSize));
|
Data plaintext(plaintextSize(ciphertextSize));
|
||||||
if (plaintext.size() > 0) {
|
if (plaintext.size() > 0) {
|
||||||
// TODO Shouldn't we pass in ciphertextSize instead of plaintext.size() here as last argument (and also in the if above)?
|
// TODO Shouldn't we pass in ciphertextSize instead of plaintext.size() here as last argument (and also in the if above)?
|
||||||
|
@ -17,7 +17,9 @@ public:
|
|||||||
BOOST_CONCEPT_USAGE(CipherConcept) {
|
BOOST_CONCEPT_USAGE(CipherConcept) {
|
||||||
same_type(UINT32_C(0), X::ciphertextSize(UINT32_C(5)));
|
same_type(UINT32_C(0), X::ciphertextSize(UINT32_C(5)));
|
||||||
same_type(UINT32_C(0), X::plaintextSize(UINT32_C(5)));
|
same_type(UINT32_C(0), X::plaintextSize(UINT32_C(5)));
|
||||||
typename X::EncryptionKey key = X::EncryptionKey::CreateKey(Random::OSRandom());
|
same_type(UINT32_C(0), X::KEYSIZE);
|
||||||
|
same_type(UINT32_C(0), X::STRING_KEYSIZE);
|
||||||
|
typename X::EncryptionKey key = X::EncryptionKey::CreateKey(Random::OSRandom(), X::KEYSIZE);
|
||||||
same_type(Data(0), X::encrypt(static_cast<uint8_t*>(nullptr), UINT32_C(0), key));
|
same_type(Data(0), X::encrypt(static_cast<uint8_t*>(nullptr), UINT32_C(0), key));
|
||||||
same_type(boost::optional<Data>(Data(0)), X::decrypt(static_cast<uint8_t*>(nullptr), UINT32_C(0), key));
|
same_type(boost::optional<Data>(Data(0)), X::decrypt(static_cast<uint8_t*>(nullptr), UINT32_C(0), key));
|
||||||
string name = X::NAME;
|
string name = X::NAME;
|
||||||
|
@ -19,14 +19,11 @@ namespace cpputils {
|
|||||||
* that there aren't any copies made to different memory regions. However, these other memory regions should be short-lived
|
* that there aren't any copies made to different memory regions. However, these other memory regions should be short-lived
|
||||||
* and therefore much less likely to swap.
|
* and therefore much less likely to swap.
|
||||||
*/
|
*/
|
||||||
template<size_t KeySize>
|
|
||||||
class EncryptionKey final {
|
class EncryptionKey final {
|
||||||
private:
|
private:
|
||||||
explicit EncryptionKey(std::shared_ptr<Data> keyData)
|
explicit EncryptionKey(std::shared_ptr<Data> keyData)
|
||||||
: _keyData(std::move(keyData)) {
|
: _keyData(std::move(keyData)) {
|
||||||
ASSERT(_keyData->size() == KeySize, "Wrong key data size");
|
|
||||||
}
|
}
|
||||||
template<size_t OtherKeySize> friend class EncryptionKey;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
EncryptionKey(const EncryptionKey& rhs) = default;
|
EncryptionKey(const EncryptionKey& rhs) = default;
|
||||||
@ -34,12 +31,17 @@ public:
|
|||||||
EncryptionKey& operator=(const EncryptionKey& rhs) = default;
|
EncryptionKey& operator=(const EncryptionKey& rhs) = default;
|
||||||
EncryptionKey& operator=(EncryptionKey&& rhs) = default;
|
EncryptionKey& operator=(EncryptionKey&& rhs) = default;
|
||||||
|
|
||||||
static constexpr size_t BINARY_LENGTH = KeySize;
|
size_t binaryLength() const {
|
||||||
static constexpr size_t STRING_LENGTH = 2 * BINARY_LENGTH;
|
return _keyData->size();
|
||||||
|
}
|
||||||
|
|
||||||
static EncryptionKey Null() {
|
size_t stringLength() const {
|
||||||
|
return 2 * binaryLength();
|
||||||
|
}
|
||||||
|
|
||||||
|
static EncryptionKey Null(size_t keySize) {
|
||||||
auto data = std::make_shared<Data>(
|
auto data = std::make_shared<Data>(
|
||||||
KeySize,
|
keySize,
|
||||||
make_unique_ref<UnswappableAllocator>()
|
make_unique_ref<UnswappableAllocator>()
|
||||||
);
|
);
|
||||||
data->FillWithZeroes();
|
data->FillWithZeroes();
|
||||||
@ -47,28 +49,27 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
static EncryptionKey FromString(const std::string& keyData) {
|
static EncryptionKey FromString(const std::string& keyData) {
|
||||||
ASSERT(keyData.size() == STRING_LENGTH, "Wrong input size or EncryptionKey::FromString()");
|
|
||||||
|
|
||||||
auto data = std::make_shared<Data>(
|
auto data = std::make_shared<Data>(
|
||||||
Data::FromString(keyData, make_unique_ref<UnswappableAllocator>())
|
Data::FromString(keyData, make_unique_ref<UnswappableAllocator>())
|
||||||
);
|
);
|
||||||
ASSERT(data->size() == KeySize, "Wrong input size for EncryptionKey::FromString()");
|
EncryptionKey key(std::move(data));
|
||||||
|
ASSERT(key.stringLength() == keyData.size(), "Wrong input size for EncryptionKey::FromString()");
|
||||||
|
|
||||||
return EncryptionKey(std::move(data));
|
return key;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string ToString() const {
|
std::string ToString() const {
|
||||||
auto result = _keyData->ToString();
|
auto result = _keyData->ToString();
|
||||||
ASSERT(result.size() == STRING_LENGTH, "Wrong string length");
|
ASSERT(result.size() == stringLength(), "Wrong string length");
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static EncryptionKey CreateKey(RandomGenerator &randomGenerator) {
|
static EncryptionKey CreateKey(RandomGenerator &randomGenerator, size_t keySize) {
|
||||||
EncryptionKey result(std::make_shared<Data>(
|
EncryptionKey result(std::make_shared<Data>(
|
||||||
KeySize,
|
keySize,
|
||||||
make_unique_ref<UnswappableAllocator>() // the allocator makes sure key data is never swapped to disk
|
make_unique_ref<UnswappableAllocator>() // the allocator makes sure key data is never swapped to disk
|
||||||
));
|
));
|
||||||
randomGenerator.write(result._keyData->data(), KeySize);
|
randomGenerator.write(result._keyData->data(), keySize);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -82,29 +83,25 @@ public:
|
|||||||
|
|
||||||
// TODO Test take/drop
|
// TODO Test take/drop
|
||||||
|
|
||||||
template<size_t NumTaken>
|
EncryptionKey take(size_t numTaken) const {
|
||||||
EncryptionKey<NumTaken> take() const {
|
ASSERT(numTaken <= _keyData->size(), "Out of bounds");
|
||||||
static_assert(NumTaken <= KeySize, "Out of bounds");
|
auto result = std::make_shared<Data>(numTaken, make_unique_ref<UnswappableAllocator>());
|
||||||
auto result = std::make_shared<Data>(NumTaken, make_unique_ref<UnswappableAllocator>());
|
std::memcpy(result->data(), _keyData->data(), numTaken);
|
||||||
std::memcpy(result->data(), _keyData->data(), NumTaken);
|
return EncryptionKey(std::move(result));
|
||||||
return EncryptionKey<NumTaken>(std::move(result));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<size_t NumDropped>
|
EncryptionKey drop(size_t numDropped) const {
|
||||||
EncryptionKey<KeySize - NumDropped> drop() const {
|
ASSERT(numDropped <= _keyData->size(), "Out of bounds");
|
||||||
static_assert(NumDropped <= KeySize, "Out of bounds");
|
const size_t resultSize = _keyData->size() - numDropped;
|
||||||
auto result = std::make_shared<Data>(KeySize - NumDropped, make_unique_ref<UnswappableAllocator>());
|
auto result = std::make_shared<Data>(resultSize, make_unique_ref<UnswappableAllocator>());
|
||||||
std::memcpy(result->data(), _keyData->dataOffset(NumDropped), KeySize - NumDropped);
|
std::memcpy(result->data(), _keyData->dataOffset(numDropped), resultSize);
|
||||||
return EncryptionKey<KeySize - NumDropped>(std::move(result));
|
return EncryptionKey(std::move(result));
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::shared_ptr<Data> _keyData;
|
std::shared_ptr<Data> _keyData;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<size_t KeySize> constexpr size_t EncryptionKey<KeySize>::BINARY_LENGTH;
|
|
||||||
template<size_t KeySize> constexpr size_t EncryptionKey<KeySize>::STRING_LENGTH;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -15,7 +15,10 @@ namespace cpputils {
|
|||||||
template<typename BlockCipher, unsigned int KeySize>
|
template<typename BlockCipher, unsigned int KeySize>
|
||||||
class GCM_Cipher {
|
class GCM_Cipher {
|
||||||
public:
|
public:
|
||||||
using EncryptionKey = cpputils::EncryptionKey<KeySize>;
|
using EncryptionKey = cpputils::EncryptionKey;
|
||||||
|
|
||||||
|
static constexpr unsigned int KEYSIZE = KeySize;
|
||||||
|
static constexpr unsigned int STRING_KEYSIZE = 2 * KEYSIZE;
|
||||||
|
|
||||||
static constexpr unsigned int ciphertextSize(unsigned int plaintextBlockSize) {
|
static constexpr unsigned int ciphertextSize(unsigned int plaintextBlockSize) {
|
||||||
return plaintextBlockSize + IV_SIZE + TAG_SIZE;
|
return plaintextBlockSize + IV_SIZE + TAG_SIZE;
|
||||||
@ -33,11 +36,18 @@ private:
|
|||||||
static constexpr unsigned int TAG_SIZE = 16;
|
static constexpr unsigned int TAG_SIZE = 16;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<class BlockCipher, unsigned int KeySize>
|
||||||
|
constexpr unsigned int GCM_Cipher<BlockCipher, KeySize>::KEYSIZE;
|
||||||
|
template<class BlockCipher, unsigned int KeySize>
|
||||||
|
constexpr unsigned int GCM_Cipher<BlockCipher, KeySize>::STRING_KEYSIZE;
|
||||||
|
|
||||||
template<typename BlockCipher, unsigned int KeySize>
|
template<typename BlockCipher, unsigned int KeySize>
|
||||||
Data GCM_Cipher<BlockCipher, KeySize>::encrypt(const CryptoPP::byte *plaintext, unsigned int plaintextSize, const EncryptionKey &encKey) {
|
Data GCM_Cipher<BlockCipher, KeySize>::encrypt(const CryptoPP::byte *plaintext, unsigned int plaintextSize, const EncryptionKey &encKey) {
|
||||||
|
ASSERT(encKey.binaryLength() == KeySize, "Wrong key size");
|
||||||
|
|
||||||
FixedSizeData<IV_SIZE> iv = Random::PseudoRandom().getFixedSize<IV_SIZE>();
|
FixedSizeData<IV_SIZE> iv = Random::PseudoRandom().getFixedSize<IV_SIZE>();
|
||||||
typename CryptoPP::GCM<BlockCipher, CryptoPP::GCM_64K_Tables>::Encryption encryption;
|
typename CryptoPP::GCM<BlockCipher, CryptoPP::GCM_64K_Tables>::Encryption encryption;
|
||||||
encryption.SetKeyWithIV(static_cast<const CryptoPP::byte*>(encKey.data()), encKey.BINARY_LENGTH, iv.data(), IV_SIZE);
|
encryption.SetKeyWithIV(static_cast<const CryptoPP::byte*>(encKey.data()), encKey.binaryLength(), iv.data(), IV_SIZE);
|
||||||
Data ciphertext(ciphertextSize(plaintextSize));
|
Data ciphertext(ciphertextSize(plaintextSize));
|
||||||
|
|
||||||
iv.ToBinary(ciphertext.data());
|
iv.ToBinary(ciphertext.data());
|
||||||
@ -52,6 +62,8 @@ Data GCM_Cipher<BlockCipher, KeySize>::encrypt(const CryptoPP::byte *plaintext,
|
|||||||
|
|
||||||
template<typename BlockCipher, unsigned int KeySize>
|
template<typename BlockCipher, unsigned int KeySize>
|
||||||
boost::optional<Data> GCM_Cipher<BlockCipher, KeySize>::decrypt(const CryptoPP::byte *ciphertext, unsigned int ciphertextSize, const EncryptionKey &encKey) {
|
boost::optional<Data> GCM_Cipher<BlockCipher, KeySize>::decrypt(const CryptoPP::byte *ciphertext, unsigned int ciphertextSize, const EncryptionKey &encKey) {
|
||||||
|
ASSERT(encKey.binaryLength() == KeySize, "Wrong key size");
|
||||||
|
|
||||||
if (ciphertextSize < IV_SIZE + TAG_SIZE) {
|
if (ciphertextSize < IV_SIZE + TAG_SIZE) {
|
||||||
return boost::none;
|
return boost::none;
|
||||||
}
|
}
|
||||||
@ -59,7 +71,7 @@ boost::optional<Data> GCM_Cipher<BlockCipher, KeySize>::decrypt(const CryptoPP::
|
|||||||
const CryptoPP::byte *ciphertextIV = ciphertext;
|
const CryptoPP::byte *ciphertextIV = ciphertext;
|
||||||
const CryptoPP::byte *ciphertextData = ciphertext + IV_SIZE;
|
const CryptoPP::byte *ciphertextData = ciphertext + IV_SIZE;
|
||||||
typename CryptoPP::GCM<BlockCipher, CryptoPP::GCM_64K_Tables>::Decryption decryption;
|
typename CryptoPP::GCM<BlockCipher, CryptoPP::GCM_64K_Tables>::Decryption decryption;
|
||||||
decryption.SetKeyWithIV(static_cast<const CryptoPP::byte*>(encKey.data()), encKey.BINARY_LENGTH, ciphertextIV, IV_SIZE);
|
decryption.SetKeyWithIV(static_cast<const CryptoPP::byte*>(encKey.data()), encKey.binaryLength(), ciphertextIV, IV_SIZE);
|
||||||
Data plaintext(plaintextSize(ciphertextSize));
|
Data plaintext(plaintextSize(ciphertextSize));
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#include "FakeAuthenticatedCipher.h"
|
#include "FakeAuthenticatedCipher.h"
|
||||||
|
|
||||||
namespace cpputils {
|
namespace cpputils {
|
||||||
constexpr unsigned int FakeKey::BINARY_LENGTH;
|
constexpr unsigned int FakeAuthenticatedCipher::KEYSIZE;
|
||||||
|
constexpr unsigned int FakeAuthenticatedCipher::STRING_KEYSIZE;
|
||||||
std::random_device FakeAuthenticatedCipher::random_;
|
std::random_device FakeAuthenticatedCipher::random_;
|
||||||
}
|
}
|
||||||
|
@ -17,9 +17,12 @@ namespace cpputils {
|
|||||||
return FakeKey{static_cast<uint64_t>(std::strtol(keyData.c_str(), nullptr, 10))};
|
return FakeKey{static_cast<uint64_t>(std::strtol(keyData.c_str(), nullptr, 10))};
|
||||||
}
|
}
|
||||||
|
|
||||||
static constexpr unsigned int BINARY_LENGTH = sizeof(uint64_t);
|
size_t binaryLength() const {
|
||||||
|
return sizeof(uint64_t);
|
||||||
|
}
|
||||||
|
|
||||||
static FakeKey CreateKey(RandomGenerator &randomGenerator) {
|
static FakeKey CreateKey(RandomGenerator &randomGenerator, size_t keySize) {
|
||||||
|
ASSERT(keySize == sizeof(uint64_t), "Wrong key size");
|
||||||
auto data = randomGenerator.getFixedSize<sizeof(uint64_t)>();
|
auto data = randomGenerator.getFixedSize<sizeof(uint64_t)>();
|
||||||
return FakeKey {*reinterpret_cast<uint64_t*>(data.data())};
|
return FakeKey {*reinterpret_cast<uint64_t*>(data.data())};
|
||||||
}
|
}
|
||||||
@ -34,6 +37,9 @@ namespace cpputils {
|
|||||||
|
|
||||||
using EncryptionKey = FakeKey;
|
using EncryptionKey = FakeKey;
|
||||||
|
|
||||||
|
static constexpr unsigned int KEYSIZE = sizeof(uint64_t);
|
||||||
|
static constexpr unsigned int STRING_KEYSIZE = 2 * KEYSIZE;
|
||||||
|
|
||||||
static EncryptionKey Key1() {
|
static EncryptionKey Key1() {
|
||||||
return FakeKey{5};
|
return FakeKey{5};
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
#include <cpp-utils/io/DontEchoStdinToStdoutRAII.h>
|
#include <cpp-utils/io/DontEchoStdinToStdoutRAII.h>
|
||||||
#include <cryfs/filesystem/CryDevice.h>
|
#include <cryfs/filesystem/CryDevice.h>
|
||||||
#include <cryfs/config/CryConfigLoader.h>
|
#include <cryfs/config/CryConfigLoader.h>
|
||||||
|
#include <cryfs/config/CryPasswordBasedKeyProvider.h>
|
||||||
#include "program_options/Parser.h"
|
#include "program_options/Parser.h"
|
||||||
#include <boost/filesystem.hpp>
|
#include <boost/filesystem.hpp>
|
||||||
|
|
||||||
@ -41,6 +42,7 @@ using cpputils::NoninteractiveConsole;
|
|||||||
using cpputils::TempFile;
|
using cpputils::TempFile;
|
||||||
using cpputils::RandomGenerator;
|
using cpputils::RandomGenerator;
|
||||||
using cpputils::unique_ref;
|
using cpputils::unique_ref;
|
||||||
|
using cpputils::SCrypt;
|
||||||
using cpputils::SCryptSettings;
|
using cpputils::SCryptSettings;
|
||||||
using cpputils::Console;
|
using cpputils::Console;
|
||||||
using cpputils::HttpClient;
|
using cpputils::HttpClient;
|
||||||
@ -65,7 +67,7 @@ using gitversion::VersionCompare;
|
|||||||
|
|
||||||
namespace cryfs {
|
namespace cryfs {
|
||||||
|
|
||||||
Cli::Cli(RandomGenerator &keyGenerator, const SCryptSettings &scryptSettings, shared_ptr<Console> console):
|
Cli::Cli(RandomGenerator &keyGenerator, const SCryptSettings& scryptSettings, shared_ptr<Console> console):
|
||||||
_keyGenerator(keyGenerator), _scryptSettings(scryptSettings), _console(), _noninteractive(false) {
|
_keyGenerator(keyGenerator), _scryptSettings(scryptSettings), _console(), _noninteractive(false) {
|
||||||
_noninteractive = Environment::isNoninteractive();
|
_noninteractive = Environment::isNoninteractive();
|
||||||
if (_noninteractive) {
|
if (_noninteractive) {
|
||||||
@ -133,6 +135,7 @@ namespace cryfs {
|
|||||||
};
|
};
|
||||||
|
|
||||||
function<string()> Cli::_askPasswordForNewFilesystem(std::shared_ptr<cpputils::Console> console) {
|
function<string()> Cli::_askPasswordForNewFilesystem(std::shared_ptr<cpputils::Console> console) {
|
||||||
|
//TODO Ask confirmation if using insecure password (<8 characters)
|
||||||
return [console] () {
|
return [console] () {
|
||||||
string password;
|
string password;
|
||||||
bool again = false;
|
bool again = false;
|
||||||
@ -204,17 +207,16 @@ namespace cryfs {
|
|||||||
}
|
}
|
||||||
|
|
||||||
optional<CryConfigLoader::ConfigLoadResult> Cli::_loadOrCreateConfigFile(bf::path configFilePath, LocalStateDir localStateDir, const optional<string> &cipher, const optional<uint32_t> &blocksizeBytes, bool allowFilesystemUpgrade, const optional<bool> &missingBlockIsIntegrityViolation, bool allowReplacedFilesystem) {
|
optional<CryConfigLoader::ConfigLoadResult> Cli::_loadOrCreateConfigFile(bf::path configFilePath, LocalStateDir localStateDir, const optional<string> &cipher, const optional<uint32_t> &blocksizeBytes, bool allowFilesystemUpgrade, const optional<bool> &missingBlockIsIntegrityViolation, bool allowReplacedFilesystem) {
|
||||||
if (_noninteractive) {
|
// TODO Instead of passing in _askPasswordXXX functions to KeyProvider, only pass in console and move logic to the key provider,
|
||||||
return CryConfigLoader(_console, _keyGenerator, std::move(localStateDir), _scryptSettings,
|
// for example by having a separate CryPasswordBasedKeyProvider / CryNoninteractivePasswordBasedKeyProvider.
|
||||||
Cli::_askPasswordNoninteractive(_console),
|
auto keyProvider = make_unique_ref<CryPasswordBasedKeyProvider>(
|
||||||
Cli::_askPasswordNoninteractive(_console),
|
_console,
|
||||||
cipher, blocksizeBytes, missingBlockIsIntegrityViolation).loadOrCreate(std::move(configFilePath), allowFilesystemUpgrade, allowReplacedFilesystem);
|
_noninteractive ? Cli::_askPasswordNoninteractive(_console) : Cli::_askPasswordForExistingFilesystem(_console),
|
||||||
} else {
|
_noninteractive ? Cli::_askPasswordNoninteractive(_console) : Cli::_askPasswordForNewFilesystem(_console),
|
||||||
return CryConfigLoader(_console, _keyGenerator, std::move(localStateDir), _scryptSettings,
|
make_unique_ref<SCrypt>(_scryptSettings)
|
||||||
Cli::_askPasswordForExistingFilesystem(_console),
|
);
|
||||||
Cli::_askPasswordForNewFilesystem(_console),
|
return CryConfigLoader(_console, _keyGenerator, std::move(keyProvider), std::move(localStateDir),
|
||||||
cipher, blocksizeBytes, missingBlockIsIntegrityViolation).loadOrCreate(std::move(configFilePath), allowFilesystemUpgrade, allowReplacedFilesystem);
|
cipher, blocksizeBytes, missingBlockIsIntegrityViolation).loadOrCreate(std::move(configFilePath), allowFilesystemUpgrade, allowReplacedFilesystem);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Cli::_runFilesystem(const ProgramOptions &options) {
|
void Cli::_runFilesystem(const ProgramOptions &options) {
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
namespace cryfs {
|
namespace cryfs {
|
||||||
class Cli final {
|
class Cli final {
|
||||||
public:
|
public:
|
||||||
Cli(cpputils::RandomGenerator &keyGenerator, const cpputils::SCryptSettings &scryptSettings, std::shared_ptr<cpputils::Console> console);
|
Cli(cpputils::RandomGenerator &keyGenerator, const cpputils::SCryptSettings& scryptSettings, std::shared_ptr<cpputils::Console> console);
|
||||||
int main(int argc, const char *argv[], cpputils::unique_ref<cpputils::HttpClient> httpClient);
|
int main(int argc, const char *argv[], cpputils::unique_ref<cpputils::HttpClient> httpClient);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
#include "Cli.h"
|
#include "Cli.h"
|
||||||
#include <cpp-utils/random/Random.h>
|
#include <cpp-utils/random/Random.h>
|
||||||
#include <cpp-utils/crypto/kdf/Scrypt.h>
|
|
||||||
#include <cpp-utils/io/IOStreamConsole.h>
|
#include <cpp-utils/io/IOStreamConsole.h>
|
||||||
#include <cryfs/CryfsException.h>
|
#include <cryfs/CryfsException.h>
|
||||||
|
|
||||||
@ -22,9 +21,9 @@ int main(int argc, const char *argv[]) {
|
|||||||
try {
|
try {
|
||||||
auto &keyGenerator = Random::OSRandom();
|
auto &keyGenerator = Random::OSRandom();
|
||||||
#if defined(_MSC_VER)
|
#if defined(_MSC_VER)
|
||||||
auto httpClient = make_unique_ref<cpputils::WinHttpClient>();
|
auto httpClient = make_unique_ref<cpputils::WinHttpClient>();
|
||||||
#else
|
#else
|
||||||
auto httpClient = make_unique_ref<cpputils::CurlHttpClient>();
|
auto httpClient = make_unique_ref<cpputils::CurlHttpClient>();
|
||||||
#endif
|
#endif
|
||||||
return Cli(keyGenerator, SCrypt::DefaultSettings, make_shared<IOStreamConsole>())
|
return Cli(keyGenerator, SCrypt::DefaultSettings, make_shared<IOStreamConsole>())
|
||||||
.main(argc, argv, std::move(httpClient));
|
.main(argc, argv, std::move(httpClient));
|
||||||
|
@ -16,6 +16,8 @@ set(LIB_SOURCES
|
|||||||
config/CryConfigFile.cpp
|
config/CryConfigFile.cpp
|
||||||
config/CryCipher.cpp
|
config/CryCipher.cpp
|
||||||
config/CryConfigCreator.cpp
|
config/CryConfigCreator.cpp
|
||||||
|
config/CryKeyProvider.cpp
|
||||||
|
config/CryPasswordBasedKeyProvider.cpp
|
||||||
filesystem/CryOpenFile.cpp
|
filesystem/CryOpenFile.cpp
|
||||||
filesystem/fsblobstore/utils/DirEntry.cpp
|
filesystem/fsblobstore/utils/DirEntry.cpp
|
||||||
filesystem/fsblobstore/utils/DirEntryList.cpp
|
filesystem/fsblobstore/utils/DirEntryList.cpp
|
||||||
|
@ -25,7 +25,7 @@ class CryCipherInstance: public CryCipher {
|
|||||||
public:
|
public:
|
||||||
BOOST_CONCEPT_ASSERT((CipherConcept<Cipher>));
|
BOOST_CONCEPT_ASSERT((CipherConcept<Cipher>));
|
||||||
|
|
||||||
static_assert(Cipher::EncryptionKey::BINARY_LENGTH <= CryCiphers::MAX_KEY_SIZE, "The key size for this cipher is too large. Please modify CryCiphers::MAX_KEY_SIZE");
|
static_assert(Cipher::KEYSIZE <= CryCiphers::MAX_KEY_SIZE, "The key size for this cipher is too large. Please modify CryCiphers::MAX_KEY_SIZE");
|
||||||
|
|
||||||
CryCipherInstance(const optional<string> warning = none): _warning(warning) {
|
CryCipherInstance(const optional<string> warning = none): _warning(warning) {
|
||||||
}
|
}
|
||||||
@ -43,11 +43,12 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
string createKey(cpputils::RandomGenerator &randomGenerator) const override {
|
string createKey(cpputils::RandomGenerator &randomGenerator) const override {
|
||||||
return Cipher::EncryptionKey::CreateKey(randomGenerator).ToString();
|
return Cipher::EncryptionKey::CreateKey(randomGenerator, Cipher::KEYSIZE).ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
unique_ref<InnerEncryptor> createInnerConfigEncryptor(const EncryptionKey<CryCiphers::MAX_KEY_SIZE>& key) const override {
|
unique_ref<InnerEncryptor> createInnerConfigEncryptor(const EncryptionKey& key) const override {
|
||||||
return make_unique_ref<ConcreteInnerEncryptor<Cipher>>(key.take<Cipher::EncryptionKey::BINARY_LENGTH>());
|
ASSERT(key.binaryLength() == CryCiphers::MAX_KEY_SIZE, "Wrong key size");
|
||||||
|
return make_unique_ref<ConcreteInnerEncryptor<Cipher>>(key.take(Cipher::KEYSIZE));
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -41,7 +41,7 @@ public:
|
|||||||
virtual const boost::optional<std::string> &warning() const = 0;
|
virtual const boost::optional<std::string> &warning() const = 0;
|
||||||
virtual cpputils::unique_ref<blockstore::BlockStore2> createEncryptedBlockstore(cpputils::unique_ref<blockstore::BlockStore2> baseBlockStore, const std::string &encKey) const = 0;
|
virtual cpputils::unique_ref<blockstore::BlockStore2> createEncryptedBlockstore(cpputils::unique_ref<blockstore::BlockStore2> baseBlockStore, const std::string &encKey) const = 0;
|
||||||
virtual std::string createKey(cpputils::RandomGenerator &randomGenerator) const = 0;
|
virtual std::string createKey(cpputils::RandomGenerator &randomGenerator) const = 0;
|
||||||
virtual cpputils::unique_ref<InnerEncryptor> createInnerConfigEncryptor(const cpputils::EncryptionKey<CryCiphers::MAX_KEY_SIZE> &key) const = 0;
|
virtual cpputils::unique_ref<InnerEncryptor> createInnerConfigEncryptor(const cpputils::EncryptionKey &key) const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -73,7 +73,7 @@ namespace cryfs {
|
|||||||
}
|
}
|
||||||
|
|
||||||
string CryConfigCreator::_generateEncKey(const std::string &cipher) {
|
string CryConfigCreator::_generateEncKey(const std::string &cipher) {
|
||||||
_console->print("\nGenerating secure encryption key. This might take some time..");
|
_console->print("\nGenerating secure encryption key. This can take some time...");
|
||||||
auto key = CryCiphers::find(cipher).createKey(_encryptionKeyGenerator);
|
auto key = CryCiphers::find(cipher).createKey(_encryptionKeyGenerator);
|
||||||
_console->print("done\n");
|
_console->print("done\n");
|
||||||
return key;
|
return key;
|
||||||
|
@ -15,7 +15,6 @@ using std::stringstream;
|
|||||||
using std::istream;
|
using std::istream;
|
||||||
using cpputils::Data;
|
using cpputils::Data;
|
||||||
using cpputils::unique_ref;
|
using cpputils::unique_ref;
|
||||||
using cpputils::SCryptSettings;
|
|
||||||
namespace bf = boost::filesystem;
|
namespace bf = boost::filesystem;
|
||||||
using namespace cpputils::logging;
|
using namespace cpputils::logging;
|
||||||
|
|
||||||
@ -25,13 +24,13 @@ CryConfigFile::~CryConfigFile() {
|
|||||||
//We do not call save() here, because we do not want the config file to be re-encrypted on each filesystem run
|
//We do not call save() here, because we do not want the config file to be re-encrypted on each filesystem run
|
||||||
}
|
}
|
||||||
|
|
||||||
optional<CryConfigFile> CryConfigFile::load(bf::path path, const string &password) {
|
optional<CryConfigFile> CryConfigFile::load(bf::path path, CryKeyProvider* keyProvider) {
|
||||||
auto encryptedConfigData = Data::LoadFromFile(path);
|
auto encryptedConfigData = Data::LoadFromFile(path);
|
||||||
if (encryptedConfigData == none) {
|
if (encryptedConfigData == none) {
|
||||||
LOG(ERR, "Config file not found");
|
LOG(ERR, "Config file not found");
|
||||||
return none;
|
return none;
|
||||||
}
|
}
|
||||||
auto encryptor = CryConfigEncryptorFactory::loadKey(*encryptedConfigData, password);
|
auto encryptor = CryConfigEncryptorFactory::loadExistingKey(*encryptedConfigData, keyProvider);
|
||||||
if (encryptor == none) {
|
if (encryptor == none) {
|
||||||
return none;
|
return none;
|
||||||
}
|
}
|
||||||
@ -53,11 +52,11 @@ optional<CryConfigFile> CryConfigFile::load(bf::path path, const string &passwor
|
|||||||
return std::move(configFile);
|
return std::move(configFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
CryConfigFile CryConfigFile::create(bf::path path, CryConfig config, const string &password, const SCryptSettings &scryptSettings) {
|
CryConfigFile CryConfigFile::create(bf::path path, CryConfig config, CryKeyProvider* keyProvider) {
|
||||||
if (bf::exists(path)) {
|
if (bf::exists(path)) {
|
||||||
throw std::runtime_error("Config file exists already.");
|
throw std::runtime_error("Config file exists already.");
|
||||||
}
|
}
|
||||||
auto result = CryConfigFile(std::move(path), std::move(config), CryConfigEncryptorFactory::deriveKey(password, scryptSettings));
|
auto result = CryConfigFile(std::move(path), std::move(config), CryConfigEncryptorFactory::deriveNewKey(keyProvider));
|
||||||
result.save();
|
result.save();
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -14,8 +14,8 @@ namespace cryfs {
|
|||||||
CryConfigFile(CryConfigFile &&rhs) = default;
|
CryConfigFile(CryConfigFile &&rhs) = default;
|
||||||
~CryConfigFile();
|
~CryConfigFile();
|
||||||
|
|
||||||
static CryConfigFile create(boost::filesystem::path path, CryConfig config, const std::string &password, const cpputils::SCryptSettings &scryptSettings);
|
static CryConfigFile create(boost::filesystem::path path, CryConfig config, CryKeyProvider* keyProvider);
|
||||||
static boost::optional<CryConfigFile> load(boost::filesystem::path path, const std::string &password);
|
static boost::optional<CryConfigFile> load(boost::filesystem::path path, CryKeyProvider* keyProvider);
|
||||||
void save() const;
|
void save() const;
|
||||||
|
|
||||||
CryConfig *config();
|
CryConfig *config();
|
||||||
|
@ -13,34 +13,29 @@
|
|||||||
namespace bf = boost::filesystem;
|
namespace bf = boost::filesystem;
|
||||||
using cpputils::Console;
|
using cpputils::Console;
|
||||||
using cpputils::RandomGenerator;
|
using cpputils::RandomGenerator;
|
||||||
using cpputils::SCryptSettings;
|
using cpputils::unique_ref;
|
||||||
using boost::optional;
|
using boost::optional;
|
||||||
using boost::none;
|
using boost::none;
|
||||||
using std::shared_ptr;
|
using std::shared_ptr;
|
||||||
using std::string;
|
using std::string;
|
||||||
using std::function;
|
|
||||||
using std::shared_ptr;
|
using std::shared_ptr;
|
||||||
using gitversion::VersionCompare;
|
using gitversion::VersionCompare;
|
||||||
using namespace cpputils::logging;
|
using namespace cpputils::logging;
|
||||||
|
|
||||||
namespace cryfs {
|
namespace cryfs {
|
||||||
|
|
||||||
CryConfigLoader::CryConfigLoader(shared_ptr<Console> console, RandomGenerator &keyGenerator, LocalStateDir localStateDir, const SCryptSettings &scryptSettings, function<string()> askPasswordForExistingFilesystem, function<string()> askPasswordForNewFilesystem, const optional<string> &cipherFromCommandLine, const boost::optional<uint32_t> &blocksizeBytesFromCommandLine, const boost::optional<bool> &missingBlockIsIntegrityViolationFromCommandLine)
|
CryConfigLoader::CryConfigLoader(shared_ptr<Console> console, RandomGenerator &keyGenerator, unique_ref<CryKeyProvider> keyProvider, LocalStateDir localStateDir, const optional<string> &cipherFromCommandLine, const boost::optional<uint32_t> &blocksizeBytesFromCommandLine, const boost::optional<bool> &missingBlockIsIntegrityViolationFromCommandLine)
|
||||||
: _console(console), _creator(std::move(console), keyGenerator, localStateDir), _scryptSettings(scryptSettings),
|
: _console(console), _creator(std::move(console), keyGenerator, localStateDir), _keyProvider(std::move(keyProvider)),
|
||||||
_askPasswordForExistingFilesystem(askPasswordForExistingFilesystem), _askPasswordForNewFilesystem(askPasswordForNewFilesystem),
|
|
||||||
_cipherFromCommandLine(cipherFromCommandLine), _blocksizeBytesFromCommandLine(blocksizeBytesFromCommandLine),
|
_cipherFromCommandLine(cipherFromCommandLine), _blocksizeBytesFromCommandLine(blocksizeBytesFromCommandLine),
|
||||||
_missingBlockIsIntegrityViolationFromCommandLine(missingBlockIsIntegrityViolationFromCommandLine),
|
_missingBlockIsIntegrityViolationFromCommandLine(missingBlockIsIntegrityViolationFromCommandLine),
|
||||||
_localStateDir(std::move(localStateDir)) {
|
_localStateDir(std::move(localStateDir)) {
|
||||||
}
|
}
|
||||||
|
|
||||||
optional<CryConfigLoader::ConfigLoadResult> CryConfigLoader::_loadConfig(bf::path filename, bool allowFilesystemUpgrade, bool allowReplacedFilesystem) {
|
optional<CryConfigLoader::ConfigLoadResult> CryConfigLoader::_loadConfig(bf::path filename, bool allowFilesystemUpgrade, bool allowReplacedFilesystem) {
|
||||||
string password = _askPasswordForExistingFilesystem();
|
auto config = CryConfigFile::load(std::move(filename), _keyProvider.get());
|
||||||
std::cout << "Loading config file (this can take some time)..." << std::flush;
|
|
||||||
auto config = CryConfigFile::load(std::move(filename), password);
|
|
||||||
if (config == none) {
|
if (config == none) {
|
||||||
return none;
|
return none;
|
||||||
}
|
}
|
||||||
std::cout << "done" << std::endl;
|
|
||||||
#ifndef CRYFS_NO_COMPATIBILITY
|
#ifndef CRYFS_NO_COMPATIBILITY
|
||||||
//Since 0.9.7 and 0.9.8 set their own version to cryfs.version instead of the filesystem format version (which is 0.9.6), overwrite it
|
//Since 0.9.7 and 0.9.8 set their own version to cryfs.version instead of the filesystem format version (which is 0.9.6), overwrite it
|
||||||
if (config->config()->Version() == "0.9.7" || config->config()->Version() == "0.9.8") {
|
if (config->config()->Version() == "0.9.7" || config->config()->Version() == "0.9.8") {
|
||||||
@ -117,11 +112,7 @@ optional<CryConfigLoader::ConfigLoadResult> CryConfigLoader::loadOrCreate(bf::pa
|
|||||||
|
|
||||||
CryConfigLoader::ConfigLoadResult CryConfigLoader::_createConfig(bf::path filename, bool allowReplacedFilesystem) {
|
CryConfigLoader::ConfigLoadResult CryConfigLoader::_createConfig(bf::path filename, bool allowReplacedFilesystem) {
|
||||||
auto config = _creator.create(_cipherFromCommandLine, _blocksizeBytesFromCommandLine, _missingBlockIsIntegrityViolationFromCommandLine, allowReplacedFilesystem);
|
auto config = _creator.create(_cipherFromCommandLine, _blocksizeBytesFromCommandLine, _missingBlockIsIntegrityViolationFromCommandLine, allowReplacedFilesystem);
|
||||||
//TODO Ask confirmation if using insecure password (<8 characters)
|
auto result = CryConfigFile::create(std::move(filename), std::move(config.config), _keyProvider.get());
|
||||||
string password = _askPasswordForNewFilesystem();
|
|
||||||
std::cout << "Creating config file (this can take some time)..." << std::flush;
|
|
||||||
auto result = CryConfigFile::create(std::move(filename), std::move(config.config), password, _scryptSettings);
|
|
||||||
std::cout << "done" << std::endl;
|
|
||||||
return ConfigLoadResult {std::move(result), config.myClientId};
|
return ConfigLoadResult {std::move(result), config.myClientId};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,13 +7,14 @@
|
|||||||
#include "CryConfigFile.h"
|
#include "CryConfigFile.h"
|
||||||
#include "CryCipher.h"
|
#include "CryCipher.h"
|
||||||
#include "CryConfigCreator.h"
|
#include "CryConfigCreator.h"
|
||||||
#include <cpp-utils/crypto/kdf/Scrypt.h>
|
#include "CryKeyProvider.h"
|
||||||
|
|
||||||
namespace cryfs {
|
namespace cryfs {
|
||||||
|
|
||||||
class CryConfigLoader final {
|
class CryConfigLoader final {
|
||||||
public:
|
public:
|
||||||
CryConfigLoader(std::shared_ptr<cpputils::Console> console, cpputils::RandomGenerator &keyGenerator, LocalStateDir localStateDir, const cpputils::SCryptSettings &scryptSettings, std::function<std::string()> askPasswordForExistingFilesystem, std::function<std::string()> askPasswordForNewFilesystem, const boost::optional<std::string> &cipherFromCommandLine, const boost::optional<uint32_t> &blocksizeBytesFromCommandLine, const boost::optional<bool> &missingBlockIsIntegrityViolationFromCommandLine);
|
// note: keyGenerator generates the inner (i.e. file system) key. keyProvider asks for the password and generates the outer (i.e. config file) key.
|
||||||
|
CryConfigLoader(std::shared_ptr<cpputils::Console> console, cpputils::RandomGenerator &keyGenerator, cpputils::unique_ref<CryKeyProvider> keyProvider, LocalStateDir localStateDir, const boost::optional<std::string> &cipherFromCommandLine, const boost::optional<uint32_t> &blocksizeBytesFromCommandLine, const boost::optional<bool> &missingBlockIsIntegrityViolationFromCommandLine);
|
||||||
CryConfigLoader(CryConfigLoader &&rhs) = default;
|
CryConfigLoader(CryConfigLoader &&rhs) = default;
|
||||||
|
|
||||||
struct ConfigLoadResult {
|
struct ConfigLoadResult {
|
||||||
@ -32,9 +33,7 @@ private:
|
|||||||
|
|
||||||
std::shared_ptr<cpputils::Console> _console;
|
std::shared_ptr<cpputils::Console> _console;
|
||||||
CryConfigCreator _creator;
|
CryConfigCreator _creator;
|
||||||
cpputils::SCryptSettings _scryptSettings;
|
cpputils::unique_ref<CryKeyProvider> _keyProvider;
|
||||||
std::function<std::string()> _askPasswordForExistingFilesystem;
|
|
||||||
std::function<std::string()> _askPasswordForNewFilesystem;
|
|
||||||
boost::optional<std::string> _cipherFromCommandLine;
|
boost::optional<std::string> _cipherFromCommandLine;
|
||||||
boost::optional<uint32_t> _blocksizeBytesFromCommandLine;
|
boost::optional<uint32_t> _blocksizeBytesFromCommandLine;
|
||||||
boost::optional<bool> _missingBlockIsIntegrityViolationFromCommandLine;
|
boost::optional<bool> _missingBlockIsIntegrityViolationFromCommandLine;
|
||||||
|
1
src/cryfs/config/CryKeyProvider.cpp
Normal file
1
src/cryfs/config/CryKeyProvider.cpp
Normal file
@ -0,0 +1 @@
|
|||||||
|
#include "CryKeyProvider.h"
|
24
src/cryfs/config/CryKeyProvider.h
Normal file
24
src/cryfs/config/CryKeyProvider.h
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
#pragma once
|
||||||
|
#ifndef CRYFS_CRYKEYPROVIDER_H
|
||||||
|
#define CRYFS_CRYKEYPROVIDER_H
|
||||||
|
|
||||||
|
#include <cpp-utils/crypto/symmetric/EncryptionKey.h>
|
||||||
|
|
||||||
|
namespace cryfs {
|
||||||
|
|
||||||
|
class CryKeyProvider {
|
||||||
|
public:
|
||||||
|
virtual ~CryKeyProvider() = default;
|
||||||
|
|
||||||
|
struct KeyResult final {
|
||||||
|
cpputils::EncryptionKey key;
|
||||||
|
cpputils::Data kdfParameters;
|
||||||
|
};
|
||||||
|
|
||||||
|
virtual cpputils::EncryptionKey requestKeyForExistingFilesystem(size_t keySize, const cpputils::Data& kdfParameters) = 0;
|
||||||
|
virtual KeyResult requestKeyForNewFilesystem(size_t keySize) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
31
src/cryfs/config/CryPasswordBasedKeyProvider.cpp
Normal file
31
src/cryfs/config/CryPasswordBasedKeyProvider.cpp
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
#include "CryPasswordBasedKeyProvider.h"
|
||||||
|
|
||||||
|
using std::shared_ptr;
|
||||||
|
using cpputils::Console;
|
||||||
|
using cpputils::unique_ref;
|
||||||
|
using cpputils::EncryptionKey;
|
||||||
|
using cpputils::unique_ref;
|
||||||
|
using cpputils::PasswordBasedKDF;
|
||||||
|
|
||||||
|
namespace cryfs {
|
||||||
|
|
||||||
|
CryPasswordBasedKeyProvider::CryPasswordBasedKeyProvider(shared_ptr<Console> console, std::function<std::string()> askPasswordForExistingFilesystem, std::function<std::string()> askPasswordForNewFilesystem, unique_ref<PasswordBasedKDF> kdf)
|
||||||
|
: _console(std::move(console)), _askPasswordForExistingFilesystem(std::move(askPasswordForExistingFilesystem)), _askPasswordForNewFilesystem(std::move(askPasswordForNewFilesystem)), _kdf(std::move(kdf)) {}
|
||||||
|
|
||||||
|
EncryptionKey CryPasswordBasedKeyProvider::requestKeyForExistingFilesystem(size_t keySize, const cpputils::Data& kdfParameters) {
|
||||||
|
auto password = _askPasswordForExistingFilesystem();
|
||||||
|
_console->print("Deriving encryption key (this can take some time)...");
|
||||||
|
auto key = _kdf->deriveExistingKey(keySize, password, kdfParameters);
|
||||||
|
_console->print("done\n");
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
|
CryKeyProvider::KeyResult CryPasswordBasedKeyProvider::requestKeyForNewFilesystem(size_t keySize) {
|
||||||
|
auto password = _askPasswordForNewFilesystem();
|
||||||
|
_console->print("Deriving encryption key (this can take some time)...");
|
||||||
|
auto keyResult = _kdf->deriveNewKey(keySize, password);
|
||||||
|
_console->print("done\n");
|
||||||
|
return {std::move(keyResult.key), std::move(keyResult.kdfParameters)};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
31
src/cryfs/config/CryPasswordBasedKeyProvider.h
Normal file
31
src/cryfs/config/CryPasswordBasedKeyProvider.h
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
#pragma once
|
||||||
|
#ifndef CRYFS_CRYPASSWORDFROMCONSOLEKEYPROVIDER_H
|
||||||
|
#define CRYFS_CRYPASSWORDFROMCONSOLEKEYPROVIDER_H
|
||||||
|
|
||||||
|
#include "CryKeyProvider.h"
|
||||||
|
#include <functional>
|
||||||
|
#include <cpp-utils/crypto/kdf/Scrypt.h>
|
||||||
|
#include <cpp-utils/io/Console.h>
|
||||||
|
|
||||||
|
namespace cryfs {
|
||||||
|
|
||||||
|
class CryPasswordBasedKeyProvider final : public CryKeyProvider {
|
||||||
|
public:
|
||||||
|
// TODO Pass in KDF as dependency (needs changes in the KDF interface because of the static functions ::forNewKey and ::forExistingKey)
|
||||||
|
explicit CryPasswordBasedKeyProvider(std::shared_ptr<cpputils::Console> console, std::function<std::string()> askPasswordForExistingFilesystem, std::function<std::string()> askPasswordForNewFilesystem, cpputils::unique_ref<cpputils::PasswordBasedKDF> kdf);
|
||||||
|
|
||||||
|
cpputils::EncryptionKey requestKeyForExistingFilesystem(size_t keySize, const cpputils::Data& kdfParameters) override;
|
||||||
|
KeyResult requestKeyForNewFilesystem(size_t keySize) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::shared_ptr<cpputils::Console> _console;
|
||||||
|
std::function<std::string()> _askPasswordForExistingFilesystem;
|
||||||
|
std::function<std::string()> _askPasswordForNewFilesystem;
|
||||||
|
cpputils::unique_ref<cpputils::PasswordBasedKDF> _kdf;
|
||||||
|
|
||||||
|
DISALLOW_COPY_AND_ASSIGN(CryPasswordBasedKeyProvider);
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
@ -13,8 +13,9 @@ namespace cryfs {
|
|||||||
constexpr size_t CryConfigEncryptor::OuterKeySize;
|
constexpr size_t CryConfigEncryptor::OuterKeySize;
|
||||||
constexpr size_t CryConfigEncryptor::MaxTotalKeySize;
|
constexpr size_t CryConfigEncryptor::MaxTotalKeySize;
|
||||||
|
|
||||||
CryConfigEncryptor::CryConfigEncryptor(cpputils::EncryptionKey<MaxTotalKeySize> derivedKey, cpputils::Data kdfParameters)
|
CryConfigEncryptor::CryConfigEncryptor(cpputils::EncryptionKey derivedKey, cpputils::Data kdfParameters)
|
||||||
: _derivedKey(std::move(derivedKey)), _kdfParameters(std::move(kdfParameters)) {
|
: _derivedKey(std::move(derivedKey)), _kdfParameters(std::move(kdfParameters)) {
|
||||||
|
ASSERT(_derivedKey.binaryLength() == MaxTotalKeySize, "Wrong key size");
|
||||||
}
|
}
|
||||||
|
|
||||||
Data CryConfigEncryptor::encrypt(const Data &plaintext, const string &cipherName) const {
|
Data CryConfigEncryptor::encrypt(const Data &plaintext, const string &cipherName) const {
|
||||||
@ -45,12 +46,12 @@ namespace cryfs {
|
|||||||
}
|
}
|
||||||
|
|
||||||
unique_ref<OuterEncryptor> CryConfigEncryptor::_outerEncryptor() const {
|
unique_ref<OuterEncryptor> CryConfigEncryptor::_outerEncryptor() const {
|
||||||
auto outerKey = _derivedKey.take<OuterKeySize>();
|
auto outerKey = _derivedKey.take(OuterKeySize);
|
||||||
return make_unique_ref<OuterEncryptor>(std::move(outerKey), _kdfParameters.copy());
|
return make_unique_ref<OuterEncryptor>(std::move(outerKey), _kdfParameters.copy());
|
||||||
}
|
}
|
||||||
|
|
||||||
unique_ref<InnerEncryptor> CryConfigEncryptor::_innerEncryptor(const string &cipherName) const {
|
unique_ref<InnerEncryptor> CryConfigEncryptor::_innerEncryptor(const string &cipherName) const {
|
||||||
auto innerKey = _derivedKey.drop<OuterKeySize>();
|
auto innerKey = _derivedKey.drop(OuterKeySize);
|
||||||
return CryCiphers::find(cipherName).createInnerConfigEncryptor(std::move(innerKey));
|
return CryCiphers::find(cipherName).createInnerConfigEncryptor(std::move(innerKey));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,7 @@ namespace cryfs {
|
|||||||
//TODO Use own exception for cpputils::Serializer/cpputils::Deserializer errors and only catch them
|
//TODO Use own exception for cpputils::Serializer/cpputils::Deserializer errors and only catch them
|
||||||
class CryConfigEncryptor final {
|
class CryConfigEncryptor final {
|
||||||
public:
|
public:
|
||||||
static constexpr size_t OuterKeySize = OuterEncryptor::Cipher::EncryptionKey::BINARY_LENGTH;
|
static constexpr size_t OuterKeySize = OuterEncryptor::Cipher::KEYSIZE;
|
||||||
static constexpr size_t MaxTotalKeySize = OuterKeySize + CryCiphers::MAX_KEY_SIZE;
|
static constexpr size_t MaxTotalKeySize = OuterKeySize + CryCiphers::MAX_KEY_SIZE;
|
||||||
|
|
||||||
struct Decrypted {
|
struct Decrypted {
|
||||||
@ -23,7 +23,7 @@ namespace cryfs {
|
|||||||
bool wasInDeprecatedConfigFormat;
|
bool wasInDeprecatedConfigFormat;
|
||||||
};
|
};
|
||||||
|
|
||||||
CryConfigEncryptor(cpputils::EncryptionKey<MaxTotalKeySize> derivedKey, cpputils::Data _kdfParameters);
|
CryConfigEncryptor(cpputils::EncryptionKey derivedKey, cpputils::Data _kdfParameters);
|
||||||
|
|
||||||
cpputils::Data encrypt(const cpputils::Data &plaintext, const std::string &cipherName) const;
|
cpputils::Data encrypt(const cpputils::Data &plaintext, const std::string &cipherName) const;
|
||||||
boost::optional<Decrypted> decrypt(const cpputils::Data &data) const;
|
boost::optional<Decrypted> decrypt(const cpputils::Data &data) const;
|
||||||
@ -32,7 +32,7 @@ namespace cryfs {
|
|||||||
cpputils::unique_ref<OuterEncryptor> _outerEncryptor() const;
|
cpputils::unique_ref<OuterEncryptor> _outerEncryptor() const;
|
||||||
cpputils::unique_ref<InnerEncryptor> _innerEncryptor(const std::string &cipherName) const;
|
cpputils::unique_ref<InnerEncryptor> _innerEncryptor(const std::string &cipherName) const;
|
||||||
|
|
||||||
cpputils::EncryptionKey<MaxTotalKeySize> _derivedKey;
|
cpputils::EncryptionKey _derivedKey;
|
||||||
cpputils::Data _kdfParameters;
|
cpputils::Data _kdfParameters;
|
||||||
|
|
||||||
DISALLOW_COPY_AND_ASSIGN(CryConfigEncryptor);
|
DISALLOW_COPY_AND_ASSIGN(CryConfigEncryptor);
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#include "CryConfigEncryptorFactory.h"
|
#include "CryConfigEncryptorFactory.h"
|
||||||
#include <cpp-utils/crypto/symmetric/ciphers.h>
|
#include <cpp-utils/crypto/symmetric/ciphers.h>
|
||||||
#include "outer/OuterConfig.h"
|
#include "outer/OuterConfig.h"
|
||||||
|
#include "cryfs/config/CryKeyProvider.h"
|
||||||
|
|
||||||
using namespace cpputils::logging;
|
using namespace cpputils::logging;
|
||||||
using boost::optional;
|
using boost::optional;
|
||||||
@ -8,32 +9,27 @@ using boost::none;
|
|||||||
using cpputils::unique_ref;
|
using cpputils::unique_ref;
|
||||||
using cpputils::make_unique_ref;
|
using cpputils::make_unique_ref;
|
||||||
using cpputils::Data;
|
using cpputils::Data;
|
||||||
using cpputils::SCrypt;
|
|
||||||
using cpputils::SCryptSettings;
|
|
||||||
using std::string;
|
using std::string;
|
||||||
|
|
||||||
|
//TODO It would be better, not to generate a MaxTotalKeySize key here, but to generate the outer key first, and then
|
||||||
|
// (once we know which inner cipher was used) only generate as many key bytes as we need for the inner cipher.
|
||||||
|
// This would need a change in the scrypt interface though, because right now we can't continue past key computations.
|
||||||
|
//TODO I might be able to know the actual key size here (at runtime) and switch the SCrypt deriveKey() interface to getting a dynamic size.
|
||||||
|
|
||||||
namespace cryfs {
|
namespace cryfs {
|
||||||
|
|
||||||
optional<unique_ref<CryConfigEncryptor>> CryConfigEncryptorFactory::loadKey(const Data &data,
|
optional<unique_ref<CryConfigEncryptor>> CryConfigEncryptorFactory::loadExistingKey(const Data &data,
|
||||||
const string &password) {
|
CryKeyProvider *keyProvider) {
|
||||||
auto outerConfig = OuterConfig::deserialize(data);
|
auto outerConfig = OuterConfig::deserialize(data);
|
||||||
if (outerConfig == none) {
|
if (outerConfig == none) {
|
||||||
return none;
|
return none;
|
||||||
}
|
}
|
||||||
return _deriveKey(SCrypt::forExistingKey(outerConfig->kdfParameters), password);
|
auto key = keyProvider->requestKeyForExistingFilesystem(CryConfigEncryptor::MaxTotalKeySize, outerConfig->kdfParameters);
|
||||||
|
return make_unique_ref<CryConfigEncryptor>(key, std::move(outerConfig->kdfParameters));
|
||||||
}
|
}
|
||||||
|
|
||||||
unique_ref<CryConfigEncryptor> CryConfigEncryptorFactory::deriveKey(const string &password, const SCryptSettings &scryptSettings) {
|
unique_ref<CryConfigEncryptor> CryConfigEncryptorFactory::deriveNewKey(CryKeyProvider *keyProvider) {
|
||||||
return _deriveKey(SCrypt::forNewKey(scryptSettings), password);
|
auto keyResult = keyProvider->requestKeyForNewFilesystem(CryConfigEncryptor::MaxTotalKeySize);
|
||||||
}
|
return make_unique_ref<CryConfigEncryptor>(std::move(keyResult.key), std::move(keyResult.kdfParameters));
|
||||||
|
|
||||||
unique_ref<CryConfigEncryptor>
|
|
||||||
CryConfigEncryptorFactory::_deriveKey(cpputils::unique_ref<SCrypt> kdf, const string &password) {
|
|
||||||
//TODO It would be better, not to generate a MaxTotalKeySize key here, but to generate the outer key first, and then
|
|
||||||
// (once we know which inner cipher was used) only generate as many key bytes as we need for the inner cipher.
|
|
||||||
// This would need a change in the scrypt interface though, because right now we can't continue past key computations.
|
|
||||||
//TODO I might be able to know the actual key size here (at runtime) and switch the SCrypt deriveKey() interface to getting a dynamic size.
|
|
||||||
auto key = kdf->deriveKey<CryConfigEncryptor::MaxTotalKeySize>(password);
|
|
||||||
return make_unique_ref<CryConfigEncryptor>(key, kdf->kdfParameters().copy());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,16 +9,14 @@
|
|||||||
#include "../CryCipher.h"
|
#include "../CryCipher.h"
|
||||||
|
|
||||||
namespace cryfs {
|
namespace cryfs {
|
||||||
|
class CryKeyProvider;
|
||||||
|
|
||||||
class CryConfigEncryptorFactory final {
|
class CryConfigEncryptorFactory final {
|
||||||
public:
|
public:
|
||||||
static cpputils::unique_ref<CryConfigEncryptor> deriveKey(const std::string &password, const cpputils::SCryptSettings &scryptSettings);
|
static cpputils::unique_ref<CryConfigEncryptor> deriveNewKey(CryKeyProvider *keyProvider);
|
||||||
|
|
||||||
static boost::optional<cpputils::unique_ref<CryConfigEncryptor>> loadKey(const cpputils::Data &ciphertext,
|
static boost::optional<cpputils::unique_ref<CryConfigEncryptor>> loadExistingKey(const cpputils::Data &ciphertext,
|
||||||
const std::string &password);
|
CryKeyProvider *keyProvider);
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
static cpputils::unique_ref<CryConfigEncryptor> _deriveKey(cpputils::unique_ref<cpputils::SCrypt> kdf, const std::string &password);
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <boost/filesystem.hpp>
|
#include <boost/filesystem.hpp>
|
||||||
#include <cryfs/config/CryConfigFile.h>
|
#include <cryfs/config/CryConfigFile.h>
|
||||||
|
#include <cryfs/config/CryPasswordBasedKeyProvider.h>
|
||||||
#include <blockstore/implementations/ondisk/OnDiskBlockStore2.h>
|
#include <blockstore/implementations/ondisk/OnDiskBlockStore2.h>
|
||||||
#include <blockstore/implementations/low2highlevel/LowToHighLevelBlockStore.h>
|
#include <blockstore/implementations/low2highlevel/LowToHighLevelBlockStore.h>
|
||||||
#include <blobstore/implementations/onblocks/datanodestore/DataNodeStore.h>
|
#include <blobstore/implementations/onblocks/datanodestore/DataNodeStore.h>
|
||||||
@ -11,6 +12,7 @@
|
|||||||
#include <cryfs/filesystem/fsblobstore/FsBlobStore.h>
|
#include <cryfs/filesystem/fsblobstore/FsBlobStore.h>
|
||||||
#include <cryfs/filesystem/fsblobstore/DirBlob.h>
|
#include <cryfs/filesystem/fsblobstore/DirBlob.h>
|
||||||
#include <cryfs/filesystem/CryDevice.h>
|
#include <cryfs/filesystem/CryDevice.h>
|
||||||
|
#include <cpp-utils/io/IOStreamConsole.h>
|
||||||
|
|
||||||
#include <set>
|
#include <set>
|
||||||
|
|
||||||
@ -112,11 +114,19 @@ set<BlockId> _getBlocksReferencedByDirEntries(const CryConfig &config) {
|
|||||||
|
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
cout << "Password: ";
|
auto console = std::make_shared<cpputils::IOStreamConsole>();
|
||||||
string password;
|
|
||||||
getline(cin, password);
|
console->print("Loading config\n");
|
||||||
cout << "Loading config" << endl;
|
auto askPassword = [console] () {
|
||||||
auto config = CryConfigFile::load("/home/heinzi/basedir/cryfs.config", password);
|
return console->askPassword("Password: ");
|
||||||
|
};
|
||||||
|
auto keyProvider = make_unique_ref<CryPasswordBasedKeyProvider>(
|
||||||
|
console,
|
||||||
|
askPassword,
|
||||||
|
askPassword,
|
||||||
|
make_unique_ref<SCrypt>(SCrypt::DefaultSettings)
|
||||||
|
);
|
||||||
|
auto config = CryConfigFile::load("/home/heinzi/basedir/cryfs.config", keyProvider.get());
|
||||||
set<BlockId> unaccountedBlocks = _getBlockstoreUnaccountedBlocks(*config->config());
|
set<BlockId> unaccountedBlocks = _getBlockstoreUnaccountedBlocks(*config->config());
|
||||||
//Remove all blocks that are referenced by a directory entry from unaccountedBlocks
|
//Remove all blocks that are referenced by a directory entry from unaccountedBlocks
|
||||||
set<BlockId> blocksReferencedByDirEntries = _getBlocksReferencedByDirEntries(*config->config());
|
set<BlockId> blocksReferencedByDirEntries = _getBlocksReferencedByDirEntries(*config->config());
|
||||||
@ -124,7 +134,7 @@ int main() {
|
|||||||
unaccountedBlocks.erase(blockId);
|
unaccountedBlocks.erase(blockId);
|
||||||
}
|
}
|
||||||
|
|
||||||
cout << "\nCalculate statistics" << endl;
|
console->print("Calculate statistics\n");
|
||||||
|
|
||||||
auto onDiskBlockStore = make_unique_ref<OnDiskBlockStore2>("/home/heinzi/basedir");
|
auto onDiskBlockStore = make_unique_ref<OnDiskBlockStore2>("/home/heinzi/basedir");
|
||||||
auto encryptedBlockStore = CryCiphers::find(config->config()->Cipher()).createEncryptedBlockstore(std::move(onDiskBlockStore), config->config()->EncryptionKey());
|
auto encryptedBlockStore = CryCiphers::find(config->config()->Cipher()).createEncryptedBlockstore(std::move(onDiskBlockStore), config->config()->EncryptionKey());
|
||||||
@ -134,9 +144,9 @@ int main() {
|
|||||||
uint32_t numUnaccountedBlocks = unaccountedBlocks.size();
|
uint32_t numUnaccountedBlocks = unaccountedBlocks.size();
|
||||||
uint32_t numLeaves = 0;
|
uint32_t numLeaves = 0;
|
||||||
uint32_t numInner = 0;
|
uint32_t numInner = 0;
|
||||||
cout << "\nUnaccounted blocks: " << unaccountedBlocks.size() << endl;
|
console->print("Unaccounted blocks: " + std::to_string(unaccountedBlocks.size()) + "\n");
|
||||||
for (const auto &blockId : unaccountedBlocks) {
|
for (const auto &blockId : unaccountedBlocks) {
|
||||||
std::cout << "\r" << (numLeaves+numInner) << "/" << numUnaccountedBlocks << flush;
|
console->print("\r" + std::to_string(numLeaves+numInner) + "/" + std::to_string(numUnaccountedBlocks));
|
||||||
auto node = nodeStore->load(blockId);
|
auto node = nodeStore->load(blockId);
|
||||||
auto innerNode = dynamic_pointer_move<DataInnerNode>(*node);
|
auto innerNode = dynamic_pointer_move<DataInnerNode>(*node);
|
||||||
if (innerNode != none) {
|
if (innerNode != none) {
|
||||||
@ -149,5 +159,5 @@ int main() {
|
|||||||
printNode(std::move(*leafNode));
|
printNode(std::move(*leafNode));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cout << "\n" << numLeaves << " leaves and " << numInner << " inner nodes" << endl;
|
console->print("\n" + std::to_string(numLeaves) + " leaves and " + std::to_string(numInner) + " inner nodes\n");
|
||||||
}
|
}
|
||||||
|
@ -36,7 +36,7 @@ public:
|
|||||||
private:
|
private:
|
||||||
static typename Cipher::EncryptionKey createKeyFixture(int seed = 0) {
|
static typename Cipher::EncryptionKey createKeyFixture(int seed = 0) {
|
||||||
return Cipher::EncryptionKey::FromString(
|
return Cipher::EncryptionKey::FromString(
|
||||||
DataFixture::generate(Cipher::EncryptionKey::BINARY_LENGTH, seed).ToString()
|
DataFixture::generate(Cipher::KEYSIZE, seed).ToString()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -55,7 +55,7 @@ public:
|
|||||||
private:
|
private:
|
||||||
static typename Cipher::EncryptionKey createKeyFixture(int seed = 0) {
|
static typename Cipher::EncryptionKey createKeyFixture(int seed = 0) {
|
||||||
return Cipher::EncryptionKey::FromString(
|
return Cipher::EncryptionKey::FromString(
|
||||||
DataFixture::generate(Cipher::EncryptionKey::BINARY_LENGTH, seed).ToString()
|
DataFixture::generate(Cipher::KEYSIZE, seed).ToString()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -6,53 +6,51 @@ using std::string;
|
|||||||
|
|
||||||
class SCryptTest : public ::testing::Test {
|
class SCryptTest : public ::testing::Test {
|
||||||
public:
|
public:
|
||||||
unique_ref<SCrypt> scryptForNewKey = SCrypt::forNewKey(SCrypt::TestSettings);
|
bool keyEquals(const EncryptionKey& lhs, const EncryptionKey& rhs) {
|
||||||
unique_ref<SCrypt> scryptForExistingKey = SCrypt::forExistingKey(scryptForNewKey->kdfParameters());
|
ASSERT(lhs.binaryLength() == rhs.binaryLength(), "Keys must have equal size to be comparable");
|
||||||
|
return 0 == std::memcmp(lhs.data(), rhs.data(), lhs.binaryLength());
|
||||||
SCryptParameters kdfParameters(const SCrypt &scrypt) {
|
|
||||||
SCryptParameters result = SCryptParameters::deserialize(scrypt.kdfParameters());
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<size_t SIZE>
|
|
||||||
bool keyEquals(const EncryptionKey<SIZE>& lhs, const EncryptionKey<SIZE>& rhs) {
|
|
||||||
return 0 == std::memcmp(lhs.data(), rhs.data(), SIZE);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
TEST_F(SCryptTest, GeneratedKeyIsReproductible_448) {
|
TEST_F(SCryptTest, GeneratedKeyIsReproductible_448) {
|
||||||
auto derivedKey = scryptForNewKey->deriveKey<56>("mypassword");
|
SCrypt scrypt(SCrypt::TestSettings);
|
||||||
auto rederivedKey = scryptForExistingKey->deriveKey<56>("mypassword");
|
auto derivedKey = scrypt.deriveNewKey(56, "mypassword");
|
||||||
EXPECT_TRUE(keyEquals(derivedKey, rederivedKey));
|
auto rederivedKey = scrypt.deriveExistingKey(56, "mypassword", derivedKey.kdfParameters);
|
||||||
|
EXPECT_TRUE(keyEquals(derivedKey.key, rederivedKey));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(SCryptTest, GeneratedKeyIsReproductible_256) {
|
TEST_F(SCryptTest, GeneratedKeyIsReproductible_256) {
|
||||||
auto derivedKey = scryptForNewKey->deriveKey<32>("mypassword");
|
SCrypt scrypt(SCrypt::TestSettings);
|
||||||
auto rederivedKey = scryptForExistingKey->deriveKey<32>("mypassword");
|
auto derivedKey = scrypt.deriveNewKey(32, "mypassword");
|
||||||
EXPECT_TRUE(keyEquals(derivedKey, rederivedKey));
|
auto rederivedKey = scrypt.deriveExistingKey(32, "mypassword", derivedKey.kdfParameters);
|
||||||
|
EXPECT_TRUE(keyEquals(derivedKey.key, rederivedKey));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(SCryptTest, GeneratedKeyIsReproductible_128) {
|
TEST_F(SCryptTest, GeneratedKeyIsReproductible_128) {
|
||||||
auto derivedKey = scryptForNewKey->deriveKey<16>("mypassword");
|
SCrypt scrypt(SCrypt::TestSettings);
|
||||||
auto rederivedKey = scryptForExistingKey->deriveKey<16>("mypassword");
|
auto derivedKey = scrypt.deriveNewKey(16, "mypassword");
|
||||||
EXPECT_TRUE(keyEquals(derivedKey, rederivedKey));
|
auto rederivedKey = scrypt.deriveExistingKey(16, "mypassword", derivedKey.kdfParameters);
|
||||||
|
EXPECT_TRUE(keyEquals(derivedKey.key, rederivedKey));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(SCryptTest, GeneratedKeyIsReproductible_DefaultSettings) {
|
TEST_F(SCryptTest, GeneratedKeyIsReproductible_DefaultSettings) {
|
||||||
auto derivedKey = scryptForNewKey->deriveKey<16>("mypassword");
|
SCrypt scrypt(SCrypt::TestSettings);
|
||||||
auto rederivedKey = scryptForExistingKey->deriveKey<16>("mypassword");
|
auto derivedKey = scrypt.deriveNewKey(16, "mypassword");
|
||||||
EXPECT_TRUE(keyEquals(derivedKey, rederivedKey));
|
auto rederivedKey = scrypt.deriveExistingKey(16, "mypassword", derivedKey.kdfParameters);
|
||||||
|
EXPECT_TRUE(keyEquals(derivedKey.key, rederivedKey));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(SCryptTest, DifferentPasswordResultsInDifferentKey) {
|
TEST_F(SCryptTest, DifferentPasswordResultsInDifferentKey) {
|
||||||
auto derivedKey = scryptForNewKey->deriveKey<16>("mypassword");
|
SCrypt scrypt(SCrypt::TestSettings);
|
||||||
auto rederivedKey = scryptForExistingKey->deriveKey<16>("mypassword2");
|
auto derivedKey = scrypt.deriveNewKey(16, "mypassword");
|
||||||
EXPECT_FALSE(keyEquals(derivedKey, rederivedKey));
|
auto rederivedKey = scrypt.deriveExistingKey(16, "mypassword2", derivedKey.kdfParameters);
|
||||||
|
EXPECT_FALSE(keyEquals(derivedKey.key, rederivedKey));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(SCryptTest, UsesCorrectSettings) {
|
TEST_F(SCryptTest, UsesCorrectSettings) {
|
||||||
auto scrypt = SCrypt::forNewKey(SCrypt::TestSettings);
|
SCrypt scrypt(SCrypt::TestSettings);
|
||||||
SCryptParameters parameters = kdfParameters(*scrypt);
|
auto derivedKey = scrypt.deriveNewKey(16, "mypassword");
|
||||||
|
auto parameters = SCryptParameters::deserialize(derivedKey.kdfParameters);
|
||||||
EXPECT_EQ(SCrypt::TestSettings.SALT_LEN, parameters.salt().size());
|
EXPECT_EQ(SCrypt::TestSettings.SALT_LEN, parameters.salt().size());
|
||||||
EXPECT_EQ(SCrypt::TestSettings.N, parameters.N());
|
EXPECT_EQ(SCrypt::TestSettings.N, parameters.N());
|
||||||
EXPECT_EQ(SCrypt::TestSettings.r, parameters.r());
|
EXPECT_EQ(SCrypt::TestSettings.r, parameters.r());
|
||||||
@ -60,8 +58,9 @@ TEST_F(SCryptTest, UsesCorrectSettings) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(SCryptTest, UsesCorrectDefaultSettings) {
|
TEST_F(SCryptTest, UsesCorrectDefaultSettings) {
|
||||||
auto scrypt = SCrypt::forNewKey(SCrypt::DefaultSettings);
|
SCrypt scrypt(SCrypt::DefaultSettings);
|
||||||
SCryptParameters parameters = kdfParameters(*scrypt);
|
auto derivedKey = scrypt.deriveNewKey(16, "mypassword");
|
||||||
|
auto parameters = SCryptParameters::deserialize(derivedKey.kdfParameters);
|
||||||
EXPECT_EQ(SCrypt::DefaultSettings.SALT_LEN, parameters.salt().size());
|
EXPECT_EQ(SCrypt::DefaultSettings.SALT_LEN, parameters.salt().size());
|
||||||
EXPECT_EQ(SCrypt::DefaultSettings.N, parameters.N());
|
EXPECT_EQ(SCrypt::DefaultSettings.N, parameters.N());
|
||||||
EXPECT_EQ(SCrypt::DefaultSettings.r, parameters.r());
|
EXPECT_EQ(SCrypt::DefaultSettings.r, parameters.r());
|
||||||
|
@ -18,7 +18,7 @@ public:
|
|||||||
typename Cipher::EncryptionKey encKey = createKeyFixture();
|
typename Cipher::EncryptionKey encKey = createKeyFixture();
|
||||||
|
|
||||||
static typename Cipher::EncryptionKey createKeyFixture(int seed = 0) {
|
static typename Cipher::EncryptionKey createKeyFixture(int seed = 0) {
|
||||||
Data data = DataFixture::generate(Cipher::EncryptionKey::BINARY_LENGTH, seed);
|
Data data = DataFixture::generate(Cipher::KEYSIZE, seed);
|
||||||
return Cipher::EncryptionKey::FromString(data.ToString());
|
return Cipher::EncryptionKey::FromString(data.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,23 +1,45 @@
|
|||||||
#include "testutils/CliTest.h"
|
#include "testutils/CliTest.h"
|
||||||
#include <cryfs/config/CryConfigFile.h>
|
#include <cryfs/config/CryConfigFile.h>
|
||||||
#include <cryfs/ErrorCodes.h>
|
#include <cryfs/ErrorCodes.h>
|
||||||
|
#include <cpp-utils/crypto/kdf/Scrypt.h>
|
||||||
|
#include <cpp-utils/data/DataFixture.h>
|
||||||
|
|
||||||
using std::vector;
|
using std::vector;
|
||||||
using std::string;
|
using std::string;
|
||||||
using cryfs::CryConfig;
|
using cryfs::CryConfig;
|
||||||
using cryfs::CryConfigFile;
|
using cryfs::CryConfigFile;
|
||||||
using cryfs::ErrorCode;
|
using cryfs::ErrorCode;
|
||||||
|
using cryfs::CryKeyProvider;
|
||||||
|
using cpputils::Data;
|
||||||
|
using cpputils::EncryptionKey;
|
||||||
|
using cpputils::SCrypt;
|
||||||
|
|
||||||
|
class FakeCryKeyProvider final : public CryKeyProvider {
|
||||||
|
EncryptionKey requestKeyForExistingFilesystem(size_t keySize, const Data& kdfParameters) override {
|
||||||
|
return SCrypt(SCrypt::TestSettings).deriveExistingKey(keySize, "pass", kdfParameters);
|
||||||
|
}
|
||||||
|
|
||||||
|
KeyResult requestKeyForNewFilesystem(size_t keySize) override {
|
||||||
|
auto derived = SCrypt(SCrypt::TestSettings).deriveNewKey(keySize, "pass");
|
||||||
|
return {
|
||||||
|
std::move(derived.key),
|
||||||
|
std::move(derived.kdfParameters)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
class CliTest_IntegrityCheck: public CliTest {
|
class CliTest_IntegrityCheck: public CliTest {
|
||||||
public:
|
public:
|
||||||
void modifyFilesystemId() {
|
void modifyFilesystemId() {
|
||||||
auto configFile = CryConfigFile::load(basedir / "cryfs.config", "pass").value();
|
FakeCryKeyProvider keyProvider;
|
||||||
|
auto configFile = CryConfigFile::load(basedir / "cryfs.config", &keyProvider).value();
|
||||||
configFile.config()->SetFilesystemId(CryConfig::FilesystemID::FromString("0123456789ABCDEF0123456789ABCDEF"));
|
configFile.config()->SetFilesystemId(CryConfig::FilesystemID::FromString("0123456789ABCDEF0123456789ABCDEF"));
|
||||||
configFile.save();
|
configFile.save();
|
||||||
}
|
}
|
||||||
|
|
||||||
void modifyFilesystemKey() {
|
void modifyFilesystemKey() {
|
||||||
auto configFile = CryConfigFile::load(basedir / "cryfs.config", "pass").value();
|
FakeCryKeyProvider keyProvider;
|
||||||
|
auto configFile = CryConfigFile::load(basedir / "cryfs.config", &keyProvider).value();
|
||||||
configFile.config()->SetEncryptionKey("0123456789ABCDEF0123456789ABCDEF");
|
configFile.config()->SetEncryptionKey("0123456789ABCDEF0123456789ABCDEF");
|
||||||
configFile.save();
|
configFile.save();
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,7 @@ set(SOURCES
|
|||||||
config/CryCipherTest.cpp
|
config/CryCipherTest.cpp
|
||||||
config/CryConfigLoaderTest.cpp
|
config/CryConfigLoaderTest.cpp
|
||||||
config/CryConfigConsoleTest.cpp
|
config/CryConfigConsoleTest.cpp
|
||||||
|
config/CryPasswordBasedKeyProviderTest.cpp
|
||||||
filesystem/CryFsTest.cpp
|
filesystem/CryFsTest.cpp
|
||||||
filesystem/CryNodeTest.cpp
|
filesystem/CryNodeTest.cpp
|
||||||
filesystem/FileSystemTest.cpp
|
filesystem/FileSystemTest.cpp
|
||||||
|
@ -7,11 +7,16 @@
|
|||||||
#include <cpp-utils/crypto/symmetric/ciphers.h>
|
#include <cpp-utils/crypto/symmetric/ciphers.h>
|
||||||
#include <cpp-utils/tempfile/TempFile.h>
|
#include <cpp-utils/tempfile/TempFile.h>
|
||||||
#include <cryfs/config/CryConfigFile.h>
|
#include <cryfs/config/CryConfigFile.h>
|
||||||
|
#include <cryfs/config/CryPasswordBasedKeyProvider.h>
|
||||||
|
#include "../testutils/MockConsole.h"
|
||||||
|
|
||||||
using cpputils::Data;
|
using cpputils::Data;
|
||||||
using cpputils::AES256_GCM;
|
using cpputils::AES256_GCM;
|
||||||
using cpputils::Serpent128_CFB;
|
using cpputils::Serpent128_CFB;
|
||||||
using cpputils::TempFile;
|
using cpputils::TempFile;
|
||||||
|
using cpputils::make_unique_ref;
|
||||||
|
using cpputils::SCrypt;
|
||||||
|
using std::make_shared;
|
||||||
using namespace cryfs;
|
using namespace cryfs;
|
||||||
|
|
||||||
// Test that config files created with (old) versions of cryfs are still loadable.
|
// Test that config files created with (old) versions of cryfs are still loadable.
|
||||||
@ -23,7 +28,13 @@ public:
|
|||||||
|
|
||||||
CryConfigFile loadConfigFromHex(const string &configFileContentHex) {
|
CryConfigFile loadConfigFromHex(const string &configFileContentHex) {
|
||||||
storeHexToFile(configFileContentHex);
|
storeHexToFile(configFileContentHex);
|
||||||
return CryConfigFile::load(file.path(), "mypassword").value();
|
CryPasswordBasedKeyProvider keyProvider(
|
||||||
|
make_shared<MockConsole>(),
|
||||||
|
[] () {return "mypassword"; },
|
||||||
|
[] () {return "mypassword"; },
|
||||||
|
make_unique_ref<SCrypt>(SCrypt::DefaultSettings)
|
||||||
|
);
|
||||||
|
return CryConfigFile::load(file.path(), &keyProvider).value();
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -37,7 +37,7 @@ public:
|
|||||||
void EXPECT_CREATES_CORRECT_ENCRYPTED_BLOCKSTORE(const string &cipherName) {
|
void EXPECT_CREATES_CORRECT_ENCRYPTED_BLOCKSTORE(const string &cipherName) {
|
||||||
const auto &actualCipher = CryCiphers::find(cipherName);
|
const auto &actualCipher = CryCiphers::find(cipherName);
|
||||||
Data dataFixture = DataFixture::generate(1024);
|
Data dataFixture = DataFixture::generate(1024);
|
||||||
string encKey = ExpectedCipher::EncryptionKey::CreateKey(Random::PseudoRandom()).ToString();
|
string encKey = ExpectedCipher::EncryptionKey::CreateKey(Random::PseudoRandom(), ExpectedCipher::KEYSIZE).ToString();
|
||||||
_EXPECT_ENCRYPTS_WITH_ACTUAL_BLOCKSTORE_DECRYPTS_CORRECTLY_WITH_EXPECTED_BLOCKSTORE<ExpectedCipher>(actualCipher, encKey, std::move(dataFixture));
|
_EXPECT_ENCRYPTS_WITH_ACTUAL_BLOCKSTORE_DECRYPTS_CORRECTLY_WITH_EXPECTED_BLOCKSTORE<ExpectedCipher>(actualCipher, encKey, std::move(dataFixture));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -125,14 +125,14 @@ TEST_F(CryCipherTest, ThereIsACipherWithIntegrityWarning) {
|
|||||||
|
|
||||||
#if CRYPTOPP_VERSION != 564
|
#if CRYPTOPP_VERSION != 564
|
||||||
TEST_F(CryCipherTest, EncryptionKeyHasCorrectSize_448) {
|
TEST_F(CryCipherTest, EncryptionKeyHasCorrectSize_448) {
|
||||||
EXPECT_EQ(Mars448_GCM::EncryptionKey::STRING_LENGTH, CryCiphers::find("mars-448-gcm").createKey(Random::PseudoRandom()).size());
|
EXPECT_EQ(Mars448_GCM::STRING_KEYSIZE, CryCiphers::find("mars-448-gcm").createKey(Random::PseudoRandom()).size());
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
TEST_F(CryCipherTest, EncryptionKeyHasCorrectSize_256) {
|
TEST_F(CryCipherTest, EncryptionKeyHasCorrectSize_256) {
|
||||||
EXPECT_EQ(AES256_GCM::EncryptionKey::STRING_LENGTH, CryCiphers::find("aes-256-gcm").createKey(Random::PseudoRandom()).size());
|
EXPECT_EQ(AES256_GCM::STRING_KEYSIZE, CryCiphers::find("aes-256-gcm").createKey(Random::PseudoRandom()).size());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(CryCipherTest, EncryptionKeyHasCorrectSize_128) {
|
TEST_F(CryCipherTest, EncryptionKeyHasCorrectSize_128) {
|
||||||
EXPECT_EQ(AES128_GCM::EncryptionKey::STRING_LENGTH, CryCiphers::find("aes-128-gcm").createKey(Random::PseudoRandom()).size());
|
EXPECT_EQ(AES128_GCM::STRING_KEYSIZE, CryCiphers::find("aes-128-gcm").createKey(Random::PseudoRandom()).size());
|
||||||
}
|
}
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
#include <gtest/gtest.h>
|
#include <gtest/gtest.h>
|
||||||
#include <cryfs/config/CryConfigFile.h>
|
#include <cryfs/config/CryConfigFile.h>
|
||||||
#include <cpp-utils/tempfile/TempFile.h>
|
#include <cpp-utils/tempfile/TempFile.h>
|
||||||
|
#include "../testutils/FakeCryKeyProvider.h"
|
||||||
|
|
||||||
using namespace cryfs;
|
using namespace cryfs;
|
||||||
using cpputils::TempFile;
|
using cpputils::TempFile;
|
||||||
using std::string;
|
using std::string;
|
||||||
using boost::optional;
|
using boost::optional;
|
||||||
using boost::none;
|
using boost::none;
|
||||||
using cpputils::SCrypt;
|
|
||||||
using cpputils::Data;
|
using cpputils::Data;
|
||||||
namespace bf = boost::filesystem;
|
namespace bf = boost::filesystem;
|
||||||
|
|
||||||
@ -33,17 +33,19 @@ public:
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
CryConfigFile CreateAndLoadEmpty(const string &password = "mypassword") {
|
CryConfigFile CreateAndLoadEmpty(unsigned char keySeed = 0) {
|
||||||
Create(Config(), password);
|
Create(Config(), keySeed);
|
||||||
return Load().value();
|
return Load().value();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Create(CryConfig cfg, const string &password = "mypassword") {
|
void Create(CryConfig cfg, unsigned int keySeed = 0) {
|
||||||
CryConfigFile::create(file.path(), std::move(cfg), password, SCrypt::TestSettings);
|
FakeCryKeyProvider keyProvider(keySeed);
|
||||||
|
CryConfigFile::create(file.path(), std::move(cfg), &keyProvider);
|
||||||
}
|
}
|
||||||
|
|
||||||
optional<CryConfigFile> Load(const string &password = "mypassword") {
|
optional<CryConfigFile> Load(unsigned int keySeed = 0) {
|
||||||
return CryConfigFile::load(file.path(), password);
|
FakeCryKeyProvider keyProvider(keySeed);
|
||||||
|
return CryConfigFile::load(file.path(), &keyProvider);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CreateWithCipher(const string &cipher) {
|
void CreateWithCipher(const string &cipher) {
|
||||||
@ -53,13 +55,16 @@ public:
|
|||||||
void CreateWithCipher(const string &cipher, const TempFile &tempFile) {
|
void CreateWithCipher(const string &cipher, const TempFile &tempFile) {
|
||||||
CryConfig cfg;
|
CryConfig cfg;
|
||||||
cfg.SetCipher(cipher);
|
cfg.SetCipher(cipher);
|
||||||
CryConfigFile::create(tempFile.path(), std::move(cfg), "mypassword", SCrypt::TestSettings);
|
FakeCryKeyProvider keyProvider(0);
|
||||||
|
CryConfigFile::create(tempFile.path(), std::move(cfg), &keyProvider);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
TEST_F(CryConfigFileTest, DoesntLoadIfWrongPassword) {
|
TEST_F(CryConfigFileTest, DoesntLoadIfWrongPassword) {
|
||||||
Create(Config(), "mypassword");
|
const unsigned char pw1 = 0;
|
||||||
auto loaded = Load("mypassword2");
|
const unsigned char pw2 = 1;
|
||||||
|
Create(Config(), pw1);
|
||||||
|
auto loaded = Load(pw2);
|
||||||
EXPECT_EQ(none, loaded);
|
EXPECT_EQ(none, loaded);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -190,11 +195,13 @@ TEST_F(CryConfigFileTest, CanSaveAndLoadModififedCipher) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(CryConfigFileTest, FailsIfConfigFileIsEncryptedWithACipherDifferentToTheOneSpecifiedByTheUser) {
|
TEST_F(CryConfigFileTest, FailsIfConfigFileIsEncryptedWithACipherDifferentToTheOneSpecifiedByTheUser) {
|
||||||
auto encryptor = CryConfigEncryptorFactory::deriveKey("mypassword", SCrypt::TestSettings);
|
constexpr unsigned char keySeed = 0;
|
||||||
|
FakeCryKeyProvider keyProvider(keySeed);
|
||||||
|
auto encryptor = CryConfigEncryptorFactory::deriveNewKey(&keyProvider);
|
||||||
auto config = Config();
|
auto config = Config();
|
||||||
config.SetCipher("aes-256-gcm");
|
config.SetCipher("aes-256-gcm");
|
||||||
Data encrypted = encryptor->encrypt(config.save(), "aes-256-cfb");
|
Data encrypted = encryptor->encrypt(config.save(), "aes-256-cfb");
|
||||||
encrypted.StoreToFile(file.path());
|
encrypted.StoreToFile(file.path());
|
||||||
auto loaded = Load("mypassword");
|
auto loaded = Load(keySeed);
|
||||||
EXPECT_EQ(none, loaded);
|
EXPECT_EQ(none, loaded);
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#include <gtest/gtest.h>
|
#include <gtest/gtest.h>
|
||||||
#include <cryfs/config/CryConfigLoader.h>
|
#include <cryfs/config/CryConfigLoader.h>
|
||||||
|
#include <cryfs/config/CryPasswordBasedKeyProvider.h>
|
||||||
#include "../testutils/MockConsole.h"
|
#include "../testutils/MockConsole.h"
|
||||||
#include "../testutils/TestWithFakeHomeDirectory.h"
|
#include "../testutils/TestWithFakeHomeDirectory.h"
|
||||||
#include <cpp-utils/tempfile/TempFile.h>
|
#include <cpp-utils/tempfile/TempFile.h>
|
||||||
@ -16,10 +17,15 @@ using cpputils::SCrypt;
|
|||||||
using cpputils::DataFixture;
|
using cpputils::DataFixture;
|
||||||
using cpputils::Data;
|
using cpputils::Data;
|
||||||
using cpputils::NoninteractiveConsole;
|
using cpputils::NoninteractiveConsole;
|
||||||
|
using cpputils::make_unique_ref;
|
||||||
|
using cpputils::Console;
|
||||||
|
using cpputils::unique_ref;
|
||||||
|
using cryfs::CryPasswordBasedKeyProvider;
|
||||||
using boost::optional;
|
using boost::optional;
|
||||||
using boost::none;
|
using boost::none;
|
||||||
using std::string;
|
using std::string;
|
||||||
using std::ostream;
|
using std::ostream;
|
||||||
|
using std::shared_ptr;
|
||||||
using std::make_shared;
|
using std::make_shared;
|
||||||
using ::testing::Return;
|
using ::testing::Return;
|
||||||
using ::testing::HasSubstr;
|
using ::testing::HasSubstr;
|
||||||
@ -56,19 +62,23 @@ private:
|
|||||||
|
|
||||||
class CryConfigLoaderTest: public ::testing::Test, public TestWithMockConsole, TestWithFakeHomeDirectory {
|
class CryConfigLoaderTest: public ::testing::Test, public TestWithMockConsole, TestWithFakeHomeDirectory {
|
||||||
public:
|
public:
|
||||||
|
unique_ref<CryKeyProvider> keyProvider(const string& password) {
|
||||||
|
auto askPassword = [password] { return password;};
|
||||||
|
return make_unique_ref<CryPasswordBasedKeyProvider>(
|
||||||
|
console,
|
||||||
|
askPassword,
|
||||||
|
askPassword,
|
||||||
|
make_unique_ref<SCrypt>(SCrypt::TestSettings)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
CryConfigLoaderTest(): file(false), tempLocalStateDir(), localStateDir(tempLocalStateDir.path()) {
|
CryConfigLoaderTest(): file(false), tempLocalStateDir(), localStateDir(tempLocalStateDir.path()) {
|
||||||
console = mockConsole();
|
console = mockConsole();
|
||||||
}
|
}
|
||||||
|
|
||||||
CryConfigLoader loader(const string &password, bool noninteractive, const optional<string> &cipher = none) {
|
CryConfigLoader loader(const string &password, bool noninteractive, const optional<string> &cipher = none) {
|
||||||
auto askPassword = [password] { return password;};
|
auto _console = noninteractive ? shared_ptr<Console>(make_shared<NoninteractiveConsole>(console)) : shared_ptr<Console>(console);
|
||||||
if(noninteractive) {
|
return CryConfigLoader(_console, cpputils::Random::PseudoRandom(), keyProvider(password), localStateDir, cipher, none, none);
|
||||||
return CryConfigLoader(make_shared<NoninteractiveConsole>(console), cpputils::Random::PseudoRandom(), localStateDir, SCrypt::TestSettings, askPassword,
|
|
||||||
askPassword, cipher, none, none);
|
|
||||||
} else {
|
|
||||||
return CryConfigLoader(console, cpputils::Random::PseudoRandom(), localStateDir, SCrypt::TestSettings, askPassword,
|
|
||||||
askPassword, cipher, none, none);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CryConfigFile Create(const string &password = "mypassword", const optional<string> &cipher = none, bool noninteractive = false) {
|
CryConfigFile Create(const string &password = "mypassword", const optional<string> &cipher = none, bool noninteractive = false) {
|
||||||
@ -98,15 +108,13 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void CreateWithEncryptionKey(const string &encKey, const string &password = "mypassword") {
|
void CreateWithEncryptionKey(const string &encKey, const string &password = "mypassword") {
|
||||||
auto askPassword = [password] { return password;};
|
|
||||||
FakeRandomGenerator generator(Data::FromString(encKey));
|
FakeRandomGenerator generator(Data::FromString(encKey));
|
||||||
auto loader = CryConfigLoader(console, generator, localStateDir, SCrypt::TestSettings, askPassword,
|
auto loader = CryConfigLoader(console, generator, keyProvider(password), localStateDir, none, none, none);
|
||||||
askPassword, none, none, none);
|
|
||||||
ASSERT_NE(boost::none, loader.loadOrCreate(file.path(), false, false));
|
ASSERT_NE(boost::none, loader.loadOrCreate(file.path(), false, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChangeEncryptionKey(const string &encKey, const string& password = "mypassword") {
|
void ChangeEncryptionKey(const string &encKey, const string& password = "mypassword") {
|
||||||
auto cfg = CryConfigFile::load(file.path(), password).value();
|
auto cfg = CryConfigFile::load(file.path(), keyProvider(password).get()).value();
|
||||||
cfg.config()->SetEncryptionKey(encKey);
|
cfg.config()->SetEncryptionKey(encKey);
|
||||||
cfg.save();
|
cfg.save();
|
||||||
}
|
}
|
||||||
@ -126,7 +134,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ChangeFilesystemID(const CryConfig::FilesystemID &filesystemId, const string& password = "mypassword") {
|
void ChangeFilesystemID(const CryConfig::FilesystemID &filesystemId, const string& password = "mypassword") {
|
||||||
auto cfg = CryConfigFile::load(file.path(), password).value();
|
auto cfg = CryConfigFile::load(file.path(), keyProvider(password).get()).value();
|
||||||
cfg.config()->SetFilesystemId(filesystemId);
|
cfg.config()->SetFilesystemId(filesystemId);
|
||||||
cfg.save();
|
cfg.save();
|
||||||
}
|
}
|
||||||
@ -258,7 +266,7 @@ TEST_F(CryConfigLoaderTest, Version_Load) {
|
|||||||
TEST_F(CryConfigLoaderTest, Version_Load_IsStoredAndNotOnlyOverwrittenInMemoryOnLoad) {
|
TEST_F(CryConfigLoaderTest, Version_Load_IsStoredAndNotOnlyOverwrittenInMemoryOnLoad) {
|
||||||
CreateWithVersion("0.9.2", "0.9.2", "mypassword");
|
CreateWithVersion("0.9.2", "0.9.2", "mypassword");
|
||||||
Load().value();
|
Load().value();
|
||||||
auto configFile = CryConfigFile::load(file.path(), "mypassword").value();
|
auto configFile = CryConfigFile::load(file.path(), keyProvider("mypassword").get()).value();
|
||||||
EXPECT_EQ(CryConfig::FilesystemFormatVersion, configFile.config()->Version());
|
EXPECT_EQ(CryConfig::FilesystemFormatVersion, configFile.config()->Version());
|
||||||
EXPECT_EQ(gitversion::VersionString(), configFile.config()->LastOpenedWithVersion());
|
EXPECT_EQ(gitversion::VersionString(), configFile.config()->LastOpenedWithVersion());
|
||||||
EXPECT_EQ("0.9.2", configFile.config()->CreatedWithVersion());
|
EXPECT_EQ("0.9.2", configFile.config()->CreatedWithVersion());
|
||||||
|
85
test/cryfs/config/CryPasswordBasedKeyProviderTest.cpp
Normal file
85
test/cryfs/config/CryPasswordBasedKeyProviderTest.cpp
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
#include <cryfs/config/CryPasswordBasedKeyProvider.h>
|
||||||
|
#include <gmock/gmock.h>
|
||||||
|
#include "../testutils/MockConsole.h"
|
||||||
|
#include <cpp-utils/data/DataFixture.h>
|
||||||
|
|
||||||
|
using cpputils::unique_ref;
|
||||||
|
using cpputils::make_unique_ref;
|
||||||
|
using cpputils::EncryptionKey;
|
||||||
|
using cpputils::PasswordBasedKDF;
|
||||||
|
using cpputils::Data;
|
||||||
|
using cpputils::DataFixture;
|
||||||
|
using std::shared_ptr;
|
||||||
|
using std::make_shared;
|
||||||
|
using std::string;
|
||||||
|
using cryfs::CryPasswordBasedKeyProvider;
|
||||||
|
using testing::Return;
|
||||||
|
using testing::Invoke;
|
||||||
|
using testing::Eq;
|
||||||
|
using testing::StrEq;
|
||||||
|
using testing::NiceMock;
|
||||||
|
using testing::_;
|
||||||
|
|
||||||
|
class MockCallable {
|
||||||
|
public:
|
||||||
|
MOCK_METHOD0(call, std::string());
|
||||||
|
};
|
||||||
|
|
||||||
|
class MockKDF : public PasswordBasedKDF {
|
||||||
|
public:
|
||||||
|
MOCK_METHOD3(deriveExistingKey, EncryptionKey(size_t keySize, const string& password, const Data& kdfParameters));
|
||||||
|
MOCK_METHOD2(deriveNewKey, KeyResult(size_t keySize, const string& password));
|
||||||
|
};
|
||||||
|
|
||||||
|
class CryPasswordBasedKeyProviderTest : public ::testing::Test {
|
||||||
|
public:
|
||||||
|
CryPasswordBasedKeyProviderTest()
|
||||||
|
: mockConsole(make_shared<NiceMock<MockConsole>>())
|
||||||
|
, askPasswordForNewFilesystem()
|
||||||
|
, askPasswordForExistingFilesystem()
|
||||||
|
, kdf_(make_unique_ref<MockKDF>())
|
||||||
|
, kdf(kdf_.get())
|
||||||
|
, keyProvider(mockConsole, [this] () {return askPasswordForExistingFilesystem.call();}, [this] () {return askPasswordForNewFilesystem.call(); }, std::move(kdf_)) {}
|
||||||
|
|
||||||
|
shared_ptr<NiceMock<MockConsole>> mockConsole;
|
||||||
|
MockCallable askPasswordForNewFilesystem;
|
||||||
|
MockCallable askPasswordForExistingFilesystem;
|
||||||
|
unique_ref<MockKDF> kdf_;
|
||||||
|
MockKDF* kdf;
|
||||||
|
|
||||||
|
CryPasswordBasedKeyProvider keyProvider;
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST_F(CryPasswordBasedKeyProviderTest, requestKeyForNewFilesystem) {
|
||||||
|
constexpr size_t keySize = 512;
|
||||||
|
constexpr const char* password = "mypassword";
|
||||||
|
const EncryptionKey key = EncryptionKey::FromString(DataFixture::generate(keySize).ToString());
|
||||||
|
const Data kdfParameters = DataFixture::generate(100);
|
||||||
|
|
||||||
|
EXPECT_CALL(askPasswordForNewFilesystem, call()).Times(1).WillOnce(Return(password));
|
||||||
|
EXPECT_CALL(askPasswordForExistingFilesystem, call()).Times(0);
|
||||||
|
EXPECT_CALL(*kdf, deriveNewKey(Eq(keySize), StrEq(password))).Times(1).WillOnce(Invoke([&] (auto, auto) {return PasswordBasedKDF::KeyResult{key, kdfParameters.copy()};}));
|
||||||
|
|
||||||
|
auto returned_key = keyProvider.requestKeyForNewFilesystem(keySize);
|
||||||
|
|
||||||
|
EXPECT_EQ(key.ToString(), returned_key.key.ToString());
|
||||||
|
EXPECT_EQ(kdfParameters, returned_key.kdfParameters);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(CryPasswordBasedKeyProviderTest, requestKeyForExistingFilesystem) {
|
||||||
|
constexpr size_t keySize = 512;
|
||||||
|
constexpr const char* password = "mypassword";
|
||||||
|
const EncryptionKey key = EncryptionKey::FromString(DataFixture::generate(keySize).ToString());
|
||||||
|
const Data kdfParameters = DataFixture::generate(100);
|
||||||
|
|
||||||
|
EXPECT_CALL(askPasswordForNewFilesystem, call()).Times(0);
|
||||||
|
EXPECT_CALL(askPasswordForExistingFilesystem, call()).Times(1).WillOnce(Return(password));
|
||||||
|
EXPECT_CALL(*kdf, deriveExistingKey(Eq(keySize), StrEq(password), _)).Times(1).WillOnce(Invoke([&] (auto, auto, const auto& kdfParams) {
|
||||||
|
EXPECT_EQ(kdfParameters, kdfParams);
|
||||||
|
return key;
|
||||||
|
}));
|
||||||
|
|
||||||
|
EncryptionKey returned_key = keyProvider.requestKeyForExistingFilesystem(keySize, kdfParameters);
|
||||||
|
|
||||||
|
EXPECT_EQ(key.ToString(), returned_key.ToString());
|
||||||
|
}
|
@ -2,8 +2,8 @@
|
|||||||
#include <cryfs/config/crypto/CryConfigEncryptorFactory.h>
|
#include <cryfs/config/crypto/CryConfigEncryptorFactory.h>
|
||||||
#include <cpp-utils/crypto/symmetric/ciphers.h>
|
#include <cpp-utils/crypto/symmetric/ciphers.h>
|
||||||
#include <cpp-utils/data/DataFixture.h>
|
#include <cpp-utils/data/DataFixture.h>
|
||||||
|
#include "../../testutils/FakeCryKeyProvider.h"
|
||||||
|
|
||||||
using cpputils::SCrypt;
|
|
||||||
using cpputils::AES256_GCM;
|
using cpputils::AES256_GCM;
|
||||||
using cpputils::Data;
|
using cpputils::Data;
|
||||||
using cpputils::DataFixture;
|
using cpputils::DataFixture;
|
||||||
@ -24,40 +24,48 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
TEST_F(CryConfigEncryptorFactoryTest, EncryptAndDecrypt_SameEncryptor) {
|
TEST_F(CryConfigEncryptorFactoryTest, EncryptAndDecrypt_SameEncryptor) {
|
||||||
auto encryptor = CryConfigEncryptorFactory::deriveKey("mypassword", SCrypt::TestSettings);
|
FakeCryKeyProvider keyProvider;
|
||||||
|
auto encryptor = CryConfigEncryptorFactory::deriveNewKey(&keyProvider);
|
||||||
Data encrypted = encryptor->encrypt(DataFixture::generate(400), AES256_GCM::NAME);
|
Data encrypted = encryptor->encrypt(DataFixture::generate(400), AES256_GCM::NAME);
|
||||||
auto decrypted = encryptor->decrypt(encrypted).value();
|
auto decrypted = encryptor->decrypt(encrypted).value();
|
||||||
EXPECT_EQ(DataFixture::generate(400), decrypted.data);
|
EXPECT_EQ(DataFixture::generate(400), decrypted.data);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(CryConfigEncryptorFactoryTest, EncryptAndDecrypt_NewEncryptor) {
|
TEST_F(CryConfigEncryptorFactoryTest, EncryptAndDecrypt_NewEncryptor) {
|
||||||
auto encryptor = CryConfigEncryptorFactory::deriveKey("mypassword", SCrypt::TestSettings);
|
FakeCryKeyProvider keyProvider1(1);
|
||||||
|
auto encryptor = CryConfigEncryptorFactory::deriveNewKey(&keyProvider1);
|
||||||
Data encrypted = encryptor->encrypt(DataFixture::generate(400), AES256_GCM::NAME);
|
Data encrypted = encryptor->encrypt(DataFixture::generate(400), AES256_GCM::NAME);
|
||||||
|
|
||||||
auto loadedEncryptor = CryConfigEncryptorFactory::loadKey(encrypted, "mypassword").value();
|
FakeCryKeyProvider keyProvider2(1);
|
||||||
|
auto loadedEncryptor = CryConfigEncryptorFactory::loadExistingKey(encrypted, &keyProvider2).value();
|
||||||
auto decrypted = loadedEncryptor->decrypt(encrypted).value();
|
auto decrypted = loadedEncryptor->decrypt(encrypted).value();
|
||||||
EXPECT_EQ(DataFixture::generate(400), decrypted.data);
|
EXPECT_EQ(DataFixture::generate(400), decrypted.data);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(CryConfigEncryptorFactoryTest, DoesntDecryptWithWrongPassword) {
|
TEST_F(CryConfigEncryptorFactoryTest, DoesntDecryptWithWrongKey) {
|
||||||
auto encryptor = CryConfigEncryptorFactory::deriveKey("mypassword", SCrypt::TestSettings);
|
FakeCryKeyProvider keyProvider1(1);
|
||||||
|
auto encryptor = CryConfigEncryptorFactory::deriveNewKey(&keyProvider1);
|
||||||
Data encrypted = encryptor->encrypt(DataFixture::generate(400), AES256_GCM::NAME);
|
Data encrypted = encryptor->encrypt(DataFixture::generate(400), AES256_GCM::NAME);
|
||||||
|
|
||||||
auto loadedEncryptor = CryConfigEncryptorFactory::loadKey(encrypted, "wrongpassword").value();
|
FakeCryKeyProvider keyProvider2(2);
|
||||||
|
auto loadedEncryptor = CryConfigEncryptorFactory::loadExistingKey(encrypted, &keyProvider2).value();
|
||||||
auto decrypted = loadedEncryptor->decrypt(encrypted);
|
auto decrypted = loadedEncryptor->decrypt(encrypted);
|
||||||
EXPECT_EQ(none, decrypted);
|
EXPECT_EQ(none, decrypted);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(CryConfigEncryptorFactoryTest, DoesntDecryptWithWrongPassword_EmptyData) {
|
TEST_F(CryConfigEncryptorFactoryTest, DoesntDecryptWithWrongKey_EmptyData) {
|
||||||
auto encryptor = CryConfigEncryptorFactory::deriveKey("mypassword", SCrypt::TestSettings);
|
FakeCryKeyProvider keyProvider1(1);
|
||||||
|
auto encryptor = CryConfigEncryptorFactory::deriveNewKey(&keyProvider1);
|
||||||
Data encrypted = encryptor->encrypt(Data(0), AES256_GCM::NAME);
|
Data encrypted = encryptor->encrypt(Data(0), AES256_GCM::NAME);
|
||||||
|
|
||||||
auto loadedEncryptor = CryConfigEncryptorFactory::loadKey(encrypted, "wrongpassword").value();
|
FakeCryKeyProvider keyProvider2(2);
|
||||||
|
auto loadedEncryptor = CryConfigEncryptorFactory::loadExistingKey(encrypted, &keyProvider2).value();
|
||||||
auto decrypted = loadedEncryptor->decrypt(encrypted);
|
auto decrypted = loadedEncryptor->decrypt(encrypted);
|
||||||
EXPECT_EQ(none, decrypted);
|
EXPECT_EQ(none, decrypted);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(CryConfigEncryptorFactoryTest, DoesntDecryptInvalidData) {
|
TEST_F(CryConfigEncryptorFactoryTest, DoesntDecryptInvalidData) {
|
||||||
auto loadedEncryptor = CryConfigEncryptorFactory::loadKey(Data(0), "mypassword");
|
FakeCryKeyProvider keyProvider;
|
||||||
|
auto loadedEncryptor = CryConfigEncryptorFactory::loadExistingKey(Data(0), &keyProvider);
|
||||||
EXPECT_EQ(none, loadedEncryptor);
|
EXPECT_EQ(none, loadedEncryptor);
|
||||||
}
|
}
|
@ -40,8 +40,8 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
EncryptionKey<CryConfigEncryptor::MaxTotalKeySize> _derivedKey() {
|
EncryptionKey _derivedKey() {
|
||||||
return EncryptionKey<CryConfigEncryptor::MaxTotalKeySize>::FromString(
|
return EncryptionKey::FromString(
|
||||||
DataFixture::generateFixedSize<CryConfigEncryptor::MaxTotalKeySize>(3).ToString()
|
DataFixture::generateFixedSize<CryConfigEncryptor::MaxTotalKeySize>(3).ToString()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -51,7 +51,7 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
unique_ref<OuterEncryptor> _outerEncryptor() {
|
unique_ref<OuterEncryptor> _outerEncryptor() {
|
||||||
auto outerKey = _derivedKey().take<CryConfigEncryptor::OuterKeySize>();
|
auto outerKey = _derivedKey().take(CryConfigEncryptor::OuterKeySize);
|
||||||
return make_unique_ref<OuterEncryptor>(outerKey, _kdfParameters());
|
return make_unique_ref<OuterEncryptor>(outerKey, _kdfParameters());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,7 +29,7 @@ public:
|
|||||||
template<class Cipher>
|
template<class Cipher>
|
||||||
unique_ref<InnerEncryptor> makeInnerEncryptor() {
|
unique_ref<InnerEncryptor> makeInnerEncryptor() {
|
||||||
auto key = Cipher::EncryptionKey::FromString(
|
auto key = Cipher::EncryptionKey::FromString(
|
||||||
DataFixture::generateFixedSize<Cipher::EncryptionKey::BINARY_LENGTH>().ToString()
|
DataFixture::generateFixedSize<Cipher::KEYSIZE>().ToString()
|
||||||
);
|
);
|
||||||
return make_unique_ref<ConcreteInnerEncryptor<Cipher>>(key);
|
return make_unique_ref<ConcreteInnerEncryptor<Cipher>>(key);
|
||||||
}
|
}
|
||||||
|
@ -29,7 +29,7 @@ public:
|
|||||||
|
|
||||||
unique_ref<OuterEncryptor> makeOuterEncryptor() {
|
unique_ref<OuterEncryptor> makeOuterEncryptor() {
|
||||||
auto key = OuterEncryptor::Cipher::EncryptionKey::FromString(
|
auto key = OuterEncryptor::Cipher::EncryptionKey::FromString(
|
||||||
DataFixture::generateFixedSize<OuterEncryptor::Cipher::EncryptionKey::BINARY_LENGTH>().ToString()
|
DataFixture::generateFixedSize<OuterEncryptor::Cipher::KEYSIZE>().ToString()
|
||||||
);
|
);
|
||||||
return make_unique_ref<OuterEncryptor>(key, kdfParameters());
|
return make_unique_ref<OuterEncryptor>(key, kdfParameters());
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
#include <cryfs/filesystem/CryOpenFile.h>
|
#include <cryfs/filesystem/CryOpenFile.h>
|
||||||
#include "../testutils/MockConsole.h"
|
#include "../testutils/MockConsole.h"
|
||||||
#include <cryfs/config/CryConfigLoader.h>
|
#include <cryfs/config/CryConfigLoader.h>
|
||||||
|
#include <cryfs/config/CryPasswordBasedKeyProvider.h>
|
||||||
#include <cpp-utils/system/homedir.h>
|
#include <cpp-utils/system/homedir.h>
|
||||||
#include "../testutils/TestWithFakeHomeDirectory.h"
|
#include "../testutils/TestWithFakeHomeDirectory.h"
|
||||||
#include <cpp-utils/io/NoninteractiveConsole.h>
|
#include <cpp-utils/io/NoninteractiveConsole.h>
|
||||||
@ -27,6 +28,7 @@ using cpputils::Data;
|
|||||||
using cpputils::NoninteractiveConsole;
|
using cpputils::NoninteractiveConsole;
|
||||||
using blockstore::ondisk::OnDiskBlockStore2;
|
using blockstore::ondisk::OnDiskBlockStore2;
|
||||||
using boost::none;
|
using boost::none;
|
||||||
|
using cryfs::CryPasswordBasedKeyProvider;
|
||||||
|
|
||||||
namespace bf = boost::filesystem;
|
namespace bf = boost::filesystem;
|
||||||
using namespace cryfs;
|
using namespace cryfs;
|
||||||
@ -38,7 +40,13 @@ public:
|
|||||||
|
|
||||||
CryConfigFile loadOrCreateConfig() {
|
CryConfigFile loadOrCreateConfig() {
|
||||||
auto askPassword = [] {return "mypassword";};
|
auto askPassword = [] {return "mypassword";};
|
||||||
return CryConfigLoader(make_shared<NoninteractiveConsole>(mockConsole()), Random::PseudoRandom(), localStateDir, SCrypt::TestSettings, askPassword, askPassword, none, none, none).loadOrCreate(config.path(), false, false).value().configFile;
|
auto keyProvider = make_unique_ref<CryPasswordBasedKeyProvider>(
|
||||||
|
make_shared<MockConsole>(),
|
||||||
|
askPassword,
|
||||||
|
askPassword,
|
||||||
|
make_unique_ref<SCrypt>(SCrypt::TestSettings)
|
||||||
|
);
|
||||||
|
return CryConfigLoader(make_shared<NoninteractiveConsole>(mockConsole()), Random::PseudoRandom(), std::move(keyProvider), localStateDir, none, none, none).loadOrCreate(config.path(), false, false).value().configFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
unique_ref<OnDiskBlockStore2> blockStore() {
|
unique_ref<OnDiskBlockStore2> blockStore() {
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
#include <cpp-utils/io/NoninteractiveConsole.h>
|
#include <cpp-utils/io/NoninteractiveConsole.h>
|
||||||
#include <cryfs/filesystem/CryDevice.h>
|
#include <cryfs/filesystem/CryDevice.h>
|
||||||
#include <cryfs/config/CryConfigLoader.h>
|
#include <cryfs/config/CryConfigLoader.h>
|
||||||
|
#include <cryfs/config/CryPasswordBasedKeyProvider.h>
|
||||||
#include "../testutils/MockConsole.h"
|
#include "../testutils/MockConsole.h"
|
||||||
#include "../testutils/TestWithFakeHomeDirectory.h"
|
#include "../testutils/TestWithFakeHomeDirectory.h"
|
||||||
|
|
||||||
@ -16,6 +17,7 @@ using fspp::Device;
|
|||||||
using boost::none;
|
using boost::none;
|
||||||
using std::make_shared;
|
using std::make_shared;
|
||||||
using blockstore::inmemory::InMemoryBlockStore2;
|
using blockstore::inmemory::InMemoryBlockStore2;
|
||||||
|
using cryfs::CryPasswordBasedKeyProvider;
|
||||||
|
|
||||||
using namespace cryfs;
|
using namespace cryfs;
|
||||||
|
|
||||||
@ -28,7 +30,14 @@ public:
|
|||||||
unique_ref<Device> createDevice() override {
|
unique_ref<Device> createDevice() override {
|
||||||
auto blockStore = cpputils::make_unique_ref<InMemoryBlockStore2>();
|
auto blockStore = cpputils::make_unique_ref<InMemoryBlockStore2>();
|
||||||
auto askPassword = [] {return "mypassword";};
|
auto askPassword = [] {return "mypassword";};
|
||||||
auto config = CryConfigLoader(make_shared<NoninteractiveConsole>(mockConsole()), Random::PseudoRandom(), localStateDir, SCrypt::TestSettings, askPassword, askPassword, none, none, none)
|
auto _console = make_shared<NoninteractiveConsole>(mockConsole());
|
||||||
|
auto keyProvider = make_unique_ref<CryPasswordBasedKeyProvider>(
|
||||||
|
_console,
|
||||||
|
askPassword,
|
||||||
|
askPassword,
|
||||||
|
make_unique_ref<SCrypt>(SCrypt::TestSettings)
|
||||||
|
);
|
||||||
|
auto config = CryConfigLoader(_console, Random::PseudoRandom(), std::move(keyProvider), localStateDir, none, none, none)
|
||||||
.loadOrCreate(configFile.path(), false, false).value();
|
.loadOrCreate(configFile.path(), false, false).value();
|
||||||
return make_unique_ref<CryDevice>(std::move(config.configFile), std::move(blockStore), localStateDir, config.myClientId, false, false);
|
return make_unique_ref<CryDevice>(std::move(config.configFile), std::move(blockStore), localStateDir, config.myClientId, false, false);
|
||||||
}
|
}
|
||||||
|
@ -2,10 +2,12 @@
|
|||||||
#define MESSMER_CRYFS_TEST_CRYFS_FILESYSTEM_CRYTESTBASE_H
|
#define MESSMER_CRYFS_TEST_CRYFS_FILESYSTEM_CRYTESTBASE_H
|
||||||
|
|
||||||
#include <cryfs/filesystem/CryDevice.h>
|
#include <cryfs/filesystem/CryDevice.h>
|
||||||
|
#include <cryfs/config/CryPasswordBasedKeyProvider.h>
|
||||||
#include <blockstore/implementations/inmemory/InMemoryBlockStore2.h>
|
#include <blockstore/implementations/inmemory/InMemoryBlockStore2.h>
|
||||||
#include <cpp-utils/tempfile/TempFile.h>
|
#include <cpp-utils/tempfile/TempFile.h>
|
||||||
#include <cpp-utils/crypto/kdf/Scrypt.h>
|
#include <cpp-utils/crypto/kdf/Scrypt.h>
|
||||||
#include "../../testutils/TestWithFakeHomeDirectory.h"
|
#include "../../testutils/TestWithFakeHomeDirectory.h"
|
||||||
|
#include "../../testutils/MockConsole.h"
|
||||||
|
|
||||||
class CryTestBase : public TestWithFakeHomeDirectory {
|
class CryTestBase : public TestWithFakeHomeDirectory {
|
||||||
public:
|
public:
|
||||||
@ -17,9 +19,15 @@ public:
|
|||||||
cryfs::CryConfigFile configFile() {
|
cryfs::CryConfigFile configFile() {
|
||||||
cryfs::CryConfig config;
|
cryfs::CryConfig config;
|
||||||
config.SetCipher("aes-256-gcm");
|
config.SetCipher("aes-256-gcm");
|
||||||
config.SetEncryptionKey(cpputils::AES256_GCM::EncryptionKey::CreateKey(cpputils::Random::PseudoRandom()).ToString());
|
config.SetEncryptionKey(cpputils::AES256_GCM::EncryptionKey::CreateKey(cpputils::Random::PseudoRandom(), cpputils::AES256_GCM::KEYSIZE).ToString());
|
||||||
config.SetBlocksizeBytes(10240);
|
config.SetBlocksizeBytes(10240);
|
||||||
return cryfs::CryConfigFile::create(_configFile.path(), std::move(config), "mypassword", cpputils::SCrypt::TestSettings);
|
cryfs::CryPasswordBasedKeyProvider keyProvider(
|
||||||
|
std::make_shared<MockConsole>(),
|
||||||
|
[] () {return "mypassword";},
|
||||||
|
[] () {return "mypassword";},
|
||||||
|
cpputils::make_unique_ref<cpputils::SCrypt>(cpputils::SCrypt::TestSettings)
|
||||||
|
);
|
||||||
|
return cryfs::CryConfigFile::create(_configFile.path(), std::move(config), &keyProvider);
|
||||||
}
|
}
|
||||||
|
|
||||||
cryfs::CryDevice &device() {
|
cryfs::CryDevice &device() {
|
||||||
|
35
test/cryfs/testutils/FakeCryKeyProvider.h
Normal file
35
test/cryfs/testutils/FakeCryKeyProvider.h
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
#pragma once
|
||||||
|
#ifndef CRYFS_FAKECRYKEYPROVIDER_H
|
||||||
|
#define CRYFS_FAKECRYKEYPROVIDER_H
|
||||||
|
|
||||||
|
#include <cryfs/config/CryKeyProvider.h>
|
||||||
|
#include <cpp-utils/data/DataFixture.h>
|
||||||
|
|
||||||
|
class FakeCryKeyProvider final : public cryfs::CryKeyProvider {
|
||||||
|
private:
|
||||||
|
static constexpr const unsigned char KDF_TEST_PARAMETERS = 5; // test value to check that kdf parameters are passed in correctly
|
||||||
|
public:
|
||||||
|
FakeCryKeyProvider(unsigned char keySeed = 0): _keySeed(keySeed) {}
|
||||||
|
|
||||||
|
cpputils::EncryptionKey requestKeyForExistingFilesystem(size_t keySize, const cpputils::Data& kdfParameters) override {
|
||||||
|
ASSERT(kdfParameters.size() == 1 && *reinterpret_cast<const unsigned char*>(kdfParameters.data()) == KDF_TEST_PARAMETERS, "Wrong kdf parameters");
|
||||||
|
|
||||||
|
return cpputils::EncryptionKey::FromString(cpputils::DataFixture::generate(keySize, _keySeed).ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
KeyResult requestKeyForNewFilesystem(size_t keySize) override {
|
||||||
|
cpputils::Data kdfParameters(sizeof(unsigned char));
|
||||||
|
*reinterpret_cast<unsigned char*>(kdfParameters.data()) = KDF_TEST_PARAMETERS;
|
||||||
|
|
||||||
|
auto key = requestKeyForExistingFilesystem(keySize, kdfParameters);
|
||||||
|
return KeyResult{
|
||||||
|
std::move(key),
|
||||||
|
std::move(kdfParameters)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
unsigned char _keySeed;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
14
test/cryfs/testutils/MockCryKeyProvider.h
Normal file
14
test/cryfs/testutils/MockCryKeyProvider.h
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
#pragma once
|
||||||
|
#ifndef CRYFS_MOCKCRYKEYPROVIDER_H
|
||||||
|
#define CRYFS_MOCKCRYKEYPROVIDER_H
|
||||||
|
|
||||||
|
#include <cryfs/config/CryKeyProvider.h>
|
||||||
|
#include <gmock/gmock.h>
|
||||||
|
|
||||||
|
class MockCryKeyProvider: public cryfs::CryKeyProvider {
|
||||||
|
public:
|
||||||
|
MOCK_METHOD2(requestKeyForExistingFilesystem, cpputils::EncryptionKey(size_t keySize, const cpputils::Data& kdfParameters));
|
||||||
|
MOCK_METHOD1(requestKeyForNewFilesystem, cryfs::CryKeyProvider::KeyResult(size_t keySize));
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
Loading…
x
Reference in New Issue
Block a user