Use either<> to indicate errors in config file loading
This commit is contained in:
parent
525c29c65d
commit
99688e51ab
221
src/cpp-utils/either.h
Normal file
221
src/cpp-utils/either.h
Normal 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
|
@ -203,7 +203,7 @@ namespace cryfs {
|
|||||||
if (config == none) {
|
if (config == none) {
|
||||||
throw CryfsException("Could not load config file. Did you enter the correct password?", ErrorCode::WrongPassword);
|
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);
|
return std::move(*config);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -241,7 +241,7 @@ namespace cryfs {
|
|||||||
throw CryfsException("Integrity violation detected. Unmounting.", ErrorCode::IntegrityViolation);
|
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,
|
_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)));
|
options.allowIntegrityViolations(), missingBlockIsIntegrityViolation, std::move(onIntegrityViolation)));
|
||||||
_sanityCheckFilesystem(_device->get());
|
_sanityCheckFilesystem(_device->get());
|
||||||
|
@ -15,6 +15,9 @@ using std::stringstream;
|
|||||||
using std::istream;
|
using std::istream;
|
||||||
using cpputils::Data;
|
using cpputils::Data;
|
||||||
using cpputils::unique_ref;
|
using cpputils::unique_ref;
|
||||||
|
using cpputils::make_unique_ref;
|
||||||
|
using cpputils::SCryptSettings;
|
||||||
|
using cpputils::either;
|
||||||
namespace bf = boost::filesystem;
|
namespace bf = boost::filesystem;
|
||||||
using namespace cpputils::logging;
|
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
|
//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);
|
auto encryptedConfigData = Data::LoadFromFile(path);
|
||||||
if (encryptedConfigData == none) {
|
if (encryptedConfigData == none) {
|
||||||
LOG(ERR, "Config file not found");
|
return LoadError::ConfigFileNotFound;
|
||||||
return none;
|
|
||||||
}
|
}
|
||||||
auto encryptor = CryConfigEncryptorFactory::loadExistingKey(*encryptedConfigData, keyProvider);
|
auto encryptor = CryConfigEncryptorFactory::loadExistingKey(*encryptedConfigData, keyProvider);
|
||||||
if (encryptor == none) {
|
if (encryptor == none) {
|
||||||
return none;
|
return LoadError::DecryptionFailed;
|
||||||
}
|
}
|
||||||
auto decrypted = (*encryptor)->decrypt(*encryptedConfigData);
|
auto decrypted = (*encryptor)->decrypt(*encryptedConfigData);
|
||||||
if (decrypted == none) {
|
if (decrypted == none) {
|
||||||
return none;
|
return LoadError::DecryptionFailed;
|
||||||
}
|
}
|
||||||
CryConfig config = CryConfig::load(decrypted->data);
|
CryConfig config = CryConfig::load(decrypted->data);
|
||||||
if (config.Cipher() != decrypted->cipherName) {
|
if (config.Cipher() != decrypted->cipherName) {
|
||||||
LOG(ERR, "Inner cipher algorithm used to encrypt config file doesn't match config value");
|
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) {
|
if (decrypted->wasInDeprecatedConfigFormat) {
|
||||||
// Migrate it to new format
|
// Migrate it to new format
|
||||||
configFile.save();
|
configFile->save();
|
||||||
}
|
}
|
||||||
//TODO For newer compilers, this works without std::move
|
//TODO For newer compilers, this works without std::move
|
||||||
return std::move(configFile);
|
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)) {
|
if (bf::exists(path)) {
|
||||||
throw std::runtime_error("Config file exists already.");
|
throw std::runtime_error("Config file exists already.");
|
||||||
}
|
}
|
||||||
auto result = CryConfigFile(std::move(path), std::move(config), CryConfigEncryptorFactory::deriveNewKey(keyProvider));
|
auto result = make_unique_ref<CryConfigFile>(std::move(path), std::move(config), CryConfigEncryptorFactory::deriveNewKey(keyProvider));
|
||||||
result.save();
|
result->save();
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -72,7 +74,7 @@ void CryConfigFile::save() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
CryConfig *CryConfigFile::config() {
|
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 {
|
const CryConfig *CryConfigFile::config() const {
|
||||||
|
@ -6,24 +6,28 @@
|
|||||||
#include <boost/filesystem.hpp>
|
#include <boost/filesystem.hpp>
|
||||||
#include "CryConfig.h"
|
#include "CryConfig.h"
|
||||||
#include <cpp-utils/crypto/symmetric/ciphers.h>
|
#include <cpp-utils/crypto/symmetric/ciphers.h>
|
||||||
|
#include <cpp-utils/either.h>
|
||||||
#include "crypto/CryConfigEncryptorFactory.h"
|
#include "crypto/CryConfigEncryptorFactory.h"
|
||||||
|
|
||||||
namespace cryfs {
|
namespace cryfs {
|
||||||
class CryConfigFile final {
|
class CryConfigFile final {
|
||||||
public:
|
public:
|
||||||
|
CryConfigFile(boost::filesystem::path path, CryConfig config, cpputils::unique_ref<CryConfigEncryptor> encryptor);
|
||||||
|
|
||||||
CryConfigFile(CryConfigFile &&rhs) = default;
|
CryConfigFile(CryConfigFile &&rhs) = default;
|
||||||
~CryConfigFile();
|
~CryConfigFile();
|
||||||
|
|
||||||
static CryConfigFile create(boost::filesystem::path path, CryConfig config, CryKeyProvider* keyProvider);
|
static cpputils::unique_ref<CryConfigFile> create(boost::filesystem::path path, CryConfig config, CryKeyProvider* keyProvider);
|
||||||
static boost::optional<CryConfigFile> load(boost::filesystem::path path, 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;
|
void save() const;
|
||||||
|
|
||||||
CryConfig *config();
|
CryConfig *config();
|
||||||
const CryConfig *config() const;
|
const CryConfig *config() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
CryConfigFile(boost::filesystem::path path, CryConfig config, cpputils::unique_ref<CryConfigEncryptor> encryptor);
|
|
||||||
|
|
||||||
boost::filesystem::path _path;
|
boost::filesystem::path _path;
|
||||||
CryConfig _config;
|
CryConfig _config;
|
||||||
cpputils::unique_ref<CryConfigEncryptor> _encryptor;
|
cpputils::unique_ref<CryConfigEncryptor> _encryptor;
|
||||||
|
@ -6,9 +6,9 @@
|
|||||||
#include <boost/algorithm/string/predicate.hpp>
|
#include <boost/algorithm/string/predicate.hpp>
|
||||||
#include <gitversion/gitversion.h>
|
#include <gitversion/gitversion.h>
|
||||||
#include <gitversion/VersionCompare.h>
|
#include <gitversion/VersionCompare.h>
|
||||||
#include "../localstate/LocalStateDir.h"
|
#include "cryfs/localstate/LocalStateDir.h"
|
||||||
#include "../localstate/LocalStateMetadata.h"
|
#include "cryfs/localstate/LocalStateMetadata.h"
|
||||||
#include "../CryfsException.h"
|
#include "cryfs/CryfsException.h"
|
||||||
|
|
||||||
namespace bf = boost::filesystem;
|
namespace bf = boost::filesystem;
|
||||||
using cpputils::Console;
|
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) {
|
optional<CryConfigLoader::ConfigLoadResult> CryConfigLoader::_loadConfig(bf::path filename, bool allowFilesystemUpgrade, bool allowReplacedFilesystem) {
|
||||||
auto config = CryConfigFile::load(std::move(filename), _keyProvider.get());
|
auto config = CryConfigFile::load(std::move(filename), _keyProvider.get());
|
||||||
if (config == none) {
|
if (config.is_left()) {
|
||||||
return none;
|
return none;
|
||||||
}
|
}
|
||||||
#ifndef CRYFS_NO_COMPATIBILITY
|
#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
|
//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") {
|
if (config.right()->config()->Version() == "0.9.7" || config.right()->config()->Version() == "0.9.8") {
|
||||||
config->config()->SetVersion("0.9.6");
|
config.right()->config()->SetVersion("0.9.6");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
_checkVersion(*config->config(), allowFilesystemUpgrade);
|
_checkVersion(*config.right()->config(), allowFilesystemUpgrade);
|
||||||
#ifndef CRYFS_NO_COMPATIBILITY
|
#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.
|
//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")) {
|
if (config.right()->config()->Version() != "0+unknown" && VersionCompare::isOlderThan(config.right()->config()->Version(), "0.9.3-rc1")) {
|
||||||
config->config()->SetBlocksizeBytes(32832);
|
config.right()->config()->SetBlocksizeBytes(32832);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (config->config()->Version() != CryConfig::FilesystemFormatVersion) {
|
if (config.right()->config()->Version() != CryConfig::FilesystemFormatVersion) {
|
||||||
config->config()->SetVersion(CryConfig::FilesystemFormatVersion);
|
config.right()->config()->SetVersion(CryConfig::FilesystemFormatVersion);
|
||||||
config->save();
|
config.right()->save();
|
||||||
}
|
}
|
||||||
if (config->config()->LastOpenedWithVersion() != gitversion::VersionString()) {
|
if (config.right()->config()->LastOpenedWithVersion() != gitversion::VersionString()) {
|
||||||
config->config()->SetLastOpenedWithVersion(gitversion::VersionString());
|
config.right()->config()->SetLastOpenedWithVersion(gitversion::VersionString());
|
||||||
config->save();
|
config.right()->save();
|
||||||
}
|
}
|
||||||
_checkCipher(*config->config());
|
_checkCipher(*config.right()->config());
|
||||||
auto localState = LocalStateMetadata::loadOrGenerate(_localStateDir.forFilesystemId(config->config()->FilesystemId()), cpputils::Data::FromString(config->config()->EncryptionKey()), allowReplacedFilesystem);
|
auto localState = LocalStateMetadata::loadOrGenerate(_localStateDir.forFilesystemId(config.right()->config()->FilesystemId()), cpputils::Data::FromString(config.right()->config()->EncryptionKey()), allowReplacedFilesystem);
|
||||||
uint32_t myClientId = localState.myClientId();
|
uint32_t myClientId = localState.myClientId();
|
||||||
_checkMissingBlocksAreIntegrityViolations(&*config, myClientId);
|
_checkMissingBlocksAreIntegrityViolations(config.right().get(), myClientId);
|
||||||
return ConfigLoadResult {std::move(*config), myClientId};
|
return ConfigLoadResult {std::move(config.right()), myClientId};
|
||||||
}
|
}
|
||||||
|
|
||||||
void CryConfigLoader::_checkVersion(const CryConfig &config, bool allowFilesystemUpgrade) {
|
void CryConfigLoader::_checkVersion(const CryConfig &config, bool allowFilesystemUpgrade) {
|
||||||
|
@ -18,7 +18,7 @@ public:
|
|||||||
CryConfigLoader(CryConfigLoader &&rhs) = default;
|
CryConfigLoader(CryConfigLoader &&rhs) = default;
|
||||||
|
|
||||||
struct ConfigLoadResult {
|
struct ConfigLoadResult {
|
||||||
CryConfigFile configFile;
|
cpputils::unique_ref<CryConfigFile> configFile;
|
||||||
uint32_t myClientId;
|
uint32_t myClientId;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#include <blockstore/implementations/caching/CachingBlockStore2.h>
|
#include <blockstore/implementations/caching/CachingBlockStore2.h>
|
||||||
#include <cpp-utils/crypto/symmetric/ciphers.h>
|
#include <cpp-utils/crypto/symmetric/ciphers.h>
|
||||||
#include "parallelaccessfsblobstore/DirBlobRef.h"
|
#include "cryfs/filesystem/parallelaccessfsblobstore/DirBlobRef.h"
|
||||||
#include "CryDevice.h"
|
#include "CryDevice.h"
|
||||||
|
|
||||||
#include "CryDir.h"
|
#include "CryDir.h"
|
||||||
@ -13,9 +13,9 @@
|
|||||||
#include <blockstore/implementations/low2highlevel/LowToHighLevelBlockStore.h>
|
#include <blockstore/implementations/low2highlevel/LowToHighLevelBlockStore.h>
|
||||||
#include <blockstore/implementations/encrypted/EncryptedBlockStore2.h>
|
#include <blockstore/implementations/encrypted/EncryptedBlockStore2.h>
|
||||||
#include <blockstore/implementations/integrity/IntegrityBlockStore2.h>
|
#include <blockstore/implementations/integrity/IntegrityBlockStore2.h>
|
||||||
#include "parallelaccessfsblobstore/ParallelAccessFsBlobStore.h"
|
#include "cryfs/filesystem/parallelaccessfsblobstore/ParallelAccessFsBlobStore.h"
|
||||||
#include "cachingfsblobstore/CachingFsBlobStore.h"
|
#include "cryfs/filesystem/cachingfsblobstore/CachingFsBlobStore.h"
|
||||||
#include "../config/CryCipher.h"
|
#include "cryfs/config/CryCipher.h"
|
||||||
#include <cpp-utils/system/homedir.h>
|
#include <cpp-utils/system/homedir.h>
|
||||||
#include <gitversion/VersionCompare.h>
|
#include <gitversion/VersionCompare.h>
|
||||||
#include <blockstore/interface/BlockStore2.h>
|
#include <blockstore/interface/BlockStore2.h>
|
||||||
@ -52,9 +52,9 @@ namespace bf = boost::filesystem;
|
|||||||
|
|
||||||
namespace cryfs {
|
namespace cryfs {
|
||||||
|
|
||||||
CryDevice::CryDevice(CryConfigFile configFile, unique_ref<BlockStore2> blockStore, const LocalStateDir& localStateDir, uint32_t myClientId, bool allowIntegrityViolations, bool missingBlockIsIntegrityViolation, std::function<void()> onIntegrityViolation)
|
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, localStateDir, myClientId, allowIntegrityViolations, missingBlockIsIntegrityViolation, std::move(onIntegrityViolation))),
|
: _fsBlobStore(CreateFsBlobStore(std::move(blockStore), configFile.get(), localStateDir, myClientId, allowIntegrityViolations, missingBlockIsIntegrityViolation, std::move(onIntegrityViolation))),
|
||||||
_rootBlobId(GetOrCreateRootBlobId(&configFile)),
|
_rootBlobId(GetOrCreateRootBlobId(configFile.get())), _configFile(std::move(configFile)),
|
||||||
_onFsAction() {
|
_onFsAction() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -132,6 +132,10 @@ BlockId CryDevice::CreateRootBlobAndReturnId() {
|
|||||||
return rootBlob->blockId();
|
return rootBlob->blockId();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const CryConfig &CryDevice::config() const {
|
||||||
|
return *_configFile->config();
|
||||||
|
}
|
||||||
|
|
||||||
optional<unique_ref<fspp::File>> CryDevice::LoadFile(const bf::path &path) {
|
optional<unique_ref<fspp::File>> CryDevice::LoadFile(const bf::path &path) {
|
||||||
auto loaded = Load(path);
|
auto loaded = Load(path);
|
||||||
if (loaded == none) {
|
if (loaded == none) {
|
||||||
|
@ -4,22 +4,22 @@
|
|||||||
|
|
||||||
#include <blockstore/interface/BlockStore.h>
|
#include <blockstore/interface/BlockStore.h>
|
||||||
#include <blockstore/interface/BlockStore2.h>
|
#include <blockstore/interface/BlockStore2.h>
|
||||||
#include "../config/CryConfigFile.h"
|
#include "cryfs/config/CryConfigFile.h"
|
||||||
|
|
||||||
#include <boost/filesystem.hpp>
|
#include <boost/filesystem.hpp>
|
||||||
#include <fspp/fs_interface/Device.h>
|
#include <fspp/fs_interface/Device.h>
|
||||||
#include <cryfs/localstate/LocalStateDir.h>
|
#include <cryfs/localstate/LocalStateDir.h>
|
||||||
|
|
||||||
#include "parallelaccessfsblobstore/ParallelAccessFsBlobStore.h"
|
#include "cryfs/filesystem/parallelaccessfsblobstore/ParallelAccessFsBlobStore.h"
|
||||||
#include "parallelaccessfsblobstore/DirBlobRef.h"
|
#include "cryfs/filesystem/parallelaccessfsblobstore/DirBlobRef.h"
|
||||||
#include "parallelaccessfsblobstore/FileBlobRef.h"
|
#include "cryfs/filesystem/parallelaccessfsblobstore/FileBlobRef.h"
|
||||||
#include "parallelaccessfsblobstore/SymlinkBlobRef.h"
|
#include "cryfs/filesystem/parallelaccessfsblobstore/SymlinkBlobRef.h"
|
||||||
|
|
||||||
namespace cryfs {
|
namespace cryfs {
|
||||||
|
|
||||||
class CryDevice final: public fspp::Device {
|
class CryDevice final: public fspp::Device {
|
||||||
public:
|
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;
|
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::Dir>> LoadDir(const boost::filesystem::path &path) override;
|
||||||
boost::optional<cpputils::unique_ref<fspp::Symlink>> LoadSymlink(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;
|
void callFsActionCallbacks() const;
|
||||||
|
|
||||||
uint64_t numBlocks() const;
|
uint64_t numBlocks() const;
|
||||||
@ -50,6 +51,7 @@ private:
|
|||||||
cpputils::unique_ref<parallelaccessfsblobstore::ParallelAccessFsBlobStore> _fsBlobStore;
|
cpputils::unique_ref<parallelaccessfsblobstore::ParallelAccessFsBlobStore> _fsBlobStore;
|
||||||
|
|
||||||
blockstore::BlockId _rootBlobId;
|
blockstore::BlockId _rootBlobId;
|
||||||
|
std::shared_ptr<CryConfigFile> _configFile;
|
||||||
std::vector<std::function<void()>> _onFsAction;
|
std::vector<std::function<void()>> _onFsAction;
|
||||||
|
|
||||||
blockstore::BlockId GetOrCreateRootBlobId(CryConfigFile *config);
|
blockstore::BlockId GetOrCreateRootBlobId(CryConfigFile *config);
|
||||||
|
@ -33,7 +33,9 @@ boost::optional<unique_ref<FsBlob>> FsBlobStore::load(const blockstore::BlockId
|
|||||||
#ifndef CRYFS_NO_COMPATIBILITY
|
#ifndef CRYFS_NO_COMPATIBILITY
|
||||||
unique_ref<FsBlobStore> FsBlobStore::migrateIfNeeded(unique_ref<BlobStore> blobStore, const blockstore::BlockId &rootBlobId) {
|
unique_ref<FsBlobStore> FsBlobStore::migrateIfNeeded(unique_ref<BlobStore> blobStore, const blockstore::BlockId &rootBlobId) {
|
||||||
auto rootBlob = blobStore->load(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);
|
uint16_t format = FsBlobView::getFormatVersionHeader(**rootBlob);
|
||||||
|
|
||||||
auto fsBlobStore = make_unique_ref<FsBlobStore>(std::move(blobStore));
|
auto fsBlobStore = make_unique_ref<FsBlobStore>(std::move(blobStore));
|
||||||
|
@ -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) {
|
unique_ref<BlockStore> makeBlockStore(const path& basedir, const CryConfigLoader::ConfigLoadResult& config, LocalStateDir& localStateDir) {
|
||||||
auto onDiskBlockStore = make_unique_ref<OnDiskBlockStore2>(basedir);
|
auto onDiskBlockStore = make_unique_ref<OnDiskBlockStore2>(basedir);
|
||||||
auto encryptedBlockStore = CryCiphers::find(config.configFile.config()->Cipher()).createEncryptedBlockstore(std::move(onDiskBlockStore), config.configFile.config()->EncryptionKey());
|
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 statePath = localStateDir.forFilesystemId(config.configFile->config()->FilesystemId());
|
||||||
auto integrityFilePath = statePath / "integritydata";
|
auto integrityFilePath = statePath / "integritydata";
|
||||||
auto onIntegrityViolation = [] () {
|
auto onIntegrityViolation = [] () {
|
||||||
std::cerr << "Warning: Integrity violation encountered" << std::endl;
|
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) {
|
std::vector<BlockId> _getKnownBlobIds(const path& basedir, const CryConfigLoader::ConfigLoadResult& config, LocalStateDir& localStateDir) {
|
||||||
auto blockStore = makeBlockStore(basedir, config, 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;
|
std::vector<BlockId> result;
|
||||||
cout << "Listing all file system entities (i.e. blobs)..." << flush;
|
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) {
|
_forEachBlob(fsBlobStore.get(), rootId, [&result] (const BlockId& blockId) {
|
||||||
result.push_back(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 knownBlobIds = _getKnownBlobIds(basedir, config, localStateDir);
|
||||||
|
|
||||||
auto blockStore = makeBlockStore(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;
|
std::vector<BlockId> result;
|
||||||
const uint32_t numNodes = nodeStore->numNodes();
|
const uint32_t numNodes = nodeStore->numNodes();
|
||||||
result.reserve(numNodes);
|
result.reserve(numNodes);
|
||||||
@ -177,7 +177,7 @@ int main(int argc, char* argv[]) {
|
|||||||
console->print("Calculate statistics\n");
|
console->print("Calculate statistics\n");
|
||||||
|
|
||||||
auto blockStore = makeBlockStore(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());
|
||||||
|
|
||||||
uint32_t numUnaccountedBlocks = unaccountedBlocks.size();
|
uint32_t numUnaccountedBlocks = unaccountedBlocks.size();
|
||||||
uint32_t numLeaves = 0;
|
uint32_t numLeaves = 0;
|
||||||
|
@ -69,16 +69,16 @@ class CliTest_IntegrityCheck : public CliTest {
|
|||||||
public:
|
public:
|
||||||
void modifyFilesystemId() {
|
void modifyFilesystemId() {
|
||||||
FakeCryKeyProvider keyProvider;
|
FakeCryKeyProvider keyProvider;
|
||||||
auto configFile = CryConfigFile::load(basedir / "cryfs.config", &keyProvider).value();
|
auto configFile = CryConfigFile::load(basedir / "cryfs.config", &keyProvider).right_opt().value();
|
||||||
configFile.config()->SetFilesystemId(CryConfig::FilesystemID::FromString("0123456789ABCDEF0123456789ABCDEF"));
|
configFile->config()->SetFilesystemId(CryConfig::FilesystemID::FromString("0123456789ABCDEF0123456789ABCDEF"));
|
||||||
configFile.save();
|
configFile->save();
|
||||||
}
|
}
|
||||||
|
|
||||||
void modifyFilesystemKey() {
|
void modifyFilesystemKey() {
|
||||||
FakeCryKeyProvider keyProvider;
|
FakeCryKeyProvider keyProvider;
|
||||||
auto configFile = CryConfigFile::load(basedir / "cryfs.config", &keyProvider).value();
|
auto configFile = CryConfigFile::load(basedir / "cryfs.config", &keyProvider).right_opt().value();
|
||||||
configFile.config()->SetEncryptionKey("0123456789ABCDEF0123456789ABCDEF");
|
configFile->config()->SetEncryptionKey("0123456789ABCDEF0123456789ABCDEF");
|
||||||
configFile.save();
|
configFile->save();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -14,8 +14,10 @@ using cpputils::Data;
|
|||||||
using cpputils::AES256_GCM;
|
using cpputils::AES256_GCM;
|
||||||
using cpputils::Serpent128_CFB;
|
using cpputils::Serpent128_CFB;
|
||||||
using cpputils::TempFile;
|
using cpputils::TempFile;
|
||||||
|
using cpputils::unique_ref;
|
||||||
using cpputils::make_unique_ref;
|
using cpputils::make_unique_ref;
|
||||||
using cpputils::SCrypt;
|
using cpputils::SCrypt;
|
||||||
|
|
||||||
using namespace cryfs;
|
using namespace cryfs;
|
||||||
|
|
||||||
// Test that config files created with (old) versions of cryfs are still loadable.
|
// Test that config files created with (old) versions of cryfs are still loadable.
|
||||||
@ -25,10 +27,10 @@ class CryConfigCompatibilityTest: public ::testing::Test {
|
|||||||
public:
|
public:
|
||||||
TempFile file;
|
TempFile file;
|
||||||
|
|
||||||
CryConfigFile loadConfigFromHex(const string &configFileContentHex) {
|
unique_ref<CryConfigFile> loadConfigFromHex(const string &configFileContentHex) {
|
||||||
storeHexToFile(configFileContentHex);
|
storeHexToFile(configFileContentHex);
|
||||||
CryPresetPasswordBasedKeyProvider keyProvider("mypassword", make_unique_ref<SCrypt>(SCrypt::DefaultSettings));
|
CryPresetPasswordBasedKeyProvider keyProvider("mypassword", make_unique_ref<SCrypt>(SCrypt::DefaultSettings));
|
||||||
return CryConfigFile::load(file.path(), &keyProvider).value();
|
return CryConfigFile::load(file.path(), &keyProvider).right();
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -57,14 +59,14 @@ private:
|
|||||||
|
|
||||||
TEST_F(CryConfigCompatibilityTest, v0_8_1_with_aes_256_gcm) {
|
TEST_F(CryConfigCompatibilityTest, v0_8_1_with_aes_256_gcm) {
|
||||||
auto config = loadConfigFromHex("63727966732e636f6e6669673b303b736372797074000004000000000000010000000100000020000000000000000af023e55f804ad303c1dbdf6a2b2bed8cc1ab3d0b2f3312c073628dc041e6f3b92f54fad63a1d4e0ad47a33e65e08080dd4e5bdec0a95fe777705ad68e88eabcb4b91d4f25c32e3e44d6e893421c9efa6d4b2c56d66d0546a410de489b04160b276184ebe7dd77840ce6e414f829bb4399451e055d3406261b4faf5fb52f27e21823f8073df255f96b37edf2c2e58ecee21ae82e3883341024aff326cc4c0929f0ed90473511cbe801d1e34899b3cdb9556477be0127c35375967bf7c8392ad4d30d81479c7923900f532b195b71cff868fa1643d1f9e0a0d7996260691d7b5b8ef3c319c2f2303f822eac389e1d6822e7ee57df60c922fa10fbc7e5970e723df2fdb2a6529c94ea1d2507f55cb9bc3fecab77bf3102e96c6675a618b54bb18e632dd99d3d47fa9e24392535abc8c76f891df76c2193233d6c93851966f69def3f53108be83b30980c98e377186da71297a1b61df76e9f138a3998577a0c486452f1b6a2d89b1e62d78695ac6a062d5a4cf5972de7bc2775fd27d25337f0666250f19d6fe50fe762371befa26de6a9299d7df362780f59ccc475e28c71cc5af9e817e4e2160005393ec7fb385d467e0915e7169934ea986141101c9e6b9c62b8819c51a4422e7fe58e24c3293c3f12173a4c480334cb67c9313df667c65802fb778e20f5a4d6cfd07fffb35c2ae8fdf235882bf0e6371125509872e73bd1bc3faca72948db76d8179e08bf3391bafdede591d5623240ba072ada17c2444116bf8c08ee32367eb86eda02ecfecc625b4bc974428b8f5024df430c352b9849f48774bac1455e7364f7660abc039d2a1134cde596a1e7c3a1a8d68591e8640a2d308e2ea5f03874ba1fa8e9ffec2d1bc1541d124adcd3e9f4ed23343e2148629317e6304c63c2a5ceeeb572246393c8e50196728e0b604aa9e2d49e65680cc53ee343645412239f82500ef3d70a6b6e3335ef8cbcfe4fd46b84f634f6fe96cd1b79207a2120ac2bad668bcdbc377b98448c9afbbda9fe8164dbb48aaa68b0aaa90e52bc419ea2ea1f5e12bb649831af12f1ef14765f312640e22c5508531bd46e3ab3a7f922a91fb83332104609e385d61d3778bc5acb03bee522ea5b791d27026fd589ec2b32f04caaf2ef2effbd50e12430ef42631fdabd061966fde1489b9a1eff3fe40b295d75e36af19ae0e69559b9c81b3bc47b35fef5c7038b83db6729aac522efee897a44895804ffbeb11317a78586f8a3511905514eee86d7cf0a395f5f0af521c72542e544ff359a69150a5e64f00b020d48c20d5716331c3b0ac314eeceaadf8b73516b4273b48046b5c3a3980bade0cc25baf54afb27755d155d4b94fa556deb30d58b1d920cbe01b13479135ff84d6a9345a0d418075ecc66bd10d8d2a07963450256897018f54b2a88fffe9383913565823dbfb71568f5d9af93e542937ecde25c2d4407ad964ece5c09a1f81a57c18a8bb2aa8d9d062415903c98752d70ad7175d0d30b391da77459e9a68a69825b3bb4061bc2504789fc395");
|
auto config = loadConfigFromHex("63727966732e636f6e6669673b303b736372797074000004000000000000010000000100000020000000000000000af023e55f804ad303c1dbdf6a2b2bed8cc1ab3d0b2f3312c073628dc041e6f3b92f54fad63a1d4e0ad47a33e65e08080dd4e5bdec0a95fe777705ad68e88eabcb4b91d4f25c32e3e44d6e893421c9efa6d4b2c56d66d0546a410de489b04160b276184ebe7dd77840ce6e414f829bb4399451e055d3406261b4faf5fb52f27e21823f8073df255f96b37edf2c2e58ecee21ae82e3883341024aff326cc4c0929f0ed90473511cbe801d1e34899b3cdb9556477be0127c35375967bf7c8392ad4d30d81479c7923900f532b195b71cff868fa1643d1f9e0a0d7996260691d7b5b8ef3c319c2f2303f822eac389e1d6822e7ee57df60c922fa10fbc7e5970e723df2fdb2a6529c94ea1d2507f55cb9bc3fecab77bf3102e96c6675a618b54bb18e632dd99d3d47fa9e24392535abc8c76f891df76c2193233d6c93851966f69def3f53108be83b30980c98e377186da71297a1b61df76e9f138a3998577a0c486452f1b6a2d89b1e62d78695ac6a062d5a4cf5972de7bc2775fd27d25337f0666250f19d6fe50fe762371befa26de6a9299d7df362780f59ccc475e28c71cc5af9e817e4e2160005393ec7fb385d467e0915e7169934ea986141101c9e6b9c62b8819c51a4422e7fe58e24c3293c3f12173a4c480334cb67c9313df667c65802fb778e20f5a4d6cfd07fffb35c2ae8fdf235882bf0e6371125509872e73bd1bc3faca72948db76d8179e08bf3391bafdede591d5623240ba072ada17c2444116bf8c08ee32367eb86eda02ecfecc625b4bc974428b8f5024df430c352b9849f48774bac1455e7364f7660abc039d2a1134cde596a1e7c3a1a8d68591e8640a2d308e2ea5f03874ba1fa8e9ffec2d1bc1541d124adcd3e9f4ed23343e2148629317e6304c63c2a5ceeeb572246393c8e50196728e0b604aa9e2d49e65680cc53ee343645412239f82500ef3d70a6b6e3335ef8cbcfe4fd46b84f634f6fe96cd1b79207a2120ac2bad668bcdbc377b98448c9afbbda9fe8164dbb48aaa68b0aaa90e52bc419ea2ea1f5e12bb649831af12f1ef14765f312640e22c5508531bd46e3ab3a7f922a91fb83332104609e385d61d3778bc5acb03bee522ea5b791d27026fd589ec2b32f04caaf2ef2effbd50e12430ef42631fdabd061966fde1489b9a1eff3fe40b295d75e36af19ae0e69559b9c81b3bc47b35fef5c7038b83db6729aac522efee897a44895804ffbeb11317a78586f8a3511905514eee86d7cf0a395f5f0af521c72542e544ff359a69150a5e64f00b020d48c20d5716331c3b0ac314eeceaadf8b73516b4273b48046b5c3a3980bade0cc25baf54afb27755d155d4b94fa556deb30d58b1d920cbe01b13479135ff84d6a9345a0d418075ecc66bd10d8d2a07963450256897018f54b2a88fffe9383913565823dbfb71568f5d9af93e542937ecde25c2d4407ad964ece5c09a1f81a57c18a8bb2aa8d9d062415903c98752d70ad7175d0d30b391da77459e9a68a69825b3bb4061bc2504789fc395");
|
||||||
EXPECT_EQ(AES256_GCM::NAME, config.config()->Cipher());
|
EXPECT_EQ(AES256_GCM::NAME, config->config()->Cipher());
|
||||||
EXPECT_EQ("4A70AD8AC565A5123586D0928B496465", config.config()->RootBlob());
|
EXPECT_EQ("4A70AD8AC565A5123586D0928B496465", config->config()->RootBlob());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(CryConfigCompatibilityTest, v0_8_1_with_serpent_128_cfb) {
|
TEST_F(CryConfigCompatibilityTest, v0_8_1_with_serpent_128_cfb) {
|
||||||
auto config = loadConfigFromHex("63727966732e636f6e6669673b303b736372797074000004000000000000010000000100000020000000000000006496611b94011d03433181e83e80c19888a5607392c2117cd377251978fbbf8d46716bd90dbae3c1728b40e7dc086ee97b8a641f1ea6cc31ccda9a1e4a7a1bf4b6ca3d1d0075acba94017c034e87dfad048c9448df24ea7b89b14d60c9f9e0162cfeb420a85759aaa011232cff99e81b25c456cb13690d5cc735e61ef9b01800961a90488073c5320c14a562f0eccd32383d144476d72d9c61733fb3561f5187c2d6069ce7ff4c43df4fc3f7c1d63df239d05a2b377f70816fb31f7a65d8fa667cd14b62a67e2d67adbf841860af2abed9d4c839c510c7fac7cd58210238830a4926917d663500dd3dc2395845297b3726c00228cb08a2bde648d2e9bc2a3e8655f86bc2f5c2b327e71c75b92894dd43b56dfefeeea598fbae9782dca64cc9676df3a954a9ecedbe3f8fe16e790aeec2ac2336984c8fcce74bfebf310d6fdcc0882ee7f2bdd32928aa53b09084e8035ec235ebe971a0b141e5fcab6ce2207f0f399e683ff4994ed638194cc7d3891019a2a674d14180114494e21270e4234a51e28661d4ac908d4f2b2d7c94ffcb74df8c9f08fb68d9a7167a05fae370e041689cce5fb13fdf3ff14863f6c882e6d302eafe5348362c026853a3717756cefb4657a721efab95f6d949b508a98de86885fe37b2f16f1792411ff47c1074e2c2d301e6401f251854b28c329040c8e55184402648bc79710536390b0f99acd2400734a81e8bd573d9a96971a5ef195d85babbe1092e271a69a146d2d4114b855c89b710908d4a584e598b6dd186709d956fbd8b13b2ba3e9115c7d75416b7ac0e6d9dde83d367af00fa8dae54f03079cdf5fa1bac35ff3fbf6440f4fa41d06278fd8a6c3edc80d4ceee900975db2a345d8eda0ce0260d389a8336134a20945c1dde16e475ae537a4407da7f389dce79b439d0d81fa915a7dc4cb018e0d1bd806101ff53970731876850255dd5b7d78bf817112bc74ebae39ecae0aa1555e2a9e61660f4ba373086492e0561efb3bfa98399f899d6909415f19963cef3dc6d154056403ed1f475cbc78981cc949c23686bd71b420ed7ce654578d322f1eeec7413c77c017479f2e19b0c5ebb25ad76e1af8ec3a6b6ba3e092af8ddd624dfd1fccb4a61cc77f5c001fafdd7d2cc6c7b418c6dac97e840bc027ef9d4b237eebc2d1255bc0f796c3de78e31a9ae346734801e0f51dc47f8279164ab35bad3b06a5f74356deec0296c350aae4da560b8d77782195621dca054703433037f28cac2603cdefe52903f25013ad4cf4f29e0e413f89f950d26b4ef129aabf78abf9acae252bc60db373cfe3963fc87e9532056f2f2a7f9f1ddd1a3cf9d0078a5c9cccdcc60714de967556032283075424446ccda9f62a5e31f2b5efbc2256c742e4a300d5bc797e90b3a65fdffe3c5f22f5a885903331dbbb031e51411facb4e80e1728c5b14c9fce196d7d5f1dfeca2fe9b877f45fc1f1c8ec09dd5335eb89accf38fe0e6dbbe77a59c96a49830ce5279f17f4897c64e2aeaec127d8d06adcefa7ac800c1e8");
|
auto config = loadConfigFromHex("63727966732e636f6e6669673b303b736372797074000004000000000000010000000100000020000000000000006496611b94011d03433181e83e80c19888a5607392c2117cd377251978fbbf8d46716bd90dbae3c1728b40e7dc086ee97b8a641f1ea6cc31ccda9a1e4a7a1bf4b6ca3d1d0075acba94017c034e87dfad048c9448df24ea7b89b14d60c9f9e0162cfeb420a85759aaa011232cff99e81b25c456cb13690d5cc735e61ef9b01800961a90488073c5320c14a562f0eccd32383d144476d72d9c61733fb3561f5187c2d6069ce7ff4c43df4fc3f7c1d63df239d05a2b377f70816fb31f7a65d8fa667cd14b62a67e2d67adbf841860af2abed9d4c839c510c7fac7cd58210238830a4926917d663500dd3dc2395845297b3726c00228cb08a2bde648d2e9bc2a3e8655f86bc2f5c2b327e71c75b92894dd43b56dfefeeea598fbae9782dca64cc9676df3a954a9ecedbe3f8fe16e790aeec2ac2336984c8fcce74bfebf310d6fdcc0882ee7f2bdd32928aa53b09084e8035ec235ebe971a0b141e5fcab6ce2207f0f399e683ff4994ed638194cc7d3891019a2a674d14180114494e21270e4234a51e28661d4ac908d4f2b2d7c94ffcb74df8c9f08fb68d9a7167a05fae370e041689cce5fb13fdf3ff14863f6c882e6d302eafe5348362c026853a3717756cefb4657a721efab95f6d949b508a98de86885fe37b2f16f1792411ff47c1074e2c2d301e6401f251854b28c329040c8e55184402648bc79710536390b0f99acd2400734a81e8bd573d9a96971a5ef195d85babbe1092e271a69a146d2d4114b855c89b710908d4a584e598b6dd186709d956fbd8b13b2ba3e9115c7d75416b7ac0e6d9dde83d367af00fa8dae54f03079cdf5fa1bac35ff3fbf6440f4fa41d06278fd8a6c3edc80d4ceee900975db2a345d8eda0ce0260d389a8336134a20945c1dde16e475ae537a4407da7f389dce79b439d0d81fa915a7dc4cb018e0d1bd806101ff53970731876850255dd5b7d78bf817112bc74ebae39ecae0aa1555e2a9e61660f4ba373086492e0561efb3bfa98399f899d6909415f19963cef3dc6d154056403ed1f475cbc78981cc949c23686bd71b420ed7ce654578d322f1eeec7413c77c017479f2e19b0c5ebb25ad76e1af8ec3a6b6ba3e092af8ddd624dfd1fccb4a61cc77f5c001fafdd7d2cc6c7b418c6dac97e840bc027ef9d4b237eebc2d1255bc0f796c3de78e31a9ae346734801e0f51dc47f8279164ab35bad3b06a5f74356deec0296c350aae4da560b8d77782195621dca054703433037f28cac2603cdefe52903f25013ad4cf4f29e0e413f89f950d26b4ef129aabf78abf9acae252bc60db373cfe3963fc87e9532056f2f2a7f9f1ddd1a3cf9d0078a5c9cccdcc60714de967556032283075424446ccda9f62a5e31f2b5efbc2256c742e4a300d5bc797e90b3a65fdffe3c5f22f5a885903331dbbb031e51411facb4e80e1728c5b14c9fce196d7d5f1dfeca2fe9b877f45fc1f1c8ec09dd5335eb89accf38fe0e6dbbe77a59c96a49830ce5279f17f4897c64e2aeaec127d8d06adcefa7ac800c1e8");
|
||||||
EXPECT_EQ(Serpent128_CFB::NAME, config.config()->Cipher());
|
EXPECT_EQ(Serpent128_CFB::NAME, config->config()->Cipher());
|
||||||
EXPECT_EQ("5821ED3B0739C7EDB6A09590232EA75B", config.config()->RootBlob());
|
EXPECT_EQ("5821ED3B0739C7EDB6A09590232EA75B", config->config()->RootBlob());
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
#include <gtest/gtest.h>
|
#include <gtest/gtest.h>
|
||||||
#include <cryfs/config/CryConfigFile.h>
|
#include <cryfs/config/CryConfigFile.h>
|
||||||
#include <cpp-utils/tempfile/TempFile.h>
|
#include <cpp-utils/tempfile/TempFile.h>
|
||||||
|
#include <cpp-utils/pointer/unique_ref_boost_optional_gtest_workaround.h>
|
||||||
#include "../testutils/FakeCryKeyProvider.h"
|
#include "../testutils/FakeCryKeyProvider.h"
|
||||||
|
|
||||||
using namespace cryfs;
|
using namespace cryfs;
|
||||||
using cpputils::TempFile;
|
using cpputils::TempFile;
|
||||||
|
using cpputils::unique_ref;
|
||||||
using std::string;
|
using std::string;
|
||||||
using boost::optional;
|
using boost::optional;
|
||||||
using boost::none;
|
using boost::none;
|
||||||
@ -33,7 +35,7 @@ public:
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
CryConfigFile CreateAndLoadEmpty(unsigned char keySeed = 0) {
|
unique_ref<CryConfigFile> CreateAndLoadEmpty(unsigned char keySeed = 0) {
|
||||||
Create(Config(), keySeed);
|
Create(Config(), keySeed);
|
||||||
return Load().value();
|
return Load().value();
|
||||||
}
|
}
|
||||||
@ -43,9 +45,9 @@ public:
|
|||||||
CryConfigFile::create(file.path(), std::move(cfg), &keyProvider);
|
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);
|
FakeCryKeyProvider keyProvider(keySeed);
|
||||||
return CryConfigFile::load(file.path(), &keyProvider);
|
return CryConfigFile::load(file.path(), &keyProvider).right_opt();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CreateWithCipher(const string &cipher) {
|
void CreateWithCipher(const string &cipher) {
|
||||||
@ -69,108 +71,108 @@ TEST_F(CryConfigFileTest, DoesntLoadIfWrongPassword) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(CryConfigFileTest, RootBlob_Init) {
|
TEST_F(CryConfigFileTest, RootBlob_Init) {
|
||||||
CryConfigFile created = CreateAndLoadEmpty();
|
unique_ref<CryConfigFile> created = CreateAndLoadEmpty();
|
||||||
EXPECT_EQ("", created.config()->RootBlob());
|
EXPECT_EQ("", created->config()->RootBlob());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(CryConfigFileTest, RootBlob_CreateAndLoad) {
|
TEST_F(CryConfigFileTest, RootBlob_CreateAndLoad) {
|
||||||
CryConfig cfg = Config();
|
CryConfig cfg = Config();
|
||||||
cfg.SetRootBlob("rootblobid");
|
cfg.SetRootBlob("rootblobid");
|
||||||
Create(std::move(cfg));
|
Create(std::move(cfg));
|
||||||
CryConfigFile loaded = Load().value();
|
unique_ref<CryConfigFile> loaded = std::move(Load().value());
|
||||||
EXPECT_EQ("rootblobid", loaded.config()->RootBlob());
|
EXPECT_EQ("rootblobid", loaded->config()->RootBlob());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(CryConfigFileTest, RootBlob_SaveAndLoad) {
|
TEST_F(CryConfigFileTest, RootBlob_SaveAndLoad) {
|
||||||
CryConfigFile created = CreateAndLoadEmpty();
|
unique_ref<CryConfigFile> created = CreateAndLoadEmpty();
|
||||||
created.config()->SetRootBlob("rootblobid");
|
created->config()->SetRootBlob("rootblobid");
|
||||||
created.save();
|
created->save();
|
||||||
CryConfigFile loaded = Load().value();
|
unique_ref<CryConfigFile> loaded = std::move(Load().value());
|
||||||
EXPECT_EQ("rootblobid", loaded.config()->RootBlob());
|
EXPECT_EQ("rootblobid", loaded->config()->RootBlob());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(CryConfigFileTest, EncryptionKey_Init) {
|
TEST_F(CryConfigFileTest, EncryptionKey_Init) {
|
||||||
CryConfigFile created = CreateAndLoadEmpty();
|
unique_ref<CryConfigFile> created = CreateAndLoadEmpty();
|
||||||
EXPECT_EQ("", created.config()->EncryptionKey());
|
EXPECT_EQ("", created->config()->EncryptionKey());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(CryConfigFileTest, EncryptionKey_CreateAndLoad) {
|
TEST_F(CryConfigFileTest, EncryptionKey_CreateAndLoad) {
|
||||||
CryConfig cfg = Config();
|
CryConfig cfg = Config();
|
||||||
cfg.SetEncryptionKey("encryptionkey");
|
cfg.SetEncryptionKey("encryptionkey");
|
||||||
Create(std::move(cfg));
|
Create(std::move(cfg));
|
||||||
CryConfigFile loaded = Load().value();
|
unique_ref<CryConfigFile> loaded = std::move(Load().value());
|
||||||
EXPECT_EQ("encryptionkey", loaded.config()->EncryptionKey());
|
EXPECT_EQ("encryptionkey", loaded->config()->EncryptionKey());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(CryConfigFileTest, EncryptionKey_SaveAndLoad) {
|
TEST_F(CryConfigFileTest, EncryptionKey_SaveAndLoad) {
|
||||||
CryConfigFile created = CreateAndLoadEmpty();
|
unique_ref<CryConfigFile> created = CreateAndLoadEmpty();
|
||||||
created.config()->SetEncryptionKey("encryptionkey");
|
created->config()->SetEncryptionKey("encryptionkey");
|
||||||
created.save();
|
created->save();
|
||||||
CryConfigFile loaded = Load().value();
|
unique_ref<CryConfigFile> loaded = std::move(Load().value());
|
||||||
EXPECT_EQ("encryptionkey", loaded.config()->EncryptionKey());
|
EXPECT_EQ("encryptionkey", loaded->config()->EncryptionKey());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(CryConfigFileTest, Cipher_Init) {
|
TEST_F(CryConfigFileTest, Cipher_Init) {
|
||||||
CryConfigFile created = CreateAndLoadEmpty();
|
unique_ref<CryConfigFile> created = CreateAndLoadEmpty();
|
||||||
EXPECT_EQ("aes-256-gcm", created.config()->Cipher());
|
EXPECT_EQ("aes-256-gcm", created->config()->Cipher());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(CryConfigFileTest, Cipher_CreateAndLoad) {
|
TEST_F(CryConfigFileTest, Cipher_CreateAndLoad) {
|
||||||
CryConfig cfg = Config();
|
CryConfig cfg = Config();
|
||||||
cfg.SetCipher("twofish-128-cfb");
|
cfg.SetCipher("twofish-128-cfb");
|
||||||
Create(std::move(cfg));
|
Create(std::move(cfg));
|
||||||
CryConfigFile loaded = Load().value();
|
unique_ref<CryConfigFile> loaded = std::move(Load().value());
|
||||||
EXPECT_EQ("twofish-128-cfb", loaded.config()->Cipher());
|
EXPECT_EQ("twofish-128-cfb", loaded->config()->Cipher());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(CryConfigFileTest, Cipher_SaveAndLoad) {
|
TEST_F(CryConfigFileTest, Cipher_SaveAndLoad) {
|
||||||
CryConfigFile created = CreateAndLoadEmpty();
|
unique_ref<CryConfigFile> created = CreateAndLoadEmpty();
|
||||||
created.config()->SetCipher("twofish-128-cfb");
|
created->config()->SetCipher("twofish-128-cfb");
|
||||||
created.save();
|
created->save();
|
||||||
CryConfigFile loaded = Load().value();
|
unique_ref<CryConfigFile> loaded = std::move(Load().value());
|
||||||
EXPECT_EQ("twofish-128-cfb", loaded.config()->Cipher());
|
EXPECT_EQ("twofish-128-cfb", loaded->config()->Cipher());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(CryConfigFileTest, Version_Init) {
|
TEST_F(CryConfigFileTest, Version_Init) {
|
||||||
CryConfigFile created = CreateAndLoadEmpty();
|
unique_ref<CryConfigFile> created = CreateAndLoadEmpty();
|
||||||
EXPECT_EQ("", created.config()->Version());
|
EXPECT_EQ("", created->config()->Version());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(CryConfigFileTest, Version_CreateAndLoad) {
|
TEST_F(CryConfigFileTest, Version_CreateAndLoad) {
|
||||||
CryConfig cfg = Config();
|
CryConfig cfg = Config();
|
||||||
cfg.SetVersion("0.9.2");
|
cfg.SetVersion("0.9.2");
|
||||||
Create(std::move(cfg));
|
Create(std::move(cfg));
|
||||||
CryConfigFile loaded = Load().value();
|
unique_ref<CryConfigFile> loaded = std::move(Load().value());
|
||||||
EXPECT_EQ("0.9.2", loaded.config()->Version());
|
EXPECT_EQ("0.9.2", loaded->config()->Version());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(CryConfigFileTest, Version_SaveAndLoad) {
|
TEST_F(CryConfigFileTest, Version_SaveAndLoad) {
|
||||||
CryConfigFile created = CreateAndLoadEmpty();
|
unique_ref<CryConfigFile> created = CreateAndLoadEmpty();
|
||||||
created.config()->SetVersion("0.9.2");
|
created->config()->SetVersion("0.9.2");
|
||||||
created.save();
|
created->save();
|
||||||
CryConfigFile loaded = Load().value();
|
unique_ref<CryConfigFile> loaded = std::move(Load().value());
|
||||||
EXPECT_EQ("0.9.2", loaded.config()->Version());
|
EXPECT_EQ("0.9.2", loaded->config()->Version());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(CryConfigFileTest, CreatedWithVersion_Init) {
|
TEST_F(CryConfigFileTest, CreatedWithVersion_Init) {
|
||||||
CryConfigFile created = CreateAndLoadEmpty();
|
unique_ref<CryConfigFile> created = CreateAndLoadEmpty();
|
||||||
EXPECT_EQ("", created.config()->Version());
|
EXPECT_EQ("", created->config()->Version());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(CryConfigFileTest, CreatedWithVersion_CreateAndLoad) {
|
TEST_F(CryConfigFileTest, CreatedWithVersion_CreateAndLoad) {
|
||||||
CryConfig cfg = Config();
|
CryConfig cfg = Config();
|
||||||
cfg.SetCreatedWithVersion("0.9.2");
|
cfg.SetCreatedWithVersion("0.9.2");
|
||||||
Create(std::move(cfg));
|
Create(std::move(cfg));
|
||||||
CryConfigFile loaded = Load().value();
|
unique_ref<CryConfigFile> loaded = std::move(Load().value());
|
||||||
EXPECT_EQ("0.9.2", loaded.config()->CreatedWithVersion());
|
EXPECT_EQ("0.9.2", loaded->config()->CreatedWithVersion());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(CryConfigFileTest, CreatedWithVersion_SaveAndLoad) {
|
TEST_F(CryConfigFileTest, CreatedWithVersion_SaveAndLoad) {
|
||||||
CryConfigFile created = CreateAndLoadEmpty();
|
unique_ref<CryConfigFile> created = CreateAndLoadEmpty();
|
||||||
created.config()->SetCreatedWithVersion("0.9.2");
|
created->config()->SetCreatedWithVersion("0.9.2");
|
||||||
created.save();
|
created->save();
|
||||||
CryConfigFile loaded = Load().value();
|
unique_ref<CryConfigFile> loaded = std::move(Load().value());
|
||||||
EXPECT_EQ("0.9.2", loaded.config()->CreatedWithVersion());
|
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.
|
//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) {
|
TEST_F(CryConfigFileTest, CanSaveAndLoadModififedCipher) {
|
||||||
CreateWithCipher("aes-256-gcm");
|
CreateWithCipher("aes-256-gcm");
|
||||||
CryConfigFile created = Load().value();
|
unique_ref<CryConfigFile> created = Load().value();
|
||||||
EXPECT_EQ("aes-256-gcm", created.config()->Cipher());
|
EXPECT_EQ("aes-256-gcm", created->config()->Cipher());
|
||||||
created.config()->SetCipher("twofish-128-cfb");
|
created->config()->SetCipher("twofish-128-cfb");
|
||||||
created.save();
|
created->save();
|
||||||
CryConfigFile loaded = Load().value();
|
unique_ref<CryConfigFile> loaded = std::move(Load().value());
|
||||||
EXPECT_EQ("twofish-128-cfb", loaded.config()->Cipher());
|
EXPECT_EQ("twofish-128-cfb", loaded->config()->Cipher());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(CryConfigFileTest, FailsIfConfigFileIsEncryptedWithACipherDifferentToTheOneSpecifiedByTheUser) {
|
TEST_F(CryConfigFileTest, FailsIfConfigFileIsEncryptedWithACipherDifferentToTheOneSpecifiedByTheUser) {
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
#include <cryfs/config/CryPresetPasswordBasedKeyProvider.h>
|
#include <cryfs/config/CryPresetPasswordBasedKeyProvider.h>
|
||||||
#include "../testutils/MockConsole.h"
|
#include "../testutils/MockConsole.h"
|
||||||
#include "../testutils/TestWithFakeHomeDirectory.h"
|
#include "../testutils/TestWithFakeHomeDirectory.h"
|
||||||
|
|
||||||
#include <cpp-utils/tempfile/TempFile.h>
|
#include <cpp-utils/tempfile/TempFile.h>
|
||||||
#include <cpp-utils/random/Random.h>
|
#include <cpp-utils/random/Random.h>
|
||||||
#include <cpp-utils/crypto/symmetric/ciphers.h>
|
#include <cpp-utils/crypto/symmetric/ciphers.h>
|
||||||
@ -11,12 +12,14 @@
|
|||||||
#include <gitversion/gitversion.h>
|
#include <gitversion/gitversion.h>
|
||||||
#include <gitversion/parser.h>
|
#include <gitversion/parser.h>
|
||||||
#include <gitversion/VersionCompare.h>
|
#include <gitversion/VersionCompare.h>
|
||||||
|
#include <cpp-utils/pointer/unique_ref_boost_optional_gtest_workaround.h>
|
||||||
|
|
||||||
using cpputils::TempFile;
|
using cpputils::TempFile;
|
||||||
using cpputils::SCrypt;
|
using cpputils::SCrypt;
|
||||||
using cpputils::DataFixture;
|
using cpputils::DataFixture;
|
||||||
using cpputils::Data;
|
using cpputils::Data;
|
||||||
using cpputils::NoninteractiveConsole;
|
using cpputils::NoninteractiveConsole;
|
||||||
|
using cpputils::unique_ref;
|
||||||
using cpputils::make_unique_ref;
|
using cpputils::make_unique_ref;
|
||||||
using cpputils::Console;
|
using cpputils::Console;
|
||||||
using cpputils::unique_ref;
|
using cpputils::unique_ref;
|
||||||
@ -75,12 +78,12 @@ public:
|
|||||||
return CryConfigLoader(_console, cpputils::Random::PseudoRandom(), keyProvider(password), localStateDir, cipher, none, none);
|
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());
|
EXPECT_FALSE(file.exists());
|
||||||
return loader(password, noninteractive, cipher).loadOrCreate(file.path(), false, false).value().configFile;
|
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());
|
EXPECT_TRUE(file.exists());
|
||||||
auto loadResult = loader(password, noninteractive, cipher).loadOrCreate(file.path(), allowFilesystemUpgrade, false);
|
auto loadResult = loader(password, noninteractive, cipher).loadOrCreate(file.path(), allowFilesystemUpgrade, false);
|
||||||
if (loadResult == none) {
|
if (loadResult == none) {
|
||||||
@ -91,14 +94,14 @@ public:
|
|||||||
|
|
||||||
void CreateWithRootBlob(const string &rootBlob, const string &password = "mypassword") {
|
void CreateWithRootBlob(const string &rootBlob, const string &password = "mypassword") {
|
||||||
auto cfg = loader(password, false).loadOrCreate(file.path(), false, false).value().configFile;
|
auto cfg = loader(password, false).loadOrCreate(file.path(), false, false).value().configFile;
|
||||||
cfg.config()->SetRootBlob(rootBlob);
|
cfg->config()->SetRootBlob(rootBlob);
|
||||||
cfg.save();
|
cfg->save();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CreateWithCipher(const string &cipher, const string &password = "mypassword") {
|
void CreateWithCipher(const string &cipher, const string &password = "mypassword") {
|
||||||
auto cfg = loader(password, false).loadOrCreate(file.path(), false, false).value().configFile;
|
auto cfg = loader(password, false).loadOrCreate(file.path(), false, false).value().configFile;
|
||||||
cfg.config()->SetCipher(cipher);
|
cfg->config()->SetCipher(cipher);
|
||||||
cfg.save();
|
cfg->save();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CreateWithEncryptionKey(const string &encKey, const string &password = "mypassword") {
|
void CreateWithEncryptionKey(const string &encKey, const string &password = "mypassword") {
|
||||||
@ -108,29 +111,29 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ChangeEncryptionKey(const string &encKey, const string& password = "mypassword") {
|
void ChangeEncryptionKey(const string &encKey, const string& password = "mypassword") {
|
||||||
auto cfg = CryConfigFile::load(file.path(), keyProvider(password).get()).value();
|
auto cfg = CryConfigFile::load(file.path(), keyProvider(password).get()).right_opt().value();
|
||||||
cfg.config()->SetEncryptionKey(encKey);
|
cfg->config()->SetEncryptionKey(encKey);
|
||||||
cfg.save();
|
cfg->save();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CreateWithVersion(const string &version, const string& formatVersion, const string &password = "mypassword") {
|
void CreateWithVersion(const string &version, const string& formatVersion, const string &password = "mypassword") {
|
||||||
auto cfg = loader(password, false).loadOrCreate(file.path(), false, false).value().configFile;
|
auto cfg = loader(password, false).loadOrCreate(file.path(), false, false).value().configFile;
|
||||||
cfg.config()->SetVersion(formatVersion);
|
cfg->config()->SetVersion(formatVersion);
|
||||||
cfg.config()->SetLastOpenedWithVersion(version);
|
cfg->config()->SetLastOpenedWithVersion(version);
|
||||||
cfg.config()->SetCreatedWithVersion(version);
|
cfg->config()->SetCreatedWithVersion(version);
|
||||||
cfg.save();
|
cfg->save();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CreateWithFilesystemID(const CryConfig::FilesystemID &filesystemId, const string &password = "mypassword") {
|
void CreateWithFilesystemID(const CryConfig::FilesystemID &filesystemId, const string &password = "mypassword") {
|
||||||
auto cfg = loader(password, false).loadOrCreate(file.path(), false, false).value().configFile;
|
auto cfg = loader(password, false).loadOrCreate(file.path(), false, false).value().configFile;
|
||||||
cfg.config()->SetFilesystemId(filesystemId);
|
cfg->config()->SetFilesystemId(filesystemId);
|
||||||
cfg.save();
|
cfg->save();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChangeFilesystemID(const CryConfig::FilesystemID &filesystemId, const string& password = "mypassword") {
|
void ChangeFilesystemID(const CryConfig::FilesystemID &filesystemId, const string& password = "mypassword") {
|
||||||
auto cfg = CryConfigFile::load(file.path(), keyProvider(password).get()).value();
|
auto cfg = CryConfigFile::load(file.path(), keyProvider(password).get()).right_opt().value();
|
||||||
cfg.config()->SetFilesystemId(filesystemId);
|
cfg->config()->SetFilesystemId(filesystemId);
|
||||||
cfg.save();
|
cfg->save();
|
||||||
}
|
}
|
||||||
|
|
||||||
string olderVersion() {
|
string olderVersion() {
|
||||||
@ -208,18 +211,18 @@ TEST_F(CryConfigLoaderTest, DoesLoadIfSameCipher_Noninteractive) {
|
|||||||
TEST_F(CryConfigLoaderTest, RootBlob_Load) {
|
TEST_F(CryConfigLoaderTest, RootBlob_Load) {
|
||||||
CreateWithRootBlob("rootblobid");
|
CreateWithRootBlob("rootblobid");
|
||||||
auto loaded = Load().value();
|
auto loaded = Load().value();
|
||||||
EXPECT_EQ("rootblobid", loaded.config()->RootBlob());
|
EXPECT_EQ("rootblobid", loaded->config()->RootBlob());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(CryConfigLoaderTest, RootBlob_Create) {
|
TEST_F(CryConfigLoaderTest, RootBlob_Create) {
|
||||||
auto created = Create();
|
auto created = Create();
|
||||||
EXPECT_EQ("", created.config()->RootBlob());
|
EXPECT_EQ("", created->config()->RootBlob());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(CryConfigLoaderTest, EncryptionKey_Load) {
|
TEST_F(CryConfigLoaderTest, EncryptionKey_Load) {
|
||||||
CreateWithEncryptionKey("3B4682CF22F3CA199E385729B9F3CA19D325229E385729B9443CA19D325229E3");
|
CreateWithEncryptionKey("3B4682CF22F3CA199E385729B9F3CA19D325229E385729B9443CA19D325229E3");
|
||||||
auto loaded = Load().value();
|
auto loaded = Load().value();
|
||||||
EXPECT_EQ("3B4682CF22F3CA199E385729B9F3CA19D325229E385729B9443CA19D325229E3", loaded.config()->EncryptionKey());
|
EXPECT_EQ("3B4682CF22F3CA199E385729B9F3CA19D325229E385729B9443CA19D325229E3", loaded->config()->EncryptionKey());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(CryConfigLoaderTest, EncryptionKey_Load_whenKeyChanged_thenFails) {
|
TEST_F(CryConfigLoaderTest, EncryptionKey_Load_whenKeyChanged_thenFails) {
|
||||||
@ -234,55 +237,55 @@ TEST_F(CryConfigLoaderTest, EncryptionKey_Load_whenKeyChanged_thenFails) {
|
|||||||
TEST_F(CryConfigLoaderTest, EncryptionKey_Create) {
|
TEST_F(CryConfigLoaderTest, EncryptionKey_Create) {
|
||||||
auto created = Create();
|
auto created = Create();
|
||||||
//aes-256-gcm is the default cipher chosen by mockConsole()
|
//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) {
|
TEST_F(CryConfigLoaderTest, Cipher_Load) {
|
||||||
CreateWithCipher("twofish-128-cfb");
|
CreateWithCipher("twofish-128-cfb");
|
||||||
auto loaded = Load().value();
|
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) {
|
TEST_F(CryConfigLoaderTest, Cipher_Create) {
|
||||||
auto created = Create();
|
auto created = Create();
|
||||||
//aes-256-gcm is the default cipher chosen by mockConsole()
|
//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) {
|
TEST_F(CryConfigLoaderTest, Version_Load) {
|
||||||
CreateWithVersion("0.9.2", "0.9.2");
|
CreateWithVersion("0.9.2", "0.9.2");
|
||||||
auto loaded = Load().value();
|
auto loaded = std::move(Load().value());
|
||||||
EXPECT_EQ(CryConfig::FilesystemFormatVersion, loaded.config()->Version());
|
EXPECT_EQ(CryConfig::FilesystemFormatVersion, loaded->config()->Version());
|
||||||
EXPECT_EQ(gitversion::VersionString(), loaded.config()->LastOpenedWithVersion());
|
EXPECT_EQ(gitversion::VersionString(), loaded->config()->LastOpenedWithVersion());
|
||||||
EXPECT_EQ("0.9.2", loaded.config()->CreatedWithVersion());
|
EXPECT_EQ("0.9.2", loaded->config()->CreatedWithVersion());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(CryConfigLoaderTest, Version_Load_IsStoredAndNotOnlyOverwrittenInMemoryOnLoad) {
|
TEST_F(CryConfigLoaderTest, Version_Load_IsStoredAndNotOnlyOverwrittenInMemoryOnLoad) {
|
||||||
CreateWithVersion("0.9.2", "0.9.2", "mypassword");
|
CreateWithVersion("0.9.2", "0.9.2", "mypassword");
|
||||||
Load().value();
|
Load().value();
|
||||||
auto configFile = CryConfigFile::load(file.path(), keyProvider("mypassword").get()).value();
|
auto configFile = CryConfigFile::load(file.path(), keyProvider("mypassword").get()).right_opt().value();
|
||||||
EXPECT_EQ(CryConfig::FilesystemFormatVersion, configFile.config()->Version());
|
EXPECT_EQ(CryConfig::FilesystemFormatVersion, configFile->config()->Version());
|
||||||
EXPECT_EQ(gitversion::VersionString(), configFile.config()->LastOpenedWithVersion());
|
EXPECT_EQ(gitversion::VersionString(), configFile->config()->LastOpenedWithVersion());
|
||||||
EXPECT_EQ("0.9.2", configFile.config()->CreatedWithVersion());
|
EXPECT_EQ("0.9.2", configFile->config()->CreatedWithVersion());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(CryConfigLoaderTest, Version_Create) {
|
TEST_F(CryConfigLoaderTest, Version_Create) {
|
||||||
auto created = Create();
|
auto created = Create();
|
||||||
EXPECT_EQ(CryConfig::FilesystemFormatVersion, created.config()->Version());
|
EXPECT_EQ(CryConfig::FilesystemFormatVersion, created->config()->Version());
|
||||||
EXPECT_EQ(gitversion::VersionString(), created.config()->LastOpenedWithVersion());
|
EXPECT_EQ(gitversion::VersionString(), created->config()->LastOpenedWithVersion());
|
||||||
EXPECT_EQ(gitversion::VersionString(), created.config()->CreatedWithVersion());
|
EXPECT_EQ(gitversion::VersionString(), created->config()->CreatedWithVersion());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(CryConfigLoaderTest, FilesystemID_Load) {
|
TEST_F(CryConfigLoaderTest, FilesystemID_Load) {
|
||||||
auto fixture = DataFixture::generateFixedSize<CryConfig::FilesystemID::BINARY_LENGTH>();
|
auto fixture = DataFixture::generateFixedSize<CryConfig::FilesystemID::BINARY_LENGTH>();
|
||||||
CreateWithFilesystemID(fixture);
|
CreateWithFilesystemID(fixture);
|
||||||
auto loaded = Load().value();
|
auto loaded = Load().value();
|
||||||
EXPECT_EQ(fixture, loaded.config()->FilesystemId());
|
EXPECT_EQ(fixture, loaded->config()->FilesystemId());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(CryConfigLoaderTest, FilesystemID_Create) {
|
TEST_F(CryConfigLoaderTest, FilesystemID_Create) {
|
||||||
auto created = 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) {
|
TEST_F(CryConfigLoaderTest, AsksWhenLoadingNewerFilesystem_AnswerYes) {
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
|
|
||||||
using ::testing::Test;
|
using ::testing::Test;
|
||||||
using std::make_shared;
|
using std::make_shared;
|
||||||
|
using std::shared_ptr;
|
||||||
using cpputils::TempDir;
|
using cpputils::TempDir;
|
||||||
using cpputils::TempFile;
|
using cpputils::TempFile;
|
||||||
using cpputils::make_unique_ref;
|
using cpputils::make_unique_ref;
|
||||||
@ -40,7 +41,7 @@ public:
|
|||||||
CryFsTest(): tempLocalStateDir(), localStateDir(tempLocalStateDir.path()), rootdir(), config(false) {
|
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));
|
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;
|
return CryConfigLoader(make_shared<NoninteractiveConsole>(mockConsole()), Random::PseudoRandom(), std::move(keyProvider), localStateDir, none, none, none).loadOrCreate(config.path(), false, false).value().configFile;
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,7 @@ public:
|
|||||||
_device = std::make_unique<cryfs::CryDevice>(configFile(), std::move(fakeBlockStore), _localStateDir, 0x12345678, false, false, failOnIntegrityViolation());
|
_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;
|
cryfs::CryConfig config;
|
||||||
config.SetCipher("aes-256-gcm");
|
config.SetCipher("aes-256-gcm");
|
||||||
config.SetEncryptionKey(cpputils::AES256_GCM::EncryptionKey::CreateKey(cpputils::Random::PseudoRandom(), cpputils::AES256_GCM::KEYSIZE).ToString());
|
config.SetEncryptionKey(cpputils::AES256_GCM::EncryptionKey::CreateKey(cpputils::Random::PseudoRandom(), cpputils::AES256_GCM::KEYSIZE).ToString());
|
||||||
|
Loading…
Reference in New Issue
Block a user