diff --git a/src/cryfs/config/CryConfig.cpp b/src/cryfs/config/CryConfig.cpp index 00c48360..82aa2b14 100644 --- a/src/cryfs/config/CryConfig.cpp +++ b/src/cryfs/config/CryConfig.cpp @@ -5,23 +5,27 @@ #include #include #include +#include namespace bf = boost::filesystem; using boost::property_tree::ptree; +using boost::optional; +using boost::none; using std::string; using std::stringstream; using cpputils::Data; using gitversion::VersionCompare; +using cpputils::Random; namespace cryfs { CryConfig::CryConfig() -: _rootBlob(""), _encKey(""), _cipher(""), _version(""), _createdWithVersion(""), _blocksizeBytes(0) { +: _rootBlob(""), _encKey(""), _cipher(""), _version(""), _createdWithVersion(""), _blocksizeBytes(0), _filesystemId(FilesystemID::Null()) { } CryConfig::CryConfig(CryConfig &&rhs) -: _rootBlob(std::move(rhs._rootBlob)), _encKey(std::move(rhs._encKey)), _cipher(std::move(rhs._cipher)), _version(std::move(rhs._version)), _createdWithVersion(std::move(rhs._createdWithVersion)), _blocksizeBytes(rhs._blocksizeBytes) { +: _rootBlob(std::move(rhs._rootBlob)), _encKey(std::move(rhs._encKey)), _cipher(std::move(rhs._cipher)), _version(std::move(rhs._version)), _createdWithVersion(std::move(rhs._createdWithVersion)), _blocksizeBytes(rhs._blocksizeBytes), _filesystemId(std::move(rhs._filesystemId)) { } CryConfig CryConfig::load(const Data &data) { @@ -35,8 +39,16 @@ CryConfig CryConfig::load(const Data &data) { cfg._encKey = pt.get("cryfs.key", ""); cfg._cipher = pt.get("cryfs.cipher", ""); cfg._version = pt.get("cryfs.version", "0.8"); // CryFS 0.8 didn't specify this field, so if the field doesn't exist, it's 0.8. - cfg._createdWithVersion = pt.get("cryfs.createdWithVersion", cfg._version); // In Crfys <= 0.9.2, we didn't have this field, but also didn't update cryfs.version, so we can use this field instead. + cfg._createdWithVersion = pt.get("cryfs.createdWithVersion", cfg._version); // In CryFS <= 0.9.2, we didn't have this field, but also didn't update cryfs.version, so we can use this field instead. cfg._blocksizeBytes = pt.get("cryfs.blocksizeBytes", 32832); // CryFS <= 0.9.2 used a 32KB block size which was this physical block size. + + string filesystemIdOpt = pt.get("cryfs.filesystemId", ""); + if (filesystemIdOpt == "") { + cfg._filesystemId = Random::PseudoRandom().getFixedSize(); + } else { + cfg._filesystemId = FilesystemID::FromString(filesystemIdOpt); + } + return cfg; } @@ -49,6 +61,7 @@ Data CryConfig::save() const { pt.put("cryfs.version", _version); pt.put("cryfs.createdWithVersion", _createdWithVersion); pt.put("cryfs.blocksizeBytes", _blocksizeBytes); + pt.put("cryfs.filesystemId", _filesystemId.ToString()); stringstream stream; write_json(stream, pt); @@ -103,4 +116,12 @@ void CryConfig::SetBlocksizeBytes(uint64_t value) { _blocksizeBytes = value; } +const CryConfig::FilesystemID &CryConfig::FilesystemId() const { + return _filesystemId; +} + +void CryConfig::SetFilesystemId(const FilesystemID &value) { + _filesystemId = value; +} + } diff --git a/src/cryfs/config/CryConfig.h b/src/cryfs/config/CryConfig.h index 655d686d..0f437d87 100644 --- a/src/cryfs/config/CryConfig.h +++ b/src/cryfs/config/CryConfig.h @@ -6,6 +6,7 @@ #include #include +#include namespace cryfs { @@ -33,6 +34,10 @@ public: uint64_t BlocksizeBytes() const; void SetBlocksizeBytes(uint64_t value); + using FilesystemID = cpputils::FixedSizeData<16>; + const FilesystemID &FilesystemId() const; + void SetFilesystemId(const FilesystemID &value); + static CryConfig load(const cpputils::Data &data); cpputils::Data save() const; @@ -43,6 +48,7 @@ private: std::string _version; std::string _createdWithVersion; uint64_t _blocksizeBytes; + FilesystemID _filesystemId; DISALLOW_COPY_AND_ASSIGN(CryConfig); }; diff --git a/src/cryfs/config/CryConfigCreator.cpp b/src/cryfs/config/CryConfigCreator.cpp index 2d6b9e8e..ab62fffe 100644 --- a/src/cryfs/config/CryConfigCreator.cpp +++ b/src/cryfs/config/CryConfigCreator.cpp @@ -1,10 +1,12 @@ #include "CryConfigCreator.h" #include "CryCipher.h" #include +#include using cpputils::Console; using cpputils::unique_ref; using cpputils::RandomGenerator; +using cpputils::Random; using std::string; using std::shared_ptr; using std::vector; @@ -25,6 +27,7 @@ namespace cryfs { config.SetBlocksizeBytes(_generateBlocksizeBytes(blocksizeBytesFromCommandLine)); config.SetRootBlob(_generateRootBlobKey()); config.SetEncryptionKey(_generateEncKey(config.Cipher())); + config.SetFilesystemId(_generateFilesystemID()); return config; } @@ -57,4 +60,8 @@ namespace cryfs { //An empty root blob entry will tell CryDevice to create a new root blob return ""; } + + CryConfig::FilesystemID CryConfigCreator::_generateFilesystemID() { + return Random::PseudoRandom().getFixedSize(); + } } diff --git a/src/cryfs/config/CryConfigCreator.h b/src/cryfs/config/CryConfigCreator.h index 867b9598..f089851c 100644 --- a/src/cryfs/config/CryConfigCreator.h +++ b/src/cryfs/config/CryConfigCreator.h @@ -20,6 +20,7 @@ namespace cryfs { std::string _generateEncKey(const std::string &cipher); std::string _generateRootBlobKey(); uint32_t _generateBlocksizeBytes(const boost::optional &blocksizeBytesFromCommandLine); + CryConfig::FilesystemID _generateFilesystemID(); std::shared_ptr _console; CryConfigConsole _configConsole; diff --git a/test/cryfs/config/CryConfigLoaderTest.cpp b/test/cryfs/config/CryConfigLoaderTest.cpp index fe10d460..bde8147e 100644 --- a/test/cryfs/config/CryConfigLoaderTest.cpp +++ b/test/cryfs/config/CryConfigLoaderTest.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include @@ -11,6 +12,7 @@ using cpputils::unique_ref; using cpputils::make_unique_ref; using cpputils::TempFile; using cpputils::SCrypt; +using cpputils::DataFixture; using boost::optional; using boost::none; using std::string; @@ -75,6 +77,12 @@ public: cfg.save(); } + void CreateWithFilesystemID(const CryConfig::FilesystemID &filesystemId, const string &password = "mypassword") { + auto cfg = loader(password, false).loadOrCreate(file.path()).value(); + cfg.config()->SetFilesystemId(filesystemId); + cfg.save(); + } + string olderVersion() { string olderVersion; if (std::stol(gitversion::MinorVersion()) > 0) { @@ -199,6 +207,18 @@ TEST_F(CryConfigLoaderTest, Version_Create) { EXPECT_EQ(gitversion::VersionString(), created.config()->CreatedWithVersion()); } +TEST_F(CryConfigLoaderTest, FilesystemID_Load) { + auto fixture = DataFixture::generateFixedSize(); + CreateWithFilesystemID(fixture); + auto loaded = Load().value(); + EXPECT_EQ(fixture, loaded.config()->FilesystemId()); +} + +TEST_F(CryConfigLoaderTest, FilesystemID_Create) { + auto created = Create(); + EXPECT_NE(CryConfig::FilesystemID::Null(), created.config()->FilesystemId()); +} + TEST_F(CryConfigLoaderTest, AsksWhenLoadingNewerFilesystem_AnswerYes) { EXPECT_CALL(*console, askYesNo(HasSubstr("should not be opened with older versions"))).Times(1).WillOnce(Return(true)); diff --git a/test/cryfs/config/CryConfigTest.cpp b/test/cryfs/config/CryConfigTest.cpp index cd1c31bb..800e2a11 100644 --- a/test/cryfs/config/CryConfigTest.cpp +++ b/test/cryfs/config/CryConfigTest.cpp @@ -1,8 +1,10 @@ #include #include +#include using namespace cryfs; using cpputils::Data; +using cpputils::DataFixture; class CryConfigTest: public ::testing::Test { public: @@ -139,3 +141,27 @@ TEST_F(CryConfigTest, BlocksizeBytes_AfterSaveAndLoad) { CryConfig loaded = SaveAndLoad(std::move(cfg)); EXPECT_EQ(10*1024u, loaded.BlocksizeBytes()); } + +TEST_F(CryConfigTest, FilesystemID_Init) { + EXPECT_EQ(CryConfig::FilesystemID::Null(), cfg.FilesystemId()); +} + +TEST_F(CryConfigTest, FilesystemID) { + auto fixture = DataFixture::generateFixedSize(); + cfg.SetFilesystemId(fixture); + EXPECT_EQ(fixture, cfg.FilesystemId()); +} + +TEST_F(CryConfigTest, FilesystemID_AfterMove) { + auto fixture = DataFixture::generateFixedSize(); + cfg.SetFilesystemId(fixture); + CryConfig moved = std::move(cfg); + EXPECT_EQ(fixture, moved.FilesystemId()); +} + +TEST_F(CryConfigTest, FilesystemID_AfterSaveAndLoad) { + auto fixture = DataFixture::generateFixedSize(); + cfg.SetFilesystemId(fixture); + CryConfig loaded = SaveAndLoad(std::move(cfg)); + EXPECT_EQ(fixture, loaded.FilesystemId()); +}