From 5e7e254e0895803b285a938ddbbc076e8090ef4e Mon Sep 17 00:00:00 2001 From: Alexey Min Date: Mon, 2 Mar 2020 06:23:42 +0300 Subject: [PATCH] main/avbtool: new aport (!1019) Tools to work with Android Verified Boot 2.0 images (vbmeta) --- main/avbtool/0001-Convert-to-python3.patch | 355 +++++++++++++++++++++ main/avbtool/APKBUILD | 23 ++ 2 files changed, 378 insertions(+) create mode 100644 main/avbtool/0001-Convert-to-python3.patch create mode 100644 main/avbtool/APKBUILD diff --git a/main/avbtool/0001-Convert-to-python3.patch b/main/avbtool/0001-Convert-to-python3.patch new file mode 100644 index 000000000..944bb72bd --- /dev/null +++ b/main/avbtool/0001-Convert-to-python3.patch @@ -0,0 +1,355 @@ +From ea3e18b3f7bbd17969b5c7646c2cc6e9441b92d0 Mon Sep 17 00:00:00 2001 +From: Alexey Min +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 +--- + 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 + diff --git a/main/avbtool/APKBUILD b/main/avbtool/APKBUILD new file mode 100644 index 000000000..ed3b64052 --- /dev/null +++ b/main/avbtool/APKBUILD @@ -0,0 +1,23 @@ +# Maintainer: Alexey Min +pkgname=avbtool +pkgver=10.0.0_p29 +pkgrel=0 +_commit="119251268c594d115a1eff31b3ec32108b88b593" +pkgdesc="Tools and libraries for working with Android Verified Boot 2.0" +arch="noarch" +url="https://android.googlesource.com/platform/external/avb/" +license="MIT" +depends="python3" +source=" + $pkgname-$_commit.tar.gz::https://source.codeaurora.org/quic/la/platform/external/avb/snapshot/$_commit.tar.gz + 0001-Convert-to-python3.patch + " +options="!check" # No tests available +builddir="$srcdir/$_commit" + +package() { + install -Dm755 "$builddir/avbtool" "$pkgdir/usr/bin/avbtool" +} + +sha512sums="9304cf577a2646dff3750707a83984f17fa476a380e7068fc042f1f4c43ac44cd42d307beadabccc224f35e176d2afcccd5ac74d0adf26cbfdda953aa4f42454 avbtool-119251268c594d115a1eff31b3ec32108b88b593.tar.gz +d07a83a728f7a42f6351ebd7532fcf6fe6aca93a8b6be9b64ba1f0aef54c8f15a18f6e8836f8ae10a94d47f3dfac67f4b3fa1cc8d1cb2afcb667584b4baca3fe 0001-Convert-to-python3.patch"