Merge "Add support for Brillo Verified Boot."

am: 003bec4

* commit '003bec431cc133134bbb29040f6c01d3f608e6ee':
  Add support for Brillo Verified Boot.
This commit is contained in:
David Zeuthen 2016-03-21 15:55:23 +00:00 committed by android-build-merger
commit 1b61e038e6
4 changed files with 224 additions and 11 deletions

View File

@ -507,8 +507,28 @@ INTERNAL_BOOTIMAGE_ARGS := \
$(addprefix --second ,$(INSTALLED_2NDBOOTLOADER_TARGET)) \
--kernel $(INSTALLED_KERNEL_TARGET)
INTERNAL_BVBTOOL_MAKE_BOOT_IMAGE_ARGS := \
--kernel $(INSTALLED_KERNEL_TARGET) \
--rootfs_with_hashes $(PRODUCT_OUT)/system.img
ifdef BOARD_BVB_ROLLBACK_INDEX
INTERNAL_BVBTOOL_MAKE_BOOT_IMAGE_ARGS += \
--rollback_index $(BOARD_BVB_ROLLBACK_INDEX)
endif
ifndef BOARD_BVB_KEY_PATH
# If key path isn't specified, use the 4096-bit test key.
INTERNAL_BVBTOOL_SIGN_BOOT_IMAGE_ARGS := --algorithm SHA256_RSA4096 \
--key system/bvb/test/testkey_rsa4096.pem
else
INTERNAL_BVBTOOL_SIGN_BOOT_IMAGE_ARGS := \
--algorithm $(BOARD_BVB_ALGORITHM) --key $(BOARD_BVB_KEY_PATH)
endif
ifneq ($(BOARD_BUILD_SYSTEM_ROOT_IMAGE),true)
INTERNAL_BOOTIMAGE_ARGS += --ramdisk $(INSTALLED_RAMDISK_TARGET)
INTERNAL_BVBTOOL_MAKE_BOOT_IMAGE_ARGS += --initrd $(INSTALLED_RAMDISK_TARGET)
endif
INTERNAL_BOOTIMAGE_FILES := $(filter-out --%,$(INTERNAL_BOOTIMAGE_ARGS))
@ -516,6 +536,7 @@ INTERNAL_BOOTIMAGE_FILES := $(filter-out --%,$(INTERNAL_BOOTIMAGE_ARGS))
BOARD_KERNEL_CMDLINE := $(strip $(BOARD_KERNEL_CMDLINE))
ifdef BOARD_KERNEL_CMDLINE
INTERNAL_BOOTIMAGE_ARGS += --cmdline "$(BOARD_KERNEL_CMDLINE)"
INTERNAL_BVBTOOL_MAKE_BOOT_IMAGE_ARGS += --kernel_cmdline "$(BOARD_KERNEL_CMDLINE)"
endif
BOARD_KERNEL_BASE := $(strip $(BOARD_KERNEL_BASE))
@ -541,6 +562,23 @@ ifneq ($(BOARD_BUILD_SYSTEM_ROOT_IMAGE),true)
endif
endif
ifeq ($(BOARD_BVB_ENABLE),true)
$(INSTALLED_BOOTIMAGE_TARGET): $(BVBTOOL) $(INTERNAL_BOOTIMAGE_FILES) $(PRODUCT_OUT)/system.img
$(call pretty,"Target boot image: $@")
$(hide) $(BVBTOOL) make_boot_image $(INTERNAL_BVBTOOL_MAKE_BOOT_IMAGE_ARGS) $(BOARD_BVB_MAKE_BOOT_IMAGE_ARGS) --output $@
$(hide) $(BVBTOOL) sign_boot_image $(INTERNAL_BVBTOOL_SIGN_BOOT_IMAGE_ARGS) $(BOARD_BVB_SIGN_BOOT_IMAGE_ARGS) --image $@
$(hide) $(call assert-max-image-size,$@,$(BOARD_BOOTIMAGE_PARTITION_SIZE))
.PHONY: bootimage-nodeps
bootimage-nodeps: $(BVBTOOL)
@echo "make $@: ignoring dependencies"
$(hide) $(BVBTOOL) make_boot_image $(INTERNAL_BVBTOOL_MAKE_BOOT_IMAGE_ARGS) $(BOARD_BVB_MAKE_BOOT_IMAGE_ARGS) --output $(INSTALLED_BOOTIMAGE_TARGET)
$(hide) $(BVBTOOL) sign_boot_image $(INTERNAL_BVBTOOL_SIGN_BOOT_IMAGE_ARGS) $(BOARD_BVB_SIGN_BOOT_IMAGE_ARGS) --image $(INSTALLED_BOOTIMAGE_TARGET)
$(hide) $(call assert-max-image-size,$(INSTALLED_BOOTIMAGE_TARGET),$(BOARD_BOOTIMAGE_PARTITION_SIZE))
else # BOARD_BVB_ENABLE
# We build recovery as boot image if BOARD_USES_RECOVERY_AS_BOOT is true.
ifneq ($(BOARD_USES_RECOVERY_AS_BOOT),true)
ifeq ($(TARGET_BOOTIMAGE_USE_EXT2),true)
@ -590,6 +628,7 @@ bootimage-nodeps: $(MKBOOTIMG)
endif # TARGET_BOOTIMAGE_USE_EXT2
endif # BOARD_USES_RECOVERY_AS_BOOT
endif # BOARD_BVB_ENABLE
else # TARGET_NO_KERNEL
# HACK: The top-level targets depend on the bootimage. Not all targets
@ -1128,8 +1167,13 @@ define build-systemimage-target
fi; \
mkdir -p $(DIST_DIR); cp $(INSTALLED_FILES_FILE) $(DIST_DIR)/installed-files-rescued.txt; \
exit 1 )
$(if $(BOARD_BVB_ENABLE), $(hide) $(BVBTOOL) add_image_hashes $(BOARD_BVB_ADD_IMAGE_HASHES_ARGS) --image $(1))
endef
ifeq ($(BOARD_BVB_ENABLE),true)
FULL_SYSTEMIMAGE_DEPS += $(BVBTOOL)
endif
$(BUILT_SYSTEMIMAGE): $(FULL_SYSTEMIMAGE_DEPS) $(INSTALLED_FILES_FILE)
$(call build-systemimage-target,$@)
@ -1772,6 +1816,15 @@ ifneq ($(strip $(SANITIZE_TARGET)),)
endif
ifeq ($(BOARD_USES_FULL_RECOVERY_IMAGE),true)
$(hide) echo "full_recovery_image=true" >> $(zip_root)/META/misc_info.txt
endif
ifeq ($(BOARD_BVB_ENABLE),true)
$(hide) echo "board_bvb_enable=true" >> $(zip_root)/META/misc_info.txt
$(hide) echo "board_bvb_make_boot_image_args=$(BOARD_BVB_MAKE_BOOT_IMAGE_ARGS)" >> $(zip_root)/META/misc_info.txt
$(hide) echo "board_bvb_sign_boot_image_args=$(BOARD_BVB_SIGN_BOOT_IMAGE_ARGS)" >> $(zip_root)/META/misc_info.txt
$(hide) echo "board_bvb_algorithm=$(BOARD_BVB_ALGORITHM)" >> $(zip_root)/META/misc_info.txt
$(hide) echo "board_bvb_key_path=$(BOARD_BVB_KEY_PATH)" >> $(zip_root)/META/misc_info.txt
$(hide) echo "board_bvb_rollback_index=$(BOARD_BVB_ROLLBACK_INDEX)" >> $(zip_root)/META/misc_info.txt
$(hide) echo "board_bvb_add_image_hashes_args=$(BOARD_BVB_ADD_IMAGE_HASHES_ARGS)" >> $(zip_root)/META/misc_info.txt
endif
$(call generate-userimage-prop-dictionary, $(zip_root)/META/misc_info.txt)
ifneq ($(INSTALLED_RECOVERYIMAGE_TARGET),)

View File

@ -528,6 +528,11 @@ MKBOOTIMG := $(HOST_OUT_EXECUTABLES)/mkbootimg$(HOST_EXECUTABLE_SUFFIX)
else
MKBOOTIMG := $(BOARD_CUSTOM_MKBOOTIMG)
endif
ifeq (,$(strip $(BOARD_CUSTOM_BVBTOOL)))
BVBTOOL := $(HOST_OUT_EXECUTABLES)/bvbtool$(HOST_EXECUTABLE_SUFFIX)
else
BVBTOOL := $(BOARD_CUSTOM_BVBTOOL)
endif
APICHECK := $(HOST_OUT_EXECUTABLES)/apicheck$(HOST_EXECUTABLE_SUFFIX)
FS_GET_STATS := $(HOST_OUT_EXECUTABLES)/fs_get_stats$(HOST_EXECUTABLE_SUFFIX)
MAKE_EXT4FS := $(HOST_OUT_EXECUTABLES)/make_ext4fs$(HOST_EXECUTABLE_SUFFIX)

View File

@ -31,7 +31,9 @@ if sys.hexversion < 0x02070000:
import datetime
import errno
import os
import shlex
import shutil
import subprocess
import tempfile
import zipfile
@ -48,12 +50,12 @@ OPTIONS.verity_signer_path = None
def AddSystem(output_zip, prefix="IMAGES/", recovery_img=None, boot_img=None):
"""Turn the contents of SYSTEM into a system image and store it in
output_zip."""
output_zip. Returns the name of the system image file."""
prebuilt_path = os.path.join(OPTIONS.input_tmp, prefix, "system.img")
if os.path.exists(prebuilt_path):
print "system.img already exists in %s, no need to rebuild..." % (prefix,)
return
return prebuilt_path
def output_sink(fn, data):
ofile = open(os.path.join(OPTIONS.input_tmp, "SYSTEM", fn), "w")
@ -68,8 +70,23 @@ def AddSystem(output_zip, prefix="IMAGES/", recovery_img=None, boot_img=None):
block_list = common.MakeTempFile(prefix="system-blocklist-", suffix=".map")
imgname = BuildSystem(OPTIONS.input_tmp, OPTIONS.info_dict,
block_list=block_list)
# If requested, calculate and add dm-verity integrity hashes and
# metadata to system.img.
if OPTIONS.info_dict.get("board_bvb_enable", None) == "true":
bvbtool = os.getenv('BVBTOOL') or "bvbtool"
cmd = [bvbtool, "add_image_hashes", "--image", imgname]
args = OPTIONS.info_dict.get("board_bvb_add_image_hashes_args", None)
if args and args.strip():
cmd.extend(shlex.split(args))
p = common.Run(cmd, stdout=subprocess.PIPE)
p.communicate()
assert p.returncode == 0, "bvbtool add_image_hashes of %s image failed" % (
os.path.basename(OPTIONS.input_tmp),)
common.ZipWrite(output_zip, imgname, prefix + "system.img")
common.ZipWrite(output_zip, block_list, prefix + "system.map")
return imgname
def BuildSystem(input_dir, info_dict, block_list=None):
@ -275,23 +292,40 @@ def AddImagesToTargetFiles(filename):
compression=zipfile.ZIP_DEFLATED)
has_recovery = (OPTIONS.info_dict.get("no_recovery") != "true")
system_root_image = (OPTIONS.info_dict.get("system_root_image", None) == "true")
board_bvb_enable = (OPTIONS.info_dict.get("board_bvb_enable", None) == "true")
# Brillo Verified Boot is incompatible with certain
# configurations. Explicitly check for these.
if board_bvb_enable:
assert not has_recovery, "has_recovery incompatible with bvb"
assert not system_root_image, "system_root_image incompatible with bvb"
assert not OPTIONS.rebuild_recovery, "rebuild_recovery incompatible with bvb"
assert not has_vendor, "VENDOR images currently incompatible with bvb"
def banner(s):
print "\n\n++++ " + s + " ++++\n\n"
banner("boot")
prebuilt_path = os.path.join(OPTIONS.input_tmp, "IMAGES", "boot.img")
boot_image = None
if os.path.exists(prebuilt_path):
banner("boot")
print "boot.img already exists in IMAGES/, no need to rebuild..."
if OPTIONS.rebuild_recovery:
boot_image = common.GetBootableImage(
"IMAGES/boot.img", "boot.img", OPTIONS.input_tmp, "BOOT")
else:
boot_image = common.GetBootableImage(
if board_bvb_enable:
# With Brillo Verified Boot, we need to build system.img before
# boot.img since the latter includes the dm-verity root hash and
# salt for the former.
pass
else:
banner("boot")
boot_image = common.GetBootableImage(
"IMAGES/boot.img", "boot.img", OPTIONS.input_tmp, "BOOT")
if boot_image:
boot_image.AddToZip(output_zip)
if boot_image:
boot_image.AddToZip(output_zip)
recovery_image = None
if has_recovery:
@ -310,7 +344,17 @@ def AddImagesToTargetFiles(filename):
recovery_image.AddToZip(output_zip)
banner("system")
AddSystem(output_zip, recovery_img=recovery_image, boot_img=boot_image)
system_img_path = AddSystem(
output_zip, recovery_img=recovery_image, boot_img=boot_image)
if OPTIONS.info_dict.get("board_bvb_enable", None) == "true":
# If we're using Brillo Verified Boot, we can now build boot.img
# given that we have system.img.
banner("boot")
boot_image = common.GetBootableImage(
"IMAGES/boot.img", "boot.img", OPTIONS.input_tmp, "BOOT",
system_img_path=system_img_path)
if boot_image:
boot_image.AddToZip(output_zip)
if has_vendor:
banner("vendor")
AddVendor(output_zip)

View File

@ -473,8 +473,114 @@ def _BuildBootableImage(sourcedir, fs_config_file, info_dict=None,
return data
def _BuildBvbBootableImage(sourcedir, fs_config_file, system_img_path,
info_dict=None, has_ramdisk=False):
"""Build a bootable image compatible with Brillo Verified Boot from the
specified sourcedir.
Take a kernel, cmdline, system image path, and optionally a ramdisk
directory from the input (in 'sourcedir'), and turn them into a boot
image. Return the image data, or None if sourcedir does not appear
to contains files for building the requested image.
"""
def make_ramdisk():
ramdisk_img = tempfile.NamedTemporaryFile()
if os.access(fs_config_file, os.F_OK):
cmd = ["mkbootfs", "-f", fs_config_file,
os.path.join(sourcedir, "RAMDISK")]
else:
cmd = ["mkbootfs", os.path.join(sourcedir, "RAMDISK")]
p1 = Run(cmd, stdout=subprocess.PIPE)
p2 = Run(["minigzip"], stdin=p1.stdout, stdout=ramdisk_img.file.fileno())
p2.wait()
p1.wait()
assert p1.returncode == 0, "mkbootfs of %s ramdisk failed" % (sourcedir,)
assert p2.returncode == 0, "minigzip of %s ramdisk failed" % (sourcedir,)
return ramdisk_img
if not os.access(os.path.join(sourcedir, "kernel"), os.F_OK):
return None
if has_ramdisk and not os.access(os.path.join(sourcedir, "RAMDISK"), os.F_OK):
return None
if info_dict is None:
info_dict = OPTIONS.info_dict
img = tempfile.NamedTemporaryFile()
if has_ramdisk:
ramdisk_img = make_ramdisk()
# use BVBTOOL from environ, or "bvbtool" if empty or not set
bvbtool = os.getenv('BVBTOOL') or "bvbtool"
# First, create boot.img.
cmd = [bvbtool, "make_boot_image"]
fn = os.path.join(sourcedir, "cmdline")
if os.access(fn, os.F_OK):
cmd.append("--kernel_cmdline")
cmd.append(open(fn).read().rstrip("\n"))
cmd.extend(["--kernel", os.path.join(sourcedir, "kernel")])
if has_ramdisk:
cmd.extend(["--initrd", ramdisk_img.name])
cmd.extend(["--rootfs_with_hashes", system_img_path])
args = info_dict.get("board_bvb_make_boot_image_args", None)
if args and args.strip():
cmd.extend(shlex.split(args))
rollback_index = info_dict.get("board_bvb_rollback_index", None)
if rollback_index and rollback_index.strip():
cmd.extend(["--rollback_index", rollback_index.strip()])
cmd.extend(["--output", img.name])
p = Run(cmd, stdout=subprocess.PIPE)
p.communicate()
assert p.returncode == 0, "bvbtool make_boot_image of %s image failed" % (
os.path.basename(sourcedir),)
# Then, sign boot.img.
cmd = [bvbtool, "sign_boot_image", "--image", img.name]
algorithm = info_dict.get("board_bvb_algorithm", None)
key_path = info_dict.get("board_bvb_key_path", None)
if algorithm and algorithm.strip() and key_path and key_path.strip():
cmd.extend(["--algorithm", algorithm, "--key", key_path])
else:
cmd.extend(["--algorithm", "SHA256_RSA4096"])
cmd.extend(["--key", "system/bvb/test/testkey_rsa4096.pem"])
args = info_dict.get("board_bvb_sign_boot_image_args", None)
if args and args.strip():
cmd.extend(shlex.split(args))
p = Run(cmd, stdout=subprocess.PIPE)
p.communicate()
assert p.returncode == 0, "bvbtool sign_boot_image of %s image failed" % (
os.path.basename(sourcedir),)
img.seek(os.SEEK_SET, 0)
data = img.read()
if has_ramdisk:
ramdisk_img.close()
img.close()
return data
def GetBootableImage(name, prebuilt_name, unpack_dir, tree_subdir,
info_dict=None):
info_dict=None, system_img_path=None):
"""Return a File object with the desired bootable image.
Look for it in 'unpack_dir'/BOOTABLE_IMAGES under the name 'prebuilt_name',
@ -504,9 +610,14 @@ def GetBootableImage(name, prebuilt_name, unpack_dir, tree_subdir,
info_dict.get("recovery_as_boot") == "true")
fs_config = "META/" + tree_subdir.lower() + "_filesystem_config.txt"
data = _BuildBootableImage(os.path.join(unpack_dir, tree_subdir),
os.path.join(unpack_dir, fs_config),
info_dict, has_ramdisk)
if info_dict.get("board_bvb_enable", None) == "true":
data = _BuildBvbBootableImage(os.path.join(unpack_dir, tree_subdir),
os.path.join(unpack_dir, fs_config),
system_img_path, info_dict, has_ramdisk)
else:
data = _BuildBootableImage(os.path.join(unpack_dir, tree_subdir),
os.path.join(unpack_dir, fs_config),
info_dict, has_ramdisk)
if data:
return File(name, data)
return None