- UnswappableAllocator
- EncryptionKey uses UnswappableAllocator
This commit is contained in:
parent
1f363fce62
commit
5ad55b1d58
@ -2,7 +2,7 @@
|
|||||||
#ifndef MESSMER_CPPUTILS_CRYPTO_KDF_PASSWORDBASEDKDF_H
|
#ifndef MESSMER_CPPUTILS_CRYPTO_KDF_PASSWORDBASEDKDF_H
|
||||||
#define MESSMER_CPPUTILS_CRYPTO_KDF_PASSWORDBASEDKDF_H
|
#define MESSMER_CPPUTILS_CRYPTO_KDF_PASSWORDBASEDKDF_H
|
||||||
|
|
||||||
#include "../../data/FixedSizeData.h"
|
#include "../../crypto/symmetric/EncryptionKey.h"
|
||||||
#include "../../data/Data.h"
|
#include "../../data/Data.h"
|
||||||
|
|
||||||
namespace cpputils {
|
namespace cpputils {
|
||||||
@ -11,16 +11,16 @@ namespace cpputils {
|
|||||||
public:
|
public:
|
||||||
virtual ~PasswordBasedKDF() {}
|
virtual ~PasswordBasedKDF() {}
|
||||||
|
|
||||||
template<size_t KEYSIZE> FixedSizeData<KEYSIZE> deriveKey(const std::string &password);
|
template<size_t KEYSIZE> EncryptionKey<KEYSIZE> deriveKey(const std::string &password);
|
||||||
virtual const Data &kdfParameters() const = 0;
|
virtual const Data &kdfParameters() const = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void derive(void *destination, size_t size, const std::string &password) = 0;
|
virtual void derive(void *destination, size_t size, const std::string &password) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<size_t KEYSIZE> FixedSizeData<KEYSIZE>
|
template<size_t KEYSIZE> EncryptionKey<KEYSIZE>
|
||||||
inline PasswordBasedKDF::deriveKey(const std::string &password) {
|
inline PasswordBasedKDF::deriveKey(const std::string &password) {
|
||||||
auto result = FixedSizeData<KEYSIZE>::Null();
|
auto result = EncryptionKey<KEYSIZE>::Null();
|
||||||
derive(result.data(), result.BINARY_LENGTH, password);
|
derive(result.data(), result.BINARY_LENGTH, password);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -22,89 +22,89 @@ namespace cpputils {
|
|||||||
template<size_t KeySize>
|
template<size_t KeySize>
|
||||||
class EncryptionKey final {
|
class EncryptionKey final {
|
||||||
private:
|
private:
|
||||||
struct EncryptionKeyData final {
|
explicit EncryptionKey(std::shared_ptr<Data> keyData)
|
||||||
public:
|
: _keyData(std::move(keyData)) {
|
||||||
constexpr static size_t BINARY_LENGTH = FixedSizeData<KeySize>::BINARY_LENGTH;
|
ASSERT(_keyData->size() == KeySize, "Wrong key data size");
|
||||||
constexpr static size_t STRING_LENGTH = FixedSizeData<KeySize>::STRING_LENGTH;
|
}
|
||||||
|
template<size_t OtherKeySize> friend class EncryptionKey;
|
||||||
EncryptionKeyData(const FixedSizeData<KeySize>& keyData);
|
|
||||||
~EncryptionKeyData();
|
|
||||||
|
|
||||||
// Disallow copying and moving
|
|
||||||
EncryptionKeyData(const EncryptionKeyData &rhs) = delete;
|
|
||||||
EncryptionKeyData(EncryptionKeyData &&rhs) = delete;
|
|
||||||
EncryptionKeyData &operator=(const EncryptionKeyData &rhs) = delete;
|
|
||||||
EncryptionKeyData &operator=(EncryptionKeyData &&rhs) = delete;
|
|
||||||
|
|
||||||
FixedSizeData<KeySize> key;
|
|
||||||
DontSwapMemoryRAII memoryProtector; // this makes sure that the key data isn't swapped to disk
|
|
||||||
};
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
constexpr static size_t BINARY_LENGTH = EncryptionKeyData::BINARY_LENGTH;
|
EncryptionKey(const EncryptionKey& rhs) = default;
|
||||||
constexpr static size_t STRING_LENGTH = EncryptionKeyData::STRING_LENGTH;
|
EncryptionKey(EncryptionKey&& rhs) = default;
|
||||||
|
EncryptionKey& operator=(const EncryptionKey& rhs) = default;
|
||||||
|
EncryptionKey& operator=(EncryptionKey&& rhs) = default;
|
||||||
|
|
||||||
EncryptionKey(const FixedSizeData<KeySize>& keyData);
|
static constexpr size_t BINARY_LENGTH = KeySize;
|
||||||
|
static constexpr size_t STRING_LENGTH = 2 * BINARY_LENGTH;
|
||||||
|
|
||||||
static EncryptionKey FromBinary(const void *source);
|
static EncryptionKey Null() {
|
||||||
static EncryptionKey FromString(const std::string& keyData);
|
auto data = std::make_shared<Data>(
|
||||||
std::string ToString() const;
|
KeySize,
|
||||||
|
make_unique_ref<UnswappableAllocator>()
|
||||||
|
);
|
||||||
|
data->FillWithZeroes();
|
||||||
|
return EncryptionKey(std::move(data));
|
||||||
|
}
|
||||||
|
|
||||||
|
static EncryptionKey FromString(const std::string& keyData) {
|
||||||
|
ASSERT(keyData.size() == STRING_LENGTH, "Wrong input size or EncryptionKey::FromString()");
|
||||||
|
|
||||||
|
auto data = std::make_shared<Data>(
|
||||||
|
Data::FromString(keyData, make_unique_ref<UnswappableAllocator>())
|
||||||
|
);
|
||||||
|
ASSERT(data->size() == KeySize, "Wrong input size for EncryptionKey::FromString()");
|
||||||
|
|
||||||
|
return EncryptionKey(std::move(data));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string ToString() const {
|
||||||
|
auto result = _keyData->ToString();
|
||||||
|
ASSERT(result.size() == STRING_LENGTH, "Wrong string length");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
static EncryptionKey CreateKey(RandomGenerator &randomGenerator) {
|
static EncryptionKey CreateKey(RandomGenerator &randomGenerator) {
|
||||||
EncryptionKey result(FixedSizeData<BINARY_LENGTH>::Null());
|
EncryptionKey result(std::make_shared<Data>(
|
||||||
randomGenerator.write(result._key->key.data(), BINARY_LENGTH);
|
KeySize,
|
||||||
|
make_unique_ref<UnswappableAllocator>() // the allocator makes sure key data is never swapped to disk
|
||||||
|
));
|
||||||
|
randomGenerator.write(result._keyData->data(), KeySize);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
const void *data() const {
|
const void *data() const {
|
||||||
return _key->key.data();
|
return _keyData->data();
|
||||||
}
|
}
|
||||||
|
|
||||||
void *data() {
|
void *data() {
|
||||||
return const_cast<void*>(const_cast<const EncryptionKey*>(this)->data());
|
return const_cast<void*>(const_cast<const EncryptionKey*>(this)->data());
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
// TODO Test take/drop
|
||||||
|
|
||||||
std::shared_ptr<EncryptionKeyData> _key;
|
template<size_t NumTaken>
|
||||||
|
EncryptionKey<NumTaken> take() const {
|
||||||
|
static_assert(NumTaken <= KeySize, "Out of bounds");
|
||||||
|
auto result = std::make_shared<Data>(NumTaken, make_unique_ref<UnswappableAllocator>());
|
||||||
|
std::memcpy(result->data(), _keyData->data(), NumTaken);
|
||||||
|
return EncryptionKey<NumTaken>(std::move(result));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<size_t NumDropped>
|
||||||
|
EncryptionKey<KeySize - NumDropped> drop() const {
|
||||||
|
static_assert(NumDropped <= KeySize, "Out of bounds");
|
||||||
|
auto result = std::make_shared<Data>(KeySize - NumDropped, make_unique_ref<UnswappableAllocator>());
|
||||||
|
std::memcpy(result->data(), _keyData->dataOffset(NumDropped), KeySize - NumDropped);
|
||||||
|
return EncryptionKey<KeySize - NumDropped>(std::move(result));
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
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>::BINARY_LENGTH;
|
||||||
template<size_t KeySize> constexpr size_t EncryptionKey<KeySize>::STRING_LENGTH;
|
template<size_t KeySize> constexpr size_t EncryptionKey<KeySize>::STRING_LENGTH;
|
||||||
|
|
||||||
template<size_t KeySize>
|
|
||||||
inline EncryptionKey<KeySize>::EncryptionKeyData::EncryptionKeyData(const FixedSizeData<KeySize>& keyData)
|
|
||||||
: key(keyData)
|
|
||||||
, memoryProtector(&key, sizeof(key)) {
|
|
||||||
}
|
|
||||||
|
|
||||||
template<size_t KeySize>
|
|
||||||
inline EncryptionKey<KeySize>::EncryptionKeyData::~EncryptionKeyData() {
|
|
||||||
// After destruction, the swap-protection is lifted, but we also don't need the key data anymore.
|
|
||||||
// Overwrite it with zeroes.
|
|
||||||
std::memset(key.data(), 0, KeySize);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<size_t KeySize>
|
|
||||||
inline EncryptionKey<KeySize>::EncryptionKey(const FixedSizeData<KeySize>& keyData)
|
|
||||||
: _key(std::make_shared<EncryptionKeyData>(keyData)) {
|
|
||||||
}
|
|
||||||
|
|
||||||
template<size_t KeySize>
|
|
||||||
EncryptionKey<KeySize> EncryptionKey<KeySize>::FromBinary(const void *source) {
|
|
||||||
return EncryptionKey(FixedSizeData<KeySize>::FromBinary(source));
|
|
||||||
}
|
|
||||||
|
|
||||||
template<size_t KeySize>
|
|
||||||
EncryptionKey<KeySize> EncryptionKey<KeySize>::FromString(const std::string& keyData) {
|
|
||||||
return EncryptionKey(FixedSizeData<KeySize>::FromString(keyData));
|
|
||||||
}
|
|
||||||
|
|
||||||
template<size_t KeySize>
|
|
||||||
std::string EncryptionKey<KeySize>::ToString() const {
|
|
||||||
return _key->key.ToString();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -13,15 +13,15 @@
|
|||||||
namespace cpputils {
|
namespace cpputils {
|
||||||
|
|
||||||
struct FakeKey {
|
struct FakeKey {
|
||||||
static FakeKey FromBinary(const void *data) {
|
static FakeKey FromString(const std::string& keyData) {
|
||||||
return FakeKey{deserialize<uint64_t>(data)};
|
return FakeKey{static_cast<uint64_t>(std::atoi(keyData.c_str()))};
|
||||||
}
|
}
|
||||||
|
|
||||||
static constexpr unsigned int BINARY_LENGTH = sizeof(uint64_t);
|
static constexpr unsigned int BINARY_LENGTH = sizeof(uint64_t);
|
||||||
|
|
||||||
static FakeKey CreateKey(RandomGenerator &randomGenerator) {
|
static FakeKey CreateKey(RandomGenerator &randomGenerator) {
|
||||||
auto data = randomGenerator.getFixedSize<sizeof(uint64_t)>();
|
auto data = randomGenerator.getFixedSize<sizeof(uint64_t)>();
|
||||||
return FromBinary(data.data());
|
return FakeKey {*reinterpret_cast<uint64_t*>(data.data())};
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t value;
|
uint64_t value;
|
||||||
|
@ -3,19 +3,15 @@
|
|||||||
#define MESSMER_CPPUTILS_SYSTEM_MEMORY_H
|
#define MESSMER_CPPUTILS_SYSTEM_MEMORY_H
|
||||||
|
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
#include "../data/Data.h"
|
||||||
|
|
||||||
namespace cpputils {
|
namespace cpputils {
|
||||||
|
|
||||||
// While this RAII object exists, it locks a given memory address into RAM,
|
// This allocator allocates memory that won't be swapped out to the disk, but will be kept in RAM
|
||||||
// i.e. tells the operating system not to swap it.
|
class UnswappableAllocator final : public Allocator {
|
||||||
class DontSwapMemoryRAII final {
|
|
||||||
public:
|
public:
|
||||||
DontSwapMemoryRAII(void* addr, size_t len);
|
void* allocate(size_t size) override;
|
||||||
~DontSwapMemoryRAII();
|
void free(void* data, size_t size) override;
|
||||||
|
|
||||||
private:
|
|
||||||
void* const addr_;
|
|
||||||
const size_t len_;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -10,19 +10,25 @@ using namespace cpputils::logging;
|
|||||||
|
|
||||||
namespace cpputils {
|
namespace cpputils {
|
||||||
|
|
||||||
DontSwapMemoryRAII::DontSwapMemoryRAII(void *addr, size_t len)
|
void* UnswappableAllocator::allocate(size_t size) {
|
||||||
: addr_(addr), len_(len) {
|
void* data = DefaultAllocator().allocate(size);
|
||||||
const int result = ::mlock(addr_, len_);
|
const int result = ::mlock(data, size);
|
||||||
if (0 != result) {
|
if (0 != result) {
|
||||||
throw std::runtime_error("Error calling mlock. Errno: " + std::to_string(errno));
|
throw std::runtime_error("Error calling mlock. Errno: " + std::to_string(errno));
|
||||||
}
|
}
|
||||||
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
DontSwapMemoryRAII::~DontSwapMemoryRAII() {
|
void UnswappableAllocator::free(void* data, size_t size) {
|
||||||
const int result = ::munlock(addr_, len_);
|
const int result = ::munlock(data, size);
|
||||||
if (0 != result) {
|
if (0 != result) {
|
||||||
LOG(WARN, "Error calling munlock. Errno: {}", errno);
|
LOG(WARN, "Error calling munlock. Errno: {}", errno);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// overwrite the memory with zeroes before we free it
|
||||||
|
std::memset(data, 0, size);
|
||||||
|
|
||||||
|
DefaultAllocator().free(data, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -9,19 +9,25 @@ using namespace cpputils::logging;
|
|||||||
|
|
||||||
namespace cpputils {
|
namespace cpputils {
|
||||||
|
|
||||||
DontSwapMemoryRAII::DontSwapMemoryRAII(void *addr, size_t len)
|
void* UnswappableAllocator::allocate(size_t size) {
|
||||||
: addr_(addr), len_(len) {
|
void* data = DefaultAllocator().allocate(size);
|
||||||
const BOOL result = ::VirtualLock(addr_, len_);
|
const BOOL result = ::VirtualLock(addr_, len_);
|
||||||
if (!result) {
|
if (!result) {
|
||||||
throw std::runtime_error("Error calling VirtualLock. Errno: " + std::to_string(GetLastError()));
|
throw std::runtime_error("Error calling VirtualLock. Errno: " + std::to_string(GetLastError()));
|
||||||
}
|
}
|
||||||
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
DontSwapMemoryRAII::~DontSwapMemoryRAII() {
|
void UnswappableAllocator::free(void* data, size_t size) {
|
||||||
const BOOL result = ::VirtualUnlock(addr_, len_);
|
const BOOL result = ::VirtualUnlock(addr_, len_);
|
||||||
if (!result) {
|
if (!result) {
|
||||||
LOG(WARN, "Error calling VirtualUnlock. Errno: {}", GetLastError());
|
LOG(WARN, "Error calling VirtualUnlock. Errno: {}", GetLastError());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// overwrite the memory with zeroes before we free it
|
||||||
|
std::memset(data, 0, size);
|
||||||
|
|
||||||
|
DefaultAllocator().free(data, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -47,7 +47,7 @@ public:
|
|||||||
return Cipher::EncryptionKey::CreateKey(randomGenerator).ToString();
|
return Cipher::EncryptionKey::CreateKey(randomGenerator).ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
unique_ref<InnerEncryptor> createInnerConfigEncryptor(const FixedSizeData<CryCiphers::MAX_KEY_SIZE> &key) const override {
|
unique_ref<InnerEncryptor> createInnerConfigEncryptor(const EncryptionKey<CryCiphers::MAX_KEY_SIZE>& key) const override {
|
||||||
return make_unique_ref<ConcreteInnerEncryptor<Cipher>>(key.take<Cipher::EncryptionKey::BINARY_LENGTH>());
|
return make_unique_ref<ConcreteInnerEncryptor<Cipher>>(key.take<Cipher::EncryptionKey::BINARY_LENGTH>());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include <blockstore/interface/BlockStore2.h>
|
#include <blockstore/interface/BlockStore2.h>
|
||||||
#include <cpp-utils/random/RandomGenerator.h>
|
#include <cpp-utils/random/RandomGenerator.h>
|
||||||
#include "crypto/inner/InnerEncryptor.h"
|
#include "crypto/inner/InnerEncryptor.h"
|
||||||
|
#include <cpp-utils/crypto/symmetric/EncryptionKey.h>
|
||||||
|
|
||||||
namespace cryfs {
|
namespace cryfs {
|
||||||
|
|
||||||
@ -40,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::FixedSizeData<CryCiphers::MAX_KEY_SIZE> &key) const = 0;
|
virtual cpputils::unique_ref<InnerEncryptor> createInnerConfigEncryptor(const cpputils::EncryptionKey<CryCiphers::MAX_KEY_SIZE> &key) const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -14,8 +14,8 @@ namespace cryfs {
|
|||||||
constexpr size_t CryConfigEncryptor::OuterKeySize;
|
constexpr size_t CryConfigEncryptor::OuterKeySize;
|
||||||
constexpr size_t CryConfigEncryptor::MaxTotalKeySize;
|
constexpr size_t CryConfigEncryptor::MaxTotalKeySize;
|
||||||
|
|
||||||
CryConfigEncryptor::CryConfigEncryptor(const FixedSizeData<MaxTotalKeySize>& derivedKey, cpputils::Data kdfParameters)
|
CryConfigEncryptor::CryConfigEncryptor(cpputils::EncryptionKey<MaxTotalKeySize> derivedKey, cpputils::Data kdfParameters)
|
||||||
: _derivedKey(derivedKey), _kdfParameters(std::move(kdfParameters)) {
|
: _derivedKey(std::move(derivedKey)), _kdfParameters(std::move(kdfParameters)) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Data CryConfigEncryptor::encrypt(const Data &plaintext, const string &cipherName) const {
|
Data CryConfigEncryptor::encrypt(const Data &plaintext, const string &cipherName) const {
|
||||||
@ -47,11 +47,11 @@ 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>(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(innerKey);
|
return CryCiphers::find(cipherName).createInnerConfigEncryptor(std::move(innerKey));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,7 @@ namespace cryfs {
|
|||||||
bool wasInDeprecatedConfigFormat;
|
bool wasInDeprecatedConfigFormat;
|
||||||
};
|
};
|
||||||
|
|
||||||
CryConfigEncryptor(const cpputils::FixedSizeData<MaxTotalKeySize>& derivedKey, cpputils::Data _kdfParameters);
|
CryConfigEncryptor(cpputils::EncryptionKey<MaxTotalKeySize> 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::FixedSizeData<MaxTotalKeySize> _derivedKey;
|
cpputils::EncryptionKey<MaxTotalKeySize> _derivedKey;
|
||||||
cpputils::Data _kdfParameters;
|
cpputils::Data _kdfParameters;
|
||||||
|
|
||||||
DISALLOW_COPY_AND_ASSIGN(CryConfigEncryptor);
|
DISALLOW_COPY_AND_ASSIGN(CryConfigEncryptor);
|
||||||
|
@ -10,8 +10,8 @@ using boost::none;
|
|||||||
using namespace cpputils::logging;
|
using namespace cpputils::logging;
|
||||||
|
|
||||||
namespace cryfs {
|
namespace cryfs {
|
||||||
OuterEncryptor::OuterEncryptor(const Cipher::EncryptionKey& key, cpputils::Data kdfParameters)
|
OuterEncryptor::OuterEncryptor(Cipher::EncryptionKey key, cpputils::Data kdfParameters)
|
||||||
: _key(key), _kdfParameters(std::move(kdfParameters)) {
|
: _key(std::move(key)), _kdfParameters(std::move(kdfParameters)) {
|
||||||
}
|
}
|
||||||
|
|
||||||
OuterConfig OuterEncryptor::encrypt(const Data &plaintext) const {
|
OuterConfig OuterEncryptor::encrypt(const Data &plaintext) const {
|
||||||
|
@ -14,7 +14,7 @@ namespace cryfs {
|
|||||||
using Cipher = cpputils::AES256_GCM;
|
using Cipher = cpputils::AES256_GCM;
|
||||||
static constexpr size_t CONFIG_SIZE = 1024; // Config data is grown to this size before encryption to hide its actual size
|
static constexpr size_t CONFIG_SIZE = 1024; // Config data is grown to this size before encryption to hide its actual size
|
||||||
|
|
||||||
OuterEncryptor(const Cipher::EncryptionKey& key, cpputils::Data kdfParameters);
|
OuterEncryptor(Cipher::EncryptionKey key, cpputils::Data kdfParameters);
|
||||||
|
|
||||||
OuterConfig encrypt(const cpputils::Data &encryptedInnerConfig) const;
|
OuterConfig encrypt(const cpputils::Data &encryptedInnerConfig) const;
|
||||||
boost::optional<cpputils::Data> decrypt(const OuterConfig &outerConfig) const;
|
boost::optional<cpputils::Data> decrypt(const OuterConfig &outerConfig) const;
|
||||||
|
@ -36,8 +36,9 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
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);
|
return Cipher::EncryptionKey::FromString(
|
||||||
return Cipher::EncryptionKey::FromBinary(data.data());
|
DataFixture::generate(Cipher::EncryptionKey::BINARY_LENGTH, seed).ToString()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -54,8 +55,9 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
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);
|
return Cipher::EncryptionKey::FromString(
|
||||||
return Cipher::EncryptionKey::FromBinary(data.data());
|
DataFixture::generate(Cipher::EncryptionKey::BINARY_LENGTH, seed).ToString()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -13,36 +13,41 @@ public:
|
|||||||
SCryptParameters result = SCryptParameters::deserialize(scrypt.kdfParameters());
|
SCryptParameters result = SCryptParameters::deserialize(scrypt.kdfParameters());
|
||||||
return result;
|
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");
|
auto derivedKey = scryptForNewKey->deriveKey<56>("mypassword");
|
||||||
auto rederivedKey = scryptForExistingKey->deriveKey<56>("mypassword");
|
auto rederivedKey = scryptForExistingKey->deriveKey<56>("mypassword");
|
||||||
EXPECT_EQ(derivedKey, rederivedKey);
|
EXPECT_TRUE(keyEquals(derivedKey, rederivedKey));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(SCryptTest, GeneratedKeyIsReproductible_256) {
|
TEST_F(SCryptTest, GeneratedKeyIsReproductible_256) {
|
||||||
auto derivedKey = scryptForNewKey->deriveKey<32>("mypassword");
|
auto derivedKey = scryptForNewKey->deriveKey<32>("mypassword");
|
||||||
auto rederivedKey = scryptForExistingKey->deriveKey<32>("mypassword");
|
auto rederivedKey = scryptForExistingKey->deriveKey<32>("mypassword");
|
||||||
EXPECT_EQ(derivedKey, rederivedKey);
|
EXPECT_TRUE(keyEquals(derivedKey, rederivedKey));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(SCryptTest, GeneratedKeyIsReproductible_128) {
|
TEST_F(SCryptTest, GeneratedKeyIsReproductible_128) {
|
||||||
auto derivedKey = scryptForNewKey->deriveKey<16>("mypassword");
|
auto derivedKey = scryptForNewKey->deriveKey<16>("mypassword");
|
||||||
auto rederivedKey = scryptForExistingKey->deriveKey<16>("mypassword");
|
auto rederivedKey = scryptForExistingKey->deriveKey<16>("mypassword");
|
||||||
EXPECT_EQ(derivedKey, rederivedKey);
|
EXPECT_TRUE(keyEquals(derivedKey, rederivedKey));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(SCryptTest, GeneratedKeyIsReproductible_DefaultSettings) {
|
TEST_F(SCryptTest, GeneratedKeyIsReproductible_DefaultSettings) {
|
||||||
auto derivedKey = scryptForNewKey->deriveKey<16>("mypassword");
|
auto derivedKey = scryptForNewKey->deriveKey<16>("mypassword");
|
||||||
auto rederivedKey = scryptForExistingKey->deriveKey<16>("mypassword");
|
auto rederivedKey = scryptForExistingKey->deriveKey<16>("mypassword");
|
||||||
EXPECT_EQ(derivedKey, rederivedKey);
|
EXPECT_TRUE(keyEquals(derivedKey, rederivedKey));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(SCryptTest, DifferentPasswordResultsInDifferentKey) {
|
TEST_F(SCryptTest, DifferentPasswordResultsInDifferentKey) {
|
||||||
auto derivedKey = scryptForNewKey->deriveKey<16>("mypassword");
|
auto derivedKey = scryptForNewKey->deriveKey<16>("mypassword");
|
||||||
auto rederivedKey = scryptForExistingKey->deriveKey<16>("mypassword2");
|
auto rederivedKey = scryptForExistingKey->deriveKey<16>("mypassword2");
|
||||||
EXPECT_NE(derivedKey, rederivedKey);
|
EXPECT_FALSE(keyEquals(derivedKey, rederivedKey));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(SCryptTest, UsesCorrectSettings) {
|
TEST_F(SCryptTest, UsesCorrectSettings) {
|
||||||
|
@ -19,7 +19,7 @@ public:
|
|||||||
|
|
||||||
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::EncryptionKey::BINARY_LENGTH, seed);
|
||||||
return Cipher::EncryptionKey::FromBinary(data.data());
|
return Cipher::EncryptionKey::FromString(data.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
void CheckEncryptThenDecryptIsIdentity(const Data &plaintext) {
|
void CheckEncryptThenDecryptIsIdentity(const Data &plaintext) {
|
||||||
|
@ -3,24 +3,16 @@
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
#include <cpp-utils/pointer/gcc_4_8_compatibility.h>
|
#include <cpp-utils/pointer/gcc_4_8_compatibility.h>
|
||||||
|
|
||||||
using cpputils::DontSwapMemoryRAII;
|
using cpputils::UnswappableAllocator;
|
||||||
|
|
||||||
TEST(MemoryTest, LockingSmallStackMemoryDoesntCrash) {
|
TEST(MemoryTest, LockingSmallMemoryDoesntCrash) {
|
||||||
bool memory;
|
UnswappableAllocator allocator;
|
||||||
DontSwapMemoryRAII obj(&memory, sizeof(memory));
|
void *data = allocator.allocate(5);
|
||||||
|
allocator.free(data, 5);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(MemoryTest, LockingLargeStackMemoryDoesntCrash) {
|
TEST(MemoryTest, LockingLargeMemoryDoesntCrash) {
|
||||||
bool memory[10*1024];
|
UnswappableAllocator allocator;
|
||||||
DontSwapMemoryRAII obj(memory, sizeof(memory));
|
void *data = allocator.allocate(10240);
|
||||||
}
|
allocator.free(data, 10240);
|
||||||
|
|
||||||
TEST(MemoryTest, LockingSmallHeapMemoryDoesntCrash) {
|
|
||||||
auto memory = std::make_unique<bool>(false);
|
|
||||||
DontSwapMemoryRAII obj(memory.get(), sizeof(*memory));
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(MemoryTest, LockingLargeHeapMemoryDoesntCrash) {
|
|
||||||
auto memory = std::make_unique<bool[]>(10*1024);
|
|
||||||
DontSwapMemoryRAII obj(memory.get(), 10*1024);
|
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@ using cpputils::unique_ref;
|
|||||||
using cpputils::make_unique_ref;
|
using cpputils::make_unique_ref;
|
||||||
using cpputils::DataFixture;
|
using cpputils::DataFixture;
|
||||||
using cpputils::Data;
|
using cpputils::Data;
|
||||||
|
using cpputils::EncryptionKey;
|
||||||
using cpputils::FixedSizeData;
|
using cpputils::FixedSizeData;
|
||||||
using cpputils::AES128_CFB;
|
using cpputils::AES128_CFB;
|
||||||
using cpputils::AES256_GCM;
|
using cpputils::AES256_GCM;
|
||||||
@ -40,8 +41,10 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
FixedSizeData<CryConfigEncryptor::MaxTotalKeySize> _derivedKey() {
|
EncryptionKey<CryConfigEncryptor::MaxTotalKeySize> _derivedKey() {
|
||||||
return DataFixture::generateFixedSize<CryConfigEncryptor::MaxTotalKeySize>(3);
|
return EncryptionKey<CryConfigEncryptor::MaxTotalKeySize>::FromString(
|
||||||
|
DataFixture::generateFixedSize<CryConfigEncryptor::MaxTotalKeySize>(3).ToString()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Data _kdfParameters() {
|
Data _kdfParameters() {
|
||||||
|
@ -28,7 +28,9 @@ class ConcreteInnerEncryptorTest : public ::testing::Test {
|
|||||||
public:
|
public:
|
||||||
template<class Cipher>
|
template<class Cipher>
|
||||||
unique_ref<InnerEncryptor> makeInnerEncryptor() {
|
unique_ref<InnerEncryptor> makeInnerEncryptor() {
|
||||||
auto key = DataFixture::generateFixedSize<Cipher::EncryptionKey::BINARY_LENGTH>();
|
auto key = Cipher::EncryptionKey::FromString(
|
||||||
|
DataFixture::generateFixedSize<Cipher::EncryptionKey::BINARY_LENGTH>().ToString()
|
||||||
|
);
|
||||||
return make_unique_ref<ConcreteInnerEncryptor<Cipher>>(key);
|
return make_unique_ref<ConcreteInnerEncryptor<Cipher>>(key);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -28,7 +28,9 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
unique_ref<OuterEncryptor> makeOuterEncryptor() {
|
unique_ref<OuterEncryptor> makeOuterEncryptor() {
|
||||||
auto key = DataFixture::generateFixedSize<OuterEncryptor::Cipher::EncryptionKey::BINARY_LENGTH>();
|
auto key = OuterEncryptor::Cipher::EncryptionKey::FromString(
|
||||||
|
DataFixture::generateFixedSize<OuterEncryptor::Cipher::EncryptionKey::BINARY_LENGTH>().ToString()
|
||||||
|
);
|
||||||
return make_unique_ref<OuterEncryptor>(key, kdfParameters());
|
return make_unique_ref<OuterEncryptor>(key, kdfParameters());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user