Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 084d3b91 authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge "libfs_avb: support rollback protection for Live GSI"

parents 4ac1829d 918668a2
Loading
Loading
Loading
Loading
+13 −0
Original line number Diff line number Diff line
@@ -34,6 +34,19 @@ using android::base::unique_fd;
namespace android {
namespace fs_mgr {

std::string GetAvbPropertyDescriptor(const std::string& key,
                                     const std::vector<VBMetaData>& vbmeta_images) {
    size_t value_size;
    for (const auto& vbmeta : vbmeta_images) {
        const char* value = avb_property_lookup(vbmeta.data(), vbmeta.size(), key.data(),
                                                key.size(), &value_size);
        if (value != nullptr) {
            return {value, value_size};
        }
    }
    return "";
}

// Constructs dm-verity arguments for sending DM_TABLE_LOAD ioctl to kernel.
// See the following link for more details:
// https://gitlab.com/cryptsetup/cryptsetup/wikis/DMVerity
+3 −0
Original line number Diff line number Diff line
@@ -37,6 +37,9 @@ struct ChainInfo {
        : partition_name(chain_partition_name), public_key_blob(chain_public_key_blob) {}
};

std::string GetAvbPropertyDescriptor(const std::string& key,
                                     const std::vector<VBMetaData>& vbmeta_images);

// AvbHashtreeDescriptor to dm-verity table setup.
std::unique_ptr<FsAvbHashtreeDescriptor> GetHashtreeDescriptor(
        const std::string& partition_name, const std::vector<VBMetaData>& vbmeta_images);
+80 −43
Original line number Diff line number Diff line
@@ -263,6 +263,69 @@ AvbUniquePtr AvbHandle::LoadAndVerifyVbmeta(
    return avb_handle;
}

AvbUniquePtr AvbHandle::LoadAndVerifyVbmeta(const FstabEntry& fstab_entry) {
    if (fstab_entry.avb_key.empty()) {
        LERROR << "avb_key=/path/to/key is missing for " << fstab_entry.mount_point;
        return nullptr;
    }

    // Binds allow_verification_error and rollback_protection to device unlock state.
    bool allow_verification_error = IsDeviceUnlocked();
    bool rollback_protection = !allow_verification_error;

    std::string expected_key_blob;
    if (!ReadFileToString(fstab_entry.avb_key, &expected_key_blob)) {
        if (!allow_verification_error) {
            LERROR << "Failed to load avb_key: " << fstab_entry.avb_key
                   << " for mount point: " << fstab_entry.mount_point;
            return nullptr;
        }
        LWARNING << "Allowing no expected key blob when verification error is permitted";
        expected_key_blob.clear();
    }

    bool verification_disabled = false;
    VBMetaVerifyResult verify_result = VBMetaVerifyResult::kError;
    std::unique_ptr<VBMetaData> vbmeta = LoadAndVerifyVbmetaByPath(
            fstab_entry.blk_device, "" /* partition_name, no need for a standalone path */,
            expected_key_blob, allow_verification_error, rollback_protection,
            false /* not is_chained_vbmeta */, nullptr /* out_public_key_data */,
            &verification_disabled, &verify_result);

    if (!vbmeta) {
        LERROR << "Failed to load vbmeta: " << fstab_entry.blk_device;
        return nullptr;
    }

    AvbUniquePtr avb_handle(new AvbHandle());
    if (!avb_handle) {
        LERROR << "Failed to allocate AvbHandle";
        return nullptr;
    }
    avb_handle->vbmeta_images_.emplace_back(std::move(*vbmeta));

    switch (verify_result) {
        case VBMetaVerifyResult::kSuccess:
            avb_handle->status_ = AvbHandleStatus::kSuccess;
            break;
        case VBMetaVerifyResult::kErrorVerification:
            avb_handle->status_ = AvbHandleStatus::kVerificationError;
            break;
        default:
            LERROR << "LoadAndVerifyVbmetaByPath failed, result: " << verify_result;
            return nullptr;
    }

    if (verification_disabled) {
        LINFO << "AVB verification disabled on: " << fstab_entry.mount_point;
        avb_handle->status_ = AvbHandleStatus::kVerificationDisabled;
    }

    LINFO << "Returning avb_handle for '" << fstab_entry.mount_point
          << "' with status: " << avb_handle->status_;
    return avb_handle;
}

AvbUniquePtr AvbHandle::LoadAndVerifyVbmeta() {
    // Loads inline vbmeta images, starting from /vbmeta.
    return LoadAndVerifyVbmeta("vbmeta", fs_mgr_get_slot_suffix(), fs_mgr_get_other_slot_suffix(),
@@ -358,52 +421,12 @@ AvbUniquePtr AvbHandle::Open() {

AvbHashtreeResult AvbHandle::SetUpStandaloneAvbHashtree(FstabEntry* fstab_entry,
                                                        bool wait_for_verity_dev) {
    if (fstab_entry->avb_key.empty()) {
        LERROR << "avb_key=/path/to/key is missing for " << fstab_entry->mount_point;
        return AvbHashtreeResult::kFail;
    }

    // Binds allow_verification_error and rollback_protection to device unlock state.
    bool allow_verification_error = IsDeviceUnlocked();
    bool rollback_protection = !allow_verification_error;

    std::string expected_key_blob;
    if (!ReadFileToString(fstab_entry->avb_key, &expected_key_blob)) {
        if (!allow_verification_error) {
            LERROR << "Failed to load avb_key: " << fstab_entry->avb_key
                   << " for mount point: " << fstab_entry->mount_point;
            return AvbHashtreeResult::kFail;
        }
        LWARNING << "Allowing no expected key blob when verification error is permitted";
        expected_key_blob.clear();
    }

    bool verification_disabled = false;
    std::unique_ptr<VBMetaData> vbmeta = LoadAndVerifyVbmetaByPath(
            fstab_entry->blk_device, "" /* partition_name, no need for a standalone path */,
            expected_key_blob, allow_verification_error, rollback_protection,
            false /* not is_chained_vbmeta */, nullptr /* out_public_key_data */,
            &verification_disabled, nullptr /* out_verify_result */);

    if (!vbmeta) {
        LERROR << "Failed to load vbmeta: " << fstab_entry->blk_device;
        return AvbHashtreeResult::kFail;
    }

    if (verification_disabled) {
        LINFO << "AVB verification disabled on: " << fstab_entry->mount_point;
        return AvbHashtreeResult::kDisabled;
    }

    // Puts the vbmeta into a vector, for LoadAvbHashtreeToEnableVerity() to use.
    std::vector<VBMetaData> vbmeta_images;
    vbmeta_images.emplace_back(std::move(*vbmeta));
    if (!LoadAvbHashtreeToEnableVerity(fstab_entry, wait_for_verity_dev, vbmeta_images,
                                       fs_mgr_get_slot_suffix(), fs_mgr_get_other_slot_suffix())) {
    auto avb_handle = LoadAndVerifyVbmeta(*fstab_entry);
    if (!avb_handle) {
        return AvbHashtreeResult::kFail;
    }

    return AvbHashtreeResult::kSuccess;
    return avb_handle->SetUpAvbHashtree(fstab_entry, wait_for_verity_dev);
}

AvbHashtreeResult AvbHandle::SetUpAvbHashtree(FstabEntry* fstab_entry, bool wait_for_verity_dev) {
@@ -425,5 +448,19 @@ AvbHashtreeResult AvbHandle::SetUpAvbHashtree(FstabEntry* fstab_entry, bool wait
    return AvbHashtreeResult::kSuccess;
}

std::string AvbHandle::GetSecurityPatchLevel(const FstabEntry& fstab_entry) const {
    if (vbmeta_images_.size() < 1) {
        return "";
    }
    std::string avb_partition_name = DeriveAvbPartitionName(fstab_entry, fs_mgr_get_slot_suffix(),
                                                            fs_mgr_get_other_slot_suffix());
    auto avb_prop_name = "com.android.build." + avb_partition_name + ".security_patch";
    return GetAvbPropertyDescriptor(avb_prop_name, vbmeta_images_);
}

bool AvbHandle::IsDeviceUnlocked() {
    return android::fs_mgr::IsDeviceUnlocked();
}

}  // namespace fs_mgr
}  // namespace android
+6 −0
Original line number Diff line number Diff line
@@ -85,6 +85,8 @@ class AvbHandle {
    // TODO(bowgotsai): remove Open() and switch to LoadAndVerifyVbmeta().
    static AvbUniquePtr Open();                 // loads inline vbmeta, via libavb.
    static AvbUniquePtr LoadAndVerifyVbmeta();  // loads inline vbmeta.
    static AvbUniquePtr LoadAndVerifyVbmeta(
            const FstabEntry& fstab_entry);     // loads offline vbmeta.
    static AvbUniquePtr LoadAndVerifyVbmeta(    // loads offline vbmeta.
            const std::string& partition_name, const std::string& ab_suffix,
            const std::string& ab_other_suffix, const std::string& expected_public_key,
@@ -108,6 +110,10 @@ class AvbHandle {
    static AvbHashtreeResult SetUpStandaloneAvbHashtree(FstabEntry* fstab_entry,
                                                        bool wait_for_verity_dev = true);

    static bool IsDeviceUnlocked();

    std::string GetSecurityPatchLevel(const FstabEntry& fstab_entry) const;

    const std::string& avb_version() const { return avb_version_; }
    const VBMetaInfo& vbmeta_info() const { return vbmeta_info_; }
    AvbHandleStatus status() const { return status_; }
+62 −0
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@ using android::fs_mgr::AvbPartitionToDevicePatition;
using android::fs_mgr::DeriveAvbPartitionName;
using android::fs_mgr::FstabEntry;
using android::fs_mgr::GetAvbFooter;
using android::fs_mgr::GetAvbPropertyDescriptor;
using android::fs_mgr::GetChainPartitionInfo;
using android::fs_mgr::GetTotalSize;
using android::fs_mgr::LoadAndVerifyVbmetaByPartition;
@@ -268,6 +269,67 @@ TEST_F(AvbUtilTest, GetAvbFooterInsufficientSize) {
    EXPECT_EQ(nullptr, footer);
}

TEST_F(AvbUtilTest, GetAvbPropertyDescriptor_Basic) {
    // Makes a vbmeta.img with some properties.
    GenerateVBMetaImage("vbmeta.img", "SHA256_RSA4096", 0, data_dir_.Append("testkey_rsa4096.pem"),
                        {}, /* include_descriptor_image_paths */
                        {}, /* chain_partitions */
                        "--prop foo:android "
                        "--prop bar:treble "
                        "--internal_release_string \"unit test\" ");
    auto vbmeta = LoadVBMetaData("vbmeta.img");

    // Puts the vbmeta into a vector, for GetAvbPropertyDescriptor to use.
    std::vector<VBMetaData> vbmeta_images;
    vbmeta_images.emplace_back(std::move(vbmeta));

    EXPECT_EQ("android", GetAvbPropertyDescriptor("foo", vbmeta_images));
    EXPECT_EQ("treble", GetAvbPropertyDescriptor("bar", vbmeta_images));
    EXPECT_EQ("", GetAvbPropertyDescriptor("non-existent", vbmeta_images));
}

TEST_F(AvbUtilTest, GetAvbPropertyDescriptor_SecurityPatchLevel) {
    // Generates a raw boot.img
    const size_t boot_image_size = 5 * 1024 * 1024;
    const size_t boot_partition_size = 10 * 1024 * 1024;
    base::FilePath boot_path = GenerateImage("boot.img", boot_image_size);
    // Adds AVB Hash Footer.
    AddAvbFooter(boot_path, "hash", "boot", boot_partition_size, "SHA256_RSA2048", 10,
                 data_dir_.Append("testkey_rsa2048.pem"), "d00df00d",
                 "--internal_release_string \"unit test\"");

    // Generates a raw system.img, use a smaller size to speed-up unit test.
    const size_t system_image_size = 10 * 1024 * 1024;
    const size_t system_partition_size = 15 * 1024 * 1024;
    base::FilePath system_path = GenerateImage("system.img", system_image_size);
    // Adds AVB Hashtree Footer.
    AddAvbFooter(system_path, "hashtree", "system", system_partition_size, "SHA512_RSA4096", 20,
                 data_dir_.Append("testkey_rsa4096.pem"), "d00df00d",
                 "--prop com.android.build.system.security_patch:2019-04-05 "
                 "--internal_release_string \"unit test\"");

    // Generates chain partition descriptors.
    base::FilePath rsa4096_public_key =
            ExtractPublicKeyAvb(data_dir_.Append("testkey_rsa4096.pem"));

    // Makes a vbmeta.img including the 'system' chained descriptor.
    GenerateVBMetaImage("vbmeta.img", "SHA256_RSA4096", 0, data_dir_.Append("testkey_rsa4096.pem"),
                        {boot_path},                         /* include_descriptor_image_paths */
                        {{"system", 3, rsa4096_public_key}}, /* chain_partitions */
                        "--internal_release_string \"unit test\"");

    auto vbmeta = LoadVBMetaData("vbmeta.img");
    auto system_vbmeta = ExtractAndLoadVBMetaData(system_path, "system-vbmeta.img");

    // Puts the vbmeta into a vector, for GetAvbPropertyDescriptor to use.
    std::vector<VBMetaData> vbmeta_images;
    vbmeta_images.emplace_back(std::move(vbmeta));
    vbmeta_images.emplace_back(std::move(system_vbmeta));

    EXPECT_EQ("2019-04-05",
              GetAvbPropertyDescriptor("com.android.build.system.security_patch", vbmeta_images));
}

TEST_F(AvbUtilTest, GetVBMetaHeader) {
    // Generates a raw boot.img
    const size_t image_size = 5 * 1024 * 1024;
Loading