diff --git a/biicode.conf b/biicode.conf index 67280e2a..886c80b5 100644 --- a/biicode.conf +++ b/biicode.conf @@ -1,6 +1,7 @@ # Biicode configuration file [requirements] + google/gmock: 4 google/gtest: 11 messmer/blobstore: 1 messmer/blockstore: 2 diff --git a/src/config/CryCipher.cpp b/src/config/CryCipher.cpp index 40770bc6..a691e14b 100644 --- a/src/config/CryCipher.cpp +++ b/src/config/CryCipher.cpp @@ -45,7 +45,7 @@ private: optional _warning; }; -const string INTEGRITY_WARNING = "This cipher does not ensure integrity."; +const string CryCiphers::INTEGRITY_WARNING = "This cipher does not ensure integrity."; //We have to use shared_ptr instead of unique_ref, because c++ initializer_list needs copyable values const vector> CryCiphers::SUPPORTED_CIPHERS = { diff --git a/src/config/CryCipher.h b/src/config/CryCipher.h index d4349224..4f43a055 100644 --- a/src/config/CryCipher.h +++ b/src/config/CryCipher.h @@ -26,6 +26,8 @@ public: static const CryCipher& find(const std::string &cipherName); private: + static const std::string INTEGRITY_WARNING; + static const std::vector> SUPPORTED_CIPHERS; }; diff --git a/src/config/CryConfigFile.cpp b/src/config/CryConfigFile.cpp index 626f4ec2..9010c1be 100644 --- a/src/config/CryConfigFile.cpp +++ b/src/config/CryConfigFile.cpp @@ -11,6 +11,9 @@ namespace bf = boost::filesystem; namespace cryfs { CryConfigFile CryConfigFile::create(const bf::path &path, CryConfig config) { + if (bf::exists(path)) { + throw std::runtime_error("Config file exists already."); + } return CryConfigFile(path, std::move(config)); } diff --git a/test/config/CryCipherTest.cpp b/test/config/CryCipherTest.cpp new file mode 100644 index 00000000..08998bb0 --- /dev/null +++ b/test/config/CryCipherTest.cpp @@ -0,0 +1,136 @@ +#include +#include +#include "../../src/config/CryCipher.h" +#include +#include +#include +#include +#include + +using namespace cryfs; +using namespace blockstore::encrypted; +using namespace blockstore::testfake; +using namespace blockstore; + +using std::initializer_list; +using std::string; +using std::vector; +using std::find; +using boost::none; +using testing::MatchesRegex; +using cpputils::DataFixture; +using cpputils::Data; +using cpputils::unique_ref; +using cpputils::make_unique_ref; + +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::CreatePseudoRandom().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::CreatePseudoRandom(); + 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(); + FakeBlockStore *baseStore = _baseStore.get(); + unique_ref encryptedStore = cipher.createEncryptedBlockstore(std::move(_baseStore), encKey); + auto created = encryptedStore->tryCreate(key, std::move(data)); + EXPECT_NE(none, created); + return _loadBlock(baseStore, key); + } + + template + Data _decryptUsingEncryptedBlockStoreWithCipher(const std::string &encKey, const blockstore::Key &key, Data data) { + unique_ref baseStore = make_unique_ref(); + auto created = baseStore->tryCreate(key, std::move(data)); + EXPECT_NE(none, created); + EncryptedBlockStore encryptedStore(std::move(baseStore), Cipher::EncryptionKey::FromString(encKey)); + return _loadBlock(&encryptedStore, key); + } + + Data _loadBlock(BlockStore *store, const blockstore::Key &key) { + auto block = store->load(key).value(); + Data data(block->size()); + std::memcpy(data.data(), block->data(), block->size()); + return data; + } +}; + +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", + "mars-448-gcm", "mars-448-cfb", "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"); + EXPECT_CREATES_CORRECT_ENCRYPTED_BLOCKSTORE("mars-448-gcm"); + EXPECT_CREATES_CORRECT_ENCRYPTED_BLOCKSTORE("mars-448-cfb"); + 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().get(), MatchesRegex(".*integrity.*")); +} + +TEST_F(CryCipherTest, EncryptionKeyHasCorrectSize_448) { + EXPECT_EQ(Mars448_GCM::EncryptionKey::STRING_LENGTH, CryCiphers::find("mars-448-gcm").createKey().size()); +} + +TEST_F(CryCipherTest, EncryptionKeyHasCorrectSize_256) { + EXPECT_EQ(AES256_GCM::EncryptionKey::STRING_LENGTH, CryCiphers::find("aes-256-gcm").createKey().size()); +} + +TEST_F(CryCipherTest, EncryptionKeyHasCorrectSize_128) { + EXPECT_EQ(AES128_GCM::EncryptionKey::STRING_LENGTH, CryCiphers::find("aes-128-gcm").createKey().size()); +} diff --git a/test/filesystem/CryFsTest.cpp b/test/filesystem/CryFsTest.cpp index 367ccc7a..906c0896 100644 --- a/test/filesystem/CryFsTest.cpp +++ b/test/filesystem/CryFsTest.cpp @@ -41,9 +41,9 @@ public: TEST_F(CryFsTest, CreatedRootdirIsLoadableAfterClosing) { { - CryDevice dev(CryConfigLoader().createNewWithWeakKey(config.path()), make_unique_ref(rootdir.path())); + CryDevice dev(CryConfigLoader().createNewForTest(config.path()), make_unique_ref(rootdir.path())); } - CryDevice dev(CryConfigLoader().loadExisting(config.path()).value(), make_unique_ref(rootdir.path())); + CryDevice dev(CryConfigFile::load(config.path()).value(), make_unique_ref(rootdir.path())); auto root = dev.Load(bf::path("/")); dynamic_pointer_move(root.get()).get()->children(); } @@ -52,7 +52,7 @@ TEST_F(CryFsTest, UsingStrongKey1_CreatedRootdirIsLoadableAfterClosing) { { CryDevice dev(CryConfigLoader(make_unique_ref()).createNew(config.path()), make_unique_ref(rootdir.path())); } - CryDevice dev(CryConfigLoader().loadExisting(config.path()).value(), make_unique_ref(rootdir.path())); + CryDevice dev(CryConfigFile::load(config.path()).value(), make_unique_ref(rootdir.path())); auto root = dev.Load(bf::path("/")); dynamic_pointer_move(root.get()).get()->children(); } diff --git a/test/filesystem/FileSystemTest.cpp b/test/filesystem/FileSystemTest.cpp index 4029e4f3..736c87c4 100644 --- a/test/filesystem/FileSystemTest.cpp +++ b/test/filesystem/FileSystemTest.cpp @@ -21,7 +21,7 @@ public: unique_ref createDevice() override { auto blockStore = cpputils::make_unique_ref(); - auto config = CryConfigLoader().loadOrCreateWithWeakKey(configFile.path()); + auto config = CryConfigLoader().loadOrCreateForTest(configFile.path()); return make_unique_ref(std::move(config), std::move(blockStore)); }