Add fsverity digest manifest
fsverity digest manifest stores a map from files to fsverity digests.
The manifest is installed as a serialized protobuf file, to a signed apk
system/etc/security/fsverity/BuildManifest.apk.
Bug: 193113311
Test: build with PRODUCT_SYSTEM_FSVERITY_GENERATE_METADATA := true
Change-Id: I55fc10400206b8ce0d5f198faea08fe3930b362c
diff --git a/tools/releasetools/build_image.py b/tools/releasetools/build_image.py
index 8e8bcde..8a5d627 100755
--- a/tools/releasetools/build_image.py
+++ b/tools/releasetools/build_image.py
@@ -35,6 +35,7 @@
import common
import verity_utils
+from fsverity_digests_pb2 import FSVerityDigests
from fsverity_metadata_generator import FSVerityMetadataGenerator
logger = logging.getLogger(__name__)
@@ -450,6 +451,68 @@
return mkfs_output
+def GenerateFSVerityMetadata(in_dir, fsverity_path, apk_key_path, apk_manifest_path, apk_out_path):
+ """Generates fsverity metadata files.
+
+ By setting PRODUCT_SYSTEM_FSVERITY_GENERATE_METADATA := true, fsverity
+ metadata files will be generated. For the input files, see `patterns` below.
+
+ One metadata file per one input file will be generated with the suffix
+ .fsv_meta. e.g. system/framework/foo.jar -> system/framework/foo.jar.fsv_meta
+ Also a mapping file containing fsverity digests will be generated to
+ system/etc/security/fsverity/BuildManifest.apk.
+
+ Args:
+ in_dir: temporary working directory (same as BuildImage)
+ fsverity_path: path to host tool fsverity
+ apk_key_path: path to key (e.g. build/make/target/product/security/platform)
+ apk_manifest_path: path to AndroidManifest.xml for APK
+ apk_out_path: path to the output APK
+
+ Returns:
+ None. The files are generated directly under in_dir.
+ """
+
+ patterns = [
+ "system/framework/*.jar",
+ "system/framework/oat/*/*.oat",
+ "system/framework/oat/*/*.vdex",
+ "system/framework/oat/*/*.art",
+ "system/etc/boot-image.prof",
+ "system/etc/dirty-image-objects",
+ ]
+ files = []
+ for pattern in patterns:
+ files += glob.glob(os.path.join(in_dir, pattern))
+ files = sorted(set(files))
+
+ generator = FSVerityMetadataGenerator(fsverity_path)
+ generator.set_hash_alg("sha256")
+
+ digests = FSVerityDigests()
+ for f in files:
+ generator.generate(f)
+ # f is a full path for now; make it relative so it starts with {mount_point}/
+ digest = digests.digests[os.path.relpath(f, in_dir)]
+ digest.digest = generator.digest(f)
+ digest.hash_alg = "sha256"
+
+ temp_dir = common.MakeTempDir()
+
+ os.mkdir(os.path.join(temp_dir, "assets"))
+ metadata_path = os.path.join(temp_dir, "assets", "build_manifest")
+ with open(metadata_path, "wb") as f:
+ f.write(digests.SerializeToString())
+
+ apk_path = os.path.join(in_dir, apk_out_path)
+
+ common.RunAndCheckOutput(["aapt2", "link",
+ "-A", os.path.join(temp_dir, "assets"),
+ "-o", apk_path,
+ "--manifest", apk_manifest_path])
+ common.RunAndCheckOutput(["apksigner", "sign", "--in", apk_path,
+ "--cert", apk_key_path + ".x509.pem",
+ "--key", apk_key_path + ".pk8"])
def BuildImage(in_dir, prop_dict, out_file, target_out=None):
"""Builds an image for the files under in_dir and writes it to out_file.
@@ -479,22 +542,11 @@
fs_spans_partition = False
if "fsverity_generate_metadata" in prop_dict:
- patterns = [
- "system/framework/*.jar",
- "system/framework/oat/*/*.oat",
- "system/framework/oat/*/*.vdex",
- "system/framework/oat/*/*.art",
- "system/etc/boot-image.prof",
- "system/etc/dirty-image-objects",
- ]
- files = []
- for pattern in patterns:
- files += glob.glob(os.path.join(in_dir, pattern))
- files = sorted(set(files))
-
- generator = FSVerityMetadataGenerator(prop_dict["fsverity"])
- for f in files:
- generator.generate(f)
+ GenerateFSVerityMetadata(in_dir,
+ fsverity_path=prop_dict["fsverity"],
+ apk_key_path=prop_dict["fsverity_apk_key"],
+ apk_manifest_path=prop_dict["fsverity_apk_manifest"],
+ apk_out_path=prop_dict["fsverity_apk_out"])
# Get a builder for creating an image that's to be verified by Verified Boot,
# or None if not applicable.
@@ -747,6 +799,9 @@
copy_prop("root_fs_config", "root_fs_config")
copy_prop("fsverity", "fsverity")
copy_prop("fsverity_generate_metadata", "fsverity_generate_metadata")
+ copy_prop("fsverity_apk_key","fsverity_apk_key")
+ copy_prop("fsverity_apk_manifest","fsverity_apk_manifest")
+ copy_prop("fsverity_apk_out","fsverity_apk_out")
elif mount_point == "data":
# Copy the generic fs type first, override with specific one if available.
copy_prop("flash_logical_block_size", "flash_logical_block_size")