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

Commit 30f09a1a authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge "Support GKI boot.img v4 signing"

parents b90b5465 27c39b0a
Loading
Loading
Loading
Loading
+42 −11
Original line number Diff line number Diff line
@@ -856,6 +856,23 @@ INTERNAL_MKBOOTIMG_VERSION_ARGS := \
    --os_version $(PLATFORM_VERSION_LAST_STABLE) \
    --os_patch_level $(PLATFORM_SECURITY_PATCH)

ifdef BOARD_GKI_SIGNING_KEY_PATH
ifndef BOARD_GKI_SIGNING_ALGORITHM
$(error BOARD_GKI_SIGNING_ALGORITHM should be defined with BOARD_GKI_SIGNING_KEY_PATH)
endif
INTERNAL_MKBOOTIMG_GKI_SINGING_ARGS := \
    --gki_signing_key $(BOARD_GKI_SIGNING_KEY_PATH) \
    --gki_signing_algorithm $(BOARD_GKI_SIGNING_ALGORITHM) \
    --gki_signing_avbtool_path $(AVBTOOL)
endif

# Using double quote to pass BOARD_GKI_SIGNING_SIGNATURE_ARGS as a single string
# to MKBOOTIMG, although it may contain multiple args.
ifdef BOARD_GKI_SIGNING_SIGNATURE_ARGS
INTERNAL_MKBOOTIMG_GKI_SINGING_ARGS += \
    --gki_signing_signature_args "$(BOARD_GKI_SIGNING_SIGNATURE_ARGS)"
endif

# Define these only if we are building boot
ifdef BUILDING_BOOT_IMAGE
INSTALLED_BOOTIMAGE_TARGET := $(BUILT_BOOTIMAGE_TARGET)
@@ -870,7 +887,8 @@ ifeq (true,$(BOARD_AVB_ENABLE))

# $1: boot image target
define build_boot_board_avb_enabled
  $(MKBOOTIMG) --kernel $(call bootimage-to-kernel,$(1)) $(INTERNAL_BOOTIMAGE_ARGS) $(INTERNAL_MKBOOTIMG_VERSION_ARGS) $(BOARD_MKBOOTIMG_ARGS) --output $(1)
  $(MKBOOTIMG) --kernel $(call bootimage-to-kernel,$(1)) $(INTERNAL_BOOTIMAGE_ARGS) $(INTERNAL_MKBOOTIMG_VERSION_ARGS) \
               $(INTERNAL_MKBOOTIMG_GKI_SINGING_ARGS) $(BOARD_MKBOOTIMG_ARGS) --output $(1)
  $(call assert-max-image-size,$(1),$(call get-hash-image-max-size,$(call get-bootimage-partition-size,$(1),boot)))
  $(AVBTOOL) add_hash_footer \
          --image $(1) \
@@ -879,12 +897,12 @@ define build_boot_board_avb_enabled
          $(BOARD_AVB_BOOT_ADD_HASH_FOOTER_ARGS)
endef

$(INSTALLED_BOOTIMAGE_TARGET): $(MKBOOTIMG) $(AVBTOOL) $(INTERNAL_BOOTIMAGE_FILES) $(BOARD_AVB_BOOT_KEY_PATH)
$(INSTALLED_BOOTIMAGE_TARGET): $(MKBOOTIMG) $(AVBTOOL) $(INTERNAL_BOOTIMAGE_FILES) $(BOARD_AVB_BOOT_KEY_PATH) $(BOARD_GKI_SIGNING_KEY_PATH)
	$(call pretty,"Target boot image: $@")
	$(call build_boot_board_avb_enabled,$@)

.PHONY: bootimage-nodeps
bootimage-nodeps: $(MKBOOTIMG) $(AVBTOOL) $(BOARD_AVB_BOOT_KEY_PATH)
bootimage-nodeps: $(MKBOOTIMG) $(AVBTOOL) $(BOARD_AVB_BOOT_KEY_PATH) $(BOARD_GKI_SIGNING_KEY_PATH)
	@echo "make $@: ignoring dependencies"
	$(foreach b,$(INSTALLED_BOOTIMAGE_TARGET),$(call build_boot_board_avb_enabled,$(b)))

@@ -2149,8 +2167,8 @@ define build-recoveryimage-target
                 $(INTERNAL_MKBOOTIMG_VERSION_ARGS) $(BOARD_RECOVERY_MKBOOTIMG_ARGS) \
                 --output $(1).unsigned, \
    $(MKBOOTIMG) $(if $(strip $(2)),--kernel $(strip $(2))) $(INTERNAL_RECOVERYIMAGE_ARGS) \
                 $(INTERNAL_MKBOOTIMG_VERSION_ARGS) $(BOARD_RECOVERY_MKBOOTIMG_ARGS) \
                 --output $(1))
                 $(INTERNAL_MKBOOTIMG_VERSION_ARGS) $(INTERNAL_MKBOOTIMG_GKI_SINGING_ARGS) \
                 $(BOARD_RECOVERY_MKBOOTIMG_ARGS) --output $(1))
  $(if $(filter true,$(PRODUCT_SUPPORTS_BOOT_SIGNER)),\
    $(if $(filter true,$(BOARD_USES_RECOVERY_AS_BOOT)),\
      $(BOOT_SIGNER) /boot $(1) $(PRODUCT_VERITY_SIGNING_KEY).pk8 $(PRODUCT_VERITY_SIGNING_KEY).x509.pem $(1),\
@@ -2178,6 +2196,9 @@ endif
ifeq (true,$(BOARD_AVB_ENABLE))
  recoveryimage-deps += $(AVBTOOL) $(BOARD_AVB_BOOT_KEY_PATH)
endif
ifdef BOARD_GKI_SIGNING_KEY_PATH
  recoveryimage-deps += $(BOARD_GKI_SIGNING_KEY_PATH) $(AVBTOOL)
endif
ifdef BOARD_INCLUDE_RECOVERY_DTBO
  ifdef BOARD_PREBUILT_RECOVERY_DTBOIMAGE
    recoveryimage-deps += $(BOARD_PREBUILT_RECOVERY_DTBOIMAGE)
@@ -2353,17 +2374,18 @@ endef
# $(1): output file
define build-debug-bootimage-target
  $(MKBOOTIMG) --kernel $(PRODUCT_OUT)/$(subst .img,,$(subst boot-debug,kernel,$(notdir $(1)))) \
    $(INTERNAL_DEBUG_BOOTIMAGE_ARGS) $(INTERNAL_MKBOOTIMG_VERSION_ARGS) $(BOARD_MKBOOTIMG_ARGS) --output $1
    $(INTERNAL_DEBUG_BOOTIMAGE_ARGS) $(INTERNAL_MKBOOTIMG_VERSION_ARGS) \
    $(INTERNAL_MKBOOTIMG_GKI_SINGING_ARGS) $(BOARD_MKBOOTIMG_ARGS) --output $1
  $(if $(BOARD_AVB_BOOT_KEY_PATH),$(call test-key-sign-bootimage,$1,boot-debug))
endef

# Depends on original boot.img and ramdisk-debug.img, to build the new boot-debug.img
$(INSTALLED_DEBUG_BOOTIMAGE_TARGET): $(MKBOOTIMG) $(INSTALLED_BOOTIMAGE_TARGET) $(INSTALLED_DEBUG_RAMDISK_TARGET)
$(INSTALLED_DEBUG_BOOTIMAGE_TARGET): $(MKBOOTIMG) $(INSTALLED_BOOTIMAGE_TARGET) $(INSTALLED_DEBUG_RAMDISK_TARGET) $(BOARD_GKI_SIGNING_KEY_PATH) $(AVBTOOL)
	$(call pretty,"Target boot debug image: $@")
	$(call build-debug-bootimage-target, $@)

.PHONY: bootimage_debug-nodeps
bootimage_debug-nodeps: $(MKBOOTIMG)
bootimage_debug-nodeps: $(MKBOOTIMG) $(BOARD_GKI_SIGNING_KEY_PATH) $(AVBTOOL)
	echo "make $@: ignoring dependencies"
	$(foreach b,$(INSTALLED_DEBUG_BOOTIMAGE_TARGET),$(call build-debug-bootimage-target,$b))

@@ -2528,17 +2550,19 @@ endif
# $(1): output file
define build-boot-test-harness-target
  $(MKBOOTIMG) --kernel $(PRODUCT_OUT)/$(subst .img,,$(subst boot-test-harness,kernel,$(notdir $(1)))) \
    $(INTERNAL_TEST_HARNESS_BOOTIMAGE_ARGS) $(INTERNAL_MKBOOTIMG_VERSION_ARGS) $(BOARD_MKBOOTIMG_ARGS) --output $@
    $(INTERNAL_TEST_HARNESS_BOOTIMAGE_ARGS) $(INTERNAL_MKBOOTIMG_VERSION_ARGS) \
    $(INTERNAL_MKBOOTIMG_GKI_SINGING_ARGS) $(BOARD_MKBOOTIMG_ARGS) --output $@
  $(if $(BOARD_AVB_BOOT_KEY_PATH),$(call test-key-sign-bootimage,$@,boot-test-harness))
endef

# Build the new boot-test-harness.img, based on boot-debug.img and ramdisk-test-harness.img.
$(INSTALLED_TEST_HARNESS_BOOTIMAGE_TARGET): $(MKBOOTIMG) $(INSTALLED_DEBUG_BOOTIMAGE_TARGET) $(INSTALLED_TEST_HARNESS_RAMDISK_TARGET)
$(INSTALLED_TEST_HARNESS_BOOTIMAGE_TARGET): $(MKBOOTIMG) $(INSTALLED_DEBUG_BOOTIMAGE_TARGET) $(INSTALLED_TEST_HARNESS_RAMDISK_TARGET) \
$(BOARD_GKI_SIGNING_KEY_PATH) $(AVBTOOL)
	$(call pretty,"Target boot test harness image: $@")
	$(call build-boot-test-harness-target,$@)

.PHONY: bootimage_test_harness-nodeps
bootimage_test_harness-nodeps: $(MKBOOTIMG)
bootimage_test_harness-nodeps: $(MKBOOTIMG) $(BOARD_GKI_SIGNING_KEY_PATH) $(AVBTOOL)
	echo "make $@: ignoring dependencies"
	$(foreach b,$(INSTALLED_TEST_HARNESS_BOOTIMAGE_TARGET),$(call build-boot-test-harness-target,$b))

@@ -4326,6 +4350,13 @@ endif
	$(hide) echo 'mkbootimg_args=$(BOARD_MKBOOTIMG_ARGS)' >> $@
	$(hide) echo 'recovery_mkbootimg_args=$(BOARD_RECOVERY_MKBOOTIMG_ARGS)' >> $@
	$(hide) echo 'mkbootimg_version_args=$(INTERNAL_MKBOOTIMG_VERSION_ARGS)' >> $@
ifdef BOARD_GKI_SIGNING_KEY_PATH
	$(hide) echo 'gki_signing_key_path=$(BOARD_GKI_SIGNING_KEY_PATH)' >> $@
	$(hide) echo 'gki_signing_algorithm=$(BOARD_GKI_SIGNING_ALGORITHM)' >> $@
endif
ifdef BOARD_GKI_SIGNING_SIGNATURE_ARGS
	$(hide) echo 'gki_signing_signature_args=$(BOARD_GKI_SIGNING_SIGNATURE_ARGS)' >> $@
endif
	$(hide) echo "multistage_support=1" >> $@
	$(hide) echo "blockimgdiff_versions=3,4" >> $@
ifeq ($(PRODUCT_BUILD_GENERIC_OTA_PACKAGE),true)
+31 −0
Original line number Diff line number Diff line
@@ -1339,6 +1339,35 @@ def AddAftlInclusionProof(output_image):
  RunAndCheckOutput(verify_cmd)


def AppendGkiSigningArgs(cmd):
  """Append GKI signing arguments for mkbootimg."""
  # e.g., --gki_signing_key path/to/signing_key
  #       --gki_signing_algorithm SHA256_RSA4096"

  key_path = OPTIONS.info_dict.get("gki_signing_key_path")
  # It's fine that a non-GKI boot.img has no gki_signing_key_path.
  if not key_path:
    return

  if not os.path.exists(key_path) and OPTIONS.search_path:
    new_key_path = os.path.join(OPTIONS.search_path, key_path)
    if os.path.exists(new_key_path):
      key_path = new_key_path

  # Checks key_path exists, before appending --gki_signing_* args.
  if not os.path.exists(key_path):
    raise ExternalError('gki_signing_key_path: "{}" not found'.format(key_path))

  algorithm = OPTIONS.info_dict.get("gki_signing_algorithm")
  if key_path and algorithm:
    cmd.extend(["--gki_signing_key", key_path,
                "--gki_signing_algorithm", algorithm])

    signature_args = OPTIONS.info_dict.get("gki_signing_signature_args")
    if signature_args:
      cmd.extend(["--gki_signing_signature_args", signature_args])


def BuildVBMeta(image_path, partitions, name, needed_partitions):
  """Creates a VBMeta image.

@@ -1520,6 +1549,8 @@ def _BuildBootableImage(image_name, sourcedir, fs_config_file, info_dict=None,
  if has_ramdisk:
    cmd.extend(["--ramdisk", ramdisk_img.name])

  AppendGkiSigningArgs(cmd)

  img_unsigned = None
  if info_dict.get("vboot"):
    img_unsigned = tempfile.NamedTemporaryFile()
+48 −0
Original line number Diff line number Diff line
@@ -123,6 +123,17 @@ Usage: sign_target_files_apks [flags] input_target_files output_target_files
      mounted on the partition (e.g. "--signing_helper /path/to/helper"). The
      args will be appended to the existing ones in info dict.

  --gki_signing_algorithm <algorithm>
  --gki_signing_key <key>
      Use the specified algorithm (e.g. SHA256_RSA4096) and the key to generate
      'boot signature' in a v4 boot.img. Otherwise it uses the existing values
      in info dict.

  --gki_signing_extra_args <args>
      Specify any additional args that are needed to generate 'boot signature'
      (e.g. --prop foo:bar). The args will be appended to the existing ones
      in info dict.

  --android_jar_path <path>
      Path to the android.jar to repack the apex file.
"""
@@ -174,6 +185,9 @@ OPTIONS.tag_changes = ("-test-keys", "-dev-keys", "+release-keys")
OPTIONS.avb_keys = {}
OPTIONS.avb_algorithms = {}
OPTIONS.avb_extra_args = {}
OPTIONS.gki_signing_key = None
OPTIONS.gki_signing_algorithm = None
OPTIONS.gki_signing_extra_args = None
OPTIONS.android_jar_path = None


@@ -677,6 +691,9 @@ def ProcessTargetFiles(input_tf_zip, output_tf_zip, misc_info,
  if misc_info.get('avb_enable') == 'true':
    RewriteAvbProps(misc_info)

  # Replace the GKI signing key for boot.img, if any.
  ReplaceGkiSigningKey(misc_info)

  # Write back misc_info with the latest values.
  ReplaceMiscInfoTxt(input_tf_zip, output_tf_zip, misc_info)

@@ -995,6 +1012,28 @@ def RewriteAvbProps(misc_info):
      misc_info[args_key] = result


def ReplaceGkiSigningKey(misc_info):
  """Replaces the GKI signing key."""

  key = OPTIONS.gki_signing_key
  if not key:
    return

  algorithm = OPTIONS.gki_signing_algorithm
  if not algorithm:
    raise ValueError("Missing --gki_signing_algorithm")

  print('Replacing GKI signing key with "%s" (%s)' % (key, algorithm))
  misc_info["gki_signing_algorithm"] = algorithm
  misc_info["gki_signing_key_path"] = key

  extra_args = OPTIONS.gki_signing_extra_args
  if extra_args:
    print('Setting extra GKI signing args: "%s"' % (extra_args))
    misc_info["gki_signing_signature_args"] = (
        misc_info.get("gki_signing_signature_args", '') + ' ' + extra_args)


def BuildKeyMap(misc_info, key_mapping_options):
  for s, d in key_mapping_options:
    if s is None:   # -d option
@@ -1226,6 +1265,12 @@ def main(argv):
      # 'oem=--signing_helper_with_files=/tmp/avbsigner.sh'.
      partition, extra_args = a.split("=", 1)
      OPTIONS.avb_extra_args[partition] = extra_args
    elif o == "--gki_signing_key":
      OPTIONS.gki_signing_key = a
    elif o == "--gki_signing_algorithm":
      OPTIONS.gki_signing_algorithm = a
    elif o == "--gki_signing_extra_args":
      OPTIONS.gki_signing_extra_args = a
    else:
      return False
    return True
@@ -1273,6 +1318,9 @@ def main(argv):
          "avb_extra_custom_image_key=",
          "avb_extra_custom_image_algorithm=",
          "avb_extra_custom_image_extra_args=",
          "gki_signing_key=",
          "gki_signing_algorithm=",
          "gki_signing_extra_args=",
      ],
      extra_option_handler=option_handler)

+121 −0
Original line number Diff line number Diff line
@@ -1670,6 +1670,127 @@ class CommonUtilsTest(test_utils.ReleaseToolsTestCase):
                  common.OPTIONS.aftl_key_path]
    common.RunAndCheckOutput(verify_cmd)

  @test_utils.SkipIfExternalToolsUnavailable()
  def test_AppendGkiSigningArgs_NoSigningKeyPath(self):
    # A non-GKI boot.img has no gki_signing_key_path.
    common.OPTIONS.info_dict = {
        # 'gki_signing_key_path': pubkey,
        'gki_signing_algorithm': 'SHA256_RSA4096',
        'gki_signing_signature_args': '--prop foo:bar',
    }

    # Tests no --gki_signing_* args are appended if there is no
    # gki_signing_key_path.
    cmd = ['mkbootimg', '--header_version', '4']
    expected_cmd = ['mkbootimg', '--header_version', '4']
    common.AppendGkiSigningArgs(cmd)
    self.assertEqual(cmd, expected_cmd)

  def test_AppendGkiSigningArgs_NoSigningAlgorithm(self):
    pubkey = os.path.join(self.testdata_dir, 'testkey_gki.pem')
    with open(pubkey, 'wb') as f:
      f.write(b'\x00' * 100)
    self.assertTrue(os.path.exists(pubkey))

    # Tests no --gki_signing_* args are appended if there is no
    # gki_signing_algorithm.
    common.OPTIONS.info_dict = {
        'gki_signing_key_path': pubkey,
        # 'gki_signing_algorithm': 'SHA256_RSA4096',
        'gki_signing_signature_args': '--prop foo:bar',
    }

    cmd = ['mkbootimg', '--header_version', '4']
    expected_cmd = ['mkbootimg', '--header_version', '4']
    common.AppendGkiSigningArgs(cmd)
    self.assertEqual(cmd, expected_cmd)

  @test_utils.SkipIfExternalToolsUnavailable()
  def test_AppendGkiSigningArgs(self):
    pubkey = os.path.join(self.testdata_dir, 'testkey_gki.pem')
    with open(pubkey, 'wb') as f:
      f.write(b'\x00' * 100)
    self.assertTrue(os.path.exists(pubkey))

    common.OPTIONS.info_dict = {
        'gki_signing_key_path': pubkey,
        'gki_signing_algorithm': 'SHA256_RSA4096',
        'gki_signing_signature_args': '--prop foo:bar',
    }
    cmd = ['mkbootimg', '--header_version', '4']
    common.AppendGkiSigningArgs(cmd)

    expected_cmd = [
      'mkbootimg', '--header_version', '4',
      '--gki_signing_key', pubkey,
      '--gki_signing_algorithm', 'SHA256_RSA4096',
      '--gki_signing_signature_args', '--prop foo:bar'
    ]
    self.assertEqual(cmd, expected_cmd)

  @test_utils.SkipIfExternalToolsUnavailable()
  def test_AppendGkiSigningArgs_KeyPathNotFound(self):
    pubkey = os.path.join(self.testdata_dir, 'no_testkey_gki.pem')
    self.assertFalse(os.path.exists(pubkey))

    common.OPTIONS.info_dict = {
        'gki_signing_key_path': pubkey,
        'gki_signing_algorithm': 'SHA256_RSA4096',
        'gki_signing_signature_args': '--prop foo:bar',
    }
    cmd = ['mkbootimg', '--header_version', '4']
    self.assertRaises(common.ExternalError, common.AppendGkiSigningArgs, cmd)

  @test_utils.SkipIfExternalToolsUnavailable()
  def test_AppendGkiSigningArgs_SearchKeyPath(self):
    pubkey = 'testkey_gki.pem'
    self.assertFalse(os.path.exists(pubkey))

    # Tests it should replace the pubkey with an existed key under
    # OPTIONS.search_path, i.e., os.path.join(OPTIONS.search_path, pubkey).
    search_path_dir = common.MakeTempDir()
    search_pubkey = os.path.join(search_path_dir, pubkey)
    with open(search_pubkey, 'wb') as f:
      f.write(b'\x00' * 100)
    self.assertTrue(os.path.exists(search_pubkey))

    common.OPTIONS.search_path = search_path_dir
    common.OPTIONS.info_dict = {
        'gki_signing_key_path': pubkey,
        'gki_signing_algorithm': 'SHA256_RSA4096',
        'gki_signing_signature_args': '--prop foo:bar',
    }
    cmd = ['mkbootimg', '--header_version', '4']
    common.AppendGkiSigningArgs(cmd)

    expected_cmd = [
      'mkbootimg', '--header_version', '4',
      '--gki_signing_key', search_pubkey,
      '--gki_signing_algorithm', 'SHA256_RSA4096',
      '--gki_signing_signature_args', '--prop foo:bar'
    ]
    self.assertEqual(cmd, expected_cmd)

  @test_utils.SkipIfExternalToolsUnavailable()
  def test_AppendGkiSigningArgs_SearchKeyPathNotFound(self):
    pubkey = 'no_testkey_gki.pem'
    self.assertFalse(os.path.exists(pubkey))

    # Tests it should raise ExternalError if no key found under
    # OPTIONS.search_path.
    search_path_dir = common.MakeTempDir()
    search_pubkey = os.path.join(search_path_dir, pubkey)
    self.assertFalse(os.path.exists(search_pubkey))

    common.OPTIONS.search_path = search_path_dir
    common.OPTIONS.info_dict = {
        'gki_signing_key_path': pubkey,
        'gki_signing_algorithm': 'SHA256_RSA4096',
        'gki_signing_signature_args': '--prop foo:bar',
    }
    cmd = ['mkbootimg', '--header_version', '4']
    self.assertRaises(common.ExternalError, common.AppendGkiSigningArgs, cmd)


class InstallRecoveryScriptFormatTest(test_utils.ReleaseToolsTestCase):
  """Checks the format of install-recovery.sh.
+51 −2
Original line number Diff line number Diff line
@@ -23,8 +23,8 @@ import common
import test_utils
from sign_target_files_apks import (
    CheckApkAndApexKeysAvailable, EditTags, GetApkFileInfo, ReadApexKeysInfo,
    ReplaceCerts, ReplaceVerityKeyId, RewriteAvbProps, RewriteProps,
    WriteOtacerts)
    ReplaceCerts, ReplaceGkiSigningKey, ReplaceVerityKeyId, RewriteAvbProps,
    RewriteProps, WriteOtacerts)


class SignTargetFilesApksTest(test_utils.ReleaseToolsTestCase):
@@ -588,3 +588,52 @@ name="apex.apexd_test_different_app.apex" public_key="system/apex/apexd/apexd_te
            'system/apex/apexd/apexd_testdata/com.android.apex.test_package_2.pem',
            'build/make/target/product/security/testkey'),
        }, keys_info)

  def test_ReplaceGkiSigningKey(self):
    common.OPTIONS.gki_signing_key = 'release_gki_key'
    common.OPTIONS.gki_signing_algorithm = 'release_gki_algorithm'
    common.OPTIONS.gki_signing_extra_args = 'release_gki_signature_extra_args'

    misc_info = {
        'gki_signing_key_path': 'default_gki_key',
        'gki_signing_algorithm': 'default_gki_algorithm',
        'gki_signing_signature_args': 'default_gki_signature_args',
    }
    expected_dict = {
        'gki_signing_key_path': 'release_gki_key',
        'gki_signing_algorithm': 'release_gki_algorithm',
        'gki_signing_signature_args': 'default_gki_signature_args release_gki_signature_extra_args',
    }
    ReplaceGkiSigningKey(misc_info)
    self.assertDictEqual(expected_dict, misc_info)

  def test_ReplaceGkiSigningKey_MissingSigningAlgorithm(self):
    common.OPTIONS.gki_signing_key = 'release_gki_key'
    common.OPTIONS.gki_signing_algorithm = None
    common.OPTIONS.gki_signing_extra_args = 'release_gki_signature_extra_args'

    misc_info = {
        'gki_signing_key_path': 'default_gki_key',
        'gki_signing_algorithm': 'default_gki_algorithm',
        'gki_signing_signature_args': 'default_gki_signature_args',
    }
    self.assertRaises(ValueError, ReplaceGkiSigningKey, misc_info)

  def test_ReplaceGkiSigningKey_MissingSigningKeyNop(self):
    common.OPTIONS.gki_signing_key = None
    common.OPTIONS.gki_signing_algorithm = 'release_gki_algorithm'
    common.OPTIONS.gki_signing_extra_args = 'release_gki_signature_extra_args'

    # No change to misc_info if common.OPTIONS.gki_signing_key is missing.
    misc_info = {
        'gki_signing_key_path': 'default_gki_key',
        'gki_signing_algorithm': 'default_gki_algorithm',
        'gki_signing_signature_args': 'default_gki_signature_args',
    }
    expected_dict = {
        'gki_signing_key_path': 'default_gki_key',
        'gki_signing_algorithm': 'default_gki_algorithm',
        'gki_signing_signature_args': 'default_gki_signature_args',
    }
    ReplaceGkiSigningKey(misc_info)
    self.assertDictEqual(expected_dict, misc_info)