#include #include #include #include #include #include #include #include #include using namespace cryfs; using namespace blockstore::encrypted; using namespace blockstore::inmemory; using namespace blockstore; using std::initializer_list; using std::string; using std::vector; using std::find; using boost::none; using testing::MatchesRegex; using namespace cpputils; class CryCipherTest : public ::testing::Test { public: void EXPECT_FINDS_CORRECT_CIPHERS(initializer_list ciphers) { for (const string & cipher : ciphers) { EXPECT_FINDS_CORRECT_CIPHER(cipher); } } void EXPECT_FINDS_CORRECT_CIPHER(const string &cipherName) { EXPECT_EQ(cipherName, CryCiphers::find(cipherName).cipherName()); } template void EXPECT_CREATES_CORRECT_ENCRYPTED_BLOCKSTORE(const string &cipherName) { const auto &actualCipher = CryCiphers::find(cipherName); Data dataFixture = DataFixture::generate(1024); string encKey = ExpectedCipher::EncryptionKey::CreateKey(Random::PseudoRandom()).ToString(); _EXPECT_ENCRYPTS_WITH_ACTUAL_BLOCKSTORE_DECRYPTS_CORRECTLY_WITH_EXPECTED_BLOCKSTORE(actualCipher, encKey, std::move(dataFixture)); } template void _EXPECT_ENCRYPTS_WITH_ACTUAL_BLOCKSTORE_DECRYPTS_CORRECTLY_WITH_EXPECTED_BLOCKSTORE(const CryCipher &actualCipher, const std::string &encKey, Data dataFixture) { blockstore::Key key = blockstore::Key::Random(); Data encrypted = _encryptUsingEncryptedBlockStoreWithCipher(actualCipher, encKey, key, dataFixture.copy()); Data decrypted = _decryptUsingEncryptedBlockStoreWithCipher(encKey, key, std::move(encrypted)); EXPECT_EQ(dataFixture, decrypted); } Data _encryptUsingEncryptedBlockStoreWithCipher(const CryCipher &cipher, const std::string &encKey, const blockstore::Key &key, Data data) { unique_ref _baseStore = make_unique_ref(); InMemoryBlockStore2 *baseStore = _baseStore.get(); unique_ref encryptedStore = cipher.createEncryptedBlockstore(std::move(_baseStore), encKey); bool created = encryptedStore->tryCreate(key, std::move(data)); EXPECT_TRUE(created); return _loadBlock(baseStore, key); } template Data _decryptUsingEncryptedBlockStoreWithCipher(const std::string &encKey, const blockstore::Key &key, Data data) { unique_ref baseStore = make_unique_ref(); bool created = baseStore->tryCreate(key, std::move(data)); EXPECT_TRUE(created); EncryptedBlockStore2 encryptedStore(std::move(baseStore), Cipher::EncryptionKey::FromString(encKey)); return _loadBlock(&encryptedStore, key); } Data _loadBlock(BlockStore2 *store, const blockstore::Key &key) { return store->load(key).value(); } }; TEST_F(CryCipherTest, FindsCorrectCipher) { EXPECT_FINDS_CORRECT_CIPHERS({ "aes-256-gcm", "aes-256-cfb", "aes-256-gcm", "aes-256-cfb", "twofish-256-gcm", "twofish-256-cfb", "twofish-256-gcm", "twofish-256-cfb", "serpent-256-gcm", "serpent-256-cfb", "serpent-256-gcm", "serpent-256-cfb", "cast-256-gcm", "cast-256-cfb", #if CRYPTOPP_VERSION != 564 "mars-448-gcm", "mars-448-cfb", #endif "mars-256-gcm", "mars-256-cfb", "mars-256-gcm", "mars-256-cfb" }); } TEST_F(CryCipherTest, CreatesCorrectEncryptedBlockStore) { EXPECT_CREATES_CORRECT_ENCRYPTED_BLOCKSTORE("aes-256-gcm"); EXPECT_CREATES_CORRECT_ENCRYPTED_BLOCKSTORE("aes-256-cfb"); EXPECT_CREATES_CORRECT_ENCRYPTED_BLOCKSTORE("aes-128-gcm"); EXPECT_CREATES_CORRECT_ENCRYPTED_BLOCKSTORE("aes-128-cfb"); EXPECT_CREATES_CORRECT_ENCRYPTED_BLOCKSTORE("twofish-256-gcm"); EXPECT_CREATES_CORRECT_ENCRYPTED_BLOCKSTORE("twofish-256-cfb"); EXPECT_CREATES_CORRECT_ENCRYPTED_BLOCKSTORE("twofish-128-gcm"); EXPECT_CREATES_CORRECT_ENCRYPTED_BLOCKSTORE("twofish-128-cfb"); EXPECT_CREATES_CORRECT_ENCRYPTED_BLOCKSTORE("serpent-256-gcm"); EXPECT_CREATES_CORRECT_ENCRYPTED_BLOCKSTORE("serpent-256-cfb"); EXPECT_CREATES_CORRECT_ENCRYPTED_BLOCKSTORE("serpent-128-gcm"); EXPECT_CREATES_CORRECT_ENCRYPTED_BLOCKSTORE("serpent-128-cfb"); EXPECT_CREATES_CORRECT_ENCRYPTED_BLOCKSTORE("cast-256-gcm"); EXPECT_CREATES_CORRECT_ENCRYPTED_BLOCKSTORE("cast-256-cfb"); #if CRYPTOPP_VERSION != 564 EXPECT_CREATES_CORRECT_ENCRYPTED_BLOCKSTORE("mars-448-gcm"); EXPECT_CREATES_CORRECT_ENCRYPTED_BLOCKSTORE("mars-448-cfb"); #endif EXPECT_CREATES_CORRECT_ENCRYPTED_BLOCKSTORE("mars-256-gcm"); EXPECT_CREATES_CORRECT_ENCRYPTED_BLOCKSTORE("mars-256-cfb"); EXPECT_CREATES_CORRECT_ENCRYPTED_BLOCKSTORE("mars-128-gcm"); EXPECT_CREATES_CORRECT_ENCRYPTED_BLOCKSTORE("mars-128-cfb"); } TEST_F(CryCipherTest, SupportedCipherNamesContainsACipher) { vector supportedCipherNames = CryCiphers::supportedCipherNames(); EXPECT_NE(supportedCipherNames.end(), find(supportedCipherNames.begin(), supportedCipherNames.end(), "aes-256-gcm")); } TEST_F(CryCipherTest, ThereIsACipherWithoutWarning) { EXPECT_EQ(none, CryCiphers::find("aes-256-gcm").warning()); } TEST_F(CryCipherTest, ThereIsACipherWithIntegrityWarning) { EXPECT_THAT(CryCiphers::find("aes-256-cfb").warning().value(), MatchesRegex(".*integrity.*")); } #if CRYPTOPP_VERSION != 564 TEST_F(CryCipherTest, EncryptionKeyHasCorrectSize_448) { EXPECT_EQ(Mars448_GCM::EncryptionKey::STRING_LENGTH, CryCiphers::find("mars-448-gcm").createKey(Random::PseudoRandom()).size()); } #endif TEST_F(CryCipherTest, EncryptionKeyHasCorrectSize_256) { EXPECT_EQ(AES256_GCM::EncryptionKey::STRING_LENGTH, CryCiphers::find("aes-256-gcm").createKey(Random::PseudoRandom()).size()); } TEST_F(CryCipherTest, EncryptionKeyHasCorrectSize_128) { EXPECT_EQ(AES128_GCM::EncryptionKey::STRING_LENGTH, CryCiphers::find("aes-128-gcm").createKey(Random::PseudoRandom()).size()); }