Merge "Revert "releasetools: Deprecate GKI build rules"" into main
This commit is contained in:
commit
e5bfa38457
6 changed files with 207 additions and 3 deletions
|
@ -168,6 +168,7 @@ python_defaults {
|
||||||
"apexd_host",
|
"apexd_host",
|
||||||
"brillo_update_payload",
|
"brillo_update_payload",
|
||||||
"checkvintf",
|
"checkvintf",
|
||||||
|
"generate_gki_certificate",
|
||||||
"lz4",
|
"lz4",
|
||||||
"toybox",
|
"toybox",
|
||||||
"unpack_bootimg",
|
"unpack_bootimg",
|
||||||
|
@ -244,6 +245,7 @@ python_library_host {
|
||||||
"boot_signer",
|
"boot_signer",
|
||||||
"brotli",
|
"brotli",
|
||||||
"bsdiff",
|
"bsdiff",
|
||||||
|
"generate_gki_certificate",
|
||||||
"imgdiff",
|
"imgdiff",
|
||||||
"lz4",
|
"lz4",
|
||||||
"mkbootfs",
|
"mkbootfs",
|
||||||
|
@ -308,6 +310,7 @@ python_defaults {
|
||||||
"brotli",
|
"brotli",
|
||||||
"bsdiff",
|
"bsdiff",
|
||||||
"deapexer",
|
"deapexer",
|
||||||
|
"generate_gki_certificate",
|
||||||
"imgdiff",
|
"imgdiff",
|
||||||
"lz4",
|
"lz4",
|
||||||
"mkbootfs",
|
"mkbootfs",
|
||||||
|
|
|
@ -1575,6 +1575,50 @@ def GetAvbChainedPartitionArg(partition, info_dict, key=None):
|
||||||
pubkey_path=pubkey_path)
|
pubkey_path=pubkey_path)
|
||||||
|
|
||||||
|
|
||||||
|
def _HasGkiCertificationArgs():
|
||||||
|
return ("gki_signing_key_path" in OPTIONS.info_dict and
|
||||||
|
"gki_signing_algorithm" in OPTIONS.info_dict)
|
||||||
|
|
||||||
|
|
||||||
|
def _GenerateGkiCertificate(image, image_name):
|
||||||
|
key_path = OPTIONS.info_dict.get("gki_signing_key_path")
|
||||||
|
algorithm = OPTIONS.info_dict.get("gki_signing_algorithm")
|
||||||
|
|
||||||
|
key_path = ResolveAVBSigningPathArgs(key_path)
|
||||||
|
|
||||||
|
# Checks key_path exists, before processing --gki_signing_* args.
|
||||||
|
if not os.path.exists(key_path):
|
||||||
|
raise ExternalError(
|
||||||
|
'gki_signing_key_path: "{}" not found'.format(key_path))
|
||||||
|
|
||||||
|
output_certificate = tempfile.NamedTemporaryFile()
|
||||||
|
cmd = [
|
||||||
|
"generate_gki_certificate",
|
||||||
|
"--name", image_name,
|
||||||
|
"--algorithm", algorithm,
|
||||||
|
"--key", key_path,
|
||||||
|
"--output", output_certificate.name,
|
||||||
|
image,
|
||||||
|
]
|
||||||
|
|
||||||
|
signature_args = OPTIONS.info_dict.get("gki_signing_signature_args", "")
|
||||||
|
signature_args = signature_args.strip()
|
||||||
|
if signature_args:
|
||||||
|
cmd.extend(["--additional_avb_args", signature_args])
|
||||||
|
|
||||||
|
args = OPTIONS.info_dict.get("avb_boot_add_hash_footer_args", "")
|
||||||
|
args = args.strip()
|
||||||
|
if args:
|
||||||
|
cmd.extend(["--additional_avb_args", args])
|
||||||
|
|
||||||
|
RunAndCheckOutput(cmd)
|
||||||
|
|
||||||
|
output_certificate.seek(os.SEEK_SET, 0)
|
||||||
|
data = output_certificate.read()
|
||||||
|
output_certificate.close()
|
||||||
|
return data
|
||||||
|
|
||||||
|
|
||||||
def BuildVBMeta(image_path, partitions, name, needed_partitions,
|
def BuildVBMeta(image_path, partitions, name, needed_partitions,
|
||||||
resolve_rollback_index_location_conflict=False):
|
resolve_rollback_index_location_conflict=False):
|
||||||
"""Creates a VBMeta image.
|
"""Creates a VBMeta image.
|
||||||
|
@ -1797,6 +1841,29 @@ def _BuildBootableImage(image_name, sourcedir, fs_config_file,
|
||||||
|
|
||||||
RunAndCheckOutput(cmd)
|
RunAndCheckOutput(cmd)
|
||||||
|
|
||||||
|
if _HasGkiCertificationArgs():
|
||||||
|
if not os.path.exists(img.name):
|
||||||
|
raise ValueError("Cannot find GKI boot.img")
|
||||||
|
if kernel_path is None or not os.path.exists(kernel_path):
|
||||||
|
raise ValueError("Cannot find GKI kernel.img")
|
||||||
|
|
||||||
|
# Certify GKI images.
|
||||||
|
boot_signature_bytes = b''
|
||||||
|
boot_signature_bytes += _GenerateGkiCertificate(img.name, "boot")
|
||||||
|
boot_signature_bytes += _GenerateGkiCertificate(
|
||||||
|
kernel_path, "generic_kernel")
|
||||||
|
|
||||||
|
BOOT_SIGNATURE_SIZE = 16 * 1024
|
||||||
|
if len(boot_signature_bytes) > BOOT_SIGNATURE_SIZE:
|
||||||
|
raise ValueError(
|
||||||
|
f"GKI boot_signature size must be <= {BOOT_SIGNATURE_SIZE}")
|
||||||
|
boot_signature_bytes += (
|
||||||
|
b'\0' * (BOOT_SIGNATURE_SIZE - len(boot_signature_bytes)))
|
||||||
|
assert len(boot_signature_bytes) == BOOT_SIGNATURE_SIZE
|
||||||
|
|
||||||
|
with open(img.name, 'ab') as f:
|
||||||
|
f.write(boot_signature_bytes)
|
||||||
|
|
||||||
# Sign the image if vboot is non-empty.
|
# Sign the image if vboot is non-empty.
|
||||||
if info_dict.get("vboot"):
|
if info_dict.get("vboot"):
|
||||||
path = "/" + partition_name
|
path = "/" + partition_name
|
||||||
|
@ -1910,6 +1977,9 @@ def HasRamdisk(partition_name, info_dict=None):
|
||||||
if info_dict.get("recovery_as_boot") == "true":
|
if info_dict.get("recovery_as_boot") == "true":
|
||||||
return True # the recovery-as-boot boot.img has a RECOVERY ramdisk.
|
return True # the recovery-as-boot boot.img has a RECOVERY ramdisk.
|
||||||
|
|
||||||
|
if info_dict.get("gki_boot_image_without_ramdisk") == "true":
|
||||||
|
return False # A GKI boot.img has no ramdisk since Android-13.
|
||||||
|
|
||||||
if info_dict.get("system_root_image") == "true":
|
if info_dict.get("system_root_image") == "true":
|
||||||
# The ramdisk content is merged into the system.img, so there is NO
|
# The ramdisk content is merged into the system.img, so there is NO
|
||||||
# ramdisk in the boot.img or boot-<kernel version>.img.
|
# ramdisk in the boot.img or boot-<kernel version>.img.
|
||||||
|
|
|
@ -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
|
mounted on the partition (e.g. "--signing_helper /path/to/helper"). The
|
||||||
args will be appended to the existing ones in info dict.
|
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>
|
--android_jar_path <path>
|
||||||
Path to the android.jar to repack the apex file.
|
Path to the android.jar to repack the apex file.
|
||||||
|
|
||||||
|
@ -182,6 +193,9 @@ OPTIONS.tag_changes = ("-test-keys", "-dev-keys", "+release-keys")
|
||||||
OPTIONS.avb_keys = {}
|
OPTIONS.avb_keys = {}
|
||||||
OPTIONS.avb_algorithms = {}
|
OPTIONS.avb_algorithms = {}
|
||||||
OPTIONS.avb_extra_args = {}
|
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
|
OPTIONS.android_jar_path = None
|
||||||
OPTIONS.vendor_partitions = set()
|
OPTIONS.vendor_partitions = set()
|
||||||
OPTIONS.vendor_otatools = None
|
OPTIONS.vendor_otatools = None
|
||||||
|
@ -538,7 +552,7 @@ def ProcessTargetFiles(input_tf_zip, output_tf_zip, misc_info,
|
||||||
[len(os.path.basename(i.filename)) for i in input_tf_zip.infolist()
|
[len(os.path.basename(i.filename)) for i in input_tf_zip.infolist()
|
||||||
if GetApkFileInfo(i.filename, compressed_extension, [])[0]])
|
if GetApkFileInfo(i.filename, compressed_extension, [])[0]])
|
||||||
except ValueError:
|
except ValueError:
|
||||||
# Sets this to zero for targets without APK files.
|
# Sets this to zero for targets without APK files, e.g., gki_arm64.
|
||||||
maxsize = 0
|
maxsize = 0
|
||||||
|
|
||||||
system_root_image = misc_info.get("system_root_image") == "true"
|
system_root_image = misc_info.get("system_root_image") == "true"
|
||||||
|
@ -754,6 +768,9 @@ def ProcessTargetFiles(input_tf_zip, output_tf_zip, misc_info,
|
||||||
if misc_info.get('avb_enable') == 'true':
|
if misc_info.get('avb_enable') == 'true':
|
||||||
RewriteAvbProps(misc_info)
|
RewriteAvbProps(misc_info)
|
||||||
|
|
||||||
|
# Replace the GKI signing key for boot.img, if any.
|
||||||
|
ReplaceGkiSigningKey(misc_info)
|
||||||
|
|
||||||
# Write back misc_info with the latest values.
|
# Write back misc_info with the latest values.
|
||||||
ReplaceMiscInfoTxt(input_tf_zip, output_tf_zip, misc_info)
|
ReplaceMiscInfoTxt(input_tf_zip, output_tf_zip, misc_info)
|
||||||
|
|
||||||
|
@ -1035,6 +1052,27 @@ def RewriteAvbProps(misc_info):
|
||||||
misc_info[args_key] = result
|
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 GKI signing args: "%s"' % (extra_args))
|
||||||
|
misc_info["gki_signing_signature_args"] = extra_args
|
||||||
|
|
||||||
|
|
||||||
def BuildKeyMap(misc_info, key_mapping_options):
|
def BuildKeyMap(misc_info, key_mapping_options):
|
||||||
for s, d in key_mapping_options:
|
for s, d in key_mapping_options:
|
||||||
if s is None: # -d option
|
if s is None: # -d option
|
||||||
|
@ -1388,6 +1426,12 @@ def main(argv):
|
||||||
# 'oem=--signing_helper_with_files=/tmp/avbsigner.sh'.
|
# 'oem=--signing_helper_with_files=/tmp/avbsigner.sh'.
|
||||||
partition, extra_args = a.split("=", 1)
|
partition, extra_args = a.split("=", 1)
|
||||||
OPTIONS.avb_extra_args[partition] = extra_args
|
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
|
||||||
elif o == "--vendor_otatools":
|
elif o == "--vendor_otatools":
|
||||||
OPTIONS.vendor_otatools = a
|
OPTIONS.vendor_otatools = a
|
||||||
elif o == "--vendor_partitions":
|
elif o == "--vendor_partitions":
|
||||||
|
@ -1451,6 +1495,9 @@ def main(argv):
|
||||||
"avb_extra_custom_image_key=",
|
"avb_extra_custom_image_key=",
|
||||||
"avb_extra_custom_image_algorithm=",
|
"avb_extra_custom_image_algorithm=",
|
||||||
"avb_extra_custom_image_extra_args=",
|
"avb_extra_custom_image_extra_args=",
|
||||||
|
"gki_signing_key=",
|
||||||
|
"gki_signing_algorithm=",
|
||||||
|
"gki_signing_extra_args=",
|
||||||
"vendor_partitions=",
|
"vendor_partitions=",
|
||||||
"vendor_otatools=",
|
"vendor_otatools=",
|
||||||
"allow_gsi_debug_sepolicy",
|
"allow_gsi_debug_sepolicy",
|
||||||
|
|
|
@ -1636,6 +1636,40 @@ class CommonUtilsTest(test_utils.ReleaseToolsTestCase):
|
||||||
self.assertEqual(3, chained_partition_args.rollback_index_location)
|
self.assertEqual(3, chained_partition_args.rollback_index_location)
|
||||||
self.assertTrue(os.path.exists(chained_partition_args.pubkey_path))
|
self.assertTrue(os.path.exists(chained_partition_args.pubkey_path))
|
||||||
|
|
||||||
|
def test_GenerateGkiCertificate_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',
|
||||||
|
}
|
||||||
|
common.OPTIONS.search_path = None
|
||||||
|
test_file = tempfile.NamedTemporaryFile()
|
||||||
|
self.assertRaises(common.ExternalError, common._GenerateGkiCertificate,
|
||||||
|
test_file.name, 'generic_kernel')
|
||||||
|
|
||||||
|
def test_GenerateGkiCertificate_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',
|
||||||
|
}
|
||||||
|
test_file = tempfile.NamedTemporaryFile()
|
||||||
|
self.assertRaises(common.ExternalError, common._GenerateGkiCertificate,
|
||||||
|
test_file.name, 'generic_kernel')
|
||||||
|
|
||||||
|
|
||||||
class InstallRecoveryScriptFormatTest(test_utils.ReleaseToolsTestCase):
|
class InstallRecoveryScriptFormatTest(test_utils.ReleaseToolsTestCase):
|
||||||
"""Checks the format of install-recovery.sh.
|
"""Checks the format of install-recovery.sh.
|
||||||
|
|
|
@ -23,7 +23,8 @@ import common
|
||||||
import test_utils
|
import test_utils
|
||||||
from sign_target_files_apks import (
|
from sign_target_files_apks import (
|
||||||
CheckApkAndApexKeysAvailable, EditTags, GetApkFileInfo, ReadApexKeysInfo,
|
CheckApkAndApexKeysAvailable, EditTags, GetApkFileInfo, ReadApexKeysInfo,
|
||||||
ReplaceCerts, RewriteAvbProps, RewriteProps, WriteOtacerts)
|
ReplaceCerts, ReplaceGkiSigningKey, RewriteAvbProps, RewriteProps,
|
||||||
|
WriteOtacerts)
|
||||||
|
|
||||||
|
|
||||||
class SignTargetFilesApksTest(test_utils.ReleaseToolsTestCase):
|
class SignTargetFilesApksTest(test_utils.ReleaseToolsTestCase):
|
||||||
|
@ -535,3 +536,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',
|
'system/apex/apexd/apexd_testdata/com.android.apex.test_package_2.pem',
|
||||||
'build/make/target/product/security/testkey', None),
|
'build/make/target/product/security/testkey', None),
|
||||||
}, keys_info)
|
}, 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': '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)
|
||||||
|
|
|
@ -132,7 +132,7 @@ def ValidateFileConsistency(input_zip, input_tmp, info_dict):
|
||||||
return
|
return
|
||||||
|
|
||||||
# Verify IMAGES/system.img if applicable.
|
# Verify IMAGES/system.img if applicable.
|
||||||
# Some targets are system.img-less.
|
# Some targets, e.g., gki_arm64, gki_x86_64, etc., are system.img-less.
|
||||||
if 'IMAGES/system.img' in input_zip.namelist():
|
if 'IMAGES/system.img' in input_zip.namelist():
|
||||||
CheckAllFiles('system')
|
CheckAllFiles('system')
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue