Use either<> to indicate errors in config file loading

This commit is contained in:
Sebastian Messmer 2018-12-22 00:58:30 +01:00
parent 525c29c65d
commit 99688e51ab
16 changed files with 406 additions and 163 deletions

221
src/cpp-utils/either.h Normal file
View File

@ -0,0 +1,221 @@
#pragma once
#ifndef MESSMER_CPPUTILS_EITHER_H
#define MESSMER_CPPUTILS_EITHER_H
#include <boost/optional.hpp>
#include <iostream>
#include "assert/assert.h"
namespace cpputils {
template<class Left, class Right>
class either final {
public:
//TODO Try allowing construction with any type that std::is_convertible to Left or Right.
either(const Left &left): _side(Side::left) {
_construct_left(left);
}
either(Left &&left): _side(Side::left) {
_construct_left(std::move(left));
}
either(const Right &right): _side(Side::right) {
_construct_right(right);
}
either(Right &&right): _side(Side::right) {
_construct_right(std::move(right));
}
//TODO Try allowing copy-construction when Left/Right types are std::is_convertible
either(const either<Left, Right> &rhs): _side(rhs._side) {
if(_side == Side::left) {
_construct_left(rhs._left);
} else {
_construct_right(rhs._right);
}
}
either(either<Left, Right> &&rhs): _side(rhs._side) {
if(_side == Side::left) {
_construct_left(std::move(rhs._left));
} else {
_construct_right(std::move(rhs._right));
}
}
~either() {
_destruct();
}
//TODO Try allowing copy-assignment when Left/Right types are std::is_convertible
either<Left, Right> &operator=(const either<Left, Right> &rhs) {
_destruct();
_side = rhs._side;
if (_side == Side::left) {
_construct_left(rhs._left);
} else {
_construct_right(rhs._right);
}
return *this;
}
either<Left, Right> &operator=(either<Left, Right> &&rhs) {
_destruct();
_side = rhs._side;
if (_side == Side::left) {
_construct_left(std::move(rhs._left));
} else {
_construct_right(std::move(rhs._right));
}
return *this;
}
//TODO fold, map_left, map_right, left_or_else(val), right_or_else(val), left_or_else(func), right_or_else(func)
bool is_left() const {
return _side == Side::left;
}
bool is_right() const {
return _side == Side::right;
}
const Left &left() const& {
ASSERT(is_left(), "Tried to get left side of an either which is right.");
return _left;
}
Left &left() & {
return const_cast<Left&>(const_cast<const either<Left, Right>*>(this)->left());
}
Left &&left() && {
return std::move(left());
}
const Right &right() const& {
ASSERT(is_right(), "Tried to get right side of an either which is left.");
return _right;
}
Right &right() & {
return const_cast<Right&>(const_cast<const either<Left, Right>*>(this)->right());
}
Right &&right() && {
return std::move(right());
}
boost::optional<const Left&> left_opt() const& {
if (_side == Side::left) {
return _left;
} else {
return boost::none;
}
}
boost::optional<Left&> left_opt() & {
if (_side == Side::left) {
return _left;
} else {
return boost::none;
}
}
boost::optional<Left> left_opt() && {
if (_side == Side::left) {
return std::move(_left);
} else {
return boost::none;
}
}
boost::optional<const Right&> right_opt() const& {
if (_side == Side::right) {
return _right;
} else {
return boost::none;
}
}
boost::optional<Right&> right_opt() & {
if (_side == Side::right) {
return _right;
} else {
return boost::none;
}
}
boost::optional<Right> right_opt() && {
if (_side == Side::right) {
return std::move(_right);
} else {
return boost::none;
}
}
private:
union {
Left _left;
Right _right;
};
enum class Side : unsigned char {left, right} _side;
either(Side side): _side(side) {}
template<typename... Args>
void _construct_left(Args&&... args) {
new(&_left)Left(std::forward<Args>(args)...);
}
template<typename... Args>
void _construct_right(Args&&... args) {
new(&_right)Right(std::forward<Args>(args)...);
}
void _destruct() {
if (_side == Side::left) {
_left.~Left();
} else {
_right.~Right();
}
}
template<typename Left_, typename Right_, typename... Args>
friend either<Left_, Right_> make_left(Args&&... args);
template<typename Left_, typename Right_, typename... Args>
friend either<Left_, Right_> make_right(Args&&... args);
};
template<class Left, class Right>
bool operator==(const either<Left, Right> &lhs, const either<Left, Right> &rhs) {
if (lhs.is_left() != rhs.is_left()) {
return false;
}
if (lhs.is_left()) {
return lhs.left() == rhs.left();
} else {
return lhs.right() == rhs.right();
}
}
template<class Left, class Right>
bool operator!=(const either<Left, Right> &lhs, const either<Left, Right> &rhs) {
return !operator==(lhs, rhs);
}
template<class Left, class Right>
std::ostream &operator<<(std::ostream &stream, const either<Left, Right> &value) {
if (value.is_left()) {
stream << "Left(" << value.left() << ")";
} else {
stream << "Right(" << value.right() << ")";
}
return stream;
}
template<typename Left, typename Right, typename... Args>
either<Left, Right> make_left(Args&&... args) {
either<Left, Right> result(either<Left, Right>::Side::left);
result._construct_left(std::forward<Args>(args)...);
return result;
}
template<typename Left, typename Right, typename... Args>
either<Left, Right> make_right(Args&&... args) {
either<Left, Right> result(either<Left, Right>::Side::right);
result._construct_right(std::forward<Args>(args)...);
return result;
}
}
#endif

View File

@ -203,7 +203,7 @@ namespace cryfs {
if (config == none) {
throw CryfsException("Could not load config file. Did you enter the correct password?", ErrorCode::WrongPassword);
}
_checkConfigIntegrity(options.baseDir(), localStateDir, config->configFile, options.allowReplacedFilesystem());
_checkConfigIntegrity(options.baseDir(), localStateDir, *config->configFile, options.allowReplacedFilesystem());
return std::move(*config);
}
@ -241,7 +241,7 @@ namespace cryfs {
throw CryfsException("Integrity violation detected. Unmounting.", ErrorCode::IntegrityViolation);
}
};
const bool missingBlockIsIntegrityViolation = config.configFile.config()->missingBlockIsIntegrityViolation();
const bool missingBlockIsIntegrityViolation = config.configFile->config()->missingBlockIsIntegrityViolation();
_device = optional<unique_ref<CryDevice>>(make_unique_ref<CryDevice>(std::move(config.configFile), std::move(blockStore), std::move(localStateDir), config.myClientId,
options.allowIntegrityViolations(), missingBlockIsIntegrityViolation, std::move(onIntegrityViolation)));
_sanityCheckFilesystem(_device->get());

View File

@ -15,6 +15,9 @@ using std::stringstream;
using std::istream;
using cpputils::Data;
using cpputils::unique_ref;
using cpputils::make_unique_ref;
using cpputils::SCryptSettings;
using cpputils::either;
namespace bf = boost::filesystem;
using namespace cpputils::logging;
@ -24,40 +27,39 @@ CryConfigFile::~CryConfigFile() {
//We do not call save() here, because we do not want the config file to be re-encrypted on each filesystem run
}
optional<CryConfigFile> CryConfigFile::load(bf::path path, CryKeyProvider* keyProvider) {
either<CryConfigFile::LoadError, unique_ref<CryConfigFile>> CryConfigFile::load(bf::path path, CryKeyProvider* keyProvider) {
auto encryptedConfigData = Data::LoadFromFile(path);
if (encryptedConfigData == none) {
LOG(ERR, "Config file not found");
return none;
return LoadError::ConfigFileNotFound;
}
auto encryptor = CryConfigEncryptorFactory::loadExistingKey(*encryptedConfigData, keyProvider);
if (encryptor == none) {
return none;
return LoadError::DecryptionFailed;
}
auto decrypted = (*encryptor)->decrypt(*encryptedConfigData);
if (decrypted == none) {
return none;
return LoadError::DecryptionFailed;
}
CryConfig config = CryConfig::load(decrypted->data);
if (config.Cipher() != decrypted->cipherName) {
LOG(ERR, "Inner cipher algorithm used to encrypt config file doesn't match config value");
return none;
return LoadError::DecryptionFailed;
}
auto configFile = CryConfigFile(std::move(path), std::move(config), std::move(*encryptor));
auto configFile = make_unique_ref<CryConfigFile>(CryConfigFile(std::move(path), std::move(config), std::move(*encryptor)));
if (decrypted->wasInDeprecatedConfigFormat) {
// Migrate it to new format
configFile.save();
configFile->save();
}
//TODO For newer compilers, this works without std::move
return std::move(configFile);
}
CryConfigFile CryConfigFile::create(bf::path path, CryConfig config, CryKeyProvider* keyProvider) {
unique_ref<CryConfigFile> CryConfigFile::create(bf::path path, CryConfig config, CryKeyProvider* keyProvider) {
if (bf::exists(path)) {
throw std::runtime_error("Config file exists already.");
}
auto result = CryConfigFile(std::move(path), std::move(config), CryConfigEncryptorFactory::deriveNewKey(keyProvider));
result.save();
auto result = make_unique_ref<CryConfigFile>(std::move(path), std::move(config), CryConfigEncryptorFactory::deriveNewKey(keyProvider));
result->save();
return result;
}
@ -72,7 +74,7 @@ void CryConfigFile::save() const {
}
CryConfig *CryConfigFile::config() {
return const_cast<CryConfig *>(const_cast<const CryConfigFile*>(this)->config());
return const_cast<CryConfig*>(const_cast<const CryConfigFile*>(this)->config());
}
const CryConfig *CryConfigFile::config() const {

View File

@ -6,24 +6,28 @@
#include <boost/filesystem.hpp>
#include "CryConfig.h"
#include <cpp-utils/crypto/symmetric/ciphers.h>
#include <cpp-utils/either.h>
#include "crypto/CryConfigEncryptorFactory.h"
namespace cryfs {
class CryConfigFile final {
public:
CryConfigFile(boost::filesystem::path path, CryConfig config, cpputils::unique_ref<CryConfigEncryptor> encryptor);
CryConfigFile(CryConfigFile &&rhs) = default;
~CryConfigFile();
static CryConfigFile create(boost::filesystem::path path, CryConfig config, CryKeyProvider* keyProvider);
static boost::optional<CryConfigFile> load(boost::filesystem::path path, CryKeyProvider* keyProvider);
static cpputils::unique_ref<CryConfigFile> create(boost::filesystem::path path, CryConfig config, CryKeyProvider* keyProvider);
enum class LoadError {ConfigFileNotFound, DecryptionFailed};
static cpputils::either<LoadError, cpputils::unique_ref<CryConfigFile>> load(boost::filesystem::path path, CryKeyProvider* keyProvider);
void save() const;
CryConfig *config();
const CryConfig *config() const;
private:
CryConfigFile(boost::filesystem::path path, CryConfig config, cpputils::unique_ref<CryConfigEncryptor> encryptor);
boost::filesystem::path _path;
CryConfig _config;
cpputils::unique_ref<CryConfigEncryptor> _encryptor;

View File

@ -6,9 +6,9 @@
#include <boost/algorithm/string/predicate.hpp>
#include <gitversion/gitversion.h>
#include <gitversion/VersionCompare.h>
#include "../localstate/LocalStateDir.h"
#include "../localstate/LocalStateMetadata.h"
#include "../CryfsException.h"
#include "cryfs/localstate/LocalStateDir.h"
#include "cryfs/localstate/LocalStateMetadata.h"
#include "cryfs/CryfsException.h"
namespace bf = boost::filesystem;
using cpputils::Console;
@ -33,35 +33,35 @@ CryConfigLoader::CryConfigLoader(shared_ptr<Console> console, RandomGenerator &k
optional<CryConfigLoader::ConfigLoadResult> CryConfigLoader::_loadConfig(bf::path filename, bool allowFilesystemUpgrade, bool allowReplacedFilesystem) {
auto config = CryConfigFile::load(std::move(filename), _keyProvider.get());
if (config == none) {
if (config.is_left()) {
return none;
}
#ifndef CRYFS_NO_COMPATIBILITY
//Since 0.9.7 and 0.9.8 set their own version to cryfs.version instead of the filesystem format version (which is 0.9.6), overwrite it
if (config->config()->Version() == "0.9.7" || config->config()->Version() == "0.9.8") {
config->config()->SetVersion("0.9.6");
if (config.right()->config()->Version() == "0.9.7" || config.right()->config()->Version() == "0.9.8") {
config.right()->config()->SetVersion("0.9.6");
}
#endif
_checkVersion(*config->config(), allowFilesystemUpgrade);
_checkVersion(*config.right()->config(), allowFilesystemUpgrade);
#ifndef CRYFS_NO_COMPATIBILITY
//Since 0.9.3-alpha set the config value cryfs.blocksizeBytes wrongly to 32768 (but didn't use the value), we have to fix this here.
if (config->config()->Version() != "0+unknown" && VersionCompare::isOlderThan(config->config()->Version(), "0.9.3-rc1")) {
config->config()->SetBlocksizeBytes(32832);
if (config.right()->config()->Version() != "0+unknown" && VersionCompare::isOlderThan(config.right()->config()->Version(), "0.9.3-rc1")) {
config.right()->config()->SetBlocksizeBytes(32832);
}
#endif
if (config->config()->Version() != CryConfig::FilesystemFormatVersion) {
config->config()->SetVersion(CryConfig::FilesystemFormatVersion);
config->save();
if (config.right()->config()->Version() != CryConfig::FilesystemFormatVersion) {
config.right()->config()->SetVersion(CryConfig::FilesystemFormatVersion);
config.right()->save();
}
if (config->config()->LastOpenedWithVersion() != gitversion::VersionString()) {
config->config()->SetLastOpenedWithVersion(gitversion::VersionString());
config->save();
if (config.right()->config()->LastOpenedWithVersion() != gitversion::VersionString()) {
config.right()->config()->SetLastOpenedWithVersion(gitversion::VersionString());
config.right()->save();
}
_checkCipher(*config->config());
auto localState = LocalStateMetadata::loadOrGenerate(_localStateDir.forFilesystemId(config->config()->FilesystemId()), cpputils::Data::FromString(config->config()->EncryptionKey()), allowReplacedFilesystem);
_checkCipher(*config.right()->config());
auto localState = LocalStateMetadata::loadOrGenerate(_localStateDir.forFilesystemId(config.right()->config()->FilesystemId()), cpputils::Data::FromString(config.right()->config()->EncryptionKey()), allowReplacedFilesystem);
uint32_t myClientId = localState.myClientId();
_checkMissingBlocksAreIntegrityViolations(&*config, myClientId);
return ConfigLoadResult {std::move(*config), myClientId};
_checkMissingBlocksAreIntegrityViolations(config.right().get(), myClientId);
return ConfigLoadResult {std::move(config.right()), myClientId};
}
void CryConfigLoader::_checkVersion(const CryConfig &config, bool allowFilesystemUpgrade) {

View File

@ -18,7 +18,7 @@ public:
CryConfigLoader(CryConfigLoader &&rhs) = default;
struct ConfigLoadResult {
CryConfigFile configFile;
cpputils::unique_ref<CryConfigFile> configFile;
uint32_t myClientId;
};

View File

@ -1,6 +1,6 @@
#include <blockstore/implementations/caching/CachingBlockStore2.h>
#include <cpp-utils/crypto/symmetric/ciphers.h>
#include "parallelaccessfsblobstore/DirBlobRef.h"
#include "cryfs/filesystem/parallelaccessfsblobstore/DirBlobRef.h"
#include "CryDevice.h"
#include "CryDir.h"
@ -13,9 +13,9 @@
#include <blockstore/implementations/low2highlevel/LowToHighLevelBlockStore.h>
#include <blockstore/implementations/encrypted/EncryptedBlockStore2.h>
#include <blockstore/implementations/integrity/IntegrityBlockStore2.h>
#include "parallelaccessfsblobstore/ParallelAccessFsBlobStore.h"
#include "cachingfsblobstore/CachingFsBlobStore.h"
#include "../config/CryCipher.h"
#include "cryfs/filesystem/parallelaccessfsblobstore/ParallelAccessFsBlobStore.h"
#include "cryfs/filesystem/cachingfsblobstore/CachingFsBlobStore.h"
#include "cryfs/config/CryCipher.h"
#include <cpp-utils/system/homedir.h>
#include <gitversion/VersionCompare.h>
#include <blockstore/interface/BlockStore2.h>
@ -52,9 +52,9 @@ namespace bf = boost::filesystem;
namespace cryfs {
CryDevice::CryDevice(CryConfigFile configFile, unique_ref<BlockStore2> blockStore, const LocalStateDir& localStateDir, uint32_t myClientId, bool allowIntegrityViolations, bool missingBlockIsIntegrityViolation, std::function<void()> onIntegrityViolation)
: _fsBlobStore(CreateFsBlobStore(std::move(blockStore), &configFile, localStateDir, myClientId, allowIntegrityViolations, missingBlockIsIntegrityViolation, std::move(onIntegrityViolation))),
_rootBlobId(GetOrCreateRootBlobId(&configFile)),
CryDevice::CryDevice(std::shared_ptr<CryConfigFile> configFile, unique_ref<BlockStore2> blockStore, const LocalStateDir& localStateDir, uint32_t myClientId, bool allowIntegrityViolations, bool missingBlockIsIntegrityViolation, std::function<void()> onIntegrityViolation)
: _fsBlobStore(CreateFsBlobStore(std::move(blockStore), configFile.get(), localStateDir, myClientId, allowIntegrityViolations, missingBlockIsIntegrityViolation, std::move(onIntegrityViolation))),
_rootBlobId(GetOrCreateRootBlobId(configFile.get())), _configFile(std::move(configFile)),
_onFsAction() {
}
@ -132,6 +132,10 @@ BlockId CryDevice::CreateRootBlobAndReturnId() {
return rootBlob->blockId();
}
const CryConfig &CryDevice::config() const {
return *_configFile->config();
}
optional<unique_ref<fspp::File>> CryDevice::LoadFile(const bf::path &path) {
auto loaded = Load(path);
if (loaded == none) {

View File

@ -4,22 +4,22 @@
#include <blockstore/interface/BlockStore.h>
#include <blockstore/interface/BlockStore2.h>
#include "../config/CryConfigFile.h"
#include "cryfs/config/CryConfigFile.h"
#include <boost/filesystem.hpp>
#include <fspp/fs_interface/Device.h>
#include <cryfs/localstate/LocalStateDir.h>
#include "parallelaccessfsblobstore/ParallelAccessFsBlobStore.h"
#include "parallelaccessfsblobstore/DirBlobRef.h"
#include "parallelaccessfsblobstore/FileBlobRef.h"
#include "parallelaccessfsblobstore/SymlinkBlobRef.h"
#include "cryfs/filesystem/parallelaccessfsblobstore/ParallelAccessFsBlobStore.h"
#include "cryfs/filesystem/parallelaccessfsblobstore/DirBlobRef.h"
#include "cryfs/filesystem/parallelaccessfsblobstore/FileBlobRef.h"
#include "cryfs/filesystem/parallelaccessfsblobstore/SymlinkBlobRef.h"
namespace cryfs {
class CryDevice final: public fspp::Device {
public:
CryDevice(CryConfigFile config, cpputils::unique_ref<blockstore::BlockStore2> blockStore, const LocalStateDir& localStateDir, uint32_t myClientId, bool allowIntegrityViolations, bool missingBlockIsIntegrityViolation, std::function<void ()> onIntegrityViolation);
CryDevice(std::shared_ptr<CryConfigFile> config, cpputils::unique_ref<blockstore::BlockStore2> blockStore, const LocalStateDir& localStateDir, uint32_t myClientId, bool allowIntegrityViolations, bool missingBlockIsIntegrityViolation, std::function<void ()> onIntegrityViolation);
statvfs statfs() override;
@ -41,6 +41,7 @@ public:
boost::optional<cpputils::unique_ref<fspp::Dir>> LoadDir(const boost::filesystem::path &path) override;
boost::optional<cpputils::unique_ref<fspp::Symlink>> LoadSymlink(const boost::filesystem::path &path) override;
const CryConfig &config() const;
void callFsActionCallbacks() const;
uint64_t numBlocks() const;
@ -50,6 +51,7 @@ private:
cpputils::unique_ref<parallelaccessfsblobstore::ParallelAccessFsBlobStore> _fsBlobStore;
blockstore::BlockId _rootBlobId;
std::shared_ptr<CryConfigFile> _configFile;
std::vector<std::function<void()>> _onFsAction;
blockstore::BlockId GetOrCreateRootBlobId(CryConfigFile *config);

View File

@ -33,7 +33,9 @@ boost::optional<unique_ref<FsBlob>> FsBlobStore::load(const blockstore::BlockId
#ifndef CRYFS_NO_COMPATIBILITY
unique_ref<FsBlobStore> FsBlobStore::migrateIfNeeded(unique_ref<BlobStore> blobStore, const blockstore::BlockId &rootBlobId) {
auto rootBlob = blobStore->load(rootBlobId);
ASSERT(rootBlob != none, "Could not load root blob");
if (rootBlob == none) {
throw std::runtime_error("Could not load root blob");
}
uint16_t format = FsBlobView::getFormatVersionHeader(**rootBlob);
auto fsBlobStore = make_unique_ref<FsBlobStore>(std::move(blobStore));

View File

@ -80,8 +80,8 @@ void _forEachBlockInBlob(DataNodeStore* nodeStore, const BlockId& rootId, std::f
unique_ref<BlockStore> makeBlockStore(const path& basedir, const CryConfigLoader::ConfigLoadResult& config, LocalStateDir& localStateDir) {
auto onDiskBlockStore = make_unique_ref<OnDiskBlockStore2>(basedir);
auto encryptedBlockStore = CryCiphers::find(config.configFile.config()->Cipher()).createEncryptedBlockstore(std::move(onDiskBlockStore), config.configFile.config()->EncryptionKey());
auto statePath = localStateDir.forFilesystemId(config.configFile.config()->FilesystemId());
auto encryptedBlockStore = CryCiphers::find(config.configFile->config()->Cipher()).createEncryptedBlockstore(std::move(onDiskBlockStore), config.configFile->config()->EncryptionKey());
auto statePath = localStateDir.forFilesystemId(config.configFile->config()->FilesystemId());
auto integrityFilePath = statePath / "integritydata";
auto onIntegrityViolation = [] () {
std::cerr << "Warning: Integrity violation encountered" << std::endl;
@ -92,11 +92,11 @@ unique_ref<BlockStore> makeBlockStore(const path& basedir, const CryConfigLoader
std::vector<BlockId> _getKnownBlobIds(const path& basedir, const CryConfigLoader::ConfigLoadResult& config, LocalStateDir& localStateDir) {
auto blockStore = makeBlockStore(basedir, config, localStateDir);
auto fsBlobStore = make_unique_ref<FsBlobStore>(make_unique_ref<BlobStoreOnBlocks>(std::move(blockStore), config.configFile.config()->BlocksizeBytes()));
auto fsBlobStore = make_unique_ref<FsBlobStore>(make_unique_ref<BlobStoreOnBlocks>(std::move(blockStore), config.configFile->config()->BlocksizeBytes()));
std::vector<BlockId> result;
cout << "Listing all file system entities (i.e. blobs)..." << flush;
auto rootId = BlockId::FromString(config.configFile.config()->RootBlob());
auto rootId = BlockId::FromString(config.configFile->config()->RootBlob());
_forEachBlob(fsBlobStore.get(), rootId, [&result] (const BlockId& blockId) {
result.push_back(blockId);
});
@ -108,7 +108,7 @@ std::vector<BlockId> _getKnownBlockIds(const path& basedir, const CryConfigLoade
auto knownBlobIds = _getKnownBlobIds(basedir, config, localStateDir);
auto blockStore = makeBlockStore(basedir, config, localStateDir);
auto nodeStore = make_unique_ref<DataNodeStore>(std::move(blockStore), config.configFile.config()->BlocksizeBytes());
auto nodeStore = make_unique_ref<DataNodeStore>(std::move(blockStore), config.configFile->config()->BlocksizeBytes());
std::vector<BlockId> result;
const uint32_t numNodes = nodeStore->numNodes();
result.reserve(numNodes);
@ -177,7 +177,7 @@ int main(int argc, char* argv[]) {
console->print("Calculate statistics\n");
auto blockStore = makeBlockStore(basedir, *config, localStateDir);
auto nodeStore = make_unique_ref<DataNodeStore>(std::move(blockStore), config->configFile.config()->BlocksizeBytes());
auto nodeStore = make_unique_ref<DataNodeStore>(std::move(blockStore), config->configFile->config()->BlocksizeBytes());
uint32_t numUnaccountedBlocks = unaccountedBlocks.size();
uint32_t numLeaves = 0;

View File

@ -69,16 +69,16 @@ class CliTest_IntegrityCheck : public CliTest {
public:
void modifyFilesystemId() {
FakeCryKeyProvider keyProvider;
auto configFile = CryConfigFile::load(basedir / "cryfs.config", &keyProvider).value();
configFile.config()->SetFilesystemId(CryConfig::FilesystemID::FromString("0123456789ABCDEF0123456789ABCDEF"));
configFile.save();
auto configFile = CryConfigFile::load(basedir / "cryfs.config", &keyProvider).right_opt().value();
configFile->config()->SetFilesystemId(CryConfig::FilesystemID::FromString("0123456789ABCDEF0123456789ABCDEF"));
configFile->save();
}
void modifyFilesystemKey() {
FakeCryKeyProvider keyProvider;
auto configFile = CryConfigFile::load(basedir / "cryfs.config", &keyProvider).value();
configFile.config()->SetEncryptionKey("0123456789ABCDEF0123456789ABCDEF");
configFile.save();
auto configFile = CryConfigFile::load(basedir / "cryfs.config", &keyProvider).right_opt().value();
configFile->config()->SetEncryptionKey("0123456789ABCDEF0123456789ABCDEF");
configFile->save();
}
};

View File

@ -14,8 +14,10 @@ using cpputils::Data;
using cpputils::AES256_GCM;
using cpputils::Serpent128_CFB;
using cpputils::TempFile;
using cpputils::unique_ref;
using cpputils::make_unique_ref;
using cpputils::SCrypt;
using namespace cryfs;
// Test that config files created with (old) versions of cryfs are still loadable.
@ -25,10 +27,10 @@ class CryConfigCompatibilityTest: public ::testing::Test {
public:
TempFile file;
CryConfigFile loadConfigFromHex(const string &configFileContentHex) {
unique_ref<CryConfigFile> loadConfigFromHex(const string &configFileContentHex) {
storeHexToFile(configFileContentHex);
CryPresetPasswordBasedKeyProvider keyProvider("mypassword", make_unique_ref<SCrypt>(SCrypt::DefaultSettings));
return CryConfigFile::load(file.path(), &keyProvider).value();
return CryConfigFile::load(file.path(), &keyProvider).right();
}
private:
@ -57,14 +59,14 @@ private:
TEST_F(CryConfigCompatibilityTest, v0_8_1_with_aes_256_gcm) {
auto config = loadConfigFromHex("63727966732e636f6e6669673b303b736372797074000004000000000000010000000100000020000000000000000af023e55f804ad303c1dbdf6a2b2bed8cc1ab3d0b2f3312c073628dc041e6f3b92f54fad63a1d4e0ad47a33e65e08080dd4e5bdec0a95fe777705ad68e88eabcb4b91d4f25c32e3e44d6e893421c9efa6d4b2c56d66d0546a410de489b04160b276184ebe7dd77840ce6e414f829bb4399451e055d3406261b4faf5fb52f27e21823f8073df255f96b37edf2c2e58ecee21ae82e3883341024aff326cc4c0929f0ed90473511cbe801d1e34899b3cdb9556477be0127c35375967bf7c8392ad4d30d81479c7923900f532b195b71cff868fa1643d1f9e0a0d7996260691d7b5b8ef3c319c2f2303f822eac389e1d6822e7ee57df60c922fa10fbc7e5970e723df2fdb2a6529c94ea1d2507f55cb9bc3fecab77bf3102e96c6675a618b54bb18e632dd99d3d47fa9e24392535abc8c76f891df76c2193233d6c93851966f69def3f53108be83b30980c98e377186da71297a1b61df76e9f138a3998577a0c486452f1b6a2d89b1e62d78695ac6a062d5a4cf5972de7bc2775fd27d25337f0666250f19d6fe50fe762371befa26de6a9299d7df362780f59ccc475e28c71cc5af9e817e4e2160005393ec7fb385d467e0915e7169934ea986141101c9e6b9c62b8819c51a4422e7fe58e24c3293c3f12173a4c480334cb67c9313df667c65802fb778e20f5a4d6cfd07fffb35c2ae8fdf235882bf0e6371125509872e73bd1bc3faca72948db76d8179e08bf3391bafdede591d5623240ba072ada17c2444116bf8c08ee32367eb86eda02ecfecc625b4bc974428b8f5024df430c352b9849f48774bac1455e7364f7660abc039d2a1134cde596a1e7c3a1a8d68591e8640a2d308e2ea5f03874ba1fa8e9ffec2d1bc1541d124adcd3e9f4ed23343e2148629317e6304c63c2a5ceeeb572246393c8e50196728e0b604aa9e2d49e65680cc53ee343645412239f82500ef3d70a6b6e3335ef8cbcfe4fd46b84f634f6fe96cd1b79207a2120ac2bad668bcdbc377b98448c9afbbda9fe8164dbb48aaa68b0aaa90e52bc419ea2ea1f5e12bb649831af12f1ef14765f312640e22c5508531bd46e3ab3a7f922a91fb83332104609e385d61d3778bc5acb03bee522ea5b791d27026fd589ec2b32f04caaf2ef2effbd50e12430ef42631fdabd061966fde1489b9a1eff3fe40b295d75e36af19ae0e69559b9c81b3bc47b35fef5c7038b83db6729aac522efee897a44895804ffbeb11317a78586f8a3511905514eee86d7cf0a395f5f0af521c72542e544ff359a69150a5e64f00b020d48c20d5716331c3b0ac314eeceaadf8b73516b4273b48046b5c3a3980bade0cc25baf54afb27755d155d4b94fa556deb30d58b1d920cbe01b13479135ff84d6a9345a0d418075ecc66bd10d8d2a07963450256897018f54b2a88fffe9383913565823dbfb71568f5d9af93e542937ecde25c2d4407ad964ece5c09a1f81a57c18a8bb2aa8d9d062415903c98752d70ad7175d0d30b391da77459e9a68a69825b3bb4061bc2504789fc395");
EXPECT_EQ(AES256_GCM::NAME, config.config()->Cipher());
EXPECT_EQ("4A70AD8AC565A5123586D0928B496465", config.config()->RootBlob());
EXPECT_EQ(AES256_GCM::NAME, config->config()->Cipher());
EXPECT_EQ("4A70AD8AC565A5123586D0928B496465", config->config()->RootBlob());
}
TEST_F(CryConfigCompatibilityTest, v0_8_1_with_serpent_128_cfb) {
auto config = loadConfigFromHex("63727966732e636f6e6669673b303b736372797074000004000000000000010000000100000020000000000000006496611b94011d03433181e83e80c19888a5607392c2117cd377251978fbbf8d46716bd90dbae3c1728b40e7dc086ee97b8a641f1ea6cc31ccda9a1e4a7a1bf4b6ca3d1d0075acba94017c034e87dfad048c9448df24ea7b89b14d60c9f9e0162cfeb420a85759aaa011232cff99e81b25c456cb13690d5cc735e61ef9b01800961a90488073c5320c14a562f0eccd32383d144476d72d9c61733fb3561f5187c2d6069ce7ff4c43df4fc3f7c1d63df239d05a2b377f70816fb31f7a65d8fa667cd14b62a67e2d67adbf841860af2abed9d4c839c510c7fac7cd58210238830a4926917d663500dd3dc2395845297b3726c00228cb08a2bde648d2e9bc2a3e8655f86bc2f5c2b327e71c75b92894dd43b56dfefeeea598fbae9782dca64cc9676df3a954a9ecedbe3f8fe16e790aeec2ac2336984c8fcce74bfebf310d6fdcc0882ee7f2bdd32928aa53b09084e8035ec235ebe971a0b141e5fcab6ce2207f0f399e683ff4994ed638194cc7d3891019a2a674d14180114494e21270e4234a51e28661d4ac908d4f2b2d7c94ffcb74df8c9f08fb68d9a7167a05fae370e041689cce5fb13fdf3ff14863f6c882e6d302eafe5348362c026853a3717756cefb4657a721efab95f6d949b508a98de86885fe37b2f16f1792411ff47c1074e2c2d301e6401f251854b28c329040c8e55184402648bc79710536390b0f99acd2400734a81e8bd573d9a96971a5ef195d85babbe1092e271a69a146d2d4114b855c89b710908d4a584e598b6dd186709d956fbd8b13b2ba3e9115c7d75416b7ac0e6d9dde83d367af00fa8dae54f03079cdf5fa1bac35ff3fbf6440f4fa41d06278fd8a6c3edc80d4ceee900975db2a345d8eda0ce0260d389a8336134a20945c1dde16e475ae537a4407da7f389dce79b439d0d81fa915a7dc4cb018e0d1bd806101ff53970731876850255dd5b7d78bf817112bc74ebae39ecae0aa1555e2a9e61660f4ba373086492e0561efb3bfa98399f899d6909415f19963cef3dc6d154056403ed1f475cbc78981cc949c23686bd71b420ed7ce654578d322f1eeec7413c77c017479f2e19b0c5ebb25ad76e1af8ec3a6b6ba3e092af8ddd624dfd1fccb4a61cc77f5c001fafdd7d2cc6c7b418c6dac97e840bc027ef9d4b237eebc2d1255bc0f796c3de78e31a9ae346734801e0f51dc47f8279164ab35bad3b06a5f74356deec0296c350aae4da560b8d77782195621dca054703433037f28cac2603cdefe52903f25013ad4cf4f29e0e413f89f950d26b4ef129aabf78abf9acae252bc60db373cfe3963fc87e9532056f2f2a7f9f1ddd1a3cf9d0078a5c9cccdcc60714de967556032283075424446ccda9f62a5e31f2b5efbc2256c742e4a300d5bc797e90b3a65fdffe3c5f22f5a885903331dbbb031e51411facb4e80e1728c5b14c9fce196d7d5f1dfeca2fe9b877f45fc1f1c8ec09dd5335eb89accf38fe0e6dbbe77a59c96a49830ce5279f17f4897c64e2aeaec127d8d06adcefa7ac800c1e8");
EXPECT_EQ(Serpent128_CFB::NAME, config.config()->Cipher());
EXPECT_EQ("5821ED3B0739C7EDB6A09590232EA75B", config.config()->RootBlob());
EXPECT_EQ(Serpent128_CFB::NAME, config->config()->Cipher());
EXPECT_EQ("5821ED3B0739C7EDB6A09590232EA75B", config->config()->RootBlob());
}
#endif

View File

@ -1,10 +1,12 @@
#include <gtest/gtest.h>
#include <cryfs/config/CryConfigFile.h>
#include <cpp-utils/tempfile/TempFile.h>
#include <cpp-utils/pointer/unique_ref_boost_optional_gtest_workaround.h>
#include "../testutils/FakeCryKeyProvider.h"
using namespace cryfs;
using cpputils::TempFile;
using cpputils::unique_ref;
using std::string;
using boost::optional;
using boost::none;
@ -33,7 +35,7 @@ public:
return result;
}
CryConfigFile CreateAndLoadEmpty(unsigned char keySeed = 0) {
unique_ref<CryConfigFile> CreateAndLoadEmpty(unsigned char keySeed = 0) {
Create(Config(), keySeed);
return Load().value();
}
@ -43,9 +45,9 @@ public:
CryConfigFile::create(file.path(), std::move(cfg), &keyProvider);
}
optional<CryConfigFile> Load(unsigned int keySeed = 0) {
optional<unique_ref<CryConfigFile>> Load(unsigned char keySeed = 0) {
FakeCryKeyProvider keyProvider(keySeed);
return CryConfigFile::load(file.path(), &keyProvider);
return CryConfigFile::load(file.path(), &keyProvider).right_opt();
}
void CreateWithCipher(const string &cipher) {
@ -69,108 +71,108 @@ TEST_F(CryConfigFileTest, DoesntLoadIfWrongPassword) {
}
TEST_F(CryConfigFileTest, RootBlob_Init) {
CryConfigFile created = CreateAndLoadEmpty();
EXPECT_EQ("", created.config()->RootBlob());
unique_ref<CryConfigFile> created = CreateAndLoadEmpty();
EXPECT_EQ("", created->config()->RootBlob());
}
TEST_F(CryConfigFileTest, RootBlob_CreateAndLoad) {
CryConfig cfg = Config();
cfg.SetRootBlob("rootblobid");
Create(std::move(cfg));
CryConfigFile loaded = Load().value();
EXPECT_EQ("rootblobid", loaded.config()->RootBlob());
unique_ref<CryConfigFile> loaded = std::move(Load().value());
EXPECT_EQ("rootblobid", loaded->config()->RootBlob());
}
TEST_F(CryConfigFileTest, RootBlob_SaveAndLoad) {
CryConfigFile created = CreateAndLoadEmpty();
created.config()->SetRootBlob("rootblobid");
created.save();
CryConfigFile loaded = Load().value();
EXPECT_EQ("rootblobid", loaded.config()->RootBlob());
unique_ref<CryConfigFile> created = CreateAndLoadEmpty();
created->config()->SetRootBlob("rootblobid");
created->save();
unique_ref<CryConfigFile> loaded = std::move(Load().value());
EXPECT_EQ("rootblobid", loaded->config()->RootBlob());
}
TEST_F(CryConfigFileTest, EncryptionKey_Init) {
CryConfigFile created = CreateAndLoadEmpty();
EXPECT_EQ("", created.config()->EncryptionKey());
unique_ref<CryConfigFile> created = CreateAndLoadEmpty();
EXPECT_EQ("", created->config()->EncryptionKey());
}
TEST_F(CryConfigFileTest, EncryptionKey_CreateAndLoad) {
CryConfig cfg = Config();
cfg.SetEncryptionKey("encryptionkey");
Create(std::move(cfg));
CryConfigFile loaded = Load().value();
EXPECT_EQ("encryptionkey", loaded.config()->EncryptionKey());
unique_ref<CryConfigFile> loaded = std::move(Load().value());
EXPECT_EQ("encryptionkey", loaded->config()->EncryptionKey());
}
TEST_F(CryConfigFileTest, EncryptionKey_SaveAndLoad) {
CryConfigFile created = CreateAndLoadEmpty();
created.config()->SetEncryptionKey("encryptionkey");
created.save();
CryConfigFile loaded = Load().value();
EXPECT_EQ("encryptionkey", loaded.config()->EncryptionKey());
unique_ref<CryConfigFile> created = CreateAndLoadEmpty();
created->config()->SetEncryptionKey("encryptionkey");
created->save();
unique_ref<CryConfigFile> loaded = std::move(Load().value());
EXPECT_EQ("encryptionkey", loaded->config()->EncryptionKey());
}
TEST_F(CryConfigFileTest, Cipher_Init) {
CryConfigFile created = CreateAndLoadEmpty();
EXPECT_EQ("aes-256-gcm", created.config()->Cipher());
unique_ref<CryConfigFile> created = CreateAndLoadEmpty();
EXPECT_EQ("aes-256-gcm", created->config()->Cipher());
}
TEST_F(CryConfigFileTest, Cipher_CreateAndLoad) {
CryConfig cfg = Config();
cfg.SetCipher("twofish-128-cfb");
Create(std::move(cfg));
CryConfigFile loaded = Load().value();
EXPECT_EQ("twofish-128-cfb", loaded.config()->Cipher());
unique_ref<CryConfigFile> loaded = std::move(Load().value());
EXPECT_EQ("twofish-128-cfb", loaded->config()->Cipher());
}
TEST_F(CryConfigFileTest, Cipher_SaveAndLoad) {
CryConfigFile created = CreateAndLoadEmpty();
created.config()->SetCipher("twofish-128-cfb");
created.save();
CryConfigFile loaded = Load().value();
EXPECT_EQ("twofish-128-cfb", loaded.config()->Cipher());
unique_ref<CryConfigFile> created = CreateAndLoadEmpty();
created->config()->SetCipher("twofish-128-cfb");
created->save();
unique_ref<CryConfigFile> loaded = std::move(Load().value());
EXPECT_EQ("twofish-128-cfb", loaded->config()->Cipher());
}
TEST_F(CryConfigFileTest, Version_Init) {
CryConfigFile created = CreateAndLoadEmpty();
EXPECT_EQ("", created.config()->Version());
unique_ref<CryConfigFile> created = CreateAndLoadEmpty();
EXPECT_EQ("", created->config()->Version());
}
TEST_F(CryConfigFileTest, Version_CreateAndLoad) {
CryConfig cfg = Config();
cfg.SetVersion("0.9.2");
Create(std::move(cfg));
CryConfigFile loaded = Load().value();
EXPECT_EQ("0.9.2", loaded.config()->Version());
unique_ref<CryConfigFile> loaded = std::move(Load().value());
EXPECT_EQ("0.9.2", loaded->config()->Version());
}
TEST_F(CryConfigFileTest, Version_SaveAndLoad) {
CryConfigFile created = CreateAndLoadEmpty();
created.config()->SetVersion("0.9.2");
created.save();
CryConfigFile loaded = Load().value();
EXPECT_EQ("0.9.2", loaded.config()->Version());
unique_ref<CryConfigFile> created = CreateAndLoadEmpty();
created->config()->SetVersion("0.9.2");
created->save();
unique_ref<CryConfigFile> loaded = std::move(Load().value());
EXPECT_EQ("0.9.2", loaded->config()->Version());
}
TEST_F(CryConfigFileTest, CreatedWithVersion_Init) {
CryConfigFile created = CreateAndLoadEmpty();
EXPECT_EQ("", created.config()->Version());
unique_ref<CryConfigFile> created = CreateAndLoadEmpty();
EXPECT_EQ("", created->config()->Version());
}
TEST_F(CryConfigFileTest, CreatedWithVersion_CreateAndLoad) {
CryConfig cfg = Config();
cfg.SetCreatedWithVersion("0.9.2");
Create(std::move(cfg));
CryConfigFile loaded = Load().value();
EXPECT_EQ("0.9.2", loaded.config()->CreatedWithVersion());
unique_ref<CryConfigFile> loaded = std::move(Load().value());
EXPECT_EQ("0.9.2", loaded->config()->CreatedWithVersion());
}
TEST_F(CryConfigFileTest, CreatedWithVersion_SaveAndLoad) {
CryConfigFile created = CreateAndLoadEmpty();
created.config()->SetCreatedWithVersion("0.9.2");
created.save();
CryConfigFile loaded = Load().value();
EXPECT_EQ("0.9.2", loaded.config()->CreatedWithVersion());
unique_ref<CryConfigFile> created = CreateAndLoadEmpty();
created->config()->SetCreatedWithVersion("0.9.2");
created->save();
unique_ref<CryConfigFile> loaded = std::move(Load().value());
EXPECT_EQ("0.9.2", loaded->config()->CreatedWithVersion());
}
//Test that the encrypted config file has the same size, no matter how big the plaintext config data.
@ -186,12 +188,12 @@ TEST_F(CryConfigFileTest, ConfigFileHasFixedSize) {
TEST_F(CryConfigFileTest, CanSaveAndLoadModififedCipher) {
CreateWithCipher("aes-256-gcm");
CryConfigFile created = Load().value();
EXPECT_EQ("aes-256-gcm", created.config()->Cipher());
created.config()->SetCipher("twofish-128-cfb");
created.save();
CryConfigFile loaded = Load().value();
EXPECT_EQ("twofish-128-cfb", loaded.config()->Cipher());
unique_ref<CryConfigFile> created = Load().value();
EXPECT_EQ("aes-256-gcm", created->config()->Cipher());
created->config()->SetCipher("twofish-128-cfb");
created->save();
unique_ref<CryConfigFile> loaded = std::move(Load().value());
EXPECT_EQ("twofish-128-cfb", loaded->config()->Cipher());
}
TEST_F(CryConfigFileTest, FailsIfConfigFileIsEncryptedWithACipherDifferentToTheOneSpecifiedByTheUser) {

View File

@ -3,6 +3,7 @@
#include <cryfs/config/CryPresetPasswordBasedKeyProvider.h>
#include "../testutils/MockConsole.h"
#include "../testutils/TestWithFakeHomeDirectory.h"
#include <cpp-utils/tempfile/TempFile.h>
#include <cpp-utils/random/Random.h>
#include <cpp-utils/crypto/symmetric/ciphers.h>
@ -11,12 +12,14 @@
#include <gitversion/gitversion.h>
#include <gitversion/parser.h>
#include <gitversion/VersionCompare.h>
#include <cpp-utils/pointer/unique_ref_boost_optional_gtest_workaround.h>
using cpputils::TempFile;
using cpputils::SCrypt;
using cpputils::DataFixture;
using cpputils::Data;
using cpputils::NoninteractiveConsole;
using cpputils::unique_ref;
using cpputils::make_unique_ref;
using cpputils::Console;
using cpputils::unique_ref;
@ -75,12 +78,12 @@ public:
return CryConfigLoader(_console, cpputils::Random::PseudoRandom(), keyProvider(password), localStateDir, cipher, none, none);
}
CryConfigFile Create(const string &password = "mypassword", const optional<string> &cipher = none, bool noninteractive = false) {
unique_ref<CryConfigFile> Create(const string &password = "mypassword", const optional<string> &cipher = none, bool noninteractive = false) {
EXPECT_FALSE(file.exists());
return loader(password, noninteractive, cipher).loadOrCreate(file.path(), false, false).value().configFile;
}
optional<CryConfigFile> Load(const string &password = "mypassword", const optional<string> &cipher = none, bool noninteractive = false, bool allowFilesystemUpgrade = false) {
optional<unique_ref<CryConfigFile>> Load(const string &password = "mypassword", const optional<string> &cipher = none, bool noninteractive = false, bool allowFilesystemUpgrade = false) {
EXPECT_TRUE(file.exists());
auto loadResult = loader(password, noninteractive, cipher).loadOrCreate(file.path(), allowFilesystemUpgrade, false);
if (loadResult == none) {
@ -91,14 +94,14 @@ public:
void CreateWithRootBlob(const string &rootBlob, const string &password = "mypassword") {
auto cfg = loader(password, false).loadOrCreate(file.path(), false, false).value().configFile;
cfg.config()->SetRootBlob(rootBlob);
cfg.save();
cfg->config()->SetRootBlob(rootBlob);
cfg->save();
}
void CreateWithCipher(const string &cipher, const string &password = "mypassword") {
auto cfg = loader(password, false).loadOrCreate(file.path(), false, false).value().configFile;
cfg.config()->SetCipher(cipher);
cfg.save();
cfg->config()->SetCipher(cipher);
cfg->save();
}
void CreateWithEncryptionKey(const string &encKey, const string &password = "mypassword") {
@ -108,29 +111,29 @@ public:
}
void ChangeEncryptionKey(const string &encKey, const string& password = "mypassword") {
auto cfg = CryConfigFile::load(file.path(), keyProvider(password).get()).value();
cfg.config()->SetEncryptionKey(encKey);
cfg.save();
auto cfg = CryConfigFile::load(file.path(), keyProvider(password).get()).right_opt().value();
cfg->config()->SetEncryptionKey(encKey);
cfg->save();
}
void CreateWithVersion(const string &version, const string& formatVersion, const string &password = "mypassword") {
auto cfg = loader(password, false).loadOrCreate(file.path(), false, false).value().configFile;
cfg.config()->SetVersion(formatVersion);
cfg.config()->SetLastOpenedWithVersion(version);
cfg.config()->SetCreatedWithVersion(version);
cfg.save();
cfg->config()->SetVersion(formatVersion);
cfg->config()->SetLastOpenedWithVersion(version);
cfg->config()->SetCreatedWithVersion(version);
cfg->save();
}
void CreateWithFilesystemID(const CryConfig::FilesystemID &filesystemId, const string &password = "mypassword") {
auto cfg = loader(password, false).loadOrCreate(file.path(), false, false).value().configFile;
cfg.config()->SetFilesystemId(filesystemId);
cfg.save();
cfg->config()->SetFilesystemId(filesystemId);
cfg->save();
}
void ChangeFilesystemID(const CryConfig::FilesystemID &filesystemId, const string& password = "mypassword") {
auto cfg = CryConfigFile::load(file.path(), keyProvider(password).get()).value();
cfg.config()->SetFilesystemId(filesystemId);
cfg.save();
auto cfg = CryConfigFile::load(file.path(), keyProvider(password).get()).right_opt().value();
cfg->config()->SetFilesystemId(filesystemId);
cfg->save();
}
string olderVersion() {
@ -208,18 +211,18 @@ TEST_F(CryConfigLoaderTest, DoesLoadIfSameCipher_Noninteractive) {
TEST_F(CryConfigLoaderTest, RootBlob_Load) {
CreateWithRootBlob("rootblobid");
auto loaded = Load().value();
EXPECT_EQ("rootblobid", loaded.config()->RootBlob());
EXPECT_EQ("rootblobid", loaded->config()->RootBlob());
}
TEST_F(CryConfigLoaderTest, RootBlob_Create) {
auto created = Create();
EXPECT_EQ("", created.config()->RootBlob());
EXPECT_EQ("", created->config()->RootBlob());
}
TEST_F(CryConfigLoaderTest, EncryptionKey_Load) {
CreateWithEncryptionKey("3B4682CF22F3CA199E385729B9F3CA19D325229E385729B9443CA19D325229E3");
auto loaded = Load().value();
EXPECT_EQ("3B4682CF22F3CA199E385729B9F3CA19D325229E385729B9443CA19D325229E3", loaded.config()->EncryptionKey());
EXPECT_EQ("3B4682CF22F3CA199E385729B9F3CA19D325229E385729B9443CA19D325229E3", loaded->config()->EncryptionKey());
}
TEST_F(CryConfigLoaderTest, EncryptionKey_Load_whenKeyChanged_thenFails) {
@ -234,55 +237,55 @@ TEST_F(CryConfigLoaderTest, EncryptionKey_Load_whenKeyChanged_thenFails) {
TEST_F(CryConfigLoaderTest, EncryptionKey_Create) {
auto created = Create();
//aes-256-gcm is the default cipher chosen by mockConsole()
cpputils::AES256_GCM::EncryptionKey::FromString(created.config()->EncryptionKey()); // This crashes if key is invalid
cpputils::AES256_GCM::EncryptionKey::FromString(created->config()->EncryptionKey()); // This crashes if key is invalid
}
TEST_F(CryConfigLoaderTest, Cipher_Load) {
CreateWithCipher("twofish-128-cfb");
auto loaded = Load().value();
EXPECT_EQ("twofish-128-cfb", loaded.config()->Cipher());
EXPECT_EQ("twofish-128-cfb", loaded->config()->Cipher());
}
TEST_F(CryConfigLoaderTest, Cipher_Create) {
auto created = Create();
//aes-256-gcm is the default cipher chosen by mockConsole()
EXPECT_EQ("aes-256-gcm", created.config()->Cipher());
EXPECT_EQ("aes-256-gcm", created->config()->Cipher());
}
TEST_F(CryConfigLoaderTest, Version_Load) {
CreateWithVersion("0.9.2", "0.9.2");
auto loaded = Load().value();
EXPECT_EQ(CryConfig::FilesystemFormatVersion, loaded.config()->Version());
EXPECT_EQ(gitversion::VersionString(), loaded.config()->LastOpenedWithVersion());
EXPECT_EQ("0.9.2", loaded.config()->CreatedWithVersion());
auto loaded = std::move(Load().value());
EXPECT_EQ(CryConfig::FilesystemFormatVersion, loaded->config()->Version());
EXPECT_EQ(gitversion::VersionString(), loaded->config()->LastOpenedWithVersion());
EXPECT_EQ("0.9.2", loaded->config()->CreatedWithVersion());
}
TEST_F(CryConfigLoaderTest, Version_Load_IsStoredAndNotOnlyOverwrittenInMemoryOnLoad) {
CreateWithVersion("0.9.2", "0.9.2", "mypassword");
Load().value();
auto configFile = CryConfigFile::load(file.path(), keyProvider("mypassword").get()).value();
EXPECT_EQ(CryConfig::FilesystemFormatVersion, configFile.config()->Version());
EXPECT_EQ(gitversion::VersionString(), configFile.config()->LastOpenedWithVersion());
EXPECT_EQ("0.9.2", configFile.config()->CreatedWithVersion());
auto configFile = CryConfigFile::load(file.path(), keyProvider("mypassword").get()).right_opt().value();
EXPECT_EQ(CryConfig::FilesystemFormatVersion, configFile->config()->Version());
EXPECT_EQ(gitversion::VersionString(), configFile->config()->LastOpenedWithVersion());
EXPECT_EQ("0.9.2", configFile->config()->CreatedWithVersion());
}
TEST_F(CryConfigLoaderTest, Version_Create) {
auto created = Create();
EXPECT_EQ(CryConfig::FilesystemFormatVersion, created.config()->Version());
EXPECT_EQ(gitversion::VersionString(), created.config()->LastOpenedWithVersion());
EXPECT_EQ(gitversion::VersionString(), created.config()->CreatedWithVersion());
EXPECT_EQ(CryConfig::FilesystemFormatVersion, created->config()->Version());
EXPECT_EQ(gitversion::VersionString(), created->config()->LastOpenedWithVersion());
EXPECT_EQ(gitversion::VersionString(), created->config()->CreatedWithVersion());
}
TEST_F(CryConfigLoaderTest, FilesystemID_Load) {
auto fixture = DataFixture::generateFixedSize<CryConfig::FilesystemID::BINARY_LENGTH>();
CreateWithFilesystemID(fixture);
auto loaded = Load().value();
EXPECT_EQ(fixture, loaded.config()->FilesystemId());
EXPECT_EQ(fixture, loaded->config()->FilesystemId());
}
TEST_F(CryConfigLoaderTest, FilesystemID_Create) {
auto created = Create();
EXPECT_NE(CryConfig::FilesystemID::Null(), created.config()->FilesystemId());
EXPECT_NE(CryConfig::FilesystemID::Null(), created->config()->FilesystemId());
}
TEST_F(CryConfigLoaderTest, AsksWhenLoadingNewerFilesystem_AnswerYes) {

View File

@ -18,6 +18,7 @@
using ::testing::Test;
using std::make_shared;
using std::shared_ptr;
using cpputils::TempDir;
using cpputils::TempFile;
using cpputils::make_unique_ref;
@ -40,7 +41,7 @@ public:
CryFsTest(): tempLocalStateDir(), localStateDir(tempLocalStateDir.path()), rootdir(), config(false) {
}
CryConfigFile loadOrCreateConfig() {
shared_ptr<CryConfigFile> loadOrCreateConfig() {
auto keyProvider = make_unique_ref<CryPresetPasswordBasedKeyProvider>("mypassword", make_unique_ref<SCrypt>(SCrypt::TestSettings));
return CryConfigLoader(make_shared<NoninteractiveConsole>(mockConsole()), Random::PseudoRandom(), std::move(keyProvider), localStateDir, none, none, none).loadOrCreate(config.path(), false, false).value().configFile;
}

View File

@ -22,7 +22,7 @@ public:
_device = std::make_unique<cryfs::CryDevice>(configFile(), std::move(fakeBlockStore), _localStateDir, 0x12345678, false, false, failOnIntegrityViolation());
}
cryfs::CryConfigFile configFile() {
std::shared_ptr<cryfs::CryConfigFile> configFile() {
cryfs::CryConfig config;
config.SetCipher("aes-256-gcm");
config.SetEncryptionKey(cpputils::AES256_GCM::EncryptionKey::CreateKey(cpputils::Random::PseudoRandom(), cpputils::AES256_GCM::KEYSIZE).ToString());