libcryfs/src/cryfs/impl/config/CryConfigCreator.cpp

89 lines
4.0 KiB
C++

#include "CryConfigCreator.h"
#include "CryCipher.h"
#include <gitversion/gitversion.h>
#include <cpp-utils/random/Random.h>
#include <cryfs/impl/localstate/LocalStateDir.h>
#include <cryfs/impl/localstate/LocalStateMetadata.h>
using cpputils::Console;
using cpputils::RandomGenerator;
using cpputils::Random;
using std::string;
using std::shared_ptr;
using boost::optional;
using boost::none;
namespace cryfs {
CryConfigCreator::CryConfigCreator(RandomGenerator &encryptionKeyGenerator, LocalStateDir localStateDir)
:_configConsole(), _encryptionKeyGenerator(encryptionKeyGenerator), _localStateDir(std::move(localStateDir)) {
}
CryConfigCreator::ConfigCreateResult CryConfigCreator::create(const optional<string> &cipherFromCommandLine, const optional<uint32_t> &blocksizeBytesFromCommandLine, const optional<bool> &missingBlockIsIntegrityViolationFromCommandLine, bool allowReplacedFilesystem) {
CryConfig config;
config.SetCipher(_generateCipher(cipherFromCommandLine));
config.SetVersion(CryConfig::FilesystemFormatVersion);
config.SetCreatedWithVersion(gitversion::VersionString());
config.SetLastOpenedWithVersion(gitversion::VersionString());
config.SetBlocksizeBytes(_generateBlocksizeBytes(blocksizeBytesFromCommandLine));
config.SetRootBlob(_generateRootBlobId());
config.SetFilesystemId(_generateFilesystemID());
auto encryptionKey = _generateEncKey(config.Cipher());
auto localState = LocalStateMetadata::loadOrGenerate(_localStateDir.forFilesystemId(config.FilesystemId()), cpputils::Data::FromString(encryptionKey), allowReplacedFilesystem);
uint32_t myClientId = localState.myClientId();
config.SetEncryptionKey(std::move(encryptionKey));
config.SetExclusiveClientId(_generateExclusiveClientId(missingBlockIsIntegrityViolationFromCommandLine, myClientId));
#ifndef CRYFS_NO_COMPATIBILITY
config.SetHasVersionNumbers(true);
#endif
return ConfigCreateResult {std::move(config), myClientId};
}
uint32_t CryConfigCreator::_generateBlocksizeBytes(const optional<uint32_t> &blocksizeBytesFromCommandLine) {
if (blocksizeBytesFromCommandLine != none) {
// TODO Check block size is valid (i.e. large enough)
return *blocksizeBytesFromCommandLine;
} else {
return _configConsole.askBlocksizeBytes();
}
}
string CryConfigCreator::_generateCipher(const optional<string> &cipherFromCommandLine) {
if (cipherFromCommandLine != none) {
ASSERT(std::find(CryCiphers::supportedCipherNames().begin(), CryCiphers::supportedCipherNames().end(), *cipherFromCommandLine) != CryCiphers::supportedCipherNames().end(), "Invalid cipher");
return *cipherFromCommandLine;
} else {
return _configConsole.askCipher();
}
}
optional<uint32_t> CryConfigCreator::_generateExclusiveClientId(const optional<bool> &missingBlockIsIntegrityViolationFromCommandLine, uint32_t myClientId) {
if (!_generateMissingBlockIsIntegrityViolation(missingBlockIsIntegrityViolationFromCommandLine)) {
return none;
}
return myClientId;
}
bool CryConfigCreator::_generateMissingBlockIsIntegrityViolation(const optional<bool> &missingBlockIsIntegrityViolationFromCommandLine) {
if (missingBlockIsIntegrityViolationFromCommandLine != none) {
return *missingBlockIsIntegrityViolationFromCommandLine;
} else {
return _configConsole.askMissingBlockIsIntegrityViolation();
}
}
string CryConfigCreator::_generateEncKey(const std::string &cipher) {
auto key = CryCiphers::find(cipher).createKey(_encryptionKeyGenerator);
return key;
}
string CryConfigCreator::_generateRootBlobId() {
//An empty root blob entry will tell CryDevice to create a new root blob
return "";
}
CryConfig::FilesystemID CryConfigCreator::_generateFilesystemID() {
return Random::PseudoRandom().getFixedSize<CryConfig::FilesystemID::BINARY_LENGTH>();
}
}