forked from openkylin/platform_build
Merge "releasetools: Allow skipping PRESIGNED APEXes."
This commit is contained in:
commit
2812fd32ac
|
@ -166,7 +166,7 @@ def GetApkCerts(certmap):
|
||||||
def GetApexKeys(keys_info, key_map):
|
def GetApexKeys(keys_info, key_map):
|
||||||
"""Gets APEX payload and container signing keys by applying the mapping rules.
|
"""Gets APEX payload and container signing keys by applying the mapping rules.
|
||||||
|
|
||||||
We currently don't allow PRESIGNED payload / container keys.
|
Presigned payload / container keys will be set accordingly.
|
||||||
|
|
||||||
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,
|
||||||
|
@ -180,7 +180,8 @@ def GetApexKeys(keys_info, key_map):
|
||||||
# Apply all the --extra_apex_payload_key options to override the payload
|
# Apply all the --extra_apex_payload_key options to override the payload
|
||||||
# signing keys in the given keys_info.
|
# signing keys in the given keys_info.
|
||||||
for apex, key in OPTIONS.extra_apex_payload_keys.items():
|
for apex, key in OPTIONS.extra_apex_payload_keys.items():
|
||||||
assert key, 'Presigned APEX payload for {} is not allowed'.format(apex)
|
if not key:
|
||||||
|
key = 'PRESIGNED'
|
||||||
keys_info[apex] = (key, keys_info[apex][1])
|
keys_info[apex] = (key, keys_info[apex][1])
|
||||||
|
|
||||||
# Apply the key remapping to container keys.
|
# Apply the key remapping to container keys.
|
||||||
|
@ -192,7 +193,8 @@ def GetApexKeys(keys_info, key_map):
|
||||||
# Skip non-APEX containers.
|
# Skip non-APEX containers.
|
||||||
if apex not in keys_info:
|
if apex not in keys_info:
|
||||||
continue
|
continue
|
||||||
assert key, 'Presigned APEX container for {} is not allowed'.format(apex)
|
if not key:
|
||||||
|
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))
|
||||||
|
|
||||||
return keys_info
|
return keys_info
|
||||||
|
@ -245,7 +247,7 @@ def GetApkFileInfo(filename, compressed_extension, skipped_prefixes):
|
||||||
|
|
||||||
|
|
||||||
def CheckApkAndApexKeysAvailable(input_tf_zip, known_keys,
|
def CheckApkAndApexKeysAvailable(input_tf_zip, known_keys,
|
||||||
compressed_extension):
|
compressed_extension, apex_keys):
|
||||||
"""Checks that all the APKs and APEXes have keys specified.
|
"""Checks that all the APKs and APEXes have keys specified.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
|
@ -253,6 +255,8 @@ def CheckApkAndApexKeysAvailable(input_tf_zip, known_keys,
|
||||||
known_keys: A set of APKs and APEXes that have known signing keys.
|
known_keys: A set of APKs and APEXes that have known signing 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
|
||||||
|
(payload_key, container_key).
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
AssertionError: On finding unknown APKs and APEXes.
|
AssertionError: On finding unknown APKs and APEXes.
|
||||||
|
@ -284,6 +288,31 @@ def CheckApkAndApexKeysAvailable(input_tf_zip, known_keys,
|
||||||
"Use '-e <apkname>=' to specify a key (which may be an empty string to "
|
"Use '-e <apkname>=' to specify a key (which may be an empty string to "
|
||||||
"not sign this apk).".format("\n ".join(unknown_files)))
|
"not sign this apk).".format("\n ".join(unknown_files)))
|
||||||
|
|
||||||
|
# For all the APEXes, double check that we won't have an APEX that has only
|
||||||
|
# one of the payload / container keys set.
|
||||||
|
if not apex_keys:
|
||||||
|
return
|
||||||
|
|
||||||
|
invalid_apexes = []
|
||||||
|
for info in input_tf_zip.infolist():
|
||||||
|
if (not info.filename.startswith('SYSTEM/apex') or
|
||||||
|
not info.filename.endswith('.apex')):
|
||||||
|
continue
|
||||||
|
|
||||||
|
name = os.path.basename(info.filename)
|
||||||
|
(payload_key, container_key) = apex_keys[name]
|
||||||
|
if ((payload_key in common.SPECIAL_CERT_STRINGS and
|
||||||
|
container_key not in common.SPECIAL_CERT_STRINGS) or
|
||||||
|
(payload_key not in common.SPECIAL_CERT_STRINGS and
|
||||||
|
container_key in common.SPECIAL_CERT_STRINGS)):
|
||||||
|
invalid_apexes.append(
|
||||||
|
"{}: payload_key {}, container_key {}".format(
|
||||||
|
name, payload_key, container_key))
|
||||||
|
|
||||||
|
assert not invalid_apexes, \
|
||||||
|
"Invalid APEX keys specified:\n {}\n".format(
|
||||||
|
"\n ".join(invalid_apexes))
|
||||||
|
|
||||||
|
|
||||||
def SignApk(data, keyname, pw, platform_api_level, codename_to_api_level_map,
|
def SignApk(data, keyname, pw, platform_api_level, codename_to_api_level_map,
|
||||||
is_compressed):
|
is_compressed):
|
||||||
|
@ -468,19 +497,29 @@ def ProcessTargetFiles(input_tf_zip, output_tf_zip, misc_info,
|
||||||
name = os.path.basename(filename)
|
name = os.path.basename(filename)
|
||||||
payload_key, container_key = apex_keys[name]
|
payload_key, container_key = apex_keys[name]
|
||||||
|
|
||||||
print(" signing: %-*s container (%s)" % (maxsize, name, container_key))
|
# We've asserted not having a case with only one of them PRESIGNED.
|
||||||
print(" : %-*s payload (%s)" % (maxsize, name, payload_key))
|
if (payload_key not in common.SPECIAL_CERT_STRINGS and
|
||||||
|
container_key not in common.SPECIAL_CERT_STRINGS):
|
||||||
|
print(" signing: %-*s container (%s)" % (
|
||||||
|
maxsize, name, container_key))
|
||||||
|
print(" : %-*s payload (%s)" % (
|
||||||
|
maxsize, name, payload_key))
|
||||||
|
|
||||||
(signed_apex, payload_key_name) = SignApex(
|
(signed_apex, payload_key_name) = SignApex(
|
||||||
data,
|
data,
|
||||||
payload_key,
|
payload_key,
|
||||||
container_key,
|
container_key,
|
||||||
key_passwords[container_key],
|
key_passwords[container_key],
|
||||||
codename_to_api_level_map,
|
codename_to_api_level_map,
|
||||||
OPTIONS.avb_extra_args.get('apex'))
|
OPTIONS.avb_extra_args.get('apex'))
|
||||||
common.ZipWrite(output_tf_zip, signed_apex, filename)
|
common.ZipWrite(output_tf_zip, signed_apex, filename)
|
||||||
|
updated_apex_payload_keys[payload_key_name] = payload_key
|
||||||
|
|
||||||
updated_apex_payload_keys[payload_key_name] = payload_key
|
else:
|
||||||
|
print(
|
||||||
|
"NOT signing: %s\n"
|
||||||
|
" (skipped due to special cert string)" % (name,))
|
||||||
|
common.ZipWriteStr(output_tf_zip, out_info, data)
|
||||||
|
|
||||||
# AVB public keys for the installed APEXes, which will be updated later.
|
# AVB public keys for the installed APEXes, which will be updated later.
|
||||||
elif (os.path.dirname(filename) == 'SYSTEM/etc/security/apex' and
|
elif (os.path.dirname(filename) == 'SYSTEM/etc/security/apex' and
|
||||||
|
@ -557,8 +596,10 @@ def ProcessTargetFiles(input_tf_zip, output_tf_zip, misc_info,
|
||||||
continue
|
continue
|
||||||
|
|
||||||
name = os.path.basename(filename)
|
name = os.path.basename(filename)
|
||||||
assert name in updated_apex_payload_keys, \
|
|
||||||
'Unsigned APEX payload key: {}'.format(filename)
|
# Skip PRESIGNED APEXes.
|
||||||
|
if name not in updated_apex_payload_keys:
|
||||||
|
continue
|
||||||
|
|
||||||
key_path = updated_apex_payload_keys[name]
|
key_path = updated_apex_payload_keys[name]
|
||||||
if not os.path.exists(key_path) and not key_path.endswith('.pem'):
|
if not os.path.exists(key_path) and not key_path.endswith('.pem'):
|
||||||
|
@ -1181,7 +1222,8 @@ def main(argv):
|
||||||
CheckApkAndApexKeysAvailable(
|
CheckApkAndApexKeysAvailable(
|
||||||
input_zip,
|
input_zip,
|
||||||
set(apk_keys.keys()) | set(apex_keys.keys()),
|
set(apk_keys.keys()) | set(apex_keys.keys()),
|
||||||
compressed_extension)
|
compressed_extension,
|
||||||
|
apex_keys)
|
||||||
|
|
||||||
key_passwords = common.GetKeyPasswords(
|
key_passwords = common.GetKeyPasswords(
|
||||||
set(apk_keys.values()) | set(itertools.chain(*apex_keys.values())))
|
set(apk_keys.values()) | set(itertools.chain(*apex_keys.values())))
|
||||||
|
|
|
@ -33,6 +33,7 @@ class SignTargetFilesApksTest(test_utils.ReleaseToolsTestCase):
|
||||||
<signer signature="{}"><seinfo value="media"/></signer>
|
<signer signature="{}"><seinfo value="media"/></signer>
|
||||||
</policy>"""
|
</policy>"""
|
||||||
|
|
||||||
|
# pylint: disable=line-too-long
|
||||||
APEX_KEYS_TXT = """name="apex.apexd_test.apex" public_key="system/apex/apexd/apexd_testdata/com.android.apex.test_package.avbpubkey" private_key="system/apex/apexd/apexd_testdata/com.android.apex.test_package.pem" container_certificate="build/target/product/security/testkey.x509.pem" container_private_key="build/target/product/security/testkey.pk8"
|
APEX_KEYS_TXT = """name="apex.apexd_test.apex" public_key="system/apex/apexd/apexd_testdata/com.android.apex.test_package.avbpubkey" private_key="system/apex/apexd/apexd_testdata/com.android.apex.test_package.pem" container_certificate="build/target/product/security/testkey.x509.pem" container_private_key="build/target/product/security/testkey.pk8"
|
||||||
name="apex.apexd_test_different_app.apex" public_key="system/apex/apexd/apexd_testdata/com.android.apex.test_package_2.avbpubkey" private_key="system/apex/apexd/apexd_testdata/com.android.apex.test_package_2.pem" container_certificate="build/target/product/security/testkey.x509.pem" container_private_key="build/target/product/security/testkey.pk8"
|
name="apex.apexd_test_different_app.apex" public_key="system/apex/apexd/apexd_testdata/com.android.apex.test_package_2.avbpubkey" private_key="system/apex/apexd/apexd_testdata/com.android.apex.test_package_2.pem" container_certificate="build/target/product/security/testkey.x509.pem" container_private_key="build/target/product/security/testkey.pk8"
|
||||||
"""
|
"""
|
||||||
|
@ -223,17 +224,50 @@ name="apex.apexd_test_different_app.apex" public_key="system/apex/apexd/apexd_te
|
||||||
'App3.apk' : 'key3',
|
'App3.apk' : 'key3',
|
||||||
}
|
}
|
||||||
with zipfile.ZipFile(input_file) as input_zip:
|
with zipfile.ZipFile(input_file) as input_zip:
|
||||||
CheckApkAndApexKeysAvailable(input_zip, apk_key_map, None)
|
CheckApkAndApexKeysAvailable(input_zip, apk_key_map, None, {})
|
||||||
CheckApkAndApexKeysAvailable(input_zip, apk_key_map, '.gz')
|
CheckApkAndApexKeysAvailable(input_zip, apk_key_map, '.gz', {})
|
||||||
|
|
||||||
# 'App2.apk.gz' won't be considered as an APK.
|
# 'App2.apk.gz' won't be considered as an APK.
|
||||||
CheckApkAndApexKeysAvailable(input_zip, apk_key_map, None)
|
CheckApkAndApexKeysAvailable(input_zip, apk_key_map, None, {})
|
||||||
CheckApkAndApexKeysAvailable(input_zip, apk_key_map, '.xz')
|
CheckApkAndApexKeysAvailable(input_zip, apk_key_map, '.xz', {})
|
||||||
|
|
||||||
del apk_key_map['App2.apk']
|
del apk_key_map['App2.apk']
|
||||||
self.assertRaises(
|
self.assertRaises(
|
||||||
AssertionError, CheckApkAndApexKeysAvailable, input_zip, apk_key_map,
|
AssertionError, CheckApkAndApexKeysAvailable, input_zip, apk_key_map,
|
||||||
'.gz')
|
'.gz', {})
|
||||||
|
|
||||||
|
def test_CheckApkAndApexKeysAvailable_invalidApexKeys(self):
|
||||||
|
input_file = common.MakeTempFile(suffix='.zip')
|
||||||
|
with zipfile.ZipFile(input_file, 'w') as input_zip:
|
||||||
|
input_zip.writestr('SYSTEM/apex/Apex1.apex', "Apex1-content")
|
||||||
|
input_zip.writestr('SYSTEM/apex/Apex2.apex', "Apex2-content")
|
||||||
|
|
||||||
|
apk_key_map = {
|
||||||
|
'Apex1.apex' : 'key1',
|
||||||
|
'Apex2.apex' : 'key2',
|
||||||
|
'Apex3.apex' : 'key3',
|
||||||
|
}
|
||||||
|
apex_keys = {
|
||||||
|
'Apex1.apex' : ('payload-key1', 'container-key1'),
|
||||||
|
'Apex2.apex' : ('payload-key2', 'container-key2'),
|
||||||
|
}
|
||||||
|
with zipfile.ZipFile(input_file) as input_zip:
|
||||||
|
CheckApkAndApexKeysAvailable(input_zip, apk_key_map, None, apex_keys)
|
||||||
|
|
||||||
|
# Fine to have both keys as PRESIGNED.
|
||||||
|
apex_keys['Apex2.apex'] = ('PRESIGNED', 'PRESIGNED')
|
||||||
|
CheckApkAndApexKeysAvailable(input_zip, apk_key_map, None, apex_keys)
|
||||||
|
|
||||||
|
# Having only one of them as PRESIGNED is not allowed.
|
||||||
|
apex_keys['Apex2.apex'] = ('payload-key2', 'PRESIGNED')
|
||||||
|
self.assertRaises(
|
||||||
|
AssertionError, CheckApkAndApexKeysAvailable, input_zip, apk_key_map,
|
||||||
|
None, apex_keys)
|
||||||
|
|
||||||
|
apex_keys['Apex2.apex'] = ('PRESIGNED', 'container-key1')
|
||||||
|
self.assertRaises(
|
||||||
|
AssertionError, CheckApkAndApexKeysAvailable, input_zip, apk_key_map,
|
||||||
|
None, apex_keys)
|
||||||
|
|
||||||
def test_GetApkFileInfo(self):
|
def test_GetApkFileInfo(self):
|
||||||
(is_apk, is_compressed, should_be_skipped) = GetApkFileInfo(
|
(is_apk, is_compressed, should_be_skipped) = GetApkFileInfo(
|
||||||
|
@ -358,16 +392,14 @@ name="apex.apexd_test_different_app.apex" public_key="system/apex/apexd/apexd_te
|
||||||
with zipfile.ZipFile(target_files) as target_files_zip:
|
with zipfile.ZipFile(target_files) as target_files_zip:
|
||||||
keys_info = ReadApexKeysInfo(target_files_zip)
|
keys_info = ReadApexKeysInfo(target_files_zip)
|
||||||
|
|
||||||
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/target/product/security/testkey'),
|
||||||
'build/target/product/security/testkey'),
|
'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/target/product/security/testkey'),
|
||||||
'build/target/product/security/testkey'),
|
}, keys_info)
|
||||||
},
|
|
||||||
keys_info)
|
|
||||||
|
|
||||||
def test_ReadApexKeysInfo_mismatchingKeys(self):
|
def test_ReadApexKeysInfo_mismatchingKeys(self):
|
||||||
# Mismatching payload public / private keys.
|
# Mismatching payload public / private keys.
|
||||||
|
@ -398,13 +430,11 @@ name="apex.apexd_test_different_app.apex" public_key="system/apex/apexd/apexd_te
|
||||||
with zipfile.ZipFile(target_files) as target_files_zip:
|
with zipfile.ZipFile(target_files) as target_files_zip:
|
||||||
keys_info = ReadApexKeysInfo(target_files_zip)
|
keys_info = ReadApexKeysInfo(target_files_zip)
|
||||||
|
|
||||||
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/target/product/security/testkey'),
|
||||||
'build/target/product/security/testkey'),
|
'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/target/product/security/testkey'),
|
||||||
'build/target/product/security/testkey'),
|
}, keys_info)
|
||||||
},
|
|
||||||
keys_info)
|
|
||||||
|
|
Loading…
Reference in New Issue