#include "CryConfigCreator.h" #include "CryCipher.h" #include #include #include #include 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 &cipherFromCommandLine, const optional &blocksizeBytesFromCommandLine, const optional &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 &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 &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 CryConfigCreator::_generateExclusiveClientId(const optional &missingBlockIsIntegrityViolationFromCommandLine, uint32_t myClientId) { if (!_generateMissingBlockIsIntegrityViolation(missingBlockIsIntegrityViolationFromCommandLine)) { return none; } return myClientId; } bool CryConfigCreator::_generateMissingBlockIsIntegrityViolation(const optional &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(); } }