aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorandroid-build-team Robot <android-build-team-robot@google.com>2020-04-28 20:23:57 +0000
committerandroid-build-team Robot <android-build-team-robot@google.com>2020-04-28 20:23:57 +0000
commite41eb6cf0e47ae7faeff4e26445fa9a4d6d4b55c (patch)
tree4e0288dcd8457d6cfbee7e3f66a6fb5608245a13
parent0102b94ebcee6dfe646b3accbe442dc961ebc317 (diff)
parentab84f1361f164e2ff20564d2d2595497ddf80ce5 (diff)
downloadavb-android10-mainline-tzdata-release.tar.gz
Change-Id: Ie91f99ce4f905f8ecdcab123ea0fe07962f9c38f
-rw-r--r--Android.bp42
-rw-r--r--README.md73
-rwxr-xr-xavbtool152
-rw-r--r--libavb/avb_cmdline.c27
-rw-r--r--libavb/avb_cmdline.h1
-rw-r--r--libavb/avb_descriptor.c11
-rw-r--r--libavb/avb_ops.h23
-rw-r--r--libavb/avb_slot_verify.c323
-rw-r--r--libavb/avb_slot_verify.h16
-rw-r--r--libavb/avb_sysdeps.h8
-rw-r--r--libavb/avb_sysdeps_posix.c4
-rw-r--r--test/Android.bp1
-rw-r--r--test/avb_slot_verify_unittest.cc177
-rw-r--r--test/avb_sysdeps_posix_testing.cc4
-rw-r--r--test/avbtool_unittest.cc232
-rw-r--r--test/fake_avb_ops.cc47
-rw-r--r--test/fake_avb_ops.h53
-rwxr-xr-xtools/at_auth_unlock.py76
-rwxr-xr-xtools/transparency/pixel_factory_image_verify.py341
19 files changed, 167 insertions, 1444 deletions
diff --git a/Android.bp b/Android.bp
index 097d80a..7245161 100644
--- a/Android.bp
+++ b/Android.bp
@@ -107,10 +107,7 @@ cc_library_static {
],
host_supported: true,
recovery_available: true,
- header_libs: [
- "avb_headers",
- ],
- export_header_lib_headers: ["avb_headers"],
+ export_include_dirs: ["."],
target: {
linux: {
srcs: ["libavb/avb_sysdeps_posix.c"],
@@ -131,10 +128,7 @@ cc_library_static {
"avb_sources",
],
recovery_available: true,
- header_libs: [
- "avb_headers",
- ],
- export_header_lib_headers: ["avb_headers"],
+ export_include_dirs: ["."],
shared_libs: ["libbase"],
static_libs: ["libfs_mgr"],
cflags: [
@@ -163,10 +157,7 @@ cc_binary {
cc_library_host_static {
name: "libavb_ab_host",
defaults: ["avb_defaults"],
- header_libs: [
- "avb_headers",
- ],
- export_header_lib_headers: ["avb_headers"],
+ export_include_dirs: ["."],
cflags: [
"-fno-stack-protector",
"-DAVB_AB_I_UNDERSTAND_LIBAVB_AB_IS_DEPRECATED",
@@ -177,10 +168,7 @@ cc_library_host_static {
cc_library_host_static {
name: "libavb_atx_host",
defaults: ["avb_defaults"],
- header_libs: [
- "avb_headers",
- ],
- export_header_lib_headers: ["avb_headers"],
+ export_include_dirs: ["."],
cflags: [
"-fno-stack-protector",
],
@@ -190,20 +178,14 @@ cc_library_host_static {
cc_library_host_static {
name: "libavb_host_sysdeps",
defaults: ["avb_defaults"],
- header_libs: [
- "avb_headers",
- ],
- export_header_lib_headers: ["avb_headers"],
+ export_include_dirs: ["."],
srcs: ["libavb/avb_sysdeps_posix.c"],
}
cc_library_host_static {
name: "libavb_things_example",
defaults: ["avb_defaults"],
- header_libs: [
- "avb_headers",
- ],
- export_header_lib_headers: ["avb_headers"],
+ export_include_dirs: ["."],
srcs: ["examples/things/avb_atx_slot_verify.c"],
}
@@ -279,15 +261,3 @@ cc_library {
],
srcs: ["boot_control/boot_control_avb.c"],
}
-
-cc_library_headers {
- name: "avb_headers",
- host_supported: true,
- recovery_available: true,
- export_include_dirs: ["."],
- target: {
- windows: {
- enabled: true,
- },
- },
-}
diff --git a/README.md b/README.md
index b01acee..fbee3f5 100644
--- a/README.md
+++ b/README.md
@@ -27,7 +27,6 @@ Verified Boot 2.0. Usually AVB is used to refer to this codebase.
+ [Persistent Digests](#Persistent-Digests)
+ [Updating Stored Rollback Indexes](#Updating-Stored-Rollback-Indexes)
+ [Recommended Bootflow](#Recommended-Bootflow)
- + [Booting Into Recovery](#Booting-Into-Recovery)
+ [Handling dm-verity Errors](#Handling-dm_verity-Errors)
+ [Android Specific Integration](#Android-Specific-Integration)
+ [Device Specific Notes](#Device-Specific-Notes)
@@ -165,24 +164,6 @@ a relying party can extract the digest and compare it with list of digests for
known good operating systems which, if found, provides additional assurance
about the device the application is running on.
-For [factory images of Pixel 3 and later
-devices](https://developers.google.com/android/images), the
-`pixel_factory_image_verify.py` located in `tools/transparency` is a convenience
-tool for downloading, verifying and calcuating VBMeta Digests.
-
- $ pixel_factory_image_verify.py https://dl.google.com/dl/android/aosp/image.zip
- Fetching file from: https://dl.google.com/dl/android/aosp/image.zip
- Successfully downloaded file.
- Successfully unpacked factory image.
- Successfully unpacked factory image partitions.
- Successfully verified VBmeta.
- Successfully calculated VBMeta Digest.
- The VBMeta Digest for factory image is: 1f329b20a2dd69425e7a29566ca870dad51d2c579311992d41c9ba9ba05e170e
-
-If the given argument is not an URL it considered to be a local file:
-
- $ pixel_factory_image_verify.py image.zip
-
# Tools and Libraries
This section contains information about the tools and libraries
@@ -422,7 +403,6 @@ hashtree is also appended to the image.
[--append_to_release_string STR] \
[--calc_max_image_size] \
[--do_not_use_ab] \
- [--no_hashtree] \
[--use_persistent_digest]
The size of an image with integrity footers can be changed using the
@@ -442,18 +422,6 @@ an external file via the `--output_vbmeta_image` option and one can
also specify that the vbmeta struct and footer not be added to the
image being operated on.
-The hashtree and FEC data in an image can be zeroed out with the following
-command:
-
- $ avbtool zero_hashtree --image IMAGE
-
-This is useful for trading compressed image size for having to reculculate the
-hashtree and FEC at runtime. If this is done the hashtree and FEC data is set
-to zero except for the first eight bytes which are set to the magic
-`ZeRoHaSH`. Either the hashtree or FEC data or both may be zeroed this way
-so applications should check for the magic both places. Applications can
-use the magic to detect if recalculation is needed.
-
To calculate the maximum size of an image that will fit in a partition
of a given size after having used the `avbtool add_hash_footer` or
`avbtool add_hashtree_footer` commands on it, use the
@@ -479,12 +447,6 @@ vbmeta struct when using `make_vbmeta_image`, `add_hash_footer`, and
--print_required_libavb_version
1.0
-Alternatively, `--no_hashtree` can be used with `avbtool add_hashtree_footer`
-command. If `--no_hashtree` is given, the hashtree blob is omitted and only
-its descriptor is added to the vbmeta struct. The descriptor says the size
-of hashtree is 0, which tells an application the need to recalculate
-hashtree.
-
The `--signing_helper` option can be used in `make_vbmeta_image`,
`add_hash_footer` and `add_hashtree_footer` commands to specify any
external program for signing hashes. The data to sign (including
@@ -602,8 +564,8 @@ a hash descriptor for `boot.img`, a hashtree descriptor for
`system.img`, a kernel-cmdline descriptor for setting up `dm-verity`
for `system.img` and append a hash-tree to `system.img`. If the build
system is set up such that one or many of `vendor.img` / `product.img`
-/ `system_ext.img` / `odm.img` are being built, the hash-tree for each
-of them will also be appended to the image respectively, and their
+/ `odm.img` / `product_services.img` are being built, the hash-tree for
+each of them will also be appended to the image respectively, and their
hash-tree descriptors will be included into `vbmeta.img` accordingly.
By default, the algorithm `SHA256_RSA4096` is used with a test key
@@ -631,20 +593,20 @@ Devices can be configured to create additional `vbmeta` partitions as
partitions without changing the top-level `vbmeta` partition. For example,
the following variables create `vbmeta_system.img` as a chained `vbmeta`
image that contains the hash-tree descriptors for `system.img` and
-`system_ext.img`. `vbmeta_system.img` itself will be signed by the specified
-key and algorithm.
+`product_services.img`. `vbmeta_system.img` itself will be signed by the
+specified key and algorithm.
- BOARD_AVB_VBMETA_SYSTEM := system system_ext
+ BOARD_AVB_VBMETA_SYSTEM := system product_services
BOARD_AVB_VBMETA_SYSTEM_KEY_PATH := external/avb/test/data/testkey_rsa2048.pem
BOARD_AVB_VBMETA_SYSTEM_ALGORITHM := SHA256_RSA2048
BOARD_AVB_VBMETA_SYSTEM_ROLLBACK_INDEX_LOCATION := 1
-Note that the hash-tree descriptors for `system.img` and `system_ext.img`
-will be included only in `vbmeta_system.img`, but not `vbmeta.img`. With
-the above setup, partitions `system.img`, `system_ext.img` and
-`vbmeta_system.img` can be updated independently - but as a group - of the
-rest of the partitions, *or* as part of the traditional updates that
-update all the partitions.
+Note that the hash-tree descriptors for `system.img` and
+`product_services.img` will be included only in `vbmeta_system.img`, but
+not `vbmeta.img`. With the above setup, partitions `system.img`,
+`product_services.img` and `vbmeta_system.img` can be updated
+independently - but as a group - of the rest of the partitions, *or* as
+part of the traditional updates that update all the partitions.
Currently build system supports building chained `vbmeta` images of
`vbmeta_system.img` (`BOARD_AVB_VBMETA_SYSTEM`) and `vbmeta_vendor.img`
@@ -925,19 +887,6 @@ Notes:
be used to convey that the device is UNLOCKED (lightbars, LEDs,
etc.).
-### Booting Into Recovery
-
-On Android devices not using A/B, the `recovery` partition usually isn't
-updated along with other partitions and therefore can't be referenced
-from the main `vbmeta` partition.
-
-It's still possible to use AVB to protect this partition (and others)
-by signing these partitions and passing the
-`AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION` flag to `avb_slot_verify()`.
-In this mode, the key used to sign each requested partition is verified
-by the `validate_public_key_for_partition()` operation which is also
-used to return the rollback index location to be used.
-
## Handling dm-verity Errors
By design, hashtree verification errors are detected by the HLOS and
diff --git a/avbtool b/avbtool
index 92c024c..610cf19 100755
--- a/avbtool
+++ b/avbtool
@@ -1121,7 +1121,7 @@ class AvbDescriptor(object):
return bytearray(ret)
def verify(self, image_dir, image_ext, expected_chain_partitions_map,
- image_containing_descriptor, accept_zeroed_hashtree):
+ image_containing_descriptor):
"""Verifies contents of the descriptor - used in verify_image sub-command.
Arguments:
@@ -1130,7 +1130,6 @@ class AvbDescriptor(object):
expected_chain_partitions_map: A map from partition name to the
tuple (rollback_index_location, key_blob).
image_containing_descriptor: The image the descriptor is in.
- accept_zeroed_hashtree: If True, don't fail if hashtree or FEC data is zeroed out.
Returns:
True if the descriptor verifies, False otherwise.
@@ -1208,7 +1207,7 @@ class AvbPropertyDescriptor(AvbDescriptor):
return bytearray(ret)
def verify(self, image_dir, image_ext, expected_chain_partitions_map,
- image_containing_descriptor, accept_zeroed_hashtree):
+ image_containing_descriptor):
"""Verifies contents of the descriptor - used in verify_image sub-command.
Arguments:
@@ -1217,7 +1216,6 @@ class AvbPropertyDescriptor(AvbDescriptor):
expected_chain_partitions_map: A map from partition name to the
tuple (rollback_index_location, key_blob).
image_containing_descriptor: The image the descriptor is in.
- accept_zeroed_hashtree: If True, don't fail if hashtree or FEC data is zeroed out.
Returns:
True if the descriptor verifies, False otherwise.
@@ -1371,7 +1369,7 @@ class AvbHashtreeDescriptor(AvbDescriptor):
return bytearray(ret)
def verify(self, image_dir, image_ext, expected_chain_partitions_map,
- image_containing_descriptor, accept_zeroed_hashtree):
+ image_containing_descriptor):
"""Verifies contents of the descriptor - used in verify_image sub-command.
Arguments:
@@ -1380,13 +1378,11 @@ class AvbHashtreeDescriptor(AvbDescriptor):
expected_chain_partitions_map: A map from partition name to the
tuple (rollback_index_location, key_blob).
image_containing_descriptor: The image the descriptor is in.
- accept_zeroed_hashtree: If True, don't fail if hashtree or FEC data is zeroed out.
Returns:
True if the descriptor verifies, False otherwise.
"""
if self.partition_name == '':
- image_filename = image_containing_descriptor.filename
image = image_containing_descriptor
else:
image_filename = os.path.join(image_dir, self.partition_name + image_ext)
@@ -1410,22 +1406,17 @@ class AvbHashtreeDescriptor(AvbDescriptor):
# ... also check that the on-disk hashtree matches
image.seek(self.tree_offset)
hash_tree_ondisk = image.read(self.tree_size)
- is_zeroed = (self.tree_size == 0) or (hash_tree_ondisk[0:8] == 'ZeRoHaSH')
- if is_zeroed and accept_zeroed_hashtree:
- print ('{}: skipping verification since hashtree is zeroed and --accept_zeroed_hashtree was given'
- .format(self.partition_name))
- else:
- if hash_tree != hash_tree_ondisk:
- sys.stderr.write('hashtree of {} contains invalid data\n'.
- format(image_filename))
- return False
- print ('{}: Successfully verified {} hashtree of {} for image of {} bytes'
- .format(self.partition_name, self.hash_algorithm, image.filename,
- self.image_size))
+ if hash_tree != hash_tree_ondisk:
+ sys.stderr.write('hashtree of {} contains invalid data\n'.
+ format(image_filename))
+ return False
# TODO: we could also verify that the FEC stored in the image is
# 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'
+ .format(self.partition_name, self.hash_algorithm, image.filename,
+ self.image_size))
return True
@@ -1535,7 +1526,7 @@ class AvbHashDescriptor(AvbDescriptor):
return bytearray(ret)
def verify(self, image_dir, image_ext, expected_chain_partitions_map,
- image_containing_descriptor, accept_zeroed_hashtree):
+ image_containing_descriptor):
"""Verifies contents of the descriptor - used in verify_image sub-command.
Arguments:
@@ -1544,13 +1535,11 @@ class AvbHashDescriptor(AvbDescriptor):
expected_chain_partitions_map: A map from partition name to the
tuple (rollback_index_location, key_blob).
image_containing_descriptor: The image the descriptor is in.
- accept_zeroed_hashtree: If True, don't fail if hashtree or FEC data is zeroed out.
Returns:
True if the descriptor verifies, False otherwise.
"""
if self.partition_name == '':
- image_filename = image_containing_descriptor.filename
image = image_containing_descriptor
else:
image_filename = os.path.join(image_dir, self.partition_name + image_ext)
@@ -1647,7 +1636,7 @@ class AvbKernelCmdlineDescriptor(AvbDescriptor):
return bytearray(ret)
def verify(self, image_dir, image_ext, expected_chain_partitions_map,
- image_containing_descriptor, accept_zeroed_hashtree):
+ image_containing_descriptor):
"""Verifies contents of the descriptor - used in verify_image sub-command.
Arguments:
@@ -1656,7 +1645,6 @@ class AvbKernelCmdlineDescriptor(AvbDescriptor):
expected_chain_partitions_map: A map from partition name to the
tuple (rollback_index_location, key_blob).
image_containing_descriptor: The image the descriptor is in.
- accept_zeroed_hashtree: If True, don't fail if hashtree or FEC data is zeroed out.
Returns:
True if the descriptor verifies, False otherwise.
@@ -1751,7 +1739,7 @@ class AvbChainPartitionDescriptor(AvbDescriptor):
return bytearray(ret)
def verify(self, image_dir, image_ext, expected_chain_partitions_map,
- image_containing_descriptor, accept_zeroed_hashtree):
+ image_containing_descriptor):
"""Verifies contents of the descriptor - used in verify_image sub-command.
Arguments:
@@ -1760,7 +1748,6 @@ class AvbChainPartitionDescriptor(AvbDescriptor):
expected_chain_partitions_map: A map from partition name to the
tuple (rollback_index_location, key_blob).
image_containing_descriptor: The image the descriptor is in.
- accept_zeroed_hashtree: If True, don't fail if hashtree or FEC data is zeroed out.
Returns:
True if the descriptor verifies, False otherwise.
@@ -2099,63 +2086,6 @@ class Avb(object):
# And cut...
image.truncate(new_image_size)
- def zero_hashtree(self, image_filename):
- """Implements the 'zero_hashtree' command.
-
- Arguments:
- image_filename: File to zero hashtree and FEC data from.
-
- Raises:
- AvbError: If there's no footer in the image.
- """
-
- image = ImageHandler(image_filename)
-
- (footer, _, descriptors, _) = self._parse_image(image)
-
- if not footer:
- raise AvbError('Given image does not have a footer.')
-
- # Search for a hashtree descriptor to figure out the location and
- # size of the hashtree and FEC.
- ht_desc = None
- for desc in descriptors:
- if isinstance(desc, AvbHashtreeDescriptor):
- ht_desc = desc
- break
-
- if not ht_desc:
- raise AvbError('No hashtree descriptor was found.')
-
- zero_ht_start_offset = ht_desc.tree_offset
- zero_ht_num_bytes = ht_desc.tree_size
- zero_fec_start_offset = None
- zero_fec_num_bytes = 0
- if ht_desc.fec_offset > 0:
- if ht_desc.fec_offset != ht_desc.tree_offset + ht_desc.tree_size:
- raise AvbError('Hash-tree and FEC data must be adjacent.')
- zero_fec_start_offset = ht_desc.fec_offset
- zero_fec_num_bytes = ht_desc.fec_size
- zero_end_offset = zero_ht_start_offset + zero_ht_num_bytes + zero_fec_num_bytes
- image.seek(zero_end_offset)
- data = image.read(image.image_size - zero_end_offset)
-
- # Write zeroes all over hashtree and FEC, except for the first eight bytes
- # where a magic marker - ZeroHaSH - is placed. Place these markers in the
- # beginning of both hashtree and FEC. (That way, in the future we can add
- # options to 'avbtool zero_hashtree' so as to zero out only either/or.)
- #
- # Applications can use these markers to detect that the hashtree and/or
- # FEC needs to be recomputed.
- image.truncate(zero_ht_start_offset)
- data_zeroed_firstblock = 'ZeRoHaSH' + '\0'*(image.block_size - 8)
- image.append_raw(data_zeroed_firstblock)
- image.append_fill('\0\0\0\0', zero_ht_num_bytes - image.block_size)
- if zero_fec_start_offset:
- image.append_raw(data_zeroed_firstblock)
- image.append_fill('\0\0\0\0', zero_fec_num_bytes - image.block_size)
- image.append_raw(data)
-
def resize_image(self, image_filename, partition_size):
"""Implements the 'resize_image' command.
@@ -2290,8 +2220,7 @@ class Avb(object):
if num_printed == 0:
o.write(' (none)\n')
- def verify_image(self, image_filename, key_path, expected_chain_partitions, follow_chain_partitions,
- accept_zeroed_hashtree):
+ def verify_image(self, image_filename, key_path, expected_chain_partitions, follow_chain_partitions):
"""Implements the 'verify_image' command.
Arguments:
@@ -2300,7 +2229,6 @@ class Avb(object):
expected_chain_partitions: List of chain partitions to check or None.
follow_chain_partitions: If True, will follows chain partitions even when not
specified with the --expected_chain_partition option
- accept_zeroed_hashtree: If True, don't fail if hashtree or FEC data is zeroed out.
"""
expected_chain_partitions_map = {}
if expected_chain_partitions:
@@ -2366,14 +2294,13 @@ class Avb(object):
.format(desc.partition_name, desc.rollback_index_location,
hashlib.sha1(desc.public_key).hexdigest()))
else:
- if not desc.verify(image_dir, image_ext, expected_chain_partitions_map, image,
- accept_zeroed_hashtree):
+ if not desc.verify(image_dir, image_ext, expected_chain_partitions_map, image):
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 '--'
chained_image_filename = os.path.join(image_dir, desc.partition_name + image_ext)
- self.verify_image(chained_image_filename, key_path, None, False, accept_zeroed_hashtree)
+ self.verify_image(chained_image_filename, key_path, None, False)
def calculate_vbmeta_digest(self, image_filename, hash_algorithm, output):
@@ -3246,7 +3173,7 @@ class Avb(object):
release_string, append_to_release_string,
output_vbmeta_image, do_not_append_vbmeta_image,
print_required_libavb_version,
- use_persistent_root_digest, do_not_use_ab, no_hashtree):
+ use_persistent_root_digest, do_not_use_ab):
"""Implements the 'add_hashtree_footer' command.
See https://gitlab.com/cryptsetup/cryptsetup/wikis/DMVerity for
@@ -3288,7 +3215,6 @@ class Avb(object):
print_required_libavb_version: True to only print required libavb version.
use_persistent_root_digest: Use a persistent root digest on device.
do_not_use_ab: The partition does not use A/B.
- no_hashtree: Do not append hashtree. Set size in descriptor as zero.
Raises:
AvbError: If an argument is incorrect.
@@ -3311,13 +3237,11 @@ class Avb(object):
# vbmeta struct) fits in |partition_size|. We use very conservative figures
# for metadata.
if partition_size > 0:
- max_tree_size = 0
+ (_, max_tree_size) = calc_hash_level_offsets(
+ partition_size, block_size, digest_size + digest_padding)
max_fec_size = 0
- if not no_hashtree:
- (_, max_tree_size) = calc_hash_level_offsets(
- partition_size, block_size, digest_size + digest_padding)
- if generate_fec:
- max_fec_size = calc_fec_data_size(partition_size, fec_num_roots)
+ if generate_fec:
+ max_fec_size = calc_fec_data_size(partition_size, fec_num_roots)
max_metadata_size = (max_fec_size + max_tree_size +
self.MAX_VBMETA_SIZE +
self.MAX_FOOTER_SIZE)
@@ -3410,9 +3334,6 @@ class Avb(object):
# Generate HashtreeDescriptor with details about the tree we
# just generated.
- if no_hashtree:
- tree_size = 0
- hash_tree = bytearray()
ht_desc = AvbHashtreeDescriptor()
ht_desc.dm_verity_version = 1
ht_desc.image_size = image.image_size
@@ -3437,10 +3358,7 @@ class Avb(object):
# Generate FEC codes, if requested.
if generate_fec:
- if no_hashtree:
- fec_data = bytearray()
- else:
- fec_data = generate_fec_data(image_filename, fec_num_roots)
+ fec_data = generate_fec_data(image_filename, fec_num_roots)
padding_needed = (round_to_multiple(len(fec_data), image.block_size) -
len(fec_data))
fec_data_with_padding = fec_data + '\0'*padding_needed
@@ -3541,7 +3459,7 @@ class Avb(object):
hasher = hashlib.sha256()
hasher.update(usage)
signed_data.extend(hasher.digest())
- if subject_key_version is None:
+ if not subject_key_version:
subject_key_version = int(time.time())
signed_data.extend(struct.pack('<Q', subject_key_version))
signature = bytearray()
@@ -4093,9 +4011,6 @@ class AvbTool(object):
sub_parser.add_argument('--setup_as_rootfs_from_kernel',
action='store_true',
help='Adds kernel cmdline for setting up rootfs')
- sub_parser.add_argument('--no_hashtree',
- action='store_true',
- help='Do not append hashtree')
self._add_common_args(sub_parser)
self._add_common_footer_args(sub_parser)
sub_parser.set_defaults(func=self.add_hashtree_footer)
@@ -4111,14 +4026,6 @@ class AvbTool(object):
action='store_true')
sub_parser.set_defaults(func=self.erase_footer)
- sub_parser = subparsers.add_parser('zero_hashtree',
- help='Zero out hashtree and FEC data.')
- sub_parser.add_argument('--image',
- help='Image with a footer',
- type=argparse.FileType('rwb+'),
- required=True)
- sub_parser.set_defaults(func=self.zero_hashtree)
-
sub_parser = subparsers.add_parser('extract_vbmeta_image',
help='Extracts vbmeta from an image with a footer.')
sub_parser.add_argument('--image',
@@ -4179,9 +4086,6 @@ class AvbTool(object):
help=('Follows chain partitions even when not '
'specified with the --expected_chain_partition option'),
action='store_true')
- sub_parser.add_argument('--accept_zeroed_hashtree',
- help=('Accept images where the hashtree or FEC data is zeroed out'),
- action='store_true')
sub_parser.set_defaults(func=self.verify_image)
sub_parser = subparsers.add_parser(
@@ -4437,17 +4341,12 @@ class AvbTool(object):
args.do_not_append_vbmeta_image,
args.print_required_libavb_version,
args.use_persistent_digest,
- args.do_not_use_ab,
- args.no_hashtree)
+ args.do_not_use_ab)
def erase_footer(self, args):
"""Implements the 'erase_footer' sub-command."""
self.avb.erase_footer(args.image.name, args.keep_hashtree)
- def zero_hashtree(self, args):
- """Implements the 'zero_hashtree' sub-command."""
- self.avb.zero_hashtree(args.image.name)
-
def extract_vbmeta_image(self, args):
"""Implements the 'extract_vbmeta_image' sub-command."""
self.avb.extract_vbmeta_image(args.output, args.image.name,
@@ -4469,8 +4368,7 @@ class AvbTool(object):
"""Implements the 'verify_image' sub-command."""
self.avb.verify_image(args.image.name, args.key,
args.expected_chain_partition,
- args.follow_chain_partitions,
- args.accept_zeroed_hashtree)
+ args.follow_chain_partitions)
def calculate_vbmeta_digest(self, args):
"""Implements the 'calculate_vbmeta_digest' sub-command."""
diff --git a/libavb/avb_cmdline.c b/libavb/avb_cmdline.c
index f87e18c..bf10865 100644
--- a/libavb/avb_cmdline.c
+++ b/libavb/avb_cmdline.c
@@ -97,15 +97,7 @@ char* avb_sub_cmdline(AvbOps* ops,
}
}
- /* It's possible there is no _PARTUUID for replacement above.
- * Duplicate cmdline to ret for additional substitutions below.
- */
- if (ret == NULL) {
- ret = avb_strdup(cmdline);
- if (ret == NULL) {
- goto fail;
- }
- }
+ avb_assert(ret != NULL);
/* Replace any additional substitutions. */
if (additional_substitutions != NULL) {
@@ -233,7 +225,6 @@ static int cmdline_append_hex(AvbSlotVerifyData* slot_data,
AvbSlotVerifyResult avb_append_options(
AvbOps* ops,
- AvbSlotVerifyFlags flags,
AvbSlotVerifyData* slot_data,
AvbVBMetaImageHeader* toplevel_vbmeta,
AvbAlgorithmType algorithm_type,
@@ -244,16 +235,12 @@ AvbSlotVerifyResult avb_append_options(
bool is_device_unlocked;
AvbIOResult io_ret;
- /* Add androidboot.vbmeta.device option... except if not using a vbmeta
- * partition since it doesn't make sense in that case.
- */
- if (!(flags & AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION)) {
- if (!cmdline_append_option(slot_data,
- "androidboot.vbmeta.device",
- "PARTUUID=$(ANDROID_VBMETA_PARTUUID)")) {
- ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
- goto out;
- }
+ /* Add androidboot.vbmeta.device option. */
+ if (!cmdline_append_option(slot_data,
+ "androidboot.vbmeta.device",
+ "PARTUUID=$(ANDROID_VBMETA_PARTUUID)")) {
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
+ goto out;
}
/* Add androidboot.vbmeta.avb_version option. */
diff --git a/libavb/avb_cmdline.h b/libavb/avb_cmdline.h
index 377783f..e1f5b1b 100644
--- a/libavb/avb_cmdline.h
+++ b/libavb/avb_cmdline.h
@@ -62,7 +62,6 @@ char* avb_sub_cmdline(AvbOps* ops,
AvbSlotVerifyResult avb_append_options(
AvbOps* ops,
- AvbSlotVerifyFlags flags,
AvbSlotVerifyData* slot_data,
AvbVBMetaImageHeader* toplevel_vbmeta,
AvbAlgorithmType algorithm_type,
diff --git a/libavb/avb_descriptor.c b/libavb/avb_descriptor.c
index cfc2aac..4f8e925 100644
--- a/libavb/avb_descriptor.c
+++ b/libavb/avb_descriptor.c
@@ -91,11 +91,7 @@ bool avb_descriptor_foreach(const uint8_t* image_data,
const AvbDescriptor* dh = (const AvbDescriptor*)p;
avb_assert_aligned(dh);
uint64_t nb_following = avb_be64toh(dh->num_bytes_following);
- uint64_t nb_total = 0;
- if (!avb_safe_add(&nb_total, sizeof(AvbDescriptor), nb_following)) {
- avb_error("Invalid descriptor length.\n");
- goto out;
- }
+ uint64_t nb_total = sizeof(AvbDescriptor) + nb_following;
if ((nb_total & 7) != 0) {
avb_error("Invalid descriptor length.\n");
@@ -111,10 +107,7 @@ bool avb_descriptor_foreach(const uint8_t* image_data,
goto out;
}
- if (!avb_safe_add_to((uint64_t*)(&p), nb_total)) {
- avb_error("Invalid descriptor length.\n");
- goto out;
- }
+ p += nb_total;
}
ret = true;
diff --git a/libavb/avb_ops.h b/libavb/avb_ops.h
index dec163d..7f86386 100644
--- a/libavb/avb_ops.h
+++ b/libavb/avb_ops.h
@@ -191,10 +191,6 @@ struct AvbOps {
*
* If AVB_IO_RESULT_OK is returned then |out_is_trusted| is set -
* true if trusted or false if untrusted.
- *
- * NOTE: If AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION is passed to
- * avb_slot_verify() then this operation is never used. Instead, the
- * validate_public_key_for_partition() operation is used
*/
AvbIOResult (*validate_vbmeta_public_key)(AvbOps* ops,
const uint8_t* public_key_data,
@@ -312,25 +308,6 @@ struct AvbOps {
const char* name,
size_t value_size,
const uint8_t* value);
-
- /* Like validate_vbmeta_public_key() but for when the flag
- * AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION is being used. The name of the
- * partition to get the public key for is passed in |partition_name|.
- *
- * Also returns the rollback index location to use for the partition, in
- * |out_rollback_index_location|.
- *
- * Returns AVB_IO_RESULT_OK on success, otherwise an error code.
- */
- AvbIOResult (*validate_public_key_for_partition)(
- AvbOps* ops,
- const char* partition,
- const uint8_t* public_key_data,
- size_t public_key_length,
- const uint8_t* public_key_metadata,
- size_t public_key_metadata_length,
- bool* out_is_trusted,
- uint32_t* out_rollback_index_location);
};
#ifdef __cplusplus
diff --git a/libavb/avb_slot_verify.c b/libavb/avb_slot_verify.c
index 0d75210..75b26d6 100644
--- a/libavb/avb_slot_verify.c
+++ b/libavb/avb_slot_verify.c
@@ -385,27 +385,19 @@ static AvbSlotVerifyResult load_and_verify_hash_partition(
if (ret != AVB_SLOT_VERIFY_RESULT_OK) {
goto out;
}
- // Although only one of the type might be used, we have to defined the
- // structure here so that they would live outside the 'if/else' scope to be
- // used later.
- AvbSHA256Ctx sha256_ctx;
- AvbSHA512Ctx sha512_ctx;
- size_t image_size_to_hash = hash_desc.image_size;
- // If we allow verification error and the whole partition is smaller than
- // image size in hash descriptor, we just hash the whole partition.
- if (image_size_to_hash > image_size) {
- image_size_to_hash = image_size;
- }
+
if (avb_strcmp((const char*)hash_desc.hash_algorithm, "sha256") == 0) {
+ AvbSHA256Ctx sha256_ctx;
avb_sha256_init(&sha256_ctx);
avb_sha256_update(&sha256_ctx, desc_salt, hash_desc.salt_len);
- avb_sha256_update(&sha256_ctx, image_buf, image_size_to_hash);
+ avb_sha256_update(&sha256_ctx, image_buf, hash_desc.image_size);
digest = avb_sha256_final(&sha256_ctx);
digest_len = AVB_SHA256_DIGEST_SIZE;
} else if (avb_strcmp((const char*)hash_desc.hash_algorithm, "sha512") == 0) {
+ AvbSHA512Ctx sha512_ctx;
avb_sha512_init(&sha512_ctx);
avb_sha512_update(&sha512_ctx, desc_salt, hash_desc.salt_len);
- avb_sha512_update(&sha512_ctx, image_buf, image_size_to_hash);
+ avb_sha512_update(&sha512_ctx, image_buf, hash_desc.image_size);
digest = avb_sha512_final(&sha512_ctx);
digest_len = AVB_SHA512_DIGEST_SIZE;
} else {
@@ -558,7 +550,6 @@ static AvbSlotVerifyResult load_and_verify_vbmeta(
AvbOps* ops,
const char* const* requested_partitions,
const char* ab_suffix,
- AvbSlotVerifyFlags flags,
bool allow_verification_error,
AvbVBMetaImageFlags toplevel_vbmeta_flags,
int rollback_index_location,
@@ -572,7 +563,7 @@ static AvbSlotVerifyResult load_and_verify_vbmeta(
char full_partition_name[AVB_PART_NAME_MAX_SIZE];
AvbSlotVerifyResult ret;
AvbIOResult io_ret;
- uint64_t vbmeta_offset;
+ size_t vbmeta_offset;
size_t vbmeta_size;
uint8_t* vbmeta_buf = NULL;
size_t vbmeta_num_read;
@@ -585,7 +576,7 @@ static AvbSlotVerifyResult load_and_verify_vbmeta(
size_t num_descriptors;
size_t n;
bool is_main_vbmeta;
- bool look_for_vbmeta_footer;
+ bool is_vbmeta_partition;
AvbVBMetaData* vbmeta_image_data = NULL;
ret = AVB_SLOT_VERIFY_RESULT_OK;
@@ -596,20 +587,8 @@ static AvbSlotVerifyResult load_and_verify_vbmeta(
* rollback_index_location to determine whether we're the main
* vbmeta struct.
*/
- is_main_vbmeta = false;
- if (rollback_index_location == 0) {
- if ((flags & AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION) == 0) {
- is_main_vbmeta = true;
- }
- }
-
- /* Don't use footers for vbmeta partitions ('vbmeta' or
- * 'vbmeta_<partition_name>').
- */
- look_for_vbmeta_footer = true;
- if (avb_strncmp(partition_name, "vbmeta", avb_strlen("vbmeta")) == 0) {
- look_for_vbmeta_footer = false;
- }
+ is_main_vbmeta = (rollback_index_location == 0);
+ is_vbmeta_partition = (avb_strcmp(partition_name, "vbmeta") == 0);
if (!avb_validate_utf8((const uint8_t*)partition_name, partition_name_len)) {
avb_error("Partition name is not valid UTF-8.\n");
@@ -637,7 +616,7 @@ static AvbSlotVerifyResult load_and_verify_vbmeta(
*/
vbmeta_offset = 0;
vbmeta_size = VBMETA_MAX_SIZE;
- if (look_for_vbmeta_footer) {
+ if (!is_vbmeta_partition) {
uint8_t footer_buf[AVB_FOOTER_SIZE];
size_t footer_num_read;
AvbFooter footer;
@@ -705,14 +684,13 @@ static AvbSlotVerifyResult load_and_verify_vbmeta(
* go try to get it from the boot partition instead.
*/
if (is_main_vbmeta && io_ret == AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION &&
- !look_for_vbmeta_footer) {
+ is_vbmeta_partition) {
avb_debugv(full_partition_name,
": No such partition. Trying 'boot' instead.\n",
NULL);
ret = load_and_verify_vbmeta(ops,
requested_partitions,
ab_suffix,
- flags,
allow_verification_error,
0 /* toplevel_vbmeta_flags */,
0 /* rollback_index_location */,
@@ -790,8 +768,6 @@ static AvbSlotVerifyResult load_and_verify_vbmeta(
}
}
- uint32_t rollback_index_location_to_use = rollback_index_location;
-
/* Check if key used to make signature matches what is expected. */
if (pk_data != NULL) {
if (expected_public_key != NULL) {
@@ -819,27 +795,9 @@ static AvbSlotVerifyResult load_and_verify_vbmeta(
pk_metadata_len = vbmeta_header.public_key_metadata_size;
}
- // If we're not using a vbmeta partition, need to use another AvbOps...
- if (flags & AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION) {
- io_ret = ops->validate_public_key_for_partition(
- ops,
- full_partition_name,
- pk_data,
- pk_len,
- pk_metadata,
- pk_metadata_len,
- &key_is_trusted,
- &rollback_index_location_to_use);
- } else {
- avb_assert(is_main_vbmeta);
- io_ret = ops->validate_vbmeta_public_key(ops,
- pk_data,
- pk_len,
- pk_metadata,
- pk_metadata_len,
- &key_is_trusted);
- }
-
+ avb_assert(is_main_vbmeta);
+ io_ret = ops->validate_vbmeta_public_key(
+ ops, pk_data, pk_len, pk_metadata, pk_metadata_len, &key_is_trusted);
if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
goto out;
@@ -864,7 +822,7 @@ static AvbSlotVerifyResult load_and_verify_vbmeta(
/* Check rollback index. */
io_ret = ops->read_rollback_index(
- ops, rollback_index_location_to_use, &stored_rollback_index);
+ ops, rollback_index_location, &stored_rollback_index);
if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
goto out;
@@ -890,9 +848,7 @@ static AvbSlotVerifyResult load_and_verify_vbmeta(
if (is_main_vbmeta) {
avb_assert(slot_data->num_vbmeta_images == 0);
} else {
- if (!(flags & AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION)) {
- avb_assert(slot_data->num_vbmeta_images > 0);
- }
+ avb_assert(slot_data->num_vbmeta_images > 0);
}
if (slot_data->num_vbmeta_images == MAX_NUMBER_OF_VBMETA_IMAGES) {
avb_errorv(full_partition_name, ": Too many vbmeta images.\n", NULL);
@@ -1016,7 +972,6 @@ static AvbSlotVerifyResult load_and_verify_vbmeta(
load_and_verify_vbmeta(ops,
requested_partitions,
ab_suffix,
- flags,
allow_verification_error,
toplevel_vbmeta_flags,
chain_desc.rollback_index_location,
@@ -1205,8 +1160,7 @@ static AvbSlotVerifyResult load_and_verify_vbmeta(
}
}
- if (rollback_index_location < 0 ||
- rollback_index_location >= AVB_MAX_NUMBER_OF_ROLLBACK_INDEX_LOCATIONS) {
+ if (rollback_index_location >= AVB_MAX_NUMBER_OF_ROLLBACK_INDEX_LOCATIONS) {
avb_errorv(
full_partition_name, ": Invalid rollback_index_location.\n", NULL);
ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
@@ -1378,6 +1332,7 @@ AvbSlotVerifyResult avb_slot_verify(AvbOps* ops,
avb_assert(ops->read_is_device_unlocked != NULL);
avb_assert(ops->read_from_partition != NULL);
avb_assert(ops->get_size_of_partition != NULL);
+ avb_assert(ops->validate_vbmeta_public_key != NULL);
avb_assert(ops->read_rollback_index != NULL);
avb_assert(ops->get_unique_guid_for_partition != NULL);
@@ -1410,21 +1365,6 @@ AvbSlotVerifyResult avb_slot_verify(AvbOps* ops,
}
}
- /* Make sure passed-in AvbOps support verifying public keys and getting
- * rollback index location if not using a vbmeta partition.
- */
- if (flags & AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION) {
- if (ops->validate_public_key_for_partition == NULL) {
- avb_error(
- "AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION was passed but the "
- "validate_public_key_for_partition() operation isn't implemented.\n");
- ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT;
- goto fail;
- }
- } else {
- avb_assert(ops->validate_vbmeta_public_key != NULL);
- }
-
slot_data = avb_calloc(sizeof(AvbSlotVerifyData));
if (slot_data == NULL) {
ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
@@ -1449,161 +1389,122 @@ AvbSlotVerifyResult avb_slot_verify(AvbOps* ops,
goto fail;
}
- if (flags & AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION) {
- if (requested_partitions == NULL || requested_partitions[0] == NULL) {
- avb_fatal(
- "Requested partitions cannot be empty when using "
- "AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION");
- ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT;
- goto fail;
- }
-
- /* No vbmeta partition, go through each of the requested partitions... */
- for (size_t n = 0; requested_partitions[n] != NULL; n++) {
- ret = load_and_verify_vbmeta(ops,
- requested_partitions,
- ab_suffix,
- flags,
- allow_verification_error,
- 0 /* toplevel_vbmeta_flags */,
- 0 /* rollback_index_location */,
- requested_partitions[n],
- avb_strlen(requested_partitions[n]),
- NULL /* expected_public_key */,
- 0 /* expected_public_key_length */,
- slot_data,
- &algorithm_type,
- additional_cmdline_subst);
- if (!allow_verification_error && ret != AVB_SLOT_VERIFY_RESULT_OK) {
- goto fail;
- }
- }
-
- } else {
- /* Usual path, load "vbmeta"... */
- ret = load_and_verify_vbmeta(ops,
- requested_partitions,
- ab_suffix,
- flags,
- allow_verification_error,
- 0 /* toplevel_vbmeta_flags */,
- 0 /* rollback_index_location */,
- "vbmeta",
- avb_strlen("vbmeta"),
- NULL /* expected_public_key */,
- 0 /* expected_public_key_length */,
- slot_data,
- &algorithm_type,
- additional_cmdline_subst);
- if (!allow_verification_error && ret != AVB_SLOT_VERIFY_RESULT_OK) {
- goto fail;
- }
- }
-
- if (!result_should_continue(ret)) {
+ ret = load_and_verify_vbmeta(ops,
+ requested_partitions,
+ ab_suffix,
+ allow_verification_error,
+ 0 /* toplevel_vbmeta_flags */,
+ 0 /* rollback_index_location */,
+ "vbmeta",
+ avb_strlen("vbmeta"),
+ NULL /* expected_public_key */,
+ 0 /* expected_public_key_length */,
+ slot_data,
+ &algorithm_type,
+ additional_cmdline_subst);
+ if (!allow_verification_error && ret != AVB_SLOT_VERIFY_RESULT_OK) {
goto fail;
}
/* If things check out, mangle the kernel command-line as needed. */
- if (!(flags & AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION)) {
+ if (result_should_continue(ret)) {
if (avb_strcmp(slot_data->vbmeta_images[0].partition_name, "vbmeta") != 0) {
avb_assert(
avb_strcmp(slot_data->vbmeta_images[0].partition_name, "boot") == 0);
using_boot_for_vbmeta = true;
}
- }
-
- /* Byteswap top-level vbmeta header since we'll need it below. */
- avb_vbmeta_image_header_to_host_byte_order(
- (const AvbVBMetaImageHeader*)slot_data->vbmeta_images[0].vbmeta_data,
- &toplevel_vbmeta);
- /* Fill in |ab_suffix| field. */
- slot_data->ab_suffix = avb_strdup(ab_suffix);
- if (slot_data->ab_suffix == NULL) {
- ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
- goto fail;
- }
+ /* Byteswap top-level vbmeta header since we'll need it below. */
+ avb_vbmeta_image_header_to_host_byte_order(
+ (const AvbVBMetaImageHeader*)slot_data->vbmeta_images[0].vbmeta_data,
+ &toplevel_vbmeta);
- /* If verification is disabled, we are done ... we specifically
- * don't want to add any androidboot.* options since verification
- * is disabled.
- */
- if (toplevel_vbmeta.flags & AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED) {
- /* Since verification is disabled we didn't process any
- * descriptors and thus there's no cmdline... so set root= such
- * that the system partition is mounted.
- */
- avb_assert(slot_data->cmdline == NULL);
- // Devices with dynamic partitions won't have system partition.
- // Instead, it has a large super partition to accommodate *.img files.
- // See b/119551429 for details.
- if (has_system_partition(ops, ab_suffix)) {
- slot_data->cmdline =
- avb_strdup("root=PARTUUID=$(ANDROID_SYSTEM_PARTUUID)");
- } else {
- // The |cmdline| field should be a NUL-terminated string.
- slot_data->cmdline = avb_strdup("");
- }
- if (slot_data->cmdline == NULL) {
+ /* Fill in |ab_suffix| field. */
+ slot_data->ab_suffix = avb_strdup(ab_suffix);
+ if (slot_data->ab_suffix == NULL) {
ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
goto fail;
}
- } else {
- /* If requested, manage dm-verity mode... */
- AvbHashtreeErrorMode resolved_hashtree_error_mode = hashtree_error_mode;
- if (hashtree_error_mode ==
- AVB_HASHTREE_ERROR_MODE_MANAGED_RESTART_AND_EIO) {
- AvbIOResult io_ret;
- io_ret = avb_manage_hashtree_error_mode(
- ops, flags, slot_data, &resolved_hashtree_error_mode);
- if (io_ret != AVB_IO_RESULT_OK) {
- ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
- if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
- ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
- }
+
+ /* If verification is disabled, we are done ... we specifically
+ * don't want to add any androidboot.* options since verification
+ * is disabled.
+ */
+ if (toplevel_vbmeta.flags & AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED) {
+ /* Since verification is disabled we didn't process any
+ * descriptors and thus there's no cmdline... so set root= such
+ * that the system partition is mounted.
+ */
+ avb_assert(slot_data->cmdline == NULL);
+ // Devices with dynamic partitions won't have system partition.
+ // Instead, it has a large super partition to accommodate *.img files.
+ // See b/119551429 for details.
+ if (has_system_partition(ops, ab_suffix)) {
+ slot_data->cmdline =
+ avb_strdup("root=PARTUUID=$(ANDROID_SYSTEM_PARTUUID)");
+ } else {
+ // The |cmdline| field should be a NUL-terminated string.
+ slot_data->cmdline = avb_strdup("");
+ }
+ if (slot_data->cmdline == NULL) {
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
goto fail;
}
- }
- slot_data->resolved_hashtree_error_mode = resolved_hashtree_error_mode;
+ } else {
+ /* If requested, manage dm-verity mode... */
+ AvbHashtreeErrorMode resolved_hashtree_error_mode = hashtree_error_mode;
+ if (hashtree_error_mode ==
+ AVB_HASHTREE_ERROR_MODE_MANAGED_RESTART_AND_EIO) {
+ AvbIOResult io_ret;
+ io_ret = avb_manage_hashtree_error_mode(
+ ops, flags, slot_data, &resolved_hashtree_error_mode);
+ if (io_ret != AVB_IO_RESULT_OK) {
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
+ if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
+ }
+ goto fail;
+ }
+ }
+ slot_data->resolved_hashtree_error_mode = resolved_hashtree_error_mode;
- /* Add options... */
- AvbSlotVerifyResult sub_ret;
- sub_ret = avb_append_options(ops,
- flags,
- slot_data,
- &toplevel_vbmeta,
- algorithm_type,
- hashtree_error_mode,
- resolved_hashtree_error_mode);
- if (sub_ret != AVB_SLOT_VERIFY_RESULT_OK) {
- ret = sub_ret;
- goto fail;
+ /* Add options... */
+ AvbSlotVerifyResult sub_ret;
+ sub_ret = avb_append_options(ops,
+ slot_data,
+ &toplevel_vbmeta,
+ algorithm_type,
+ hashtree_error_mode,
+ resolved_hashtree_error_mode);
+ if (sub_ret != AVB_SLOT_VERIFY_RESULT_OK) {
+ ret = sub_ret;
+ goto fail;
+ }
}
- }
- /* Substitute $(ANDROID_SYSTEM_PARTUUID) and friends. */
- if (slot_data->cmdline != NULL && avb_strlen(slot_data->cmdline) != 0) {
- char* new_cmdline;
- new_cmdline = avb_sub_cmdline(ops,
- slot_data->cmdline,
- ab_suffix,
- using_boot_for_vbmeta,
- additional_cmdline_subst);
- if (new_cmdline != slot_data->cmdline) {
- if (new_cmdline == NULL) {
- ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
- goto fail;
+ /* Substitute $(ANDROID_SYSTEM_PARTUUID) and friends. */
+ if (slot_data->cmdline != NULL && avb_strlen(slot_data->cmdline) != 0) {
+ char* new_cmdline;
+ new_cmdline = avb_sub_cmdline(ops,
+ slot_data->cmdline,
+ ab_suffix,
+ using_boot_for_vbmeta,
+ additional_cmdline_subst);
+ if (new_cmdline != slot_data->cmdline) {
+ if (new_cmdline == NULL) {
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
+ goto fail;
+ }
+ avb_free(slot_data->cmdline);
+ slot_data->cmdline = new_cmdline;
}
- avb_free(slot_data->cmdline);
- slot_data->cmdline = new_cmdline;
}
- }
- if (out_data != NULL) {
- *out_data = slot_data;
- } else {
- avb_slot_verify_data_free(slot_data);
+ if (out_data != NULL) {
+ *out_data = slot_data;
+ } else {
+ avb_slot_verify_data_free(slot_data);
+ }
}
avb_free_cmdline_subst_list(additional_cmdline_subst);
diff --git a/libavb/avb_slot_verify.h b/libavb/avb_slot_verify.h
index a2c98f4..d42d64c 100644
--- a/libavb/avb_slot_verify.h
+++ b/libavb/avb_slot_verify.h
@@ -117,21 +117,11 @@ typedef enum {
* should be set if using AVB_HASHTREE_ERROR_MODE_MANAGED_RESTART_AND_EIO
* and the reason the boot loader is running is because the device
* was restarted by the dm-verity driver.
- *
- * If the AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION flag is set then
- * data won't be loaded from the "vbmeta" partition and the
- * |validate_vbmeta_public_key| operation is never called. Instead, the
- * vbmeta structs in |requested_partitions| are loaded and processed and the
- * |validate_public_key_for_partition| operation is called for each of these
- * vbmeta structs. This flag is useful when booting into recovery on a device
- * not using A/B - see section "Booting into recovery" in README.md for
- * more information.
*/
typedef enum {
AVB_SLOT_VERIFY_FLAGS_NONE = 0,
AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR = (1 << 0),
- AVB_SLOT_VERIFY_FLAGS_RESTART_CAUSED_BY_HASHTREE_CORRUPTION = (1 << 1),
- AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION = (1 << 2),
+ AVB_SLOT_VERIFY_FLAGS_RESTART_CAUSED_BY_HASHTREE_CORRUPTION = (1 << 1)
} AvbSlotVerifyFlags;
/* Get a textual representation of |result|. */
@@ -255,9 +245,7 @@ typedef struct {
* PARTUUID=$(ANDROID_VBMETA_PARTUUID) before substitution so it
* will end up pointing to the vbmeta partition for the verified
* slot. If there is no vbmeta partition it will point to the boot
- * partition of the verified slot. If the flag
- * AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION is used, this is not
- * set.
+ * partition of the verified slot.
*
* androidboot.vbmeta.avb_version: This is set to the decimal value
* of AVB_VERSION_MAJOR followed by a dot followed by the decimal
diff --git a/libavb/avb_sysdeps.h b/libavb/avb_sysdeps.h
index e511a8a..e1f2ebc 100644
--- a/libavb/avb_sysdeps.h
+++ b/libavb/avb_sysdeps.h
@@ -75,14 +75,6 @@ int avb_memcmp(const void* src1,
*/
int avb_strcmp(const char* s1, const char* s2);
-/* Compare |n| bytes in two strings.
- *
- * Return an integer less than, equal to, or greater than zero if the
- * first |n| bytes of |s1| is found, respectively, to be less than,
- * to match, or be greater than the first |n| bytes of |s2|.
- */
-int avb_strncmp(const char* s1, const char* s2, size_t n);
-
/* Copy |n| bytes from |src| to |dest|. */
void* avb_memcpy(void* dest, const void* src, size_t n);
diff --git a/libavb/avb_sysdeps_posix.c b/libavb/avb_sysdeps_posix.c
index e26c3ef..0cbabee 100644
--- a/libavb/avb_sysdeps_posix.c
+++ b/libavb/avb_sysdeps_posix.c
@@ -46,10 +46,6 @@ int avb_strcmp(const char* s1, const char* s2) {
return strcmp(s1, s2);
}
-int avb_strncmp(const char* s1, const char* s2, size_t n) {
- return strncmp(s1, s2, n);
-}
-
size_t avb_strlen(const char* str) {
return strlen(str);
}
diff --git a/test/Android.bp b/test/Android.bp
index 057cd1e..e3c2f31 100644
--- a/test/Android.bp
+++ b/test/Android.bp
@@ -39,4 +39,5 @@ python_test_host {
},
},
test_config: "at_auth_unlock_unittest.xml",
+ test_suites: ["general-tests"],
}
diff --git a/test/avb_slot_verify_unittest.cc b/test/avb_slot_verify_unittest.cc
index 28ec151..e03c37e 100644
--- a/test/avb_slot_verify_unittest.cc
+++ b/test/avb_slot_verify_unittest.cc
@@ -478,74 +478,6 @@ TEST_F(AvbSlotVerifyTest, LoadEntirePartitionIfAllowingVerificationError) {
avb_slot_verify_data_free(slot_data);
}
-TEST_F(AvbSlotVerifyTest, LoadSmallerPartitionIfAllowingVerificationError) {
- const size_t boot_partition_size = 16 * 1024 * 1024;
- const size_t boot_image_size = 5 * 1024 * 1024;
- const size_t new_boot_image_size = 1 * 1024 * 1024;
- base::FilePath boot_path = GenerateImage("boot_a.img", boot_image_size);
-
- // If we're allowing verification errors then check that the whole
- // partition is loaded. This is needed because in this mode for
- // example the "boot" partition might be flashed with another
- // boot.img that is larger than what the HashDescriptor in vbmeta
- // says.
- EXPECT_COMMAND(
- 0,
- "./avbtool add_hash_footer"
- " --image %s"
- " --rollback_index 0"
- " --partition_name boot"
- " --partition_size %zd"
- " --kernel_cmdline 'cmdline in hash footer $(ANDROID_SYSTEM_PARTUUID)'"
- " --salt deadbeef"
- " --internal_release_string \"\"",
- boot_path.value().c_str(),
- boot_partition_size);
-
- GenerateVBMetaImage(
- "vbmeta_a.img",
- "SHA256_RSA2048",
- 4,
- base::FilePath("test/data/testkey_rsa2048.pem"),
- base::StringPrintf(
- "--include_descriptors_from_image %s"
- " --kernel_cmdline 'cmdline in vbmeta $(ANDROID_BOOT_PARTUUID)'"
- " --internal_release_string \"\"",
- boot_path.value().c_str()));
-
- // Now replace the boot partition with something bigger and
- // different. Because FakeOps's get_size_of_partition() operation
- // just returns the file size it means that this is what is returned
- // by get_size_of_partition().
- //
- // Also make sure this image will return a different digest by using
- // a non-standard starting byte. This is to force avb_slot_verify()
- // to return ERROR_VERIFICATION below.
- GenerateImage("boot_a.img", new_boot_image_size, 1 /* start_byte */);
-
- ops_.set_expected_public_key(
- PublicKeyAVB(base::FilePath("test/data/testkey_rsa2048.pem")));
-
- AvbSlotVerifyData* slot_data = NULL;
- const char* requested_partitions[] = {"boot", NULL};
- EXPECT_EQ(AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION,
- avb_slot_verify(ops_.avb_ops(),
- requested_partitions,
- "_a",
- AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR,
- AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE,
- &slot_data));
- EXPECT_NE(nullptr, slot_data);
-
- // Check that the loaded partition is actually
- // |new_boot_image_size|.
- EXPECT_EQ(size_t(1), slot_data->num_loaded_partitions);
- EXPECT_EQ("boot",
- std::string(slot_data->loaded_partitions[0].partition_name));
- EXPECT_EQ(new_boot_image_size, slot_data->loaded_partitions[0].data_size);
- avb_slot_verify_data_free(slot_data);
-}
-
TEST_F(AvbSlotVerifyTest, HashDescriptorInVBMeta) {
const size_t boot_partition_size = 16 * 1024 * 1024;
const size_t boot_image_size = 5 * 1024 * 1024;
@@ -1728,115 +1660,6 @@ TEST_F(AvbSlotVerifyTest, OnlyLoadWhatHasBeenRequested) {
EXPECT_TRUE(partitions.find("bar_a") == partitions.end());
}
-TEST_F(AvbSlotVerifyTest, NoVBMetaPartitionFlag) {
- const size_t foo_partition_size = 16 * 1024 * 1024;
- const size_t bar_partition_size = 32 * 1024 * 1024;
- const size_t foo_image_size = 5 * 1024 * 1024;
- const size_t bar_image_size = 10 * 1024 * 1024;
- base::FilePath foo_path = GenerateImage("foo_a.img", foo_image_size);
- base::FilePath bar_path = GenerateImage("bar_a.img", bar_image_size);
-
- EXPECT_COMMAND(0,
- "./avbtool add_hash_footer"
- " --image %s"
- " --kernel_cmdline 'this is=5 from foo=42'"
- " --partition_name foo"
- " --partition_size %zd"
- " --salt deadbeef"
- " --internal_release_string \"\""
- " --algorithm SHA256_RSA4096"
- " --salt deadbeef"
- " --key test/data/testkey_rsa4096.pem"
- " --rollback_index 42",
- foo_path.value().c_str(),
- foo_partition_size);
-
- EXPECT_COMMAND(0,
- "./avbtool add_hash_footer"
- " --image %s"
- " --kernel_cmdline 'and=43 from bar'"
- " --partition_name bar"
- " --partition_size %zd"
- " --salt deadbeef"
- " --internal_release_string \"\""
- " --algorithm SHA256_RSA2048"
- " --salt deadbeef"
- " --key test/data/testkey_rsa2048.pem"
- " --rollback_index 43",
- bar_path.value().c_str(),
- bar_partition_size);
-
- ops_.set_expected_public_key_for_partition(
- "foo_a",
- PublicKeyAVB(base::FilePath("test/data/testkey_rsa4096.pem")),
- 1);
- ops_.set_expected_public_key_for_partition(
- "bar_a",
- PublicKeyAVB(base::FilePath("test/data/testkey_rsa2048.pem")),
- 2);
- ops_.set_stored_rollback_indexes({{0, 1000}, {1, 10}, {2, 11}});
- AvbSlotVerifyData* slot_data = NULL;
- const char* requested_partitions[] = {"foo", "bar", NULL};
-
- // Without AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION, this should fail because
- // vbmeta_a (or boot_a) cannot not be found.
- EXPECT_EQ(AVB_SLOT_VERIFY_RESULT_ERROR_IO,
- avb_slot_verify(ops_.avb_ops(),
- requested_partitions,
- "_a",
- AVB_SLOT_VERIFY_FLAGS_NONE,
- AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE,
- &slot_data));
-
- // However, with this flag it should succeed (note that rollback indexes in
- // the images exceed the stored rollback indexes)
- EXPECT_EQ(AVB_SLOT_VERIFY_RESULT_OK,
- avb_slot_verify(ops_.avb_ops(),
- requested_partitions,
- "_a",
- AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION,
- AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE,
- &slot_data));
- EXPECT_NE(nullptr, slot_data);
- EXPECT_EQ(size_t(2), slot_data->num_loaded_partitions);
- EXPECT_EQ("foo", std::string(slot_data->loaded_partitions[0].partition_name));
- EXPECT_EQ("bar", std::string(slot_data->loaded_partitions[1].partition_name));
- // Note the absence of 'androidboot.vbmeta.device'
- EXPECT_EQ(
- "this is=5 from foo=42 and=43 from bar "
- "androidboot.vbmeta.avb_version=1.1 "
- "androidboot.vbmeta.device_state=locked "
- "androidboot.vbmeta.hash_alg=sha256 "
- "androidboot.vbmeta.size=3456 "
- "androidboot.vbmeta.digest="
- "b5dbfb1743073f9a4cb45f94d1d849f89ca9777d158a2a06d09517c79ffd86cd "
- "androidboot.vbmeta.invalidate_on_error=yes "
- "androidboot.veritymode=enforcing",
- std::string(slot_data->cmdline));
- avb_slot_verify_data_free(slot_data);
-
- // Check that rollback protection works if we increase the stored rollback
- // indexes to exceed that of the image... do a check for each location.
- ops_.set_stored_rollback_indexes({{0, 1000}, {1, 10}, {2, 100}});
- EXPECT_EQ(AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX,
- avb_slot_verify(ops_.avb_ops(),
- requested_partitions,
- "_a",
- AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION,
- AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE,
- &slot_data));
- EXPECT_EQ(nullptr, slot_data);
- ops_.set_stored_rollback_indexes({{0, 1000}, {1, 100}, {2, 10}});
- EXPECT_EQ(AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX,
- avb_slot_verify(ops_.avb_ops(),
- requested_partitions,
- "_a",
- AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION,
- AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE,
- &slot_data));
- EXPECT_EQ(nullptr, slot_data);
-}
-
TEST_F(AvbSlotVerifyTest, PublicKeyMetadata) {
base::FilePath md_path = GenerateImage("md.bin", 1536);
diff --git a/test/avb_sysdeps_posix_testing.cc b/test/avb_sysdeps_posix_testing.cc
index 0a6ac13..ee1cb97 100644
--- a/test/avb_sysdeps_posix_testing.cc
+++ b/test/avb_sysdeps_posix_testing.cc
@@ -50,10 +50,6 @@ int avb_strcmp(const char* s1, const char* s2) {
return strcmp(s1, s2);
}
-int avb_strncmp(const char* s1, const char* s2, size_t n) {
- return strncmp(s1, s2, n);
-}
-
size_t avb_strlen(const char* str) {
return strlen(str);
}
diff --git a/test/avbtool_unittest.cc b/test/avbtool_unittest.cc
index 42f6f4d..1dfdf86 100644
--- a/test/avbtool_unittest.cc
+++ b/test/avbtool_unittest.cc
@@ -1003,15 +1003,6 @@ void AvbToolTest::AddHashtreeFooterTest(bool sparse_image) {
extracted_vbmeta_path.value().c_str());
}
- /* Zero the hashtree on a copy of the image. */
- EXPECT_COMMAND(0,
- "cp %s %s.zht",
- rootfs_path.value().c_str(),
- rootfs_path.value().c_str());
- EXPECT_COMMAND(0,
- "./avbtool zero_hashtree --image %s.zht ",
- rootfs_path.value().c_str());
-
if (sparse_image) {
EXPECT_COMMAND(0,
"mv %s %s.sparse",
@@ -1022,16 +1013,6 @@ void AvbToolTest::AddHashtreeFooterTest(bool sparse_image) {
rootfs_path.value().c_str(),
rootfs_path.value().c_str());
EXPECT_COMMAND(0, "rm -f %s.sparse", rootfs_path.value().c_str());
-
- EXPECT_COMMAND(0,
- "mv %s.zht %s.zht.sparse",
- rootfs_path.value().c_str(),
- rootfs_path.value().c_str());
- EXPECT_COMMAND(0,
- "simg2img %s.zht.sparse %s.zht",
- rootfs_path.value().c_str(),
- rootfs_path.value().c_str());
- EXPECT_COMMAND(0, "rm -f %s.zht.sparse", rootfs_path.value().c_str());
}
// To check that we generate the correct hashtree we can use
@@ -1057,11 +1038,6 @@ void AvbToolTest::AddHashtreeFooterTest(bool sparse_image) {
std::string part_data;
ASSERT_TRUE(base::ReadFileToString(rootfs_path, &part_data));
- // Also read the zeroed hash-tree version.
- std::string zht_part_data;
- ASSERT_TRUE(base::ReadFileToString(
- base::FilePath(rootfs_path.value() + ".zht"), &zht_part_data));
-
// Check footer contains correct data.
AvbFooter f;
EXPECT_NE(0,
@@ -1119,33 +1095,6 @@ void AvbToolTest::AddHashtreeFooterTest(bool sparse_image) {
EXPECT_EQ("e811611467dcd6e8dc4324e45f706c2bdd51db67",
mem_to_hexstring(desc_end + o, d.root_digest_len));
- // Check that the zeroed hashtree version differ only by the hashtree + fec
- // being zeroed out.
- EXPECT_EQ(part_data.size(), zht_part_data.size());
- size_t zht_ht_begin = d.tree_offset;
- size_t zht_ht_end = zht_ht_begin + d.tree_size;
- size_t zht_fec_begin = zht_ht_end;
- size_t zht_fec_end = zht_fec_begin + d.fec_size;
- EXPECT_EQ(0, memcmp(part_data.data(), zht_part_data.data(), zht_ht_begin));
- EXPECT_NE(0,
- memcmp(part_data.data() + zht_ht_begin,
- zht_part_data.data() + zht_ht_begin,
- zht_fec_end - zht_ht_begin));
- EXPECT_EQ(0,
- memcmp(part_data.data() + zht_fec_end,
- zht_part_data.data() + zht_fec_end,
- zht_part_data.size() - zht_fec_end));
- EXPECT_EQ(0, strncmp(zht_part_data.data() + zht_ht_begin, "ZeRoHaSH", 8));
- for (size_t n = zht_ht_begin + 8; n < zht_ht_end; n++) {
- EXPECT_EQ(0, zht_part_data.data()[n]);
- }
- if (d.fec_size > 0) {
- EXPECT_EQ(0, strncmp(zht_part_data.data() + zht_fec_begin, "ZeRoHaSH", 8));
- for (size_t n = zht_fec_begin + 8; n < zht_fec_end; n++) {
- EXPECT_EQ(0, zht_part_data.data()[n]);
- }
- }
-
// Check that we correctly generate dm-verity kernel cmdline
// snippets, if requested.
base::FilePath vbmeta_dmv_path = testdir_.Append("vbmeta_dm_verity_desc.bin");
@@ -1298,15 +1247,6 @@ void AvbToolTest::AddHashtreeFooterFECTest(bool sparse_image) {
InfoImage(rootfs_path));
}
- /* Zero the hashtree and FEC on a copy of the image. */
- EXPECT_COMMAND(0,
- "cp %s %s.zht",
- rootfs_path.value().c_str(),
- rootfs_path.value().c_str());
- EXPECT_COMMAND(0,
- "./avbtool zero_hashtree --image %s.zht ",
- rootfs_path.value().c_str());
-
if (sparse_image) {
EXPECT_COMMAND(0,
"mv %s %s.sparse",
@@ -1317,16 +1257,6 @@ void AvbToolTest::AddHashtreeFooterFECTest(bool sparse_image) {
rootfs_path.value().c_str(),
rootfs_path.value().c_str());
EXPECT_COMMAND(0, "rm -f %s.sparse", rootfs_path.value().c_str());
-
- EXPECT_COMMAND(0,
- "mv %s.zht %s.zht.sparse",
- rootfs_path.value().c_str(),
- rootfs_path.value().c_str());
- EXPECT_COMMAND(0,
- "simg2img %s.zht.sparse %s.zht",
- rootfs_path.value().c_str(),
- rootfs_path.value().c_str());
- EXPECT_COMMAND(0, "rm -f %s.zht.sparse", rootfs_path.value().c_str());
}
/* TODO: would be nice to verify that the FEC data is correct. */
@@ -1335,11 +1265,6 @@ void AvbToolTest::AddHashtreeFooterFECTest(bool sparse_image) {
std::string part_data;
ASSERT_TRUE(base::ReadFileToString(rootfs_path, &part_data));
- // Also read the zeroed hash-tree version.
- std::string zht_part_data;
- ASSERT_TRUE(base::ReadFileToString(
- base::FilePath(rootfs_path.value() + ".zht"), &zht_part_data));
-
// Check footer contains correct data.
AvbFooter f;
EXPECT_NE(0,
@@ -1399,33 +1324,6 @@ void AvbToolTest::AddHashtreeFooterFECTest(bool sparse_image) {
EXPECT_EQ("e811611467dcd6e8dc4324e45f706c2bdd51db67",
mem_to_hexstring(desc_end + o, d.root_digest_len));
- // Check that the zeroed hashtree version differ only by the hashtree + fec
- // being zeroed out.
- EXPECT_EQ(part_data.size(), zht_part_data.size());
- size_t zht_ht_begin = d.tree_offset;
- size_t zht_ht_end = zht_ht_begin + d.tree_size;
- size_t zht_fec_begin = zht_ht_end;
- size_t zht_fec_end = zht_fec_begin + d.fec_size;
- EXPECT_EQ(0, memcmp(part_data.data(), zht_part_data.data(), zht_ht_begin));
- EXPECT_NE(0,
- memcmp(part_data.data() + zht_ht_begin,
- zht_part_data.data() + zht_ht_begin,
- zht_fec_end - zht_ht_begin));
- EXPECT_EQ(0,
- memcmp(part_data.data() + zht_fec_end,
- zht_part_data.data() + zht_fec_end,
- zht_part_data.size() - zht_fec_end));
- EXPECT_EQ(0, strncmp(zht_part_data.data() + zht_ht_begin, "ZeRoHaSH", 8));
- for (size_t n = zht_ht_begin + 8; n < zht_ht_end; n++) {
- EXPECT_EQ(0, zht_part_data.data()[n]);
- }
- if (d.fec_size > 0) {
- EXPECT_EQ(0, strncmp(zht_part_data.data() + zht_fec_begin, "ZeRoHaSH", 8));
- for (size_t n = zht_fec_begin + 8; n < zht_fec_end; n++) {
- EXPECT_EQ(0, zht_part_data.data()[n]);
- }
- }
-
// Check that we correctly generate dm-verity kernel cmdline
// snippets, if requested.
base::FilePath vbmeta_dmv_path = testdir_.Append("vbmeta_dm_verity_desc.bin");
@@ -1553,74 +1451,6 @@ TEST_F(AvbToolTest, AddHashtreeFooterCalcMaxImageSizeWithFEC) {
partition_size);
}
-TEST_F(AvbToolTest, AddHashtreeFooterCalcMaxImageSizeWithNoHashtree) {
- const size_t partition_size = 10 * 1024 * 1024;
- base::FilePath output_path = testdir_.Append("max_size.txt");
-
- EXPECT_COMMAND(0,
- "./avbtool add_hashtree_footer "
- "--no_hashtree "
- "--partition_size %zd --calc_max_image_size > %s",
- partition_size,
- output_path.value().c_str());
- std::string max_image_size_data;
- EXPECT_TRUE(base::ReadFileToString(output_path, &max_image_size_data));
- EXPECT_EQ("10416128\n", max_image_size_data);
- size_t max_image_size = atoll(max_image_size_data.c_str());
-
- // vbmeta(64) + footer(4) takes up 68 KiB
- EXPECT_EQ(68 * 1024ULL, partition_size - max_image_size);
-
- // Check that we can add a hashtree with an image this size for such
- // a partition size.
- base::FilePath system_path = GenerateImage("system", max_image_size);
- EXPECT_COMMAND(0,
- "./avbtool add_hashtree_footer"
- " --image %s"
- " --no_hashtree"
- " --partition_name system"
- " --partition_size %zd"
- " --salt deadbeef"
- " --algorithm SHA512_RSA4096 "
- " --key test/data/testkey_rsa4096.pem"
- " --internal_release_string \"\"",
- system_path.value().c_str(),
- partition_size);
- // with --no_hashtree, Tree/FEC sizes are 0 bytes
- ASSERT_EQ(
- "Footer version: 1.0\n"
- "Image size: 10485760 bytes\n"
- "Original image size: 10416128 bytes\n"
- "VBMeta offset: 10416128\n"
- "VBMeta size: 2112 bytes\n"
- "--\n"
- "Minimum libavb version: 1.0\n"
- "Header Block: 256 bytes\n"
- "Authentication Block: 576 bytes\n"
- "Auxiliary Block: 1280 bytes\n"
- "Algorithm: SHA512_RSA4096\n"
- "Rollback Index: 0\n"
- "Flags: 0\n"
- "Release String: ''\n"
- "Descriptors:\n"
- " Hashtree descriptor:\n"
- " Version of dm-verity: 1\n"
- " Image Size: 10416128 bytes\n"
- " Tree Offset: 10416128\n"
- " Tree Size: 0 bytes\n"
- " Data Block Size: 4096 bytes\n"
- " Hash Block Size: 4096 bytes\n"
- " FEC num roots: 2\n"
- " FEC offset: 10416128\n"
- " FEC size: 0 bytes\n"
- " Hash Algorithm: sha1\n"
- " Partition Name: system\n"
- " Salt: deadbeef\n"
- " Root Digest: 4215bd42bcc99636f42956ce3d2c7884d6a8093b\n"
- " Flags: 0\n",
- InfoImage(system_path));
-}
-
TEST_F(AvbToolTest, AddHashtreeFooterWithPersistentDigest) {
size_t partition_size = 10 * 1024 * 1024;
base::FilePath path = GenerateImage("digest_location", partition_size / 2);
@@ -2562,68 +2392,6 @@ TEST_F(AvbToolTest, VerifyImageWithHashAndHashtree) {
}
}
-TEST_F(AvbToolTest, VerifyImageWithHashAndZeroedHashtree) {
- const size_t system_partition_size = 10 * 1024 * 1024;
- const size_t system_image_size = 8 * 1024 * 1024;
- base::FilePath system_path = GenerateImage("system.img", system_image_size);
- EXPECT_COMMAND(0,
- "./avbtool add_hashtree_footer --salt d00df00d --image %s "
- "--partition_size %zd --partition_name system "
- "--internal_release_string \"\" ",
- system_path.value().c_str(),
- system_partition_size);
-
- GenerateVBMetaImage("vbmeta.img",
- "SHA256_RSA2048",
- 0,
- base::FilePath("test/data/testkey_rsa2048.pem"),
- base::StringPrintf("--include_descriptors_from_image %s ",
- system_path.value().c_str()));
-
- EXPECT_COMMAND(0,
- "./avbtool verify_image --image %s --accept_zeroed_hashtree",
- vbmeta_image_path_.value().c_str());
-
- EXPECT_COMMAND(
- 0, "./avbtool zero_hashtree --image %s", system_path.value().c_str());
-
- EXPECT_COMMAND(1,
- "./avbtool verify_image --image %s",
- vbmeta_image_path_.value().c_str());
-
- EXPECT_COMMAND(0,
- "./avbtool verify_image --image %s --accept_zeroed_hashtree",
- vbmeta_image_path_.value().c_str());
-}
-
-TEST_F(AvbToolTest, VerifyImageWithNoHashtree) {
- const size_t system_partition_size = 10 * 1024 * 1024;
- const size_t system_image_size = 8 * 1024 * 1024;
- base::FilePath system_path = GenerateImage("system.img", system_image_size);
- EXPECT_COMMAND(0,
- "./avbtool add_hashtree_footer --salt d00df00d --image %s "
- "--partition_size %zd --partition_name system "
- "--no_hashtree "
- "--internal_release_string \"\" ",
- system_path.value().c_str(),
- system_partition_size);
-
- GenerateVBMetaImage("vbmeta.img",
- "SHA256_RSA2048",
- 0,
- base::FilePath("test/data/testkey_rsa2048.pem"),
- base::StringPrintf("--include_descriptors_from_image %s ",
- system_path.value().c_str()));
-
- EXPECT_COMMAND(1,
- "./avbtool verify_image --image %s",
- vbmeta_image_path_.value().c_str());
-
- EXPECT_COMMAND(0,
- "./avbtool verify_image --image %s --accept_zeroed_hashtree",
- vbmeta_image_path_.value().c_str());
-}
-
TEST_F(AvbToolTest, VerifyImageWithHashAndHashtreeCorruptHash) {
GenerateImageWithHashAndHashtreeSetup();
diff --git a/test/fake_avb_ops.cc b/test/fake_avb_ops.cc
index 6e8ab8c..2fdba10 100644
--- a/test/fake_avb_ops.cc
+++ b/test/fake_avb_ops.cc
@@ -262,30 +262,6 @@ AvbIOResult FakeAvbOps::validate_vbmeta_public_key(
return AVB_IO_RESULT_OK;
}
-AvbIOResult FakeAvbOps::validate_public_key_for_partition(
- AvbOps* ops,
- const char* partition,
- const uint8_t* public_key_data,
- size_t public_key_length,
- const uint8_t* public_key_metadata,
- size_t public_key_metadata_length,
- bool* out_key_is_trusted,
- uint32_t* out_rollback_index_location) {
- std::string expected_public_key =
- expected_public_key_for_partition_map_[partition];
- uint32_t rollback_index_location =
- rollback_index_location_for_partition_map_[partition];
- if (out_key_is_trusted != NULL) {
- bool pk_matches = (public_key_length == expected_public_key.size() &&
- (memcmp(expected_public_key.c_str(),
- public_key_data,
- public_key_length) == 0));
- *out_key_is_trusted = pk_matches;
- *out_rollback_index_location = rollback_index_location;
- }
- return AVB_IO_RESULT_OK;
-}
-
AvbIOResult FakeAvbOps::read_rollback_index(AvbOps* ops,
size_t rollback_index_location,
uint64_t* out_rollback_index) {
@@ -460,27 +436,6 @@ static AvbIOResult my_ops_validate_vbmeta_public_key(
out_key_is_trusted);
}
-static AvbIOResult my_ops_validate_public_key_for_partition(
- AvbOps* ops,
- const char* partition,
- const uint8_t* public_key_data,
- size_t public_key_length,
- const uint8_t* public_key_metadata,
- size_t public_key_metadata_length,
- bool* out_key_is_trusted,
- uint32_t* out_rollback_index_location) {
- return FakeAvbOps::GetInstanceFromAvbOps(ops)
- ->delegate()
- ->validate_public_key_for_partition(ops,
- partition,
- public_key_data,
- public_key_length,
- public_key_metadata,
- public_key_metadata_length,
- out_key_is_trusted,
- out_rollback_index_location);
-}
-
static AvbIOResult my_ops_read_rollback_index(AvbOps* ops,
size_t rollback_index_location,
uint64_t* out_rollback_index) {
@@ -586,8 +541,6 @@ FakeAvbOps::FakeAvbOps() {
avb_ops_.get_size_of_partition = my_ops_get_size_of_partition;
avb_ops_.read_persistent_value = my_ops_read_persistent_value;
avb_ops_.write_persistent_value = my_ops_write_persistent_value;
- avb_ops_.validate_public_key_for_partition =
- my_ops_validate_public_key_for_partition;
// Just use the built-in A/B metadata read/write routines.
avb_ab_ops_.ops = &avb_ops_;
diff --git a/test/fake_avb_ops.h b/test/fake_avb_ops.h
index 2cc12d8..935dbf4 100644
--- a/test/fake_avb_ops.h
+++ b/test/fake_avb_ops.h
@@ -95,16 +95,6 @@ class FakeAvbOpsDelegate {
size_t value_size,
const uint8_t* value) = 0;
- virtual AvbIOResult validate_public_key_for_partition(
- AvbOps* ops,
- const char* partition,
- const uint8_t* public_key_data,
- size_t public_key_length,
- const uint8_t* public_key_metadata,
- size_t public_key_metadata_length,
- bool* out_is_trusted,
- uint32_t* out_rollback_index_location) = 0;
-
virtual AvbIOResult read_permanent_attributes(
AvbAtxPermanentAttributes* attributes) = 0;
@@ -160,16 +150,6 @@ class FakeAvbOps : public FakeAvbOpsDelegate {
expected_public_key_ = expected_public_key;
}
- void set_expected_public_key_for_partition(
- const std::string& partition_name,
- const std::string& expected_public_key,
- uint32_t rollback_index_location) {
- expected_public_key_for_partition_map_[partition_name] =
- expected_public_key;
- rollback_index_location_for_partition_map_[partition_name] =
- rollback_index_location;
- }
-
void set_expected_public_key_metadata(
const std::string& expected_public_key_metadata) {
expected_public_key_metadata_ = expected_public_key_metadata;
@@ -268,16 +248,6 @@ class FakeAvbOps : public FakeAvbOpsDelegate {
size_t value_size,
const uint8_t* value) override;
- AvbIOResult validate_public_key_for_partition(
- AvbOps* ops,
- const char* partition,
- const uint8_t* public_key_data,
- size_t public_key_length,
- const uint8_t* public_key_metadata,
- size_t public_key_metadata_length,
- bool* out_is_trusted,
- uint32_t* out_rollback_index_location) override;
-
AvbIOResult read_permanent_attributes(
AvbAtxPermanentAttributes* attributes) override;
@@ -301,10 +271,6 @@ class FakeAvbOps : public FakeAvbOpsDelegate {
std::string expected_public_key_;
std::string expected_public_key_metadata_;
- std::map<std::string, std::string> expected_public_key_for_partition_map_;
-
- std::map<std::string, uint32_t> rollback_index_location_for_partition_map_;
-
std::map<size_t, uint64_t> stored_rollback_indexes_;
std::map<size_t, uint64_t> verified_rollback_indexes_;
@@ -362,25 +328,6 @@ class FakeAvbOpsDelegateWithDefaults : public FakeAvbOpsDelegate {
out_key_is_trusted);
}
- AvbIOResult validate_public_key_for_partition(
- AvbOps* ops,
- const char* partition,
- const uint8_t* public_key_data,
- size_t public_key_length,
- const uint8_t* public_key_metadata,
- size_t public_key_metadata_length,
- bool* out_key_is_trusted,
- uint32_t* out_rollback_index_location) override {
- return ops_.validate_public_key_for_partition(ops,
- partition,
- public_key_data,
- public_key_length,
- public_key_metadata,
- public_key_metadata_length,
- out_key_is_trusted,
- out_rollback_index_location);
- }
-
AvbIOResult read_rollback_index(AvbOps* ops,
size_t rollback_index_slot,
uint64_t* out_rollback_index) override {
diff --git a/tools/at_auth_unlock.py b/tools/at_auth_unlock.py
index c7e6869..80b5bb6 100755
--- a/tools/at_auth_unlock.py
+++ b/tools/at_auth_unlock.py
@@ -38,10 +38,6 @@ Unlock credentials can be provided to the tool in one of two ways:
of the provided credential archives for a match against the product ID of
the device being unlocked and automatically use the first match.
-This tool also clears the factory partition persistent digest unless the
---clear_factory_digest=false option is used. There is no harm to clear this
-digest even if changes to the factory partition are not planned.
-
Dependencies:
- Python 2.7.x, 3.2.x, or newer (for argparse)
- PyCrypto 2.5 or newer (for PKCS1_v1_5 and RSA PKCS#8 PEM key import)
@@ -53,7 +49,7 @@ HELP_DESCRIPTION = """Performs an authenticated AVB unlock of an Android Things
fastboot, given valid unlock credentials for the device."""
HELP_USAGE = """
- %(prog)s [-h] [-v] [-s SERIAL] [--clear_factory_digest=true|false] unlock_creds.zip [unlock_creds_2.zip ...]
+ %(prog)s [-h] [-v] [-s SERIAL] unlock_creds.zip [unlock_creds_2.zip ...]
%(prog)s --pik_cert pik_cert.bin --puk_cert puk_cert.bin --puk puk.pem"""
HELP_EPILOG = """examples:
@@ -374,67 +370,6 @@ def FindUnlockCredentialsInDirectory(dir, verbose=False):
return creds
-def ClearFactoryPersistentDigest(serial=None, verbose=False):
- """Clears the factory partition persistent digest using fastboot.
-
- Most of the time this should be cleared when unlocking a device because
- otherwise any attempts to update the factory partition will be rejected once
- the device is again locked, causing confusion. There is no harm to clear this
- digest even if factory partition updates are not planned.
-
- Arguments:
- serial: [optional] A device serial number or other valid value to be passed
- to fastboot's '-s' switch to select the device to unlock.
- verbose: [optional] Enable verbose output, which prints the fastboot
- commands and their output as the commands are run.
- """
- FACTORY_PERSISTENT_DIGEST_NAME = 'avb.persistent_digest.factory'
-
- tempdir = tempfile.mkdtemp()
- try:
- digest_data = os.path.join(tempdir, 'digest_data')
-
- with open(digest_data, 'wb') as out:
- out.write(struct.pack('<I', len(FACTORY_PERSISTENT_DIGEST_NAME)))
- out.write(FACTORY_PERSISTENT_DIGEST_NAME)
- # Sending a zero length digest will clear the existing digest.
- out.write(struct.pack('<I', 0))
-
- def fastboot_cmd(args):
- args = ['fastboot'] + (['-s', serial] if serial else []) + args
- if verbose:
- print('$ ' + ' '.join(args))
-
- out = subprocess.check_output(
- args, stderr=subprocess.STDOUT).decode('utf-8')
-
- if verbose:
- print(out)
-
- try:
- fastboot_cmd(['stage', digest_data])
- fastboot_cmd(['oem', 'at-write-persistent-digest'])
- print("Successfully cleared the factory partition persistent digest.")
- return True
- except subprocess.CalledProcessError as e:
- print(e.output.decode('utf-8'))
- print("Command '{}' returned non-zero exit status {}".format(
- ' '.join(e.cmd), e.returncode))
- print("Warning: Failed to clear factory partition persistent digest.")
- return False
-
- finally:
- shutil.rmtree(tempdir)
-
-
-def parse_boolean(value):
- if value.strip().lower() in ('true', 't', 'yes', 'y', 'on', '1'):
- return True
- elif value.strip().lower() in ('false', 'f', 'no', 'n', 'off', '0'):
- return False
- else:
- raise argparse.ArgumentTypeError('Unexpected boolean value: %s' % value)
-
def main(in_args):
parser = argparse.ArgumentParser(
description=HELP_DESCRIPTION,
@@ -455,13 +390,6 @@ def main(in_args):
help=
"specify device to unlock, either by serial or any other valid value for fastboot's -s arg"
)
- parser.add_argument(
- '--clear_factory_digest',
- nargs='?',
- type=parse_boolean,
- default='true',
- const='true',
- help='Defaults to true. Set to false to prevent clearing the factory persistent digest')
# User must provide either a unlock credential bundle, or the individual files
# normally contained in such a bundle.
@@ -537,8 +465,6 @@ def main(in_args):
creds = [UnlockCredentials(args.pik_cert, args.puk_cert, args.puk)]
ret = AuthenticatedUnlock(creds, serial=args.serial, verbose=args.verbose)
- if ret and args.clear_factory_digest:
- ret = ClearFactoryPersistentDigest(serial=args.serial, verbose=args.verbose)
return 0 if ret else 1
diff --git a/tools/transparency/pixel_factory_image_verify.py b/tools/transparency/pixel_factory_image_verify.py
deleted file mode 100755
index 4479789..0000000
--- a/tools/transparency/pixel_factory_image_verify.py
+++ /dev/null
@@ -1,341 +0,0 @@
-#!/usr/bin/env python
-
-# Copyright 2019, The Android Open Source Project
-#
-# Permission is hereby granted, free of charge, to any person
-# obtaining a copy of this software and associated documentation
-# files (the "Software"), to deal in the Software without
-# restriction, including without limitation the rights to use, copy,
-# modify, merge, publish, distribute, sublicense, and/or sell copies
-# of the Software, and to permit persons to whom the Software is
-# furnished to do so, subject to the following conditions:
-#
-# The above copyright notice and this permission notice shall be
-# included in all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
-# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
-# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-# SOFTWARE.
-#
-
-"""Tool for verifying VBMeta & calculate VBMeta Digests of Pixel factory images.
-
-If given an HTTPS URL it will download the file first before processing.
-$ pixel_factory_image_verify.py https://dl.google.com/dl/android/aosp/image.zip
-
-Otherwise, the argument is considered to be a local file.
-$ pixel_factory_image_verify.py image.zip
-
-The list of canonical Pixel factory images can be found here:
-https://developers.google.com/android/images
-
-Supported are all factory images of Pixel 3 and later devices.
-
-In order for the tool to run correct the following utilities need to be
-pre-installed: wget, unzip.
-
-The tool also runs outside of the repository location as long as the working
-directory is writable.
-"""
-
-from __future__ import print_function
-
-import os
-import shutil
-import subprocess
-import sys
-import tempfile
-import distutils.spawn
-
-
-class PixelFactoryImageVerifier(object):
- """Object for the pixel_factory_image_verify command line tool."""
-
- def __init__(self):
- self.working_dir = os.getcwd()
- self.script_path = os.path.realpath(__file__)
- self.script_dir = os.path.split(self.script_path)[0]
- self.avbtool_path = os.path.abspath(os.path.join(self.script_path,
- '../../../avbtool'))
-
- def run(self, argv):
- """Command line processor.
-
- Args:
- argv: The command line parameter list.
- """
- # Checks for command line parameters and show help if non given.
- if len(argv) != 2:
- print('No command line parameter given. At least a filename or URL for a '
- 'Pixel 3 or later factory image needs to be specified.')
- sys.exit(1)
-
- # Checks if necessary commands are available.
- for cmd in ['grep', 'unzip', 'wget']:
- if not distutils.spawn.find_executable(cmd):
- print('Necessary command line tool needs to be installed first: %s'
- % cmd)
- sys.exit(1)
-
- # Downloads factory image if URL is specified; otherwise treat it as file.
- if argv[1].lower().startswith('https://'):
- factory_image_zip = self._download_factory_image(argv[1])
- if not factory_image_zip:
- sys.exit(1)
- else:
- factory_image_zip = os.path.abspath(argv[1])
-
- # Unpacks the factory image into partition images.
- partition_image_dir = self._unpack_factory_image(factory_image_zip)
- if not partition_image_dir:
- sys.exit(1)
-
- # Validates the VBMeta of the factory image.
- verified = self._verify_vbmeta_partitions(partition_image_dir)
- if not verified:
- sys.exit(1)
-
- fingerprint = self._extract_build_fingerprint(partition_image_dir)
- if not fingerprint:
- sys.exit(1)
-
- # Calculates the VBMeta Digest for the factory image.
- vbmeta_digest = self._calculate_vbmeta_digest(partition_image_dir)
- if not vbmeta_digest:
- sys.exit(1)
-
- print('The build fingerprint for factory image is: %s' % fingerprint)
- print('The VBMeta Digest for factory image is: %s' % vbmeta_digest)
- sys.exit(0)
-
- def _download_factory_image(self, url):
- """Downloads the factory image to the working directory.
-
- Args:
- url: The download URL for the factory image.
-
- Returns:
- The absolute path to the factory image or None if it failed.
- """
- # Creates temporary download folder.
- download_path = tempfile.mkdtemp(dir=self.working_dir)
-
- # Downloads the factory image to the temporary folder.
- download_filename = self._download_file(download_path, url)
- if not download_filename:
- return None
-
- # Moves the downloaded file into the working directory.
- download_file = os.path.join(download_path, download_filename)
- target_file = os.path.join(self.working_dir, download_filename)
- if os.path.exists(target_file):
- try:
- os.remove(target_file)
- except OSError as e:
- print('File %s already exists and cannot be deleted.' % download_file)
- return None
- try:
- shutil.move(download_file, self.working_dir)
- except shutil.Error as e:
- print('File %s cannot be moved to %s: %s' % (download_file,
- target_file, e))
- return None
-
- # Removes temporary download folder.
- try:
- shutil.rmtree(download_path)
- except shutil.Error as e:
- print('Temporary download folder %s could not be removed.'
- % download_path)
- return os.path.join(self.working_dir, download_filename)
-
- def _download_file(self, download_dir, url):
- """Downloads a file from the Internet.
-
- Args:
- download_dir: The folder the file should be downloaded to.
- url: The download URL for the file.
-
- Returns:
- The name of the downloaded file as it apears on disk; otherwise None
- if download failed.
- """
- print('Fetching file from: %s' % url)
- os.chdir(download_dir)
- args = ['wget', url]
- result, _ = self._run_command(args,
- 'Successfully downloaded file.',
- 'File download failed.')
- os.chdir(self.working_dir)
- if not result:
- return None
-
- # Figure out the file name of what was downloaded: It will be the only file
- # in the download folder.
- files = os.listdir(download_dir)
- if files and len(files) == 1:
- return files[0]
- else:
- return None
-
- def _unpack_factory_image(self, factory_image_file):
- """Unpacks the factory image zip file.
-
- Args:
- factory_image_file: path and file name to the image file.
-
- Returns:
- The path to the folder which contains the unpacked factory image files or
- None if it failed.
- """
- unpack_dir = tempfile.mkdtemp(dir=self.working_dir)
- args = ['unzip', factory_image_file, '-d', unpack_dir]
- result, _ = self._run_command(args,
- 'Successfully unpacked factory image.',
- 'Failed to unpack factory image.')
- if not result:
- return None
-
- # Locate the directory which contains the image files.
- files = os.listdir(unpack_dir)
- image_name = None
- for f in files:
- path = os.path.join(self.working_dir, unpack_dir, f)
- if os.path.isdir(path):
- image_name = f
- break
- if not image_name:
- print('No image found: %s' % image_name)
- return None
-
- # Move image file directory to the working directory
- image_dir = os.path.join(unpack_dir, image_name)
- target_dir = os.path.join(self.working_dir, image_name)
- if os.path.exists(target_dir):
- try:
- shutil.rmtree(target_dir)
- except shutil.Error as e:
- print('Directory %s already exists and cannot be deleted.' % target_dir)
- return None
-
- try:
- shutil.move(image_dir, self.working_dir)
- except shutil.Error as e:
- print('Directory %s could not be moved to %s: %s' % (image_dir,
- self.working_dir, e))
- return None
-
- # Removes tmp unpack directory.
- try:
- shutil.rmtree(unpack_dir)
- except shutil.Error as e:
- print('Temporary download folder %s could not be removed.'
- % unpack_dir)
-
- # Unzip the secondary zip file which contain the individual images.
- image_filename = 'image-%s' % image_name
- image_folder = os.path.join(self.working_dir, image_name)
- os.chdir(image_folder)
-
- args = ['unzip', image_filename]
- result, _ = self._run_command(
- args,
- 'Successfully unpacked factory image partitions.',
- 'Failed to unpack factory image partitions.')
- if not result:
- return None
- return image_folder
-
- def _verify_vbmeta_partitions(self, image_dir):
- """Verifies all partitions protected by VBMeta using avbtool verify_image.
-
- Args:
- image_dir: The folder containing the unpacked factory image partitions,
- which contains a vbmeta.img patition.
-
- Returns:
- True if the VBMeta protected parititions verify.
- """
- os.chdir(image_dir)
- args = [self.avbtool_path,
- 'verify_image',
- '--image', 'vbmeta.img',
- '--follow_chain_partitions']
- result, _ = self._run_command(args,
- 'Successfully verified VBmeta.',
- 'Verification of VBmeta failed.')
- os.chdir(self.working_dir)
- return result
-
- def _extract_build_fingerprint(self, image_dir):
- """Extracts the build fingerprint from the system.img.
- Args:
- image_dir: The folder containing the unpacked factory image partitions,
- which contains a vbmeta.img patition.
-
- Returns:
- The build fingerprint string, e.g.
- google/blueline/blueline:9/PQ2A.190305.002/5240760:user/release-keys
- """
- os.chdir(image_dir)
- args = ['grep',
- '-a',
- 'ro\.build\.fingerprint=google/.*/release-keys',
- 'system.img']
-
- result, output = self._run_command(
- args,
- 'Successfully extracted build fingerpint.',
- 'Build fingerprint extraction failed.')
- os.chdir(self.working_dir)
- if result:
- _, fingerprint = output.split('=', 1)
- return fingerprint.rstrip()
- else:
- return None
-
- def _calculate_vbmeta_digest(self, image_dir):
- """Calculates the VBMeta Digest for given parititions using avbtool.
-
- Args:
- image_dir: The folder containing the unpacked factory image partitions,
- which contains a vbmeta.img partition.
-
- Returns:
- Hex string with the VBmeta Digest value or None if it failed.
- """
- os.chdir(image_dir)
- args = [self.avbtool_path,
- 'calculate_vbmeta_digest',
- '--image', 'vbmeta.img']
- result, output = self._run_command(args,
- 'Successfully calculated VBMeta Digest.',
- 'Failed to calculate VBmeta Digest.')
- os.chdir(self.working_dir)
- if result:
- return output
- else:
- return None
-
- def _run_command(self, args, success_msg, fail_msg):
- """Runs command line tools."""
- p = subprocess.Popen(args, stdin=subprocess.PIPE,
- stdout=subprocess.PIPE, stderr=subprocess.PIPE)
- pout, _ = p.communicate()
- if p.wait() == 0:
- print(success_msg)
- return True, pout
- else:
- print(fail_msg)
- return False, pout
-
-
-if __name__ == '__main__':
- tool = PixelFactoryImageVerifier()
- tool.run(sys.argv)
-