Merge "libfs_avb: support enable verity for a standalone partition"
This commit is contained in:
commit
30fef71b2c
8 changed files with 713 additions and 162 deletions
|
|
@ -1090,6 +1090,13 @@ int fs_mgr_mount_all(Fstab* fstab, int mount_mode) {
|
|||
// Skips mounting the device.
|
||||
continue;
|
||||
}
|
||||
} else if (!current_entry.avb_key.empty()) {
|
||||
if (AvbHandle::SetUpStandaloneAvbHashtree(¤t_entry) == AvbHashtreeResult::kFail) {
|
||||
LERROR << "Failed to set up AVB on standalone partition: "
|
||||
<< current_entry.mount_point << ", skipping!";
|
||||
// Skips mounting the device.
|
||||
continue;
|
||||
}
|
||||
} else if ((current_entry.fs_mgr_flags.verify)) {
|
||||
int rc = fs_mgr_setup_verity(¤t_entry, true);
|
||||
if (__android_log_is_debuggable() &&
|
||||
|
|
@ -1326,6 +1333,13 @@ static int fs_mgr_do_mount_helper(Fstab* fstab, const std::string& n_name,
|
|||
// Skips mounting the device.
|
||||
continue;
|
||||
}
|
||||
} else if (!fstab_entry.avb_key.empty()) {
|
||||
if (AvbHandle::SetUpStandaloneAvbHashtree(&fstab_entry) == AvbHashtreeResult::kFail) {
|
||||
LERROR << "Failed to set up AVB on standalone partition: "
|
||||
<< fstab_entry.mount_point << ", skipping!";
|
||||
// Skips mounting the device.
|
||||
continue;
|
||||
}
|
||||
} else if (fstab_entry.fs_mgr_flags.verify) {
|
||||
int rc = fs_mgr_setup_verity(&fstab_entry, true);
|
||||
if (__android_log_is_debuggable() &&
|
||||
|
|
|
|||
|
|
@ -338,6 +338,8 @@ static void ParseFsMgrFlags(const std::string& flags, FstabEntry* entry) {
|
|||
} else if (StartsWith(flag, "zram_backing_dev_path=")) {
|
||||
entry->fs_mgr_flags.zram_backing_dev_path = true;
|
||||
entry->zram_backing_dev_path = arg;
|
||||
} else if (StartsWith(flag, "avb_key=")) {
|
||||
entry->avb_key = arg;
|
||||
} else {
|
||||
LWARNING << "Warning: unknown flag: " << flag;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -116,6 +116,7 @@ struct FstabEntry {
|
|||
std::string zram_loopback_path;
|
||||
uint64_t zram_loopback_size = 512 * 1024 * 1024; // 512MB by default;
|
||||
std::string zram_backing_dev_path;
|
||||
std::string avb_key;
|
||||
|
||||
// TODO: Remove this union once fstab_rec is deprecated. It only serves as a
|
||||
// convenient way to convert between fstab_rec::fs_mgr_flags and these bools.
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@
|
|||
|
||||
#include "util.h"
|
||||
|
||||
using android::base::Basename;
|
||||
using android::base::StartsWith;
|
||||
using android::base::unique_fd;
|
||||
|
||||
|
|
@ -61,7 +62,7 @@ std::ostream& operator<<(std::ostream& os, VBMetaVerifyResult result) {
|
|||
// class VBMetaData
|
||||
// ----------------
|
||||
std::unique_ptr<AvbVBMetaImageHeader> VBMetaData::GetVBMetaHeader(bool update_vbmeta_size) {
|
||||
auto vbmeta_header(std::make_unique<AvbVBMetaImageHeader>());
|
||||
auto vbmeta_header = std::make_unique<AvbVBMetaImageHeader>();
|
||||
|
||||
if (!vbmeta_header) return nullptr;
|
||||
|
||||
|
|
@ -136,7 +137,7 @@ bool HashtreeDmVeritySetup(FstabEntry* fstab_entry, const AvbHashtreeDescriptor&
|
|||
}
|
||||
table.set_readonly(true);
|
||||
|
||||
const std::string mount_point(basename(fstab_entry->mount_point.c_str()));
|
||||
const std::string mount_point(Basename(fstab_entry->mount_point));
|
||||
android::dm::DeviceMapper& dm = android::dm::DeviceMapper::Instance();
|
||||
if (!dm.CreateDevice(mount_point, table)) {
|
||||
LERROR << "Couldn't create verity device!";
|
||||
|
|
@ -163,12 +164,12 @@ bool HashtreeDmVeritySetup(FstabEntry* fstab_entry, const AvbHashtreeDescriptor&
|
|||
return true;
|
||||
}
|
||||
|
||||
bool GetHashtreeDescriptor(const std::string& partition_name,
|
||||
const std::vector<VBMetaData>& vbmeta_images,
|
||||
AvbHashtreeDescriptor* out_hashtree_desc, std::string* out_salt,
|
||||
std::string* out_digest) {
|
||||
std::unique_ptr<AvbHashtreeDescriptor> GetHashtreeDescriptor(
|
||||
const std::string& partition_name, const std::vector<VBMetaData>& vbmeta_images,
|
||||
std::string* out_salt, std::string* out_digest) {
|
||||
bool found = false;
|
||||
const uint8_t* desc_partition_name;
|
||||
auto hashtree_desc = std::make_unique<AvbHashtreeDescriptor>();
|
||||
|
||||
for (const auto& vbmeta : vbmeta_images) {
|
||||
size_t num_descriptors;
|
||||
|
|
@ -189,15 +190,15 @@ bool GetHashtreeDescriptor(const std::string& partition_name,
|
|||
desc_partition_name =
|
||||
(const uint8_t*)descriptors[n] + sizeof(AvbHashtreeDescriptor);
|
||||
if (!avb_hashtree_descriptor_validate_and_byteswap(
|
||||
(AvbHashtreeDescriptor*)descriptors[n], out_hashtree_desc)) {
|
||||
(AvbHashtreeDescriptor*)descriptors[n], hashtree_desc.get())) {
|
||||
continue;
|
||||
}
|
||||
if (out_hashtree_desc->partition_name_len != partition_name.length()) {
|
||||
if (hashtree_desc->partition_name_len != partition_name.length()) {
|
||||
continue;
|
||||
}
|
||||
// Notes that desc_partition_name is not NUL-terminated.
|
||||
std::string hashtree_partition_name((const char*)desc_partition_name,
|
||||
out_hashtree_desc->partition_name_len);
|
||||
hashtree_desc->partition_name_len);
|
||||
if (hashtree_partition_name == partition_name) {
|
||||
found = true;
|
||||
}
|
||||
|
|
@ -209,16 +210,43 @@ bool GetHashtreeDescriptor(const std::string& partition_name,
|
|||
|
||||
if (!found) {
|
||||
LERROR << "Partition descriptor not found: " << partition_name.c_str();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const uint8_t* desc_salt = desc_partition_name + hashtree_desc->partition_name_len;
|
||||
*out_salt = BytesToHex(desc_salt, hashtree_desc->salt_len);
|
||||
|
||||
const uint8_t* desc_digest = desc_salt + hashtree_desc->salt_len;
|
||||
*out_digest = BytesToHex(desc_digest, hashtree_desc->root_digest_len);
|
||||
|
||||
return hashtree_desc;
|
||||
}
|
||||
|
||||
bool LoadAvbHashtreeToEnableVerity(FstabEntry* fstab_entry, bool wait_for_verity_dev,
|
||||
const std::vector<VBMetaData>& vbmeta_images,
|
||||
const std::string& ab_suffix,
|
||||
const std::string& ab_other_suffix) {
|
||||
// Derives partition_name from blk_device to query the corresponding AVB HASHTREE descriptor
|
||||
// to setup dm-verity. The partition_names in AVB descriptors are without A/B suffix.
|
||||
std::string partition_name = DeriveAvbPartitionName(*fstab_entry, ab_suffix, ab_other_suffix);
|
||||
|
||||
if (partition_name.empty()) {
|
||||
LERROR << "partition name is empty, cannot lookup AVB descriptors";
|
||||
return false;
|
||||
}
|
||||
|
||||
const uint8_t* desc_salt = desc_partition_name + out_hashtree_desc->partition_name_len;
|
||||
*out_salt = BytesToHex(desc_salt, out_hashtree_desc->salt_len);
|
||||
std::string salt;
|
||||
std::string root_digest;
|
||||
std::unique_ptr<AvbHashtreeDescriptor> hashtree_descriptor =
|
||||
GetHashtreeDescriptor(partition_name, vbmeta_images, &salt, &root_digest);
|
||||
if (!hashtree_descriptor) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const uint8_t* desc_digest = desc_salt + out_hashtree_desc->salt_len;
|
||||
*out_digest = BytesToHex(desc_digest, out_hashtree_desc->root_digest_len);
|
||||
|
||||
return true;
|
||||
// Converts HASHTREE descriptor to verity table to load into kernel.
|
||||
// When success, the new device path will be returned, e.g., /dev/block/dm-2.
|
||||
return HashtreeDmVeritySetup(fstab_entry, *hashtree_descriptor, salt, root_digest,
|
||||
wait_for_verity_dev);
|
||||
}
|
||||
|
||||
// Converts a AVB partition_name (without A/B suffix) to a device partition name.
|
||||
|
|
@ -244,6 +272,38 @@ std::string AvbPartitionToDevicePatition(const std::string& avb_partition_name,
|
|||
return sanitized_partition_name + append_suffix;
|
||||
}
|
||||
|
||||
// Converts fstab_entry.blk_device (with ab_suffix) to a AVB partition name.
|
||||
// e.g., "/dev/block/by-name/system_a", slot_select => "system",
|
||||
// "/dev/block/by-name/system_b", slot_select_other => "system_other".
|
||||
//
|
||||
// Or for a logical partition (with ab_suffix):
|
||||
// e.g., "system_a", slot_select => "system",
|
||||
// "system_b", slot_select_other => "system_other".
|
||||
std::string DeriveAvbPartitionName(const FstabEntry& fstab_entry, const std::string& ab_suffix,
|
||||
const std::string& ab_other_suffix) {
|
||||
std::string partition_name;
|
||||
if (fstab_entry.fs_mgr_flags.logical) {
|
||||
partition_name = fstab_entry.logical_partition_name;
|
||||
} else {
|
||||
partition_name = Basename(fstab_entry.blk_device);
|
||||
}
|
||||
|
||||
if (fstab_entry.fs_mgr_flags.slot_select) {
|
||||
auto found = partition_name.rfind(ab_suffix);
|
||||
if (found != std::string::npos) {
|
||||
partition_name.erase(found); // converts system_a => system
|
||||
}
|
||||
} else if (fstab_entry.fs_mgr_flags.slot_select_other) {
|
||||
auto found = partition_name.rfind(ab_other_suffix);
|
||||
if (found != std::string::npos) {
|
||||
partition_name.erase(found); // converts system_b => system
|
||||
}
|
||||
partition_name += "_other"; // converts system => system_other
|
||||
}
|
||||
|
||||
return partition_name;
|
||||
}
|
||||
|
||||
off64_t GetTotalSize(int fd) {
|
||||
off64_t saved_current = lseek64(fd, 0, SEEK_CUR);
|
||||
if (saved_current == -1) {
|
||||
|
|
@ -268,19 +328,19 @@ off64_t GetTotalSize(int fd) {
|
|||
|
||||
std::unique_ptr<AvbFooter> GetAvbFooter(int fd) {
|
||||
std::array<uint8_t, AVB_FOOTER_SIZE> footer_buf;
|
||||
auto footer(std::make_unique<AvbFooter>());
|
||||
auto footer = std::make_unique<AvbFooter>();
|
||||
|
||||
off64_t footer_offset = GetTotalSize(fd) - AVB_FOOTER_SIZE;
|
||||
|
||||
ssize_t num_read =
|
||||
TEMP_FAILURE_RETRY(pread64(fd, footer_buf.data(), AVB_FOOTER_SIZE, footer_offset));
|
||||
if (num_read < 0 || num_read != AVB_FOOTER_SIZE) {
|
||||
PERROR << "Failed to read AVB footer";
|
||||
PERROR << "Failed to read AVB footer at offset: " << footer_offset;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!avb_footer_validate_and_byteswap((const AvbFooter*)footer_buf.data(), footer.get())) {
|
||||
PERROR << "AVB footer verification failed.";
|
||||
PERROR << "AVB footer verification failed at offset " << footer_offset;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
|
@ -432,24 +492,22 @@ std::vector<ChainInfo> GetChainPartitionInfo(const VBMetaData& vbmeta, bool* fat
|
|||
return chain_partitions;
|
||||
}
|
||||
|
||||
VBMetaVerifyResult LoadAndVerifyVbmetaImpl(
|
||||
const std::string& partition_name, const std::string& ab_suffix,
|
||||
const std::string& ab_other_suffix, const std::string& expected_public_key_blob,
|
||||
bool allow_verification_error, bool load_chained_vbmeta, bool rollback_protection,
|
||||
std::function<std::string(const std::string&)> device_path_constructor,
|
||||
bool is_chained_vbmeta, std::vector<VBMetaData>* out_vbmeta_images) {
|
||||
// Loads the vbmeta from a given path.
|
||||
std::unique_ptr<VBMetaData> LoadAndVerifyVbmetaByPath(
|
||||
const std::string& image_path, const std::string& partition_name,
|
||||
const std::string& expected_public_key_blob, bool allow_verification_error,
|
||||
bool rollback_protection, bool is_chained_vbmeta, bool* out_verification_disabled,
|
||||
VBMetaVerifyResult* out_verify_result) {
|
||||
// Ensures the device path (might be a symlink created by init) is ready to access.
|
||||
auto device_path = device_path_constructor(
|
||||
AvbPartitionToDevicePatition(partition_name, ab_suffix, ab_other_suffix));
|
||||
if (!WaitForFile(device_path, 1s)) {
|
||||
PERROR << "No such partition: " << device_path;
|
||||
return VBMetaVerifyResult::kError;
|
||||
if (!WaitForFile(image_path, 1s)) {
|
||||
PERROR << "No such path: " << image_path;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
unique_fd fd(TEMP_FAILURE_RETRY(open(device_path.c_str(), O_RDONLY | O_CLOEXEC)));
|
||||
unique_fd fd(TEMP_FAILURE_RETRY(open(image_path.c_str(), O_RDONLY | O_CLOEXEC)));
|
||||
if (fd < 0) {
|
||||
PERROR << "Failed to open: " << device_path;
|
||||
return VBMetaVerifyResult::kError;
|
||||
PERROR << "Failed to open: " << image_path;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
VBMetaVerifyResult verify_result;
|
||||
|
|
@ -457,53 +515,84 @@ VBMetaVerifyResult LoadAndVerifyVbmetaImpl(
|
|||
VerifyVBMetaData(fd, partition_name, expected_public_key_blob, &verify_result);
|
||||
if (!vbmeta) {
|
||||
LERROR << partition_name << ": Failed to load vbmeta, result: " << verify_result;
|
||||
return VBMetaVerifyResult::kError;
|
||||
return nullptr;
|
||||
}
|
||||
vbmeta->set_vbmeta_path(image_path);
|
||||
|
||||
if (!allow_verification_error && verify_result == VBMetaVerifyResult::kErrorVerification) {
|
||||
LERROR << partition_name << ": allow verification error is not allowed";
|
||||
return VBMetaVerifyResult::kError;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::unique_ptr<AvbVBMetaImageHeader> vbmeta_header =
|
||||
vbmeta->GetVBMetaHeader(true /* update_vbmeta_size */);
|
||||
if (!vbmeta_header) {
|
||||
LERROR << partition_name << ": Failed to get vbmeta header";
|
||||
return VBMetaVerifyResult::kError;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (rollback_protection && RollbackDetected(partition_name, vbmeta_header->rollback_index)) {
|
||||
return VBMetaVerifyResult::kError;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// vbmeta flags can only be set by the top-level vbmeta image.
|
||||
if (is_chained_vbmeta && vbmeta_header->flags != 0) {
|
||||
LERROR << partition_name << ": chained vbmeta image has non-zero flags";
|
||||
return VBMetaVerifyResult::kError;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Checks if verification has been disabled by setting a bit in the image.
|
||||
if (out_verification_disabled) {
|
||||
if (vbmeta_header->flags & AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED) {
|
||||
LWARNING << "VERIFICATION_DISABLED bit is set for partition: " << partition_name;
|
||||
*out_verification_disabled = true;
|
||||
} else {
|
||||
*out_verification_disabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (out_verify_result) {
|
||||
*out_verify_result = verify_result;
|
||||
}
|
||||
|
||||
return vbmeta;
|
||||
}
|
||||
|
||||
VBMetaVerifyResult LoadAndVerifyVbmetaByPartition(
|
||||
const std::string& partition_name, const std::string& ab_suffix,
|
||||
const std::string& ab_other_suffix, const std::string& expected_public_key_blob,
|
||||
bool allow_verification_error, bool load_chained_vbmeta, bool rollback_protection,
|
||||
std::function<std::string(const std::string&)> device_path_constructor, bool is_chained_vbmeta,
|
||||
std::vector<VBMetaData>* out_vbmeta_images) {
|
||||
auto image_path = device_path_constructor(
|
||||
AvbPartitionToDevicePatition(partition_name, ab_suffix, ab_other_suffix));
|
||||
|
||||
bool verification_disabled = false;
|
||||
VBMetaVerifyResult verify_result;
|
||||
auto vbmeta = LoadAndVerifyVbmetaByPath(
|
||||
image_path, partition_name, expected_public_key_blob, allow_verification_error,
|
||||
rollback_protection, is_chained_vbmeta, &verification_disabled, &verify_result);
|
||||
|
||||
if (!vbmeta) {
|
||||
return VBMetaVerifyResult::kError;
|
||||
}
|
||||
if (out_vbmeta_images) {
|
||||
out_vbmeta_images->emplace_back(std::move(*vbmeta));
|
||||
}
|
||||
|
||||
// If verification has been disabled by setting a bit in the image, we're done.
|
||||
if (vbmeta_header->flags & AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED) {
|
||||
LWARNING << "VERIFICATION_DISABLED bit is set for partition: " << partition_name;
|
||||
return verify_result;
|
||||
}
|
||||
|
||||
if (load_chained_vbmeta) {
|
||||
// Only loads chained vbmeta if AVB verification is NOT disabled.
|
||||
if (!verification_disabled && load_chained_vbmeta) {
|
||||
bool fatal_error = false;
|
||||
auto chain_partitions = GetChainPartitionInfo(*out_vbmeta_images->rbegin(), &fatal_error);
|
||||
if (fatal_error) {
|
||||
return VBMetaVerifyResult::kError;
|
||||
}
|
||||
for (auto& chain : chain_partitions) {
|
||||
auto sub_ret = LoadAndVerifyVbmetaImpl(
|
||||
chain.partition_name, ab_suffix, ab_other_suffix, chain.public_key_blob,
|
||||
allow_verification_error, load_chained_vbmeta, rollback_protection,
|
||||
device_path_constructor, true, /* is_chained_vbmeta */
|
||||
out_vbmeta_images);
|
||||
auto sub_ret = LoadAndVerifyVbmetaByPartition(
|
||||
chain.partition_name, ab_suffix, ab_other_suffix, chain.public_key_blob,
|
||||
allow_verification_error, load_chained_vbmeta, rollback_protection,
|
||||
device_path_constructor, true, /* is_chained_vbmeta */
|
||||
out_vbmeta_images);
|
||||
if (sub_ret != VBMetaVerifyResult::kSuccess) {
|
||||
verify_result = sub_ret; // might be 'ERROR' or 'ERROR VERIFICATION'.
|
||||
if (verify_result == VBMetaVerifyResult::kError) {
|
||||
|
|
|
|||
|
|
@ -46,10 +46,9 @@ struct ChainInfo {
|
|||
};
|
||||
|
||||
// AvbHashtreeDescriptor to dm-verity table setup.
|
||||
bool GetHashtreeDescriptor(const std::string& partition_name,
|
||||
const std::vector<VBMetaData>& vbmeta_images,
|
||||
AvbHashtreeDescriptor* out_hashtree_desc, std::string* out_salt,
|
||||
std::string* out_digest);
|
||||
std::unique_ptr<AvbHashtreeDescriptor> GetHashtreeDescriptor(
|
||||
const std::string& partition_name, const std::vector<VBMetaData>& vbmeta_images,
|
||||
std::string* out_salt, std::string* out_digest);
|
||||
|
||||
bool ConstructVerityTable(const AvbHashtreeDescriptor& hashtree_desc, const std::string& salt,
|
||||
const std::string& root_digest, const std::string& blk_device,
|
||||
|
|
@ -59,11 +58,20 @@ bool HashtreeDmVeritySetup(FstabEntry* fstab_entry, const AvbHashtreeDescriptor&
|
|||
const std::string& salt, const std::string& root_digest,
|
||||
bool wait_for_verity_dev);
|
||||
|
||||
// Maps AVB partition name to a device partition name.
|
||||
// Searches a Avb hashtree descriptor in vbmeta_images for fstab_entry, to enable dm-verity.
|
||||
bool LoadAvbHashtreeToEnableVerity(FstabEntry* fstab_entry, bool wait_for_verity_dev,
|
||||
const std::vector<VBMetaData>& vbmeta_images,
|
||||
const std::string& ab_suffix, const std::string& ab_other_suffix);
|
||||
|
||||
// Converts AVB partition name to a device partition name.
|
||||
std::string AvbPartitionToDevicePatition(const std::string& avb_partition_name,
|
||||
const std::string& ab_suffix,
|
||||
const std::string& ab_other_suffix);
|
||||
|
||||
// Converts by-name symlink to AVB partition name.
|
||||
std::string DeriveAvbPartitionName(const FstabEntry& fstab_entry, const std::string& ab_suffix,
|
||||
const std::string& ab_other_suffix);
|
||||
|
||||
// AvbFooter and AvbMetaImage maninpulations.
|
||||
off64_t GetTotalSize(int fd);
|
||||
|
||||
|
|
@ -84,12 +92,22 @@ bool RollbackDetected(const std::string& partition_name, uint64_t rollback_index
|
|||
// Extracts chain partition info.
|
||||
std::vector<ChainInfo> GetChainPartitionInfo(const VBMetaData& vbmeta, bool* fatal_error);
|
||||
|
||||
VBMetaVerifyResult LoadAndVerifyVbmetaImpl(
|
||||
const std::string& partition_name, const std::string& ab_suffix,
|
||||
const std::string& ab_other_suffix, const std::string& expected_public_key_blob,
|
||||
bool allow_verification_error, bool load_chained_vbmeta, bool rollback_protection,
|
||||
std::function<std::string(const std::string&)> device_path_constructor,
|
||||
bool is_chained_vbmeta, std::vector<VBMetaData>* out_vbmeta_images);
|
||||
// Loads the single vbmeta from a given path.
|
||||
std::unique_ptr<VBMetaData> LoadAndVerifyVbmetaByPath(
|
||||
const std::string& image_path, const std::string& partition_name,
|
||||
const std::string& expected_public_key_blob, bool allow_verification_error,
|
||||
bool rollback_protection, bool is_chained_vbmeta, bool* out_verification_disabled,
|
||||
VBMetaVerifyResult* out_verify_result);
|
||||
|
||||
// Loads the top-level vbmeta and all its chained vbmeta images.
|
||||
// The actual device path is constructed at runtime by:
|
||||
// partition_name, ab_suffix, ab_other_suffix, and device_path_constructor.
|
||||
VBMetaVerifyResult LoadAndVerifyVbmetaByPartition(
|
||||
const std::string& partition_name, const std::string& ab_suffix,
|
||||
const std::string& ab_other_suffix, const std::string& expected_public_key_blob,
|
||||
bool allow_verification_error, bool load_chained_vbmeta, bool rollback_protection,
|
||||
std::function<std::string(const std::string&)> device_path_constructor, bool is_chained_vbmeta,
|
||||
std::vector<VBMetaData>* out_vbmeta_images);
|
||||
|
||||
} // namespace fs_mgr
|
||||
} // namespace android
|
||||
|
|
|
|||
|
|
@ -233,10 +233,10 @@ AvbUniquePtr AvbHandle::LoadAndVerifyVbmeta(
|
|||
|
||||
auto device_path = custom_device_path ? custom_device_path : android_by_name_symlink;
|
||||
|
||||
auto verify_result = LoadAndVerifyVbmetaImpl(
|
||||
partition_name, ab_suffix, ab_other_suffix, expected_key_blob, allow_verification_error,
|
||||
load_chained_vbmeta, rollback_protection, device_path, false,
|
||||
/* is_chained_vbmeta */ &avb_handle->vbmeta_images_);
|
||||
auto verify_result = LoadAndVerifyVbmetaByPartition(
|
||||
partition_name, ab_suffix, ab_other_suffix, expected_key_blob, allow_verification_error,
|
||||
load_chained_vbmeta, rollback_protection, device_path, false,
|
||||
/* is_chained_vbmeta */ &avb_handle->vbmeta_images_);
|
||||
switch (verify_result) {
|
||||
case VBMetaVerifyResult::kSuccess:
|
||||
avb_handle->status_ = AvbHandleStatus::kSuccess;
|
||||
|
|
@ -245,10 +245,16 @@ AvbUniquePtr AvbHandle::LoadAndVerifyVbmeta(
|
|||
avb_handle->status_ = AvbHandleStatus::kVerificationError;
|
||||
break;
|
||||
default:
|
||||
LERROR << "LoadAndVerifyVbmetaImpl failed, result: " << verify_result;
|
||||
LERROR << "LoadAndVerifyVbmetaByPartition failed, result: " << verify_result;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Sanity check here because we have to use vbmeta_images_[0] below.
|
||||
if (avb_handle->vbmeta_images_.size() < 1) {
|
||||
LERROR << "LoadAndVerifyVbmetaByPartition failed, no vbmeta loaded";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Sets the MAJOR.MINOR for init to set it into "ro.boot.avb_version".
|
||||
avb_handle->avb_version_ = StringPrintf("%d.%d", AVB_VERSION_MAJOR, AVB_VERSION_MINOR);
|
||||
|
||||
|
|
@ -377,6 +383,54 @@ AvbUniquePtr AvbHandle::Open() {
|
|||
return avb_handle;
|
||||
}
|
||||
|
||||
AvbHashtreeResult AvbHandle::SetUpStandaloneAvbHashtree(FstabEntry* fstab_entry) {
|
||||
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;
|
||||
}
|
||||
// Use empty key blob, which means no expectation, if allow verification error.
|
||||
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 */, &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, true /* wait_for_verity_dev */, vbmeta_images,
|
||||
fs_mgr_get_slot_suffix(), fs_mgr_get_other_slot_suffix())) {
|
||||
return AvbHashtreeResult::kFail;
|
||||
}
|
||||
|
||||
return AvbHashtreeResult::kSuccess;
|
||||
}
|
||||
|
||||
AvbHashtreeResult AvbHandle::SetUpAvbHashtree(FstabEntry* fstab_entry, bool wait_for_verity_dev) {
|
||||
if (!fstab_entry || status_ == AvbHandleStatus::kUninitialized || vbmeta_images_.size() < 1) {
|
||||
return AvbHashtreeResult::kFail;
|
||||
|
|
@ -388,33 +442,8 @@ AvbHashtreeResult AvbHandle::SetUpAvbHashtree(FstabEntry* fstab_entry, bool wait
|
|||
return AvbHashtreeResult::kDisabled;
|
||||
}
|
||||
|
||||
// Derives partition_name from blk_device to query the corresponding AVB HASHTREE descriptor
|
||||
// to setup dm-verity. The partition_names in AVB descriptors are without A/B suffix.
|
||||
std::string partition_name;
|
||||
if (fstab_entry->fs_mgr_flags.logical) {
|
||||
partition_name = fstab_entry->logical_partition_name;
|
||||
} else {
|
||||
partition_name = Basename(fstab_entry->blk_device);
|
||||
}
|
||||
|
||||
if (fstab_entry->fs_mgr_flags.slot_select) {
|
||||
auto ab_suffix = partition_name.rfind(fs_mgr_get_slot_suffix());
|
||||
if (ab_suffix != std::string::npos) {
|
||||
partition_name.erase(ab_suffix);
|
||||
}
|
||||
}
|
||||
|
||||
AvbHashtreeDescriptor hashtree_descriptor;
|
||||
std::string salt;
|
||||
std::string root_digest;
|
||||
if (!GetHashtreeDescriptor(partition_name, vbmeta_images_, &hashtree_descriptor, &salt,
|
||||
&root_digest)) {
|
||||
return AvbHashtreeResult::kFail;
|
||||
}
|
||||
|
||||
// Converts HASHTREE descriptor to verity_table_params.
|
||||
if (!HashtreeDmVeritySetup(fstab_entry, hashtree_descriptor, salt, root_digest,
|
||||
wait_for_verity_dev)) {
|
||||
if (!LoadAvbHashtreeToEnableVerity(fstab_entry, wait_for_verity_dev, vbmeta_images_,
|
||||
fs_mgr_get_slot_suffix(), fs_mgr_get_other_slot_suffix())) {
|
||||
return AvbHashtreeResult::kFail;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -81,8 +81,15 @@ class VBMetaData {
|
|||
// true to update vbmeta_size_ to the actual size with valid content.
|
||||
std::unique_ptr<AvbVBMetaImageHeader> GetVBMetaHeader(bool update_vbmeta_size = false);
|
||||
|
||||
// Sets the vbmeta_path where we load the vbmeta data. Could be a partition or a file.
|
||||
// e.g.,
|
||||
// - /dev/block/by-name/system_a
|
||||
// - /path/to/system_other.img.
|
||||
void set_vbmeta_path(std::string vbmeta_path) { vbmeta_path_ = std::move(vbmeta_path); }
|
||||
|
||||
// Get methods for each data member.
|
||||
const std::string& partition() const { return partition_name_; }
|
||||
const std::string& vbmeta_path() const { return vbmeta_path_; }
|
||||
uint8_t* data() const { return vbmeta_ptr_.get(); }
|
||||
const size_t& size() const { return vbmeta_size_; }
|
||||
|
||||
|
|
@ -93,6 +100,7 @@ class VBMetaData {
|
|||
std::unique_ptr<uint8_t[]> vbmeta_ptr_;
|
||||
size_t vbmeta_size_;
|
||||
std::string partition_name_;
|
||||
std::string vbmeta_path_;
|
||||
};
|
||||
|
||||
class FsManagerAvbOps;
|
||||
|
|
@ -160,6 +168,9 @@ class AvbHandle {
|
|||
// - kDisabled: hashtree is disabled.
|
||||
AvbHashtreeResult SetUpAvbHashtree(FstabEntry* fstab_entry, bool wait_for_verity_dev);
|
||||
|
||||
// Similar to above, but loads the offline vbmeta from the end of fstab_entry->blk_device.
|
||||
static AvbHashtreeResult SetUpStandaloneAvbHashtree(FstabEntry* fstab_entry);
|
||||
|
||||
const std::string& avb_version() const { return avb_version_; }
|
||||
const VBMetaInfo& vbmeta_info() const { return vbmeta_info_; }
|
||||
AvbHandleStatus status() const { return status_; }
|
||||
|
|
|
|||
|
|
@ -14,20 +14,25 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <endian.h>
|
||||
|
||||
#include <android-base/unique_fd.h>
|
||||
#include <base/files/file_util.h>
|
||||
#include <base/rand_util.h>
|
||||
#include <base/strings/string_util.h>
|
||||
#include <libavb/libavb.h>
|
||||
|
||||
#include "avb_util.h"
|
||||
#include "fs_avb_test_util.h"
|
||||
|
||||
// Target classes or functions to test:
|
||||
using android::fs_mgr::AvbPartitionToDevicePatition;
|
||||
using android::fs_mgr::DeriveAvbPartitionName;
|
||||
using android::fs_mgr::GetAvbFooter;
|
||||
using android::fs_mgr::GetChainPartitionInfo;
|
||||
using android::fs_mgr::GetTotalSize;
|
||||
using android::fs_mgr::LoadAndVerifyVbmetaImpl;
|
||||
using android::fs_mgr::LoadAndVerifyVbmetaByPartition;
|
||||
using android::fs_mgr::LoadAndVerifyVbmetaByPath;
|
||||
using android::fs_mgr::VBMetaData;
|
||||
using android::fs_mgr::VBMetaVerifyResult;
|
||||
using android::fs_mgr::VerifyPublicKeyBlob;
|
||||
|
|
@ -52,8 +57,34 @@ class AvbUtilTest : public BaseFsAvbTest {
|
|||
|
||||
// Loads the content of avb_image_path and comparies it with the content of vbmeta.
|
||||
bool CompareVBMeta(const base::FilePath& avb_image_path, const VBMetaData& expected_vbmeta);
|
||||
|
||||
// Sets the flas in vbmeta header, the image_path could be a vbmeta.img or a system.img.
|
||||
void SetVBMetaFlags(const base::FilePath& image_path, uint32_t flags);
|
||||
};
|
||||
|
||||
void AvbUtilTest::SetVBMetaFlags(const base::FilePath& image_path, uint32_t flags) {
|
||||
if (!base::PathExists(image_path)) return;
|
||||
|
||||
std::string image_file_name = image_path.RemoveExtension().BaseName().value();
|
||||
bool is_vbmeta_partition =
|
||||
base::StartsWith(image_file_name, "vbmeta", base::CompareCase::INSENSITIVE_ASCII);
|
||||
|
||||
android::base::unique_fd fd(open(image_path.value().c_str(), O_RDWR | O_CLOEXEC));
|
||||
EXPECT_TRUE(fd > 0);
|
||||
|
||||
uint64_t vbmeta_offset = 0; // for vbmeta.img
|
||||
if (!is_vbmeta_partition) {
|
||||
std::unique_ptr<AvbFooter> footer = GetAvbFooter(fd);
|
||||
EXPECT_NE(nullptr, footer);
|
||||
vbmeta_offset = footer->vbmeta_offset;
|
||||
}
|
||||
|
||||
auto flags_offset = vbmeta_offset + offsetof(AvbVBMetaImageHeader, flags);
|
||||
uint32_t flags_data = htobe32(flags);
|
||||
EXPECT_EQ(flags_offset, lseek64(fd, flags_offset, SEEK_SET));
|
||||
EXPECT_EQ(sizeof flags_data, write(fd, &flags_data, sizeof flags_data));
|
||||
}
|
||||
|
||||
TEST_F(AvbUtilTest, AvbPartitionToDevicePatition) {
|
||||
EXPECT_EQ("system", AvbPartitionToDevicePatition("system", "", ""));
|
||||
EXPECT_EQ("system", AvbPartitionToDevicePatition("system", "", "_b"));
|
||||
|
|
@ -65,6 +96,63 @@ TEST_F(AvbUtilTest, AvbPartitionToDevicePatition) {
|
|||
EXPECT_EQ("system_b", AvbPartitionToDevicePatition("system_other", "_a", "_b"));
|
||||
}
|
||||
|
||||
TEST_F(AvbUtilTest, DeriveAvbPartitionName) {
|
||||
// The fstab_entry to test.
|
||||
FstabEntry fstab_entry = {
|
||||
.blk_device = "/dev/block/dm-1", // a dm-linear device (logical)
|
||||
.mount_point = "/system",
|
||||
.fs_type = "ext4",
|
||||
.logical_partition_name = "system",
|
||||
};
|
||||
|
||||
// Logical partitions.
|
||||
// non-A/B
|
||||
fstab_entry.fs_mgr_flags.logical = true;
|
||||
EXPECT_EQ("system", DeriveAvbPartitionName(fstab_entry, "_dont_care", "_dont_care"));
|
||||
EXPECT_EQ("system", DeriveAvbPartitionName(fstab_entry, "_a", "_b"));
|
||||
EXPECT_EQ("system", DeriveAvbPartitionName(fstab_entry, "", ""));
|
||||
// Active slot.
|
||||
fstab_entry.fs_mgr_flags.slot_select = true;
|
||||
fstab_entry.logical_partition_name = "system_a";
|
||||
EXPECT_EQ("system", DeriveAvbPartitionName(fstab_entry, "_a", "_dont_care"));
|
||||
EXPECT_EQ("system", DeriveAvbPartitionName(fstab_entry, "_a", "_b"));
|
||||
EXPECT_EQ("system", DeriveAvbPartitionName(fstab_entry, "_a", ""));
|
||||
EXPECT_EQ("system_a", DeriveAvbPartitionName(fstab_entry, "_wont_erase_a", "_dont_care"));
|
||||
// The other slot.
|
||||
fstab_entry.fs_mgr_flags.slot_select = false;
|
||||
fstab_entry.fs_mgr_flags.slot_select_other = true;
|
||||
fstab_entry.logical_partition_name = "system_b";
|
||||
EXPECT_EQ("system_other", DeriveAvbPartitionName(fstab_entry, "_dont_care", "_b"));
|
||||
EXPECT_EQ("system_other", DeriveAvbPartitionName(fstab_entry, "_a", "_b"));
|
||||
EXPECT_EQ("system_other", DeriveAvbPartitionName(fstab_entry, "", "_b"));
|
||||
EXPECT_EQ("system_b_other", DeriveAvbPartitionName(fstab_entry, "_dont_care", "_wont_erase_b"));
|
||||
|
||||
// Non-logical partitions.
|
||||
// non-A/B.
|
||||
fstab_entry.fs_mgr_flags.logical = false;
|
||||
fstab_entry.fs_mgr_flags.slot_select = false;
|
||||
fstab_entry.fs_mgr_flags.slot_select_other = false;
|
||||
fstab_entry.blk_device = "/dev/block/by-name/system";
|
||||
EXPECT_EQ("system", DeriveAvbPartitionName(fstab_entry, "_dont_care", "_dont_care"));
|
||||
EXPECT_EQ("system", DeriveAvbPartitionName(fstab_entry, "_a", "_b"));
|
||||
EXPECT_EQ("system", DeriveAvbPartitionName(fstab_entry, "", ""));
|
||||
// Active slot _a.
|
||||
fstab_entry.fs_mgr_flags.slot_select = true;
|
||||
fstab_entry.blk_device = "/dev/block/by-name/system_a";
|
||||
EXPECT_EQ("system", DeriveAvbPartitionName(fstab_entry, "_a", "_dont_care"));
|
||||
EXPECT_EQ("system", DeriveAvbPartitionName(fstab_entry, "_a", "_b"));
|
||||
EXPECT_EQ("system", DeriveAvbPartitionName(fstab_entry, "_a", ""));
|
||||
EXPECT_EQ("system_a", DeriveAvbPartitionName(fstab_entry, "_wont_erase_a", "_dont_care"));
|
||||
// Inactive slot _b.
|
||||
fstab_entry.fs_mgr_flags.slot_select = false;
|
||||
fstab_entry.fs_mgr_flags.slot_select_other = true;
|
||||
fstab_entry.blk_device = "/dev/block/by-name/system_b";
|
||||
EXPECT_EQ("system_other", DeriveAvbPartitionName(fstab_entry, "dont_care", "_b"));
|
||||
EXPECT_EQ("system_other", DeriveAvbPartitionName(fstab_entry, "_a", "_b"));
|
||||
EXPECT_EQ("system_other", DeriveAvbPartitionName(fstab_entry, "", "_b"));
|
||||
EXPECT_EQ("system_b_other", DeriveAvbPartitionName(fstab_entry, "dont_care", "_wont_erase_b"));
|
||||
}
|
||||
|
||||
TEST_F(AvbUtilTest, GetFdTotalSize) {
|
||||
// Generates a raw test.img via BaseFsAvbTest.
|
||||
const size_t image_size = 5 * 1024 * 1024;
|
||||
|
|
@ -751,7 +839,213 @@ TEST_F(AvbUtilTest, GetChainPartitionInfoNone) {
|
|||
EXPECT_EQ(false, fatal_error);
|
||||
}
|
||||
|
||||
TEST_F(AvbUtilTest, LoadAndVerifyVbmetaImpl) {
|
||||
TEST_F(AvbUtilTest, LoadAndVerifyVbmetaByPath) {
|
||||
// Generates a raw system_other.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_other.img", system_image_size);
|
||||
|
||||
// Adds AVB Hashtree Footer.
|
||||
AddAvbFooter(system_path, "hashtree", "system_other", system_partition_size, "SHA512_RSA4096",
|
||||
20, data_dir_.Append("testkey_rsa4096.pem"), "d00df00d",
|
||||
"--internal_release_string \"unit test\"");
|
||||
|
||||
base::FilePath rsa4096_public_key =
|
||||
ExtractPublicKeyAvb(data_dir_.Append("testkey_rsa4096.pem"));
|
||||
|
||||
std::string expected_key_blob_4096;
|
||||
EXPECT_TRUE(base::ReadFileToString(rsa4096_public_key, &expected_key_blob_4096));
|
||||
|
||||
bool verification_disabled;
|
||||
VBMetaVerifyResult verify_result;
|
||||
std::unique_ptr<VBMetaData> vbmeta = LoadAndVerifyVbmetaByPath(
|
||||
system_path.value(), "system_other", expected_key_blob_4096,
|
||||
false /* allow_verification_error */, false /* rollback_protection */,
|
||||
false /* is_chained_vbmeta */, &verification_disabled, &verify_result);
|
||||
|
||||
EXPECT_NE(nullptr, vbmeta);
|
||||
EXPECT_EQ(VBMetaVerifyResult::kSuccess, verify_result);
|
||||
EXPECT_EQ(false, verification_disabled);
|
||||
|
||||
EXPECT_EQ(2112UL, vbmeta->size());
|
||||
EXPECT_EQ(system_path.value(), vbmeta->vbmeta_path());
|
||||
EXPECT_EQ("system_other", vbmeta->partition());
|
||||
EXPECT_TRUE(CompareVBMeta(system_path, *vbmeta));
|
||||
}
|
||||
|
||||
TEST_F(AvbUtilTest, LoadAndVerifyVbmetaByPathErrorVerification) {
|
||||
// Generates a raw system_other.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_other.img", system_image_size);
|
||||
|
||||
// Adds AVB Hashtree Footer.
|
||||
AddAvbFooter(system_path, "hashtree", "system_other", system_partition_size, "SHA512_RSA4096",
|
||||
20, data_dir_.Append("testkey_rsa4096.pem"), "d00df00d",
|
||||
"--internal_release_string \"unit test\"");
|
||||
|
||||
base::FilePath rsa4096_public_key =
|
||||
ExtractPublicKeyAvb(data_dir_.Append("testkey_rsa4096.pem"));
|
||||
|
||||
std::string expected_key_blob_4096;
|
||||
EXPECT_TRUE(base::ReadFileToString(rsa4096_public_key, &expected_key_blob_4096));
|
||||
|
||||
// Modifies the auxiliary data of system_other.img
|
||||
auto fd = OpenUniqueReadFd(system_path);
|
||||
auto system_footer = GetAvbFooter(fd);
|
||||
auto system_vbmeta = ExtractAndLoadVBMetaData(system_path, "system_other-vbmeta.img");
|
||||
auto system_header = system_vbmeta.GetVBMetaHeader(true /* update_vbmeta_size */);
|
||||
size_t header_block_offset = 0;
|
||||
size_t authentication_block_offset = header_block_offset + sizeof(AvbVBMetaImageHeader);
|
||||
size_t auxiliary_block_offset =
|
||||
authentication_block_offset + system_header->authentication_data_block_size;
|
||||
|
||||
// Modifies the hash.
|
||||
ModifyFile(
|
||||
system_path,
|
||||
(system_footer->vbmeta_offset + authentication_block_offset + system_header->hash_offset),
|
||||
system_header->hash_size);
|
||||
|
||||
VBMetaVerifyResult verify_result;
|
||||
// Not allow verification error.
|
||||
std::unique_ptr<VBMetaData> vbmeta = LoadAndVerifyVbmetaByPath(
|
||||
system_path.value(), "system_other", expected_key_blob_4096,
|
||||
false /* allow_verification_error */, false /* rollback_protection */,
|
||||
false /* is_chained_vbmeta */, nullptr /* verification_disabled */, &verify_result);
|
||||
EXPECT_EQ(nullptr, vbmeta);
|
||||
|
||||
// Allow verification error.
|
||||
vbmeta = LoadAndVerifyVbmetaByPath(
|
||||
system_path.value(), "system_other", expected_key_blob_4096,
|
||||
true /* allow_verification_error */, false /* rollback_protection */,
|
||||
false /* is_chained_vbmeta */, nullptr /* verification_disabled */, &verify_result);
|
||||
EXPECT_NE(nullptr, vbmeta);
|
||||
EXPECT_EQ(VBMetaVerifyResult::kErrorVerification, verify_result);
|
||||
|
||||
EXPECT_EQ(2112UL, vbmeta->size());
|
||||
EXPECT_EQ(system_path.value(), vbmeta->vbmeta_path());
|
||||
EXPECT_EQ("system_other", vbmeta->partition());
|
||||
EXPECT_TRUE(CompareVBMeta(system_path, *vbmeta));
|
||||
|
||||
// Modifies the auxiliary data block.
|
||||
ModifyFile(system_path, system_footer->vbmeta_offset + auxiliary_block_offset,
|
||||
system_header->auxiliary_data_block_size);
|
||||
|
||||
// Not allow verification error.
|
||||
vbmeta = LoadAndVerifyVbmetaByPath(
|
||||
system_path.value(), "system_other", expected_key_blob_4096,
|
||||
false /* allow_verification_error */, false /* rollback_protection */,
|
||||
false /* is_chained_vbmeta */, nullptr /* verification_disabled */, &verify_result);
|
||||
EXPECT_EQ(nullptr, vbmeta);
|
||||
|
||||
// Allow verification error.
|
||||
vbmeta = LoadAndVerifyVbmetaByPath(
|
||||
system_path.value(), "system_other", expected_key_blob_4096,
|
||||
true /* allow_verification_error */, false /* rollback_protection */,
|
||||
false /* is_chained_vbmeta */, nullptr /* verification_disabled */, &verify_result);
|
||||
EXPECT_NE(nullptr, vbmeta);
|
||||
EXPECT_EQ(VBMetaVerifyResult::kErrorVerification, verify_result);
|
||||
}
|
||||
|
||||
TEST_F(AvbUtilTest, LoadAndVerifyVbmetaByPathUnexpectedPublicKey) {
|
||||
// Generates a raw system_other.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_other.img", system_image_size);
|
||||
|
||||
// Adds AVB Hashtree Footer.
|
||||
AddAvbFooter(system_path, "hashtree", "system_other", system_partition_size, "SHA512_RSA4096",
|
||||
20, data_dir_.Append("testkey_rsa4096.pem"), "d00df00d",
|
||||
"--internal_release_string \"unit test\"");
|
||||
|
||||
base::FilePath rsa2048_public_key =
|
||||
ExtractPublicKeyAvb(data_dir_.Append("testkey_rsa2048.pem"));
|
||||
base::FilePath rsa4096_public_key =
|
||||
ExtractPublicKeyAvb(data_dir_.Append("testkey_rsa4096.pem"));
|
||||
|
||||
std::string expected_key_blob_4096;
|
||||
EXPECT_TRUE(base::ReadFileToString(rsa4096_public_key, &expected_key_blob_4096));
|
||||
std::string unexpected_key_blob_2048;
|
||||
EXPECT_TRUE(base::ReadFileToString(rsa2048_public_key, &unexpected_key_blob_2048));
|
||||
|
||||
// Uses the correct expected public key.
|
||||
VBMetaVerifyResult verify_result;
|
||||
std::unique_ptr<VBMetaData> vbmeta = LoadAndVerifyVbmetaByPath(
|
||||
system_path.value(), "system_other", expected_key_blob_4096,
|
||||
false /* allow_verification_error */, false /* rollback_protection */,
|
||||
false /* is_chained_vbmeta */, nullptr /* verification_disabled */, &verify_result);
|
||||
EXPECT_NE(nullptr, vbmeta);
|
||||
EXPECT_EQ(verify_result, VBMetaVerifyResult::kSuccess);
|
||||
EXPECT_EQ(2112UL, vbmeta->size());
|
||||
EXPECT_EQ(system_path.value(), vbmeta->vbmeta_path());
|
||||
EXPECT_EQ("system_other", vbmeta->partition());
|
||||
EXPECT_TRUE(CompareVBMeta(system_path, *vbmeta));
|
||||
|
||||
// Uses the wrong expected public key with allow_verification_error set to false.
|
||||
vbmeta = LoadAndVerifyVbmetaByPath(
|
||||
system_path.value(), "system_other", unexpected_key_blob_2048,
|
||||
false /* allow_verification_error */, false /* rollback_protection */,
|
||||
false /* is_chained_vbmeta */, nullptr /* verification_disabled */, &verify_result);
|
||||
EXPECT_EQ(nullptr, vbmeta);
|
||||
|
||||
// Uses the wrong expected public key with allow_verification_error set to true.
|
||||
vbmeta = LoadAndVerifyVbmetaByPath(
|
||||
system_path.value(), "system_other", unexpected_key_blob_2048,
|
||||
true /* allow_verification_error */, false /* rollback_protection */,
|
||||
false /* is_chained_vbmeta */, nullptr /* verification_disabled */, &verify_result);
|
||||
EXPECT_NE(nullptr, vbmeta);
|
||||
EXPECT_EQ(verify_result, VBMetaVerifyResult::kErrorVerification);
|
||||
EXPECT_EQ(2112UL, vbmeta->size());
|
||||
EXPECT_EQ(system_path.value(), vbmeta->vbmeta_path());
|
||||
EXPECT_EQ("system_other", vbmeta->partition());
|
||||
EXPECT_TRUE(CompareVBMeta(system_path, *vbmeta));
|
||||
}
|
||||
|
||||
TEST_F(AvbUtilTest, LoadAndVerifyVbmetaByPathVerificationDisabled) {
|
||||
// Generates a raw system_other.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_other.img", system_image_size);
|
||||
|
||||
// Adds AVB Hashtree Footer.
|
||||
AddAvbFooter(system_path, "hashtree", "system_other", system_partition_size, "SHA512_RSA4096",
|
||||
20, data_dir_.Append("testkey_rsa4096.pem"), "d00df00d",
|
||||
"--internal_release_string \"unit test\"");
|
||||
|
||||
base::FilePath rsa4096_public_key =
|
||||
ExtractPublicKeyAvb(data_dir_.Append("testkey_rsa4096.pem"));
|
||||
|
||||
std::string expected_key_blob_4096;
|
||||
EXPECT_TRUE(base::ReadFileToString(rsa4096_public_key, &expected_key_blob_4096));
|
||||
|
||||
// Sets disabled flag and expect the returned verification_disabled is true.
|
||||
SetVBMetaFlags(system_path, AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED);
|
||||
bool verification_disabled;
|
||||
VBMetaVerifyResult verify_result;
|
||||
std::unique_ptr<VBMetaData> vbmeta = LoadAndVerifyVbmetaByPath(
|
||||
system_path.value(), "system_other", expected_key_blob_4096,
|
||||
true /* allow_verification_error */, false /* rollback_protection */,
|
||||
false /* is_chained_vbmeta */, &verification_disabled, &verify_result);
|
||||
|
||||
EXPECT_NE(nullptr, vbmeta);
|
||||
EXPECT_EQ(VBMetaVerifyResult::kErrorVerification, verify_result);
|
||||
EXPECT_EQ(true, verification_disabled); // should be true.
|
||||
|
||||
EXPECT_EQ(2112UL, vbmeta->size());
|
||||
EXPECT_EQ(system_path.value(), vbmeta->vbmeta_path());
|
||||
EXPECT_EQ("system_other", vbmeta->partition());
|
||||
EXPECT_TRUE(CompareVBMeta(system_path, *vbmeta));
|
||||
|
||||
// Since the vbmeta flags is modified, vbmeta will be nullptr
|
||||
// if verification error isn't allowed.
|
||||
vbmeta = LoadAndVerifyVbmetaByPath(
|
||||
system_path.value(), "system_other", expected_key_blob_4096,
|
||||
false /* allow_verification_error */, false /* rollback_protection */,
|
||||
false /* is_chained_vbmeta */, &verification_disabled, &verify_result);
|
||||
EXPECT_EQ(nullptr, vbmeta);
|
||||
}
|
||||
|
||||
TEST_F(AvbUtilTest, LoadAndVerifyVbmetaByPartition) {
|
||||
// Generates a raw boot.img
|
||||
const size_t boot_image_size = 5 * 1024 * 1024;
|
||||
const size_t boot_partition_size = 10 * 1024 * 1024;
|
||||
|
|
@ -795,18 +1089,18 @@ TEST_F(AvbUtilTest, LoadAndVerifyVbmetaImpl) {
|
|||
EXPECT_EQ("6f4bf815a651aa35ec7102a88b7906b91aef284bc5e20d0bf527c7d460da3266",
|
||||
CalcVBMetaDigest("vbmeta.img", "sha256"));
|
||||
|
||||
// Starts to test LoadAndVerifyVbmetaImpl.
|
||||
// Starts to test LoadAndVerifyVbmetaByPartition.
|
||||
std::vector<VBMetaData> vbmeta_images;
|
||||
auto vbmeta_image_path = [this](const std::string& partition_name) {
|
||||
return test_dir_.Append(partition_name + ".img").value();
|
||||
};
|
||||
|
||||
EXPECT_EQ(VBMetaVerifyResult::kSuccess,
|
||||
LoadAndVerifyVbmetaImpl(
|
||||
"vbmeta" /* partition_name */, "" /* ab_suffix */, "" /* other_suffix */,
|
||||
"" /* expected_public_key_blob*/, false /* allow_verification_error */,
|
||||
true /* load_chained_vbmeta */, true /* rollback_protection */,
|
||||
vbmeta_image_path, false /* is_chained_vbmeta*/, &vbmeta_images));
|
||||
LoadAndVerifyVbmetaByPartition(
|
||||
"vbmeta" /* partition_name */, "" /* ab_suffix */, "" /* other_suffix */,
|
||||
"" /* expected_public_key_blob*/, false /* allow_verification_error */,
|
||||
true /* load_chained_vbmeta */, true /* rollback_protection */, vbmeta_image_path,
|
||||
false /* is_chained_vbmeta*/, &vbmeta_images));
|
||||
|
||||
EXPECT_EQ(4UL, vbmeta_images.size()); // vbmeta, boot, vbmeta_system and system
|
||||
// Binary comparison for each vbmeta image.
|
||||
|
|
@ -818,17 +1112,17 @@ TEST_F(AvbUtilTest, LoadAndVerifyVbmetaImpl) {
|
|||
// Skip loading chained vbmeta images.
|
||||
vbmeta_images.clear();
|
||||
EXPECT_EQ(VBMetaVerifyResult::kSuccess,
|
||||
LoadAndVerifyVbmetaImpl(
|
||||
"vbmeta" /* partition_name */, "" /* ab_suffix */, "" /* other_suffix */,
|
||||
"" /* expected_public_key_blob*/, false /* allow_verification_error */,
|
||||
false /* load_chained_vbmeta */, true /* rollback_protection */,
|
||||
vbmeta_image_path, false /* is_chained_vbmeta*/, &vbmeta_images));
|
||||
LoadAndVerifyVbmetaByPartition(
|
||||
"vbmeta" /* partition_name */, "" /* ab_suffix */, "" /* other_suffix */,
|
||||
"" /* expected_public_key_blob*/, false /* allow_verification_error */,
|
||||
false /* load_chained_vbmeta */, true /* rollback_protection */,
|
||||
vbmeta_image_path, false /* is_chained_vbmeta*/, &vbmeta_images));
|
||||
// Only vbmeta is loaded.
|
||||
EXPECT_EQ(1UL, vbmeta_images.size());
|
||||
EXPECT_TRUE(CompareVBMeta(vbmeta_path, vbmeta_images[0]));
|
||||
}
|
||||
|
||||
TEST_F(AvbUtilTest, LoadAndVerifyVbmetaImplWithSuffixes) {
|
||||
TEST_F(AvbUtilTest, LoadAndVerifyVbmetaByPartitionWithSuffixes) {
|
||||
// Tests the following chained partitions.
|
||||
// vbmeta_a.img
|
||||
// |--> boot_b.img (boot_other)
|
||||
|
|
@ -874,18 +1168,18 @@ TEST_F(AvbUtilTest, LoadAndVerifyVbmetaImplWithSuffixes) {
|
|||
{"vbmeta_system_other", 2, rsa4096_public_key}},
|
||||
"--internal_release_string \"unit test\"");
|
||||
|
||||
// Starts to test LoadAndVerifyVbmetaImpl with ab_suffix and ab_other_suffix.
|
||||
// Starts to test LoadAndVerifyVbmetaByPartition with ab_suffix and ab_other_suffix.
|
||||
auto vbmeta_image_path = [this](const std::string& partition_name) {
|
||||
return test_dir_.Append(partition_name + ".img").value();
|
||||
};
|
||||
|
||||
std::vector<VBMetaData> vbmeta_images;
|
||||
EXPECT_EQ(VBMetaVerifyResult::kSuccess,
|
||||
LoadAndVerifyVbmetaImpl(
|
||||
"vbmeta" /* partition_name */, "_a" /* ab_suffix */, "_b" /* other_suffix */,
|
||||
"" /* expected_public_key_blob*/, false /* allow_verification_error */,
|
||||
true /* load_chained_vbmeta */, true /* rollback_protection */,
|
||||
vbmeta_image_path, false /* is_chained_vbmeta*/, &vbmeta_images));
|
||||
LoadAndVerifyVbmetaByPartition(
|
||||
"vbmeta" /* partition_name */, "_a" /* ab_suffix */, "_b" /* other_suffix */,
|
||||
"" /* expected_public_key_blob*/, false /* allow_verification_error */,
|
||||
true /* load_chained_vbmeta */, true /* rollback_protection */, vbmeta_image_path,
|
||||
false /* is_chained_vbmeta*/, &vbmeta_images));
|
||||
|
||||
EXPECT_EQ(4UL, vbmeta_images.size()); // vbmeta, boot_other, vbmeta_system_other and system
|
||||
// Binary comparison for each vbmeta image.
|
||||
|
|
@ -897,26 +1191,26 @@ TEST_F(AvbUtilTest, LoadAndVerifyVbmetaImplWithSuffixes) {
|
|||
// Skips loading chained vbmeta images.
|
||||
vbmeta_images.clear();
|
||||
EXPECT_EQ(VBMetaVerifyResult::kSuccess,
|
||||
LoadAndVerifyVbmetaImpl(
|
||||
"vbmeta" /* partition_name */, "_a" /* ab_suffix */, "_b" /* other_suffix */,
|
||||
"" /* expected_public_key_blob*/, false /* allow_verification_error */,
|
||||
false /* load_chained_vbmeta */, true /* rollback_protection */,
|
||||
vbmeta_image_path, false /* is_chained_vbmeta*/, &vbmeta_images));
|
||||
LoadAndVerifyVbmetaByPartition(
|
||||
"vbmeta" /* partition_name */, "_a" /* ab_suffix */, "_b" /* other_suffix */,
|
||||
"" /* expected_public_key_blob*/, false /* allow_verification_error */,
|
||||
false /* load_chained_vbmeta */, true /* rollback_protection */,
|
||||
vbmeta_image_path, false /* is_chained_vbmeta*/, &vbmeta_images));
|
||||
// Only vbmeta is loaded.
|
||||
EXPECT_EQ(1UL, vbmeta_images.size());
|
||||
EXPECT_TRUE(CompareVBMeta(vbmeta_path, vbmeta_images[0]));
|
||||
|
||||
// Using an invalid suffix for 'other' slot, checks it returns error.
|
||||
EXPECT_EQ(VBMetaVerifyResult::kError,
|
||||
LoadAndVerifyVbmetaImpl(
|
||||
"vbmeta" /* partition_name */, "_a" /* ab_suffix */,
|
||||
"_invalid_suffix" /* other_suffix */, "" /* expected_public_key_blob*/,
|
||||
false /* allow_verification_error */, true /* load_chained_vbmeta */,
|
||||
true /* rollback_protection */, vbmeta_image_path,
|
||||
false /* is_chained_vbmeta*/, &vbmeta_images));
|
||||
LoadAndVerifyVbmetaByPartition(
|
||||
"vbmeta" /* partition_name */, "_a" /* ab_suffix */,
|
||||
"_invalid_suffix" /* other_suffix */, "" /* expected_public_key_blob*/,
|
||||
false /* allow_verification_error */, true /* load_chained_vbmeta */,
|
||||
true /* rollback_protection */, vbmeta_image_path, false /* is_chained_vbmeta*/,
|
||||
&vbmeta_images));
|
||||
}
|
||||
|
||||
TEST_F(AvbUtilTest, LoadAndVerifyVbmetaImplErrorVerification) {
|
||||
TEST_F(AvbUtilTest, LoadAndVerifyVbmetaByPartitionErrorVerification) {
|
||||
// Generates a raw boot.img
|
||||
const size_t boot_image_size = 5 * 1024 * 1024;
|
||||
const size_t boot_partition_size = 10 * 1024 * 1024;
|
||||
|
|
@ -964,27 +1258,27 @@ TEST_F(AvbUtilTest, LoadAndVerifyVbmetaImplErrorVerification) {
|
|||
// Modifies the hash.
|
||||
ModifyFile(vbmeta_path, authentication_block_offset + header->hash_offset, header->hash_size);
|
||||
|
||||
// Starts to test LoadAndVerifyVbmetaImpl.
|
||||
// Starts to test LoadAndVerifyVbmetaByPartition.
|
||||
std::vector<VBMetaData> vbmeta_images;
|
||||
auto vbmeta_image_path = [this](const std::string& partition_name) {
|
||||
return test_dir_.Append(partition_name + ".img").value();
|
||||
};
|
||||
EXPECT_EQ(VBMetaVerifyResult::kError,
|
||||
LoadAndVerifyVbmetaImpl(
|
||||
"vbmeta" /* partition_name */, "" /* ab_suffix */, "" /* other_suffix */,
|
||||
"" /* expected_public_key_blob*/, false /* allow_verification_error */,
|
||||
true /* load_chained_vbmeta */, true /* rollback_protection */,
|
||||
vbmeta_image_path, false /* is_chained_vbmeta*/, &vbmeta_images));
|
||||
LoadAndVerifyVbmetaByPartition(
|
||||
"vbmeta" /* partition_name */, "" /* ab_suffix */, "" /* other_suffix */,
|
||||
"" /* expected_public_key_blob*/, false /* allow_verification_error */,
|
||||
true /* load_chained_vbmeta */, true /* rollback_protection */, vbmeta_image_path,
|
||||
false /* is_chained_vbmeta*/, &vbmeta_images));
|
||||
// Stops to load vbmeta because the top-level vbmeta has verification error.
|
||||
EXPECT_EQ(0UL, vbmeta_images.size());
|
||||
|
||||
// Tries again with verification error allowed.
|
||||
EXPECT_EQ(VBMetaVerifyResult::kErrorVerification,
|
||||
LoadAndVerifyVbmetaImpl(
|
||||
"vbmeta" /* partition_name */, "" /* ab_suffix */, "", /* other_suffix */
|
||||
"" /* expected_public_key_blob*/, true /* allow_verification_error */,
|
||||
true /* load_chained_vbmeta */, true /* rollback_protection */,
|
||||
vbmeta_image_path, false /* is_chained_vbmeta*/, &vbmeta_images));
|
||||
LoadAndVerifyVbmetaByPartition(
|
||||
"vbmeta" /* partition_name */, "" /* ab_suffix */, "", /* other_suffix */
|
||||
"" /* expected_public_key_blob*/, true /* allow_verification_error */,
|
||||
true /* load_chained_vbmeta */, true /* rollback_protection */, vbmeta_image_path,
|
||||
false /* is_chained_vbmeta*/, &vbmeta_images));
|
||||
|
||||
EXPECT_EQ(3UL, vbmeta_images.size()); // vbmeta, boot, and system
|
||||
// Binary comparison for each vbmeta image.
|
||||
|
|
@ -1008,11 +1302,11 @@ TEST_F(AvbUtilTest, LoadAndVerifyVbmetaImplErrorVerification) {
|
|||
system_header->auxiliary_data_block_size);
|
||||
vbmeta_images.clear();
|
||||
EXPECT_EQ(VBMetaVerifyResult::kError,
|
||||
LoadAndVerifyVbmetaImpl(
|
||||
"vbmeta" /* partition_name */, "" /* ab_suffix */, "" /* other_suffix */,
|
||||
"" /* expected_public_key_blob*/, false /* allow_verification_error */,
|
||||
true /* load_chained_vbmeta */, true /* rollback_protection */,
|
||||
vbmeta_image_path, false /* is_chained_vbmeta*/, &vbmeta_images));
|
||||
LoadAndVerifyVbmetaByPartition(
|
||||
"vbmeta" /* partition_name */, "" /* ab_suffix */, "" /* other_suffix */,
|
||||
"" /* expected_public_key_blob*/, false /* allow_verification_error */,
|
||||
true /* load_chained_vbmeta */, true /* rollback_protection */, vbmeta_image_path,
|
||||
false /* is_chained_vbmeta*/, &vbmeta_images));
|
||||
// 'vbmeta', 'boot' but no 'system', because of verification error.
|
||||
EXPECT_EQ(2UL, vbmeta_images.size());
|
||||
// Binary comparison for the loaded 'vbmeta' and 'boot'.
|
||||
|
|
@ -1020,20 +1314,113 @@ TEST_F(AvbUtilTest, LoadAndVerifyVbmetaImplErrorVerification) {
|
|||
EXPECT_TRUE(CompareVBMeta(boot_path, vbmeta_images[1]));
|
||||
|
||||
// Resets the modification of the auxiliary data.
|
||||
ModifyFile(vbmeta_path, 0 /* offset */, -1 /* length */);
|
||||
ModifyFile(system_path, 0 /* offset */, -1 /* length */);
|
||||
|
||||
// Sets the vbmeta header flags on a chained partition, which introduces an error.
|
||||
ModifyFile(system_path, system_footer->vbmeta_offset + offsetof(AvbVBMetaImageHeader, flags),
|
||||
sizeof(uint32_t));
|
||||
EXPECT_EQ(VBMetaVerifyResult::kError,
|
||||
LoadAndVerifyVbmetaImpl(
|
||||
"vbmeta" /* partition_name */, "" /* ab_suffix */, "" /* other_suffix */,
|
||||
"" /* expected_public_key_blob*/, true /* allow_verification_error */,
|
||||
true /* load_chained_vbmeta */, true /* rollback_protection */,
|
||||
vbmeta_image_path, false /* is_chained_vbmeta*/, &vbmeta_images));
|
||||
LoadAndVerifyVbmetaByPartition(
|
||||
"vbmeta" /* partition_name */, "" /* ab_suffix */, "" /* other_suffix */,
|
||||
"" /* expected_public_key_blob*/, true /* allow_verification_error */,
|
||||
true /* load_chained_vbmeta */, true /* rollback_protection */, vbmeta_image_path,
|
||||
false /* is_chained_vbmeta*/, &vbmeta_images));
|
||||
}
|
||||
|
||||
TEST_F(AvbUtilTest, LoadAndVerifyVbmetaImplUnexpectedPublicKey) {
|
||||
TEST_F(AvbUtilTest, LoadAndVerifyVbmetaByPartitionVerificationDisabled) {
|
||||
// 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",
|
||||
"--internal_release_string \"unit test\"");
|
||||
|
||||
// Generates chain partition descriptors.
|
||||
base::FilePath rsa2048_public_key =
|
||||
ExtractPublicKeyAvb(data_dir_.Append("testkey_rsa2048.pem"));
|
||||
base::FilePath rsa4096_public_key =
|
||||
ExtractPublicKeyAvb(data_dir_.Append("testkey_rsa4096.pem"));
|
||||
// Makes a vbmeta_system.img including the 'system' chained descriptor.
|
||||
auto vbmeta_system_path = GenerateVBMetaImage(
|
||||
"vbmeta_system.img", "SHA256_RSA4096", 0, data_dir_.Append("testkey_rsa4096.pem"),
|
||||
{}, /* include_descriptor_image_paths */
|
||||
{{"system", 3, rsa4096_public_key}}, /* chain_partitions */
|
||||
"--internal_release_string \"unit test\"");
|
||||
|
||||
// Makes a vbmeta image includeing 'boot' and 'vbmeta_system' chained descriptors.
|
||||
auto vbmeta_path = GenerateVBMetaImage("vbmeta.img", "SHA256_RSA8192", 0,
|
||||
data_dir_.Append("testkey_rsa8192.pem"),
|
||||
{}, /* include_descriptor_image_paths */
|
||||
{{"boot", 1, rsa2048_public_key}, /* chain_partitions */
|
||||
{"vbmeta_system", 2, rsa4096_public_key}},
|
||||
"--internal_release_string \"unit test\"");
|
||||
|
||||
// Calculates the digest of all chained partitions, to ensure the chained is formed properly.
|
||||
EXPECT_EQ("6f4bf815a651aa35ec7102a88b7906b91aef284bc5e20d0bf527c7d460da3266",
|
||||
CalcVBMetaDigest("vbmeta.img", "sha256"));
|
||||
|
||||
// Starts to test LoadAndVerifyVbmetaByPartition.
|
||||
std::vector<VBMetaData> vbmeta_images;
|
||||
auto vbmeta_image_path = [this](const std::string& partition_name) {
|
||||
return test_dir_.Append(partition_name + ".img").value();
|
||||
};
|
||||
|
||||
EXPECT_EQ(VBMetaVerifyResult::kSuccess,
|
||||
LoadAndVerifyVbmetaByPartition(
|
||||
"vbmeta" /* partition_name */, "" /* ab_suffix */, "" /* other_suffix */,
|
||||
"" /* expected_public_key_blob*/, false /* allow_verification_error */,
|
||||
true /* load_chained_vbmeta */, true /* rollback_protection */, vbmeta_image_path,
|
||||
false /* is_chained_vbmeta*/, &vbmeta_images));
|
||||
|
||||
EXPECT_EQ(4UL, vbmeta_images.size()); // vbmeta, boot, vbmeta_system and system
|
||||
// Binary comparison for each vbmeta image.
|
||||
EXPECT_TRUE(CompareVBMeta(vbmeta_path, vbmeta_images[0]));
|
||||
EXPECT_TRUE(CompareVBMeta(boot_path, vbmeta_images[1]));
|
||||
EXPECT_TRUE(CompareVBMeta(vbmeta_system_path, vbmeta_images[2]));
|
||||
EXPECT_TRUE(CompareVBMeta(system_path, vbmeta_images[3]));
|
||||
|
||||
// Sets VERIFICATION_DISABLED to the top-level vbmeta.img
|
||||
SetVBMetaFlags(vbmeta_path, AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED);
|
||||
vbmeta_images.clear();
|
||||
EXPECT_EQ(VBMetaVerifyResult::kErrorVerification,
|
||||
LoadAndVerifyVbmetaByPartition(
|
||||
"vbmeta" /* partition_name */, "" /* ab_suffix */, "" /* other_suffix */,
|
||||
"" /* expected_public_key_blob*/, true /* allow_verification_error */,
|
||||
true /* load_chained_vbmeta */, true /* rollback_protection */, vbmeta_image_path,
|
||||
false /* is_chained_vbmeta*/, &vbmeta_images));
|
||||
EXPECT_EQ(1UL, vbmeta_images.size()); // Only vbmeta is loaded
|
||||
EXPECT_TRUE(CompareVBMeta(vbmeta_path, vbmeta_images[0]));
|
||||
|
||||
// HASHTREE_DISABLED still loads the chained vbmeta.
|
||||
SetVBMetaFlags(vbmeta_path, AVB_VBMETA_IMAGE_FLAGS_HASHTREE_DISABLED);
|
||||
vbmeta_images.clear();
|
||||
EXPECT_EQ(VBMetaVerifyResult::kErrorVerification,
|
||||
LoadAndVerifyVbmetaByPartition(
|
||||
"vbmeta" /* partition_name */, "" /* ab_suffix */, "" /* other_suffix */,
|
||||
"" /* expected_public_key_blob*/, true /* allow_verification_error */,
|
||||
true /* load_chained_vbmeta */, true /* rollback_protection */, vbmeta_image_path,
|
||||
false /* is_chained_vbmeta*/, &vbmeta_images));
|
||||
EXPECT_EQ(4UL, vbmeta_images.size()); // vbmeta, boot, vbmeta_system and system
|
||||
// Binary comparison for each vbmeta image.
|
||||
EXPECT_TRUE(CompareVBMeta(vbmeta_path, vbmeta_images[0]));
|
||||
EXPECT_TRUE(CompareVBMeta(boot_path, vbmeta_images[1]));
|
||||
EXPECT_TRUE(CompareVBMeta(vbmeta_system_path, vbmeta_images[2]));
|
||||
EXPECT_TRUE(CompareVBMeta(system_path, vbmeta_images[3]));
|
||||
}
|
||||
|
||||
TEST_F(AvbUtilTest, LoadAndVerifyVbmetaByPartitionUnexpectedPublicKey) {
|
||||
// Generates chain partition descriptors.
|
||||
base::FilePath rsa2048_public_key =
|
||||
ExtractPublicKeyAvb(data_dir_.Append("testkey_rsa2048.pem"));
|
||||
|
|
@ -1060,29 +1447,29 @@ TEST_F(AvbUtilTest, LoadAndVerifyVbmetaImplUnexpectedPublicKey) {
|
|||
std::vector<VBMetaData> vbmeta_images;
|
||||
// Uses the correct expected public key.
|
||||
EXPECT_EQ(VBMetaVerifyResult::kSuccess,
|
||||
LoadAndVerifyVbmetaImpl(
|
||||
"vbmeta" /* partition_name */, "" /* ab_suffix */, "" /* other_suffix */,
|
||||
expected_key_blob_8192, true /* allow_verification_error */,
|
||||
false /* load_chained_vbmeta */, true /* rollback_protection */,
|
||||
vbmeta_image_path, false /* is_chained_vbmeta*/, &vbmeta_images));
|
||||
LoadAndVerifyVbmetaByPartition(
|
||||
"vbmeta" /* partition_name */, "" /* ab_suffix */, "" /* other_suffix */,
|
||||
expected_key_blob_8192, true /* allow_verification_error */,
|
||||
false /* load_chained_vbmeta */, true /* rollback_protection */,
|
||||
vbmeta_image_path, false /* is_chained_vbmeta*/, &vbmeta_images));
|
||||
|
||||
// Uses the wrong expected public key with allow_verification_error set to true.
|
||||
vbmeta_images.clear();
|
||||
EXPECT_EQ(VBMetaVerifyResult::kErrorVerification,
|
||||
LoadAndVerifyVbmetaImpl(
|
||||
"vbmeta" /* partition_name */, "" /* ab_suffix */, "" /* other_suffix */,
|
||||
expected_key_blob_4096, true /* allow_verification_error */,
|
||||
false /* load_chained_vbmeta */, true /* rollback_protection */,
|
||||
vbmeta_image_path, false /* is_chained_vbmeta*/, &vbmeta_images));
|
||||
LoadAndVerifyVbmetaByPartition(
|
||||
"vbmeta" /* partition_name */, "" /* ab_suffix */, "" /* other_suffix */,
|
||||
expected_key_blob_4096, true /* allow_verification_error */,
|
||||
false /* load_chained_vbmeta */, true /* rollback_protection */,
|
||||
vbmeta_image_path, false /* is_chained_vbmeta*/, &vbmeta_images));
|
||||
|
||||
// Uses the wrong expected public key with allow_verification_error set to false.
|
||||
vbmeta_images.clear();
|
||||
EXPECT_EQ(VBMetaVerifyResult::kError,
|
||||
LoadAndVerifyVbmetaImpl(
|
||||
"vbmeta" /* partition_name */, "" /* ab_suffix */, "" /* other_suffix */,
|
||||
expected_key_blob_4096, false /* allow_verification_error */,
|
||||
false /* load_chained_vbmeta */, true /* rollback_protection */,
|
||||
vbmeta_image_path, false /* is_chained_vbmeta*/, &vbmeta_images));
|
||||
LoadAndVerifyVbmetaByPartition(
|
||||
"vbmeta" /* partition_name */, "" /* ab_suffix */, "" /* other_suffix */,
|
||||
expected_key_blob_4096, false /* allow_verification_error */,
|
||||
false /* load_chained_vbmeta */, true /* rollback_protection */,
|
||||
vbmeta_image_path, false /* is_chained_vbmeta*/, &vbmeta_images));
|
||||
}
|
||||
|
||||
} // namespace fs_avb_host_test
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue