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
This commit is contained in:
Tianjie 2021-05-03 21:18:56 -07:00 committed by Tianjie Xu
parent bf7d6d78c7
commit bbde59f9eb
4 changed files with 76 additions and 3 deletions

View file

@ -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:

View file

@ -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

View file

@ -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)

View file

@ -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__)