1
0
mirror of https://github.com/apple/foundationdb.git synced 2025-05-31 18:19:35 +08:00

Move global key into StreamCipher

This commit is contained in:
sfc-gh-tclinkenbeard 2021-02-03 17:39:59 -08:00
parent 24c3827317
commit 5be4df6f84
4 changed files with 25 additions and 31 deletions

@ -42,7 +42,7 @@ public:
state unsigned char* encrypted = new (arena) unsigned char[FLOW_KNOBS->ENCRYPTION_BLOCK_SIZE];
int bytes = wait(
self->file->read(encrypted, FLOW_KNOBS->ENCRYPTION_BLOCK_SIZE, FLOW_KNOBS->ENCRYPTION_BLOCK_SIZE * block));
DecryptionStreamCipher decryptor(AsyncFileEncrypted::getKey(), self->getIV(block));
DecryptionStreamCipher decryptor(StreamCipher::getKey(), self->getIV(block));
auto decrypted = decryptor.decrypt(encrypted, bytes, arena);
return Standalone<StringRef>(decrypted, arena);
}
@ -98,7 +98,8 @@ public:
self->offsetInBlock = 0;
ASSERT(self->currentBlock < std::numeric_limits<uint16_t>::max());
++self->currentBlock;
self->encryptor = std::make_unique<EncryptionStreamCipher>(AsyncFileEncrypted::getKey(), self->getIV(self->currentBlock));
self->encryptor =
std::make_unique<EncryptionStreamCipher>(StreamCipher::getKey(), self->getIV(self->currentBlock));
}
}
return Void();
@ -111,20 +112,6 @@ public:
return Void();
}
ACTOR static Future<Void> initializeKey(Reference<IAsyncFile> keyFile, int64_t offset) {
ASSERT(!AsyncFileEncrypted::key.present());
AsyncFileEncrypted::key = StreamCipher::Key{};
state int keySize = AsyncFileEncrypted::key.get().size();
if (g_network->isSimulated()) {
generateRandomData(AsyncFileEncrypted::key.get().data(), keySize);
return Void();
} else {
int bytesRead = wait(keyFile->read(AsyncFileEncrypted::key.get().data(), keySize, offset));
ASSERT(bytesRead == keySize);
return Void();
}
}
ACTOR static Future<Void> zeroRange(AsyncFileEncrypted* self, int64_t offset, int64_t length) {
// TODO: Could optimize this
Arena arena;
@ -139,7 +126,7 @@ AsyncFileEncrypted::AsyncFileEncrypted(Reference<IAsyncFile> file, bool canWrite
: file(file), canWrite(canWrite), currentBlock(0), readBuffers(FLOW_KNOBS->MAX_DECRYPTED_BLOCKS) {
firstBlockIV = AsyncFileEncryptedImpl::getFirstBlockIV(file->getFilename());
if (canWrite) {
encryptor = std::make_unique<EncryptionStreamCipher>(AsyncFileEncrypted::getKey(), getIV(currentBlock));
encryptor = std::make_unique<EncryptionStreamCipher>(StreamCipher::getKey(), getIV(currentBlock));
writeBuffer = std::vector<unsigned char>(FLOW_KNOBS->ENCRYPTION_BLOCK_SIZE, 0);
}
}
@ -209,16 +196,6 @@ Future<Void> AsyncFileEncrypted::writeLastBlockToFile() {
return file->write(&writeBuffer[0], offsetInBlock, currentBlock * FLOW_KNOBS->ENCRYPTION_BLOCK_SIZE);
}
Optional<StreamCipher::Key> AsyncFileEncrypted::key;
StreamCipher::Key AsyncFileEncrypted::getKey() {
return key.get();
}
Future<Void> AsyncFileEncrypted::initializeKey(const Reference<IAsyncFile>& keyFile, int64_t offset) {
return AsyncFileEncryptedImpl::initializeKey(keyFile, offset);
}
size_t AsyncFileEncrypted::RandomCache::evict() {
ASSERT(vec.size() == maxSize);
auto index = deterministicRandom()->randomInt(0, maxSize);
@ -257,7 +234,7 @@ TEST_CASE("fdbrpc/AsyncFileEncrypted") {
generateRandomData(&writeBuffer.front(), bytes);
state std::vector<unsigned char> readBuffer(bytes, 0);
ASSERT(g_network->isSimulated());
wait(AsyncFileEncrypted::initializeKey(Reference<IAsyncFile>{}));
StreamCipher::initializeRandomKey();
int flags = IAsyncFile::OPEN_READWRITE | IAsyncFile::OPEN_CREATE | IAsyncFile::OPEN_ATOMIC_WRITE_AND_CREATE |
IAsyncFile::OPEN_UNBUFFERED | IAsyncFile::OPEN_ENCRYPTED | IAsyncFile::OPEN_UNCACHED |
IAsyncFile::OPEN_NO_AIO;

@ -39,8 +39,6 @@ class AsyncFileEncrypted : public IAsyncFile, public ReferenceCounted<AsyncFileE
bool canWrite;
Future<Void> writeLastBlockToFile();
friend class AsyncFileEncryptedImpl;
static Optional<StreamCipher::Key> key;
static StreamCipher::Key getKey();
// Reading:
class RandomCache {
@ -76,7 +74,6 @@ public:
Future<Void> readZeroCopy(void** data, int* length, int64_t offset) override;
void releaseZeroCopy(void* data, int length, int64_t offset) override;
int64_t debugFD() const override;
static Future<Void> initializeKey(const Reference<IAsyncFile>& keyFile, int64_t offset = 0);
};
#endif

@ -21,6 +21,8 @@
#include "flow/StreamCipher.h"
#include "flow/UnitTest.h"
#include <unordered_set>
EncryptionStreamCipher::EncryptionStreamCipher(const StreamCipher::Key& key, const StreamCipher::IV& iv)
: ctx(EVP_CIPHER_CTX_new()) {
EVP_EncryptInit_ex(ctx, EVP_aes_128_gcm(), nullptr, nullptr, nullptr);
@ -74,6 +76,20 @@ StringRef DecryptionStreamCipher::finish(Arena& arena) {
return StringRef(plaintext, finalBlockBytes);
}
static std::unordered_set<EVP_CIPHER_CTX*> ciphers;
static Optional<StreamCipher::Key> globalKey;
void StreamCipher::initializeRandomKey() {
ASSERT(g_network->isSimulated());
ASSERT(!globalKey.present());
globalKey = StreamCipher::Key{};
generateRandomData(globalKey.get().data(), globalKey.get().size());
}
StreamCipher::Key StreamCipher::getKey() {
return globalKey.get();
}
void forceLinkStreamCipherTests() {}
TEST_CASE("flow/StreamCipher") {

@ -33,6 +33,10 @@
namespace StreamCipher {
using Key = std::array<unsigned char, 16>;
using IV = std::array<unsigned char, 16>;
void initializeRandomKey();
Key getKey();
void registerCipherForCleanup(EVP_CIPHER_CTX*) noexcept;
void deregisterCipherForCleanup(EVP_CIPHER_CTX*) noexcept;
}; // namespace StreamCipher
class EncryptionStreamCipher final : NonCopyable, public ReferenceCounted<EncryptionStreamCipher> {