diff --git a/tools/releasetools/add_img_to_target_files.py b/tools/releasetools/add_img_to_target_files.py index 00bbb212df..2aceb78f01 100644 --- a/tools/releasetools/add_img_to_target_files.py +++ b/tools/releasetools/add_img_to_target_files.py @@ -259,6 +259,7 @@ def AddVendorDlkm(output_zip): block_list=block_list) return img.name + def AddOdmDlkm(output_zip): """Turn the contents of OdmDlkm into an odm_dlkm image and store it in output_zip.""" @@ -310,6 +311,7 @@ def AddDtbo(output_zip): img.Write() return img.name + def AddPvmfw(output_zip): """Adds the pvmfw image. @@ -345,6 +347,7 @@ def AddPvmfw(output_zip): img.Write() return img.name + def AddCustomImages(output_zip, partition_name): """Adds and signs custom images in IMAGES/. @@ -359,8 +362,6 @@ def AddCustomImages(output_zip, partition_name): AssertionError: If image can't be found. """ - partition_size = OPTIONS.info_dict.get( - "avb_{}_partition_size".format(partition_name)) key_path = OPTIONS.info_dict.get("avb_{}_key_path".format(partition_name)) algorithm = OPTIONS.info_dict.get("avb_{}_algorithm".format(partition_name)) extra_args = OPTIONS.info_dict.get( @@ -955,6 +956,20 @@ def AddImagesToTargetFiles(filename): with open(pack_radioimages_txt) as f: AddPackRadioImages(output_zip, f.readlines()) + # Calculate the vbmeta digest and put the result in to META/ + boot_images = OPTIONS.info_dict.get("boot_images") + # Disable the digest calculation if the target_file is used as a container + # for boot images. + boot_container = boot_images and len(boot_images.split()) >= 2 + if (OPTIONS.info_dict.get("avb_enable") == "true" and not boot_container and + OPTIONS.info_dict.get("avb_building_vbmeta_image") == "true"): + avbtool = OPTIONS.info_dict["avb_avbtool"] + digest = verity_utils.CalculateVbmetaDigest(OPTIONS.input_tmp, avbtool) + vbmeta_digest_txt = os.path.join(OPTIONS.input_tmp, "META", + "vbmeta_digest.txt") + with open(vbmeta_digest_txt, 'w') as f: + f.write(digest) + if output_zip: common.ZipClose(output_zip) if OPTIONS.replace_updated_files_list: diff --git a/tools/releasetools/sign_target_files_apks.py b/tools/releasetools/sign_target_files_apks.py index 313d1e6aa7..f0110eaaab 100755 --- a/tools/releasetools/sign_target_files_apks.py +++ b/tools/releasetools/sign_target_files_apks.py @@ -629,6 +629,10 @@ def ProcessTargetFiles(input_tf_zip, output_tf_zip, misc_info, elif OPTIONS.replace_verity_keyid and filename == "BOOT/cmdline": pass + # Skip the vbmeta digest as we will recalculate it. + elif filename == "META/vbmeta_digest.txt": + pass + # Skip the care_map as we will regenerate the system/vendor images. elif filename in ["META/care_map.pb", "META/care_map.txt"]: pass diff --git a/tools/releasetools/test_verity_utils.py b/tools/releasetools/test_verity_utils.py index a850390b8e..e2a022a648 100644 --- a/tools/releasetools/test_verity_utils.py +++ b/tools/releasetools/test_verity_utils.py @@ -27,7 +27,8 @@ from rangelib import RangeSet from test_utils import ( get_testdata_dir, ReleaseToolsTestCase, SkipIfExternalToolsUnavailable) from verity_utils import ( - CreateHashtreeInfoGenerator, CreateVerityImageBuilder, HashtreeInfo, + CalculateVbmetaDigest, CreateHashtreeInfoGenerator, + CreateVerityImageBuilder, HashtreeInfo, VerifiedBootVersion1HashtreeInfoGenerator) BLOCK_SIZE = common.BLOCK_SIZE @@ -388,3 +389,31 @@ class VerifiedBootVersion2VerityImageBuilderTest(ReleaseToolsTestCase): self.assertLess( _SizeCalculator(min_partition_size - BLOCK_SIZE), image_size) + + @SkipIfExternalToolsUnavailable() + def test_CalculateVbmetaDigest(self): + prop_dict = copy.deepcopy(self.DEFAULT_PROP_DICT) + verity_image_builder = CreateVerityImageBuilder(prop_dict) + self.assertEqual(2, verity_image_builder.version) + + input_dir = common.MakeTempDir() + image_dir = common.MakeTempDir() + os.mkdir(os.path.join(image_dir, 'IMAGES')) + system_image = os.path.join(image_dir, 'IMAGES', 'system.img') + system_image_size = verity_image_builder.CalculateMaxImageSize() + cmd = ['mkuserimg_mke2fs', input_dir, system_image, 'ext4', '/system', + str(system_image_size), '-j', '0', '-s'] + common.RunAndCheckOutput(cmd) + verity_image_builder.Build(system_image) + + # Additionally make vbmeta image + vbmeta_image = os.path.join(image_dir, 'IMAGES', 'vbmeta.img') + cmd = ['avbtool', 'make_vbmeta_image', '--include_descriptors_from_image', + system_image, '--output', vbmeta_image] + common.RunAndCheckOutput(cmd) + + # Verify the verity metadata. + cmd = ['avbtool', 'verify_image', '--image', vbmeta_image] + common.RunAndCheckOutput(cmd) + digest = CalculateVbmetaDigest(image_dir, 'avbtool') + self.assertIsNotNone(digest) diff --git a/tools/releasetools/verity_utils.py b/tools/releasetools/verity_utils.py index 8faa2d1fc0..a08ddbede6 100644 --- a/tools/releasetools/verity_utils.py +++ b/tools/releasetools/verity_utils.py @@ -26,6 +26,7 @@ import logging import os.path import shlex import struct +import sys import common import sparse_img @@ -739,6 +740,30 @@ def GetDiskUsage(path): return int(output.split()[0]) * 1024 +def CalculateVbmetaDigest(extracted_dir, avbtool): + """Calculates the vbmeta digest of the images in the extracted target_file""" + + images_dir = common.MakeTempDir() + for name in ("PREBUILT_IMAGES", "RADIO", "IMAGES"): + path = os.path.join(extracted_dir, name) + if not os.path.exists(path): + continue + + # Create symlink for image files under PREBUILT_IMAGES, RADIO and IMAGES, + # and put them into one directory. + for filename in os.listdir(path): + if not filename.endswith(".img"): + continue + symlink_path = os.path.join(images_dir, filename) + # The files in latter directory overwrite the existing links + common.RunAndCheckOutput( + ['ln', '-sf', os.path.join(path, filename), symlink_path]) + + cmd = [avbtool, "calculate_vbmeta_digest", "--image", + os.path.join(images_dir, 'vbmeta.img')] + return common.RunAndCheckOutput(cmd) + + def main(argv): if len(argv) != 2: print(__doc__)