From bbde59f9eb656f6150815b6a74f95273c646dc35 Mon Sep 17 00:00:00 2001 From: Tianjie Date: Mon, 3 May 2021 21:18:56 -0700 Subject: [PATCH] Calculate the vbmeta digest when building images Calculate the vbmeta digest if the device builds vbmeta image. The digest will used later to determine the build fingerprint in new format. One sample usage is the ota package generation, where we put the build fingerprint in the ota metadata. But we don't have the runtime vbmeta digest provided the bootloader. Bug: 186786987 Test: unit tests Change-Id: If572e2b973e295a6c95a9e23a65bb20b3afbf1b0 --- tools/releasetools/add_img_to_target_files.py | 19 ++++++++++-- tools/releasetools/sign_target_files_apks.py | 4 +++ tools/releasetools/test_verity_utils.py | 31 ++++++++++++++++++- tools/releasetools/verity_utils.py | 25 +++++++++++++++ 4 files changed, 76 insertions(+), 3 deletions(-) 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__)