#pragma once #ifndef BLOCKSTORE_IMPLEMENTATIONS_ENCRYPTED_ENCRYPTEDBLOCKSTORE_H_ #define BLOCKSTORE_IMPLEMENTATIONS_ENCRYPTED_ENCRYPTEDBLOCKSTORE_H_ #include "../../interface/BlockStore.h" #include #include #include "EncryptedBlock.h" #include namespace blockstore { namespace encrypted { template class EncryptedBlockStore: public BlockStore { public: EncryptedBlockStore(cpputils::unique_ref baseBlockStore, const typename Cipher::EncryptionKey &encKey); //TODO Are createKey() tests included in generic BlockStoreTest? If not, add it! Key createKey() override; boost::optional> tryCreate(const Key &key, cpputils::Data data) override; boost::optional> load(const Key &key) override; void remove(cpputils::unique_ref block) override; uint64_t numBlocks() const override; //This function should only be used by test cases void __setKey(const typename Cipher::EncryptionKey &encKey); private: cpputils::unique_ref _baseBlockStore; typename Cipher::EncryptionKey _encKey; DISALLOW_COPY_AND_ASSIGN(EncryptedBlockStore); }; template EncryptedBlockStore::EncryptedBlockStore(cpputils::unique_ref baseBlockStore, const typename Cipher::EncryptionKey &encKey) : _baseBlockStore(std::move(baseBlockStore)), _encKey(encKey) { } template Key EncryptedBlockStore::createKey() { return _baseBlockStore->createKey(); } template boost::optional> EncryptedBlockStore::tryCreate(const Key &key, cpputils::Data data) { //TODO Test that this returns boost::none when base blockstore returns nullptr (for all pass-through-blockstores) //TODO Easier implementation? This is only so complicated because of the case EncryptedBlock -> Block auto result = EncryptedBlock::TryCreateNew(_baseBlockStore.get(), key, std::move(data), _encKey); if (result == boost::none) { return boost::none; } return cpputils::unique_ref(std::move(*result)); } template boost::optional> EncryptedBlockStore::load(const Key &key) { auto block = _baseBlockStore->load(key); if (block == boost::none) { //TODO Test this path (for all pass-through-blockstores) return boost::none; } return boost::optional>(EncryptedBlock::TryDecrypt(std::move(*block), _encKey)); } template void EncryptedBlockStore::remove(cpputils::unique_ref block) { auto encryptedBlock = cpputils::dynamic_pointer_move>(block); assert(encryptedBlock != boost::none); auto baseBlock = (*encryptedBlock)->releaseBlock(); return _baseBlockStore->remove(std::move(baseBlock)); } template uint64_t EncryptedBlockStore::numBlocks() const { return _baseBlockStore->numBlocks(); } template void EncryptedBlockStore::__setKey(const typename Cipher::EncryptionKey &encKey) { _encKey = encKey; } } } #endif