diff --git a/implementations/encrypted/ciphers/AES256_CFB.cpp b/implementations/encrypted/ciphers/AES256_CFB.cpp deleted file mode 100644 index afef76dc..00000000 --- a/implementations/encrypted/ciphers/AES256_CFB.cpp +++ /dev/null @@ -1,37 +0,0 @@ -#include -#include "AES256_CFB.h" - -using CryptoPP::CFB_Mode; -using CryptoPP::AES; -using cpputils::Data; -using cpputils::FixedSizeData; - -namespace blockstore { -namespace encrypted { - -constexpr unsigned int AES256_CFB::IV_SIZE; - -Data AES256_CFB::encrypt(const byte *plaintext, unsigned int plaintextSize, const EncryptionKey &encKey) { - FixedSizeData iv = FixedSizeData::CreatePseudoRandom(); - auto encryption = CFB_Mode::Encryption(encKey.data(), encKey.BINARY_LENGTH, iv.data()); - Data ciphertext(ciphertextSize(plaintextSize)); - std::memcpy(ciphertext.data(), iv.data(), IV_SIZE); - encryption.ProcessData((byte*)ciphertext.data() + IV_SIZE, plaintext, plaintextSize); - return ciphertext; -} - -boost::optional AES256_CFB::decrypt(const byte *ciphertext, unsigned int ciphertextSize, const EncryptionKey &encKey) { - if (ciphertextSize < IV_SIZE) { - return boost::none; - } - - const byte *ciphertextIV = ciphertext; - const byte *ciphertextData = ciphertext + IV_SIZE; - auto decryption = CFB_Mode::Decryption((byte*)encKey.data(), encKey.BINARY_LENGTH, ciphertextIV); - Data plaintext(plaintextSize(ciphertextSize)); - decryption.ProcessData((byte*)plaintext.data(), ciphertextData, plaintext.size()); - return std::move(plaintext); -} - -} -} diff --git a/implementations/encrypted/ciphers/AES256_CFB.h b/implementations/encrypted/ciphers/AES256_CFB.h deleted file mode 100644 index 313842d6..00000000 --- a/implementations/encrypted/ciphers/AES256_CFB.h +++ /dev/null @@ -1,39 +0,0 @@ -#pragma once -#ifndef MESSMER_BLOCKSTORE_IMPLEMENTATIONS_ENCRYPTED_CIPHERS_AES256_CFB_H_ -#define MESSMER_BLOCKSTORE_IMPLEMENTATIONS_ENCRYPTED_CIPHERS_AES256_CFB_H_ - -#include -#include -#include -#include -#include "Cipher.h" - -namespace blockstore { -namespace encrypted { - -class AES256_CFB { -public: - BOOST_CONCEPT_ASSERT((CipherConcept)); - - using EncryptionKey = cpputils::FixedSizeData<32>; - static_assert(32 == CryptoPP::AES::MAX_KEYLENGTH, "If AES offered larger keys, we should offer a variant with it"); - - static constexpr unsigned int ciphertextSize(unsigned int plaintextBlockSize) { - return plaintextBlockSize + IV_SIZE; - } - - static constexpr unsigned int plaintextSize(unsigned int ciphertextBlockSize) { - return ciphertextBlockSize - IV_SIZE; - } - - static cpputils::Data encrypt(const byte *plaintext, unsigned int plaintextSize, const EncryptionKey &encKey); - static boost::optional decrypt(const byte *ciphertext, unsigned int ciphertextSize, const EncryptionKey &encKey); - -private: - static constexpr unsigned int IV_SIZE = CryptoPP::AES::BLOCKSIZE; -}; - -} -} - -#endif diff --git a/implementations/encrypted/ciphers/AES256_GCM.cpp b/implementations/encrypted/ciphers/AES256_GCM.cpp deleted file mode 100644 index 552a9009..00000000 --- a/implementations/encrypted/ciphers/AES256_GCM.cpp +++ /dev/null @@ -1,61 +0,0 @@ -#include -#include "AES256_GCM.h" - -using CryptoPP::GCM; -using CryptoPP::AES; -using CryptoPP::AuthenticatedEncryptionFilter; -using CryptoPP::AuthenticatedDecryptionFilter; -using CryptoPP::ArraySource; -using CryptoPP::ArraySink; -using CryptoPP::GCM_64K_Tables; -using CryptoPP::HashVerificationFilter; -using cpputils::Data; -using cpputils::FixedSizeData; - -namespace blockstore { -namespace encrypted { - -constexpr unsigned int AES256_GCM::IV_SIZE; - -Data AES256_GCM::encrypt(const byte *plaintext, unsigned int plaintextSize, const EncryptionKey &encKey) { - FixedSizeData iv = FixedSizeData::CreatePseudoRandom(); - GCM::Encryption encryption; - encryption.SetKeyWithIV(encKey.data(), encKey.BINARY_LENGTH, iv.data(), IV_SIZE); - Data ciphertext(ciphertextSize(plaintextSize)); - - std::memcpy(ciphertext.data(), iv.data(), IV_SIZE); - ArraySource(plaintext, plaintextSize, true, - new AuthenticatedEncryptionFilter(encryption, - new ArraySink((byte*)ciphertext.data() + IV_SIZE, ciphertext.size() - IV_SIZE), - false, TAG_SIZE - ) - ); - return ciphertext; -} - -boost::optional AES256_GCM::decrypt(const byte *ciphertext, unsigned int ciphertextSize, const EncryptionKey &encKey) { - if (ciphertextSize < IV_SIZE + TAG_SIZE) { - return boost::none; - } - - const byte *ciphertextIV = ciphertext; - const byte *ciphertextData = ciphertext + IV_SIZE; - GCM::Decryption decryption; - decryption.SetKeyWithIV((byte*)encKey.data(), encKey.BINARY_LENGTH, ciphertextIV, IV_SIZE); - Data plaintext(plaintextSize(ciphertextSize)); - - try { - ArraySource((byte*)ciphertextData, ciphertextSize - IV_SIZE, true, - new AuthenticatedDecryptionFilter(decryption, - new ArraySink((byte*)plaintext.data(), plaintext.size()), - AuthenticatedDecryptionFilter::DEFAULT_FLAGS, TAG_SIZE - ) - ); - return std::move(plaintext); - } catch (const HashVerificationFilter::HashVerificationFailed &e) { - return boost::none; - } -} - -} -} diff --git a/implementations/encrypted/ciphers/AES256_GCM.h b/implementations/encrypted/ciphers/AES256_GCM.h deleted file mode 100644 index 4f864488..00000000 --- a/implementations/encrypted/ciphers/AES256_GCM.h +++ /dev/null @@ -1,40 +0,0 @@ -#pragma once -#ifndef MESSMER_BLOCKSTORE_IMPLEMENTATIONS_ENCRYPTED_CIPHERS_AES256_GCM_H_ -#define MESSMER_BLOCKSTORE_IMPLEMENTATIONS_ENCRYPTED_CIPHERS_AES256_GCM_H_ - -#include -#include -#include -#include "Cipher.h" - -namespace blockstore { -namespace encrypted { - -class AES256_GCM { -public: - BOOST_CONCEPT_ASSERT((CipherConcept)); - - //TODO Does EncryptionKey::GenerateRandom() use a PseudoRandomGenerator? Would be better to use real randomness. This is true for all ciphers - we should offer a CreateKey() method in Ciphers. - using EncryptionKey = cpputils::FixedSizeData<32>; - static_assert(32 == CryptoPP::AES::MAX_KEYLENGTH, "If AES offered larger keys, we should offer a variant with it"); - - static constexpr unsigned int ciphertextSize(unsigned int plaintextBlockSize) { - return plaintextBlockSize + IV_SIZE + TAG_SIZE; - } - - static constexpr unsigned int plaintextSize(unsigned int ciphertextBlockSize) { - return ciphertextBlockSize - IV_SIZE - TAG_SIZE; - } - - static cpputils::Data encrypt(const byte *plaintext, unsigned int plaintextSize, const EncryptionKey &encKey); - static boost::optional decrypt(const byte *ciphertext, unsigned int ciphertextSize, const EncryptionKey &encKey); - -private: - static constexpr unsigned int IV_SIZE = CryptoPP::AES::BLOCKSIZE; - static constexpr unsigned int TAG_SIZE = 16; -}; - -} -} - -#endif diff --git a/implementations/encrypted/ciphers/CFB_Cipher.h b/implementations/encrypted/ciphers/CFB_Cipher.h new file mode 100644 index 00000000..02028a7e --- /dev/null +++ b/implementations/encrypted/ciphers/CFB_Cipher.h @@ -0,0 +1,63 @@ +#pragma once +#ifndef MESSMER_BLOCKSTORE_IMPLEMENTATIONS_ENCRYPTED_CIPHERS_AES256_CFB_H_ +#define MESSMER_BLOCKSTORE_IMPLEMENTATIONS_ENCRYPTED_CIPHERS_AES256_CFB_H_ + +#include +#include +#include +#include +#include "Cipher.h" + +namespace blockstore { +namespace encrypted { + +template +class CFB_Cipher { +public: + BOOST_CONCEPT_ASSERT((CipherConcept>)); + + using EncryptionKey = cpputils::FixedSizeData; + + static constexpr unsigned int ciphertextSize(unsigned int plaintextBlockSize) { + return plaintextBlockSize + IV_SIZE; + } + + static constexpr unsigned int plaintextSize(unsigned int ciphertextBlockSize) { + return ciphertextBlockSize - IV_SIZE; + } + + static cpputils::Data encrypt(const byte *plaintext, unsigned int plaintextSize, const EncryptionKey &encKey); + static boost::optional decrypt(const byte *ciphertext, unsigned int ciphertextSize, const EncryptionKey &encKey); + +private: + static constexpr unsigned int IV_SIZE = BlockCipher::BLOCKSIZE; +}; + +template +cpputils::Data CFB_Cipher::encrypt(const byte *plaintext, unsigned int plaintextSize, const EncryptionKey &encKey) { + auto iv = cpputils::FixedSizeData::CreatePseudoRandom(); + auto encryption = typename CryptoPP::CFB_Mode::Encryption(encKey.data(), encKey.BINARY_LENGTH, iv.data()); + cpputils::Data ciphertext(ciphertextSize(plaintextSize)); + std::memcpy(ciphertext.data(), iv.data(), IV_SIZE); + encryption.ProcessData((byte*)ciphertext.data() + IV_SIZE, plaintext, plaintextSize); + return ciphertext; +} + +template +boost::optional CFB_Cipher::decrypt(const byte *ciphertext, unsigned int ciphertextSize, const EncryptionKey &encKey) { + if (ciphertextSize < IV_SIZE) { + return boost::none; + } + + const byte *ciphertextIV = ciphertext; + const byte *ciphertextData = ciphertext + IV_SIZE; + auto decryption = typename CryptoPP::CFB_Mode::Decryption((byte*)encKey.data(), encKey.BINARY_LENGTH, ciphertextIV); + cpputils::Data plaintext(plaintextSize(ciphertextSize)); + decryption.ProcessData((byte*)plaintext.data(), ciphertextData, plaintext.size()); + return std::move(plaintext); +} + +} +} + +#endif diff --git a/implementations/encrypted/ciphers/GCM_Cipher.h b/implementations/encrypted/ciphers/GCM_Cipher.h new file mode 100644 index 00000000..3bc7418c --- /dev/null +++ b/implementations/encrypted/ciphers/GCM_Cipher.h @@ -0,0 +1,81 @@ +#pragma once +#ifndef MESSMER_BLOCKSTORE_IMPLEMENTATIONS_ENCRYPTED_CIPHERS_GCM_CIPHER_H_ +#define MESSMER_BLOCKSTORE_IMPLEMENTATIONS_ENCRYPTED_CIPHERS_GCM_CIPHER_H_ + +#include +#include +#include +#include "Cipher.h" + +namespace blockstore { +namespace encrypted { + +template +class GCM_Cipher { +public: + BOOST_CONCEPT_ASSERT((CipherConcept>)); + + using EncryptionKey = cpputils::FixedSizeData; + + static constexpr unsigned int ciphertextSize(unsigned int plaintextBlockSize) { + return plaintextBlockSize + IV_SIZE + TAG_SIZE; + } + + static constexpr unsigned int plaintextSize(unsigned int ciphertextBlockSize) { + return ciphertextBlockSize - IV_SIZE - TAG_SIZE; + } + + static cpputils::Data encrypt(const byte *plaintext, unsigned int plaintextSize, const EncryptionKey &encKey); + static boost::optional decrypt(const byte *ciphertext, unsigned int ciphertextSize, const EncryptionKey &encKey); + +private: + static constexpr unsigned int IV_SIZE = BlockCipher::BLOCKSIZE; + static constexpr unsigned int TAG_SIZE = 16; +}; + +template +cpputils::Data GCM_Cipher::encrypt(const byte *plaintext, unsigned int plaintextSize, const EncryptionKey &encKey) { + auto iv = cpputils::FixedSizeData::CreatePseudoRandom(); + typename CryptoPP::GCM::Encryption encryption; + encryption.SetKeyWithIV(encKey.data(), encKey.BINARY_LENGTH, iv.data(), IV_SIZE); + cpputils::Data ciphertext(ciphertextSize(plaintextSize)); + + std::memcpy(ciphertext.data(), iv.data(), IV_SIZE); + CryptoPP::ArraySource(plaintext, plaintextSize, true, + new CryptoPP::AuthenticatedEncryptionFilter(encryption, + new CryptoPP::ArraySink((byte*)ciphertext.data() + IV_SIZE, ciphertext.size() - IV_SIZE), + false, TAG_SIZE + ) + ); + return ciphertext; +} + +template +boost::optional GCM_Cipher::decrypt(const byte *ciphertext, unsigned int ciphertextSize, const EncryptionKey &encKey) { + if (ciphertextSize < IV_SIZE + TAG_SIZE) { + return boost::none; + } + + const byte *ciphertextIV = ciphertext; + const byte *ciphertextData = ciphertext + IV_SIZE; + typename CryptoPP::GCM::Decryption decryption; + decryption.SetKeyWithIV((byte*)encKey.data(), encKey.BINARY_LENGTH, ciphertextIV, IV_SIZE); + cpputils::Data plaintext(plaintextSize(ciphertextSize)); + + try { + CryptoPP::ArraySource((byte*)ciphertextData, ciphertextSize - IV_SIZE, true, + new CryptoPP::AuthenticatedDecryptionFilter(decryption, + new CryptoPP::ArraySink((byte*)plaintext.data(), plaintext.size()), + CryptoPP::AuthenticatedDecryptionFilter::DEFAULT_FLAGS, TAG_SIZE + ) + ); + return std::move(plaintext); + } catch (const CryptoPP::HashVerificationFilter::HashVerificationFailed &e) { + return boost::none; + } +} + +} +} + +#endif diff --git a/implementations/encrypted/ciphers/ciphers.h b/implementations/encrypted/ciphers/ciphers.h new file mode 100644 index 00000000..a25cc9c3 --- /dev/null +++ b/implementations/encrypted/ciphers/ciphers.h @@ -0,0 +1,49 @@ +#pragma once +#ifndef MESSMER_BLOCKSTORE_IMPLEMENTATIONS_ENCRYPTED_CIPHERS_CIPHERS_H_ +#define MESSMER_BLOCKSTORE_IMPLEMENTATIONS_ENCRYPTED_CIPHERS_CIPHERS_H_ + +#include +#include +#include +#include +#include +#include "GCM_Cipher.h" +#include "CFB_Cipher.h" + +namespace blockstore { +namespace encrypted { + +static_assert(32 == CryptoPP::AES::MAX_KEYLENGTH, "If AES offered larger keys, we should offer a variant with it"); +using AES256_GCM = GCM_Cipher; +using AES256_CFB = CFB_Cipher; +using AES128_GCM = GCM_Cipher; +using AES128_CFB = CFB_Cipher; + +static_assert(32 == CryptoPP::Twofish::MAX_KEYLENGTH, "If Twofish offered larger keys, we should offer a variant with it"); +using Twofish256_GCM = GCM_Cipher; +using Twofish256_CFB = CFB_Cipher; +using Twofish128_GCM = GCM_Cipher; +using Twofish128_CFB = CFB_Cipher; + +static_assert(32 == CryptoPP::Serpent::MAX_KEYLENGTH, "If Serpent offered larger keys, we should offer a variant with it"); +using Serpent256_GCM = GCM_Cipher; +using Serpent256_CFB = CFB_Cipher; +using Serpent128_GCM = GCM_Cipher; +using Serpent128_CFB = CFB_Cipher; + +static_assert(32 == CryptoPP::CAST256::MAX_KEYLENGTH, "If Cast offered larger keys, we should offer a variant with it"); +using Cast256_GCM = GCM_Cipher; +using Cast256_CFB = CFB_Cipher; + +static_assert(56 == CryptoPP::MARS::MAX_KEYLENGTH, "If Mars offered larger keys, we should offer a variant with it"); +using Mars448_GCM = GCM_Cipher; +using Mars448_CFB = CFB_Cipher; +using Mars256_GCM = GCM_Cipher; +using Mars256_CFB = CFB_Cipher; +using Mars128_GCM = GCM_Cipher; +using Mars128_CFB = CFB_Cipher; + +} +} + +#endif diff --git a/test/implementations/caching/CachingBlockStoreTest.cpp b/test/implementations/caching/CachingBlockStoreTest.cpp index 1b6804b2..312012ae 100644 --- a/test/implementations/caching/CachingBlockStoreTest.cpp +++ b/test/implementations/caching/CachingBlockStoreTest.cpp @@ -2,6 +2,7 @@ #include "../../../implementations/testfake/FakeBlockStore.h" #include "../../testutils/BlockStoreTest.h" #include "google/gtest/gtest.h" +#include using blockstore::BlockStore; diff --git a/test/implementations/caching/cache/CacheTest_PushAndPop.cpp b/test/implementations/caching/cache/CacheTest_PushAndPop.cpp index c64cc7b9..f1efd267 100644 --- a/test/implementations/caching/cache/CacheTest_PushAndPop.cpp +++ b/test/implementations/caching/cache/CacheTest_PushAndPop.cpp @@ -3,6 +3,7 @@ #include "../../../../implementations/caching/cache/Cache.h" #include "testutils/MinimalKeyType.h" #include "testutils/MinimalValueType.h" +#include using ::testing::Test; diff --git a/test/implementations/encrypted/CipherTest.cpp b/test/implementations/encrypted/CipherTest.cpp index f5581b05..8c050ca7 100644 --- a/test/implementations/encrypted/CipherTest.cpp +++ b/test/implementations/encrypted/CipherTest.cpp @@ -1,13 +1,11 @@ #include #include "../../../implementations/encrypted/ciphers/Cipher.h" -#include "../../../implementations/encrypted/ciphers/AES256_CFB.h" -#include "../../../implementations/encrypted/ciphers/AES256_GCM.h" +#include "../../../implementations/encrypted/ciphers/ciphers.h" #include "testutils/FakeAuthenticatedCipher.h" #include #include - - #include +#include using namespace blockstore::encrypted; using cpputils::Data; @@ -221,6 +219,38 @@ REGISTER_TYPED_TEST_CASE_P(AuthenticatedCipherTest, INSTANTIATE_TYPED_TEST_CASE_P(Fake, CipherTest, FakeAuthenticatedCipher); INSTANTIATE_TYPED_TEST_CASE_P(Fake, AuthenticatedCipherTest, FakeAuthenticatedCipher); + INSTANTIATE_TYPED_TEST_CASE_P(AES256_CFB, CipherTest, AES256_CFB); //CFB mode is not authenticated INSTANTIATE_TYPED_TEST_CASE_P(AES256_GCM, CipherTest, AES256_GCM); INSTANTIATE_TYPED_TEST_CASE_P(AES256_GCM, AuthenticatedCipherTest, AES256_GCM); +INSTANTIATE_TYPED_TEST_CASE_P(AES128_CFB, CipherTest, AES128_CFB); //CFB mode is not authenticated +INSTANTIATE_TYPED_TEST_CASE_P(AES128_GCM, CipherTest, AES128_GCM); +INSTANTIATE_TYPED_TEST_CASE_P(AES128_GCM, AuthenticatedCipherTest, AES128_GCM); + +INSTANTIATE_TYPED_TEST_CASE_P(Twofish256_CFB, CipherTest, Twofish256_CFB); //CFB mode is not authenticated +INSTANTIATE_TYPED_TEST_CASE_P(Twofish256_GCM, CipherTest, Twofish256_GCM); +INSTANTIATE_TYPED_TEST_CASE_P(Twofish256_GCM, AuthenticatedCipherTest, Twofish256_GCM); +INSTANTIATE_TYPED_TEST_CASE_P(Twofish128_CFB, CipherTest, Twofish128_CFB); //CFB mode is not authenticated +INSTANTIATE_TYPED_TEST_CASE_P(Twofish128_GCM, CipherTest, Twofish128_GCM); +INSTANTIATE_TYPED_TEST_CASE_P(Twofish128_GCM, AuthenticatedCipherTest, Twofish128_GCM); + +INSTANTIATE_TYPED_TEST_CASE_P(Serpent256_CFB, CipherTest, Serpent256_CFB); //CFB mode is not authenticated +INSTANTIATE_TYPED_TEST_CASE_P(Serpent256_GCM, CipherTest, Serpent256_GCM); +INSTANTIATE_TYPED_TEST_CASE_P(Serpent256_GCM, AuthenticatedCipherTest, Serpent256_GCM); +INSTANTIATE_TYPED_TEST_CASE_P(Serpent128_CFB, CipherTest, Serpent128_CFB); //CFB mode is not authenticated +INSTANTIATE_TYPED_TEST_CASE_P(Serpent128_GCM, CipherTest, Serpent128_GCM); +INSTANTIATE_TYPED_TEST_CASE_P(Serpent128_GCM, AuthenticatedCipherTest, Serpent128_GCM); + +INSTANTIATE_TYPED_TEST_CASE_P(Cast256_CFB, CipherTest, Cast256_CFB); //CFB mode is not authenticated +INSTANTIATE_TYPED_TEST_CASE_P(Cast256_GCM, CipherTest, Cast256_GCM); +INSTANTIATE_TYPED_TEST_CASE_P(Cast256_GCM, AuthenticatedCipherTest, Cast256_GCM); + +INSTANTIATE_TYPED_TEST_CASE_P(Mars448_CFB, CipherTest, Mars448_CFB); //CFB mode is not authenticated +INSTANTIATE_TYPED_TEST_CASE_P(Mars448_GCM, CipherTest, Mars448_GCM); +INSTANTIATE_TYPED_TEST_CASE_P(Mars448_GCM, AuthenticatedCipherTest, Mars448_GCM); +INSTANTIATE_TYPED_TEST_CASE_P(Mars256_CFB, CipherTest, Mars256_CFB); //CFB mode is not authenticated +INSTANTIATE_TYPED_TEST_CASE_P(Mars256_GCM, CipherTest, Mars256_GCM); +INSTANTIATE_TYPED_TEST_CASE_P(Mars256_GCM, AuthenticatedCipherTest, Mars256_GCM); +INSTANTIATE_TYPED_TEST_CASE_P(Mars128_CFB, CipherTest, Mars128_CFB); //CFB mode is not authenticated +INSTANTIATE_TYPED_TEST_CASE_P(Mars128_GCM, CipherTest, Mars128_GCM); +INSTANTIATE_TYPED_TEST_CASE_P(Mars128_GCM, AuthenticatedCipherTest, Mars128_GCM); \ No newline at end of file diff --git a/test/implementations/encrypted/EncryptedBlockStoreTest_Generic.cpp b/test/implementations/encrypted/EncryptedBlockStoreTest_Generic.cpp index a72ab547..d0efc39f 100644 --- a/test/implementations/encrypted/EncryptedBlockStoreTest_Generic.cpp +++ b/test/implementations/encrypted/EncryptedBlockStoreTest_Generic.cpp @@ -1,5 +1,4 @@ -#include "../../../implementations/encrypted/ciphers/AES256_GCM.h" -#include "../../../implementations/encrypted/ciphers/AES256_CFB.h" +#include "../../../implementations/encrypted/ciphers/ciphers.h" #include "../../../implementations/encrypted/ciphers/Cipher.h" #include "../../../implementations/encrypted/EncryptedBlockStore.h" #include "../../../implementations/testfake/FakeBlockStore.h"