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
diff --git a/tools/releasetools/add_img_to_target_files.py b/tools/releasetools/add_img_to_target_files.py
index 00bbb21..2aceb78 100644
--- a/tools/releasetools/add_img_to_target_files.py
+++ b/tools/releasetools/add_img_to_target_files.py
@@ -259,6 +259,7 @@
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 @@
img.Write()
return img.name
+
def AddPvmfw(output_zip):
"""Adds the pvmfw image.
@@ -345,6 +347,7 @@
img.Write()
return img.name
+
def AddCustomImages(output_zip, partition_name):
"""Adds and signs custom images in IMAGES/.
@@ -359,8 +362,6 @@
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 @@
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 313d1e6..f0110ea 100755
--- a/tools/releasetools/sign_target_files_apks.py
+++ b/tools/releasetools/sign_target_files_apks.py
@@ -629,6 +629,10 @@
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 a850390..e2a022a 100644
--- a/tools/releasetools/test_verity_utils.py
+++ b/tools/releasetools/test_verity_utils.py
@@ -27,7 +27,8 @@
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 @@
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 8faa2d1..a08ddbe 100644
--- a/tools/releasetools/verity_utils.py
+++ b/tools/releasetools/verity_utils.py
@@ -26,6 +26,7 @@
import os.path
import shlex
import struct
+import sys
import common
import sparse_img
@@ -739,6 +740,30 @@
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__)