Support custom APEX signing tool
When an APEX specifies its custom signing tool (custom_sign_tool:), apexkeys.txt contains the info and sign_target_files_apks pass the value to apex_util. For now the Virt APEX has its own custom signing tool (sign_virt_apex), which is added to OTATOOLS. Bug: 193504286 Test: sign_target_files_apks invokes sign_virt_apex Change-Id: Iba845723fe3e18f542963324b9c58cd00914c5ba
This commit is contained in:
@@ -4323,6 +4323,7 @@ INTERNAL_OTATOOLS_MODULES := \
|
|||||||
shflags \
|
shflags \
|
||||||
sign_apex \
|
sign_apex \
|
||||||
sign_target_files_apks \
|
sign_target_files_apks \
|
||||||
|
sign_virt_apex \
|
||||||
signapk \
|
signapk \
|
||||||
simg2img \
|
simg2img \
|
||||||
sload_f2fs \
|
sload_f2fs \
|
||||||
|
@@ -142,6 +142,7 @@ class ApexApkSigner(object):
|
|||||||
has_signed_content = True
|
has_signed_content = True
|
||||||
|
|
||||||
if self.sign_tool:
|
if self.sign_tool:
|
||||||
|
logger.info('Signing payload contents in apex %s with %s', self.apex_path, self.sign_tool)
|
||||||
cmd = [self.sign_tool, '--avbtool', self.avbtool, payload_key, payload_dir]
|
cmd = [self.sign_tool, '--avbtool', self.avbtool, payload_key, payload_dir]
|
||||||
common.RunAndCheckOutput(cmd)
|
common.RunAndCheckOutput(cmd)
|
||||||
has_signed_content = True
|
has_signed_content = True
|
||||||
|
@@ -2107,7 +2107,7 @@ def GetKeyPasswords(keylist):
|
|||||||
devnull = open("/dev/null", "w+b")
|
devnull = open("/dev/null", "w+b")
|
||||||
for k in sorted(keylist):
|
for k in sorted(keylist):
|
||||||
# We don't need a password for things that aren't really keys.
|
# We don't need a password for things that aren't really keys.
|
||||||
if k in SPECIAL_CERT_STRINGS:
|
if k in SPECIAL_CERT_STRINGS or k is None:
|
||||||
no_passwords.append(k)
|
no_passwords.append(k)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
@@ -262,7 +262,7 @@ def GetApexKeys(keys_info, key_map):
|
|||||||
|
|
||||||
Args:
|
Args:
|
||||||
keys_info: A dict that maps from APEX filenames to a tuple of (payload_key,
|
keys_info: A dict that maps from APEX filenames to a tuple of (payload_key,
|
||||||
container_key).
|
container_key, sign_tool).
|
||||||
key_map: A dict that overrides the keys, specified via command-line input.
|
key_map: A dict that overrides the keys, specified via command-line input.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
@@ -280,11 +280,11 @@ def GetApexKeys(keys_info, key_map):
|
|||||||
if apex not in keys_info:
|
if apex not in keys_info:
|
||||||
logger.warning('Failed to find %s in target_files; Ignored', apex)
|
logger.warning('Failed to find %s in target_files; Ignored', apex)
|
||||||
continue
|
continue
|
||||||
keys_info[apex] = (key, keys_info[apex][1])
|
keys_info[apex] = (key, keys_info[apex][1], keys_info[apex][2])
|
||||||
|
|
||||||
# Apply the key remapping to container keys.
|
# Apply the key remapping to container keys.
|
||||||
for apex, (payload_key, container_key) in keys_info.items():
|
for apex, (payload_key, container_key, sign_tool) in keys_info.items():
|
||||||
keys_info[apex] = (payload_key, key_map.get(container_key, container_key))
|
keys_info[apex] = (payload_key, key_map.get(container_key, container_key), sign_tool)
|
||||||
|
|
||||||
# Apply all the --extra_apks options to override the container keys.
|
# Apply all the --extra_apks options to override the container keys.
|
||||||
for apex, key in OPTIONS.extra_apks.items():
|
for apex, key in OPTIONS.extra_apks.items():
|
||||||
@@ -293,13 +293,13 @@ def GetApexKeys(keys_info, key_map):
|
|||||||
continue
|
continue
|
||||||
if not key:
|
if not key:
|
||||||
key = 'PRESIGNED'
|
key = 'PRESIGNED'
|
||||||
keys_info[apex] = (keys_info[apex][0], key_map.get(key, key))
|
keys_info[apex] = (keys_info[apex][0], key_map.get(key, key), keys_info[apex][2])
|
||||||
|
|
||||||
# A PRESIGNED container entails a PRESIGNED payload. Apply this to all the
|
# A PRESIGNED container entails a PRESIGNED payload. Apply this to all the
|
||||||
# APEX key pairs. However, a PRESIGNED container with non-PRESIGNED payload
|
# APEX key pairs. However, a PRESIGNED container with non-PRESIGNED payload
|
||||||
# (overridden via commandline) indicates a config error, which should not be
|
# (overridden via commandline) indicates a config error, which should not be
|
||||||
# allowed.
|
# allowed.
|
||||||
for apex, (payload_key, container_key) in keys_info.items():
|
for apex, (payload_key, container_key, sign_tool) in keys_info.items():
|
||||||
if container_key != 'PRESIGNED':
|
if container_key != 'PRESIGNED':
|
||||||
continue
|
continue
|
||||||
if apex in OPTIONS.extra_apex_payload_keys:
|
if apex in OPTIONS.extra_apex_payload_keys:
|
||||||
@@ -311,7 +311,7 @@ def GetApexKeys(keys_info, key_map):
|
|||||||
print(
|
print(
|
||||||
"Setting {} payload as PRESIGNED due to PRESIGNED container".format(
|
"Setting {} payload as PRESIGNED due to PRESIGNED container".format(
|
||||||
apex))
|
apex))
|
||||||
keys_info[apex] = ('PRESIGNED', 'PRESIGNED')
|
keys_info[apex] = ('PRESIGNED', 'PRESIGNED', None)
|
||||||
|
|
||||||
return keys_info
|
return keys_info
|
||||||
|
|
||||||
@@ -372,7 +372,7 @@ def CheckApkAndApexKeysAvailable(input_tf_zip, known_keys,
|
|||||||
compressed_extension: The extension string of compressed APKs, such as
|
compressed_extension: The extension string of compressed APKs, such as
|
||||||
'.gz', or None if there's no compressed APKs.
|
'.gz', or None if there's no compressed APKs.
|
||||||
apex_keys: A dict that contains the key mapping from APEX name to
|
apex_keys: A dict that contains the key mapping from APEX name to
|
||||||
(payload_key, container_key).
|
(payload_key, container_key, sign_tool).
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
AssertionError: On finding unknown APKs and APEXes.
|
AssertionError: On finding unknown APKs and APEXes.
|
||||||
@@ -417,7 +417,7 @@ def CheckApkAndApexKeysAvailable(input_tf_zip, known_keys,
|
|||||||
|
|
||||||
name = GetApexFilename(info.filename)
|
name = GetApexFilename(info.filename)
|
||||||
|
|
||||||
(payload_key, container_key) = apex_keys[name]
|
(payload_key, container_key, _) = apex_keys[name]
|
||||||
if ((payload_key in common.SPECIAL_CERT_STRINGS and
|
if ((payload_key in common.SPECIAL_CERT_STRINGS and
|
||||||
container_key not in common.SPECIAL_CERT_STRINGS) or
|
container_key not in common.SPECIAL_CERT_STRINGS) or
|
||||||
(payload_key not in common.SPECIAL_CERT_STRINGS and
|
(payload_key not in common.SPECIAL_CERT_STRINGS and
|
||||||
@@ -569,7 +569,7 @@ def ProcessTargetFiles(input_tf_zip, output_tf_zip, misc_info,
|
|||||||
elif IsApexFile(filename):
|
elif IsApexFile(filename):
|
||||||
name = GetApexFilename(filename)
|
name = GetApexFilename(filename)
|
||||||
|
|
||||||
payload_key, container_key = apex_keys[name]
|
payload_key, container_key, sign_tool = apex_keys[name]
|
||||||
|
|
||||||
# We've asserted not having a case with only one of them PRESIGNED.
|
# We've asserted not having a case with only one of them PRESIGNED.
|
||||||
if (payload_key not in common.SPECIAL_CERT_STRINGS and
|
if (payload_key not in common.SPECIAL_CERT_STRINGS and
|
||||||
@@ -588,7 +588,8 @@ def ProcessTargetFiles(input_tf_zip, output_tf_zip, misc_info,
|
|||||||
apk_keys,
|
apk_keys,
|
||||||
codename_to_api_level_map,
|
codename_to_api_level_map,
|
||||||
no_hashtree=None, # Let apex_util determine if hash tree is needed
|
no_hashtree=None, # Let apex_util determine if hash tree is needed
|
||||||
signing_args=OPTIONS.avb_extra_args.get('apex'))
|
signing_args=OPTIONS.avb_extra_args.get('apex'),
|
||||||
|
sign_tool=sign_tool)
|
||||||
common.ZipWrite(output_tf_zip, signed_apex, filename)
|
common.ZipWrite(output_tf_zip, signed_apex, filename)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
@@ -1147,15 +1148,16 @@ def ReadApexKeysInfo(tf_zip):
|
|||||||
|
|
||||||
Given a target-files ZipFile, parses the META/apexkeys.txt entry and returns a
|
Given a target-files ZipFile, parses the META/apexkeys.txt entry and returns a
|
||||||
dict that contains the mapping from APEX names (e.g. com.android.tzdata) to a
|
dict that contains the mapping from APEX names (e.g. com.android.tzdata) to a
|
||||||
tuple of (payload_key, container_key).
|
tuple of (payload_key, container_key, sign_tool).
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
tf_zip: The input target_files ZipFile (already open).
|
tf_zip: The input target_files ZipFile (already open).
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
(payload_key, container_key): payload_key contains the path to the payload
|
(payload_key, container_key, sign_tool):
|
||||||
signing key; container_key contains the path to the container signing
|
- payload_key contains the path to the payload signing key
|
||||||
key.
|
- container_key contains the path to the container signing key
|
||||||
|
- sign_tool is an apex-specific signing tool for its payload contents
|
||||||
"""
|
"""
|
||||||
keys = {}
|
keys = {}
|
||||||
for line in tf_zip.read('META/apexkeys.txt').decode().split('\n'):
|
for line in tf_zip.read('META/apexkeys.txt').decode().split('\n'):
|
||||||
@@ -1168,7 +1170,8 @@ def ReadApexKeysInfo(tf_zip):
|
|||||||
r'private_key="(?P<PAYLOAD_PRIVATE_KEY>.*)"\s+'
|
r'private_key="(?P<PAYLOAD_PRIVATE_KEY>.*)"\s+'
|
||||||
r'container_certificate="(?P<CONTAINER_CERT>.*)"\s+'
|
r'container_certificate="(?P<CONTAINER_CERT>.*)"\s+'
|
||||||
r'container_private_key="(?P<CONTAINER_PRIVATE_KEY>.*?)"'
|
r'container_private_key="(?P<CONTAINER_PRIVATE_KEY>.*?)"'
|
||||||
r'(\s+partition="(?P<PARTITION>.*?)")?$',
|
r'(\s+partition="(?P<PARTITION>.*?)")?'
|
||||||
|
r'(\s+sign_tool="(?P<SIGN_TOOL>.*?)")?$',
|
||||||
line)
|
line)
|
||||||
if not matches:
|
if not matches:
|
||||||
continue
|
continue
|
||||||
@@ -1197,7 +1200,8 @@ def ReadApexKeysInfo(tf_zip):
|
|||||||
else:
|
else:
|
||||||
raise ValueError("Failed to parse container keys: \n{}".format(line))
|
raise ValueError("Failed to parse container keys: \n{}".format(line))
|
||||||
|
|
||||||
keys[name] = (payload_private_key, container_key)
|
sign_tool = matches.group("SIGN_TOOL")
|
||||||
|
keys[name] = (payload_private_key, container_key, sign_tool)
|
||||||
|
|
||||||
return keys
|
return keys
|
||||||
|
|
||||||
|
@@ -328,23 +328,23 @@ name="apex.apexd_test_different_app.apex" public_key="system/apex/apexd/apexd_te
|
|||||||
'Apex3.apex' : 'key3',
|
'Apex3.apex' : 'key3',
|
||||||
}
|
}
|
||||||
apex_keys = {
|
apex_keys = {
|
||||||
'Apex1.apex' : ('payload-key1', 'container-key1'),
|
'Apex1.apex' : ('payload-key1', 'container-key1', None),
|
||||||
'Apex2.apex' : ('payload-key2', 'container-key2'),
|
'Apex2.apex' : ('payload-key2', 'container-key2', None),
|
||||||
}
|
}
|
||||||
with zipfile.ZipFile(input_file) as input_zip:
|
with zipfile.ZipFile(input_file) as input_zip:
|
||||||
CheckApkAndApexKeysAvailable(input_zip, apk_key_map, None, apex_keys)
|
CheckApkAndApexKeysAvailable(input_zip, apk_key_map, None, apex_keys)
|
||||||
|
|
||||||
# Fine to have both keys as PRESIGNED.
|
# Fine to have both keys as PRESIGNED.
|
||||||
apex_keys['Apex2.apex'] = ('PRESIGNED', 'PRESIGNED')
|
apex_keys['Apex2.apex'] = ('PRESIGNED', 'PRESIGNED', None)
|
||||||
CheckApkAndApexKeysAvailable(input_zip, apk_key_map, None, apex_keys)
|
CheckApkAndApexKeysAvailable(input_zip, apk_key_map, None, apex_keys)
|
||||||
|
|
||||||
# Having only one of them as PRESIGNED is not allowed.
|
# Having only one of them as PRESIGNED is not allowed.
|
||||||
apex_keys['Apex2.apex'] = ('payload-key2', 'PRESIGNED')
|
apex_keys['Apex2.apex'] = ('payload-key2', 'PRESIGNED', None)
|
||||||
self.assertRaises(
|
self.assertRaises(
|
||||||
AssertionError, CheckApkAndApexKeysAvailable, input_zip, apk_key_map,
|
AssertionError, CheckApkAndApexKeysAvailable, input_zip, apk_key_map,
|
||||||
None, apex_keys)
|
None, apex_keys)
|
||||||
|
|
||||||
apex_keys['Apex2.apex'] = ('PRESIGNED', 'container-key1')
|
apex_keys['Apex2.apex'] = ('PRESIGNED', 'container-key1', None)
|
||||||
self.assertRaises(
|
self.assertRaises(
|
||||||
AssertionError, CheckApkAndApexKeysAvailable, input_zip, apk_key_map,
|
AssertionError, CheckApkAndApexKeysAvailable, input_zip, apk_key_map,
|
||||||
None, apex_keys)
|
None, apex_keys)
|
||||||
@@ -475,10 +475,10 @@ name="apex.apexd_test_different_app.apex" public_key="system/apex/apexd/apexd_te
|
|||||||
self.assertEqual({
|
self.assertEqual({
|
||||||
'apex.apexd_test.apex': (
|
'apex.apexd_test.apex': (
|
||||||
'system/apex/apexd/apexd_testdata/com.android.apex.test_package.pem',
|
'system/apex/apexd/apexd_testdata/com.android.apex.test_package.pem',
|
||||||
'build/make/target/product/security/testkey'),
|
'build/make/target/product/security/testkey', None),
|
||||||
'apex.apexd_test_different_app.apex': (
|
'apex.apexd_test_different_app.apex': (
|
||||||
'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'),
|
'build/make/target/product/security/testkey', None),
|
||||||
}, keys_info)
|
}, keys_info)
|
||||||
|
|
||||||
def test_ReadApexKeysInfo_mismatchingContainerKeys(self):
|
def test_ReadApexKeysInfo_mismatchingContainerKeys(self):
|
||||||
@@ -514,10 +514,10 @@ name="apex.apexd_test_different_app.apex" public_key="system/apex/apexd/apexd_te
|
|||||||
self.assertEqual({
|
self.assertEqual({
|
||||||
'apex.apexd_test.apex': (
|
'apex.apexd_test.apex': (
|
||||||
'system/apex/apexd/apexd_testdata/com.android.apex.test_package.pem',
|
'system/apex/apexd/apexd_testdata/com.android.apex.test_package.pem',
|
||||||
'build/make/target/product/security/testkey'),
|
'build/make/target/product/security/testkey', None),
|
||||||
'apex.apexd_test_different_app.apex': (
|
'apex.apexd_test_different_app.apex': (
|
||||||
'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'),
|
'build/make/target/product/security/testkey', None),
|
||||||
}, keys_info)
|
}, keys_info)
|
||||||
|
|
||||||
def test_ReadApexKeysInfo_missingPayloadPublicKey(self):
|
def test_ReadApexKeysInfo_missingPayloadPublicKey(self):
|
||||||
@@ -537,10 +537,10 @@ name="apex.apexd_test_different_app.apex" public_key="system/apex/apexd/apexd_te
|
|||||||
self.assertEqual({
|
self.assertEqual({
|
||||||
'apex.apexd_test.apex': (
|
'apex.apexd_test.apex': (
|
||||||
'system/apex/apexd/apexd_testdata/com.android.apex.test_package.pem',
|
'system/apex/apexd/apexd_testdata/com.android.apex.test_package.pem',
|
||||||
'build/make/target/product/security/testkey'),
|
'build/make/target/product/security/testkey', None),
|
||||||
'apex.apexd_test_different_app.apex': (
|
'apex.apexd_test_different_app.apex': (
|
||||||
'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'),
|
'build/make/target/product/security/testkey', None),
|
||||||
}, keys_info)
|
}, keys_info)
|
||||||
|
|
||||||
def test_ReadApexKeysInfo_presignedKeys(self):
|
def test_ReadApexKeysInfo_presignedKeys(self):
|
||||||
@@ -560,10 +560,10 @@ name="apex.apexd_test_different_app.apex" public_key="system/apex/apexd/apexd_te
|
|||||||
self.assertEqual({
|
self.assertEqual({
|
||||||
'apex.apexd_test.apex': (
|
'apex.apexd_test.apex': (
|
||||||
'system/apex/apexd/apexd_testdata/com.android.apex.test_package.pem',
|
'system/apex/apexd/apexd_testdata/com.android.apex.test_package.pem',
|
||||||
'build/make/target/product/security/testkey'),
|
'build/make/target/product/security/testkey', None),
|
||||||
'apex.apexd_test_different_app.apex': (
|
'apex.apexd_test_different_app.apex': (
|
||||||
'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'),
|
'build/make/target/product/security/testkey', None),
|
||||||
}, keys_info)
|
}, keys_info)
|
||||||
|
|
||||||
def test_ReadApexKeysInfo_presignedKeys(self):
|
def test_ReadApexKeysInfo_presignedKeys(self):
|
||||||
@@ -583,10 +583,10 @@ name="apex.apexd_test_different_app.apex" public_key="system/apex/apexd/apexd_te
|
|||||||
self.assertEqual({
|
self.assertEqual({
|
||||||
'apex.apexd_test.apex': (
|
'apex.apexd_test.apex': (
|
||||||
'system/apex/apexd/apexd_testdata/com.android.apex.test_package.pem',
|
'system/apex/apexd/apexd_testdata/com.android.apex.test_package.pem',
|
||||||
'build/make/target/product/security/testkey'),
|
'build/make/target/product/security/testkey', None),
|
||||||
'apex.apexd_test_different_app.apex': (
|
'apex.apexd_test_different_app.apex': (
|
||||||
'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'),
|
'build/make/target/product/security/testkey', None),
|
||||||
}, keys_info)
|
}, keys_info)
|
||||||
|
|
||||||
def test_ReplaceGkiSigningKey(self):
|
def test_ReplaceGkiSigningKey(self):
|
||||||
|
Reference in New Issue
Block a user