diff --git a/fs_mgr/libdm/dm_target.cpp b/fs_mgr/libdm/dm_target.cpp index f440e6dc7..da1013e44 100644 --- a/fs_mgr/libdm/dm_target.cpp +++ b/fs_mgr/libdm/dm_target.cpp @@ -16,6 +16,9 @@ #include "libdm/dm_target.h" +#include +#include + #include #include #include @@ -193,5 +196,30 @@ bool DmTargetSnapshot::ParseStatusText(const std::string& text, Status* status) return true; } +std::string DmTargetCrypt::GetParameterString() const { + std::vector argv = { + cipher_, + key_, + std::to_string(iv_sector_offset_), + device_, + std::to_string(device_sector_), + }; + + std::vector extra_argv; + if (allow_discards_) extra_argv.emplace_back("allow_discards"); + if (allow_encrypt_override_) extra_argv.emplace_back("allow_encrypt_override"); + if (iv_large_sectors_) extra_argv.emplace_back("iv_large_sectors"); + if (sector_size_) extra_argv.emplace_back("sector_size:" + std::to_string(sector_size_)); + + if (!extra_argv.empty()) argv.emplace_back(std::to_string(extra_argv.size())); + + argv.insert(argv.end(), extra_argv.begin(), extra_argv.end()); + return android::base::Join(argv, " "); +} + +std::string DmTargetDefaultKey::GetParameterString() const { + return cipher_ + " " + key_ + " " + blockdev_ + " " + std::to_string(start_sector_); +} + } // namespace dm } // namespace android diff --git a/fs_mgr/libdm/dm_test.cpp b/fs_mgr/libdm/dm_test.cpp index 72a0e119f..dc47c33b0 100644 --- a/fs_mgr/libdm/dm_test.cpp +++ b/fs_mgr/libdm/dm_test.cpp @@ -438,3 +438,26 @@ TEST(libdm, DmSnapshotOverflow) { ASSERT_EQ(status.error, "Invalid"); } } + +TEST(libdm, CryptArgs) { + DmTargetCrypt target1(0, 512, "sha1", "abcdefgh", 50, "/dev/loop0", 100); + ASSERT_EQ(target1.name(), "crypt"); + ASSERT_TRUE(target1.Valid()); + ASSERT_EQ(target1.GetParameterString(), "sha1 abcdefgh 50 /dev/loop0 100"); + + DmTargetCrypt target2(0, 512, "sha1", "abcdefgh", 50, "/dev/loop0", 100); + target2.SetSectorSize(64); + target2.AllowDiscards(); + target2.SetIvLargeSectors(); + target2.AllowEncryptOverride(); + ASSERT_EQ(target2.GetParameterString(), + "sha1 abcdefgh 50 /dev/loop0 100 4 allow_discards allow_encrypt_override " + "iv_large_sectors sector_size:64"); +} + +TEST(libdm, DefaultKeyArgs) { + DmTargetDefaultKey target(0, 4096, "AES-256-XTS", "abcdef0123456789", "/dev/loop0", 0); + ASSERT_EQ(target.name(), "default-key"); + ASSERT_TRUE(target.Valid()); + ASSERT_EQ(target.GetParameterString(), "AES-256-XTS abcdef0123456789 /dev/loop0 0"); +} diff --git a/fs_mgr/libdm/include/libdm/dm_table.h b/fs_mgr/libdm/include/libdm/dm_table.h index 5c639bee0..ee66653a5 100644 --- a/fs_mgr/libdm/include/libdm/dm_table.h +++ b/fs_mgr/libdm/include/libdm/dm_table.h @@ -43,12 +43,20 @@ class DmTable { // successfully removed. bool RemoveTarget(std::unique_ptr&& target); + // Adds a target, constructing it in-place for convenience. For example, + // + // table.Emplace(0, num_sectors); + template + bool Emplace(Args&&... args) { + return AddTarget(std::make_unique(std::forward(args)...)); + } + // Checks the table to make sure it is valid. i.e. Checks for range overlaps, range gaps // and returns 'true' if the table is ready to be loaded into kernel. Returns 'false' if the // table is malformed. bool valid() const; - // Returns the toatl number of targets. + // Returns the total number of targets. size_t num_targets() const { return targets_.size(); } // Returns the total size represented by the table in terms of number of 512-byte sectors. diff --git a/fs_mgr/libdm/include/libdm/dm_target.h b/fs_mgr/libdm/include/libdm/dm_target.h index fce1175b5..722922d67 100644 --- a/fs_mgr/libdm/include/libdm/dm_target.h +++ b/fs_mgr/libdm/include/libdm/dm_target.h @@ -241,6 +241,60 @@ class DmTargetSnapshotOrigin final : public DmTarget { std::string device_; }; +class DmTargetCrypt final : public DmTarget { + public: + DmTargetCrypt(uint64_t start, uint64_t length, const std::string& cipher, + const std::string& key, uint64_t iv_sector_offset, const std::string& device, + uint64_t device_sector) + : DmTarget(start, length), + cipher_(cipher), + key_(key), + iv_sector_offset_(iv_sector_offset), + device_(device), + device_sector_(device_sector) {} + + void AllowDiscards() { allow_discards_ = true; } + void AllowEncryptOverride() { allow_encrypt_override_ = true; } + void SetIvLargeSectors() { iv_large_sectors_ = true; } + void SetSectorSize(uint32_t sector_size) { sector_size_ = sector_size; } + + std::string name() const override { return "crypt"; } + bool Valid() const override { return true; } + std::string GetParameterString() const override; + + private: + std::string cipher_; + std::string key_; + uint64_t iv_sector_offset_; + std::string device_; + uint64_t device_sector_; + bool allow_discards_ = false; + bool allow_encrypt_override_ = false; + bool iv_large_sectors_ = false; + uint32_t sector_size_ = 0; +}; + +class DmTargetDefaultKey final : public DmTarget { + public: + DmTargetDefaultKey(uint64_t start, uint64_t length, const std::string& cipher, + const std::string& key, const std::string& blockdev, uint64_t start_sector) + : DmTarget(start, length), + cipher_(cipher), + key_(key), + blockdev_(blockdev), + start_sector_(start_sector) {} + + std::string name() const override { return "default-key"; } + bool Valid() const override { return true; } + std::string GetParameterString() const override; + + private: + std::string cipher_; + std::string key_; + std::string blockdev_; + uint64_t start_sector_; +}; + } // namespace dm } // namespace android