Loading fs_mgr/libfs_avb/fs_avb.cpp +86 −34 Original line number Diff line number Diff line Loading @@ -288,14 +288,82 @@ static bool IsAvbPermissive() { return false; } AvbUniquePtr AvbHandle::LoadAndVerifyVbmeta(const FstabEntry& fstab_entry, bool IsPublicKeyMatching(const FstabEntry& fstab_entry, const std::string& public_key_data, const std::vector<std::string>& preload_avb_key_blobs) { // At least one of the following should be provided for public key matching. if (preload_avb_key_blobs.empty() && fstab_entry.avb_keys.empty()) { LERROR << "avb_keys=/path/to/key(s) is missing for " << fstab_entry.mount_point; return nullptr; return false; } // Expected key shouldn't be empty. if (public_key_data.empty()) { LERROR << "public key data shouldn't be empty for " << fstab_entry.mount_point; return false; } // Performs key matching for preload_avb_key_blobs first, if it is present. if (!preload_avb_key_blobs.empty()) { if (std::find(preload_avb_key_blobs.begin(), preload_avb_key_blobs.end(), public_key_data) != preload_avb_key_blobs.end()) { return true; } } // Performs key matching for fstab_entry.avb_keys if necessary. // Note that it is intentional to match both preload_avb_key_blobs and fstab_entry.avb_keys. // Some keys might only be available before init chroots into /system, e.g., /avb/key1 // in the first-stage ramdisk, while other keys might only be available after the chroot, // e.g., /system/etc/avb/key2. // fstab_entry.avb_keys might be either a directory containing multiple keys, // or a string indicating multiple keys separated by ':'. std::vector<std::string> allowed_avb_keys; auto list_avb_keys_in_dir = ListFiles(fstab_entry.avb_keys); if (list_avb_keys_in_dir.ok()) { std::sort(list_avb_keys_in_dir->begin(), list_avb_keys_in_dir->end()); allowed_avb_keys = *list_avb_keys_in_dir; } else { allowed_avb_keys = Split(fstab_entry.avb_keys, ":"); } return ValidatePublicKeyBlob(public_key_data, allowed_avb_keys); } bool IsHashtreeDescriptorRootDigestMatching(const FstabEntry& fstab_entry, const std::vector<VBMetaData>& vbmeta_images, const std::string& ab_suffix, const std::string& ab_other_suffix) { // Read expected value of hashtree descriptor root digest from fstab_entry. std::string root_digest_expected; if (!ReadFileToString(fstab_entry.avb_hashtree_digest, &root_digest_expected)) { LERROR << "Failed to load expected root digest for " << fstab_entry.mount_point; return false; } // Read actual hashtree descriptor from vbmeta image. std::string partition_name = DeriveAvbPartitionName(fstab_entry, ab_suffix, ab_other_suffix); if (partition_name.empty()) { LERROR << "Failed to find partition name for " << fstab_entry.mount_point; return false; } std::unique_ptr<FsAvbHashtreeDescriptor> hashtree_descriptor = android::fs_mgr::GetHashtreeDescriptor(partition_name, vbmeta_images); if (!hashtree_descriptor) { LERROR << "Not found hashtree descriptor for " << fstab_entry.mount_point; return false; } // Performs hashtree descriptor root digest matching. if (hashtree_descriptor->root_digest != root_digest_expected) { LERROR << "root digest (" << hashtree_descriptor->root_digest << ") is different from expected value (" << root_digest_expected << ")"; return false; } return true; } AvbUniquePtr AvbHandle::LoadAndVerifyVbmeta(const FstabEntry& fstab_entry, const std::vector<std::string>& preload_avb_key_blobs) { // Binds allow_verification_error and rollback_protection to device unlock state. bool allow_verification_error = IsAvbPermissive(); bool rollback_protection = !allow_verification_error; Loading Loading @@ -333,36 +401,9 @@ AvbUniquePtr AvbHandle::LoadAndVerifyVbmeta(const FstabEntry& fstab_entry, return nullptr; } bool public_key_match = false; // Performs key matching for preload_avb_key_blobs first, if it is present. if (!public_key_data.empty() && !preload_avb_key_blobs.empty()) { if (std::find(preload_avb_key_blobs.begin(), preload_avb_key_blobs.end(), public_key_data) != preload_avb_key_blobs.end()) { public_key_match = true; } } // Performs key matching for fstab_entry.avb_keys if necessary. // Note that it is intentional to match both preload_avb_key_blobs and fstab_entry.avb_keys. // Some keys might only be availble before init chroots into /system, e.g., /avb/key1 // in the first-stage ramdisk, while other keys might only be available after the chroot, // e.g., /system/etc/avb/key2. if (!public_key_data.empty() && !public_key_match) { // fstab_entry.avb_keys might be either a directory containing multiple keys, // or a string indicating multiple keys separated by ':'. std::vector<std::string> allowed_avb_keys; auto list_avb_keys_in_dir = ListFiles(fstab_entry.avb_keys); if (list_avb_keys_in_dir.ok()) { std::sort(list_avb_keys_in_dir->begin(), list_avb_keys_in_dir->end()); allowed_avb_keys = *list_avb_keys_in_dir; } else { allowed_avb_keys = Split(fstab_entry.avb_keys, ":"); } if (ValidatePublicKeyBlob(public_key_data, allowed_avb_keys)) { public_key_match = true; } } if (!public_key_match) { // Verify vbmeta image checking by either public key or hashtree descriptor root digest. if (!preload_avb_key_blobs.empty() || !fstab_entry.avb_keys.empty()) { if (!IsPublicKeyMatching(fstab_entry, public_key_data, preload_avb_key_blobs)) { avb_handle->status_ = AvbHandleStatus::kVerificationError; LWARNING << "Found unknown public key used to sign " << fstab_entry.mount_point; if (!allow_verification_error) { Loading @@ -370,6 +411,17 @@ AvbUniquePtr AvbHandle::LoadAndVerifyVbmeta(const FstabEntry& fstab_entry, return nullptr; } } } else if (!IsHashtreeDescriptorRootDigestMatching(fstab_entry, avb_handle->vbmeta_images_, avb_handle->slot_suffix_, avb_handle->other_slot_suffix_)) { avb_handle->status_ = AvbHandleStatus::kVerificationError; LWARNING << "Found unknown hashtree descriptor root digest used on " << fstab_entry.mount_point; if (!allow_verification_error) { LERROR << "Verification based on root digest failed. Vbmeta image is not allowed."; return nullptr; } } if (verification_disabled) { LINFO << "AVB verification disabled on: " << fstab_entry.mount_point; Loading fs_mgr/libfstab/fstab.cpp +4 −0 Original line number Diff line number Diff line Loading @@ -286,6 +286,10 @@ bool ParseFsMgrFlags(const std::string& flags, FstabEntry* entry) { } } else if (StartsWith(flag, "avb_keys=")) { // must before the following "avb" entry->avb_keys = arg; } else if (StartsWith(flag, "avb_hashtree_digest=")) { // "avb_hashtree_digest" must before the following "avb" // The path where hex-encoded hashtree descriptor root digest is located. entry->avb_hashtree_digest = arg; } else if (StartsWith(flag, "avb")) { entry->fs_mgr_flags.avb = true; entry->vbmeta_partition = arg; Loading fs_mgr/libfstab/include/fstab/fstab.h +1 −0 Original line number Diff line number Diff line Loading @@ -57,6 +57,7 @@ struct FstabEntry { uint64_t zram_backingdev_size = 0; std::string avb_keys; std::string lowerdir; std::string avb_hashtree_digest; struct FsMgrFlags { bool wait : 1; Loading init/first_stage_mount.cpp +42 −21 Original line number Diff line number Diff line Loading @@ -732,6 +732,15 @@ bool FirstStageMountVBootV2::GetDmVerityDevices(std::set<std::string>* devices) return true; } bool IsHashtreeDisabled(const AvbHandle& vbmeta, std::string mount_point) { if (vbmeta.status() == AvbHandleStatus::kHashtreeDisabled || vbmeta.status() == AvbHandleStatus::kVerificationDisabled) { LOG(ERROR) << "Top-level vbmeta is disabled, skip Hashtree setup for " << mount_point; return true; // Returns true to mount the partition directly. } return false; } bool FirstStageMountVBootV2::SetUpDmVerity(FstabEntry* fstab_entry) { AvbHashtreeResult hashtree_result; Loading @@ -740,12 +749,9 @@ bool FirstStageMountVBootV2::SetUpDmVerity(FstabEntry* fstab_entry) { if (!fstab_entry->avb_keys.empty()) { if (!InitAvbHandle()) return false; // Checks if hashtree should be disabled from the top-level /vbmeta. if (avb_handle_->status() == AvbHandleStatus::kHashtreeDisabled || avb_handle_->status() == AvbHandleStatus::kVerificationDisabled) { LOG(ERROR) << "Top-level vbmeta is disabled, skip Hashtree setup for " << fstab_entry->mount_point; return true; // Returns true to mount the partition directly. } else { if (IsHashtreeDisabled(*avb_handle_, fstab_entry->mount_point)) { return true; } auto avb_standalone_handle = AvbHandle::LoadAndVerifyVbmeta( *fstab_entry, preload_avb_key_blobs_[fstab_entry->avb_keys]); if (!avb_standalone_handle) { Loading @@ -763,11 +769,26 @@ bool FirstStageMountVBootV2::SetUpDmVerity(FstabEntry* fstab_entry) { hashtree_result = avb_standalone_handle->SetUpAvbHashtree( fstab_entry, false /* wait_for_verity_dev */); } } } else if (fstab_entry->fs_mgr_flags.avb) { if (!InitAvbHandle()) return false; hashtree_result = avb_handle_->SetUpAvbHashtree(fstab_entry, false /* wait_for_verity_dev */); } else if (!fstab_entry->avb_hashtree_digest.empty()) { // When fstab_entry has neither avb_keys nor avb flag, try using // avb_hashtree_digest. if (!InitAvbHandle()) return false; // Checks if hashtree should be disabled from the top-level /vbmeta. if (IsHashtreeDisabled(*avb_handle_, fstab_entry->mount_point)) { return true; } auto avb_standalone_handle = AvbHandle::LoadAndVerifyVbmeta(*fstab_entry); if (!avb_standalone_handle) { LOG(ERROR) << "Failed to load vbmeta based on hashtree descriptor root digest for " << fstab_entry->mount_point; return false; } hashtree_result = avb_standalone_handle->SetUpAvbHashtree(fstab_entry, false /* wait_for_verity_dev */); } else { return true; // No need AVB, returns true to mount the partition directly. } Loading Loading
fs_mgr/libfs_avb/fs_avb.cpp +86 −34 Original line number Diff line number Diff line Loading @@ -288,14 +288,82 @@ static bool IsAvbPermissive() { return false; } AvbUniquePtr AvbHandle::LoadAndVerifyVbmeta(const FstabEntry& fstab_entry, bool IsPublicKeyMatching(const FstabEntry& fstab_entry, const std::string& public_key_data, const std::vector<std::string>& preload_avb_key_blobs) { // At least one of the following should be provided for public key matching. if (preload_avb_key_blobs.empty() && fstab_entry.avb_keys.empty()) { LERROR << "avb_keys=/path/to/key(s) is missing for " << fstab_entry.mount_point; return nullptr; return false; } // Expected key shouldn't be empty. if (public_key_data.empty()) { LERROR << "public key data shouldn't be empty for " << fstab_entry.mount_point; return false; } // Performs key matching for preload_avb_key_blobs first, if it is present. if (!preload_avb_key_blobs.empty()) { if (std::find(preload_avb_key_blobs.begin(), preload_avb_key_blobs.end(), public_key_data) != preload_avb_key_blobs.end()) { return true; } } // Performs key matching for fstab_entry.avb_keys if necessary. // Note that it is intentional to match both preload_avb_key_blobs and fstab_entry.avb_keys. // Some keys might only be available before init chroots into /system, e.g., /avb/key1 // in the first-stage ramdisk, while other keys might only be available after the chroot, // e.g., /system/etc/avb/key2. // fstab_entry.avb_keys might be either a directory containing multiple keys, // or a string indicating multiple keys separated by ':'. std::vector<std::string> allowed_avb_keys; auto list_avb_keys_in_dir = ListFiles(fstab_entry.avb_keys); if (list_avb_keys_in_dir.ok()) { std::sort(list_avb_keys_in_dir->begin(), list_avb_keys_in_dir->end()); allowed_avb_keys = *list_avb_keys_in_dir; } else { allowed_avb_keys = Split(fstab_entry.avb_keys, ":"); } return ValidatePublicKeyBlob(public_key_data, allowed_avb_keys); } bool IsHashtreeDescriptorRootDigestMatching(const FstabEntry& fstab_entry, const std::vector<VBMetaData>& vbmeta_images, const std::string& ab_suffix, const std::string& ab_other_suffix) { // Read expected value of hashtree descriptor root digest from fstab_entry. std::string root_digest_expected; if (!ReadFileToString(fstab_entry.avb_hashtree_digest, &root_digest_expected)) { LERROR << "Failed to load expected root digest for " << fstab_entry.mount_point; return false; } // Read actual hashtree descriptor from vbmeta image. std::string partition_name = DeriveAvbPartitionName(fstab_entry, ab_suffix, ab_other_suffix); if (partition_name.empty()) { LERROR << "Failed to find partition name for " << fstab_entry.mount_point; return false; } std::unique_ptr<FsAvbHashtreeDescriptor> hashtree_descriptor = android::fs_mgr::GetHashtreeDescriptor(partition_name, vbmeta_images); if (!hashtree_descriptor) { LERROR << "Not found hashtree descriptor for " << fstab_entry.mount_point; return false; } // Performs hashtree descriptor root digest matching. if (hashtree_descriptor->root_digest != root_digest_expected) { LERROR << "root digest (" << hashtree_descriptor->root_digest << ") is different from expected value (" << root_digest_expected << ")"; return false; } return true; } AvbUniquePtr AvbHandle::LoadAndVerifyVbmeta(const FstabEntry& fstab_entry, const std::vector<std::string>& preload_avb_key_blobs) { // Binds allow_verification_error and rollback_protection to device unlock state. bool allow_verification_error = IsAvbPermissive(); bool rollback_protection = !allow_verification_error; Loading Loading @@ -333,36 +401,9 @@ AvbUniquePtr AvbHandle::LoadAndVerifyVbmeta(const FstabEntry& fstab_entry, return nullptr; } bool public_key_match = false; // Performs key matching for preload_avb_key_blobs first, if it is present. if (!public_key_data.empty() && !preload_avb_key_blobs.empty()) { if (std::find(preload_avb_key_blobs.begin(), preload_avb_key_blobs.end(), public_key_data) != preload_avb_key_blobs.end()) { public_key_match = true; } } // Performs key matching for fstab_entry.avb_keys if necessary. // Note that it is intentional to match both preload_avb_key_blobs and fstab_entry.avb_keys. // Some keys might only be availble before init chroots into /system, e.g., /avb/key1 // in the first-stage ramdisk, while other keys might only be available after the chroot, // e.g., /system/etc/avb/key2. if (!public_key_data.empty() && !public_key_match) { // fstab_entry.avb_keys might be either a directory containing multiple keys, // or a string indicating multiple keys separated by ':'. std::vector<std::string> allowed_avb_keys; auto list_avb_keys_in_dir = ListFiles(fstab_entry.avb_keys); if (list_avb_keys_in_dir.ok()) { std::sort(list_avb_keys_in_dir->begin(), list_avb_keys_in_dir->end()); allowed_avb_keys = *list_avb_keys_in_dir; } else { allowed_avb_keys = Split(fstab_entry.avb_keys, ":"); } if (ValidatePublicKeyBlob(public_key_data, allowed_avb_keys)) { public_key_match = true; } } if (!public_key_match) { // Verify vbmeta image checking by either public key or hashtree descriptor root digest. if (!preload_avb_key_blobs.empty() || !fstab_entry.avb_keys.empty()) { if (!IsPublicKeyMatching(fstab_entry, public_key_data, preload_avb_key_blobs)) { avb_handle->status_ = AvbHandleStatus::kVerificationError; LWARNING << "Found unknown public key used to sign " << fstab_entry.mount_point; if (!allow_verification_error) { Loading @@ -370,6 +411,17 @@ AvbUniquePtr AvbHandle::LoadAndVerifyVbmeta(const FstabEntry& fstab_entry, return nullptr; } } } else if (!IsHashtreeDescriptorRootDigestMatching(fstab_entry, avb_handle->vbmeta_images_, avb_handle->slot_suffix_, avb_handle->other_slot_suffix_)) { avb_handle->status_ = AvbHandleStatus::kVerificationError; LWARNING << "Found unknown hashtree descriptor root digest used on " << fstab_entry.mount_point; if (!allow_verification_error) { LERROR << "Verification based on root digest failed. Vbmeta image is not allowed."; return nullptr; } } if (verification_disabled) { LINFO << "AVB verification disabled on: " << fstab_entry.mount_point; Loading
fs_mgr/libfstab/fstab.cpp +4 −0 Original line number Diff line number Diff line Loading @@ -286,6 +286,10 @@ bool ParseFsMgrFlags(const std::string& flags, FstabEntry* entry) { } } else if (StartsWith(flag, "avb_keys=")) { // must before the following "avb" entry->avb_keys = arg; } else if (StartsWith(flag, "avb_hashtree_digest=")) { // "avb_hashtree_digest" must before the following "avb" // The path where hex-encoded hashtree descriptor root digest is located. entry->avb_hashtree_digest = arg; } else if (StartsWith(flag, "avb")) { entry->fs_mgr_flags.avb = true; entry->vbmeta_partition = arg; Loading
fs_mgr/libfstab/include/fstab/fstab.h +1 −0 Original line number Diff line number Diff line Loading @@ -57,6 +57,7 @@ struct FstabEntry { uint64_t zram_backingdev_size = 0; std::string avb_keys; std::string lowerdir; std::string avb_hashtree_digest; struct FsMgrFlags { bool wait : 1; Loading
init/first_stage_mount.cpp +42 −21 Original line number Diff line number Diff line Loading @@ -732,6 +732,15 @@ bool FirstStageMountVBootV2::GetDmVerityDevices(std::set<std::string>* devices) return true; } bool IsHashtreeDisabled(const AvbHandle& vbmeta, std::string mount_point) { if (vbmeta.status() == AvbHandleStatus::kHashtreeDisabled || vbmeta.status() == AvbHandleStatus::kVerificationDisabled) { LOG(ERROR) << "Top-level vbmeta is disabled, skip Hashtree setup for " << mount_point; return true; // Returns true to mount the partition directly. } return false; } bool FirstStageMountVBootV2::SetUpDmVerity(FstabEntry* fstab_entry) { AvbHashtreeResult hashtree_result; Loading @@ -740,12 +749,9 @@ bool FirstStageMountVBootV2::SetUpDmVerity(FstabEntry* fstab_entry) { if (!fstab_entry->avb_keys.empty()) { if (!InitAvbHandle()) return false; // Checks if hashtree should be disabled from the top-level /vbmeta. if (avb_handle_->status() == AvbHandleStatus::kHashtreeDisabled || avb_handle_->status() == AvbHandleStatus::kVerificationDisabled) { LOG(ERROR) << "Top-level vbmeta is disabled, skip Hashtree setup for " << fstab_entry->mount_point; return true; // Returns true to mount the partition directly. } else { if (IsHashtreeDisabled(*avb_handle_, fstab_entry->mount_point)) { return true; } auto avb_standalone_handle = AvbHandle::LoadAndVerifyVbmeta( *fstab_entry, preload_avb_key_blobs_[fstab_entry->avb_keys]); if (!avb_standalone_handle) { Loading @@ -763,11 +769,26 @@ bool FirstStageMountVBootV2::SetUpDmVerity(FstabEntry* fstab_entry) { hashtree_result = avb_standalone_handle->SetUpAvbHashtree( fstab_entry, false /* wait_for_verity_dev */); } } } else if (fstab_entry->fs_mgr_flags.avb) { if (!InitAvbHandle()) return false; hashtree_result = avb_handle_->SetUpAvbHashtree(fstab_entry, false /* wait_for_verity_dev */); } else if (!fstab_entry->avb_hashtree_digest.empty()) { // When fstab_entry has neither avb_keys nor avb flag, try using // avb_hashtree_digest. if (!InitAvbHandle()) return false; // Checks if hashtree should be disabled from the top-level /vbmeta. if (IsHashtreeDisabled(*avb_handle_, fstab_entry->mount_point)) { return true; } auto avb_standalone_handle = AvbHandle::LoadAndVerifyVbmeta(*fstab_entry); if (!avb_standalone_handle) { LOG(ERROR) << "Failed to load vbmeta based on hashtree descriptor root digest for " << fstab_entry->mount_point; return false; } hashtree_result = avb_standalone_handle->SetUpAvbHashtree(fstab_entry, false /* wait_for_verity_dev */); } else { return true; // No need AVB, returns true to mount the partition directly. } Loading