[automerger skipped] avbtool: avoid repeated string concatentations am: 7be0d9025e am: 4a2dc9d94a am: 3d6543e08b -s ours

am skip reason: Change-Id Idbbdb075d860d7e834e3d130b1968ac380eace31 with SHA-1 7be0d9025e is in history

Original change: https://googleplex-android-review.googlesource.com/c/platform/external/avb/+/10501780

Change-Id: Id3e9ef80de1d0acac995b343434ab04f72948844
diff --git a/avbtool b/avbtool
index bdac52d..c263b90 100755
--- a/avbtool
+++ b/avbtool
@@ -2340,6 +2340,13 @@
 
     (footer, header, descriptors, image_size) = self._parse_image(image)
 
+    # To show the SHA1 of the public key.
+    vbmeta_blob = self._load_vbmeta_blob(image)
+    key_offset = (header.SIZE +
+                  header.authentication_data_block_size +
+                  header.public_key_offset)
+    key_blob = vbmeta_blob[key_offset:key_offset + header.public_key_size]
+
     if footer:
       o.write('Footer version:           {}.{}\n'.format(footer.version_major,
                                                          footer.version_minor))
@@ -2361,6 +2368,9 @@
         header.authentication_data_block_size))
     o.write('Auxiliary Block:          {} bytes\n'.format(
         header.auxiliary_data_block_size))
+    if key_blob:
+      hexdig = hashlib.sha1(key_blob).hexdigest()
+      o.write('Public key (sha1):        {}\n'.format(hexdig))
     o.write('Algorithm:                {}\n'.format(alg_name))
     o.write('Rollback Index:           {}\n'.format(header.rollback_index))
     o.write('Flags:                    {}\n'.format(header.flags))
diff --git a/libavb/avb_descriptor.c b/libavb/avb_descriptor.c
index cfc2aac..7030a40 100644
--- a/libavb/avb_descriptor.c
+++ b/libavb/avb_descriptor.c
@@ -88,6 +88,10 @@
   }
 
   for (p = desc_start; p < desc_end;) {
+    if (p + sizeof(AvbDescriptor) > desc_end) {
+      avb_error("Invalid descriptor length.\n");
+      goto out;
+    }
     const AvbDescriptor* dh = (const AvbDescriptor*)p;
     avb_assert_aligned(dh);
     uint64_t nb_following = avb_be64toh(dh->num_bytes_following);
diff --git a/libavb/avb_util.c b/libavb/avb_util.c
index 938ce4e..c0064cf 100644
--- a/libavb/avb_util.c
+++ b/libavb/avb_util.c
@@ -195,6 +195,12 @@
                     size_t str2_len) {
   uint64_t combined_len;
 
+  // Doesn't make sense to pass 0 for buf_size since there's
+  // no room for the terminating NUL byte.
+  if (buf_size == 0) {
+    return false;
+  }
+
   if (!avb_safe_add(&combined_len, str1_len, str2_len)) {
     avb_error("Overflow when adding string sizes.\n");
     return false;
diff --git a/libavb_aftl/avb_aftl_types.h b/libavb_aftl/avb_aftl_types.h
index 752d6d7..e36fc18 100644
--- a/libavb_aftl/avb_aftl_types.h
+++ b/libavb_aftl/avb_aftl_types.h
@@ -48,6 +48,8 @@
 #define AVB_AFTL_MAX_AFTL_DESCRIPTOR_SIZE 65536ul
 /* Limit version.incremental size to 256 characters. */
 #define AVB_AFTL_MAX_VERSION_INCREMENTAL_SIZE 256ul
+/* AFTL trees require at most 64 hashes to reconstruct the root */
+#define AVB_AFTL_MAX_PROOF_SIZE 64 * AVB_AFTL_HASH_SIZE
 /* Max URL limit. */
 #define AVB_AFTL_MAX_URL_SIZE 2048ul
 /* Minimum valid size for a FirmwareInfo leaf. Derived from a minimal json
@@ -151,7 +153,7 @@
   FirmwareInfo fw_info_leaf;
   uint8_t* log_root_signature;
   uint8_t proofs[/*proof_hash_count*/][AVB_AFTL_HASH_SIZE];
-} AftlIcpEntry;
+} AVB_ATTR_PACKED AftlIcpEntry;
 
 /* Main data structure for an AFTL descriptor. */
 typedef struct AftlDescriptor {
diff --git a/libavb_aftl/avb_aftl_util.c b/libavb_aftl/avb_aftl_util.c
index 74f0653..d1fa33c 100644
--- a/libavb_aftl/avb_aftl_util.c
+++ b/libavb_aftl/avb_aftl_util.c
@@ -413,7 +413,7 @@
              *aftl_blob,
              avb_aftl_member_size(TrillianLogRootDescriptor, version));
   icp_entry->log_root_descriptor.version =
-      avb_htobe16(icp_entry->log_root_descriptor.version);
+      avb_be16toh(icp_entry->log_root_descriptor.version);
   *aftl_blob += avb_aftl_member_size(TrillianLogRootDescriptor, version);
   parsed_size = avb_aftl_member_size(TrillianLogRootDescriptor, version);
   /* Copy in the tree size field from the blob. */
@@ -421,7 +421,7 @@
              *aftl_blob,
              avb_aftl_member_size(TrillianLogRootDescriptor, tree_size));
   icp_entry->log_root_descriptor.tree_size =
-      avb_htobe64(icp_entry->log_root_descriptor.tree_size);
+      avb_be64toh(icp_entry->log_root_descriptor.tree_size);
   *aftl_blob += avb_aftl_member_size(TrillianLogRootDescriptor, tree_size);
   parsed_size += avb_aftl_member_size(TrillianLogRootDescriptor, tree_size);
   /* Copy in the root hash size field from the blob. */
@@ -455,7 +455,7 @@
              *aftl_blob,
              avb_aftl_member_size(TrillianLogRootDescriptor, timestamp));
   icp_entry->log_root_descriptor.timestamp =
-      avb_htobe64(icp_entry->log_root_descriptor.timestamp);
+      avb_be64toh(icp_entry->log_root_descriptor.timestamp);
   *aftl_blob += avb_aftl_member_size(TrillianLogRootDescriptor, timestamp);
   parsed_size += avb_aftl_member_size(TrillianLogRootDescriptor, timestamp);
   /* Copy in the revision field from the blob. */
@@ -463,7 +463,7 @@
              *aftl_blob,
              avb_aftl_member_size(TrillianLogRootDescriptor, revision));
   icp_entry->log_root_descriptor.revision =
-      avb_htobe64(icp_entry->log_root_descriptor.revision);
+      avb_be64toh(icp_entry->log_root_descriptor.revision);
   *aftl_blob += avb_aftl_member_size(TrillianLogRootDescriptor, revision);
   parsed_size += avb_aftl_member_size(TrillianLogRootDescriptor, revision);
   /* Copy in the metadata size field from the blob. */
@@ -471,7 +471,7 @@
              *aftl_blob,
              avb_aftl_member_size(TrillianLogRootDescriptor, metadata_size));
   icp_entry->log_root_descriptor.metadata_size =
-      avb_htobe16(icp_entry->log_root_descriptor.metadata_size);
+      avb_be16toh(icp_entry->log_root_descriptor.metadata_size);
   *aftl_blob += avb_aftl_member_size(TrillianLogRootDescriptor, metadata_size);
   parsed_size += avb_aftl_member_size(TrillianLogRootDescriptor, metadata_size);
   if (icp_entry->log_root_descriptor.metadata_size >
@@ -623,108 +623,108 @@
 /* Allocates and populates an AftlIcpEntry from a binary blob.
    The blob is expected to be pointing to the beginning of a
    serialized AftlIcpEntry structure. */
-AftlIcpEntry* parse_icp_entry(uint8_t* aftl_blob, size_t* remaining_size) {
+AftlIcpEntry* parse_icp_entry(uint8_t** aftl_blob, size_t* remaining_size) {
   AftlIcpEntry *icp_entry, *tmp_icp_entry;
+  uint32_t proof_size;
   uint64_t parsed_size;
+
   /* Make a temp AftlIcpEntry to get the inclusion proof size
      for memory allocation purposes.*/
-  tmp_icp_entry = (AftlIcpEntry*)aftl_blob;
-  tmp_icp_entry->inc_proof_size = avb_htobe32(tmp_icp_entry->inc_proof_size);
+  tmp_icp_entry = (AftlIcpEntry*)*aftl_blob;
+  proof_size = avb_be32toh(tmp_icp_entry->inc_proof_size);
+
   /* Ensure the calculated size is sane. */
-  if (tmp_icp_entry->inc_proof_size + AVB_AFTL_MIN_AFTL_ICP_ENTRY_SIZE <
-      tmp_icp_entry->inc_proof_size) {
+  if (proof_size > AVB_AFTL_MAX_PROOF_SIZE) {
     avb_error("Invalid inclusion proof size.\n");
     return NULL;
   }
 
-  if (*remaining_size >=
-      tmp_icp_entry->inc_proof_size + AVB_AFTL_MIN_AFTL_ICP_ENTRY_SIZE) {
+  if (*remaining_size < proof_size + AVB_AFTL_MIN_AFTL_ICP_ENTRY_SIZE) {
     avb_error("Invalid AftlDescriptor\n");
     return NULL;
   }
 
-  icp_entry = (AftlIcpEntry*)avb_calloc(tmp_icp_entry->inc_proof_size +
-                                        sizeof(AftlIcpEntry));
+  icp_entry = (AftlIcpEntry*)avb_calloc(proof_size + sizeof(AftlIcpEntry));
   if (!icp_entry) {
     avb_error("Failure allocating AftlIcpEntry\n");
     return NULL;
   }
   /* Copy in the log server URL size field. */
   avb_memcpy(&(icp_entry->log_url_size),
-             aftl_blob,
+             *aftl_blob,
              avb_aftl_member_size(AftlIcpEntry, log_url_size));
-  icp_entry->log_url_size = avb_htobe32(icp_entry->log_url_size);
+  icp_entry->log_url_size = avb_be32toh(icp_entry->log_url_size);
   if (icp_entry->log_url_size > AVB_AFTL_MAX_URL_SIZE) {
     avb_error("Invalid log URL size.\n");
     avb_free(icp_entry);
     return NULL;
   }
-  aftl_blob += avb_aftl_member_size(AftlIcpEntry, log_url_size);
+  *aftl_blob += avb_aftl_member_size(AftlIcpEntry, log_url_size);
   parsed_size = avb_aftl_member_size(AftlIcpEntry, log_url_size);
   /* Copy in the leaf index field. */
   avb_memcpy(&(icp_entry->leaf_index),
-             aftl_blob,
+             *aftl_blob,
              avb_aftl_member_size(AftlIcpEntry, leaf_index));
-  icp_entry->leaf_index = avb_htobe64(icp_entry->leaf_index);
-  aftl_blob += avb_aftl_member_size(AftlIcpEntry, leaf_index);
+  icp_entry->leaf_index = avb_be64toh(icp_entry->leaf_index);
+  *aftl_blob += avb_aftl_member_size(AftlIcpEntry, leaf_index);
   parsed_size += avb_aftl_member_size(AftlIcpEntry, leaf_index);
   /* Copy in the TrillianLogRootDescriptor size field. */
   avb_memcpy(&(icp_entry->log_root_descriptor_size),
-             aftl_blob,
+             *aftl_blob,
              avb_aftl_member_size(AftlIcpEntry, log_root_descriptor_size));
   icp_entry->log_root_descriptor_size =
-      avb_htobe32(icp_entry->log_root_descriptor_size);
+      avb_be32toh(icp_entry->log_root_descriptor_size);
   if (icp_entry->log_root_descriptor_size < AVB_AFTL_MIN_TLRD_SIZE ||
       icp_entry->log_root_descriptor_size > AVB_AFTL_MAX_TLRD_SIZE) {
     avb_error("Invalid TrillianLogRootDescriptor size.\n");
     avb_free(icp_entry);
     return NULL;
   }
-  aftl_blob += avb_aftl_member_size(AftlIcpEntry, log_root_descriptor_size);
+  *aftl_blob += avb_aftl_member_size(AftlIcpEntry, log_root_descriptor_size);
   parsed_size += avb_aftl_member_size(AftlIcpEntry, log_root_descriptor_size);
   /* Copy in the FirmwareInfo leaf size field. */
   avb_memcpy(&(icp_entry->fw_info_leaf_size),
-             aftl_blob,
+             *aftl_blob,
              avb_aftl_member_size(AftlIcpEntry, fw_info_leaf_size));
-  icp_entry->fw_info_leaf_size = avb_htobe32(icp_entry->fw_info_leaf_size);
+  icp_entry->fw_info_leaf_size = avb_be32toh(icp_entry->fw_info_leaf_size);
   if (icp_entry->fw_info_leaf_size == 0 ||
       icp_entry->fw_info_leaf_size > AVB_AFTL_MAX_FW_INFO_SIZE) {
     avb_error("Invalid FirmwareInfo leaf size.\n");
     avb_free(icp_entry);
     return NULL;
   }
-  aftl_blob += avb_aftl_member_size(AftlIcpEntry, fw_info_leaf_size);
+  *aftl_blob += avb_aftl_member_size(AftlIcpEntry, fw_info_leaf_size);
   parsed_size += avb_aftl_member_size(AftlIcpEntry, fw_info_leaf_size);
   /* Copy the log root signature size field. */
   avb_memcpy(&(icp_entry->log_root_sig_size),
-             aftl_blob,
+             *aftl_blob,
              avb_aftl_member_size(AftlIcpEntry, log_root_sig_size));
-  icp_entry->log_root_sig_size = avb_htobe16(icp_entry->log_root_sig_size);
+  icp_entry->log_root_sig_size = avb_be16toh(icp_entry->log_root_sig_size);
   if (icp_entry->log_root_sig_size != AVB_AFTL_SIGNATURE_SIZE) {
     avb_error("Invalid log root signature size.\n");
     avb_free(icp_entry);
     return NULL;
   }
-  aftl_blob += avb_aftl_member_size(AftlIcpEntry, log_root_sig_size);
+  *aftl_blob += avb_aftl_member_size(AftlIcpEntry, log_root_sig_size);
   parsed_size += avb_aftl_member_size(AftlIcpEntry, log_root_sig_size);
   /* Copy the inclusion proof hash count field. */
   avb_memcpy(&(icp_entry->proof_hash_count),
-             aftl_blob,
+             *aftl_blob,
              avb_aftl_member_size(AftlIcpEntry, proof_hash_count));
-  aftl_blob += avb_aftl_member_size(AftlIcpEntry, proof_hash_count);
+  *aftl_blob += avb_aftl_member_size(AftlIcpEntry, proof_hash_count);
   parsed_size += avb_aftl_member_size(AftlIcpEntry, proof_hash_count);
   /* Copy the inclusion proof size field. */
   avb_memcpy(&(icp_entry->inc_proof_size),
-             aftl_blob,
+             *aftl_blob,
              avb_aftl_member_size(AftlIcpEntry, inc_proof_size));
-  icp_entry->inc_proof_size = avb_htobe32(icp_entry->inc_proof_size);
+  icp_entry->inc_proof_size = avb_be32toh(icp_entry->inc_proof_size);
   if (icp_entry->inc_proof_size !=
       icp_entry->proof_hash_count * AVB_AFTL_HASH_SIZE) {
     avb_error("Invalid inclusion proof size.\n");
     avb_free(icp_entry);
     return NULL;
   }
-  aftl_blob += avb_aftl_member_size(AftlIcpEntry, inc_proof_size);
+  *aftl_blob += avb_aftl_member_size(AftlIcpEntry, inc_proof_size);
   parsed_size += avb_aftl_member_size(AftlIcpEntry, inc_proof_size);
   /* Copy in the log server URL from the blob. */
   if (!avb_safe_add_to(&parsed_size, icp_entry->log_url_size)) {
@@ -743,8 +743,8 @@
     free_aftl_icp_entry(icp_entry);
     return NULL;
   }
-  avb_memcpy(icp_entry->log_url, aftl_blob, icp_entry->log_url_size);
-  aftl_blob += icp_entry->log_url_size;
+  avb_memcpy(icp_entry->log_url, *aftl_blob, icp_entry->log_url_size);
+  *aftl_blob += icp_entry->log_url_size;
 
   /* Populate the TrillianLogRootDescriptor elements. */
   if (!avb_safe_add_to(&parsed_size, icp_entry->log_root_descriptor_size)) {
@@ -758,7 +758,7 @@
     return NULL;
   }
   if (!parse_trillian_log_root_descriptor(
-          icp_entry, &aftl_blob, icp_entry->log_root_descriptor_size)) {
+          icp_entry, aftl_blob, icp_entry->log_root_descriptor_size)) {
     return NULL;
   }
 
@@ -773,7 +773,7 @@
     free_aftl_icp_entry(icp_entry);
     return NULL;
   }
-  if (!parse_firmware_info(icp_entry, &aftl_blob)) return NULL;
+  if (!parse_firmware_info(icp_entry, aftl_blob)) return NULL;
 
   /* Allocate and copy the log root signature from the blob. */
   if (!avb_safe_add_to(&parsed_size, icp_entry->log_root_sig_size)) {
@@ -794,8 +794,8 @@
     return NULL;
   }
   avb_memcpy(
-      icp_entry->log_root_signature, aftl_blob, icp_entry->log_root_sig_size);
-  aftl_blob += icp_entry->log_root_sig_size;
+      icp_entry->log_root_signature, *aftl_blob, icp_entry->log_root_sig_size);
+  *aftl_blob += icp_entry->log_root_sig_size;
 
   if (!avb_safe_add_to(&parsed_size, icp_entry->inc_proof_size)) {
     avb_error("Invalid inclusion proof size.\n");
@@ -809,8 +809,8 @@
   }
 
   /* Finally, copy the proof hash data from the blob to the AftlDescriptor. */
-  avb_memcpy(icp_entry->proofs, aftl_blob, icp_entry->inc_proof_size);
-  aftl_blob += icp_entry->inc_proof_size;
+  avb_memcpy(icp_entry->proofs, *aftl_blob, icp_entry->inc_proof_size);
+  *aftl_blob += icp_entry->inc_proof_size;
   *remaining_size -= parsed_size;
 
   return icp_entry;
@@ -834,7 +834,7 @@
     return NULL;
   }
   /* Extract the size out of the header. */
-  aftl_descriptor_size = avb_htobe32(icp_header->aftl_descriptor_size);
+  aftl_descriptor_size = avb_be32toh(icp_header->aftl_descriptor_size);
   if (aftl_descriptor_size > AVB_AFTL_MAX_AFTL_DESCRIPTOR_SIZE) return NULL;
   avb_assert(aftl_descriptor_size >= sizeof(AftlIcpHeader) &&
              aftl_descriptor_size < AVB_AFTL_MAX_AFTL_DESCRIPTOR_SIZE);
@@ -847,13 +847,13 @@
   avb_memcpy(&(aftl_descriptor->header), aftl_blob, sizeof(AftlIcpHeader));
   /* Fix endianness. */
   aftl_descriptor->header.required_icp_version_major =
-      avb_htobe32(aftl_descriptor->header.required_icp_version_major);
+      avb_be32toh(aftl_descriptor->header.required_icp_version_major);
   aftl_descriptor->header.required_icp_version_minor =
-      avb_htobe32(aftl_descriptor->header.required_icp_version_minor);
+      avb_be32toh(aftl_descriptor->header.required_icp_version_minor);
   aftl_descriptor->header.aftl_descriptor_size =
-      avb_htobe32(aftl_descriptor->header.aftl_descriptor_size);
+      avb_be32toh(aftl_descriptor->header.aftl_descriptor_size);
   aftl_descriptor->header.icp_count =
-      avb_htobe16(aftl_descriptor->header.icp_count);
+      avb_be16toh(aftl_descriptor->header.icp_count);
   /* Allocate memory for the entry array */
   aftl_descriptor->entries = (AftlIcpEntry**)avb_calloc(
       sizeof(AftlIcpEntry*) * aftl_descriptor->header.icp_count);
@@ -868,7 +868,7 @@
   remaining_size = aftl_blob_size - sizeof(AftlIcpHeader);
   for (i = 0; i < aftl_descriptor->header.icp_count && remaining_size > 0;
        i++) {
-    aftl_descriptor->entries[i] = parse_icp_entry(aftl_blob, &remaining_size);
+    aftl_descriptor->entries[i] = parse_icp_entry(&aftl_blob, &remaining_size);
   }
 
   return aftl_descriptor;
diff --git a/libavb_aftl/avb_aftl_util.h b/libavb_aftl/avb_aftl_util.h
index a17b454..bbbc34a 100644
--- a/libavb_aftl/avb_aftl_util.h
+++ b/libavb_aftl/avb_aftl_util.h
@@ -105,7 +105,7 @@
 
 /* Allocates and populates an AftlIcpEntry and all sub-fields from
    a binary blob. It is assumed that the blob points to an AftlIcpEntry. */
-AftlIcpEntry* parse_icp_entry(uint8_t* aftl_blob, size_t* remaining_size);
+AftlIcpEntry* parse_icp_entry(uint8_t** aftl_blob, size_t* remaining_size);
 
 /* Frees an AftlIcpEntry and all sub-fields that were previously
    allocated by a call to allocate_icp_entry. */
diff --git a/libavb_aftl/avb_aftl_verify.c b/libavb_aftl/avb_aftl_verify.c
index a3c4770..06911b0 100644
--- a/libavb_aftl/avb_aftl_verify.c
+++ b/libavb_aftl/avb_aftl_verify.c
@@ -22,75 +22,52 @@
  * SOFTWARE.
  */
 
-#include <libavb_aftl/libavb_aftl.h>
+#include "libavb_aftl/avb_aftl_verify.h"
 
+#include <libavb/avb_cmdline.h>
 #include <libavb/avb_slot_verify.h>
 #include <libavb/avb_util.h>
 
 #include "libavb_aftl/avb_aftl_types.h"
 #include "libavb_aftl/avb_aftl_util.h"
 #include "libavb_aftl/avb_aftl_validate.h"
-#include "libavb_aftl/avb_aftl_verify.h"
 
-/* The entry point of AFTL validation, Takes a AvbSlotVerifyData
-   struct generated by a prior call to avb_slot_verify and the transparency
-   log's public key and validates the inclusion proof. Returns
-   AVB_SLOT_VERIFY_RESULT_OK upon success, and
-   AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION
-   otherwise.
-*/
-AvbSlotVerifyResult aftl_slot_verify(AvbSlotVerifyData* asv_data,
-                                     uint8_t* key_bytes,
-                                     size_t key_size) {
-  size_t i;
-  size_t aftl_descriptor_size;
-  size_t vbmeta_size;
-  uint8_t* current_aftl_blob;
-  AvbSlotVerifyResult result = AVB_SLOT_VERIFY_RESULT_OK;
+/* Read the vbmeta partition, after the AvbVBMetaImageHeader structure, to find
+ * the AftlDescriptor.
+ */
+static AvbSlotVerifyResult avb_aftl_find_aftl_descriptor(
+    AvbOps* ops,
+    const char* part_name,
+    size_t vbmeta_size,
+    uint8_t* out_image_buf,
+    size_t* out_image_size) {
+  AvbIOResult io_ret;
 
-  avb_assert(asv_data != NULL);
-  avb_assert(key_bytes != NULL);
-  avb_assert(key_size == AVB_AFTL_PUB_KEY_SIZE);
-  /* Walk through each vbmeta blob in the AvbSlotVerifyData struct. */
-  if (asv_data->vbmeta_images != NULL) {
-    for (i = 0; i < asv_data->num_vbmeta_images; i++) {
-      aftl_descriptor_size = asv_data->vbmeta_images[i].vbmeta_size;
-      current_aftl_blob = avb_aftl_find_aftl_descriptor(
-          asv_data->vbmeta_images[i].vbmeta_data, &aftl_descriptor_size);
-      if (current_aftl_blob != NULL) {
-        /* Adjust the vbmeta size for hash calculations. */
-        vbmeta_size =
-            asv_data->vbmeta_images[i].vbmeta_size - aftl_descriptor_size;
-        /* Validate the AFTL descriptor in the vbmeta image. */
-        result =
-            avb_aftl_verify_descriptor(asv_data->vbmeta_images[i].vbmeta_data,
-                                       vbmeta_size,
-                                       current_aftl_blob,
-                                       aftl_descriptor_size,
-                                       key_bytes,
-                                       key_size);
-        if (result != AVB_SLOT_VERIFY_RESULT_OK) break;
-      }
-    }
+  avb_assert(vbmeta_size <= AVB_AFTL_MAX_AFTL_DESCRIPTOR_SIZE);
+  io_ret =
+      ops->read_from_partition(ops,
+                               part_name,
+                               vbmeta_size /* offset */,
+                               AVB_AFTL_MAX_AFTL_DESCRIPTOR_SIZE - vbmeta_size,
+                               out_image_buf,
+                               out_image_size);
+
+  if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
+    return AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
+  } else if (io_ret != AVB_IO_RESULT_OK) {
+    avb_errorv(
+        part_name, ": Error loading AftlDescriptor from partition.\n", NULL);
+    return AVB_SLOT_VERIFY_RESULT_ERROR_IO;
   }
 
-  return result;
-}
-
-/* Scans a vbmeta image for the AFTL descriptor's magic value.
-   Returns the offset of the AFTL descriptor if found, or NULL otherwise. */
-uint8_t* avb_aftl_find_aftl_descriptor(uint8_t* vbmeta_blob,
-                                       size_t* vbmeta_size) {
-  size_t i;
-  for (i = 0; i < *vbmeta_size - 4; i++) {
-    if ((vbmeta_blob[i] == 'A') && (vbmeta_blob[i + 1] == 'F') &&
-        (vbmeta_blob[i + 2] == 'T') && (vbmeta_blob[i + 3] == 'L')) {
-      *vbmeta_size -= i;
-      return &(vbmeta_blob[i]);
-    }
+  if (*out_image_size < 4 || (out_image_buf[0] != 'A') ||
+      (out_image_buf[1] != 'F') || (out_image_buf[2] != 'T') ||
+      (out_image_buf[3] != 'L')) {
+    avb_errorv(part_name, ": Unexpected AftlDescriptor magic.\n", NULL);
+    return AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
   }
-  *vbmeta_size = 0;
-  return NULL;
+
+  return AVB_SLOT_VERIFY_RESULT_OK;
 }
 
 /* Performs the three validation steps for an AFTL descriptor:
@@ -98,12 +75,12 @@
    2. Ensure the root hash of the Merkle tree matches that in the descriptor.
    3. Verify the signature using the transparency log public key.
 */
-AvbSlotVerifyResult avb_aftl_verify_descriptor(uint8_t* cur_vbmeta_data,
-                                               size_t cur_vbmeta_size,
-                                               uint8_t* aftl_blob,
-                                               size_t aftl_size,
-                                               uint8_t* key_bytes,
-                                               size_t key_num_bytes) {
+static AvbSlotVerifyResult avb_aftl_verify_descriptor(uint8_t* cur_vbmeta_data,
+                                                      size_t cur_vbmeta_size,
+                                                      uint8_t* aftl_blob,
+                                                      size_t aftl_size,
+                                                      uint8_t* key_bytes,
+                                                      size_t key_num_bytes) {
   size_t i;
   AftlDescriptor* aftl_descriptor;
   AvbSlotVerifyResult result = AVB_SLOT_VERIFY_RESULT_OK;
@@ -119,35 +96,92 @@
   for (i = 0; i < aftl_descriptor->header.icp_count; i++) {
     /* 1. Ensure that the vbmeta hash stored in the AftlIcpEntry matches
        the one that represents the partition. */
-    if (avb_aftl_verify_vbmeta_hash(
+    if (!avb_aftl_verify_vbmeta_hash(
             cur_vbmeta_data, cur_vbmeta_size, aftl_descriptor->entries[i])) {
-      /* 2. Ensure that the root hash of the Merkle tree representing
-         the transparency log entry matches the one stored in the
-         AftlIcpEntry. */
-      if (avb_aftl_verify_icp_root_hash(aftl_descriptor->entries[i])) {
-        /* 3. Verify the signature using the transparency log public
-           key stored on device. */
-        if (avb_aftl_verify_entry_signature(
-                key_bytes, key_num_bytes, aftl_descriptor->entries[i])) {
-          /* Everything passed verification, set status to OK. */
-          result = AVB_SLOT_VERIFY_RESULT_OK;
-        } else {
-          avb_errorv(
-              "AFTL signature verification failed on entry ", i, "\n", NULL);
-          result = AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION;
-        }
-      } else {
-        avb_errorv(
-            "AFTL root hash verification failed on entry ", i, "\n", NULL);
-        result = AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION;
-      }
-    } else {
-      avb_errorv(
-          "AFTL vbmeta hash verification failed on entry ", i, "\n", NULL);
+      avb_error("AFTL vbmeta hash verification failed.\n");
       result = AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION;
+      break;
     }
-    if (result != AVB_SLOT_VERIFY_RESULT_OK) break;
+    /* 2. Ensure that the root hash of the Merkle tree representing
+       the transparency log entry matches the one stored in the
+       AftlIcpEntry. */
+    if (!avb_aftl_verify_icp_root_hash(aftl_descriptor->entries[i])) {
+      avb_error("AFTL root hash verification failed.\n");
+      result = AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION;
+      break;
+    }
+    /* 3. Verify the signature using the transparency log public
+       key stored on device. */
+    if (!avb_aftl_verify_entry_signature(
+            key_bytes, key_num_bytes, aftl_descriptor->entries[i])) {
+      avb_error("AFTL signature verification failed on entry.\n");
+      result = AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION;
+      break;
+    }
   }
   free_aftl_descriptor(aftl_descriptor);
   return result;
 }
+
+AvbSlotVerifyResult aftl_slot_verify(AvbOps* ops,
+                                     AvbSlotVerifyData* asv_data,
+                                     uint8_t* key_bytes,
+                                     size_t key_size) {
+  size_t i;
+  size_t aftl_descriptor_size;
+  size_t vbmeta_size;
+  uint8_t* current_aftl_blob;
+  char part_name[AVB_PART_NAME_MAX_SIZE];
+  char* pname;
+  AvbSlotVerifyResult ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
+
+  avb_assert(asv_data != NULL);
+  avb_assert(key_bytes != NULL);
+  avb_assert(key_size == AVB_AFTL_PUB_KEY_SIZE);
+  if (asv_data->vbmeta_images == NULL) {
+    return AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION;
+  }
+
+  current_aftl_blob = avb_malloc(AVB_AFTL_MAX_AFTL_DESCRIPTOR_SIZE);
+  if (current_aftl_blob == NULL) {
+    return AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
+  }
+
+  /* Walk through each vbmeta blob in the AvbSlotVerifyData struct. */
+  for (i = 0; i < asv_data->num_vbmeta_images; i++) {
+    /* Rebuild partition name, appending the suffix */
+    pname = asv_data->vbmeta_images[i].partition_name;
+    if (!avb_str_concat(part_name,
+                        sizeof part_name,
+                        (const char*)pname,
+                        avb_strlen(pname),
+                        asv_data->ab_suffix,
+                        avb_strlen(asv_data->ab_suffix))) {
+      avb_error("Partition name and suffix does not fit.\n");
+      ret = AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION;
+      break;
+    }
+
+    /* Use the partition info to find the AftlDescriptor */
+    vbmeta_size = asv_data->vbmeta_images[i].vbmeta_size;
+    ret = avb_aftl_find_aftl_descriptor(
+        ops, part_name, vbmeta_size, current_aftl_blob, &aftl_descriptor_size);
+    if (ret != AVB_SLOT_VERIFY_RESULT_OK) {
+      avb_error("Unable to find the AftlDescriptor.\n");
+      ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
+      break;
+    }
+
+    /* Validate the AFTL descriptor in the vbmeta image. */
+    ret = avb_aftl_verify_descriptor(asv_data->vbmeta_images[i].vbmeta_data,
+                                     vbmeta_size,
+                                     current_aftl_blob,
+                                     aftl_descriptor_size,
+                                     key_bytes,
+                                     key_size);
+    if (ret != AVB_SLOT_VERIFY_RESULT_OK) break;
+  }
+
+  avb_free(current_aftl_blob);
+  return ret;
+}
diff --git a/libavb_aftl/avb_aftl_verify.h b/libavb_aftl/avb_aftl_verify.h
index 78f8b29..fe7ef41 100644
--- a/libavb_aftl/avb_aftl_verify.h
+++ b/libavb_aftl/avb_aftl_verify.h
@@ -28,26 +28,30 @@
 #ifndef AVB_AFTL_VERIFY_H_
 #define AVB_AFTL_VERIFY_H_
 
+#include <libavb/libavb.h>
+
 #ifdef __cplusplus
 extern "C" {
 #endif
 
-/* Scans a vbmeta image for the AFTL descriptor's magic value.
-   Returns the offset of the AFTL descriptor if found, or NULL otherwise. */
-uint8_t* avb_aftl_find_aftl_descriptor(uint8_t* vbmeta_blob,
-                                       size_t* vbmeta_size);
-
-/* Performs the three validation steps for an AFTL descriptor:
+/* The entry point of AFTL validation. Takes an AvbSlotVerifyData
+   struct generated by a prior call to avb_slot_verify and the transparency
+   log's public key and validates the inclusion proof. It does this by
+   performing the following three validation steps for an AFTL
+   descriptor:
    1. Ensure the vbmeta image hash matches that in the descriptor.
    2. Ensure the root hash of the Merkle tree matches that in the descriptor.
    3. Verify the signature using the transparency log public key.
+   It returns AVB_SLOT_VERIFY_RESULT_OK upon success,
+   AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA if at least one VBMeta did not
+   have an AftlDescriptor and AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION
+   otherwise.
 */
-AvbSlotVerifyResult avb_aftl_verify_descriptor(uint8_t* cur_vbmeta_data,
-                                               size_t cur_vbmeta_size,
-                                               uint8_t* aftl_blob,
-                                               size_t aftl_size,
-                                               uint8_t* key_bytes,
-                                               size_t key_num_bytes);
+
+AvbSlotVerifyResult aftl_slot_verify(AvbOps* ops,
+                                     AvbSlotVerifyData* asv_data,
+                                     uint8_t* key_bytes,
+                                     size_t key_size);
 #ifdef __cplusplus
 }
 #endif
diff --git a/libavb_aftl/libavb_aftl.h b/libavb_aftl/libavb_aftl.h
index ef47c1f..dbf0146 100644
--- a/libavb_aftl/libavb_aftl.h
+++ b/libavb_aftl/libavb_aftl.h
@@ -25,7 +25,6 @@
 #ifndef LIBAVB_AFTL_H_
 #define LIBAVB_AFTL_H_
 
-#include <libavb/libavb.h>
 
 /* The AVB_INSIDE_LIBAVB_AFTL_H preprocessor symbol is used to enforce
  * library users to include only this file. All public interfaces, and
@@ -33,32 +32,7 @@
  */
 
 #define AVB_INSIDE_LIBAVB_AFTL_H
-#include "avb_ops_aftl.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* The entry point of AFTL validation, Takes a AvbSlotVerifyData
-   struct generated by a prior call to avb_slot_verify and the transparency
-   log's public key and validates the inclusion proof. It does this by
-   performing the following three validation steps for an AFTL
-   descriptor:
-   1. Ensure the vbmeta image hash matches that in the descriptor.
-   2. Ensure the root hash of the Merkle tree matches that in the descriptor.
-   3. Verify the signature using the transparency log public key.
-   It returns  AVB_SLOT_VERIFY_RESULT_OK upon success, and
-   AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION otherwise.
-*/
-
-AvbSlotVerifyResult aftl_slot_verify(AvbSlotVerifyData* asv_data,
-                                     uint8_t* key_bytes,
-                                     size_t key_size);
-
-#ifdef __cplusplus
-}
-#endif
-
+#include "avb_aftl_verify.h"
 #undef AVB_INSIDE_LIBAVB_AFTL_H
 
 #endif /* LIBAVB_AFTL_H_ */
diff --git a/test/avb_aftl_util_unittest.cc b/test/avb_aftl_util_unittest.cc
index 9172995..0d3ba54 100644
--- a/test/avb_aftl_util_unittest.cc
+++ b/test/avb_aftl_util_unittest.cc
@@ -29,10 +29,6 @@
 
 namespace {
 
-#define AFTL_DESCRIPTOR_SIZE 1652ul
-#define AFTL_DESCRIPTOR_MULTI_SIZE 3358ul
-
-const char kAftlLogSigPath[] = "test/data/aftl_log_sig.bin";
 const char kAftlDescriptorPath[] = "test/data/aftl_descriptor.bin";
 const char kAftlDescriptorMultiPath[] = "test/data/aftl_descriptor_multi.bin";
 
@@ -49,31 +45,25 @@
     int64_t aftl_descriptor_size;
 
     BaseAvbToolTest::SetUp();
-    /* Read in test data from the aftl_descriptor and log_sig binaries. */
-    base::GetFileSize(base::FilePath(kAftlLogSigPath), &log_sig_size_);
-    if (log_sig_size_ != AVB_AFTL_SIGNATURE_SIZE) return;
-    log_sig_bytes_ = (uint8_t*)avb_malloc(log_sig_size_);
-    if (!log_sig_bytes_) return;
-    base::ReadFile(
-        base::FilePath(kAftlLogSigPath), (char*)log_sig_bytes_, log_sig_size_);
-
+    /* Read in test data from the aftl_descriptor binaries. */
     base::GetFileSize(base::FilePath(kAftlDescriptorPath),
                       &aftl_descriptor_size);
-    if (aftl_descriptor_size != AFTL_DESCRIPTOR_SIZE) return;
+    ASSERT_GT(aftl_descriptor_size, 0);
     aftl_blob = (uint8_t*)avb_malloc(aftl_descriptor_size);
-    if (!aftl_blob) return;
+    ASSERT_TRUE(aftl_blob != NULL);
     base::ReadFile(base::FilePath(kAftlDescriptorPath),
                    (char*)aftl_blob,
                    aftl_descriptor_size);
     /* Allocate and populate an AftlDescriptor for testing. */
     aftl_descriptor_ = parse_aftl_descriptor(aftl_blob, aftl_descriptor_size);
     avb_free(aftl_blob);
+
     /* Read in test data from the aftl_descriptor file with multiple ICPs. */
     base::GetFileSize(base::FilePath(kAftlDescriptorMultiPath),
                       &aftl_descriptor_size);
-    if (aftl_descriptor_size != AFTL_DESCRIPTOR_MULTI_SIZE) return;
+    ASSERT_GT(aftl_descriptor_size, 0);
     aftl_blob = (uint8_t*)avb_malloc(aftl_descriptor_size);
-    if (!aftl_blob) return;
+    ASSERT_TRUE(aftl_blob != NULL);
     base::ReadFile(base::FilePath(kAftlDescriptorMultiPath),
                    (char*)aftl_blob,
                    aftl_descriptor_size);
@@ -86,64 +76,44 @@
   void TearDown() override {
     free_aftl_descriptor(aftl_descriptor_);
     free_aftl_descriptor(aftl_descriptor_multi_);
-    avb_free(log_sig_bytes_);
     BaseAvbToolTest::TearDown();
   }
 
   void TestAftlIcpHeader(AftlIcpHeader* aftl_header,
-                         uint32_t descriptor_size,
                          uint16_t icp_count) {
     EXPECT_EQ(aftl_header->magic, 0x4c544641ul);
     EXPECT_EQ(aftl_header->required_icp_version_major, 1ul);
     EXPECT_EQ(aftl_header->required_icp_version_minor, 1ul);
-    EXPECT_EQ(aftl_header->aftl_descriptor_size, descriptor_size);
     EXPECT_EQ(aftl_header->icp_count, icp_count);
   }
 
   void TestAftlIcpEntry(AftlIcpEntry* icp_entry) {
     /* Test each field in the AftlIcpEntry. */
-    EXPECT_EQ(icp_entry->log_url_size, 10ul);
-    EXPECT_EQ(icp_entry->leaf_index, 2ul);
-    EXPECT_EQ(icp_entry->log_root_descriptor_size, 61ul);
-    EXPECT_EQ(icp_entry->fw_info_leaf_size, 992ul);
+    EXPECT_GT(icp_entry->log_url_size, 0ul);
+    EXPECT_GT(icp_entry->leaf_index, 1ul);
+    EXPECT_GT(icp_entry->log_root_descriptor_size, 0ul);
+    EXPECT_GT(icp_entry->fw_info_leaf_size, 0ul);
     EXPECT_EQ(icp_entry->log_root_sig_size, AVB_AFTL_SIGNATURE_SIZE);
-    EXPECT_EQ(icp_entry->proof_hash_count, 1);
-    EXPECT_EQ(icp_entry->inc_proof_size, 32ul);
-    EXPECT_EQ(mem_to_hexstring(icp_entry->log_url, 10), "61616161616161616161");
+    EXPECT_GT(icp_entry->proof_hash_count, 0ul);
+    EXPECT_LT(icp_entry->proof_hash_count, 64ul);
+    EXPECT_GT(icp_entry->inc_proof_size, 0ul);
+    EXPECT_EQ(mem_to_hexstring(icp_entry->log_url, 8), "6c6f672e656e6470");
     /* Test the TrillianLogRootDescriptor fields. */
     EXPECT_EQ(icp_entry->log_root_descriptor.version, 1ul);
-    EXPECT_EQ(icp_entry->log_root_descriptor.tree_size, 3ull);
+    EXPECT_GT(icp_entry->log_root_descriptor.tree_size, 0ull);
     EXPECT_EQ(icp_entry->log_root_descriptor.root_hash_size,
               AVB_AFTL_HASH_SIZE);
-    EXPECT_EQ(mem_to_hexstring(icp_entry->log_root_descriptor.root_hash,
-                               AVB_AFTL_HASH_SIZE),
-              "4414e445033df6006bd1f01a14188a79"
-              "1fdd09464edc7016032c9f855f281088");
-    EXPECT_EQ(icp_entry->log_root_descriptor.timestamp, 322325503ull);
-    EXPECT_EQ(icp_entry->log_root_descriptor.revision, 0ull);
+    EXPECT_GT(icp_entry->log_root_descriptor.timestamp, 0ull);
+    EXPECT_GT(icp_entry->log_root_descriptor.revision, 0ull);
     EXPECT_EQ(icp_entry->log_root_descriptor.metadata_size, 0);
     /* Test the FirmwareInfo fields. */
     EXPECT_EQ(icp_entry->fw_info_leaf.vbmeta_hash_size, AVB_AFTL_HASH_SIZE);
-    EXPECT_EQ(
-        mem_to_hexstring(icp_entry->fw_info_leaf.vbmeta_hash,
-                         AVB_AFTL_HASH_SIZE),
-        "992e3ad5d916b8ab4f10d9aa69542983fc681d43cdb2a46f9eb875b8b5242824");
-    /* Test the log_root_signature. */
-    EXPECT_EQ(mem_to_hexstring(icp_entry->log_root_signature,
-                               AVB_AFTL_SIGNATURE_SIZE),
-              mem_to_hexstring(log_sig_bytes_, AVB_AFTL_SIGNATURE_SIZE));
-    /* And finally the proof blob. */
-    EXPECT_EQ(mem_to_hexstring((uint8_t*)icp_entry->proofs,
-                               icp_entry->inc_proof_size),
-              "fac54203e7cc696cf0dfcb42c92a1d9d"
-              "baf70ad9e621f4bd8d98662f00e38255");
+    EXPECT_EQ(icp_entry->proof_hash_count * 32ul, icp_entry->inc_proof_size);
   }
 
  protected:
   AftlDescriptor* aftl_descriptor_;
   AftlDescriptor* aftl_descriptor_multi_;
-  uint8_t* log_sig_bytes_;
-  int64_t log_sig_size_;
 };
 
 TEST_F(AvbAftlUtilTest, AftlIcpHeaderStructure) {
@@ -151,7 +121,7 @@
   ASSERT_NE(aftl_descriptor_, nullptr);
   header = &(aftl_descriptor_->header);
   ASSERT_NE(header, nullptr);
-  TestAftlIcpHeader(header, AFTL_DESCRIPTOR_SIZE, 1);
+  TestAftlIcpHeader(header, 1);
 }
 
 TEST_F(AvbAftlUtilTest, AftlDescriptorMultipleIcps) {
@@ -161,7 +131,7 @@
   ASSERT_NE(aftl_descriptor_multi_, nullptr);
   header = &(aftl_descriptor_multi_->header);
   ASSERT_NE(header, nullptr);
-  TestAftlIcpHeader(header, AFTL_DESCRIPTOR_MULTI_SIZE, 2);
+  TestAftlIcpHeader(header, 2);
 
   for (i = 0; i < header->icp_count; i++) {
     ASSERT_NE(aftl_descriptor_multi_->entries[i], nullptr)
diff --git a/test/avb_aftl_verify_unittest.cc b/test/avb_aftl_verify_unittest.cc
index 884bddc..8eedcd4 100644
--- a/test/avb_aftl_verify_unittest.cc
+++ b/test/avb_aftl_verify_unittest.cc
@@ -27,104 +27,79 @@
 #include <libavb_aftl/libavb_aftl.h>
 
 #include "avb_unittest_util.h"
+#include "fake_avb_ops.h"
 #include "libavb_aftl/avb_aftl_types.h"
 #include "libavb_aftl/avb_aftl_util.h"
 #include "libavb_aftl/avb_aftl_validate.h"
 #include "libavb_aftl/avb_aftl_verify.h"
 
-#define AFTL_DESCRIPTOR_SIZE 3554ul
-#define AFTL_MAGIC "4146544c"
-
 namespace {
 
-const char kAftlDescriptorFindTestBin[] = "test/data/find_aftl_descriptor.bin";
+/* Log transparency key */
 const char kAftlTestKey[] = "test/data/aftl_log_key_bytes.bin";
+/* Regular VBMeta structure without AFTL-specific data */
 const char kVbmetaBin[] = "test/data/aftl_verify_vbmeta.bin";
-const char kAftlBin[] = "test/data/aftl_verify_aftl.bin";
-const char kVbmetaFullBin[] = "test/data/aftl_verify_full.bin";
+/* Full vbmeta partition which contains the VBMeta above followed by its
+ * associated AftlDescriptor */
+const char kVbmetaWithAftlDescBin[] = "test/data/aftl_verify_full.img";
 
 } /* namespace */
 
 namespace avb {
 
 /* Extend BaseAvbToolTest to take advantage of common checks and tooling. */
-class AvbAftlVerifyTest : public BaseAvbToolTest {
+class AvbAftlVerifyTest : public BaseAvbToolTest,
+                          public FakeAvbOpsDelegateWithDefaults {
  public:
   AvbAftlVerifyTest() {}
   ~AvbAftlVerifyTest() {}
   void SetUp() override {
     BaseAvbToolTest::SetUp();
+    ops_.set_delegate(this);
+    ops_.set_partition_dir(base::FilePath("test/data"));
     asv_test_data_ = NULL;
 
     /* Read in the test data. */
-    base::GetFileSize(base::FilePath(kAftlDescriptorFindTestBin),
-                      &blob_with_aftl_size_);
-    blob_with_aftl_ = (uint8_t*)avb_malloc(blob_with_aftl_size_);
-    if (blob_with_aftl_ == NULL) return;
-    base::ReadFile(base::FilePath(kAftlDescriptorFindTestBin),
-                   (char*)blob_with_aftl_,
-                   blob_with_aftl_size_);
-
     base::GetFileSize(base::FilePath(kAftlTestKey), &key_size_);
     key_bytes_ = (uint8_t*)avb_malloc(key_size_);
-    if (key_bytes_ == NULL) {
-      return;
-    }
+    ASSERT_TRUE(key_bytes_ != NULL);
     base::ReadFile(base::FilePath(kAftlTestKey), (char*)key_bytes_, key_size_);
 
-    base::GetFileSize(base::FilePath(kVbmetaBin), &aftl_vbmeta_blob_size_);
-    aftl_vbmeta_blob_ = (uint8_t*)avb_malloc(aftl_vbmeta_blob_size_);
-    if (aftl_vbmeta_blob_ == NULL) {
-      return;
-    }
-    base::ReadFile(base::FilePath(kVbmetaBin),
-                   (char*)aftl_vbmeta_blob_,
-                   aftl_vbmeta_blob_size_);
-
-    base::GetFileSize(base::FilePath(kAftlBin), &aftl_blob_size_);
-    aftl_blob_ = (uint8_t*)avb_malloc(aftl_blob_size_);
-    if (aftl_blob_ == NULL) {
-      return;
-    }
+    base::GetFileSize(base::FilePath(kVbmetaBin), &vbmeta_blob_size_);
+    vbmeta_blob_ = (uint8_t*)avb_malloc(vbmeta_blob_size_);
+    ASSERT_TRUE(vbmeta_blob_ != NULL);
     base::ReadFile(
-        base::FilePath(kAftlBin), (char*)aftl_blob_, aftl_blob_size_);
+        base::FilePath(kVbmetaBin), (char*)vbmeta_blob_, vbmeta_blob_size_);
 
-    base::GetFileSize(base::FilePath(kVbmetaFullBin), &vbmeta_full_blob_size_);
+    base::GetFileSize(base::FilePath(kVbmetaWithAftlDescBin),
+                      &vbmeta_full_blob_size_);
     vbmeta_full_blob_ = (uint8_t*)avb_malloc(vbmeta_full_blob_size_);
-    if (vbmeta_full_blob_ == NULL) {
-      return;
-    }
-    base::ReadFile(base::FilePath(kVbmetaFullBin),
+    ASSERT_TRUE(vbmeta_full_blob_ != NULL);
+    base::ReadFile(base::FilePath(kVbmetaWithAftlDescBin),
                    (char*)vbmeta_full_blob_,
                    vbmeta_full_blob_size_);
 
     /* Set up required parts of asv_test_data */
     asv_test_data_ = (AvbSlotVerifyData*)avb_calloc(sizeof(AvbSlotVerifyData));
-    if (asv_test_data_ == NULL) {
-      return;
-    }
+    ASSERT_TRUE(asv_test_data_ != NULL);
+    asv_test_data_->ab_suffix = (char*)"";
     asv_test_data_->num_vbmeta_images = 1;
     asv_test_data_->vbmeta_images =
         (AvbVBMetaData*)avb_calloc(sizeof(AvbVBMetaData));
-    if (asv_test_data_->vbmeta_images == NULL) {
-      return;
-    }
-    asv_test_data_->vbmeta_images[0].vbmeta_size = vbmeta_full_blob_size_;
+    ASSERT_TRUE(asv_test_data_->vbmeta_images != NULL);
+    asv_test_data_->vbmeta_images[0].vbmeta_size = vbmeta_blob_size_;
     asv_test_data_->vbmeta_images[0].vbmeta_data =
-        (uint8_t*)avb_calloc(asv_test_data_->vbmeta_images[0].vbmeta_size);
-    if (asv_test_data_->vbmeta_images[0].vbmeta_data == NULL) {
-      return;
-    }
+        (uint8_t*)avb_calloc(vbmeta_blob_size_);
+    ASSERT_TRUE(asv_test_data_->vbmeta_images[0].vbmeta_data != NULL);
     memcpy(asv_test_data_->vbmeta_images[0].vbmeta_data,
-           vbmeta_full_blob_,
-           vbmeta_full_blob_size_);
+           vbmeta_blob_,
+           vbmeta_blob_size_);
+    asv_test_data_->vbmeta_images[0].partition_name = (char*)"aftl_verify_full";
   }
 
   void TearDown() override {
-    if (blob_with_aftl_ != NULL) avb_free(blob_with_aftl_);
     if (key_bytes_ != NULL) avb_free(key_bytes_);
-    if (aftl_vbmeta_blob_ != NULL) avb_free(aftl_vbmeta_blob_);
-    if (aftl_blob_ != NULL) avb_free(aftl_blob_);
+    if (vbmeta_blob_ != NULL) avb_free(vbmeta_blob_);
     if (vbmeta_full_blob_ != NULL) avb_free(vbmeta_full_blob_);
     if (asv_test_data_ != NULL) {
       if (asv_test_data_->vbmeta_images != NULL) {
@@ -142,55 +117,31 @@
   AvbSlotVerifyData* asv_test_data_;
   uint8_t* key_bytes_;
   int64_t key_size_;
-  uint8_t* blob_with_aftl_;
-  int64_t blob_with_aftl_size_;
 
-  uint8_t* aftl_vbmeta_blob_;
-  int64_t aftl_vbmeta_blob_size_;
-  uint8_t* aftl_blob_;
-  int64_t aftl_blob_size_;
+  uint8_t* vbmeta_blob_;
+  int64_t vbmeta_blob_size_;
   uint8_t* vbmeta_full_blob_;
   int64_t vbmeta_full_blob_size_;
 };
 
-TEST_F(AvbAftlVerifyTest, AvbAftlFindAftlDescriptor) {
-  uint8_t* aftl_offset;
-  size_t aftl_size;
-
-  aftl_size = aftl_vbmeta_blob_size_;
-  aftl_offset = avb_aftl_find_aftl_descriptor(aftl_vbmeta_blob_, &aftl_size);
-  EXPECT_EQ(aftl_offset, nullptr);
-  EXPECT_EQ(aftl_size, 0ul);
-  aftl_size = vbmeta_full_blob_size_;
-  aftl_offset = avb_aftl_find_aftl_descriptor(vbmeta_full_blob_, &aftl_size);
-  EXPECT_EQ(mem_to_hexstring(aftl_offset, 4), AFTL_MAGIC);
-  EXPECT_EQ(aftl_size, AFTL_DESCRIPTOR_SIZE);
-}
-
-TEST_F(AvbAftlVerifyTest, AvbAftlVerifyDescriptor) {
-  AvbSlotVerifyResult result;
-  result = avb_aftl_verify_descriptor(aftl_vbmeta_blob_,
-                                      aftl_vbmeta_blob_size_,
-                                      aftl_vbmeta_blob_,
-                                      aftl_vbmeta_blob_size_,
-                                      key_bytes_,
-                                      key_size_);
-  EXPECT_EQ(result, AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION);
-
-  result = avb_aftl_verify_descriptor(aftl_vbmeta_blob_,
-                                      aftl_vbmeta_blob_size_,
-                                      aftl_blob_,
-                                      aftl_blob_size_,
-                                      key_bytes_,
-                                      key_size_);
-
-  EXPECT_EQ(result, AVB_SLOT_VERIFY_RESULT_OK);
-}
-
-TEST_F(AvbAftlVerifyTest, AftlSlotVerify) {
+TEST_F(AvbAftlVerifyTest, Basic) {
   AvbSlotVerifyResult result =
-      aftl_slot_verify(asv_test_data_, key_bytes_, key_size_);
+      aftl_slot_verify(ops_.avb_ops(), asv_test_data_, key_bytes_, key_size_);
   EXPECT_EQ(result, AVB_SLOT_VERIFY_RESULT_OK);
 }
 
+TEST_F(AvbAftlVerifyTest, MissingAFTLDescriptor) {
+  asv_test_data_->vbmeta_images[0].partition_name = (char*)"do-no-exist";
+  AvbSlotVerifyResult result =
+      aftl_slot_verify(ops_.avb_ops(), asv_test_data_, key_bytes_, key_size_);
+  EXPECT_EQ(result, AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA);
+}
+
+TEST_F(AvbAftlVerifyTest, NonMatchingVBMeta) {
+  asv_test_data_->vbmeta_images[0].vbmeta_data[0] = 'X';
+  AvbSlotVerifyResult result =
+      aftl_slot_verify(ops_.avb_ops(), asv_test_data_, key_bytes_, key_size_);
+  EXPECT_EQ(result, AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION);
+}
+
 } /* namespace avb */
diff --git a/test/avb_slot_verify_unittest.cc b/test/avb_slot_verify_unittest.cc
index 28ec151..6d4adac 100644
--- a/test/avb_slot_verify_unittest.cc
+++ b/test/avb_slot_verify_unittest.cc
@@ -580,6 +580,7 @@
       "Header Block:             256 bytes\n"
       "Authentication Block:     320 bytes\n"
       "Auxiliary Block:          896 bytes\n"
+      "Public key (sha1):        cdbb77177f731920bbe0a0f94f84d9038ae0617d\n"
       "Algorithm:                SHA256_RSA2048\n"
       "Rollback Index:           4\n"
       "Flags:                    0\n"
@@ -860,6 +861,7 @@
       "Header Block:             256 bytes\n"
       "Authentication Block:     320 bytes\n"
       "Auxiliary Block:          1728 bytes\n"
+      "Public key (sha1):        cdbb77177f731920bbe0a0f94f84d9038ae0617d\n"
       "Algorithm:                SHA256_RSA2048\n"
       "Rollback Index:           11\n"
       "Flags:                    0\n"
@@ -886,6 +888,7 @@
       "Header Block:             256 bytes\n"
       "Authentication Block:     576 bytes\n"
       "Auxiliary Block:          1280 bytes\n"
+      "Public key (sha1):        2597c218aae470a130f61162feaae70afd97f011\n"
       "Algorithm:                SHA256_RSA4096\n"
       "Rollback Index:           12\n"
       "Flags:                    0\n"
@@ -1055,6 +1058,7 @@
       "Header Block:             256 bytes\n"
       "Authentication Block:     320 bytes\n"
       "Auxiliary Block:          1728 bytes\n"
+      "Public key (sha1):        cdbb77177f731920bbe0a0f94f84d9038ae0617d\n"
       "Algorithm:                SHA256_RSA2048\n"
       "Rollback Index:           11\n"
       "Flags:                    0\n"
@@ -1075,6 +1079,7 @@
       "Header Block:             256 bytes\n"
       "Authentication Block:     576 bytes\n"
       "Auxiliary Block:          1280 bytes\n"
+      "Public key (sha1):        2597c218aae470a130f61162feaae70afd97f011\n"
       "Algorithm:                SHA256_RSA4096\n"
       "Rollback Index:           12\n"
       "Flags:                    0\n"
@@ -1454,6 +1459,7 @@
       "Header Block:             256 bytes\n"
       "Authentication Block:     320 bytes\n"
       "Auxiliary Block:          1728 bytes\n"
+      "Public key (sha1):        cdbb77177f731920bbe0a0f94f84d9038ae0617d\n"
       "Algorithm:                SHA256_RSA2048\n"
       "Rollback Index:           11\n"
       "Flags:                    0\n"
@@ -1568,6 +1574,7 @@
       "Header Block:             256 bytes\n"
       "Authentication Block:     320 bytes\n"
       "Auxiliary Block:          896 bytes\n"
+      "Public key (sha1):        cdbb77177f731920bbe0a0f94f84d9038ae0617d\n"
       "Algorithm:                SHA256_RSA2048\n"
       "Rollback Index:           4\n"
       "Flags:                    0\n"
@@ -1681,6 +1688,7 @@
       "Header Block:             256 bytes\n"
       "Authentication Block:     320 bytes\n"
       "Auxiliary Block:          896 bytes\n"
+      "Public key (sha1):        cdbb77177f731920bbe0a0f94f84d9038ae0617d\n"
       "Algorithm:                SHA256_RSA2048\n"
       "Rollback Index:           4\n"
       "Flags:                    0\n"
@@ -1928,6 +1936,7 @@
           "Header Block:             256 bytes\n"
           "Authentication Block:     320 bytes\n"
           "Auxiliary Block:          960 bytes\n"
+          "Public key (sha1):        cdbb77177f731920bbe0a0f94f84d9038ae0617d\n"
           "Algorithm:                SHA256_RSA2048\n"
           "Rollback Index:           4\n"
           "Flags:                    %d\n"
@@ -2049,6 +2058,7 @@
       "Header Block:             256 bytes\n"
       "Authentication Block:     320 bytes\n"
       "Auxiliary Block:          1088 bytes\n"
+      "Public key (sha1):        cdbb77177f731920bbe0a0f94f84d9038ae0617d\n"
       "Algorithm:                SHA256_RSA2048\n"
       "Rollback Index:           0\n"
       "Flags:                    0\n"
@@ -2108,6 +2118,8 @@
                          "Header Block:             256 bytes\n"
                          "Authentication Block:     320 bytes\n"
                          "Auxiliary Block:          1216 bytes\n"
+                         "Public key (sha1):        "
+                         "cdbb77177f731920bbe0a0f94f84d9038ae0617d\n"
                          "Algorithm:                SHA256_RSA2048\n"
                          "Rollback Index:           4\n"
                          "Flags:                    %d\n"
@@ -2244,6 +2256,7 @@
           "Header Block:             256 bytes\n"
           "Authentication Block:     320 bytes\n"
           "Auxiliary Block:          960 bytes\n"
+          "Public key (sha1):        cdbb77177f731920bbe0a0f94f84d9038ae0617d\n"
           "Algorithm:                SHA256_RSA2048\n"
           "Rollback Index:           4\n"
           "Flags:                    %d\n"
@@ -2468,6 +2481,7 @@
       "Header Block:             256 bytes\n"
       "Authentication Block:     320 bytes\n"
       "Auxiliary Block:          2624 bytes\n"
+      "Public key (sha1):        cdbb77177f731920bbe0a0f94f84d9038ae0617d\n"
       "Algorithm:                SHA256_RSA2048\n"
       "Rollback Index:           0\n"
       "Flags:                    2147483648\n"
@@ -2908,6 +2922,8 @@
                                  "Header Block:             256 bytes\n"
                                  "Authentication Block:     320 bytes\n"
                                  "Auxiliary Block:          704 bytes\n"
+                                 "Public key (sha1):        "
+                                 "cdbb77177f731920bbe0a0f94f84d9038ae0617d\n"
                                  "Algorithm:                SHA256_RSA2048\n"
                                  "Rollback Index:           0\n"
                                  "Flags:                    0\n"
@@ -2967,6 +2983,8 @@
                                  "Header Block:             256 bytes\n"
                                  "Authentication Block:     320 bytes\n"
                                  "Auxiliary Block:          832 bytes\n"
+                                 "Public key (sha1):        "
+                                 "cdbb77177f731920bbe0a0f94f84d9038ae0617d\n"
                                  "Algorithm:                SHA256_RSA2048\n"
                                  "Rollback Index:           0\n"
                                  "Flags:                    0\n"
diff --git a/test/avbtool_unittest.cc b/test/avbtool_unittest.cc
index 42f6f4d..0d8e1eb 100644
--- a/test/avbtool_unittest.cc
+++ b/test/avbtool_unittest.cc
@@ -356,6 +356,7 @@
       "Header Block:             256 bytes\n"
       "Authentication Block:     320 bytes\n"
       "Auxiliary Block:          3200 bytes\n"
+      "Public key (sha1):        cdbb77177f731920bbe0a0f94f84d9038ae0617d\n"
       "Algorithm:                SHA256_RSA2048\n"
       "Rollback Index:           0\n"
       "Flags:                    0\n"
@@ -397,6 +398,7 @@
       "Header Block:             256 bytes\n"
       "Authentication Block:     320 bytes\n"
       "Auxiliary Block:          704 bytes\n"
+      "Public key (sha1):        cdbb77177f731920bbe0a0f94f84d9038ae0617d\n"
       "Algorithm:                SHA256_RSA2048\n"
       "Rollback Index:           0\n"
       "Flags:                    0\n"
@@ -477,6 +479,7 @@
         "Header Block:             256 bytes\n"
         "Authentication Block:     320 bytes\n"
         "Auxiliary Block:          704 bytes\n"
+        "Public key (sha1):        cdbb77177f731920bbe0a0f94f84d9038ae0617d\n"
         "Algorithm:                SHA256_RSA2048\n"
         "Rollback Index:           0\n"
         "Flags:                    0\n"
@@ -698,6 +701,7 @@
       "Header Block:             256 bytes\n"
       "Authentication Block:     320 bytes\n"
       "Auxiliary Block:          704 bytes\n"
+      "Public key (sha1):        cdbb77177f731920bbe0a0f94f84d9038ae0617d\n"
       "Algorithm:                SHA256_RSA2048\n"
       "Rollback Index:           0\n"
       "Flags:                    0\n"
@@ -783,6 +787,7 @@
       "Header Block:             256 bytes\n"
       "Authentication Block:     320 bytes\n"
       "Auxiliary Block:          704 bytes\n"
+      "Public key (sha1):        cdbb77177f731920bbe0a0f94f84d9038ae0617d\n"
       "Algorithm:                SHA256_RSA2048\n"
       "Rollback Index:           0\n"
       "Flags:                    0\n"
@@ -825,6 +830,7 @@
       "Header Block:             256 bytes\n"
       "Authentication Block:     320 bytes\n"
       "Auxiliary Block:          704 bytes\n"
+      "Public key (sha1):        cdbb77177f731920bbe0a0f94f84d9038ae0617d\n"
       "Algorithm:                SHA256_RSA2048\n"
       "Rollback Index:           0\n"
       "Flags:                    0\n"
@@ -869,6 +875,7 @@
       "Header Block:             256 bytes\n"
       "Authentication Block:     320 bytes\n"
       "Auxiliary Block:          704 bytes\n"
+      "Public key (sha1):        cdbb77177f731920bbe0a0f94f84d9038ae0617d\n"
       "Algorithm:                SHA256_RSA2048\n"
       "Rollback Index:           0\n"
       "Flags:                    0\n"
@@ -939,6 +946,8 @@
                                  "Header Block:             256 bytes\n"
                                  "Authentication Block:     320 bytes\n"
                                  "Auxiliary Block:          768 bytes\n"
+                                 "Public key (sha1):        "
+                                 "cdbb77177f731920bbe0a0f94f84d9038ae0617d\n"
                                  "Algorithm:                SHA256_RSA2048\n"
                                  "Rollback Index:           0\n"
                                  "Flags:                    0\n"
@@ -968,6 +977,7 @@
         "Header Block:             256 bytes\n"
         "Authentication Block:     320 bytes\n"
         "Auxiliary Block:          768 bytes\n"
+        "Public key (sha1):        cdbb77177f731920bbe0a0f94f84d9038ae0617d\n"
         "Algorithm:                SHA256_RSA2048\n"
         "Rollback Index:           0\n"
         "Flags:                    0\n"
@@ -1164,6 +1174,7 @@
       "Header Block:             256 bytes\n"
       "Authentication Block:     320 bytes\n"
       "Auxiliary Block:          896 bytes\n"
+      "Public key (sha1):        cdbb77177f731920bbe0a0f94f84d9038ae0617d\n"
       "Algorithm:                SHA256_RSA2048\n"
       "Rollback Index:           0\n"
       "Flags:                    0\n"
@@ -1273,6 +1284,8 @@
                                  "Header Block:             256 bytes\n"
                                  "Authentication Block:     320 bytes\n"
                                  "Auxiliary Block:          768 bytes\n"
+                                 "Public key (sha1):        "
+                                 "cdbb77177f731920bbe0a0f94f84d9038ae0617d\n"
                                  "Algorithm:                SHA256_RSA2048\n"
                                  "Rollback Index:           0\n"
                                  "Flags:                    0\n"
@@ -1444,6 +1457,7 @@
       "Header Block:             256 bytes\n"
       "Authentication Block:     320 bytes\n"
       "Auxiliary Block:          960 bytes\n"
+      "Public key (sha1):        cdbb77177f731920bbe0a0f94f84d9038ae0617d\n"
       "Algorithm:                SHA256_RSA2048\n"
       "Rollback Index:           0\n"
       "Flags:                    0\n"
@@ -1598,6 +1612,7 @@
       "Header Block:             256 bytes\n"
       "Authentication Block:     576 bytes\n"
       "Auxiliary Block:          1280 bytes\n"
+      "Public key (sha1):        2597c218aae470a130f61162feaae70afd97f011\n"
       "Algorithm:                SHA512_RSA4096\n"
       "Rollback Index:           0\n"
       "Flags:                    0\n"
@@ -1648,6 +1663,7 @@
       "Header Block:             256 bytes\n"
       "Authentication Block:     320 bytes\n"
       "Auxiliary Block:          768 bytes\n"
+      "Public key (sha1):        cdbb77177f731920bbe0a0f94f84d9038ae0617d\n"
       "Algorithm:                SHA256_RSA2048\n"
       "Rollback Index:           0\n"
       "Flags:                    0\n"
@@ -1698,6 +1714,7 @@
       "Header Block:             256 bytes\n"
       "Authentication Block:     320 bytes\n"
       "Auxiliary Block:          768 bytes\n"
+      "Public key (sha1):        cdbb77177f731920bbe0a0f94f84d9038ae0617d\n"
       "Algorithm:                SHA256_RSA2048\n"
       "Rollback Index:           0\n"
       "Flags:                    0\n"
@@ -1750,6 +1767,7 @@
       "Header Block:             256 bytes\n"
       "Authentication Block:     320 bytes\n"
       "Auxiliary Block:          768 bytes\n"
+      "Public key (sha1):        cdbb77177f731920bbe0a0f94f84d9038ae0617d\n"
       "Algorithm:                SHA256_RSA2048\n"
       "Rollback Index:           0\n"
       "Flags:                    0\n"
@@ -1798,6 +1816,7 @@
       "Header Block:             256 bytes\n"
       "Authentication Block:     320 bytes\n"
       "Auxiliary Block:          768 bytes\n"
+      "Public key (sha1):        cdbb77177f731920bbe0a0f94f84d9038ae0617d\n"
       "Algorithm:                SHA256_RSA2048\n"
       "Rollback Index:           0\n"
       "Flags:                    0\n"
@@ -1861,6 +1880,7 @@
       "Header Block:             256 bytes\n"
       "Authentication Block:     320 bytes\n"
       "Auxiliary Block:          640 bytes\n"
+      "Public key (sha1):        cdbb77177f731920bbe0a0f94f84d9038ae0617d\n"
       "Algorithm:                SHA256_RSA2048\n"
       "Rollback Index:           0\n"
       "Flags:                    0\n"
@@ -1985,6 +2005,7 @@
       "Header Block:             256 bytes\n"
       "Authentication Block:     320 bytes\n"
       "Auxiliary Block:          1216 bytes\n"
+      "Public key (sha1):        cdbb77177f731920bbe0a0f94f84d9038ae0617d\n"
       "Algorithm:                SHA256_RSA2048\n"
       "Rollback Index:           0\n"
       "Flags:                    0\n"
@@ -2037,6 +2058,7 @@
       "Header Block:             256 bytes\n"
       "Authentication Block:     320 bytes\n"
       "Auxiliary Block:          1280 bytes\n"
+      "Public key (sha1):        cdbb77177f731920bbe0a0f94f84d9038ae0617d\n"
       "Algorithm:                SHA256_RSA2048\n"
       "Rollback Index:           0\n"
       "Flags:                    0\n"
@@ -2202,6 +2224,7 @@
       "Header Block:             256 bytes\n"
       "Authentication Block:     320 bytes\n"
       "Auxiliary Block:          1152 bytes\n"
+      "Public key (sha1):        cdbb77177f731920bbe0a0f94f84d9038ae0617d\n"
       "Algorithm:                SHA256_RSA2048\n"
       "Rollback Index:           0\n"
       "Flags:                    0\n"
@@ -2315,6 +2338,7 @@
       "Header Block:             256 bytes\n"
       "Authentication Block:     320 bytes\n"
       "Auxiliary Block:          576 bytes\n"
+      "Public key (sha1):        cdbb77177f731920bbe0a0f94f84d9038ae0617d\n"
       "Algorithm:                SHA256_RSA2048\n"
       "Rollback Index:           0\n"
       "Flags:                    0\n"
diff --git a/test/data/aftl_descriptor.bin b/test/data/aftl_descriptor.bin
index 60e2a21..1e6e65a 100644
--- a/test/data/aftl_descriptor.bin
+++ b/test/data/aftl_descriptor.bin
Binary files differ
diff --git a/test/data/aftl_descriptor_multi.bin b/test/data/aftl_descriptor_multi.bin
index 3658771..9a16421 100644
--- a/test/data/aftl_descriptor_multi.bin
+++ b/test/data/aftl_descriptor_multi.bin
Binary files differ
diff --git a/test/data/aftl_verify_aftl.bin b/test/data/aftl_verify_aftl.bin
deleted file mode 100644
index f2eecef..0000000
--- a/test/data/aftl_verify_aftl.bin
+++ /dev/null
Binary files differ
diff --git a/test/data/aftl_verify_full.bin b/test/data/aftl_verify_full.img
similarity index 100%
rename from test/data/aftl_verify_full.bin
rename to test/data/aftl_verify_full.img
Binary files differ