Snap for 10447354 from d70d0c6b71a02628aa75193ca3c2e25d2994fed1 to mainline-networking-release

Change-Id: I61a282c630827ae6b8b2ec695ea67d724ae7b75e
diff --git a/Android.bp b/Android.bp
index b73a924..b4660f8 100644
--- a/Android.bp
+++ b/Android.bp
@@ -114,9 +114,6 @@
     local_include_dirs: [
         "libavb/boringssl",
     ],
-    shared_libs: [
-        "libcrypto",
-    ],
 }
 
 cc_defaults {
@@ -130,40 +127,49 @@
     ],
 }
 
+python_library_host {
+    name: "libavbtool",
+    srcs: ["avbtool.py"],
+}
+
 python_binary_host {
     name: "avbtool",
     srcs: ["avbtool.py"],
     main: "avbtool.py",
     required: ["fec"],
     version: {
-        py2: {
-            enabled: false,
-        },
         py3: {
-            enabled: true,
             embedded_launcher: true,
         },
     },
     compile_multilib: "first",
 }
 
-// Build libavb - this is a static library that depends
-// on only libc and libcrypto, but no other dependencies.
-cc_library_static {
-    name: "libavb",
+cc_defaults {
+    name: "libavb_defaults",
     defaults: [
         "avb_defaults",
         "avb_sources",
         "avb_crypto_ops_impl_boringssl",
     ],
-    host_supported: true,
-    ramdisk_available: true,
-    vendor_ramdisk_available: true,
-    recovery_available: true,
     header_libs: [
         "avb_headers",
     ],
     export_header_lib_headers: ["avb_headers"],
+}
+
+// Build libavb - this is a static library that depends
+// on only libc and libcrypto, but no other dependencies.
+cc_library_static {
+    name: "libavb",
+    defaults: ["libavb_defaults"],
+    host_supported: true,
+    ramdisk_available: true,
+    vendor_ramdisk_available: true,
+    recovery_available: true,
+    shared_libs: [
+        "libcrypto",
+    ],
     target: {
         linux: {
             srcs: ["libavb/avb_sysdeps_posix.c"],
@@ -174,6 +180,19 @@
     },
 }
 
+// A variant of the library that can run in baremetal environments.
+//
+// The debug feature isn't enabled, removing verbose logging and assertions.
+cc_library_static {
+    name: "libavb_baremetal",
+    defaults: ["libavb_defaults"],
+    cflags: ["-UAVB_ENABLE_DEBUG"],
+    static_libs: [
+        "libcrypto_baremetal",
+    ],
+    srcs: ["libavb/avb_sysdeps_posix.c"],
+}
+
 // Build libavb_user for the target - in addition to libavb, it
 // includes libavb_ab, libavb_user and also depends on libbase and
 // libfs_mgr.
@@ -189,7 +208,10 @@
         "avb_headers",
     ],
     export_header_lib_headers: ["avb_headers"],
-    shared_libs: ["libbase"],
+    shared_libs: [
+        "libbase",
+        "libcrypto",
+    ],
     static_libs: ["libfs_mgr"],
     cflags: [
         "-DAVB_AB_I_UNDERSTAND_LIBAVB_AB_IS_DEPRECATED",
@@ -269,7 +291,7 @@
     },
     compile_multilib: "first",
     data: [
-        "avbtool",
+        "avbtool.py",
         "test/avbtool_signing_helper_test.py",
         "test/avbtool_signing_helper_with_files_test.py",
         "test/data/*",
diff --git a/README.md b/README.md
index a293cb0..9b51426 100644
--- a/README.md
+++ b/README.md
@@ -30,6 +30,7 @@
       + [Booting Into Recovery](#Booting-Into-Recovery)
     + [Handling dm-verity Errors](#Handling-dm_verity-Errors)
     + [Android Specific Integration](#Android-Specific-Integration)
+    + [GKI 2.0 Integration](#GKI-2_0-Integration)
     + [Device Specific Notes](#Device-Specific-Notes)
 * [Version History](#Version-History)
 
@@ -622,11 +623,11 @@
 variable AVB_INVOCATION_LOGFILE with the name of the log file:
 
     $ export AVB_INVOCATION_LOGFILE='/tmp/avb_invocation.log'
-    $ ./avbtool version
-    $ ./avbtool version
+    $ ./avbtool.py version
+    $ ./avbtool.py version
     $ cat /tmp/avb_invocation.log
-    ./avbtool version
-    ./avbtool version
+    ./avbtool.py version
+    ./avbtool.py version
 
 
 ## Build System Integration
@@ -1089,6 +1090,35 @@
 * **yellow**: If in LOCKED state and the key used for verification was set by the end user.
 * **orange**: If in the UNLOCKED state.
 
+## GKI 2.0 Integration
+
+Starting from Android 12, devices launching with kernel version 5.10 or higher
+must ship with the GKI kernel. See [GKI 2.0](https://source.android.com/devices/architecture/kernel/generic-kernel-image#gki2)
+for details.
+
+While incorporating a certified GKI `boot.img` into a device codebase, the
+following board variables should be configured. The setting shown below is just
+an example to be adjusted per device.
+
+```
+# Uses a prebuilt boot.img
+TARGET_NO_KERNEL := true
+BOARD_PREBUILT_BOOTIMAGE := device/${company}/${board}/boot.img
+
+# Enables chained vbmeta for the boot.img so it can be updated independently,
+# without updating the vbmeta.img. The following configs are optional.
+# When they're absent, the hash of the boot.img will be stored then signed in
+# the vbmeta.img.
+BOARD_AVB_BOOT_KEY_PATH := external/avb/test/data/testkey_rsa4096.pem
+BOARD_AVB_BOOT_ALGORITHM := SHA256_RSA4096
+BOARD_AVB_BOOT_ROLLBACK_INDEX := $(PLATFORM_SECURITY_PATCH_TIMESTAMP)
+BOARD_AVB_BOOT_ROLLBACK_INDEX_LOCATION := 2
+```
+
+**NOTE**: The certified GKI `boot.img` isn't signed for verified boot.
+A device-specific verified boot chain should still be configured for a prebuilt
+GKI `boot.img`.
+
 ## Device Specific Notes
 
 This section contains information about how AVB is integrated into specific
diff --git a/avbtool b/avbtool
deleted file mode 120000
index 5f6383e..0000000
--- a/avbtool
+++ /dev/null
@@ -1 +0,0 @@
-avbtool.py
\ No newline at end of file
diff --git a/avbtool.py b/avbtool.py
index f944af4..67416d4 100755
--- a/avbtool.py
+++ b/avbtool.py
@@ -930,18 +930,22 @@
                                   struct.calcsize(ImageChunk.FORMAT)))
     self._read_header()
 
-  def append_raw(self, data):
+  def append_raw(self, data, multiple_block_size=True):
     """Appends a RAW chunk to the sparse file.
 
-    The length of the given data must be a multiple of the block size.
+    The length of the given data must be a multiple of the block size,
+    unless |multiple_block_size| is False.
 
     Arguments:
       data: Data to append as bytes.
+      multiple_block_size: whether to check the length of the
+        data is a multiple of the block size.
 
     Raises:
       OSError: If ImageHandler was initialized in read-only mode.
     """
-    assert len(data) % self.block_size == 0
+    if multiple_block_size:
+      assert len(data) % self.block_size == 0
 
     if self._read_only:
       raise OSError('ImageHandler is in read-only mode.')
@@ -3684,7 +3688,12 @@
       # Ensure image is multiple of block_size.
       rounded_image_size = round_to_multiple(image.image_size, block_size)
       if rounded_image_size > image.image_size:
-        image.append_raw('\0' * (rounded_image_size - image.image_size))
+        # If we need to round up the image size, it means the length of the
+        # data to append is not a multiple of block size.
+        # Setting multiple_block_size to false, so append_raw() will not
+        # require it.
+        image.append_raw(b'\0' * (rounded_image_size - image.image_size),
+                         multiple_block_size=False)
 
       # If image size exceeds the maximum image size, fail.
       if partition_size > 0:
@@ -3753,7 +3762,8 @@
       padding_needed = (round_to_multiple(len(hash_tree), image.block_size) -
                         len(hash_tree))
       hash_tree_with_padding = hash_tree + b'\0' * padding_needed
-      image.append_raw(hash_tree_with_padding)
+      if len(hash_tree_with_padding) > 0:
+        image.append_raw(hash_tree_with_padding)
       len_hashtree_and_fec = len(hash_tree_with_padding)
 
       # Generate FEC codes, if requested.
diff --git a/boot_control/boot_control_avb.c b/boot_control/boot_control_avb.c
index a4bdfe9..34bf13d 100644
--- a/boot_control/boot_control_avb.c
+++ b/boot_control/boot_control_avb.c
@@ -58,7 +58,7 @@
   } else if (strcmp(propbuf, "_b") == 0) {
     return 1;
   } else {
-    avb_errorv("Unexpected slot suffix '", propbuf, "'.\n", NULL);
+    avb_error("Unexpected slot suffix '", propbuf, "'.\n");
     return 0;
   }
   return 0;
diff --git a/examples/uefi/main.c b/examples/uefi/main.c
index 01dae48..887ac08 100644
--- a/examples/uefi/main.c
+++ b/examples/uefi/main.c
@@ -103,10 +103,9 @@
       }
       boot_result =
           uefi_avb_boot_kernel(ImageHandle, slot_data, additional_cmdline);
-      avb_fatalv("uefi_avb_boot_kernel() failed with error ",
-                 uefi_avb_boot_kernel_result_to_string(boot_result),
-                 "\n",
-                 NULL);
+      avb_fatal("uefi_avb_boot_kernel() failed with error ",
+                uefi_avb_boot_kernel_result_to_string(boot_result),
+                "\n");
       avb_slot_verify_data_free(slot_data);
       avb_free(additional_cmdline);
       break;
diff --git a/examples/uefi/uefi_avb_boot.c b/examples/uefi/uefi_avb_boot.c
index 800c9a1..d79d899 100644
--- a/examples/uefi/uefi_avb_boot.c
+++ b/examples/uefi/uefi_avb_boot.c
@@ -142,8 +142,7 @@
 
   boot = &slot_data->loaded_partitions[0];
   if (avb_strcmp(boot->partition_name, "boot") != 0) {
-    avb_errorv(
-        "Unexpected partition name '", boot->partition_name, "'.\n", NULL);
+    avb_error("Unexpected partition name '", boot->partition_name, "'.\n");
     ret = UEFI_AVB_BOOT_KERNEL_RESULT_ERROR_PARTITION_INVALID_FORMAT;
     goto out;
   }
diff --git a/libavb/avb_slot_verify.c b/libavb/avb_slot_verify.c
index 8e0721d..3f6007d 100644
--- a/libavb/avb_slot_verify.c
+++ b/libavb/avb_slot_verify.c
@@ -43,6 +43,9 @@
 /* Maximum size of a vbmeta image - 64 KiB. */
 #define VBMETA_MAX_SIZE (64 * 1024)
 
+/* Test buffer used to check the existence of a partition. */
+#define TEST_BUFFER_SIZE 1
+
 static AvbSlotVerifyResult initialize_persistent_digest(
     AvbOps* ops,
     const char* part_name,
@@ -89,7 +92,7 @@
   /* We are going to implicitly cast image_size from uint64_t to size_t in the
    * following code, so we need to make sure that the cast is safe. */
   if (image_size != (size_t)(image_size)) {
-    avb_errorv(part_name, ": Partition size too large to load.\n", NULL);
+    avb_error(part_name, ": Partition size too large to load.\n");
     return AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
   }
 
@@ -100,14 +103,14 @@
     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 data from partition.\n", NULL);
+      avb_error(part_name, ": Error loading data from partition.\n");
       return AVB_SLOT_VERIFY_RESULT_ERROR_IO;
     }
 
     if (*out_image_buf != NULL) {
       *out_image_preloaded = true;
       if (part_num_read != image_size) {
-        avb_errorv(part_name, ": Read incorrect number of bytes.\n", NULL);
+        avb_error(part_name, ": Read incorrect number of bytes.\n");
         return AVB_SLOT_VERIFY_RESULT_ERROR_IO;
       }
     }
@@ -129,11 +132,11 @@
     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 data from partition.\n", NULL);
+      avb_error(part_name, ": Error loading data from partition.\n");
       return AVB_SLOT_VERIFY_RESULT_ERROR_IO;
     }
     if (part_num_read != image_size) {
-      avb_errorv(part_name, ": Read incorrect number of bytes.\n", NULL);
+      avb_error(part_name, ": Read incorrect number of bytes.\n");
       return AVB_SLOT_VERIFY_RESULT_ERROR_IO;
     }
   }
@@ -167,7 +170,7 @@
   size_t stored_digest_size = 0;
 
   if (ops->read_persistent_value == NULL) {
-    avb_errorv(part_name, ": Persistent values are not implemented.\n", NULL);
+    avb_error(part_name, ": Persistent values are not implemented.\n");
     return AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
   }
   persistent_value_name =
@@ -204,19 +207,17 @@
   } else if (io_ret == AVB_IO_RESULT_ERROR_NO_SUCH_VALUE) {
     // Treat a missing persistent value as a verification error, which is
     // ignoreable, rather than a metadata error which is not.
-    avb_errorv(part_name, ": Persistent digest does not exist.\n", NULL);
+    avb_error(part_name, ": Persistent digest does not exist.\n");
     return AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION;
   } else if (io_ret == AVB_IO_RESULT_ERROR_INVALID_VALUE_SIZE ||
              io_ret == AVB_IO_RESULT_ERROR_INSUFFICIENT_SPACE) {
-    avb_errorv(
-        part_name, ": Persistent digest is not of expected size.\n", NULL);
+    avb_error(part_name, ": Persistent digest is not of expected size.\n");
     return AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
   } else if (io_ret != AVB_IO_RESULT_OK) {
-    avb_errorv(part_name, ": Error reading persistent digest.\n", NULL);
+    avb_error(part_name, ": Error reading persistent digest.\n");
     return AVB_SLOT_VERIFY_RESULT_ERROR_IO;
   } else if (expected_digest_size != stored_digest_size) {
-    avb_errorv(
-        part_name, ": Persistent digest is not of expected size.\n", NULL);
+    avb_error(part_name, ": Persistent digest is not of expected size.\n");
     return AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
   }
   return AVB_SLOT_VERIFY_RESULT_OK;
@@ -242,23 +243,21 @@
   }
 
   if (is_device_unlocked) {
-    avb_debugv(part_name,
-               ": Digest does not exist, device unlocked so not initializing "
-               "digest.\n",
-               NULL);
+    avb_debug(part_name,
+              ": Digest does not exist, device unlocked so not initializing "
+              "digest.\n");
     return AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION;
   }
 
   // Device locked; initialize digest with given initial value.
-  avb_debugv(part_name,
-             ": Digest does not exist, initializing persistent digest.\n",
-             NULL);
+  avb_debug(part_name,
+            ": Digest does not exist, initializing persistent digest.\n");
   io_ret = ops->write_persistent_value(
       ops, persistent_value_name, digest_size, initial_digest);
   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 initializing persistent digest.\n", NULL);
+    avb_error(part_name, ": Error initializing persistent digest.\n");
     return AVB_SLOT_VERIFY_RESULT_ERROR_IO;
   }
 
@@ -268,9 +267,8 @@
   // initial_digest ensures that this will not recurse again.
   ret = read_persistent_digest(ops, part_name, digest_size, NULL, out_digest);
   if (ret != AVB_SLOT_VERIFY_RESULT_OK) {
-    avb_errorv(part_name,
-               ": Reading back initialized persistent digest failed!\n",
-               NULL);
+    avb_error(part_name,
+              ": Reading back initialized persistent digest failed!\n");
   }
   return ret;
 }
@@ -373,11 +371,11 @@
       ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
       goto out;
     } else if (io_ret != AVB_IO_RESULT_OK) {
-      avb_errorv(part_name, ": Error determining partition size.\n", NULL);
+      avb_error(part_name, ": Error determining partition size.\n");
       ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
       goto out;
     }
-    avb_debugv(part_name, ": Loading entire partition.\n", NULL);
+    avb_debug(part_name, ": Loading entire partition.\n");
   }
 
   ret = load_full_partition(
@@ -409,14 +407,14 @@
     digest = avb_sha512_final(&sha512_ctx);
     digest_len = AVB_SHA512_DIGEST_SIZE;
   } else {
-    avb_errorv(part_name, ": Unsupported hash algorithm.\n", NULL);
+    avb_error(part_name, ": Unsupported hash algorithm.\n");
     ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
     goto out;
   }
 
   if (hash_desc.digest_len == 0) {
     /* Expect a match to a persistent digest. */
-    avb_debugv(part_name, ": No digest, using persistent digest.\n", NULL);
+    avb_debug(part_name, ": No digest, using persistent digest.\n");
     expected_digest_len = digest_len;
     expected_digest = expected_digest_buf;
     avb_assert(expected_digest_len <= sizeof(expected_digest_buf));
@@ -435,16 +433,14 @@
   }
 
   if (digest_len != expected_digest_len) {
-    avb_errorv(
-        part_name, ": Digest in descriptor not of expected size.\n", NULL);
+    avb_error(part_name, ": Digest in descriptor not of expected size.\n");
     ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
     goto out;
   }
 
   if (avb_safe_memcmp(digest, expected_digest, digest_len) != 0) {
-    avb_errorv(part_name,
-               ": Hash of data does not match digest in descriptor.\n",
-               NULL);
+    avb_error(part_name,
+              ": Hash of data does not match digest in descriptor.\n");
     ret = AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION;
     goto out;
   }
@@ -458,7 +454,7 @@
       image_buf != NULL) {
     AvbPartitionData* loaded_partition;
     if (slot_data->num_loaded_partitions == MAX_NUMBER_OF_LOADED_PARTITIONS) {
-      avb_errorv(part_name, ": Too many loaded partitions.\n", NULL);
+      avb_error(part_name, ": Too many loaded partitions.\n");
       ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
       goto fail;
     }
@@ -511,11 +507,11 @@
       ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
       goto out;
     } else if (io_ret != AVB_IO_RESULT_OK) {
-      avb_errorv(part_name, ": Error determining partition size.\n", NULL);
+      avb_error(part_name, ": Error determining partition size.\n");
       ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
       goto out;
     }
-    avb_debugv(part_name, ": Loading entire partition.\n", NULL);
+    avb_debug(part_name, ": Loading entire partition.\n");
 
     ret = load_full_partition(
         ops, part_name, image_size, &image_buf, &image_preloaded);
@@ -525,7 +521,7 @@
 
     /* Move to slot_data. */
     if (slot_data->num_loaded_partitions == MAX_NUMBER_OF_LOADED_PARTITIONS) {
-      avb_errorv(part_name, ": Too many loaded partitions.\n", NULL);
+      avb_error(part_name, ": Too many loaded partitions.\n");
       ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
       goto out;
     }
@@ -653,7 +649,7 @@
       ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
       goto out;
     } else if (io_ret != AVB_IO_RESULT_OK) {
-      avb_errorv(full_partition_name, ": Error loading footer.\n", NULL);
+      avb_error(full_partition_name, ": Error loading footer.\n");
       ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
       goto out;
     }
@@ -661,43 +657,67 @@
 
     if (!avb_footer_validate_and_byteswap((const AvbFooter*)footer_buf,
                                           &footer)) {
-      avb_debugv(full_partition_name, ": No footer detected.\n", NULL);
+      avb_debug(full_partition_name, ": No footer detected.\n");
     } else {
       /* Basic footer sanity check since the data is untrusted. */
       if (footer.vbmeta_size > VBMETA_MAX_SIZE) {
-        avb_errorv(
-            full_partition_name, ": Invalid vbmeta size in footer.\n", NULL);
+        avb_error(full_partition_name, ": Invalid vbmeta size in footer.\n");
       } else {
         vbmeta_offset = footer.vbmeta_offset;
         vbmeta_size = footer.vbmeta_size;
       }
     }
-  }
-
-  vbmeta_buf = avb_malloc(vbmeta_size);
-  if (vbmeta_buf == NULL) {
-    ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
-    goto out;
-  }
-
-  if (vbmeta_offset != 0) {
-    avb_debugv("Loading vbmeta struct in footer from partition '",
-               full_partition_name,
-               "'.\n",
-               NULL);
   } else {
-    avb_debugv("Loading vbmeta struct from partition '",
-               full_partition_name,
-               "'.\n",
-               NULL);
+    uint64_t partition_size = 0;
+    io_ret =
+        ops->get_size_of_partition(ops, full_partition_name, &partition_size);
+    if (io_ret == AVB_IO_RESULT_OK) {
+      if (partition_size < vbmeta_size && partition_size > 0) {
+        avb_debug(full_partition_name,
+                  ": Using partition size as vbmeta size\n");
+        vbmeta_size = partition_size;
+      }
+    } else {
+      avb_debug(full_partition_name, ": Failed to get partition size\n");
+      // libavb might fall back to other partitions if current vbmeta partition
+      // isn't found. So AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION is recoverable,
+      // but other errors are not.
+      if (io_ret != AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION) {
+        ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
+        goto out;
+      }
+    }
   }
 
-  io_ret = ops->read_from_partition(ops,
-                                    full_partition_name,
-                                    vbmeta_offset,
-                                    vbmeta_size,
-                                    vbmeta_buf,
-                                    &vbmeta_num_read);
+  /* Use result from previous I/O operation to check the existence of the
+   * partition before allocating the big chunk of memory on heap
+   * for vbmeta later. `io_ret` will be used later to decide whether
+   * to fallback on the `boot` partition.
+   */
+  if (io_ret != AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION) {
+    vbmeta_buf = avb_malloc(vbmeta_size);
+    if (vbmeta_buf == NULL) {
+      ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
+      goto out;
+    }
+
+    if (vbmeta_offset != 0) {
+      avb_debug("Loading vbmeta struct in footer from partition '",
+                full_partition_name,
+                "'.\n");
+    } else {
+      avb_debug("Loading vbmeta struct from partition '",
+                full_partition_name,
+                "'.\n");
+    }
+
+    io_ret = ops->read_from_partition(ops,
+                                      full_partition_name,
+                                      vbmeta_offset,
+                                      vbmeta_size,
+                                      vbmeta_buf,
+                                      &vbmeta_num_read);
+  }
   if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
     ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
     goto out;
@@ -707,9 +727,8 @@
      */
     if (is_main_vbmeta && io_ret == AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION &&
         !look_for_vbmeta_footer) {
-      avb_debugv(full_partition_name,
-                 ": No such partition. Trying 'boot' instead.\n",
-                 NULL);
+      avb_debug(full_partition_name,
+                ": No such partition. Trying 'boot' instead.\n");
       ret = load_and_verify_vbmeta(ops,
                                    requested_partitions,
                                    ab_suffix,
@@ -726,7 +745,7 @@
                                    out_additional_cmdline_subst);
       goto out;
     } else {
-      avb_errorv(full_partition_name, ": Error loading vbmeta data.\n", NULL);
+      avb_error(full_partition_name, ": Error loading vbmeta data.\n");
       ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
       goto out;
     }
@@ -747,11 +766,10 @@
     case AVB_VBMETA_VERIFY_RESULT_HASH_MISMATCH:
     case AVB_VBMETA_VERIFY_RESULT_SIGNATURE_MISMATCH:
       ret = AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION;
-      avb_errorv(full_partition_name,
-                 ": Error verifying vbmeta image: ",
-                 avb_vbmeta_verify_result_to_string(vbmeta_ret),
-                 "\n",
-                 NULL);
+      avb_error(full_partition_name,
+                ": Error verifying vbmeta image: ",
+                avb_vbmeta_verify_result_to_string(vbmeta_ret),
+                "\n");
       if (!allow_verification_error) {
         goto out;
       }
@@ -760,17 +778,15 @@
     case AVB_VBMETA_VERIFY_RESULT_INVALID_VBMETA_HEADER:
       /* No way to continue this case. */
       ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
-      avb_errorv(full_partition_name,
-                 ": Error verifying vbmeta image: invalid vbmeta header\n",
-                 NULL);
+      avb_error(full_partition_name,
+                ": Error verifying vbmeta image: invalid vbmeta header\n");
       goto out;
 
     case AVB_VBMETA_VERIFY_RESULT_UNSUPPORTED_VERSION:
       /* No way to continue this case. */
       ret = AVB_SLOT_VERIFY_RESULT_ERROR_UNSUPPORTED_VERSION;
-      avb_errorv(full_partition_name,
-                 ": Error verifying vbmeta image: unsupported AVB version\n",
-                 NULL);
+      avb_error(full_partition_name,
+                ": Error verifying vbmeta image: unsupported AVB version\n");
       goto out;
   }
 
@@ -784,9 +800,8 @@
   } else {
     if (vbmeta_header.flags != 0) {
       ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
-      avb_errorv(full_partition_name,
-                 ": chained vbmeta image has non-zero flags\n",
-                 NULL);
+      avb_error(full_partition_name,
+                ": chained vbmeta image has non-zero flags\n");
       goto out;
     }
   }
@@ -802,10 +817,9 @@
       avb_assert(!is_main_vbmeta);
       if (expected_public_key_length != pk_len ||
           avb_safe_memcmp(expected_public_key, pk_data, pk_len) != 0) {
-        avb_errorv(full_partition_name,
-                   ": Public key used to sign data does not match key in chain "
-                   "partition descriptor.\n",
-                   NULL);
+        avb_error(full_partition_name,
+                  ": Public key used to sign data does not match key in chain "
+                  "partition descriptor.\n");
         ret = AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED;
         if (!allow_verification_error) {
           goto out;
@@ -848,16 +862,14 @@
         ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
         goto out;
       } else if (io_ret != AVB_IO_RESULT_OK) {
-        avb_errorv(full_partition_name,
-                   ": Error while checking public key used to sign data.\n",
-                   NULL);
+        avb_error(full_partition_name,
+                  ": Error while checking public key used to sign data.\n");
         ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
         goto out;
       }
       if (!key_is_trusted) {
-        avb_errorv(full_partition_name,
-                   ": Public key used to sign data rejected.\n",
-                   NULL);
+        avb_error(full_partition_name,
+                  ": Public key used to sign data rejected.\n");
         ret = AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED;
         if (!allow_verification_error) {
           goto out;
@@ -873,17 +885,15 @@
     ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
     goto out;
   } else if (io_ret != AVB_IO_RESULT_OK) {
-    avb_errorv(full_partition_name,
-               ": Error getting rollback index for location.\n",
-               NULL);
+    avb_error(full_partition_name,
+              ": Error getting rollback index for location.\n");
     ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
     goto out;
   }
   if (vbmeta_header.rollback_index < stored_rollback_index) {
-    avb_errorv(
+    avb_error(
         full_partition_name,
-        ": Image rollback index is less than the stored rollback index.\n",
-        NULL);
+        ": Image rollback index is less than the stored rollback index.\n");
     ret = AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX;
     if (!allow_verification_error) {
       goto out;
@@ -899,7 +909,7 @@
     }
   }
   if (slot_data->num_vbmeta_images == MAX_NUMBER_OF_VBMETA_IMAGES) {
-    avb_errorv(full_partition_name, ": Too many vbmeta images.\n", NULL);
+    avb_error(full_partition_name, ": Too many vbmeta images.\n");
     ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
     goto out;
   }
@@ -923,8 +933,7 @@
    */
   if (vbmeta_header.flags & AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED) {
     AvbSlotVerifyResult sub_ret;
-    avb_debugv(
-        full_partition_name, ": VERIFICATION_DISABLED bit is set.\n", NULL);
+    avb_debug(full_partition_name, ": VERIFICATION_DISABLED bit is set.\n");
     /* If load_requested_partitions() fail it is always a fatal
      * failure (e.g. ERROR_INVALID_ARGUMENT, ERROR_OOM, etc.) rather
      * than recoverable (e.g. one where result_should_continue()
@@ -957,7 +966,7 @@
     AvbDescriptor desc;
 
     if (!avb_descriptor_validate_and_byteswap(descriptors[n], &desc)) {
-      avb_errorv(full_partition_name, ": Descriptor is invalid.\n", NULL);
+      avb_error(full_partition_name, ": Descriptor is invalid.\n");
       ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
       goto out;
     }
@@ -987,27 +996,24 @@
 
         /* Only allow CHAIN_PARTITION descriptors in the main vbmeta image. */
         if (!is_main_vbmeta) {
-          avb_errorv(full_partition_name,
-                     ": Encountered chain descriptor not in main image.\n",
-                     NULL);
+          avb_error(full_partition_name,
+                    ": Encountered chain descriptor not in main image.\n");
           ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
           goto out;
         }
 
         if (!avb_chain_partition_descriptor_validate_and_byteswap(
                 (AvbChainPartitionDescriptor*)descriptors[n], &chain_desc)) {
-          avb_errorv(full_partition_name,
-                     ": Chain partition descriptor is invalid.\n",
-                     NULL);
+          avb_error(full_partition_name,
+                    ": Chain partition descriptor is invalid.\n");
           ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
           goto out;
         }
 
         if (chain_desc.rollback_index_location == 0) {
-          avb_errorv(full_partition_name,
-                     ": Chain partition has invalid "
-                     "rollback_index_location field.\n",
-                     NULL);
+          avb_error(full_partition_name,
+                    ": Chain partition has invalid "
+                    "rollback_index_location field.\n");
           ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
           goto out;
         }
@@ -1047,9 +1053,8 @@
         if (!avb_kernel_cmdline_descriptor_validate_and_byteswap(
                 (AvbKernelCmdlineDescriptor*)descriptors[n],
                 &kernel_cmdline_desc)) {
-          avb_errorv(full_partition_name,
-                     ": Kernel cmdline descriptor is invalid.\n",
-                     NULL);
+          avb_error(full_partition_name,
+                    ": Kernel cmdline descriptor is invalid.\n");
           ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
           goto out;
         }
@@ -1059,9 +1064,8 @@
 
         if (!avb_validate_utf8(kernel_cmdline,
                                kernel_cmdline_desc.kernel_cmdline_length)) {
-          avb_errorv(full_partition_name,
-                     ": Kernel cmdline is not valid UTF-8.\n",
-                     NULL);
+          avb_error(full_partition_name,
+                    ": Kernel cmdline is not valid UTF-8.\n");
           ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
           goto out;
         }
@@ -1121,8 +1125,7 @@
 
         if (!avb_hashtree_descriptor_validate_and_byteswap(
                 (AvbHashtreeDescriptor*)descriptors[n], &hashtree_desc)) {
-          avb_errorv(
-              full_partition_name, ": Hashtree descriptor is invalid.\n", NULL);
+          avb_error(full_partition_name, ": Hashtree descriptor is invalid.\n");
           ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
           goto out;
         }
@@ -1176,7 +1179,7 @@
                                 "sha512") == 0) {
             digest_len = AVB_SHA512_DIGEST_SIZE;
           } else {
-            avb_errorv(part_name, ": Unsupported hash algorithm.\n", NULL);
+            avb_error(part_name, ": Unsupported hash algorithm.\n");
             ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
             goto out;
           }
@@ -1211,8 +1214,7 @@
 
   if (rollback_index_location_to_use >=
       AVB_MAX_NUMBER_OF_ROLLBACK_INDEX_LOCATIONS) {
-    avb_errorv(
-        full_partition_name, ": Invalid rollback_index_location.\n", NULL);
+    avb_error(full_partition_name, ": Invalid rollback_index_location.\n");
     ret = AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA;
     goto out;
   }
diff --git a/libavb/avb_sysdeps.h b/libavb/avb_sysdeps.h
index e511a8a..b4a1e99 100644
--- a/libavb/avb_sysdeps.h
+++ b/libavb/avb_sysdeps.h
@@ -48,6 +48,7 @@
  */
 #define AVB_ATTR_WARN_UNUSED_RESULT __attribute__((warn_unused_result))
 #define AVB_ATTR_PACKED __attribute__((packed))
+#define AVB_ATTR_PRINTF(x, y) __attribute__((format(printf, x, y)))
 #define AVB_ATTR_NO_RETURN __attribute__((noreturn))
 #define AVB_ATTR_SENTINEL __attribute__((__sentinel__))
 
@@ -95,10 +96,16 @@
 void avb_print(const char* message);
 
 /* Prints out a vector of strings. Each argument must point to a
- * NUL-terminated UTF-8 string and NULL should be the last argument.
+ * NUL-terminated UTF-8 string and NULL must be the last argument.
  */
 void avb_printv(const char* message, ...) AVB_ATTR_SENTINEL;
 
+/* Prints out a formatted string.
+ *
+ * Replaces avb_printv when AVB_USE_PRINTF_LOGS is enabled.
+ */
+void avb_printf(const char* fmt, ...) AVB_ATTR_PRINTF(1, 2);
+
 /* Aborts the program or reboots the device. */
 void avb_abort(void) AVB_ATTR_NO_RETURN;
 
diff --git a/libavb/avb_sysdeps_posix.c b/libavb/avb_sysdeps_posix.c
index e26c3ef..a954869 100644
--- a/libavb/avb_sysdeps_posix.c
+++ b/libavb/avb_sysdeps_posix.c
@@ -58,6 +58,13 @@
   abort();
 }
 
+void avb_printf(const char* fmt, ...) {
+  va_list ap;
+  va_start(ap, fmt);
+  vfprintf(stderr, fmt, ap);
+  va_end(ap);
+}
+
 void avb_print(const char* message) {
   fprintf(stderr, "%s", message);
 }
diff --git a/libavb/avb_util.h b/libavb/avb_util.h
index b6b036e..da638fc 100644
--- a/libavb/avb_util.h
+++ b/libavb/avb_util.h
@@ -35,9 +35,44 @@
 extern "C" {
 #endif
 
+#define AVB_CONCAT(x, y) x##y
 #define AVB_STRINGIFY(x) #x
 #define AVB_TO_STRING(x) AVB_STRINGIFY(x)
 
+#define AVB__COUNT_ARGS(_0, _1, _2, _3, _4, _5, _6, _7, x, ...) x
+#define AVB_COUNT_ARGS(...) \
+  AVB__COUNT_ARGS(, ##__VA_ARGS__, 7, 6, 5, 4, 3, 2, 1, 0)
+
+#define AVB__REPEAT0(x)
+#define AVB__REPEAT1(x) x
+#define AVB__REPEAT2(x) AVB__REPEAT1(x) x
+#define AVB__REPEAT3(x) AVB__REPEAT2(x) x
+#define AVB__REPEAT4(x) AVB__REPEAT3(x) x
+#define AVB__REPEAT5(x) AVB__REPEAT4(x) x
+#define AVB__REPEAT6(x) AVB__REPEAT5(x) x
+#define AVB__REPEAT7(x) AVB__REPEAT6(x) x
+#define AVB__REPEAT(n, x) AVB_CONCAT(AVB__REPEAT, n)(x)
+#define AVB_REPEAT(n, x) AVB__REPEAT(n, x)
+
+#ifdef AVB_USE_PRINTF_LOGS
+#define AVB_LOG(level, message, ...)                                        \
+  avb_printf("%s:%d: " level                                                \
+             ": " AVB_REPEAT(AVB_COUNT_ARGS(message, ##__VA_ARGS__), "%s"), \
+             avb_basename(__FILE__),                                        \
+             __LINE__,                                                      \
+             message,                                                       \
+             ##__VA_ARGS__)
+#else
+#define AVB_LOG(level, message, ...)  \
+  avb_printv(avb_basename(__FILE__),  \
+             ":",                     \
+             AVB_TO_STRING(__LINE__), \
+             ": " level ": ",         \
+             message,                 \
+             ##__VA_ARGS__,           \
+             NULL)
+#endif
+
 #ifdef AVB_ENABLE_DEBUG
 /* Aborts the program if |expr| is false.
  *
@@ -49,21 +84,28 @@
       avb_fatal("assert fail: " #expr "\n"); \
     }                                        \
   } while (0)
-#else
-#define avb_assert(expr)
-#endif
 
 /* Aborts the program if reached.
  *
  * This has no effect unless AVB_ENABLE_DEBUG is defined.
  */
-#ifdef AVB_ENABLE_DEBUG
 #define avb_assert_not_reached()         \
   do {                                   \
     avb_fatal("assert_not_reached()\n"); \
   } while (0)
+
+/* Print functions, used for diagnostics.
+ *
+ * These have no effect unless AVB_ENABLE_DEBUG is defined.
+ */
+#define avb_debug(message, ...)               \
+  do {                                        \
+    AVB_LOG("DEBUG", message, ##__VA_ARGS__); \
+  } while (0)
 #else
+#define avb_assert(expr)
 #define avb_assert_not_reached()
+#define avb_debug(message, ...)
 #endif
 
 /* Aborts the program if |addr| is not word-aligned.
@@ -73,78 +115,29 @@
 #define avb_assert_aligned(addr) \
   avb_assert((((uintptr_t)addr) & (AVB_ALIGNMENT_SIZE - 1)) == 0)
 
-#ifdef AVB_ENABLE_DEBUG
-/* Print functions, used for diagnostics.
- *
- * These have no effect unless AVB_ENABLE_DEBUG is defined.
- */
-#define avb_debug(message)              \
-  do {                                  \
-    avb_printv(avb_basename(__FILE__),  \
-               ":",                     \
-               AVB_TO_STRING(__LINE__), \
-               ": DEBUG: ",             \
-               message,                 \
-               NULL);                   \
-  } while (0)
-#define avb_debugv(message, ...)        \
-  do {                                  \
-    avb_printv(avb_basename(__FILE__),  \
-               ":",                     \
-               AVB_TO_STRING(__LINE__), \
-               ": DEBUG: ",             \
-               message,                 \
-               ##__VA_ARGS__);          \
-  } while (0)
-#else
-#define avb_debug(message)
-#define avb_debugv(message, ...)
-#endif
-
 /* Prints out a message. This is typically used if a runtime-error
  * occurs.
  */
-#define avb_error(message)              \
-  do {                                  \
-    avb_printv(avb_basename(__FILE__),  \
-               ":",                     \
-               AVB_TO_STRING(__LINE__), \
-               ": ERROR: ",             \
-               message,                 \
-               NULL);                   \
-  } while (0)
-#define avb_errorv(message, ...)        \
-  do {                                  \
-    avb_printv(avb_basename(__FILE__),  \
-               ":",                     \
-               AVB_TO_STRING(__LINE__), \
-               ": ERROR: ",             \
-               message,                 \
-               ##__VA_ARGS__);          \
+#define avb_error(message, ...)               \
+  do {                                        \
+    AVB_LOG("ERROR", message, ##__VA_ARGS__); \
   } while (0)
 
 /* Prints out a message and calls avb_abort().
  */
-#define avb_fatal(message)              \
-  do {                                  \
-    avb_printv(avb_basename(__FILE__),  \
-               ":",                     \
-               AVB_TO_STRING(__LINE__), \
-               ": FATAL: ",             \
-               message,                 \
-               NULL);                   \
-    avb_abort();                        \
+#define avb_fatal(message, ...)               \
+  do {                                        \
+    AVB_LOG("FATAL", message, ##__VA_ARGS__); \
+    avb_abort();                              \
   } while (0)
-#define avb_fatalv(message, ...)        \
-  do {                                  \
-    avb_printv(avb_basename(__FILE__),  \
-               ":",                     \
-               AVB_TO_STRING(__LINE__), \
-               ": FATAL: ",             \
-               message,                 \
-               ##__VA_ARGS__);          \
-    avb_abort();                        \
-  } while (0)
+
+#ifndef AVB_USE_PRINTF_LOGS
+/* Deprecated legacy logging functions -- kept for client compatibility.
+ */
+#define avb_debugv(message, ...) avb_debug(message, ##__VA_ARGS__)
+#define avb_errorv(message, ...) avb_error(message, ##__VA_ARGS__)
+#define avb_fatalv(message, ...) avb_fatal(message, ##__VA_ARGS__)
+#endif
 
 /* Converts a 16-bit unsigned integer from big-endian to host byte order. */
 uint16_t avb_be16toh(uint16_t in) AVB_ATTR_WARN_UNUSED_RESULT;
diff --git a/libavb/boringssl/sha.c b/libavb/boringssl/sha.c
index 96973ec..41a0f3f 100644
--- a/libavb/boringssl/sha.c
+++ b/libavb/boringssl/sha.c
@@ -22,8 +22,7 @@
  * SOFTWARE.
  */
 
-#include <libavb/avb_sha.h>
-
+#include "../avb_sha.h"
 #include "avb_crypto_ops_impl.h"
 
 /* SHA-256 implementation */
diff --git a/libavb/sha/avb_crypto_ops_impl.h b/libavb/sha/avb_crypto_ops_impl.h
index 321e0fb..7e721a3 100644
--- a/libavb/sha/avb_crypto_ops_impl.h
+++ b/libavb/sha/avb_crypto_ops_impl.h
@@ -37,7 +37,7 @@
 extern "C" {
 #endif
 
-#include <libavb/avb_sysdeps.h>
+#include "../avb_sysdeps.h"
 
 /* Block size in bytes of a SHA-256 digest. */
 #define AVB_SHA256_BLOCK_SIZE 64
diff --git a/libavb/sha/sha256_impl.c b/libavb/sha/sha256_impl.c
index 7e99358..736588f 100644
--- a/libavb/sha/sha256_impl.c
+++ b/libavb/sha/sha256_impl.c
@@ -35,8 +35,7 @@
  * SUCH DAMAGE.
  */
 
-#include <libavb/avb_sha.h>
-
+#include "../avb_sha.h"
 #include "avb_crypto_ops_impl.h"
 
 #define SHFR(x, n) (x >> n)
diff --git a/libavb/sha/sha512_impl.c b/libavb/sha/sha512_impl.c
index 1eb9ba4..3c85d3d 100644
--- a/libavb/sha/sha512_impl.c
+++ b/libavb/sha/sha512_impl.c
@@ -35,8 +35,7 @@
  * SUCH DAMAGE.
  */
 
-#include <libavb/avb_sha.h>
-
+#include "../avb_sha.h"
 #include "avb_crypto_ops_impl.h"
 
 #define SHFR(x, n) (x >> n)
diff --git a/libavb_ab/avb_ab_flow.c b/libavb_ab/avb_ab_flow.c
index bf6eab1..cbdf6c9 100644
--- a/libavb_ab/avb_ab_flow.c
+++ b/libavb_ab/avb_ab_flow.c
@@ -263,15 +263,12 @@
         case AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED:
           if (flags & AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR) {
             /* Do nothing since we allow this. */
-            avb_debugv("Allowing slot ",
-                       slot_suffixes[n],
-                       " which verified "
-                       "with result ",
-                       avb_slot_verify_result_to_string(verify_result),
-                       " because "
-                       "AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR "
-                       "is set.\n",
-                       NULL);
+            avb_debug("Allowing slot ",
+                      slot_suffixes[n],
+                      " which verified with result ",
+                      avb_slot_verify_result_to_string(verify_result),
+                      " because AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR "
+                      "is set.\n");
             saw_and_allowed_verification_error = true;
           } else {
             set_slot_unbootable = true;
@@ -285,12 +282,11 @@
       }
 
       if (set_slot_unbootable) {
-        avb_errorv("Error verifying slot ",
-                   slot_suffixes[n],
-                   " with result ",
-                   avb_slot_verify_result_to_string(verify_result),
-                   " - setting unbootable.\n",
-                   NULL);
+        avb_error("Error verifying slot ",
+                  slot_suffixes[n],
+                  " with result ",
+                  avb_slot_verify_result_to_string(verify_result),
+                  " - setting unbootable.\n");
         slot_set_unbootable(&ab_data.slots[n]);
       }
     }
diff --git a/libavb_user/avb_ops_user.cpp b/libavb_user/avb_ops_user.cpp
index d7815f0..1ce5391 100644
--- a/libavb_user/avb_ops_user.cpp
+++ b/libavb_user/avb_ops_user.cpp
@@ -138,8 +138,7 @@
   if (offset < 0) {
     uint64_t partition_size;
     if (ioctl(fd, BLKGETSIZE64, &partition_size) != 0) {
-      avb_errorv(
-          "Error getting size of \"", partition, "\" partition.\n", NULL);
+      avb_error("Error getting size of \"", partition, "\" partition.\n");
       ret = AVB_IO_RESULT_ERROR_IO;
       goto out;
     }
@@ -194,7 +193,7 @@
 
   fd = open_partition(partition, O_WRONLY);
   if (fd == -1) {
-    avb_errorv("Error opening \"", partition, "\" partition.\n", NULL);
+    avb_error("Error opening \"", partition, "\" partition.\n");
     ret = AVB_IO_RESULT_ERROR_IO;
     goto out;
   }
@@ -273,15 +272,14 @@
 
   fd = open_partition(partition, O_WRONLY);
   if (fd == -1) {
-    avb_errorv("Error opening \"", partition, "\" partition.\n", NULL);
+    avb_error("Error opening \"", partition, "\" partition.\n");
     ret = AVB_IO_RESULT_ERROR_IO;
     goto out;
   }
 
   if (out_size_in_bytes != NULL) {
     if (ioctl(fd, BLKGETSIZE64, out_size_in_bytes) != 0) {
-      avb_errorv(
-          "Error getting size of \"", partition, "\" partition.\n", NULL);
+      avb_error("Error getting size of \"", partition, "\" partition.\n");
       ret = AVB_IO_RESULT_ERROR_IO;
       goto out;
     }
diff --git a/libavb_user/avb_user_verification.c b/libavb_user/avb_user_verification.c
index f572128..7a124d8 100644
--- a/libavb_user/avb_user_verification.c
+++ b/libavb_user/avb_user_verification.c
@@ -86,18 +86,15 @@
                                       &footer,
                                       &num_read);
     if (io_res != AVB_IO_RESULT_OK) {
-      avb_errorv("Error loading footer from partition '",
-                 out_partition_name,
-                 "'\n",
-                 NULL);
+      avb_error(
+          "Error loading footer from partition '", out_partition_name, "'\n");
       goto out;
     }
 
     if (avb_memcmp(footer.magic, AVB_FOOTER_MAGIC, AVB_FOOTER_MAGIC_LEN) != 0) {
-      avb_errorv("Data from '",
-                 out_partition_name,
-                 "' does not look like a vbmeta footer.\n",
-                 NULL);
+      avb_error("Data from '",
+                out_partition_name,
+                "' does not look like a vbmeta footer.\n");
       goto out;
     }
 
@@ -111,8 +108,7 @@
   }
 
   if (io_res != AVB_IO_RESULT_OK) {
-    avb_errorv(
-        "Error loading from partition '", out_partition_name, "'\n", NULL);
+    avb_error("Error loading from partition '", out_partition_name, "'\n");
     goto out;
   }
 
@@ -141,10 +137,9 @@
   }
 
   if (avb_memcmp(vbmeta_image, AVB_MAGIC, AVB_MAGIC_LEN) != 0) {
-    avb_errorv("Data from '",
-               partition_name,
-               "' does not look like a vbmeta header.\n",
-               NULL);
+    avb_error("Data from '",
+              partition_name,
+              "' does not look like a vbmeta header.\n");
     goto out;
   }
 
@@ -180,10 +175,9 @@
   }
 
   if (avb_memcmp(vbmeta_image, AVB_MAGIC, AVB_MAGIC_LEN) != 0) {
-    avb_errorv("Data from '",
-               partition_name,
-               "' does not look like a vbmeta header.\n",
-               NULL);
+    avb_error("Data from '",
+              partition_name,
+              "' does not look like a vbmeta header.\n");
     goto out;
   }
 
@@ -203,7 +197,7 @@
                                    AVB_VBMETA_IMAGE_HEADER_SIZE,
                                    vbmeta_image);
   if (io_res != AVB_IO_RESULT_OK) {
-    avb_errorv("Error writing to partition '", partition_name, "'\n", NULL);
+    avb_error("Error writing to partition '", partition_name, "'\n");
     goto out;
   }
 
diff --git a/libavb_user/avb_user_verity.c b/libavb_user/avb_user_verity.c
index ecf0043..dd64b3c 100644
--- a/libavb_user/avb_user_verity.c
+++ b/libavb_user/avb_user_verity.c
@@ -86,18 +86,15 @@
                                       &footer,
                                       &num_read);
     if (io_res != AVB_IO_RESULT_OK) {
-      avb_errorv("Error loading footer from partition '",
-                 out_partition_name,
-                 "'\n",
-                 NULL);
+      avb_error(
+          "Error loading footer from partition '", out_partition_name, "'\n");
       goto out;
     }
 
     if (avb_memcmp(footer.magic, AVB_FOOTER_MAGIC, AVB_FOOTER_MAGIC_LEN) != 0) {
-      avb_errorv("Data from '",
-                 out_partition_name,
-                 "' does not look like a vbmeta footer.\n",
-                 NULL);
+      avb_error("Data from '",
+                out_partition_name,
+                "' does not look like a vbmeta footer.\n");
       goto out;
     }
 
@@ -111,8 +108,7 @@
   }
 
   if (io_res != AVB_IO_RESULT_OK) {
-    avb_errorv(
-        "Error loading from partition '", out_partition_name, "'\n", NULL);
+    avb_error("Error loading from partition '", out_partition_name, "'\n");
     goto out;
   }
 
@@ -141,10 +137,9 @@
   }
 
   if (avb_memcmp(vbmeta_image, AVB_MAGIC, AVB_MAGIC_LEN) != 0) {
-    avb_errorv("Data from '",
-               partition_name,
-               "' does not look like a vbmeta header.\n",
-               NULL);
+    avb_error("Data from '",
+              partition_name,
+              "' does not look like a vbmeta header.\n");
     goto out;
   }
 
@@ -179,10 +174,9 @@
   }
 
   if (avb_memcmp(vbmeta_image, AVB_MAGIC, AVB_MAGIC_LEN) != 0) {
-    avb_errorv("Data from '",
-               partition_name,
-               "' does not look like a vbmeta header.\n",
-               NULL);
+    avb_error("Data from '",
+              partition_name,
+              "' does not look like a vbmeta header.\n");
     goto out;
   }
 
@@ -202,7 +196,7 @@
                                    AVB_VBMETA_IMAGE_HEADER_SIZE,
                                    vbmeta_image);
   if (io_res != AVB_IO_RESULT_OK) {
-    avb_errorv("Error writing to partition '", partition_name, "'\n", NULL);
+    avb_error("Error writing to partition '", partition_name, "'\n");
     goto out;
   }
 
diff --git a/test/Android.bp b/test/Android.bp
index 38627fd..8d8809a 100644
--- a/test/Android.bp
+++ b/test/Android.bp
@@ -40,18 +40,15 @@
         "data/atx_unlock_credential.bin",
         "data/testkey_atx_puk.pem",
     ],
-    version: {
-        py2: {
-            enabled: false,
-        },
-        py3: {
-            enabled: true,
-        },
-    },
     test_config: "at_auth_unlock_unittest.xml",
 }
 
 filegroup {
+    name: "avb_testkey_rsa8192",
+    srcs: ["data/testkey_rsa8192.pem"],
+}
+
+filegroup {
     name: "avb_testkey_rsa4096",
     srcs: ["data/testkey_rsa4096.pem"],
 }
@@ -60,3 +57,27 @@
     name: "avb_testkey_rsa2048",
     srcs: ["data/testkey_rsa2048.pem"],
 }
+
+genrule {
+    name: "avb_testkey_rsa2048_pub_bin",
+    tools: ["avbtool"],
+    srcs: [":avb_testkey_rsa2048"],
+    out: ["data/testkey_rsa2048_pub.bin"],
+    cmd: "$(location avbtool) extract_public_key --key $(in) --output $(out)",
+}
+
+genrule {
+    name: "avb_testkey_rsa4096_pub_bin",
+    tools: ["avbtool"],
+    srcs: [":avb_testkey_rsa4096"],
+    out: ["data/testkey_rsa4096_pub.bin"],
+    cmd: "$(location avbtool) extract_public_key --key $(in) --output $(out)",
+}
+
+genrule {
+    name: "avb_testkey_rsa8192_pub_bin",
+    tools: ["avbtool"],
+    srcs: [":avb_testkey_rsa8192"],
+    out: ["data/testkey_rsa8192_pub.bin"],
+    cmd: "$(location avbtool) extract_public_key --key $(in) --output $(out)",
+}
diff --git a/test/avb_ab_flow_unittest.cc b/test/avb_ab_flow_unittest.cc
index ea79224..e055efe 100644
--- a/test/avb_ab_flow_unittest.cc
+++ b/test/avb_ab_flow_unittest.cc
@@ -180,7 +180,7 @@
     const size_t boot_image_size = 5 * 1024 * 1024;
     base::FilePath boot_path = GenerateImage(boot_name, boot_image_size);
     EXPECT_COMMAND(0,
-                   "./avbtool add_hash_footer"
+                   "./avbtool.py add_hash_footer"
                    " --image %s"
                    " --rollback_index %" PRIu64
                    " --partition_name boot"
@@ -194,7 +194,7 @@
     const size_t odm_image_size = 80 * 1024;
     base::FilePath odm_path = GenerateImage(odm_name, odm_image_size);
     EXPECT_COMMAND(0,
-                   "./avbtool add_hashtree_footer"
+                   "./avbtool.py add_hashtree_footer"
                    " --image %s"
                    " --rollback_index %" PRIu64
                    " --partition_name odm"
@@ -210,7 +210,7 @@
     base::FilePath pk_path = testdir_.Append("testkey_rsa4096.avbpubkey");
     EXPECT_COMMAND(
         0,
-        "./avbtool extract_public_key --key test/data/testkey_rsa4096.pem"
+        "./avbtool.py extract_public_key --key test/data/testkey_rsa4096.pem"
         " --output %s",
         pk_path.value().c_str());
 
@@ -1304,7 +1304,7 @@
 
   base::FilePath misc_path = testdir_.Append("misc.img");
   EXPECT_COMMAND(0,
-                 "./avbtool set_ab_metadata"
+                 "./avbtool.py set_ab_metadata"
                  " --misc_image %s"
                  " --slot_data 13:3:0:11:2:1",
                  misc_path.value().c_str());
@@ -1326,7 +1326,7 @@
   size_t misc_size = 1024 * 1024;
   base::FilePath misc_path = GenerateImage("misc.img", misc_size);
   EXPECT_COMMAND(0,
-                 "./avbtool set_ab_metadata"
+                 "./avbtool.py set_ab_metadata"
                  " --misc_image %s"
                  " --slot_data 12:2:1:10:5:0",
                  misc_path.value().c_str());
diff --git a/test/avb_atx_generate_test_data b/test/avb_atx_generate_test_data
index 1b8bb2b..795a2b1 100755
--- a/test/avb_atx_generate_test_data
+++ b/test/avb_atx_generate_test_data
@@ -43,7 +43,7 @@
 TMP_FILE=$(mktemp /tmp/atx_generator.XXXXXXXXXX)
 trap "rm -f '${TMP_FILE}'" EXIT
 
-AVBTOOL=$(dirname "$0")/../avbtool
+AVBTOOL=$(dirname "$0")/../avbtool.py
 
 echo AVBTOOL = ${AVBTOOL}
 
diff --git a/test/avb_slot_verify_unittest.cc b/test/avb_slot_verify_unittest.cc
index 680ea27..9745308 100644
--- a/test/avb_slot_verify_unittest.cc
+++ b/test/avb_slot_verify_unittest.cc
@@ -506,7 +506,7 @@
   // says.
   EXPECT_COMMAND(
       0,
-      "./avbtool add_hash_footer"
+      "./avbtool.py add_hash_footer"
       " --image %s"
       " --rollback_index 0"
       " --partition_name boot"
@@ -574,7 +574,7 @@
   // says.
   EXPECT_COMMAND(
       0,
-      "./avbtool add_hash_footer"
+      "./avbtool.py add_hash_footer"
       " --image %s"
       " --rollback_index 0"
       " --partition_name boot"
@@ -636,7 +636,7 @@
 
   EXPECT_COMMAND(
       0,
-      "./avbtool add_hash_footer"
+      "./avbtool.py add_hash_footer"
       " --image %s"
       " --rollback_index 0"
       " --partition_name boot"
@@ -689,13 +689,13 @@
       InfoImage(vbmeta_image_path_));
 
   EXPECT_COMMAND(0,
-                 "./avbtool erase_footer"
+                 "./avbtool.py erase_footer"
                  " --image %s",
                  boot_path.value().c_str());
 
   // With no footer, 'avbtool info_image' should fail (exit status 1).
   EXPECT_COMMAND(
-      1, "./avbtool info_image --image %s", boot_path.value().c_str());
+      1, "./avbtool.py info_image --image %s", boot_path.value().c_str());
 
   ops_.set_expected_public_key(
       PublicKeyAVB(base::FilePath("test/data/testkey_rsa2048.pem")));
@@ -760,7 +760,7 @@
 
   EXPECT_COMMAND(
       0,
-      "./avbtool add_hash_footer"
+      "./avbtool.py add_hash_footer"
       " --image %s"
       " --rollback_index 0"
       " --partition_name boot"
@@ -783,13 +783,13 @@
           boot_path.value().c_str()));
 
   EXPECT_COMMAND(0,
-                 "./avbtool erase_footer"
+                 "./avbtool.py erase_footer"
                  " --image %s",
                  boot_path.value().c_str());
 
   // With no footer, 'avbtool info_image' should fail (exit status 1).
   EXPECT_COMMAND(
-      1, "./avbtool info_image --image %s", boot_path.value().c_str());
+      1, "./avbtool.py info_image --image %s", boot_path.value().c_str());
 
   ops_.set_expected_public_key(
       PublicKeyAVB(base::FilePath("test/data/testkey_rsa2048.pem")));
@@ -844,7 +844,7 @@
 
   EXPECT_COMMAND(
       0,
-      "./avbtool add_hash_footer"
+      "./avbtool.py add_hash_footer"
       " --image %s"
       " --rollback_index 0"
       " --partition_name boot"
@@ -867,7 +867,7 @@
           boot_path.value().c_str()));
 
   EXPECT_COMMAND(0,
-                 "./avbtool erase_footer"
+                 "./avbtool.py erase_footer"
                  " --image %s",
                  boot_path.value().c_str());
 
@@ -895,7 +895,7 @@
   const char* requested_partitions[] = {"boot", NULL};
 
   EXPECT_COMMAND(0,
-                 "./avbtool add_hash_footer"
+                 "./avbtool.py add_hash_footer"
                  " --image %s"
                  " --rollback_index 0"
                  " --partition_name boot"
@@ -914,7 +914,7 @@
                                          boot_path.value().c_str()));
 
   EXPECT_COMMAND(0,
-                 "./avbtool erase_footer"
+                 "./avbtool.py erase_footer"
                  " --image %s",
                  boot_path.value().c_str());
 
@@ -968,7 +968,7 @@
   const char* requested_partitions[] = {"boot", NULL};
 
   EXPECT_COMMAND(0,
-                 "./avbtool add_hash_footer"
+                 "./avbtool.py add_hash_footer"
                  " --image %s"
                  " --kernel_cmdline 'cmdline2 in hash footer'"
                  " --rollback_index 12"
@@ -984,7 +984,7 @@
   base::FilePath pk_path = testdir_.Append("testkey_rsa4096.avbpubkey");
   EXPECT_COMMAND(
       0,
-      "./avbtool extract_public_key --key test/data/testkey_rsa4096.pem"
+      "./avbtool.py extract_public_key --key test/data/testkey_rsa4096.pem"
       " --output %s",
       pk_path.value().c_str());
 
@@ -1153,7 +1153,7 @@
   const char* requested_partitions[] = {"boot", NULL};
 
   EXPECT_COMMAND(0,
-                 "./avbtool add_hash_footer"
+                 "./avbtool.py add_hash_footer"
                  " --image %s"
                  " --kernel_cmdline 'cmdline2 in hash footer'"
                  " --rollback_index 12"
@@ -1170,7 +1170,7 @@
   base::FilePath pk_path = testdir_.Append("testkey_rsa4096.avbpubkey");
   EXPECT_COMMAND(
       0,
-      "./avbtool extract_public_key --key test/data/testkey_rsa4096.pem"
+      "./avbtool.py extract_public_key --key test/data/testkey_rsa4096.pem"
       " --output %s",
       pk_path.value().c_str());
 
@@ -1271,7 +1271,7 @@
   const char* requested_partitions[] = {"boot", NULL};
 
   EXPECT_COMMAND(0,
-                 "./avbtool add_hash_footer"
+                 "./avbtool.py add_hash_footer"
                  " --image %s"
                  " --kernel_cmdline 'cmdline2 in hash footer'"
                  " --rollback_index 12"
@@ -1287,20 +1287,20 @@
   // Extract the vbmeta blob from the footer in boot.img, put it into
   // vbmeta_google.img, and erase the footer from boot.img
   EXPECT_COMMAND(0,
-                 "./avbtool extract_vbmeta_image"
+                 "./avbtool.py extract_vbmeta_image"
                  " --image %s"
                  " --output %s",
                  boot_path.value().c_str(),
                  other_vbmeta_path.value().c_str());
   EXPECT_COMMAND(0,
-                 "./avbtool erase_footer"
+                 "./avbtool.py erase_footer"
                  " --image %s",
                  boot_path.value().c_str());
 
   base::FilePath pk_path = testdir_.Append("testkey_rsa4096.avbpubkey");
   EXPECT_COMMAND(
       0,
-      "./avbtool extract_public_key --key test/data/testkey_rsa4096.pem"
+      "./avbtool.py extract_public_key --key test/data/testkey_rsa4096.pem"
       " --output %s",
       pk_path.value().c_str());
 
@@ -1463,7 +1463,7 @@
   const char* requested_partitions[] = {"boot", NULL};
 
   EXPECT_COMMAND(0,
-                 "./avbtool add_hash_footer"
+                 "./avbtool.py add_hash_footer"
                  " --image %s"
                  " --rollback_index 0"
                  " --partition_name boot"
@@ -1478,7 +1478,7 @@
   base::FilePath pk_path = testdir_.Append("testkey_rsa4096.avbpubkey");
   EXPECT_COMMAND(
       0,
-      "./avbtool extract_public_key --key test/data/testkey_rsa4096.pem"
+      "./avbtool.py extract_public_key --key test/data/testkey_rsa4096.pem"
       " --output %s",
       pk_path.value().c_str());
 
@@ -1543,7 +1543,7 @@
   // AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED.
 
   EXPECT_COMMAND(0,
-                 "./avbtool add_hash_footer"
+                 "./avbtool.py add_hash_footer"
                  " --image %s"
                  " --rollback_index 0"
                  " --partition_name boot"
@@ -1558,7 +1558,7 @@
   base::FilePath pk_path = testdir_.Append("testkey_rsa4096.avbpubkey");
   EXPECT_COMMAND(
       0,
-      "./avbtool extract_public_key --key test/data/testkey_rsa4096.pem"
+      "./avbtool.py extract_public_key --key test/data/testkey_rsa4096.pem"
       " --output %s",
       pk_path.value().c_str());
 
@@ -1599,7 +1599,7 @@
   const char* requested_partitions[] = {"boot", NULL};
 
   EXPECT_COMMAND(0,
-                 "./avbtool add_hash_footer"
+                 "./avbtool.py add_hash_footer"
                  " --image %s"
                  " --rollback_index 10"
                  " --partition_name boot"
@@ -1614,7 +1614,7 @@
   base::FilePath pk_path = testdir_.Append("testkey_rsa4096.avbpubkey");
   EXPECT_COMMAND(
       0,
-      "./avbtool extract_public_key --key test/data/testkey_rsa4096.pem"
+      "./avbtool.py extract_public_key --key test/data/testkey_rsa4096.pem"
       " --output %s",
       pk_path.value().c_str());
 
@@ -1687,7 +1687,7 @@
   const char* requested_partitions[] = {"boot", NULL};
 
   EXPECT_COMMAND(0,
-                 "./avbtool add_hash_footer"
+                 "./avbtool.py add_hash_footer"
                  " --image %s"
                  " --kernel_cmdline 'cmdline2 in hash footer'"
                  " --rollback_index 12"
@@ -1703,7 +1703,7 @@
   base::FilePath pk_path = testdir_.Append("testkey_rsa4096.avbpubkey");
   EXPECT_COMMAND(
       0,
-      "./avbtool extract_public_key --key test/data/testkey_rsa4096.pem"
+      "./avbtool.py extract_public_key --key test/data/testkey_rsa4096.pem"
       " --output %s",
       pk_path.value().c_str());
 
@@ -1804,7 +1804,7 @@
   base::FilePath bar_path = GenerateImage("bar_a.img", bar_image_size);
 
   EXPECT_COMMAND(0,
-                 "./avbtool add_hash_footer"
+                 "./avbtool.py add_hash_footer"
                  " --image %s"
                  " --partition_name foo"
                  " --partition_size %zd"
@@ -1814,7 +1814,7 @@
                  foo_partition_size);
 
   EXPECT_COMMAND(0,
-                 "./avbtool add_hash_footer"
+                 "./avbtool.py add_hash_footer"
                  " --image %s"
                  " --partition_name bar"
                  " --partition_size %zd"
@@ -1919,7 +1919,7 @@
   base::FilePath bar_path = GenerateImage("bar_a.img", bar_image_size);
 
   EXPECT_COMMAND(0,
-                 "./avbtool add_hash_footer"
+                 "./avbtool.py add_hash_footer"
                  " --image %s"
                  " --partition_name foo"
                  " --partition_size %zd"
@@ -1929,7 +1929,7 @@
                  foo_partition_size);
 
   EXPECT_COMMAND(0,
-                 "./avbtool add_hash_footer"
+                 "./avbtool.py add_hash_footer"
                  " --image %s"
                  " --partition_name bar"
                  " --partition_size %zd"
@@ -2011,7 +2011,7 @@
   base::FilePath bar_path = GenerateImage("bar_a.img", bar_image_size);
 
   EXPECT_COMMAND(0,
-                 "./avbtool add_hash_footer"
+                 "./avbtool.py add_hash_footer"
                  " --image %s"
                  " --kernel_cmdline 'this is=5 from foo=42'"
                  " --partition_name foo"
@@ -2026,7 +2026,7 @@
                  foo_partition_size);
 
   EXPECT_COMMAND(0,
-                 "./avbtool add_hash_footer"
+                 "./avbtool.py add_hash_footer"
                  " --image %s"
                  " --kernel_cmdline 'and=43 from bar'"
                  " --partition_name bar"
@@ -2170,7 +2170,7 @@
                                 rootfs.size())));
 
   EXPECT_COMMAND(0,
-                 "./avbtool add_hashtree_footer --salt d00df00d --image %s "
+                 "./avbtool.py add_hashtree_footer --salt d00df00d --image %s "
                  "--partition_size %d --partition_name foobar "
                  "--algorithm SHA256_RSA2048 "
                  "--key test/data/testkey_rsa2048.pem "
@@ -2304,7 +2304,7 @@
   // Check that we correctly generate dm-verity kernel cmdline
   // snippets, if requested.
   EXPECT_COMMAND(0,
-                 "./avbtool add_hashtree_footer --salt d00df00d --image %s "
+                 "./avbtool.py add_hashtree_footer --salt d00df00d --image %s "
                  "--partition_size %d --partition_name foobar "
                  "--algorithm SHA256_RSA2048 "
                  "--key test/data/testkey_rsa2048.pem "
@@ -2362,7 +2362,7 @@
   base::FilePath pk_path = testdir_.Append("testkey_rsa2048.avbpubkey");
   EXPECT_COMMAND(
       0,
-      "./avbtool extract_public_key --key test/data/testkey_rsa2048.pem"
+      "./avbtool.py extract_public_key --key test/data/testkey_rsa2048.pem"
       " --output %s",
       pk_path.value().c_str());
 
@@ -2494,7 +2494,7 @@
                                 rootfs.size())));
 
   EXPECT_COMMAND(0,
-                 "./avbtool add_hashtree_footer --salt d00df00d --image %s "
+                 "./avbtool.py add_hashtree_footer --salt d00df00d --image %s "
                  "--partition_size %d --partition_name foobar "
                  "--algorithm SHA256_RSA2048 "
                  "--key test/data/testkey_rsa2048.pem "
@@ -2682,7 +2682,7 @@
   base::FilePath bazboo_path = GenerateImage("bazboo.img", bazboo_size);
 
   EXPECT_COMMAND(0,
-                 "./avbtool add_hashtree_footer --salt d00df00d --image %s "
+                 "./avbtool.py add_hashtree_footer --salt d00df00d --image %s "
                  "--partition_size %d --partition_name system "
                  "--algorithm SHA256_RSA2048 "
                  "--key test/data/testkey_rsa2048.pem "
@@ -2692,7 +2692,7 @@
                  (int)system_part_size);
 
   EXPECT_COMMAND(0,
-                 "./avbtool add_hashtree_footer --salt d00df00d --image %s "
+                 "./avbtool.py add_hashtree_footer --salt d00df00d --image %s "
                  "--partition_size %d --partition_name foobar "
                  "--algorithm SHA256_RSA2048 "
                  "--key test/data/testkey_rsa2048.pem "
@@ -2702,7 +2702,7 @@
                  (int)foobar_part_size);
 
   EXPECT_COMMAND(0,
-                 "./avbtool add_hashtree_footer --salt d00df00d --image %s "
+                 "./avbtool.py add_hashtree_footer --salt d00df00d --image %s "
                  "--partition_size %d --partition_name bazboo "
                  "--algorithm SHA512_RSA4096 "
                  "--key test/data/testkey_rsa4096.pem "
@@ -2714,7 +2714,7 @@
   base::FilePath pk_path = testdir_.Append("testkey_rsa4096.avbpubkey");
   EXPECT_COMMAND(
       0,
-      "./avbtool extract_public_key --key test/data/testkey_rsa4096.pem"
+      "./avbtool.py extract_public_key --key test/data/testkey_rsa4096.pem"
       " --output %s",
       pk_path.value().c_str());
 
@@ -2722,7 +2722,7 @@
   // boot.img is treated as top-level. Note the corresponding "Flags:"
   // field below in the avbtool info_image output.
   EXPECT_COMMAND(0,
-                 "./avbtool add_hash_footer --salt d00df00d "
+                 "./avbtool.py add_hash_footer --salt d00df00d "
                  "--hash_algorithm sha256 --image %s "
                  "--partition_size %d --partition_name boot "
                  "--algorithm SHA256_RSA2048 "
@@ -2858,7 +2858,7 @@
   const char* requested_partitions[] = {"boot", NULL};
 
   EXPECT_COMMAND(0,
-                 "./avbtool add_hash_footer"
+                 "./avbtool.py add_hash_footer"
                  " --image %s"
                  " --kernel_cmdline 'cmdline2 in hash footer'"
                  " --rollback_index 12"
@@ -2875,7 +2875,7 @@
   base::FilePath pk_path = testdir_.Append("testkey_rsa4096.avbpubkey");
   EXPECT_COMMAND(
       0,
-      "./avbtool extract_public_key --key test/data/testkey_rsa4096.pem"
+      "./avbtool.py extract_public_key --key test/data/testkey_rsa4096.pem"
       " --output %s",
       pk_path.value().c_str());
 
@@ -2914,12 +2914,12 @@
   base::FilePath pk_path = testdir_.Append("testkey_rsa4096.avbpubkey");
   EXPECT_COMMAND(
       0,
-      "./avbtool extract_public_key --key test/data/testkey_rsa4096.pem"
+      "./avbtool.py extract_public_key --key test/data/testkey_rsa4096.pem"
       " --output %s",
       pk_path.value().c_str());
 
   EXPECT_COMMAND(0,
-                 "./avbtool add_hash_footer"
+                 "./avbtool.py add_hash_footer"
                  " --image %s"
                  " --kernel_cmdline 'cmdline2 in hash footer'"
                  " --rollback_index 12"
@@ -2965,7 +2965,7 @@
   base::FilePath system_path = GenerateImage("system.img", system_size);
 
   EXPECT_COMMAND(0,
-                 "./avbtool add_hashtree_footer --salt d00df00d --image %s "
+                 "./avbtool.py add_hashtree_footer --salt d00df00d --image %s "
                  "--partition_size %d --partition_name system "
                  "--algorithm SHA256_RSA2048 "
                  "--key test/data/testkey_rsa2048.pem "
@@ -3169,7 +3169,7 @@
         GenerateImage("factory.img", factory_image_size);
 
     EXPECT_COMMAND(0,
-                   "./avbtool add_hash_footer"
+                   "./avbtool.py add_hash_footer"
                    " --image %s"
                    " --rollback_index 0"
                    " --partition_name factory"
@@ -3223,7 +3223,7 @@
 
     EXPECT_COMMAND(
         0,
-        "./avbtool add_hashtree_footer"
+        "./avbtool.py add_hashtree_footer"
         " --image %s"
         " --rollback_index 0"
         " --partition_name factory"
diff --git a/test/avb_sysdeps_posix_testing.cc b/test/avb_sysdeps_posix_testing.cc
index 0a6ac13..6b1f210 100644
--- a/test/avb_sysdeps_posix_testing.cc
+++ b/test/avb_sysdeps_posix_testing.cc
@@ -77,6 +77,13 @@
   va_end(ap);
 }
 
+void avb_printf(const char* fmt, ...) {
+  va_list ap;
+  va_start(ap, fmt);
+  vfprintf(stderr, fmt, ap);
+  va_end(ap);
+}
+
 typedef struct {
   size_t size;
   base::debug::StackTrace stack_trace;
diff --git a/test/avb_unittest_util.cc b/test/avb_unittest_util.cc
index 5202e6a..f59458a 100644
--- a/test/avb_unittest_util.cc
+++ b/test/avb_unittest_util.cc
@@ -79,7 +79,7 @@
   base::FilePath vbmeta_digest_path = testdir_.Append("vbmeta_digest");
   EXPECT_COMMAND(
       0,
-      "./avbtool calculate_vbmeta_digest --image %s --hash_algorithm %s"
+      "./avbtool.py calculate_vbmeta_digest --image %s --hash_algorithm %s"
       " --output %s",
       vbmeta_path.value().c_str(),
       digest_alg.c_str(),
@@ -104,7 +104,7 @@
   }
   vbmeta_image_path_ = testdir_.Append(image_name);
   EXPECT_COMMAND(0,
-                 "./avbtool make_vbmeta_image"
+                 "./avbtool.py make_vbmeta_image"
                  " --rollback_index %" PRIu64
                  " %s %s "
                  " --output %s",
@@ -128,7 +128,7 @@
                                               uint8_t start_byte) {
   base::FilePath image_path = testdir_.Append(file_name);
   EXPECT_COMMAND(0,
-                 "./avbtool generate_test_image "
+                 "./avbtool.py generate_test_image "
                  "--image_size %d "
                  "--start_byte %d "
                  "--output %s",
@@ -144,7 +144,7 @@
 std::string BaseAvbToolTest::InfoImage(const base::FilePath& image_path) {
   base::FilePath tmp_path = testdir_.Append("info_output.txt");
   EXPECT_COMMAND(0,
-                 "./avbtool info_image --image %s --output %s",
+                 "./avbtool.py info_image --image %s --output %s",
                  image_path.value().c_str(),
                  tmp_path.value().c_str());
   std::string info_data;
@@ -155,7 +155,7 @@
 std::string BaseAvbToolTest::PublicKeyAVB(const base::FilePath& key_path) {
   base::FilePath tmp_path = testdir_.Append("public_key.bin");
   EXPECT_COMMAND(0,
-                 "./avbtool extract_public_key --key %s"
+                 "./avbtool.py extract_public_key --key %s"
                  " --output %s",
                  key_path.value().c_str(),
                  tmp_path.value().c_str());
diff --git a/test/avbtool_unittest.cc b/test/avbtool_unittest.cc
index b8fdc0e..0a226a8 100644
--- a/test/avbtool_unittest.cc
+++ b/test/avbtool_unittest.cc
@@ -69,7 +69,7 @@
 // avb_boot_image.h and the avb tool.
 TEST_F(AvbToolTest, AvbVersionInSync) {
   base::FilePath path = testdir_.Append("version.txt");
-  EXPECT_COMMAND(0, "./avbtool version > %s", path.value().c_str());
+  EXPECT_COMMAND(0, "./avbtool.py version > %s", path.value().c_str());
   std::string printed_version;
   ASSERT_TRUE(base::ReadFileToString(path, &printed_version));
   base::TrimWhitespaceASCII(printed_version, base::TRIM_ALL, &printed_version);
@@ -502,7 +502,7 @@
   /* Do this twice to check that 'add_hash_footer' is idempotent. */
   for (int n = 0; n < 2; n++) {
     EXPECT_COMMAND(0,
-                   "./avbtool add_hash_footer --salt d00df00d "
+                   "./avbtool.py add_hash_footer --salt d00df00d "
                    "--hash_algorithm sha256 --image %s "
                    "--partition_size %d --partition_name foobar "
                    "--algorithm SHA256_RSA2048 "
@@ -541,7 +541,7 @@
 
     // Check that the extracted vbmeta matches the externally generally one.
     EXPECT_COMMAND(0,
-                   "./avbtool extract_vbmeta_image --image %s "
+                   "./avbtool.py extract_vbmeta_image --image %s "
                    "--output %s",
                    rootfs_path.value().c_str(),
                    extracted_vbmeta_path.value().c_str());
@@ -557,12 +557,12 @@
   // larger than the original rootfs but smaller than the current
   // partition size.
   EXPECT_COMMAND(1,
-                 "./avbtool resize_image --image %s "
+                 "./avbtool.py resize_image --image %s "
                  "--partition_size %d",
                  rootfs_path.value().c_str(),
                  (int)(rootfs_size - 16 * 1024));
   EXPECT_COMMAND(0,
-                 "./avbtool resize_image --image %s "
+                 "./avbtool.py resize_image --image %s "
                  "--partition_size %d",
                  rootfs_path.value().c_str(),
                  (int)resized_partition_size);
@@ -650,14 +650,14 @@
 
   // Check that the footer is correctly erased.
   EXPECT_COMMAND(
-      0, "./avbtool erase_footer --image %s", rootfs_path.value().c_str());
+      0, "./avbtool.py erase_footer --image %s", rootfs_path.value().c_str());
   int64_t erased_footer_file_size;
   ASSERT_TRUE(base::GetFileSize(rootfs_path, &erased_footer_file_size));
   EXPECT_EQ(static_cast<size_t>(erased_footer_file_size), rootfs_size);
 
   // Check that --do_not_append_vbmeta_image works as intended.
   EXPECT_COMMAND(0,
-                 "./avbtool add_hash_footer --salt d00df00d "
+                 "./avbtool.py add_hash_footer --salt d00df00d "
                  "--hash_algorithm sha256 --image %s "
                  "--partition_size %d --partition_name foobar "
                  "--algorithm SHA256_RSA2048 "
@@ -718,7 +718,7 @@
                  partition_path.value().c_str());
 
   EXPECT_COMMAND(0,
-                 "./avbtool add_hash_footer --salt d00df00d "
+                 "./avbtool.py add_hash_footer --salt d00df00d "
                  "--hash_algorithm sha256 --image %s "
                  "--partition_size %d --partition_name foobar "
                  "--algorithm SHA256_RSA2048 "
@@ -775,7 +775,7 @@
   base::FilePath output_path = testdir_.Append("max_size.txt");
 
   EXPECT_COMMAND(0,
-                 "./avbtool add_hash_footer "
+                 "./avbtool.py add_hash_footer "
                  "--partition_size %zd "
                  "--calc_max_image_size > %s",
                  partition_size,
@@ -792,7 +792,7 @@
   // such a partition size.
   base::FilePath boot_path = GenerateImage("boot", max_image_size);
   EXPECT_COMMAND(0,
-                 "./avbtool add_hash_footer"
+                 "./avbtool.py add_hash_footer"
                  " --image %s"
                  " --partition_name boot"
                  " --partition_size %zd"
@@ -808,7 +808,7 @@
   size_t partition_size = 1024 * 1024;
   base::FilePath path = GenerateImage("digest_location", 1024);
   EXPECT_COMMAND(0,
-                 "./avbtool add_hash_footer "
+                 "./avbtool.py add_hash_footer "
                  "--hash_algorithm sha256 --image %s "
                  "--partition_size %d --partition_name foobar "
                  "--algorithm SHA256_RSA2048 "
@@ -852,7 +852,7 @@
   size_t partition_size = 1024 * 1024;
   base::FilePath path = GenerateImage("digest_location", 1024);
   EXPECT_COMMAND(0,
-                 "./avbtool add_hash_footer --salt d00df00d "
+                 "./avbtool.py add_hash_footer --salt d00df00d "
                  "--hash_algorithm sha256 --image %s "
                  "--partition_size %d --partition_name foobar "
                  "--algorithm SHA256_RSA2048 "
@@ -897,7 +897,7 @@
   size_t partition_size = 1024 * 1024;
   base::FilePath path = GenerateImage("digest_location", 1024);
   EXPECT_COMMAND(0,
-                 "./avbtool add_hash_footer "
+                 "./avbtool.py add_hash_footer "
                  "--hash_algorithm sha256 --image %s "
                  "--partition_size %d --partition_name foobar "
                  "--algorithm SHA256_RSA2048 "
@@ -976,7 +976,7 @@
   /* Do this twice to check that 'add_hashtree_footer' is idempotent. */
   for (int n = 0; n < 2; n++) {
     EXPECT_COMMAND(0,
-                   "./avbtool add_hashtree_footer --salt d00df00d --image %s "
+                   "./avbtool.py add_hashtree_footer --salt d00df00d --image %s "
                    "--hash_algorithm %s "
                    "--partition_size %d --partition_name foobar "
                    "--algorithm SHA256_RSA2048 "
@@ -1062,7 +1062,7 @@
 
     // Check that the extracted vbmeta matches the externally generally one.
     EXPECT_COMMAND(0,
-                   "./avbtool extract_vbmeta_image --image %s "
+                   "./avbtool.py extract_vbmeta_image --image %s "
                    "--output %s",
                    rootfs_path.value().c_str(),
                    extracted_vbmeta_path.value().c_str());
@@ -1088,7 +1088,7 @@
                  rootfs_path.value().c_str(),
                  rootfs_path.value().c_str());
   EXPECT_COMMAND(0,
-                 "./avbtool zero_hashtree --image %s.zht ",
+                 "./avbtool.py zero_hashtree --image %s.zht ",
                  rootfs_path.value().c_str());
 
   if (sparse_image) {
@@ -1229,7 +1229,7 @@
   // snippets, if requested.
   base::FilePath vbmeta_dmv_path = testdir_.Append("vbmeta_dm_verity_desc.bin");
   EXPECT_COMMAND(0,
-                 "./avbtool make_vbmeta_image "
+                 "./avbtool.py make_vbmeta_image "
                  "--output %s "
                  "--setup_rootfs_from_kernel %s "
                  "--algorithm SHA256_RSA2048 "
@@ -1265,7 +1265,7 @@
   // Check that the footer is correctly erased and the hashtree
   // remains - see above for why the constant 1069056 is used.
   EXPECT_COMMAND(0,
-                 "./avbtool erase_footer --image %s --keep_hashtree",
+                 "./avbtool.py erase_footer --image %s --keep_hashtree",
                  rootfs_path.value().c_str());
   int64_t erased_footer_file_size;
   ASSERT_TRUE(base::GetFileSize(rootfs_path, &erased_footer_file_size));
@@ -1281,7 +1281,7 @@
   EXPECT_COMMAND(
       0, "truncate -s %d %s", (int)rootfs_size, rootfs_path.value().c_str());
   EXPECT_COMMAND(0,
-                 "./avbtool add_hashtree_footer --salt d00df00d --image %s "
+                 "./avbtool.py add_hashtree_footer --salt d00df00d --image %s "
                  "--partition_size %d --partition_name foobar "
                  "--algorithm SHA256_RSA2048 "
                  "--key test/data/testkey_rsa2048.pem "
@@ -1348,7 +1348,7 @@
   /* Do this twice to check that 'add_hashtree_footer' is idempotent. */
   for (int n = 0; n < 2; n++) {
     EXPECT_COMMAND(0,
-                   "./avbtool add_hashtree_footer --salt d00df00d --image %s "
+                   "./avbtool.py add_hashtree_footer --salt d00df00d --image %s "
                    "--partition_size %d --partition_name foobar "
                    "--algorithm SHA256_RSA2048 "
                    "--key test/data/testkey_rsa2048.pem "
@@ -1400,7 +1400,7 @@
                  rootfs_path.value().c_str(),
                  rootfs_path.value().c_str());
   EXPECT_COMMAND(0,
-                 "./avbtool zero_hashtree --image %s.zht ",
+                 "./avbtool.py zero_hashtree --image %s.zht ",
                  rootfs_path.value().c_str());
 
   if (sparse_image) {
@@ -1526,7 +1526,7 @@
   // snippets, if requested.
   base::FilePath vbmeta_dmv_path = testdir_.Append("vbmeta_dm_verity_desc.bin");
   EXPECT_COMMAND(0,
-                 "./avbtool make_vbmeta_image "
+                 "./avbtool.py make_vbmeta_image "
                  "--output %s "
                  "--setup_rootfs_from_kernel %s "
                  "--algorithm SHA256_RSA2048 "
@@ -1566,7 +1566,7 @@
   // FEC data remains. The constant 1085440 is used because it's where
   // the FEC data ends (it's at offset 1069056 and size 16384).
   EXPECT_COMMAND(0,
-                 "./avbtool erase_footer --image %s --keep_hashtree",
+                 "./avbtool.py erase_footer --image %s --keep_hashtree",
                  rootfs_path.value().c_str());
   int64_t erased_footer_file_size;
   ASSERT_TRUE(base::GetFileSize(rootfs_path, &erased_footer_file_size));
@@ -1586,7 +1586,7 @@
   base::FilePath output_path = testdir_.Append("max_size.txt");
 
   EXPECT_COMMAND(0,
-                 "./avbtool add_hashtree_footer "
+                 "./avbtool.py add_hashtree_footer "
                  "--partition_size %zd --calc_max_image_size "
                  "--do_not_generate_fec > %s",
                  partition_size,
@@ -1604,7 +1604,7 @@
   // a partition size.
   base::FilePath system_path = GenerateImage("system", max_image_size);
   EXPECT_COMMAND(0,
-                 "./avbtool add_hashtree_footer"
+                 "./avbtool.py add_hashtree_footer"
                  " --image %s"
                  " --partition_name system"
                  " --partition_size %zd"
@@ -1622,7 +1622,7 @@
   base::FilePath output_path = testdir_.Append("max_size.txt");
 
   EXPECT_COMMAND(0,
-                 "./avbtool add_hashtree_footer "
+                 "./avbtool.py add_hashtree_footer "
                  "--partition_size %zd --calc_max_image_size > %s",
                  partition_size,
                  output_path.value().c_str());
@@ -1639,7 +1639,7 @@
   // a partition size.
   base::FilePath system_path = GenerateImage("system", max_image_size);
   EXPECT_COMMAND(0,
-                 "./avbtool add_hashtree_footer"
+                 "./avbtool.py add_hashtree_footer"
                  " --image %s"
                  " --partition_name system"
                  " --partition_size %zd"
@@ -1656,7 +1656,7 @@
   base::FilePath output_path = testdir_.Append("max_size.txt");
 
   EXPECT_COMMAND(0,
-                 "./avbtool add_hashtree_footer "
+                 "./avbtool.py add_hashtree_footer "
                  "--no_hashtree "
                  "--partition_size %zd --calc_max_image_size > %s",
                  partition_size,
@@ -1673,7 +1673,7 @@
   // a partition size.
   base::FilePath system_path = GenerateImage("system", max_image_size);
   EXPECT_COMMAND(0,
-                 "./avbtool add_hashtree_footer"
+                 "./avbtool.py add_hashtree_footer"
                  " --image %s"
                  " --no_hashtree"
                  " --partition_name system"
@@ -1725,7 +1725,7 @@
   size_t partition_size = 10 * 1024 * 1024;
   base::FilePath path = GenerateImage("digest_location", partition_size / 2);
   EXPECT_COMMAND(0,
-                 "./avbtool add_hashtree_footer "
+                 "./avbtool.py add_hashtree_footer "
                  "--hash_algorithm sha256 --image %s "
                  "--partition_size %d --partition_name foobar "
                  "--algorithm SHA256_RSA2048 "
@@ -1777,7 +1777,7 @@
   size_t partition_size = 10 * 1024 * 1024;
   base::FilePath path = GenerateImage("digest_location", partition_size / 2);
   EXPECT_COMMAND(0,
-                 "./avbtool add_hashtree_footer --salt d00df00d "
+                 "./avbtool.py add_hashtree_footer --salt d00df00d "
                  "--hash_algorithm sha256 --image %s "
                  "--partition_size %d --partition_name foobar "
                  "--algorithm SHA256_RSA2048 "
@@ -1830,7 +1830,7 @@
   size_t partition_size = 10 * 1024 * 1024;
   base::FilePath path = GenerateImage("digest_location", partition_size / 2);
   EXPECT_COMMAND(0,
-                 "./avbtool add_hashtree_footer "
+                 "./avbtool.py add_hashtree_footer "
                  "--hash_algorithm sha256 --image %s "
                  "--partition_size %d --partition_name foobar "
                  "--algorithm SHA256_RSA2048 "
@@ -1886,7 +1886,7 @@
 
   // Note how there is no --partition_size or --partition_name here.
   EXPECT_COMMAND(0,
-                 "./avbtool add_hashtree_footer --salt d00df00d "
+                 "./avbtool.py add_hashtree_footer --salt d00df00d "
                  "--image %s "
                  "--algorithm SHA256_RSA2048 "
                  "--key test/data/testkey_rsa2048.pem "
@@ -1930,7 +1930,7 @@
 
   // Check that at least avbtool can verify the image and hashtree.
   EXPECT_COMMAND(0,
-                 "./avbtool verify_image "
+                 "./avbtool.py verify_image "
                  "--image %s ",
                  path.value().c_str());
 }
@@ -1942,7 +1942,7 @@
 
   // Note how there is no --partition_size or --partition_name here.
   EXPECT_COMMAND(0,
-                 "./avbtool add_hashtree_footer --salt d00df00d "
+                 "./avbtool.py add_hashtree_footer --salt d00df00d "
                  "--image %s "
                  "--algorithm SHA256_RSA2048 "
                  "--key test/data/testkey_rsa2048.pem "
@@ -1986,7 +1986,7 @@
 
   // Check that at least avbtool can verify the image and hashtree.
   EXPECT_COMMAND(0,
-                 "./avbtool verify_image "
+                 "./avbtool.py verify_image "
                  "--image %s ",
                  path.value().c_str());
 }
@@ -1998,7 +1998,7 @@
 
   // ... so we expect this command to fail.
   EXPECT_COMMAND(1,
-                 "./avbtool add_hashtree_footer --salt d00df00d "
+                 "./avbtool.py add_hashtree_footer --salt d00df00d "
                  "--image %s "
                  "--algorithm SHA256_RSA2048 "
                  "--key test/data/testkey_rsa2048.pem "
@@ -2006,11 +2006,52 @@
                  path.value().c_str());
 }
 
+TEST_F(AvbToolTest, AddHashtreeFooterRoundImageSize) {
+  // Image size needs not to be a multiple of block size (4096 bytes) if
+  // --partition_size is specified. avbtool will round the image size being
+  // a multiple of block size, prior to add an AVB footer.
+  size_t image_size = 70 * 1024;
+  base::FilePath path = GenerateImage("data.bin", image_size);
+
+  size_t partition_size = 10 * 1024 * 1024;
+  // Note that there is --partition_size here.
+  EXPECT_COMMAND(0,
+                 "./avbtool.py add_hashtree_footer --salt d00df00d "
+                 "--image %s "
+                 "--algorithm SHA256_RSA2048 "
+                 "--key test/data/testkey_rsa2048.pem "
+                 "--partition_size %d --partition_name foobar "
+                 "--internal_release_string \"\" ",
+                 path.value().c_str(),
+                 (int)partition_size);
+}
+
+TEST_F(AvbToolTest, AddHashtreeFooterNoWrongPartitionSize) {
+  // Partition size must be a multiple of block size (4096 bytes) and this
+  // one isn't...
+  size_t partition_size = 10 * 1024 * 1024 + 1024;
+
+  // Image size doesn't matter in this case.
+  size_t image_size = 70 * 1024;
+  base::FilePath path = GenerateImage("data.bin", image_size);
+
+  // ... so we expect this command to fail.
+  EXPECT_COMMAND(1,
+                 "./avbtool.py add_hashtree_footer --salt d00df00d "
+                 "--image %s "
+                 "--algorithm SHA256_RSA2048 "
+                 "--key test/data/testkey_rsa2048.pem "
+                 "--partition_size %d --partition_name foobar "
+                 "--internal_release_string \"\" ",
+                 path.value().c_str(),
+                 (int)partition_size);
+}
+
 TEST_F(AvbToolTest, AddHashtreeFooterWithCheckAtMostOnce) {
   size_t partition_size = 10 * 1024 * 1024;
   base::FilePath path = GenerateImage("digest_location", partition_size / 2);
   EXPECT_COMMAND(0,
-                 "./avbtool add_hashtree_footer --salt d00df00d "
+                 "./avbtool.py add_hashtree_footer --salt d00df00d "
                  "--hash_algorithm sha256 --image %s "
                  "--partition_size %d --partition_name foobar "
                  "--algorithm SHA256_RSA2048 "
@@ -2064,7 +2105,7 @@
       testdir_.Append("vbmeta_kernel_cmdline_desc.bin");
 
   EXPECT_COMMAND(0,
-                 "./avbtool make_vbmeta_image "
+                 "./avbtool.py make_vbmeta_image "
                  "--output %s "
                  "--kernel_cmdline 'foo bar baz' "
                  "--kernel_cmdline 'second cmdline' "
@@ -2138,7 +2179,7 @@
 TEST_F(AvbToolTest, CalculateKernelCmdline) {
   base::FilePath vbmeta_path = testdir_.Append("vbmeta.bin");
   EXPECT_COMMAND(0,
-                 "./avbtool make_vbmeta_image "
+                 "./avbtool.py make_vbmeta_image "
                  "--output %s "
                  "--kernel_cmdline 'foo bar baz' "
                  "--kernel_cmdline 'second cmdline' "
@@ -2150,7 +2191,7 @@
   base::FilePath out_path = testdir_.Append("out.txt");
   std::string out;
   EXPECT_COMMAND(0,
-                 "./avbtool calculate_kernel_cmdline --image %s > %s",
+                 "./avbtool.py calculate_kernel_cmdline --image %s > %s",
                  vbmeta_path.value().c_str(),
                  out_path.value().c_str());
   ASSERT_TRUE(base::ReadFileToString(out_path, &out));
@@ -2180,12 +2221,12 @@
 
   EXPECT_COMMAND(
       0,
-      "./avbtool extract_public_key --key test/data/testkey_rsa2048.pem"
+      "./avbtool.py extract_public_key --key test/data/testkey_rsa2048.pem"
       " --output %s",
       pk_path.value().c_str());
 
   EXPECT_COMMAND(0,
-                 "./avbtool add_hashtree_footer --salt d00df00d --image %s "
+                 "./avbtool.py add_hashtree_footer --salt d00df00d --image %s "
                  "--partition_size %d --partition_name rootfs "
                  "--algorithm SHA256_RSA2048 "
                  "--key test/data/testkey_rsa2048.pem "
@@ -2243,7 +2284,7 @@
   // Chain to the rootfs.img and include two cmdline descriptors.
   base::FilePath vbmeta_path = testdir_.Append("vbmeta.bin");
   EXPECT_COMMAND(0,
-                 "./avbtool make_vbmeta_image "
+                 "./avbtool.py make_vbmeta_image "
                  "--output %s "
                  "--kernel_cmdline 'foo bar baz' "
                  "--kernel_cmdline 'second cmdline' "
@@ -2284,7 +2325,7 @@
   // First check the kernel cmdline without --hashtree_disabled - compare with
   // above info_image output.
   EXPECT_COMMAND(0,
-                 "./avbtool calculate_kernel_cmdline --image %s > %s",
+                 "./avbtool.py calculate_kernel_cmdline --image %s > %s",
                  vbmeta_path.value().c_str(),
                  out_path.value().c_str());
   ASSERT_TRUE(base::ReadFileToString(out_path, &out));
@@ -2302,7 +2343,7 @@
   // info_image output.
   EXPECT_COMMAND(
       0,
-      "./avbtool calculate_kernel_cmdline --image %s --hashtree_disabled > %s",
+      "./avbtool.py calculate_kernel_cmdline --image %s --hashtree_disabled > %s",
       vbmeta_path.value().c_str(),
       out_path.value().c_str());
   ASSERT_TRUE(base::ReadFileToString(out_path, &out));
@@ -2328,7 +2369,7 @@
                                 reinterpret_cast<const char*>(image.data()),
                                 image.size())));
   EXPECT_COMMAND(0,
-                 "./avbtool add_hash_footer --salt d00df00d "
+                 "./avbtool.py add_hash_footer --salt d00df00d "
                  "--hash_algorithm sha256 --image %s "
                  "--partition_size %zu --partition_name kernel "
                  "--algorithm SHA256_RSA2048 "
@@ -2353,7 +2394,7 @@
   base::FilePath vbmeta3_path = testdir_.Append("vbmeta_id3.bin");
 
   EXPECT_COMMAND(0,
-                 "./avbtool make_vbmeta_image "
+                 "./avbtool.py make_vbmeta_image "
                  "--output %s "
                  "--kernel_cmdline 'something' "
                  "--prop name:value "
@@ -2361,7 +2402,7 @@
                  vbmeta1_path.value().c_str());
 
   EXPECT_COMMAND(0,
-                 "./avbtool make_vbmeta_image "
+                 "./avbtool.py make_vbmeta_image "
                  "--output %s "
                  "--prop name2:value2 "
                  "--prop name3:value3 "
@@ -2369,7 +2410,7 @@
                  vbmeta2_path.value().c_str());
 
   EXPECT_COMMAND(0,
-                 "./avbtool make_vbmeta_image "
+                 "./avbtool.py make_vbmeta_image "
                  "--output %s "
                  "--prop name4:value4 "
                  "--include_descriptors_from_image %s "
@@ -2407,13 +2448,13 @@
 
   EXPECT_COMMAND(
       0,
-      "./avbtool extract_public_key --key test/data/testkey_rsa2048.pem"
+      "./avbtool.py extract_public_key --key test/data/testkey_rsa2048.pem"
       " --output %s",
       pk_path.value().c_str());
 
   EXPECT_COMMAND(
       0,
-      "./avbtool make_vbmeta_image "
+      "./avbtool.py make_vbmeta_image "
       "--output %s "
       "--chain_partition system:1:%s "
       "--algorithm SHA256_RSA2048 --key test/data/testkey_rsa2048.pem "
@@ -2489,7 +2530,7 @@
 
   EXPECT_COMMAND(
       0,
-      "./avbtool extract_public_key --key test/data/testkey_rsa2048.pem"
+      "./avbtool.py extract_public_key --key test/data/testkey_rsa2048.pem"
       " --output %s",
       pk_path.value().c_str());
 
@@ -2497,7 +2538,7 @@
   // used for multiple chained partitions.
   EXPECT_COMMAND(
       1,
-      "./avbtool make_vbmeta_image "
+      "./avbtool.py make_vbmeta_image "
       "--output %s "
       "--chain_partition system:1:%s "
       "--chain_partition other:1:%s "
@@ -2521,7 +2562,7 @@
                                   "--kernel_cmdline foo"));
 
   EXPECT_COMMAND(0,
-                 "./avbtool append_vbmeta_image "
+                 "./avbtool.py append_vbmeta_image "
                  "--image %s "
                  "--partition_size %d "
                  "--vbmeta_image %s ",
@@ -2579,7 +2620,7 @@
       testdir_.Append("signing_helper_test");
   EXPECT_COMMAND(
       0,
-      "SIGNING_HELPER_TEST=\"%s\" ./avbtool make_vbmeta_image "
+      "SIGNING_HELPER_TEST=\"%s\" ./avbtool.py make_vbmeta_image "
       "--output %s "
       "--algorithm SHA256_RSA2048 --key test/data/testkey_rsa2048.pem "
       "--signing_helper test/avbtool_signing_helper_test.py "
@@ -2599,7 +2640,7 @@
       testdir_.Append("signing_helper_test");
   EXPECT_COMMAND(
       0,
-      "SIGNING_HELPER_TEST=\"%s\" ./avbtool make_vbmeta_image "
+      "SIGNING_HELPER_TEST=\"%s\" ./avbtool.py make_vbmeta_image "
       "--output %s "
       "--algorithm SHA256_RSA2048 --key test/data/testkey_rsa2048.pem "
       "--signing_helper_with_files "
@@ -2618,7 +2659,7 @@
   base::FilePath vbmeta_path = testdir_.Append("vbmeta.bin");
   EXPECT_COMMAND(
       1,
-      "./avbtool make_vbmeta_image "
+      "./avbtool.py make_vbmeta_image "
       "--output %s "
       "--algorithm SHA256_RSA2048 --key test/data/testkey_rsa2048.pem "
       "--signing_helper test/avbtool_signing_helper_test.py "
@@ -2630,7 +2671,7 @@
   base::FilePath vbmeta_path = testdir_.Append("vbmeta.bin");
   EXPECT_COMMAND(
       1,
-      "./avbtool make_vbmeta_image "
+      "./avbtool.py make_vbmeta_image "
       "--output %s "
       "--algorithm SHA256_RSA2048 --key test/data/testkey_rsa2048.pem "
       "--signing_helper_with_files "
@@ -2646,7 +2687,7 @@
                       base::FilePath());
 
   EXPECT_COMMAND(0,
-                 "./avbtool verify_image "
+                 "./avbtool.py verify_image "
                  "--image %s ",
                  vbmeta_image_path_.value().c_str());
 }
@@ -2658,7 +2699,7 @@
                       base::FilePath("test/data/testkey_rsa2048.pem"));
 
   EXPECT_COMMAND(0,
-                 "./avbtool verify_image "
+                 "./avbtool.py verify_image "
                  "--image %s ",
                  vbmeta_image_path_.value().c_str());
 }
@@ -2681,7 +2722,7 @@
                                                corrupt_data));
 
   EXPECT_COMMAND(1,
-                 "./avbtool verify_image "
+                 "./avbtool.py verify_image "
                  "--image %s ",
                  vbmeta_image_path_.value().c_str());
 }
@@ -2693,7 +2734,7 @@
                       base::FilePath("test/data/testkey_rsa2048.pem"));
 
   EXPECT_COMMAND(0,
-                 "./avbtool verify_image "
+                 "./avbtool.py verify_image "
                  "--image %s --key test/data/testkey_rsa2048.pem",
                  vbmeta_image_path_.value().c_str());
 }
@@ -2705,7 +2746,7 @@
                       base::FilePath("test/data/testkey_rsa2048.pem"));
 
   EXPECT_COMMAND(1,
-                 "./avbtool verify_image "
+                 "./avbtool.py verify_image "
                  "--image %s --key test/data/testkey_rsa4096.pem",
                  vbmeta_image_path_.value().c_str());
 }
@@ -2718,7 +2759,7 @@
   // Intentionally make the signer generate a wrong signature.
   EXPECT_COMMAND(
       0,
-      "SIGNING_HELPER_GENERATE_WRONG_SIGNATURE=1 ./avbtool make_vbmeta_image "
+      "SIGNING_HELPER_GENERATE_WRONG_SIGNATURE=1 ./avbtool.py make_vbmeta_image "
       "--output %s "
       "--algorithm SHA256_RSA2048 --key test/data/testkey_rsa2048.pem "
       "--signing_helper test/avbtool_signing_helper_test.py "
@@ -2726,7 +2767,7 @@
       vbmeta_path.value().c_str());
 
   EXPECT_COMMAND(1,
-                 "./avbtool verify_image "
+                 "./avbtool.py verify_image "
                  "--image %s ",
                  vbmeta_path.value().c_str());
 }
@@ -2737,7 +2778,7 @@
   const size_t boot_image_size = 5 * 1024 * 1024;
   base::FilePath boot_path = GenerateImage("boot.img", boot_image_size);
   EXPECT_COMMAND(0,
-                 "./avbtool add_hash_footer"
+                 "./avbtool.py add_hash_footer"
                  " --image %s"
                  " --rollback_index 0"
                  " --partition_name boot"
@@ -2751,7 +2792,7 @@
   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 "
+                 "./avbtool.py add_hashtree_footer --salt d00df00d --image %s "
                  "--partition_size %zd --partition_name system "
                  "--internal_release_string \"\" ",
                  system_path.value().c_str(),
@@ -2774,7 +2815,7 @@
   // is sparse.
   for (int n = 0; n < 2; n++) {
     EXPECT_COMMAND(0,
-                   "./avbtool verify_image "
+                   "./avbtool.py verify_image "
                    "--image %s ",
                    vbmeta_image_path_.value().c_str());
     if (n == 0) {
@@ -2795,7 +2836,7 @@
   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 "
+                 "./avbtool.py add_hashtree_footer --salt d00df00d --image %s "
                  "--partition_size %zd --partition_name system "
                  "--internal_release_string \"\" ",
                  system_path.value().c_str(),
@@ -2809,18 +2850,18 @@
                                          system_path.value().c_str()));
 
   EXPECT_COMMAND(0,
-                 "./avbtool verify_image --image %s --accept_zeroed_hashtree",
+                 "./avbtool.py 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());
+      0, "./avbtool.py zero_hashtree --image %s", system_path.value().c_str());
 
   EXPECT_COMMAND(1,
-                 "./avbtool verify_image --image %s",
+                 "./avbtool.py verify_image --image %s",
                  vbmeta_image_path_.value().c_str());
 
   EXPECT_COMMAND(0,
-                 "./avbtool verify_image --image %s --accept_zeroed_hashtree",
+                 "./avbtool.py verify_image --image %s --accept_zeroed_hashtree",
                  vbmeta_image_path_.value().c_str());
 }
 
@@ -2829,7 +2870,7 @@
   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 "
+                 "./avbtool.py add_hashtree_footer --salt d00df00d --image %s "
                  "--partition_size %zd --partition_name system "
                  "--no_hashtree "
                  "--internal_release_string \"\" ",
@@ -2844,11 +2885,11 @@
                                          system_path.value().c_str()));
 
   EXPECT_COMMAND(1,
-                 "./avbtool verify_image --image %s",
+                 "./avbtool.py verify_image --image %s",
                  vbmeta_image_path_.value().c_str());
 
   EXPECT_COMMAND(0,
-                 "./avbtool verify_image --image %s --accept_zeroed_hashtree",
+                 "./avbtool.py verify_image --image %s --accept_zeroed_hashtree",
                  vbmeta_image_path_.value().c_str());
 }
 
@@ -2865,7 +2906,7 @@
                                                corrupt_data));
 
   EXPECT_COMMAND(1,
-                 "./avbtool verify_image "
+                 "./avbtool.py verify_image "
                  "--image %s ",
                  vbmeta_image_path_.value().c_str());
 }
@@ -2886,7 +2927,7 @@
   // is sparse.
   for (int n = 0; n < 2; n++) {
     EXPECT_COMMAND(1,
-                   "./avbtool verify_image "
+                   "./avbtool.py verify_image "
                    "--image %s ",
                    vbmeta_image_path_.value().c_str());
     if (n == 0) {
@@ -2906,14 +2947,14 @@
   base::FilePath pk4096_path = testdir_.Append("testkey_rsa4096.avbpubkey");
   EXPECT_COMMAND(
       0,
-      "./avbtool extract_public_key --key test/data/testkey_rsa4096.pem"
+      "./avbtool.py extract_public_key --key test/data/testkey_rsa4096.pem"
       " --output %s",
       pk4096_path.value().c_str());
 
   base::FilePath pk8192_path = testdir_.Append("testkey_rsa8192.avbpubkey");
   EXPECT_COMMAND(
       0,
-      "./avbtool extract_public_key --key test/data/testkey_rsa8192.pem"
+      "./avbtool.py extract_public_key --key test/data/testkey_rsa8192.pem"
       " --output %s",
       pk8192_path.value().c_str());
 
@@ -2926,7 +2967,7 @@
 
   // Should not fail (name, rollback_index, contents all correct).
   EXPECT_COMMAND(0,
-                 "./avbtool verify_image "
+                 "./avbtool.py verify_image "
                  "--image %s "
                  "--expected_chain_partition system:1:%s",
                  vbmeta_image_path_.value().c_str(),
@@ -2934,13 +2975,13 @@
 
   // Should fail because we didn't use --expected_chain_partition.
   EXPECT_COMMAND(1,
-                 "./avbtool verify_image "
+                 "./avbtool.py verify_image "
                  "--image %s ",
                  vbmeta_image_path_.value().c_str());
 
   // Should fail because partition name is wrong.
   EXPECT_COMMAND(1,
-                 "./avbtool verify_image "
+                 "./avbtool.py verify_image "
                  "--image %s "
                  "--expected_chain_partition xyz:1:%s",
                  vbmeta_image_path_.value().c_str(),
@@ -2948,7 +2989,7 @@
 
   // Should fail because rollback index location is wrong.
   EXPECT_COMMAND(1,
-                 "./avbtool verify_image "
+                 "./avbtool.py verify_image "
                  "--image %s "
                  "--expected_chain_partition system:2:%s",
                  vbmeta_image_path_.value().c_str(),
@@ -2956,7 +2997,7 @@
 
   // Should fail because public key blob is wrong.
   EXPECT_COMMAND(1,
-                 "./avbtool verify_image "
+                 "./avbtool.py verify_image "
                  "--image %s "
                  "--expected_chain_partition system:1:%s",
                  vbmeta_image_path_.value().c_str(),
@@ -2967,7 +3008,7 @@
   base::FilePath pk4096_path = testdir_.Append("testkey_rsa4096.avbpubkey");
   EXPECT_COMMAND(
       0,
-      "./avbtool extract_public_key --key test/data/testkey_rsa4096.pem"
+      "./avbtool.py extract_public_key --key test/data/testkey_rsa4096.pem"
       " --output %s",
       pk4096_path.value().c_str());
 
@@ -2982,7 +3023,7 @@
   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 "
+                 "./avbtool.py add_hashtree_footer --salt d00df00d --image %s "
                  "--partition_size %zd --partition_name system "
                  "--algorithm SHA256_RSA4096 "
                  "--key test/data/testkey_rsa4096.pem "
@@ -2997,7 +3038,7 @@
   char cwdbuf[PATH_MAX];
   ASSERT_NE(nullptr, getcwd(cwdbuf, sizeof cwdbuf));
   EXPECT_COMMAND(0,
-                 "cd %s && (%s/avbtool verify_image "
+                 "cd %s && (%s/avbtool.py verify_image "
                  "--image vbmeta.img --follow_chain_partitions > out.txt)",
                  testdir_.value().c_str(),
                  cwdbuf);
@@ -3021,7 +3062,7 @@
   // Make sure we also follow partitions *even* when specifying
   // --expect_chain_partition. The output is slightly different from above.
   EXPECT_COMMAND(0,
-                 "cd %s && (%s/avbtool verify_image "
+                 "cd %s && (%s/avbtool.py verify_image "
                  "--image vbmeta.img --expected_chain_partition system:1:%s "
                  "--follow_chain_partitions > out.txt)",
                  testdir_.value().c_str(),
@@ -3047,7 +3088,7 @@
   base::FilePath pk4096_path = testdir_.Append("testkey_rsa4096.avbpubkey");
   EXPECT_COMMAND(
       0,
-      "./avbtool extract_public_key --key test/data/testkey_rsa4096.pem"
+      "./avbtool.py extract_public_key --key test/data/testkey_rsa4096.pem"
       " --output %s",
       pk4096_path.value().c_str());
 
@@ -3055,7 +3096,7 @@
   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 "
+                 "./avbtool.py add_hashtree_footer --salt d00df00d --image %s "
                  "--partition_size %zd --partition_name system "
                  "--internal_release_string \"\" "
                  "--algorithm SHA256_RSA4096 "
@@ -3074,7 +3115,7 @@
 
   // Should not fail (name, rollback_index, contents all correct).
   EXPECT_COMMAND(0,
-                 "./avbtool verify_image "
+                 "./avbtool.py verify_image "
                  "--image %s "
                  "--expected_chain_partition vbmeta_google:1:%s",
                  vbmeta_image_path_.value().c_str(),
@@ -3082,7 +3123,7 @@
 
   // Should not fail (looks in system.img image).
   EXPECT_COMMAND(0,
-                 "./avbtool verify_image "
+                 "./avbtool.py verify_image "
                  "--image %s ",
                  system_path.value().c_str());
 
@@ -3091,20 +3132,20 @@
   // the hash tree in system.img)
   base::FilePath vbmeta_google_path = GenerateImage("vbmeta_google.img", 0);
   EXPECT_COMMAND(0,
-                 "./avbtool extract_vbmeta_image"
+                 "./avbtool.py extract_vbmeta_image"
                  " --image %s"
                  " --output %s",
                  system_path.value().c_str(),
                  vbmeta_google_path.value().c_str());
   EXPECT_COMMAND(0,
-                 "./avbtool erase_footer"
+                 "./avbtool.py erase_footer"
                  " --image %s --keep_hashtree",
                  system_path.value().c_str());
 
   // Should not fail - looks in system.img's detached vbmeta (vbmeta_google.img)
   // for vbmeta blob and system.img for the actual hashtree.
   EXPECT_COMMAND(0,
-                 "./avbtool verify_image "
+                 "./avbtool.py verify_image "
                  "--image %s ",
                  vbmeta_google_path.value().c_str());
 }
@@ -3113,7 +3154,7 @@
   base::FilePath pk4096_path = testdir_.Append("testkey_rsa4096.avbpubkey");
   EXPECT_COMMAND(
       0,
-      "./avbtool extract_public_key --key test/data/testkey_rsa4096.pem"
+      "./avbtool.py extract_public_key --key test/data/testkey_rsa4096.pem"
       " --output %s",
       pk4096_path.value().c_str());
 
@@ -3121,7 +3162,7 @@
   const size_t boot_image_size = 5 * 1024 * 1024;
   base::FilePath boot_path = GenerateImage("boot.img", boot_image_size);
   EXPECT_COMMAND(0,
-                 "./avbtool add_hash_footer"
+                 "./avbtool.py add_hash_footer"
                  " --image %s"
                  " --rollback_index 0"
                  " --partition_name boot"
@@ -3144,7 +3185,7 @@
   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 "
+                 "./avbtool.py add_hashtree_footer --salt d00df00d --image %s "
                  "--partition_size %zd --partition_name system "
                  "--algorithm SHA256_RSA4096 "
                  "--key test/data/testkey_rsa4096.pem "
@@ -3157,7 +3198,7 @@
 
   // Normal output
   EXPECT_COMMAND(0,
-                 "./avbtool print_partition_digests --image %s --output %s",
+                 "./avbtool.py print_partition_digests --image %s --output %s",
                  vbmeta_image_path_.value().c_str(),
                  out_path.value().c_str());
   ASSERT_TRUE(base::ReadFileToString(out_path, &out));
@@ -3170,7 +3211,7 @@
   // JSON output
   EXPECT_COMMAND(
       0,
-      "./avbtool print_partition_digests --image %s --json --output %s",
+      "./avbtool.py print_partition_digests --image %s --json --output %s",
       vbmeta_image_path_.value().c_str(),
       out_path.value().c_str());
   ASSERT_TRUE(base::ReadFileToString(out_path, &out));
@@ -3209,7 +3250,7 @@
     const size_t boot_partition_size = 16 * 1024 * 1024;
     base::FilePath output_path = testdir_.Append(kOutputFile);
     EXPECT_COMMAND(0,
-                   "./avbtool add_hash_footer"
+                   "./avbtool.py add_hash_footer"
                    " --rollback_index 0"
                    " --partition_name boot"
                    " --partition_size %zd"
@@ -3234,7 +3275,7 @@
     const size_t system_partition_size = 10 * 1024 * 1024;
     base::FilePath output_path = testdir_.Append(kOutputFile);
     EXPECT_COMMAND(0,
-                   "./avbtool add_hashtree_footer --salt d00df00d "
+                   "./avbtool.py add_hashtree_footer --salt d00df00d "
                    "--partition_size %zd --partition_name system "
                    "--internal_release_string \"\""
                    " %s"
@@ -3252,7 +3293,7 @@
       const size_t boot_partition_size = 16 * 1024 * 1024;
       base::FilePath image_path = GenerateImage("test_print_version", 1024);
       EXPECT_COMMAND(0,
-                     "./avbtool add_hash_footer --salt d00df00d "
+                     "./avbtool.py add_hash_footer --salt d00df00d "
                      "--hash_algorithm sha256 --image %s "
                      "--partition_size %d --partition_name foobar "
                      "--algorithm SHA256_RSA2048 "
@@ -3269,7 +3310,7 @@
 
     base::FilePath output_path = testdir_.Append(kOutputFile);
     EXPECT_COMMAND(0,
-                   "./avbtool make_vbmeta_image "
+                   "./avbtool.py make_vbmeta_image "
                    "--algorithm SHA256_RSA2048 "
                    "--key test/data/testkey_rsa2048.pem "
                    "--internal_release_string \"\""
@@ -3336,7 +3377,7 @@
 
   base::FilePath output_path = testdir_.Append("tmp_certificate.bin");
   EXPECT_COMMAND(0,
-                 "./avbtool make_atx_certificate"
+                 "./avbtool.py make_atx_certificate"
                  " --subject %s"
                  " --subject_key %s"
                  " --subject_key_version 42"
@@ -3361,7 +3402,7 @@
 
   base::FilePath output_path = testdir_.Append("tmp_certificate.bin");
   EXPECT_COMMAND(0,
-                 "./avbtool make_atx_certificate"
+                 "./avbtool.py make_atx_certificate"
                  " --subject test/data/atx_product_id.bin"
                  " --subject_key %s"
                  " --subject_key_version 42"
@@ -3384,7 +3425,7 @@
 
   base::FilePath output_path = testdir_.Append("tmp_certificate.bin");
   EXPECT_COMMAND(0,
-                 "./avbtool make_atx_certificate"
+                 "./avbtool.py make_atx_certificate"
                  " --subject test/data/atx_product_id.bin"
                  " --subject_key %s"
                  " --subject_key_version 42"
@@ -3408,7 +3449,7 @@
 
   base::FilePath output_path = testdir_.Append("tmp_attributes.bin");
   EXPECT_COMMAND(0,
-                 "./avbtool make_atx_permanent_attributes"
+                 "./avbtool.py make_atx_permanent_attributes"
                  " --root_authority_key %s"
                  " --product_id test/data/atx_product_id.bin"
                  " --output %s",
@@ -3425,7 +3466,7 @@
 
   EXPECT_COMMAND(
       0,
-      "./avbtool make_atx_metadata"
+      "./avbtool.py make_atx_metadata"
       " --intermediate_key_certificate test/data/atx_pik_certificate.bin"
       " --product_key_certificate test/data/atx_psk_certificate.bin"
       " --output %s",
@@ -3440,7 +3481,7 @@
 
   EXPECT_COMMAND(
       0,
-      "./avbtool make_atx_unlock_credential"
+      "./avbtool.py make_atx_unlock_credential"
       " --intermediate_key_certificate test/data/atx_pik_certificate.bin"
       " --unlock_key_certificate test/data/atx_puk_certificate.bin"
       " --challenge test/data/atx_unlock_challenge.bin"
diff --git a/test/data/testkey_rsa4096_pub.bin b/test/data/testkey_rsa4096_pub.bin
deleted file mode 100644
index f2e8fbd..0000000
--- a/test/data/testkey_rsa4096_pub.bin
+++ /dev/null
Binary files differ
diff --git a/test/image_handler_unittest.py b/test/image_handler_unittest.py
index 9eacac0..085059f 100755
--- a/test/image_handler_unittest.py
+++ b/test/image_handler_unittest.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 
 # Copyright 2016, The Android Open Source Project
 #
@@ -33,7 +33,7 @@
 import unittest
 
 sys.dont_write_bytecode = True
-avbtool = imp.load_source('avbtool', './avbtool')
+avbtool = imp.load_source('avbtool', './avbtool.py')
 
 # The file test_file.bin and test_file.bin.sparse are generated using
 # the following python code:
@@ -102,8 +102,8 @@
     return size
 
   def _clone_sparse_file(self):
-    f = tempfile.NamedTemporaryFile()
-    f.write(open(self.TEST_FILE_SPARSE_PATH).read())
+    f = tempfile.NamedTemporaryFile(mode='wb')
+    f.write(open(self.TEST_FILE_SPARSE_PATH, 'rb').read())
     f.flush()
     return f
 
@@ -120,24 +120,24 @@
     self.assertEqual(ih.tell(), 0)
 
     # Check that reading advances the cursor.
-    self.assertEqual(ih.read(14), bytearray('Barfoo43Barfoo'))
+    self.assertEqual(ih.read(14), bytearray(b'Barfoo43Barfoo'))
     self.assertEqual(ih.tell(), 14)
-    self.assertEqual(ih.read(2), bytearray('43'))
+    self.assertEqual(ih.read(2), bytearray(b'43'))
     self.assertEqual(ih.tell(), 16)
 
     # Check reading in the middle of a fill chunk gets the right data.
     ih.seek(0x6000 + 1)
-    self.assertEqual(ih.read(4), bytearray('\x02\x03\x04\x01'))
+    self.assertEqual(ih.read(4), bytearray(b'\x02\x03\x04\x01'))
 
     # Check we can cross the chunk boundary correctly.
     ih.seek(0x3000 - 10)
-    self.assertEqual(ih.read(12), bytearray('43Barfoo43\x00\x00'))
+    self.assertEqual(ih.read(12), bytearray(b'43Barfoo43\x00\x00'))
     ih.seek(0x9000 - 3)
-    self.assertEqual(ih.read(5), bytearray('\x02\x03\x04Fo'))
+    self.assertEqual(ih.read(5), bytearray(b'\x02\x03\x04Fo'))
 
     # Check reading at end of file is a partial read.
     ih.seek(0xf000 - 2)
-    self.assertEqual(ih.read(16), bytearray('\x00\x00'))
+    self.assertEqual(ih.read(16), bytearray(b'\x00\x00'))
 
   def testTruncate(self):
     """Checks that we can truncate a sparse file correctly."""
@@ -165,13 +165,13 @@
                                               self.TEST_FILE_PATH,
                                               self.TEST_FILE_SIZE))
     unsparse_file.seek(self.TEST_FILE_SIZE)
-    self.assertEqual(unsparse_file.read(), '\0'*grow_size)
+    self.assertEqual(unsparse_file.read(), b'\0'*grow_size)
 
   def testAppendRaw(self):
     """Checks that we can append raw data correctly."""
     sparse_file = self._clone_sparse_file()
     ih = avbtool.ImageHandler(sparse_file.name)
-    data = 'SomeData'*4096
+    data = b'SomeData'*4096
     ih.append_raw(data)
     unsparse_file = self._unsparsify(sparse_file.name)
     self.assertTrue(self._file_contents_equal(unsparse_file.name,
@@ -184,8 +184,8 @@
     """Checks that we can append fill data correctly."""
     sparse_file = self._clone_sparse_file()
     ih = avbtool.ImageHandler(sparse_file.name)
-    data = 'ABCD'*4096
-    ih.append_fill('ABCD', len(data))
+    data = b'ABCD'*4096
+    ih.append_fill(b'ABCD', len(data))
     unsparse_file = self._unsparsify(sparse_file.name)
     self.assertTrue(self._file_contents_equal(unsparse_file.name,
                                               self.TEST_FILE_PATH,
@@ -197,7 +197,7 @@
     """Checks that we can append DONT_CARE data correctly."""
     sparse_file = self._clone_sparse_file()
     ih = avbtool.ImageHandler(sparse_file.name)
-    data = '\0'*40960
+    data = b'\0'*40960
     ih.append_dont_care(len(data))
     unsparse_file = self._unsparsify(sparse_file.name)
     self.assertTrue(self._file_contents_equal(unsparse_file.name,
diff --git a/tools/transparency/pixel_factory_image_verify.py b/tools/transparency/pixel_factory_image_verify.py
index 2040ab9..93baf59 100755
--- a/tools/transparency/pixel_factory_image_verify.py
+++ b/tools/transparency/pixel_factory_image_verify.py
@@ -68,7 +68,7 @@
     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'))
+                                                     '../../../avbtool.py'))
     self.fw_unpacker_path = distutils.spawn.find_executable('fbpacktool')
     self.wget_path = distutils.spawn.find_executable('wget')
     self.curl_path = distutils.spawn.find_executable('curl')
diff --git a/tools/transparency/verify/cmd/verifier/verifier.go b/tools/transparency/verify/cmd/verifier/verifier.go
index fd02241..c579cd9 100644
--- a/tools/transparency/verify/cmd/verifier/verifier.go
+++ b/tools/transparency/verify/cmd/verifier/verifier.go
@@ -37,7 +37,7 @@
 // resistance similar to that used in RFC 6962.
 const (
 	LeafHashPrefix     = 0
-	KeyNameForVerifier = "pixel6_transparency_log"
+	KeyNameForVerifier = "pixel_transparency_log"
 )
 
 // See https://developers.google.com/android/binary_transparency/pixel#signature-verification.
diff --git a/tools/transparency/verify/internal/checkpoint/checkpoint_test.go b/tools/transparency/verify/internal/checkpoint/checkpoint_test.go
index 1c81394..1c47e82 100644
--- a/tools/transparency/verify/internal/checkpoint/checkpoint_test.go
+++ b/tools/transparency/verify/internal/checkpoint/checkpoint_test.go
@@ -1,9 +1,6 @@
 package checkpoint
 
 import (
-	"crypto/ecdsa"
-	"crypto/elliptic"
-	"crypto/rand"
 	"net/http"
 	"net/http/httptest"
 	"net/url"
@@ -13,17 +10,6 @@
 	"github.com/google/go-cmp/cmp"
 )
 
-// privateKeyForTest returns a ecdsa PrivateKey used in tests only.
-func privateKeyForTest(t *testing.T) *ecdsa.PrivateKey {
-	t.Helper()
-	privateKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
-	if err != nil {
-		t.Fatalf("GenerateKey(): %v", err)
-	}
-
-	return privateKey
-}
-
 func TestInvalidCheckpointFormat(t *testing.T) {
 	tests := []struct {
 		desc    string