Make apex util detect if hashtree is present
Test: sign_target_fiels_apks oriole_target_files.zip Bug: 195194430 Change-Id: I919d169ce4d66e6a1cdbfd15babde25005971a30
This commit is contained in:
parent
bff4b52ce1
commit
45b44d96e6
|
@ -340,6 +340,8 @@ def SignUncompressedApex(avbtool, apex_file, payload_key, container_key,
|
||||||
zip_items = apex_fd.namelist()
|
zip_items = apex_fd.namelist()
|
||||||
|
|
||||||
payload_info = ParseApexPayloadInfo(avbtool, payload_file)
|
payload_info = ParseApexPayloadInfo(avbtool, payload_file)
|
||||||
|
if no_hashtree is None:
|
||||||
|
no_hashtree = payload_info.get("Tree Size", 0) == 0
|
||||||
SignApexPayload(
|
SignApexPayload(
|
||||||
avbtool,
|
avbtool,
|
||||||
payload_file,
|
payload_file,
|
||||||
|
@ -385,8 +387,8 @@ def SignUncompressedApex(avbtool, apex_file, payload_key, container_key,
|
||||||
|
|
||||||
|
|
||||||
def SignCompressedApex(avbtool, apex_file, payload_key, container_key,
|
def SignCompressedApex(avbtool, apex_file, payload_key, container_key,
|
||||||
container_pw, apk_keys, codename_to_api_level_map,
|
container_pw, apk_keys, codename_to_api_level_map,
|
||||||
no_hashtree, signing_args=None):
|
no_hashtree, signing_args=None):
|
||||||
"""Signs the current compressed APEX with the given payload/container keys.
|
"""Signs the current compressed APEX with the given payload/container keys.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
|
@ -516,6 +518,7 @@ def SignApex(avbtool, apex_data, payload_key, container_key, container_pw,
|
||||||
raise ApexInfoError(
|
raise ApexInfoError(
|
||||||
'Failed to get type for {}:\n{}'.format(apex_file, e))
|
'Failed to get type for {}:\n{}'.format(apex_file, e))
|
||||||
|
|
||||||
|
|
||||||
def GetApexInfoFromTargetFiles(input_file, partition, compressed_only=True):
|
def GetApexInfoFromTargetFiles(input_file, partition, compressed_only=True):
|
||||||
"""
|
"""
|
||||||
Get information about system APEX stored in the input_file zip
|
Get information about system APEX stored in the input_file zip
|
||||||
|
@ -558,7 +561,7 @@ def GetApexInfoFromTargetFiles(input_file, partition, compressed_only=True):
|
||||||
for apex_filename in os.listdir(target_dir):
|
for apex_filename in os.listdir(target_dir):
|
||||||
apex_filepath = os.path.join(target_dir, apex_filename)
|
apex_filepath = os.path.join(target_dir, apex_filename)
|
||||||
if not os.path.isfile(apex_filepath) or \
|
if not os.path.isfile(apex_filepath) or \
|
||||||
not zipfile.is_zipfile(apex_filepath):
|
not zipfile.is_zipfile(apex_filepath):
|
||||||
logger.info("Skipping %s because it's not a zipfile", apex_filepath)
|
logger.info("Skipping %s because it's not a zipfile", apex_filepath)
|
||||||
continue
|
continue
|
||||||
apex_info = ota_metadata_pb2.ApexInfo()
|
apex_info = ota_metadata_pb2.ApexInfo()
|
||||||
|
|
|
@ -428,7 +428,7 @@ def SignApk(data, keyname, pw, platform_api_level, codename_to_api_level_map,
|
||||||
if is_compressed:
|
if is_compressed:
|
||||||
uncompressed = tempfile.NamedTemporaryFile()
|
uncompressed = tempfile.NamedTemporaryFile()
|
||||||
with gzip.open(unsigned.name, "rb") as in_file, \
|
with gzip.open(unsigned.name, "rb") as in_file, \
|
||||||
open(uncompressed.name, "wb") as out_file:
|
open(uncompressed.name, "wb") as out_file:
|
||||||
shutil.copyfileobj(in_file, out_file)
|
shutil.copyfileobj(in_file, out_file)
|
||||||
|
|
||||||
# Finally, close the "unsigned" file (which is gzip compressed), and then
|
# Finally, close the "unsigned" file (which is gzip compressed), and then
|
||||||
|
@ -468,7 +468,7 @@ def SignApk(data, keyname, pw, platform_api_level, codename_to_api_level_map,
|
||||||
# Recompress the file after it has been signed.
|
# Recompress the file after it has been signed.
|
||||||
compressed = tempfile.NamedTemporaryFile()
|
compressed = tempfile.NamedTemporaryFile()
|
||||||
with open(signed.name, "rb") as in_file, \
|
with open(signed.name, "rb") as in_file, \
|
||||||
gzip.open(compressed.name, "wb") as out_file:
|
gzip.open(compressed.name, "wb") as out_file:
|
||||||
shutil.copyfileobj(in_file, out_file)
|
shutil.copyfileobj(in_file, out_file)
|
||||||
|
|
||||||
data = compressed.read()
|
data = compressed.read()
|
||||||
|
@ -484,21 +484,21 @@ def SignApk(data, keyname, pw, platform_api_level, codename_to_api_level_map,
|
||||||
|
|
||||||
def IsBuildPropFile(filename):
|
def IsBuildPropFile(filename):
|
||||||
return filename in (
|
return filename in (
|
||||||
"SYSTEM/etc/prop.default",
|
"SYSTEM/etc/prop.default",
|
||||||
"BOOT/RAMDISK/prop.default",
|
"BOOT/RAMDISK/prop.default",
|
||||||
"RECOVERY/RAMDISK/prop.default",
|
"RECOVERY/RAMDISK/prop.default",
|
||||||
|
|
||||||
"VENDOR_BOOT/RAMDISK/default.prop",
|
"VENDOR_BOOT/RAMDISK/default.prop",
|
||||||
"VENDOR_BOOT/RAMDISK/prop.default",
|
"VENDOR_BOOT/RAMDISK/prop.default",
|
||||||
|
|
||||||
# ROOT/default.prop is a legacy path, but may still exist for upgrading
|
# ROOT/default.prop is a legacy path, but may still exist for upgrading
|
||||||
# devices that don't support `property_overrides_split_enabled`.
|
# devices that don't support `property_overrides_split_enabled`.
|
||||||
"ROOT/default.prop",
|
"ROOT/default.prop",
|
||||||
|
|
||||||
# RECOVERY/RAMDISK/default.prop is a legacy path, but will always exist
|
# RECOVERY/RAMDISK/default.prop is a legacy path, but will always exist
|
||||||
# as a symlink in the current code. So it's a no-op here. Keeping the
|
# as a symlink in the current code. So it's a no-op here. Keeping the
|
||||||
# path here for clarity.
|
# path here for clarity.
|
||||||
"RECOVERY/RAMDISK/default.prop") or filename.endswith("build.prop")
|
"RECOVERY/RAMDISK/default.prop") or filename.endswith("build.prop")
|
||||||
|
|
||||||
|
|
||||||
def ProcessTargetFiles(input_tf_zip, output_tf_zip, misc_info,
|
def ProcessTargetFiles(input_tf_zip, output_tf_zip, misc_info,
|
||||||
|
@ -561,7 +561,7 @@ def ProcessTargetFiles(input_tf_zip, output_tf_zip, misc_info,
|
||||||
|
|
||||||
# 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
|
||||||
container_key not in common.SPECIAL_CERT_STRINGS):
|
container_key not in common.SPECIAL_CERT_STRINGS):
|
||||||
print(" signing: %-*s container (%s)" % (
|
print(" signing: %-*s container (%s)" % (
|
||||||
maxsize, name, container_key))
|
maxsize, name, container_key))
|
||||||
print(" : %-*s payload (%s)" % (
|
print(" : %-*s payload (%s)" % (
|
||||||
|
@ -575,7 +575,7 @@ def ProcessTargetFiles(input_tf_zip, output_tf_zip, misc_info,
|
||||||
key_passwords,
|
key_passwords,
|
||||||
apk_keys,
|
apk_keys,
|
||||||
codename_to_api_level_map,
|
codename_to_api_level_map,
|
||||||
no_hashtree=True,
|
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'))
|
||||||
common.ZipWrite(output_tf_zip, signed_apex, filename)
|
common.ZipWrite(output_tf_zip, signed_apex, filename)
|
||||||
|
|
||||||
|
@ -658,7 +658,7 @@ def ProcessTargetFiles(input_tf_zip, output_tf_zip, misc_info,
|
||||||
# Updates system_other.avbpubkey in /product/etc/.
|
# Updates system_other.avbpubkey in /product/etc/.
|
||||||
elif filename in (
|
elif filename in (
|
||||||
"PRODUCT/etc/security/avb/system_other.avbpubkey",
|
"PRODUCT/etc/security/avb/system_other.avbpubkey",
|
||||||
"SYSTEM/product/etc/security/avb/system_other.avbpubkey"):
|
"SYSTEM/product/etc/security/avb/system_other.avbpubkey"):
|
||||||
# Only update system_other's public key, if the corresponding signing
|
# Only update system_other's public key, if the corresponding signing
|
||||||
# key is specified via --avb_system_other_key.
|
# key is specified via --avb_system_other_key.
|
||||||
signing_key = OPTIONS.avb_keys.get("system_other")
|
signing_key = OPTIONS.avb_keys.get("system_other")
|
||||||
|
@ -671,7 +671,7 @@ def ProcessTargetFiles(input_tf_zip, output_tf_zip, misc_info,
|
||||||
# Should NOT sign boot-debug.img.
|
# Should NOT sign boot-debug.img.
|
||||||
elif filename in (
|
elif filename in (
|
||||||
"BOOT/RAMDISK/force_debuggable",
|
"BOOT/RAMDISK/force_debuggable",
|
||||||
"BOOT/RAMDISK/first_stage_ramdisk/force_debuggable"):
|
"BOOT/RAMDISK/first_stage_ramdisk/force_debuggable"):
|
||||||
raise common.ExternalError("debuggable boot.img cannot be signed")
|
raise common.ExternalError("debuggable boot.img cannot be signed")
|
||||||
|
|
||||||
# A non-APK file; copy it verbatim.
|
# A non-APK file; copy it verbatim.
|
||||||
|
@ -762,7 +762,8 @@ def ReplaceCerts(data):
|
||||||
# it's only checking entries with global seinfo at the moment (i.e. ignoring
|
# it's only checking entries with global seinfo at the moment (i.e. ignoring
|
||||||
# the ones with inner packages). (Bug: 69479366)
|
# the ones with inner packages). (Bug: 69479366)
|
||||||
root = ElementTree.fromstring(data)
|
root = ElementTree.fromstring(data)
|
||||||
signatures = [signer.attrib['signature'] for signer in root.findall('signer')]
|
signatures = [signer.attrib['signature']
|
||||||
|
for signer in root.findall('signer')]
|
||||||
assert len(signatures) == len(set(signatures)), \
|
assert len(signatures) == len(set(signatures)), \
|
||||||
"Found duplicate entries after cert replacement: {}".format(data)
|
"Found duplicate entries after cert replacement: {}".format(data)
|
||||||
|
|
||||||
|
@ -807,7 +808,7 @@ def RewriteProps(data):
|
||||||
if line and line[0] != '#' and "=" in line:
|
if line and line[0] != '#' and "=" in line:
|
||||||
key, value = line.split("=", 1)
|
key, value = line.split("=", 1)
|
||||||
if (key.startswith("ro.") and
|
if (key.startswith("ro.") and
|
||||||
key.endswith((".build.fingerprint", ".build.thumbprint"))):
|
key.endswith((".build.fingerprint", ".build.thumbprint"))):
|
||||||
pieces = value.split("/")
|
pieces = value.split("/")
|
||||||
pieces[-1] = EditTags(pieces[-1])
|
pieces[-1] = EditTags(pieces[-1])
|
||||||
value = "/".join(pieces)
|
value = "/".join(pieces)
|
||||||
|
@ -1000,7 +1001,7 @@ def ReplaceAvbSigningKeys(misc_info):
|
||||||
ReplaceAvbPartitionSigningKey(partition)
|
ReplaceAvbPartitionSigningKey(partition)
|
||||||
|
|
||||||
for custom_partition in misc_info.get(
|
for custom_partition in misc_info.get(
|
||||||
"avb_custom_images_partition_list", "").strip().split():
|
"avb_custom_images_partition_list", "").strip().split():
|
||||||
ReplaceAvbPartitionSigningKey(custom_partition)
|
ReplaceAvbPartitionSigningKey(custom_partition)
|
||||||
|
|
||||||
|
|
||||||
|
@ -1065,7 +1066,7 @@ def BuildKeyMap(misc_info, key_mapping_options):
|
||||||
devkeydir + "/shared": d + "/shared",
|
devkeydir + "/shared": d + "/shared",
|
||||||
devkeydir + "/platform": d + "/platform",
|
devkeydir + "/platform": d + "/platform",
|
||||||
devkeydir + "/networkstack": d + "/networkstack",
|
devkeydir + "/networkstack": d + "/networkstack",
|
||||||
})
|
})
|
||||||
else:
|
else:
|
||||||
OPTIONS.key_map[s] = d
|
OPTIONS.key_map[s] = d
|
||||||
|
|
||||||
|
@ -1168,8 +1169,8 @@ def ReadApexKeysInfo(tf_zip):
|
||||||
if container_cert == 'PRESIGNED' and container_private_key == 'PRESIGNED':
|
if container_cert == 'PRESIGNED' and container_private_key == 'PRESIGNED':
|
||||||
container_key = 'PRESIGNED'
|
container_key = 'PRESIGNED'
|
||||||
elif CompareKeys(
|
elif CompareKeys(
|
||||||
container_cert, OPTIONS.public_key_suffix,
|
container_cert, OPTIONS.public_key_suffix,
|
||||||
container_private_key, OPTIONS.private_key_suffix):
|
container_private_key, OPTIONS.private_key_suffix):
|
||||||
container_key = container_cert[:-len(OPTIONS.public_key_suffix)]
|
container_key = container_cert[:-len(OPTIONS.public_key_suffix)]
|
||||||
else:
|
else:
|
||||||
raise ValueError("Failed to parse container keys: \n{}".format(line))
|
raise ValueError("Failed to parse container keys: \n{}".format(line))
|
||||||
|
|
Loading…
Reference in New Issue