Skip to content

Commit 5ad55b1

Browse files
committed
- UnswappableAllocator
- EncryptionKey uses UnswappableAllocator
1 parent 1f363fc commit 5ad55b1

19 files changed

Lines changed: 141 additions & 126 deletions

File tree

src/cpp-utils/crypto/kdf/PasswordBasedKDF.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
#ifndef MESSMER_CPPUTILS_CRYPTO_KDF_PASSWORDBASEDKDF_H
33
#define MESSMER_CPPUTILS_CRYPTO_KDF_PASSWORDBASEDKDF_H
44

5-
#include "../../data/FixedSizeData.h"
5+
#include "../../crypto/symmetric/EncryptionKey.h"
66
#include "../../data/Data.h"
77

88
namespace cpputils {
@@ -11,16 +11,16 @@ namespace cpputils {
1111
public:
1212
virtual ~PasswordBasedKDF() {}
1313

14-
template<size_t KEYSIZE> FixedSizeData<KEYSIZE> deriveKey(const std::string &password);
14+
template<size_t KEYSIZE> EncryptionKey<KEYSIZE> deriveKey(const std::string &password);
1515
virtual const Data &kdfParameters() const = 0;
1616

1717
protected:
1818
virtual void derive(void *destination, size_t size, const std::string &password) = 0;
1919
};
2020

21-
template<size_t KEYSIZE> FixedSizeData<KEYSIZE>
21+
template<size_t KEYSIZE> EncryptionKey<KEYSIZE>
2222
inline PasswordBasedKDF::deriveKey(const std::string &password) {
23-
auto result = FixedSizeData<KEYSIZE>::Null();
23+
auto result = EncryptionKey<KEYSIZE>::Null();
2424
derive(result.data(), result.BINARY_LENGTH, password);
2525
return result;
2626
}

src/cpp-utils/crypto/symmetric/EncryptionKey.h

Lines changed: 60 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -22,89 +22,89 @@ namespace cpputils {
2222
template<size_t KeySize>
2323
class EncryptionKey final {
2424
private:
25-
struct EncryptionKeyData final {
26-
public:
27-
constexpr static size_t BINARY_LENGTH = FixedSizeData<KeySize>::BINARY_LENGTH;
28-
constexpr static size_t STRING_LENGTH = FixedSizeData<KeySize>::STRING_LENGTH;
29-
30-
EncryptionKeyData(const FixedSizeData<KeySize>& keyData);
31-
~EncryptionKeyData();
25+
explicit EncryptionKey(std::shared_ptr<Data> keyData)
26+
: _keyData(std::move(keyData)) {
27+
ASSERT(_keyData->size() == KeySize, "Wrong key data size");
28+
}
29+
template<size_t OtherKeySize> friend class EncryptionKey;
3230

33-
// Disallow copying and moving
34-
EncryptionKeyData(const EncryptionKeyData &rhs) = delete;
35-
EncryptionKeyData(EncryptionKeyData &&rhs) = delete;
36-
EncryptionKeyData &operator=(const EncryptionKeyData &rhs) = delete;
37-
EncryptionKeyData &operator=(EncryptionKeyData &&rhs) = delete;
31+
public:
32+
EncryptionKey(const EncryptionKey& rhs) = default;
33+
EncryptionKey(EncryptionKey&& rhs) = default;
34+
EncryptionKey& operator=(const EncryptionKey& rhs) = default;
35+
EncryptionKey& operator=(EncryptionKey&& rhs) = default;
36+
37+
static constexpr size_t BINARY_LENGTH = KeySize;
38+
static constexpr size_t STRING_LENGTH = 2 * BINARY_LENGTH;
39+
40+
static EncryptionKey Null() {
41+
auto data = std::make_shared<Data>(
42+
KeySize,
43+
make_unique_ref<UnswappableAllocator>()
44+
);
45+
data->FillWithZeroes();
46+
return EncryptionKey(std::move(data));
47+
}
3848

39-
FixedSizeData<KeySize> key;
40-
DontSwapMemoryRAII memoryProtector; // this makes sure that the key data isn't swapped to disk
41-
};
49+
static EncryptionKey FromString(const std::string& keyData) {
50+
ASSERT(keyData.size() == STRING_LENGTH, "Wrong input size or EncryptionKey::FromString()");
4251

43-
public:
44-
constexpr static size_t BINARY_LENGTH = EncryptionKeyData::BINARY_LENGTH;
45-
constexpr static size_t STRING_LENGTH = EncryptionKeyData::STRING_LENGTH;
52+
auto data = std::make_shared<Data>(
53+
Data::FromString(keyData, make_unique_ref<UnswappableAllocator>())
54+
);
55+
ASSERT(data->size() == KeySize, "Wrong input size for EncryptionKey::FromString()");
4656

47-
EncryptionKey(const FixedSizeData<KeySize>& keyData);
57+
return EncryptionKey(std::move(data));
58+
}
4859

49-
static EncryptionKey FromBinary(const void *source);
50-
static EncryptionKey FromString(const std::string& keyData);
51-
std::string ToString() const;
60+
std::string ToString() const {
61+
auto result = _keyData->ToString();
62+
ASSERT(result.size() == STRING_LENGTH, "Wrong string length");
63+
return result;
64+
}
5265

5366
static EncryptionKey CreateKey(RandomGenerator &randomGenerator) {
54-
EncryptionKey result(FixedSizeData<BINARY_LENGTH>::Null());
55-
randomGenerator.write(result._key->key.data(), BINARY_LENGTH);
67+
EncryptionKey result(std::make_shared<Data>(
68+
KeySize,
69+
make_unique_ref<UnswappableAllocator>() // the allocator makes sure key data is never swapped to disk
70+
));
71+
randomGenerator.write(result._keyData->data(), KeySize);
5672
return result;
5773
}
5874

5975
const void *data() const {
60-
return _key->key.data();
76+
return _keyData->data();
6177
}
6278

6379
void *data() {
6480
return const_cast<void*>(const_cast<const EncryptionKey*>(this)->data());
6581
}
6682

67-
private:
83+
// TODO Test take/drop
84+
85+
template<size_t NumTaken>
86+
EncryptionKey<NumTaken> take() const {
87+
static_assert(NumTaken <= KeySize, "Out of bounds");
88+
auto result = std::make_shared<Data>(NumTaken, make_unique_ref<UnswappableAllocator>());
89+
std::memcpy(result->data(), _keyData->data(), NumTaken);
90+
return EncryptionKey<NumTaken>(std::move(result));
91+
}
92+
93+
template<size_t NumDropped>
94+
EncryptionKey<KeySize - NumDropped> drop() const {
95+
static_assert(NumDropped <= KeySize, "Out of bounds");
96+
auto result = std::make_shared<Data>(KeySize - NumDropped, make_unique_ref<UnswappableAllocator>());
97+
std::memcpy(result->data(), _keyData->dataOffset(NumDropped), KeySize - NumDropped);
98+
return EncryptionKey<KeySize - NumDropped>(std::move(result));
99+
}
68100

69-
std::shared_ptr<EncryptionKeyData> _key;
101+
private:
102+
std::shared_ptr<Data> _keyData;
70103
};
71104

72105
template<size_t KeySize> constexpr size_t EncryptionKey<KeySize>::BINARY_LENGTH;
73106
template<size_t KeySize> constexpr size_t EncryptionKey<KeySize>::STRING_LENGTH;
74107

75-
template<size_t KeySize>
76-
inline EncryptionKey<KeySize>::EncryptionKeyData::EncryptionKeyData(const FixedSizeData<KeySize>& keyData)
77-
: key(keyData)
78-
, memoryProtector(&key, sizeof(key)) {
79-
}
80-
81-
template<size_t KeySize>
82-
inline EncryptionKey<KeySize>::EncryptionKeyData::~EncryptionKeyData() {
83-
// After destruction, the swap-protection is lifted, but we also don't need the key data anymore.
84-
// Overwrite it with zeroes.
85-
std::memset(key.data(), 0, KeySize);
86-
}
87-
88-
template<size_t KeySize>
89-
inline EncryptionKey<KeySize>::EncryptionKey(const FixedSizeData<KeySize>& keyData)
90-
: _key(std::make_shared<EncryptionKeyData>(keyData)) {
91-
}
92-
93-
template<size_t KeySize>
94-
EncryptionKey<KeySize> EncryptionKey<KeySize>::FromBinary(const void *source) {
95-
return EncryptionKey(FixedSizeData<KeySize>::FromBinary(source));
96-
}
97-
98-
template<size_t KeySize>
99-
EncryptionKey<KeySize> EncryptionKey<KeySize>::FromString(const std::string& keyData) {
100-
return EncryptionKey(FixedSizeData<KeySize>::FromString(keyData));
101-
}
102-
103-
template<size_t KeySize>
104-
std::string EncryptionKey<KeySize>::ToString() const {
105-
return _key->key.ToString();
106-
}
107-
108108
}
109109

110110
#endif

src/cpp-utils/crypto/symmetric/testutils/FakeAuthenticatedCipher.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,15 @@
1313
namespace cpputils {
1414

1515
struct FakeKey {
16-
static FakeKey FromBinary(const void *data) {
17-
return FakeKey{deserialize<uint64_t>(data)};
16+
static FakeKey FromString(const std::string& keyData) {
17+
return FakeKey{static_cast<uint64_t>(std::atoi(keyData.c_str()))};
1818
}
1919

2020
static constexpr unsigned int BINARY_LENGTH = sizeof(uint64_t);
2121

2222
static FakeKey CreateKey(RandomGenerator &randomGenerator) {
2323
auto data = randomGenerator.getFixedSize<sizeof(uint64_t)>();
24-
return FromBinary(data.data());
24+
return FakeKey {*reinterpret_cast<uint64_t*>(data.data())};
2525
}
2626

2727
uint64_t value;

src/cpp-utils/system/memory.h

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,15 @@
33
#define MESSMER_CPPUTILS_SYSTEM_MEMORY_H
44

55
#include <cstdlib>
6+
#include "../data/Data.h"
67

78
namespace cpputils {
89

9-
// While this RAII object exists, it locks a given memory address into RAM,
10-
// i.e. tells the operating system not to swap it.
11-
class DontSwapMemoryRAII final {
10+
// This allocator allocates memory that won't be swapped out to the disk, but will be kept in RAM
11+
class UnswappableAllocator final : public Allocator {
1212
public:
13-
DontSwapMemoryRAII(void* addr, size_t len);
14-
~DontSwapMemoryRAII();
15-
16-
private:
17-
void* const addr_;
18-
const size_t len_;
13+
void* allocate(size_t size) override;
14+
void free(void* data, size_t size) override;
1915
};
2016

2117
}

src/cpp-utils/system/memory_nonwindows.cpp

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,19 +10,25 @@ using namespace cpputils::logging;
1010

1111
namespace cpputils {
1212

13-
DontSwapMemoryRAII::DontSwapMemoryRAII(void *addr, size_t len)
14-
: addr_(addr), len_(len) {
15-
const int result = ::mlock(addr_, len_);
13+
void* UnswappableAllocator::allocate(size_t size) {
14+
void* data = DefaultAllocator().allocate(size);
15+
const int result = ::mlock(data, size);
1616
if (0 != result) {
1717
throw std::runtime_error("Error calling mlock. Errno: " + std::to_string(errno));
1818
}
19+
return data;
1920
}
2021

21-
DontSwapMemoryRAII::~DontSwapMemoryRAII() {
22-
const int result = ::munlock(addr_, len_);
22+
void UnswappableAllocator::free(void* data, size_t size) {
23+
const int result = ::munlock(data, size);
2324
if (0 != result) {
2425
LOG(WARN, "Error calling munlock. Errno: {}", errno);
2526
}
27+
28+
// overwrite the memory with zeroes before we free it
29+
std::memset(data, 0, size);
30+
31+
DefaultAllocator().free(data, size);
2632
}
2733

2834
}

src/cpp-utils/system/memory_windows.cpp

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,19 +9,25 @@ using namespace cpputils::logging;
99

1010
namespace cpputils {
1111

12-
DontSwapMemoryRAII::DontSwapMemoryRAII(void *addr, size_t len)
13-
: addr_(addr), len_(len) {
12+
void* UnswappableAllocator::allocate(size_t size) {
13+
void* data = DefaultAllocator().allocate(size);
1414
const BOOL result = ::VirtualLock(addr_, len_);
1515
if (!result) {
1616
throw std::runtime_error("Error calling VirtualLock. Errno: " + std::to_string(GetLastError()));
1717
}
18+
return data;
1819
}
1920

20-
DontSwapMemoryRAII::~DontSwapMemoryRAII() {
21+
void UnswappableAllocator::free(void* data, size_t size) {
2122
const BOOL result = ::VirtualUnlock(addr_, len_);
2223
if (!result) {
2324
LOG(WARN, "Error calling VirtualUnlock. Errno: {}", GetLastError());
2425
}
26+
27+
// overwrite the memory with zeroes before we free it
28+
std::memset(data, 0, size);
29+
30+
DefaultAllocator().free(data, size);
2531
}
2632

2733
}

src/cryfs/config/CryCipher.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ class CryCipherInstance: public CryCipher {
4747
return Cipher::EncryptionKey::CreateKey(randomGenerator).ToString();
4848
}
4949

50-
unique_ref<InnerEncryptor> createInnerConfigEncryptor(const FixedSizeData<CryCiphers::MAX_KEY_SIZE> &key) const override {
50+
unique_ref<InnerEncryptor> createInnerConfigEncryptor(const EncryptionKey<CryCiphers::MAX_KEY_SIZE>& key) const override {
5151
return make_unique_ref<ConcreteInnerEncryptor<Cipher>>(key.take<Cipher::EncryptionKey::BINARY_LENGTH>());
5252
}
5353

src/cryfs/config/CryCipher.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include <blockstore/interface/BlockStore2.h>
99
#include <cpp-utils/random/RandomGenerator.h>
1010
#include "crypto/inner/InnerEncryptor.h"
11+
#include <cpp-utils/crypto/symmetric/EncryptionKey.h>
1112

1213
namespace cryfs {
1314

@@ -40,7 +41,7 @@ class CryCipher {
4041
virtual const boost::optional<std::string> &warning() const = 0;
4142
virtual cpputils::unique_ref<blockstore::BlockStore2> createEncryptedBlockstore(cpputils::unique_ref<blockstore::BlockStore2> baseBlockStore, const std::string &encKey) const = 0;
4243
virtual std::string createKey(cpputils::RandomGenerator &randomGenerator) const = 0;
43-
virtual cpputils::unique_ref<InnerEncryptor> createInnerConfigEncryptor(const cpputils::FixedSizeData<CryCiphers::MAX_KEY_SIZE> &key) const = 0;
44+
virtual cpputils::unique_ref<InnerEncryptor> createInnerConfigEncryptor(const cpputils::EncryptionKey<CryCiphers::MAX_KEY_SIZE> &key) const = 0;
4445
};
4546

4647

src/cryfs/config/crypto/CryConfigEncryptor.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ namespace cryfs {
1414
constexpr size_t CryConfigEncryptor::OuterKeySize;
1515
constexpr size_t CryConfigEncryptor::MaxTotalKeySize;
1616

17-
CryConfigEncryptor::CryConfigEncryptor(const FixedSizeData<MaxTotalKeySize>& derivedKey, cpputils::Data kdfParameters)
18-
: _derivedKey(derivedKey), _kdfParameters(std::move(kdfParameters)) {
17+
CryConfigEncryptor::CryConfigEncryptor(cpputils::EncryptionKey<MaxTotalKeySize> derivedKey, cpputils::Data kdfParameters)
18+
: _derivedKey(std::move(derivedKey)), _kdfParameters(std::move(kdfParameters)) {
1919
}
2020

2121
Data CryConfigEncryptor::encrypt(const Data &plaintext, const string &cipherName) const {
@@ -47,11 +47,11 @@ namespace cryfs {
4747

4848
unique_ref<OuterEncryptor> CryConfigEncryptor::_outerEncryptor() const {
4949
auto outerKey = _derivedKey.take<OuterKeySize>();
50-
return make_unique_ref<OuterEncryptor>(outerKey, _kdfParameters.copy());
50+
return make_unique_ref<OuterEncryptor>(std::move(outerKey), _kdfParameters.copy());
5151
}
5252

5353
unique_ref<InnerEncryptor> CryConfigEncryptor::_innerEncryptor(const string &cipherName) const {
5454
auto innerKey = _derivedKey.drop<OuterKeySize>();
55-
return CryCiphers::find(cipherName).createInnerConfigEncryptor(innerKey);
55+
return CryCiphers::find(cipherName).createInnerConfigEncryptor(std::move(innerKey));
5656
}
5757
}

src/cryfs/config/crypto/CryConfigEncryptor.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ namespace cryfs {
2323
bool wasInDeprecatedConfigFormat;
2424
};
2525

26-
CryConfigEncryptor(const cpputils::FixedSizeData<MaxTotalKeySize>& derivedKey, cpputils::Data _kdfParameters);
26+
CryConfigEncryptor(cpputils::EncryptionKey<MaxTotalKeySize> derivedKey, cpputils::Data _kdfParameters);
2727

2828
cpputils::Data encrypt(const cpputils::Data &plaintext, const std::string &cipherName) const;
2929
boost::optional<Decrypted> decrypt(const cpputils::Data &data) const;
@@ -32,7 +32,7 @@ namespace cryfs {
3232
cpputils::unique_ref<OuterEncryptor> _outerEncryptor() const;
3333
cpputils::unique_ref<InnerEncryptor> _innerEncryptor(const std::string &cipherName) const;
3434

35-
cpputils::FixedSizeData<MaxTotalKeySize> _derivedKey;
35+
cpputils::EncryptionKey<MaxTotalKeySize> _derivedKey;
3636
cpputils::Data _kdfParameters;
3737

3838
DISALLOW_COPY_AND_ASSIGN(CryConfigEncryptor);

0 commit comments

Comments
 (0)