5e7e254e08
Tools to work with Android Verified Boot 2.0 images (vbmeta)
355 lines
16 KiB
Diff
355 lines
16 KiB
Diff
From ea3e18b3f7bbd17969b5c7646c2cc6e9441b92d0 Mon Sep 17 00:00:00 2001
|
|
From: Alexey Min <alexey.min@gmail.com>
|
|
Date: Mon, 2 Mar 2020 06:01:46 +0300
|
|
Subject: [PATCH] Convert to python3
|
|
|
|
Partially generated by 2to3 tool, partially by hand.
|
|
|
|
Signed-off-by: Alexey Min <alexey.min@gmail.com>
|
|
---
|
|
avbtool | 105 +++++++++++++++++++++++++++-----------------------------
|
|
1 file changed, 50 insertions(+), 55 deletions(-)
|
|
|
|
diff --git a/avbtool b/avbtool
|
|
index 610cf19..a917810 100755
|
|
--- a/avbtool
|
|
+++ b/avbtool
|
|
@@ -1,4 +1,4 @@
|
|
-#!/usr/bin/env python
|
|
+#!/usr/bin/python3
|
|
|
|
# Copyright 2016, The Android Open Source Project
|
|
#
|
|
@@ -407,10 +407,10 @@ def encode_rsa_key(key_path):
|
|
raise AvbError('Only RSA keys with exponent 65537 are supported.')
|
|
ret = bytearray()
|
|
# Calculate n0inv = -1/n[0] (mod 2^32)
|
|
- b = 2L**32
|
|
+ b = 2**32
|
|
n0inv = b - modinv(key.modulus, b)
|
|
# Calculate rr = r^2 (mod N), where r = 2^(# of key bits)
|
|
- r = 2L**key.modulus.bit_length()
|
|
+ r = 2**key.modulus.bit_length()
|
|
rrmodn = r * r % key.modulus
|
|
ret.extend(struct.pack('!II', key.num_bits, n0inv))
|
|
ret.extend(encode_long(key.num_bits, key.modulus))
|
|
@@ -741,7 +741,7 @@ class ImageHandler(object):
|
|
# image.
|
|
offset = 0
|
|
output_offset = 0
|
|
- for _ in xrange(1, self._num_total_chunks + 1):
|
|
+ for _ in range(1, self._num_total_chunks + 1):
|
|
chunk_offset = self._image.tell()
|
|
|
|
header_bin = self._image.read(struct.calcsize(ImageChunk.FORMAT))
|
|
@@ -1187,7 +1187,7 @@ class AvbPropertyDescriptor(AvbDescriptor):
|
|
o: The object to write the output to.
|
|
"""
|
|
if len(self.value) < 256:
|
|
- o.write(' Prop: {} -> {}\n'.format(self.key, repr(str(self.value))))
|
|
+ o.write(' Prop: {} -> {}\n'.format(self.key.decode('utf-8'), repr(self.value.decode('utf-8'))))
|
|
else:
|
|
o.write(' Prop: {} -> ({} bytes)\n'.format(self.key, len(self.value)))
|
|
|
|
@@ -1290,17 +1290,17 @@ class AvbHashtreeDescriptor(AvbDescriptor):
|
|
raise LookupError('Given data does not look like a hashtree '
|
|
'descriptor.')
|
|
# Nuke NUL-bytes at the end.
|
|
- self.hash_algorithm = self.hash_algorithm.split('\0', 1)[0]
|
|
+ self.hash_algorithm = self.hash_algorithm.split(b'\0', 1)[0]
|
|
o = 0
|
|
- self.partition_name = str(data[(self.SIZE + o):(self.SIZE + o +
|
|
+ self.partition_name = bytes(data[(self.SIZE + o):(self.SIZE + o +
|
|
partition_name_len)])
|
|
# Validate UTF-8 - decode() raises UnicodeDecodeError if not valid UTF-8.
|
|
self.partition_name.decode('utf-8')
|
|
o += partition_name_len
|
|
- self.salt = data[(self.SIZE + o):(self.SIZE + o + salt_len)]
|
|
+ self.salt = bytes(data[(self.SIZE + o):(self.SIZE + o + salt_len)])
|
|
o += salt_len
|
|
self.root_digest = data[(self.SIZE + o):(self.SIZE + o + root_digest_len)]
|
|
- if root_digest_len != len(hashlib.new(name=self.hash_algorithm).digest()):
|
|
+ if root_digest_len != len(hashlib.new(name=self.hash_algorithm.decode('utf-8')).digest()):
|
|
if root_digest_len != 0:
|
|
raise LookupError('root_digest_len doesn\'t match hash algorithm')
|
|
|
|
@@ -1315,7 +1315,7 @@ class AvbHashtreeDescriptor(AvbDescriptor):
|
|
self.fec_offset = 0
|
|
self.fec_size = 0
|
|
self.hash_algorithm = ''
|
|
- self.partition_name = ''
|
|
+ self.partition_name = b''
|
|
self.salt = bytearray()
|
|
self.root_digest = bytearray()
|
|
self.flags = 0
|
|
@@ -1338,12 +1338,10 @@ class AvbHashtreeDescriptor(AvbDescriptor):
|
|
o.write(' FEC num roots: {}\n'.format(self.fec_num_roots))
|
|
o.write(' FEC offset: {}\n'.format(self.fec_offset))
|
|
o.write(' FEC size: {} bytes\n'.format(self.fec_size))
|
|
- o.write(' Hash Algorithm: {}\n'.format(self.hash_algorithm))
|
|
- o.write(' Partition Name: {}\n'.format(self.partition_name))
|
|
- o.write(' Salt: {}\n'.format(str(self.salt).encode(
|
|
- 'hex')))
|
|
- o.write(' Root Digest: {}\n'.format(str(
|
|
- self.root_digest).encode('hex')))
|
|
+ o.write(' Hash Algorithm: {}\n'.format(self.hash_algorithm.decode('utf-8')))
|
|
+ o.write(' Partition Name: {}\n'.format(self.partition_name.decode('utf-8')))
|
|
+ o.write(' Salt: {}\n'.format(self.salt.hex()))
|
|
+ o.write(' Root Digest: {}\n'.format(self.root_digest.hex()))
|
|
o.write(' Flags: {}\n'.format(self.flags))
|
|
|
|
def encode(self):
|
|
@@ -1414,7 +1412,7 @@ class AvbHashtreeDescriptor(AvbDescriptor):
|
|
# correct but this a) currently requires the 'fec' binary; and b)
|
|
# takes a long time; and c) is not strictly needed for
|
|
# verification purposes as we've already verified the root hash.
|
|
- print ('{}: Successfully verified {} hashtree of {} for image of {} bytes'
|
|
+ print('{}: Successfully verified {} hashtree of {} for image of {} bytes'
|
|
.format(self.partition_name, self.hash_algorithm, image.filename,
|
|
self.image_size))
|
|
return True
|
|
@@ -1468,17 +1466,17 @@ class AvbHashDescriptor(AvbDescriptor):
|
|
if tag != self.TAG or num_bytes_following != expected_size:
|
|
raise LookupError('Given data does not look like a hash ' 'descriptor.')
|
|
# Nuke NUL-bytes at the end.
|
|
- self.hash_algorithm = self.hash_algorithm.split('\0', 1)[0]
|
|
+ self.hash_algorithm = self.hash_algorithm.split(b'\0', 1)[0]
|
|
o = 0
|
|
- self.partition_name = str(data[(self.SIZE + o):(self.SIZE + o +
|
|
+ self.partition_name = bytes(data[(self.SIZE + o):(self.SIZE + o +
|
|
partition_name_len)])
|
|
# Validate UTF-8 - decode() raises UnicodeDecodeError if not valid UTF-8.
|
|
self.partition_name.decode('utf-8')
|
|
o += partition_name_len
|
|
- self.salt = data[(self.SIZE + o):(self.SIZE + o + salt_len)]
|
|
+ self.salt = bytes(data[(self.SIZE + o):(self.SIZE + o + salt_len)])
|
|
o += salt_len
|
|
self.digest = data[(self.SIZE + o):(self.SIZE + o + digest_len)]
|
|
- if digest_len != len(hashlib.new(name=self.hash_algorithm).digest()):
|
|
+ if digest_len != len(hashlib.new(name=self.hash_algorithm.decode('utf-8')).digest()):
|
|
if digest_len != 0:
|
|
raise LookupError('digest_len doesn\'t match hash algorithm')
|
|
|
|
@@ -1498,12 +1496,10 @@ class AvbHashDescriptor(AvbDescriptor):
|
|
"""
|
|
o.write(' Hash descriptor:\n')
|
|
o.write(' Image Size: {} bytes\n'.format(self.image_size))
|
|
- o.write(' Hash Algorithm: {}\n'.format(self.hash_algorithm))
|
|
- o.write(' Partition Name: {}\n'.format(self.partition_name))
|
|
- o.write(' Salt: {}\n'.format(str(self.salt).encode(
|
|
- 'hex')))
|
|
- o.write(' Digest: {}\n'.format(str(self.digest).encode(
|
|
- 'hex')))
|
|
+ o.write(' Hash Algorithm: {}\n'.format(self.hash_algorithm.decode('utf-8')))
|
|
+ o.write(' Partition Name: {}\n'.format(self.partition_name.decode('utf-8')))
|
|
+ o.write(' Salt: {}\n'.format(self.salt.hex()))
|
|
+ o.write(' Digest: {}\n'.format(self.digest.hex()))
|
|
o.write(' Flags: {}\n'.format(self.flags))
|
|
|
|
def encode(self):
|
|
@@ -1554,7 +1550,7 @@ class AvbHashDescriptor(AvbDescriptor):
|
|
sys.stderr.write('{} digest of {} does not match digest in descriptor\n'.
|
|
format(self.hash_algorithm, image_filename))
|
|
return False
|
|
- print ('{}: Successfully verified {} hash of {} for image of {} bytes'
|
|
+ print('{}: Successfully verified {} hash of {} for image of {} bytes'
|
|
.format(self.partition_name, self.hash_algorithm, image.filename,
|
|
self.image_size))
|
|
return True
|
|
@@ -1600,13 +1596,13 @@ class AvbKernelCmdlineDescriptor(AvbDescriptor):
|
|
raise LookupError('Given data does not look like a kernel cmdline '
|
|
'descriptor.')
|
|
# Nuke NUL-bytes at the end.
|
|
- self.kernel_cmdline = str(data[self.SIZE:(self.SIZE +
|
|
+ self.kernel_cmdline = bytes(data[self.SIZE:(self.SIZE +
|
|
kernel_cmdline_length)])
|
|
# Validate UTF-8 - decode() raises UnicodeDecodeError if not valid UTF-8.
|
|
self.kernel_cmdline.decode('utf-8')
|
|
else:
|
|
self.flags = 0
|
|
- self.kernel_cmdline = ''
|
|
+ self.kernel_cmdline = b''
|
|
|
|
def print_desc(self, o):
|
|
"""Print the descriptor.
|
|
@@ -1616,8 +1612,7 @@ class AvbKernelCmdlineDescriptor(AvbDescriptor):
|
|
"""
|
|
o.write(' Kernel Cmdline descriptor:\n')
|
|
o.write(' Flags: {}\n'.format(self.flags))
|
|
- o.write(' Kernel Cmdline: {}\n'.format(repr(
|
|
- self.kernel_cmdline)))
|
|
+ o.write(' Kernel Cmdline: {}\n'.format(self.kernel_cmdline.decode('utf-8')))
|
|
|
|
def encode(self):
|
|
"""Serializes the descriptor.
|
|
@@ -1775,7 +1770,7 @@ class AvbChainPartitionDescriptor(AvbDescriptor):
|
|
format(self.partition_name))
|
|
return False
|
|
|
|
- print ('{}: Successfully verified chain partition descriptor matches '
|
|
+ print('{}: Successfully verified chain partition descriptor matches '
|
|
'expected data'.format(self.partition_name))
|
|
|
|
return True
|
|
@@ -1927,10 +1922,10 @@ class AvbVBMetaHeader(object):
|
|
self.flags,
|
|
self.release_string) = struct.unpack(self.FORMAT_STRING, data)
|
|
# Nuke NUL-bytes at the end of the string.
|
|
- if self.magic != 'AVB0':
|
|
+ if self.magic != b'AVB0':
|
|
raise AvbError('Given image does not look like a vbmeta image.')
|
|
else:
|
|
- self.magic = 'AVB0'
|
|
+ self.magic = b'AVB0'
|
|
# Start by just requiring version 1.0. Code that adds features
|
|
# in a future version can use bump_required_libavb_version_minor() to
|
|
# bump the minor.
|
|
@@ -1951,7 +1946,7 @@ class AvbVBMetaHeader(object):
|
|
self.descriptors_size = 0
|
|
self.rollback_index = 0
|
|
self.flags = 0
|
|
- self.release_string = get_release_string()
|
|
+ self.release_string = get_release_string().encode('utf-8')
|
|
|
|
def bump_required_libavb_version_minor(self, minor):
|
|
"""Function to bump required_libavb_version_minor.
|
|
@@ -2209,7 +2204,7 @@ class Avb(object):
|
|
o.write('Rollback Index: {}\n'.format(header.rollback_index))
|
|
o.write('Flags: {}\n'.format(header.flags))
|
|
o.write('Release String: \'{}\'\n'.format(
|
|
- header.release_string.rstrip('\0')))
|
|
+ header.release_string.rstrip(b'\0').decode('utf-8')))
|
|
|
|
# Print descriptors.
|
|
num_printed = 0
|
|
@@ -2248,10 +2243,10 @@ class Avb(object):
|
|
|
|
key_blob = None
|
|
if key_path:
|
|
- print 'Verifying image {} using key at {}'.format(image_filename, key_path)
|
|
+ print('Verifying image {} using key at {}'.format(image_filename, key_path))
|
|
key_blob = encode_rsa_key(key_path)
|
|
else:
|
|
- print 'Verifying image {} using embedded public key'.format(image_filename)
|
|
+ print('Verifying image {} using embedded public key'.format(image_filename))
|
|
|
|
image = ImageHandler(image_filename)
|
|
(footer, header, descriptors, image_size) = self._parse_image(image)
|
|
@@ -2278,10 +2273,10 @@ class Avb(object):
|
|
raise AvbError('Embedded public key does not match given key.')
|
|
|
|
if footer:
|
|
- print ('vbmeta: Successfully verified footer and {} vbmeta struct in {}'
|
|
+ print('vbmeta: Successfully verified footer and {} vbmeta struct in {}'
|
|
.format(alg_name, image.filename))
|
|
else:
|
|
- print ('vbmeta: Successfully verified {} vbmeta struct in {}'
|
|
+ print('vbmeta: Successfully verified {} vbmeta struct in {}'
|
|
.format(alg_name, image.filename))
|
|
|
|
for desc in descriptors:
|
|
@@ -2290,7 +2285,7 @@ class Avb(object):
|
|
# In this case we're processing a chain descriptor but don't have a
|
|
# --expect_chain_partition ... however --follow_chain_partitions was
|
|
# specified so we shouldn't error out in desc.verify().
|
|
- print ('{}: Chained but ROLLBACK_SLOT (which is {}) and KEY (which has sha1 {}) not specified'
|
|
+ print('{}: Chained but ROLLBACK_SLOT (which is {}) and KEY (which has sha1 {}) not specified'
|
|
.format(desc.partition_name, desc.rollback_index_location,
|
|
hashlib.sha1(desc.public_key).hexdigest()))
|
|
else:
|
|
@@ -2298,7 +2293,7 @@ class Avb(object):
|
|
raise AvbError('Error verifying descriptor.')
|
|
# Honor --follow_chain_partitions - add '--' to make the output more readable.
|
|
if isinstance(desc, AvbChainPartitionDescriptor) and follow_chain_partitions:
|
|
- print '--'
|
|
+ print('--')
|
|
chained_image_filename = os.path.join(image_dir, desc.partition_name + image_ext)
|
|
self.verify_image(chained_image_filename, key_path, None, False)
|
|
|
|
@@ -2593,10 +2588,10 @@ class Avb(object):
|
|
(_, image_header, _, _) = self._parse_image(ImageHandler(image.name))
|
|
tmp_header.bump_required_libavb_version_minor(
|
|
image_header.required_libavb_version_minor)
|
|
- print '1.{}'.format(tmp_header.required_libavb_version_minor)
|
|
+ print('1.{}'.format(tmp_header.required_libavb_version_minor))
|
|
else:
|
|
# Descriptors aside, all vbmeta features are supported in 1.0.
|
|
- print '1.0'
|
|
+ print('1.0')
|
|
return
|
|
|
|
if not output:
|
|
@@ -2619,7 +2614,7 @@ class Avb(object):
|
|
if padding_size > 0:
|
|
padded_size = round_to_multiple(len(vbmeta_blob), padding_size)
|
|
padding_needed = padded_size - len(vbmeta_blob)
|
|
- output.write('\0' * padding_needed)
|
|
+ output.write(b'\0' * padding_needed)
|
|
|
|
def _generate_vbmeta_blob(self, algorithm_name, key_path,
|
|
public_key_metadata_path, descriptors,
|
|
@@ -2800,12 +2795,12 @@ class Avb(object):
|
|
algorithm_name))
|
|
|
|
# Override release string, if requested.
|
|
- if isinstance(release_string, (str, unicode)):
|
|
- h.release_string = release_string
|
|
+ if isinstance(release_string, str):
|
|
+ h.release_string = release_string.encode('utf-8')
|
|
|
|
# Append to release string, if requested. Also insert a space before.
|
|
- if isinstance(append_to_release_string, (str, unicode)):
|
|
- h.release_string += ' ' + append_to_release_string
|
|
+ if isinstance(append_to_release_string, str):
|
|
+ h.release_string += ' ' + append_to_release_string.encode('utf-8')
|
|
|
|
# For the Auxiliary data block, descriptors are stored at offset 0,
|
|
# followed by the public key, followed by the public key metadata blob.
|
|
@@ -3017,7 +3012,7 @@ class Avb(object):
|
|
|
|
# If we're asked to calculate minimum required libavb version, we're done.
|
|
if print_required_libavb_version:
|
|
- print '1.{}'.format(required_libavb_version_minor)
|
|
+ print('1.{}'.format(required_libavb_version_minor))
|
|
return
|
|
|
|
# First, calculate the maximum image size such that an image
|
|
@@ -3032,7 +3027,7 @@ class Avb(object):
|
|
|
|
# If we're asked to only calculate the maximum image size, we're done.
|
|
if calc_max_image_size:
|
|
- print '{}'.format(max_image_size)
|
|
+ print('{}'.format(max_image_size))
|
|
return
|
|
|
|
image = ImageHandler(image_filename)
|
|
@@ -3226,7 +3221,7 @@ class Avb(object):
|
|
|
|
# If we're asked to calculate minimum required libavb version, we're done.
|
|
if print_required_libavb_version:
|
|
- print '1.{}'.format(required_libavb_version_minor)
|
|
+ print('1.{}'.format(required_libavb_version_minor))
|
|
return
|
|
|
|
digest_size = len(hashlib.new(name=hash_algorithm).digest())
|
|
@@ -3251,7 +3246,7 @@ class Avb(object):
|
|
|
|
# If we're asked to only calculate the maximum image size, we're done.
|
|
if calc_max_image_size:
|
|
- print '{}'.format(max_image_size)
|
|
+ print('{}'.format(max_image_size))
|
|
return
|
|
|
|
image = ImageHandler(image_filename)
|
|
@@ -4258,7 +4253,7 @@ class AvbTool(object):
|
|
|
|
def version(self, _):
|
|
"""Implements the 'version' sub-command."""
|
|
- print get_release_string()
|
|
+ print(get_release_string())
|
|
|
|
def extract_public_key(self, args):
|
|
"""Implements the 'extract_public_key' sub-command."""
|
|
--
|
|
2.24.1
|
|
|