Support AVB signing for BOARD_PREBUILT_BOOTIMAGE
Devices using GKI architecture will use a prebuilt boot.img.
However, we should still sign this prebuilt boot.img with
device-specific AVB keys.
Steps to test the CL.
1. In a device BoardConfig.mk:
# Uses a prebuilt boot.img
TARGET_NO_KERNEL := true
BOARD_PREBUILT_BOOTIMAGE := device/google/redbull/boot.img
# Enable chained vbmeta for the boot image.
# The following can be absent, where the hash descriptor of the
# 'boot' partition will be stored then signed in vbmeta.img instead.
BOARD_AVB_BOOT_KEY_PATH := external/avb/test/data/testkey_rsa4096.pem
BOARD_AVB_BOOT_ALGORITHM := SHA256_RSA4096
BOARD_AVB_BOOT_ROLLBACK_INDEX := $(PLATFORM_SECURITY_PATCH_TIMESTAMP)
BOARD_AVB_BOOT_ROLLBACK_INDEX_LOCATION := 2
2. `make bootimage`, then `avbtool info_image --image $OUT/boot.img`,
checks the image is re-signed with a device-specific key
3. `make dist` to generate out/dist/TF.zip
4. `unzip out/dist/TF.zip IMAGES/boot.img`
5. `avbtool info_image --image out/dist/IMAGES/boot.img`,
checks the image is re-signed with a device-specific key
6. `sign_target_files_apks \
--avb_boot_key=external/avb/test/data/testkey_rsa8192.pem \
--avb_boot_algorithm=SHA256_RSA8192 \
--avb_boot_extra_args="--prop test:sign" \
./out/dist/*-target_files-eng.*.zip signed.zip`, resign the TF.zip
7. `unzip signed.zip IMAGES/boot.img`, then use `avbtool info_image` to
check the boot.img is re-signed with the --avb_boot_key in step 6.
Bug: 188485657
Test: above steps
Change-Id: I7ee8b3ffe6a86aaca34bbb7a8898a97b3f8bd801
diff --git a/tools/releasetools/common.py b/tools/releasetools/common.py
index 5e2a50d..985a21a 100644
--- a/tools/releasetools/common.py
+++ b/tools/releasetools/common.py
@@ -1710,6 +1710,38 @@
return data
+def _SignBootableImage(image_path, prebuilt_name, partition_name,
+ info_dict=None):
+ """Performs AVB signing for a prebuilt boot.img.
+
+ Args:
+ image_path: The full path of the image, e.g., /path/to/boot.img.
+ prebuilt_name: The prebuilt image name, e.g., boot.img, boot-5.4-gz.img,
+ boot-5.10.img, recovery.img.
+ partition_name: The partition name, e.g., 'boot' or 'recovery'.
+ info_dict: The information dict read from misc_info.txt.
+ """
+ if info_dict is None:
+ info_dict = OPTIONS.info_dict
+
+ # AVB: if enabled, calculate and add hash to boot.img or recovery.img.
+ if info_dict.get("avb_enable") == "true":
+ avbtool = info_dict["avb_avbtool"]
+ if partition_name == "recovery":
+ part_size = info_dict["recovery_size"]
+ else:
+ part_size = info_dict[prebuilt_name.replace(".img", "_size")]
+
+ cmd = [avbtool, "add_hash_footer", "--image", image_path,
+ "--partition_size", str(part_size), "--partition_name",
+ partition_name]
+ AppendAVBSigningArgs(cmd, partition_name)
+ args = info_dict.get("avb_" + partition_name + "_add_hash_footer_args")
+ if args and args.strip():
+ cmd.extend(shlex.split(args))
+ RunAndCheckOutput(cmd)
+
+
def GetBootableImage(name, prebuilt_name, unpack_dir, tree_subdir,
info_dict=None, two_step_image=False):
"""Return a File object with the desired bootable image.
@@ -1718,6 +1750,9 @@
otherwise look for it under 'unpack_dir'/IMAGES, otherwise construct it from
the source files in 'unpack_dir'/'tree_subdir'."""
+ if info_dict is None:
+ info_dict = OPTIONS.info_dict
+
prebuilt_path = os.path.join(unpack_dir, "BOOTABLE_IMAGES", prebuilt_name)
if os.path.exists(prebuilt_path):
logger.info("using prebuilt %s from BOOTABLE_IMAGES...", prebuilt_name)
@@ -1728,10 +1763,16 @@
logger.info("using prebuilt %s from IMAGES...", prebuilt_name)
return File.FromLocalFile(name, prebuilt_path)
- logger.info("building image from target_files %s...", tree_subdir)
+ prebuilt_path = os.path.join(unpack_dir, "PREBUILT_IMAGES", prebuilt_name)
+ if os.path.exists(prebuilt_path):
+ logger.info("Re-signing prebuilt %s from PREBUILT_IMAGES...", prebuilt_name)
+ signed_img = MakeTempFile()
+ shutil.copy(prebuilt_path, signed_img)
+ partition_name = tree_subdir.lower()
+ _SignBootableImage(signed_img, prebuilt_name, partition_name, info_dict)
+ return File.FromLocalFile(name, signed_img)
- if info_dict is None:
- info_dict = OPTIONS.info_dict
+ logger.info("building image from target_files %s...", tree_subdir)
# With system_root_image == "true", we don't pack ramdisk into the boot image.
# Unless "recovery_as_boot" is specified, in which case we carry the ramdisk