Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 003bec43 authored by David Zeuthen's avatar David Zeuthen Committed by Gerrit Code Review
Browse files

Merge "Add support for Brillo Verified Boot."

parents 6721b1d1 d995f4b0
Loading
Loading
Loading
Loading
+53 −0
Original line number Diff line number Diff line
@@ -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


@@ -517,6 +537,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))
@@ -542,6 +563,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)
@@ -591,6 +629,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
@@ -1117,8 +1156,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,$@)

@@ -1721,6 +1765,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),)
+5 −0
Original line number Diff line number Diff line
@@ -518,6 +518,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)
+51 −7
Original line number Diff line number Diff line
@@ -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,19 +292,36 @@ 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:
    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:
@@ -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)
+115 −4
Original line number Diff line number Diff line
@@ -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,6 +610,11 @@ 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"
  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)