From 596b04acce405c379cc580d33c1fc35d99328231 Mon Sep 17 00:00:00 2001 From: Sebastian Messmer Date: Sat, 27 Oct 2018 18:18:32 -0700 Subject: [PATCH] Introduce a CryPresetPasswordBasedKeyProvider for when the password is already known --- src/cryfs/CMakeLists.txt | 1 + .../config/CryPasswordBasedKeyProvider.h | 4 +- .../CryPresetPasswordBasedKeyProvider.cpp | 23 ++++++++ .../CryPresetPasswordBasedKeyProvider.h | 27 +++++++++ test/cryfs/CMakeLists.txt | 1 + test/cryfs/config/CompatibilityTest.cpp | 10 +--- test/cryfs/config/CryConfigLoaderTest.cpp | 12 +--- .../CryPresetPasswordBasedKeyProviderTest.cpp | 56 +++++++++++++++++++ test/cryfs/filesystem/CryFsTest.cpp | 12 +--- test/cryfs/filesystem/FileSystemTest.cpp | 12 +--- test/cryfs/filesystem/testutils/CryTestBase.h | 9 +-- 11 files changed, 123 insertions(+), 44 deletions(-) create mode 100644 src/cryfs/config/CryPresetPasswordBasedKeyProvider.cpp create mode 100644 src/cryfs/config/CryPresetPasswordBasedKeyProvider.h create mode 100644 test/cryfs/config/CryPresetPasswordBasedKeyProviderTest.cpp diff --git a/src/cryfs/CMakeLists.txt b/src/cryfs/CMakeLists.txt index d0b7ebe4..62d358de 100644 --- a/src/cryfs/CMakeLists.txt +++ b/src/cryfs/CMakeLists.txt @@ -18,6 +18,7 @@ set(LIB_SOURCES config/CryConfigCreator.cpp config/CryKeyProvider.cpp config/CryPasswordBasedKeyProvider.cpp + config/CryPresetPasswordBasedKeyProvider.cpp filesystem/CryOpenFile.cpp filesystem/fsblobstore/utils/DirEntry.cpp filesystem/fsblobstore/utils/DirEntryList.cpp diff --git a/src/cryfs/config/CryPasswordBasedKeyProvider.h b/src/cryfs/config/CryPasswordBasedKeyProvider.h index 2584a24f..6e6a8fe3 100644 --- a/src/cryfs/config/CryPasswordBasedKeyProvider.h +++ b/src/cryfs/config/CryPasswordBasedKeyProvider.h @@ -4,14 +4,14 @@ #include "CryKeyProvider.h" #include -#include +#include #include namespace cryfs { +// TODO Remove duplication with CryPresetPasswordBasedKeyProvider class CryPasswordBasedKeyProvider final : public CryKeyProvider { public: - // TODO Pass in KDF as dependency (needs changes in the KDF interface because of the static functions ::forNewKey and ::forExistingKey) explicit CryPasswordBasedKeyProvider(std::shared_ptr console, std::function askPasswordForExistingFilesystem, std::function askPasswordForNewFilesystem, cpputils::unique_ref kdf); cpputils::EncryptionKey requestKeyForExistingFilesystem(size_t keySize, const cpputils::Data& kdfParameters) override; diff --git a/src/cryfs/config/CryPresetPasswordBasedKeyProvider.cpp b/src/cryfs/config/CryPresetPasswordBasedKeyProvider.cpp new file mode 100644 index 00000000..9eddf4aa --- /dev/null +++ b/src/cryfs/config/CryPresetPasswordBasedKeyProvider.cpp @@ -0,0 +1,23 @@ +#include "CryPresetPasswordBasedKeyProvider.h" + +using cpputils::unique_ref; +using cpputils::EncryptionKey; +using cpputils::unique_ref; +using cpputils::PasswordBasedKDF; +using cpputils::Data; + +namespace cryfs { + +CryPresetPasswordBasedKeyProvider::CryPresetPasswordBasedKeyProvider(std::string password, unique_ref kdf) +: _password(std::move(password)), _kdf(std::move(kdf)) {} + +EncryptionKey CryPresetPasswordBasedKeyProvider::requestKeyForExistingFilesystem(size_t keySize, const Data& kdfParameters) { + return _kdf->deriveExistingKey(keySize, _password, kdfParameters); +} + +CryPresetPasswordBasedKeyProvider::KeyResult CryPresetPasswordBasedKeyProvider::requestKeyForNewFilesystem(size_t keySize) { + auto keyResult = _kdf->deriveNewKey(keySize, _password); + return {std::move(keyResult.key), std::move(keyResult.kdfParameters)}; +} + +} diff --git a/src/cryfs/config/CryPresetPasswordBasedKeyProvider.h b/src/cryfs/config/CryPresetPasswordBasedKeyProvider.h new file mode 100644 index 00000000..d41b8720 --- /dev/null +++ b/src/cryfs/config/CryPresetPasswordBasedKeyProvider.h @@ -0,0 +1,27 @@ +#pragma once +#ifndef CRYFS_CRYPRESETPASSWORDFROMCONSOLEKEYPROVIDER_H +#define CRYFS_CRYPRESETPASSWORDFROMCONSOLEKEYPROVIDER_H + +#include "CryKeyProvider.h" +#include +#include + +namespace cryfs { + + class CryPresetPasswordBasedKeyProvider final : public CryKeyProvider { + public: + explicit CryPresetPasswordBasedKeyProvider(std::string password, cpputils::unique_ref kdf); + + cpputils::EncryptionKey requestKeyForExistingFilesystem(size_t keySize, const cpputils::Data& kdfParameters) override; + KeyResult requestKeyForNewFilesystem(size_t keySize) override; + + private: + std::string _password; + cpputils::unique_ref _kdf; + + DISALLOW_COPY_AND_ASSIGN(CryPresetPasswordBasedKeyProvider); + }; + +} + +#endif diff --git a/test/cryfs/CMakeLists.txt b/test/cryfs/CMakeLists.txt index 8665a86c..463f13e6 100644 --- a/test/cryfs/CMakeLists.txt +++ b/test/cryfs/CMakeLists.txt @@ -15,6 +15,7 @@ set(SOURCES config/CryConfigLoaderTest.cpp config/CryConfigConsoleTest.cpp config/CryPasswordBasedKeyProviderTest.cpp + config/CryPresetPasswordBasedKeyProviderTest.cpp filesystem/CryFsTest.cpp filesystem/CryNodeTest.cpp filesystem/FileSystemTest.cpp diff --git a/test/cryfs/config/CompatibilityTest.cpp b/test/cryfs/config/CompatibilityTest.cpp index 9ffb70ca..36c1871c 100644 --- a/test/cryfs/config/CompatibilityTest.cpp +++ b/test/cryfs/config/CompatibilityTest.cpp @@ -7,7 +7,7 @@ #include #include #include -#include +#include #include "../testutils/MockConsole.h" using cpputils::Data; @@ -16,7 +16,6 @@ using cpputils::Serpent128_CFB; using cpputils::TempFile; using cpputils::make_unique_ref; using cpputils::SCrypt; -using std::make_shared; using namespace cryfs; // Test that config files created with (old) versions of cryfs are still loadable. @@ -28,12 +27,7 @@ public: CryConfigFile loadConfigFromHex(const string &configFileContentHex) { storeHexToFile(configFileContentHex); - CryPasswordBasedKeyProvider keyProvider( - make_shared(), - [] () {return "mypassword"; }, - [] () {return "mypassword"; }, - make_unique_ref(SCrypt::DefaultSettings) - ); + CryPresetPasswordBasedKeyProvider keyProvider("mypassword", make_unique_ref(SCrypt::DefaultSettings)); return CryConfigFile::load(file.path(), &keyProvider).value(); } diff --git a/test/cryfs/config/CryConfigLoaderTest.cpp b/test/cryfs/config/CryConfigLoaderTest.cpp index 3929b193..8cf30e23 100644 --- a/test/cryfs/config/CryConfigLoaderTest.cpp +++ b/test/cryfs/config/CryConfigLoaderTest.cpp @@ -1,6 +1,6 @@ #include #include -#include +#include #include "../testutils/MockConsole.h" #include "../testutils/TestWithFakeHomeDirectory.h" #include @@ -20,7 +20,7 @@ using cpputils::NoninteractiveConsole; using cpputils::make_unique_ref; using cpputils::Console; using cpputils::unique_ref; -using cryfs::CryPasswordBasedKeyProvider; +using cryfs::CryPresetPasswordBasedKeyProvider; using boost::optional; using boost::none; using std::string; @@ -63,13 +63,7 @@ private: class CryConfigLoaderTest: public ::testing::Test, public TestWithMockConsole, TestWithFakeHomeDirectory { public: unique_ref keyProvider(const string& password) { - auto askPassword = [password] { return password;}; - return make_unique_ref( - console, - askPassword, - askPassword, - make_unique_ref(SCrypt::TestSettings) - ); + return make_unique_ref(password, make_unique_ref(SCrypt::TestSettings)); } CryConfigLoaderTest(): file(false), tempLocalStateDir(), localStateDir(tempLocalStateDir.path()) { diff --git a/test/cryfs/config/CryPresetPasswordBasedKeyProviderTest.cpp b/test/cryfs/config/CryPresetPasswordBasedKeyProviderTest.cpp new file mode 100644 index 00000000..56ea501a --- /dev/null +++ b/test/cryfs/config/CryPresetPasswordBasedKeyProviderTest.cpp @@ -0,0 +1,56 @@ +#include +#include +#include "../testutils/MockConsole.h" +#include + +using cpputils::make_unique_ref; +using cpputils::EncryptionKey; +using cpputils::PasswordBasedKDF; +using cpputils::Data; +using cpputils::DataFixture; +using std::string; +using cryfs::CryPresetPasswordBasedKeyProvider; +using testing::Invoke; +using testing::Eq; +using testing::StrEq; +using testing::_; + +class MockKDF : public PasswordBasedKDF { +public: + MOCK_METHOD3(deriveExistingKey, EncryptionKey(size_t keySize, const string& password, const Data& kdfParameters)); + MOCK_METHOD2(deriveNewKey, KeyResult(size_t keySize, const string& password)); +}; + +TEST(CryPresetPasswordBasedKeyProviderTest, requestKeyForNewFilesystem) { + constexpr size_t keySize = 512; + constexpr const char* password = "mypassword"; + const EncryptionKey key = EncryptionKey::FromString(DataFixture::generate(keySize).ToString()); + auto kdf = make_unique_ref(); + const Data kdfParameters = DataFixture::generate(100); + + EXPECT_CALL(*kdf, deriveNewKey(Eq(keySize), StrEq(password))).Times(1).WillOnce(Invoke([&] (auto, auto) {return PasswordBasedKDF::KeyResult{key, kdfParameters.copy()};})); + + CryPresetPasswordBasedKeyProvider keyProvider(password, std::move(kdf)); + auto returned_key = keyProvider.requestKeyForNewFilesystem(keySize); + + EXPECT_EQ(key.ToString(), returned_key.key.ToString()); + EXPECT_EQ(kdfParameters, returned_key.kdfParameters); +} + +TEST(CryPresetPasswordBasedKeyProviderTest, requestKeyForExistingFilesystem) { + constexpr size_t keySize = 512; + constexpr const char* password = "mypassword"; + const EncryptionKey key = EncryptionKey::FromString(DataFixture::generate(keySize).ToString()); + auto kdf = make_unique_ref(); + const Data kdfParameters = DataFixture::generate(100); + + EXPECT_CALL(*kdf, deriveExistingKey(Eq(keySize), StrEq(password), _)).Times(1).WillOnce(Invoke([&] (auto, auto, const auto& kdfParams) { + EXPECT_EQ(kdfParameters, kdfParams); + return key; + })); + + CryPresetPasswordBasedKeyProvider keyProvider(password, std::move(kdf)); + EncryptionKey returned_key = keyProvider.requestKeyForExistingFilesystem(keySize, kdfParameters); + + EXPECT_EQ(key.ToString(), returned_key.ToString()); +} diff --git a/test/cryfs/filesystem/CryFsTest.cpp b/test/cryfs/filesystem/CryFsTest.cpp index 5cd1a1bb..61854bdf 100644 --- a/test/cryfs/filesystem/CryFsTest.cpp +++ b/test/cryfs/filesystem/CryFsTest.cpp @@ -9,7 +9,7 @@ #include #include "../testutils/MockConsole.h" #include -#include +#include #include #include "../testutils/TestWithFakeHomeDirectory.h" #include @@ -28,7 +28,7 @@ using cpputils::Data; using cpputils::NoninteractiveConsole; using blockstore::ondisk::OnDiskBlockStore2; using boost::none; -using cryfs::CryPasswordBasedKeyProvider; +using cryfs::CryPresetPasswordBasedKeyProvider; namespace bf = boost::filesystem; using namespace cryfs; @@ -39,13 +39,7 @@ public: } CryConfigFile loadOrCreateConfig() { - auto askPassword = [] {return "mypassword";}; - auto keyProvider = make_unique_ref( - make_shared(), - askPassword, - askPassword, - make_unique_ref(SCrypt::TestSettings) - ); + auto keyProvider = make_unique_ref("mypassword", make_unique_ref(SCrypt::TestSettings)); return CryConfigLoader(make_shared(mockConsole()), Random::PseudoRandom(), std::move(keyProvider), localStateDir, none, none, none).loadOrCreate(config.path(), false, false).value().configFile; } diff --git a/test/cryfs/filesystem/FileSystemTest.cpp b/test/cryfs/filesystem/FileSystemTest.cpp index 7f6f6162..dd796195 100644 --- a/test/cryfs/filesystem/FileSystemTest.cpp +++ b/test/cryfs/filesystem/FileSystemTest.cpp @@ -4,7 +4,7 @@ #include #include #include -#include +#include #include "../testutils/MockConsole.h" #include "../testutils/TestWithFakeHomeDirectory.h" @@ -17,7 +17,7 @@ using fspp::Device; using boost::none; using std::make_shared; using blockstore::inmemory::InMemoryBlockStore2; -using cryfs::CryPasswordBasedKeyProvider; +using cryfs::CryPresetPasswordBasedKeyProvider; using namespace cryfs; @@ -29,14 +29,8 @@ public: unique_ref createDevice() override { auto blockStore = cpputils::make_unique_ref(); - auto askPassword = [] {return "mypassword";}; auto _console = make_shared(mockConsole()); - auto keyProvider = make_unique_ref( - _console, - askPassword, - askPassword, - make_unique_ref(SCrypt::TestSettings) - ); + auto keyProvider = make_unique_ref("mypassword", make_unique_ref(SCrypt::TestSettings)); auto config = CryConfigLoader(_console, Random::PseudoRandom(), std::move(keyProvider), localStateDir, none, none, none) .loadOrCreate(configFile.path(), false, false).value(); return make_unique_ref(std::move(config.configFile), std::move(blockStore), localStateDir, config.myClientId, false, false); diff --git a/test/cryfs/filesystem/testutils/CryTestBase.h b/test/cryfs/filesystem/testutils/CryTestBase.h index 457e64c9..e01f631f 100644 --- a/test/cryfs/filesystem/testutils/CryTestBase.h +++ b/test/cryfs/filesystem/testutils/CryTestBase.h @@ -2,7 +2,7 @@ #define MESSMER_CRYFS_TEST_CRYFS_FILESYSTEM_CRYTESTBASE_H #include -#include +#include #include #include #include @@ -21,12 +21,7 @@ public: config.SetCipher("aes-256-gcm"); config.SetEncryptionKey(cpputils::AES256_GCM::EncryptionKey::CreateKey(cpputils::Random::PseudoRandom(), cpputils::AES256_GCM::KEYSIZE).ToString()); config.SetBlocksizeBytes(10240); - cryfs::CryPasswordBasedKeyProvider keyProvider( - std::make_shared(), - [] () {return "mypassword";}, - [] () {return "mypassword";}, - cpputils::make_unique_ref(cpputils::SCrypt::TestSettings) - ); + cryfs::CryPresetPasswordBasedKeyProvider keyProvider("mypassword", cpputils::make_unique_ref(cpputils::SCrypt::TestSettings)); return cryfs::CryConfigFile::create(_configFile.path(), std::move(config), &keyProvider); }