mirror of
https://github.com/apple/foundationdb.git
synced 2025-06-02 11:15:50 +08:00
Move global key into StreamCipher
This commit is contained in:
parent
24c3827317
commit
5be4df6f84
@ -42,7 +42,7 @@ public:
|
|||||||
state unsigned char* encrypted = new (arena) unsigned char[FLOW_KNOBS->ENCRYPTION_BLOCK_SIZE];
|
state unsigned char* encrypted = new (arena) unsigned char[FLOW_KNOBS->ENCRYPTION_BLOCK_SIZE];
|
||||||
int bytes = wait(
|
int bytes = wait(
|
||||||
self->file->read(encrypted, FLOW_KNOBS->ENCRYPTION_BLOCK_SIZE, FLOW_KNOBS->ENCRYPTION_BLOCK_SIZE * block));
|
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);
|
auto decrypted = decryptor.decrypt(encrypted, bytes, arena);
|
||||||
return Standalone<StringRef>(decrypted, arena);
|
return Standalone<StringRef>(decrypted, arena);
|
||||||
}
|
}
|
||||||
@ -98,7 +98,8 @@ public:
|
|||||||
self->offsetInBlock = 0;
|
self->offsetInBlock = 0;
|
||||||
ASSERT(self->currentBlock < std::numeric_limits<uint16_t>::max());
|
ASSERT(self->currentBlock < std::numeric_limits<uint16_t>::max());
|
||||||
++self->currentBlock;
|
++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();
|
return Void();
|
||||||
@ -111,20 +112,6 @@ public:
|
|||||||
return Void();
|
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) {
|
ACTOR static Future<Void> zeroRange(AsyncFileEncrypted* self, int64_t offset, int64_t length) {
|
||||||
// TODO: Could optimize this
|
// TODO: Could optimize this
|
||||||
Arena arena;
|
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) {
|
: file(file), canWrite(canWrite), currentBlock(0), readBuffers(FLOW_KNOBS->MAX_DECRYPTED_BLOCKS) {
|
||||||
firstBlockIV = AsyncFileEncryptedImpl::getFirstBlockIV(file->getFilename());
|
firstBlockIV = AsyncFileEncryptedImpl::getFirstBlockIV(file->getFilename());
|
||||||
if (canWrite) {
|
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);
|
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);
|
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() {
|
size_t AsyncFileEncrypted::RandomCache::evict() {
|
||||||
ASSERT(vec.size() == maxSize);
|
ASSERT(vec.size() == maxSize);
|
||||||
auto index = deterministicRandom()->randomInt(0, maxSize);
|
auto index = deterministicRandom()->randomInt(0, maxSize);
|
||||||
@ -257,7 +234,7 @@ TEST_CASE("fdbrpc/AsyncFileEncrypted") {
|
|||||||
generateRandomData(&writeBuffer.front(), bytes);
|
generateRandomData(&writeBuffer.front(), bytes);
|
||||||
state std::vector<unsigned char> readBuffer(bytes, 0);
|
state std::vector<unsigned char> readBuffer(bytes, 0);
|
||||||
ASSERT(g_network->isSimulated());
|
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 |
|
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_UNBUFFERED | IAsyncFile::OPEN_ENCRYPTED | IAsyncFile::OPEN_UNCACHED |
|
||||||
IAsyncFile::OPEN_NO_AIO;
|
IAsyncFile::OPEN_NO_AIO;
|
||||||
|
@ -39,8 +39,6 @@ class AsyncFileEncrypted : public IAsyncFile, public ReferenceCounted<AsyncFileE
|
|||||||
bool canWrite;
|
bool canWrite;
|
||||||
Future<Void> writeLastBlockToFile();
|
Future<Void> writeLastBlockToFile();
|
||||||
friend class AsyncFileEncryptedImpl;
|
friend class AsyncFileEncryptedImpl;
|
||||||
static Optional<StreamCipher::Key> key;
|
|
||||||
static StreamCipher::Key getKey();
|
|
||||||
|
|
||||||
// Reading:
|
// Reading:
|
||||||
class RandomCache {
|
class RandomCache {
|
||||||
@ -76,7 +74,6 @@ public:
|
|||||||
Future<Void> readZeroCopy(void** data, int* length, int64_t offset) override;
|
Future<Void> readZeroCopy(void** data, int* length, int64_t offset) override;
|
||||||
void releaseZeroCopy(void* data, int length, int64_t offset) override;
|
void releaseZeroCopy(void* data, int length, int64_t offset) override;
|
||||||
int64_t debugFD() const override;
|
int64_t debugFD() const override;
|
||||||
static Future<Void> initializeKey(const Reference<IAsyncFile>& keyFile, int64_t offset = 0);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -21,6 +21,8 @@
|
|||||||
#include "flow/StreamCipher.h"
|
#include "flow/StreamCipher.h"
|
||||||
#include "flow/UnitTest.h"
|
#include "flow/UnitTest.h"
|
||||||
|
|
||||||
|
#include <unordered_set>
|
||||||
|
|
||||||
EncryptionStreamCipher::EncryptionStreamCipher(const StreamCipher::Key& key, const StreamCipher::IV& iv)
|
EncryptionStreamCipher::EncryptionStreamCipher(const StreamCipher::Key& key, const StreamCipher::IV& iv)
|
||||||
: ctx(EVP_CIPHER_CTX_new()) {
|
: ctx(EVP_CIPHER_CTX_new()) {
|
||||||
EVP_EncryptInit_ex(ctx, EVP_aes_128_gcm(), nullptr, nullptr, nullptr);
|
EVP_EncryptInit_ex(ctx, EVP_aes_128_gcm(), nullptr, nullptr, nullptr);
|
||||||
@ -74,6 +76,20 @@ StringRef DecryptionStreamCipher::finish(Arena& arena) {
|
|||||||
return StringRef(plaintext, finalBlockBytes);
|
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() {}
|
void forceLinkStreamCipherTests() {}
|
||||||
|
|
||||||
TEST_CASE("flow/StreamCipher") {
|
TEST_CASE("flow/StreamCipher") {
|
||||||
|
@ -33,6 +33,10 @@
|
|||||||
namespace StreamCipher {
|
namespace StreamCipher {
|
||||||
using Key = std::array<unsigned char, 16>;
|
using Key = std::array<unsigned char, 16>;
|
||||||
using IV = 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
|
}; // namespace StreamCipher
|
||||||
|
|
||||||
class EncryptionStreamCipher final : NonCopyable, public ReferenceCounted<EncryptionStreamCipher> {
|
class EncryptionStreamCipher final : NonCopyable, public ReferenceCounted<EncryptionStreamCipher> {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user