Don't generate hashtree when signing bundled APEXes.
Bug: 139957269 Test: Sign a target_files.zip. Extract a re-signed APEX and check the hashtree size (being zero). Test: Use sign_apex to sign an APEX file. Check the hashtree size (not being zero). Test: python -m unittest test_apex_utils Test: python -m unittest test_sign_apex Change-Id: I927b7681d66920d7732b700ec3a8f7a65b4cb351
This commit is contained in:
@@ -42,7 +42,7 @@ class ApexSigningError(Exception):
|
|||||||
|
|
||||||
|
|
||||||
def SignApexPayload(avbtool, payload_file, payload_key_path, payload_key_name,
|
def SignApexPayload(avbtool, payload_file, payload_key_path, payload_key_name,
|
||||||
algorithm, salt, signing_args=None):
|
algorithm, salt, no_hashtree, signing_args=None):
|
||||||
"""Signs a given payload_file with the payload key."""
|
"""Signs a given payload_file with the payload key."""
|
||||||
# Add the new footer. Old footer, if any, will be replaced by avbtool.
|
# Add the new footer. Old footer, if any, will be replaced by avbtool.
|
||||||
cmd = [avbtool, 'add_hashtree_footer',
|
cmd = [avbtool, 'add_hashtree_footer',
|
||||||
@@ -52,6 +52,8 @@ def SignApexPayload(avbtool, payload_file, payload_key_path, payload_key_name,
|
|||||||
'--prop', 'apex.key:{}'.format(payload_key_name),
|
'--prop', 'apex.key:{}'.format(payload_key_name),
|
||||||
'--image', payload_file,
|
'--image', payload_file,
|
||||||
'--salt', salt]
|
'--salt', salt]
|
||||||
|
if no_hashtree:
|
||||||
|
cmd.append('--no_hashtree')
|
||||||
if signing_args:
|
if signing_args:
|
||||||
cmd.extend(shlex.split(signing_args))
|
cmd.extend(shlex.split(signing_args))
|
||||||
|
|
||||||
@@ -64,13 +66,15 @@ def SignApexPayload(avbtool, payload_file, payload_key_path, payload_key_name,
|
|||||||
|
|
||||||
# Verify the signed payload image with specified public key.
|
# Verify the signed payload image with specified public key.
|
||||||
logger.info('Verifying %s', payload_file)
|
logger.info('Verifying %s', payload_file)
|
||||||
VerifyApexPayload(avbtool, payload_file, payload_key_path)
|
VerifyApexPayload(avbtool, payload_file, payload_key_path, no_hashtree)
|
||||||
|
|
||||||
|
|
||||||
def VerifyApexPayload(avbtool, payload_file, payload_key):
|
def VerifyApexPayload(avbtool, payload_file, payload_key, no_hashtree=False):
|
||||||
"""Verifies the APEX payload signature with the given key."""
|
"""Verifies the APEX payload signature with the given key."""
|
||||||
cmd = [avbtool, 'verify_image', '--image', payload_file,
|
cmd = [avbtool, 'verify_image', '--image', payload_file,
|
||||||
'--key', payload_key]
|
'--key', payload_key]
|
||||||
|
if no_hashtree:
|
||||||
|
cmd.append('--accept_zeroed_hashtree')
|
||||||
try:
|
try:
|
||||||
common.RunAndCheckOutput(cmd)
|
common.RunAndCheckOutput(cmd)
|
||||||
except common.ExternalError as e:
|
except common.ExternalError as e:
|
||||||
@@ -91,7 +95,7 @@ def ParseApexPayloadInfo(avbtool, payload_path):
|
|||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
A dict that contains payload property-value pairs. The dict should at least
|
A dict that contains payload property-value pairs. The dict should at least
|
||||||
contain Algorithm, Salt and apex.key.
|
contain Algorithm, Salt, Tree Size and apex.key.
|
||||||
"""
|
"""
|
||||||
if not os.path.exists(payload_path):
|
if not os.path.exists(payload_path):
|
||||||
raise ApexInfoError('Failed to find image: {}'.format(payload_path))
|
raise ApexInfoError('Failed to find image: {}'.format(payload_path))
|
||||||
@@ -104,11 +108,11 @@ def ParseApexPayloadInfo(avbtool, payload_path):
|
|||||||
'Failed to get APEX payload info for {}:\n{}'.format(
|
'Failed to get APEX payload info for {}:\n{}'.format(
|
||||||
payload_path, e))
|
payload_path, e))
|
||||||
|
|
||||||
# Extract the Algorithm / Salt / Prop info from payload (i.e. an image signed
|
# Extract the Algorithm / Salt / Prop info / Tree size from payload (i.e. an
|
||||||
# with avbtool). For example,
|
# image signed with avbtool). For example,
|
||||||
# Algorithm: SHA256_RSA4096
|
# Algorithm: SHA256_RSA4096
|
||||||
PAYLOAD_INFO_PATTERN = (
|
PAYLOAD_INFO_PATTERN = (
|
||||||
r'^\s*(?P<key>Algorithm|Salt|Prop)\:\s*(?P<value>.*?)$')
|
r'^\s*(?P<key>Algorithm|Salt|Prop|Tree Size)\:\s*(?P<value>.*?)$')
|
||||||
payload_info_matcher = re.compile(PAYLOAD_INFO_PATTERN)
|
payload_info_matcher = re.compile(PAYLOAD_INFO_PATTERN)
|
||||||
|
|
||||||
payload_info = {}
|
payload_info = {}
|
||||||
@@ -151,7 +155,7 @@ def ParseApexPayloadInfo(avbtool, payload_path):
|
|||||||
|
|
||||||
|
|
||||||
def SignApex(avbtool, apex_data, payload_key, container_key, container_pw,
|
def SignApex(avbtool, apex_data, payload_key, container_key, container_pw,
|
||||||
codename_to_api_level_map, signing_args=None):
|
codename_to_api_level_map, no_hashtree, signing_args=None):
|
||||||
"""Signs the current APEX with the given payload/container keys.
|
"""Signs the current APEX with the given payload/container keys.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@@ -160,6 +164,7 @@ def SignApex(avbtool, apex_data, payload_key, container_key, container_pw,
|
|||||||
container_key: The path to container signing key (w/o extension).
|
container_key: The path to container signing key (w/o extension).
|
||||||
container_pw: The matching password of the container_key, or None.
|
container_pw: The matching password of the container_key, or None.
|
||||||
codename_to_api_level_map: A dict that maps from codename to API level.
|
codename_to_api_level_map: A dict that maps from codename to API level.
|
||||||
|
no_hashtree: Don't include hashtree in the signed APEX.
|
||||||
signing_args: Additional args to be passed to the payload signer.
|
signing_args: Additional args to be passed to the payload signer.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
@@ -187,6 +192,7 @@ def SignApex(avbtool, apex_data, payload_key, container_key, container_pw,
|
|||||||
payload_info['apex.key'],
|
payload_info['apex.key'],
|
||||||
payload_info['Algorithm'],
|
payload_info['Algorithm'],
|
||||||
payload_info['Salt'],
|
payload_info['Salt'],
|
||||||
|
no_hashtree,
|
||||||
signing_args)
|
signing_args)
|
||||||
|
|
||||||
# 1b. Update the embedded payload public key.
|
# 1b. Update the embedded payload public key.
|
||||||
|
@@ -56,6 +56,7 @@ def SignApexFile(avbtool, apex_file, payload_key, container_key,
|
|||||||
container_key=container_key,
|
container_key=container_key,
|
||||||
container_pw=None,
|
container_pw=None,
|
||||||
codename_to_api_level_map=None,
|
codename_to_api_level_map=None,
|
||||||
|
no_hashtree=False,
|
||||||
signing_args=signing_args)
|
signing_args=signing_args)
|
||||||
|
|
||||||
|
|
||||||
@@ -103,7 +104,8 @@ def main(argv):
|
|||||||
args[0],
|
args[0],
|
||||||
options['payload_key'],
|
options['payload_key'],
|
||||||
options['container_key'],
|
options['container_key'],
|
||||||
options.get('payload_extra_args'))
|
no_hashtree=False,
|
||||||
|
signing_args=options.get('payload_extra_args'))
|
||||||
shutil.copyfile(signed_apex, args[1])
|
shutil.copyfile(signed_apex, args[1])
|
||||||
logger.info("done.")
|
logger.info("done.")
|
||||||
|
|
||||||
|
@@ -479,7 +479,8 @@ def ProcessTargetFiles(input_tf_zip, output_tf_zip, misc_info,
|
|||||||
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'))
|
no_hashtree=True,
|
||||||
|
signing_args=OPTIONS.avb_extra_args.get('apex'))
|
||||||
common.ZipWrite(output_tf_zip, signed_apex, filename)
|
common.ZipWrite(output_tf_zip, signed_apex, filename)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
|
@@ -44,19 +44,42 @@ class ApexUtilsTest(test_utils.ReleaseToolsTestCase):
|
|||||||
payload_file = self._GetTestPayload()
|
payload_file = self._GetTestPayload()
|
||||||
apex_utils.SignApexPayload(
|
apex_utils.SignApexPayload(
|
||||||
'avbtool', payload_file, self.payload_key, 'testkey', 'SHA256_RSA2048',
|
'avbtool', payload_file, self.payload_key, 'testkey', 'SHA256_RSA2048',
|
||||||
self.SALT)
|
self.SALT, no_hashtree=True)
|
||||||
payload_info = apex_utils.ParseApexPayloadInfo('avbtool', payload_file)
|
payload_info = apex_utils.ParseApexPayloadInfo('avbtool', payload_file)
|
||||||
self.assertEqual('SHA256_RSA2048', payload_info['Algorithm'])
|
self.assertEqual('SHA256_RSA2048', payload_info['Algorithm'])
|
||||||
self.assertEqual(self.SALT, payload_info['Salt'])
|
self.assertEqual(self.SALT, payload_info['Salt'])
|
||||||
self.assertEqual('testkey', payload_info['apex.key'])
|
self.assertEqual('testkey', payload_info['apex.key'])
|
||||||
|
self.assertEqual('0 bytes', payload_info['Tree Size'])
|
||||||
|
|
||||||
@test_utils.SkipIfExternalToolsUnavailable()
|
@test_utils.SkipIfExternalToolsUnavailable()
|
||||||
def test_SignApexPayload(self):
|
def test_SignApexPayload(self):
|
||||||
payload_file = self._GetTestPayload()
|
payload_file = self._GetTestPayload()
|
||||||
apex_utils.SignApexPayload(
|
apex_utils.SignApexPayload(
|
||||||
'avbtool', payload_file, self.payload_key, 'testkey', 'SHA256_RSA2048',
|
'avbtool', payload_file, self.payload_key, 'testkey', 'SHA256_RSA2048',
|
||||||
self.SALT)
|
self.SALT, no_hashtree=True)
|
||||||
|
apex_utils.VerifyApexPayload(
|
||||||
|
'avbtool', payload_file, self.payload_key, True)
|
||||||
|
|
||||||
|
@test_utils.SkipIfExternalToolsUnavailable()
|
||||||
|
def test_SignApexPayload_withHashtree(self):
|
||||||
|
payload_file = self._GetTestPayload()
|
||||||
|
apex_utils.SignApexPayload(
|
||||||
|
'avbtool', payload_file, self.payload_key, 'testkey', 'SHA256_RSA2048',
|
||||||
|
self.SALT, no_hashtree=False)
|
||||||
apex_utils.VerifyApexPayload('avbtool', payload_file, self.payload_key)
|
apex_utils.VerifyApexPayload('avbtool', payload_file, self.payload_key)
|
||||||
|
payload_info = apex_utils.ParseApexPayloadInfo('avbtool', payload_file)
|
||||||
|
self.assertEqual('4096 bytes', payload_info['Tree Size'])
|
||||||
|
|
||||||
|
@test_utils.SkipIfExternalToolsUnavailable()
|
||||||
|
def test_SignApexPayload_noHashtree(self):
|
||||||
|
payload_file = self._GetTestPayload()
|
||||||
|
apex_utils.SignApexPayload(
|
||||||
|
'avbtool', payload_file, self.payload_key, 'testkey', 'SHA256_RSA2048',
|
||||||
|
self.SALT, no_hashtree=True)
|
||||||
|
apex_utils.VerifyApexPayload('avbtool', payload_file, self.payload_key,
|
||||||
|
no_hashtree=True)
|
||||||
|
payload_info = apex_utils.ParseApexPayloadInfo('avbtool', payload_file)
|
||||||
|
self.assertEqual('0 bytes', payload_info['Tree Size'])
|
||||||
|
|
||||||
@test_utils.SkipIfExternalToolsUnavailable()
|
@test_utils.SkipIfExternalToolsUnavailable()
|
||||||
def test_SignApexPayload_withSignerHelper(self):
|
def test_SignApexPayload_withSignerHelper(self):
|
||||||
@@ -70,8 +93,10 @@ class ApexUtilsTest(test_utils.ReleaseToolsTestCase):
|
|||||||
payload_file,
|
payload_file,
|
||||||
self.payload_key,
|
self.payload_key,
|
||||||
'testkey', 'SHA256_RSA2048', self.SALT,
|
'testkey', 'SHA256_RSA2048', self.SALT,
|
||||||
|
True,
|
||||||
payload_signer_args)
|
payload_signer_args)
|
||||||
apex_utils.VerifyApexPayload('avbtool', payload_file, self.payload_key)
|
apex_utils.VerifyApexPayload(
|
||||||
|
'avbtool', payload_file, self.payload_key, True)
|
||||||
|
|
||||||
@test_utils.SkipIfExternalToolsUnavailable()
|
@test_utils.SkipIfExternalToolsUnavailable()
|
||||||
def test_SignApexPayload_invalidKey(self):
|
def test_SignApexPayload_invalidKey(self):
|
||||||
@@ -83,18 +108,21 @@ class ApexUtilsTest(test_utils.ReleaseToolsTestCase):
|
|||||||
os.path.join(self.testdata_dir, 'testkey.x509.pem'),
|
os.path.join(self.testdata_dir, 'testkey.x509.pem'),
|
||||||
'testkey',
|
'testkey',
|
||||||
'SHA256_RSA2048',
|
'SHA256_RSA2048',
|
||||||
self.SALT)
|
self.SALT,
|
||||||
|
no_hashtree=True)
|
||||||
|
|
||||||
@test_utils.SkipIfExternalToolsUnavailable()
|
@test_utils.SkipIfExternalToolsUnavailable()
|
||||||
def test_VerifyApexPayload_wrongKey(self):
|
def test_VerifyApexPayload_wrongKey(self):
|
||||||
payload_file = self._GetTestPayload()
|
payload_file = self._GetTestPayload()
|
||||||
apex_utils.SignApexPayload(
|
apex_utils.SignApexPayload(
|
||||||
'avbtool', payload_file, self.payload_key, 'testkey', 'SHA256_RSA2048',
|
'avbtool', payload_file, self.payload_key, 'testkey', 'SHA256_RSA2048',
|
||||||
self.SALT)
|
self.SALT, True)
|
||||||
apex_utils.VerifyApexPayload('avbtool', payload_file, self.payload_key)
|
apex_utils.VerifyApexPayload(
|
||||||
|
'avbtool', payload_file, self.payload_key, True)
|
||||||
self.assertRaises(
|
self.assertRaises(
|
||||||
apex_utils.ApexSigningError,
|
apex_utils.ApexSigningError,
|
||||||
apex_utils.VerifyApexPayload,
|
apex_utils.VerifyApexPayload,
|
||||||
'avbtool',
|
'avbtool',
|
||||||
payload_file,
|
payload_file,
|
||||||
os.path.join(self.testdata_dir, 'testkey_with_passwd.key'))
|
os.path.join(self.testdata_dir, 'testkey_with_passwd.key'),
|
||||||
|
no_hashtree=True)
|
||||||
|
Reference in New Issue
Block a user