Snap for 10453563 from 22dec6ce02ae63c40381b6b10bb3e0014387b7ee to mainline-conscrypt-release

Change-Id: I7a116e01eb877faaf0939aed63dd58569e45c42e
diff --git a/Android.bp b/Android.bp
index 65b6ac2..1de0238 100644
--- a/Android.bp
+++ b/Android.bp
@@ -43,11 +43,7 @@
 python_defaults {
     name: "mkbootimg_defaults",
     version: {
-        py2: {
-            enabled: false,
-        },
         py3: {
-            enabled: true,
             embedded_launcher: true,
         },
     },
diff --git a/BUILD.bazel b/BUILD.bazel
index e80a82a..6fc323b 100644
--- a/BUILD.bazel
+++ b/BUILD.bazel
@@ -14,4 +14,5 @@
 
 exports_files([
     "mkbootimg.py",
+    "gki/testdata/testkey_rsa4096.pem",
 ])
diff --git a/OWNERS b/OWNERS
index d71a5a1..f161afd 100644
--- a/OWNERS
+++ b/OWNERS
@@ -1,2 +1 @@
-smuckle@google.com
-yochiang@google.com
\ No newline at end of file
+yochiang@google.com
diff --git a/gki/Android.bp b/gki/Android.bp
index c62e7d8..41a1c3e 100644
--- a/gki/Android.bp
+++ b/gki/Android.bp
@@ -45,59 +45,3 @@
         "avbtool",
     ],
 }
-
-sh_binary_host {
-    name: "retrofit_gki",
-    src: "retrofit_gki.sh",
-    required: [
-        "avbtool",
-        "mkbootimg",
-        "unpack_bootimg",
-    ],
-}
-
-sh_test_host {
-    name: "retrofit_gki_test",
-    src: "retrofit_gki_test.sh",
-    data: [
-        "retrofit_gki.sh",
-    ],
-    data_bins: [
-        "avbtool",
-        "mkbootimg",
-        "unpack_bootimg",
-    ],
-    test_suites: [
-        "general-tests",
-    ],
-}
-
-genrule {
-    name: "gki_retrofitting_tools",
-    tools: [
-        "soong_zip",
-        "retrofit_gki",
-        "avbtool",
-        "mkbootimg",
-        "unpack_bootimg",
-    ],
-    srcs: [
-        "README.md",
-    ],
-    cmd: "STAGE_DIR=$(genDir)/gki_retrofitting_tools && " +
-         "rm -rf $${STAGE_DIR} && mkdir -p $${STAGE_DIR} && " +
-         "cp $(location retrofit_gki) $${STAGE_DIR} && " +
-         "cp $(location avbtool) $${STAGE_DIR} && " +
-         "cp $(location mkbootimg) $${STAGE_DIR} && " +
-         "cp $(location unpack_bootimg) $${STAGE_DIR} && " +
-         "cp $(in) $${STAGE_DIR} && " +
-         "$(location soong_zip) -o $(out) -C $(genDir) -D $${STAGE_DIR}",
-    out: [
-        "gki_retrofitting_tools.zip",
-    ],
-    dist: {
-        targets: [
-            "gki_retrofitting_tools",
-        ],
-    },
-}
diff --git a/gki/Android.mk b/gki/Android.mk
deleted file mode 100644
index c0af5ef..0000000
--- a/gki/Android.mk
+++ /dev/null
@@ -1,36 +0,0 @@
-#
-# Copyright (C) 2022 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-_gsi_gki_product_names := \
-  aosp_arm \
-  aosp_arm64 \
-  aosp_x86 \
-  aosp_x86_64 \
-  gsi_arm \
-  gsi_arm64 \
-  gsi_x86 \
-  gsi_x86_64 \
-  gki_arm64 \
-  gki_x86_64 \
-
-# Add gki_retrofitting_tools to `m dist` of GSI/GKI for easy pickup.
-ifneq (,$(filter $(_gsi_gki_product_names),$(TARGET_PRODUCT)))
-
-droidcore-unbundled: gki_retrofitting_tools
-
-endif
-
-_gsi_gki_product_names :=
diff --git a/gki/README.md b/gki/README.md
deleted file mode 100644
index 628e52a..0000000
--- a/gki/README.md
+++ /dev/null
@@ -1,74 +0,0 @@
-# GKI boot image retrofitting tools for upgrading devices
-
-Starting from Android T the GKI boot images consist of the generic `boot.img`
-and `init_boot.img`. The `boot.img` contains the generic kernel, and
-`init_boot.img` contains the generic ramdisk.
-For upgrading devices whose `vendor_boot` partition is non-existent, this tool
-(or spec) can be used to retrofit a set of Android T GKI `boot`, `init_boot` and
-OEM `vendor_boot` partition images back into a single boot image containing the
-GKI kernel plus generic and vendor ramdisks.
-
-## Retrofitting the boot images
-
-1. Download the certified GKI `boot.img`.
-2. Go to the build artifacts page of `aosp_arm64` on `aosp-master` branch on
-   https://ci.android.com/ and download `gki_retrofitting_tools.zip`.
-3. Unzip and make sure the tool is in `${PATH}`.
-
-   ```bash
-   unzip gki_retrofitting_tools.zip
-   export PATH="$(pwd)/gki_retrofitting_tools:${PATH}"
-   # See tool usage:
-   retrofit_gki --help
-   ```
-
-4. Create the retrofitted image. The `--version` argument lets you choose the
-   boot image header version of the retrofitted boot image. Only version 2 is
-   supported at the moment.
-
-   ```bash
-   retrofit_gki --boot boot.img --init_boot init_boot.img \
-     --vendor_boot vendor_boot.img --version 2 -o boot.retrofitted.img
-   ```
-
-## Spec of the retrofitted images
-
-* The SOURCE `boot.img` must be officially certified Android T (or later) GKI.
-* The DEST retrofitted boot image must not set the security patch level in its
-  header. This is because the SOURCE images might have different SPL value, thus
-  making the boot header SPL of the retrofitted image ill-defined. The SPL value
-  must be defined by the chained vbmeta image of the `boot` partition.
-* The `boot signature` of the DEST image is the `boot signature` of the DEST
-  `boot.img`.
-* The DEST retrofitted boot image must pass the `vts_gki_compliance_test`
-  testcase.
-
-### Retrofit to boot image V2
-
-* The `kernel` of the DEST image must be from the SOURCE `boot.img`.
-* The `ramdisk` of the DEST image must be from the SOURCE `vendor_boot.img` and
-  `init_boot.img`. The DEST `ramdisk` is the ramdisk concatenation of the vendor
-  ramdisk and generic ramdisk.
-* The `recovery dtbo / acpio` must be empty.
-* The `dtb` of the DEST image must be from the SOURCE `vendor_boot.img`.
-* The `boot_signature` section must be appended to the end of the boot image,
-  and its size is zero-padded to 16KiB.
-
-```
-  +---------------------+
-  | boot header         | 1 page
-  +---------------------+
-  | kernel              | n pages
-  +---------------------+
-  | * vendor ramdisk    |
-  |  +generic ramdisk   | m pages
-  +---------------------+
-  | second stage        | o pages
-  +---------------------+
-  | recovery dtbo/acpio | 0 byte
-  +---------------------+
-  | dtb                 | q pages
-  +---------------------+
-  | * boot signature    | 16384 (16K) bytes
-  +---------------------+
-```
diff --git a/gki/certify_bootimg.py b/gki/certify_bootimg.py
index 9a7b058..68a042e 100755
--- a/gki/certify_bootimg.py
+++ b/gki/certify_bootimg.py
@@ -132,7 +132,7 @@
     return 0
 
 
-def add_avb_footer(image, partition_size):
+def add_avb_footer(image, partition_size, extra_footer_args):
     """Appends a AVB hash footer to the image."""
 
     avbtool_cmd = ['avbtool', 'add_hash_footer', '--image', image,
@@ -143,6 +143,7 @@
     else:
         avbtool_cmd.extend(['--dynamic_partition_size'])
 
+    avbtool_cmd.extend(extra_footer_args)
     subprocess.check_call(avbtool_cmd)
 
 
@@ -160,6 +161,40 @@
     return d
 
 
+def load_gki_info_file(gki_info_file, extra_args, extra_footer_args):
+    """Loads extra arguments from the gki info file.
+
+    Args:
+        gki_info_file: path to a gki-info.txt.
+        extra_args: the extra arguments forwarded to avbtool when creating
+          the gki certificate.
+        extra_footer_args: the extra arguments forwarded to avbtool when
+          creating the avb footer.
+
+    """
+    info_dict = load_dict_from_file(gki_info_file)
+    if 'certify_bootimg_extra_args' in info_dict:
+        extra_args.extend(
+            shlex.split(info_dict['certify_bootimg_extra_args']))
+    if 'certify_bootimg_extra_footer_args' in info_dict:
+        extra_footer_args.extend(
+            shlex.split(info_dict['certify_bootimg_extra_footer_args']))
+
+
+def get_archive_name_and_format_for_shutil(path):
+    """Returns archive name and format to shutil.make_archive() for the |path|.
+
+    e.g., returns ('/path/to/boot-img', 'gztar') if |path| is
+    '/path/to/boot-img.tar.gz'.
+    """
+    for format_name, format_extensions, _ in shutil.get_unpack_formats():
+        for extension in format_extensions:
+            if path.endswith(extension):
+                return path[:-len(extension)], format_name
+
+    raise ValueError(f"Unsupported archive format: '{path}'")
+
+
 def parse_cmdline():
     """Parse command-line options."""
     parser = ArgumentParser(add_help=True)
@@ -169,30 +204,50 @@
     input_group.add_argument(
         '--boot_img', help='path to the boot image to certify')
     input_group.add_argument(
-        '--boot_img_zip', help='path to the boot-img-*.zip archive to certify')
+        '--boot_img_archive', help='path to the boot images archive to certify')
 
     parser.add_argument('--algorithm', required=True,
                         help='signing algorithm for the certificate')
     parser.add_argument('--key', required=True,
                         help='path to the RSA private key')
+    parser.add_argument('--gki_info',
+                        help='path to a gki-info.txt to append additional'
+                             'properties into the boot signature')
     parser.add_argument('-o', '--output', required=True,
                         help='output file name')
 
     # Optional args.
     parser.add_argument('--extra_args', default=[], action='append',
                         help='extra arguments to be forwarded to avbtool')
+    parser.add_argument('--extra_footer_args', default=[], action='append',
+                        help='extra arguments for adding the avb footer')
 
     args = parser.parse_args()
 
+    if args.gki_info and args.boot_img_archive:
+        parser.error('--gki_info cannot be used with --boot_image_archive. '
+                     'The gki_info file should be included in the archive.')
+
     extra_args = []
     for a in args.extra_args:
         extra_args.extend(shlex.split(a))
     args.extra_args = extra_args
 
+    extra_footer_args = []
+    for a in args.extra_footer_args:
+        extra_footer_args.extend(shlex.split(a))
+    args.extra_footer_args = extra_footer_args
+
+    if args.gki_info:
+        load_gki_info_file(args.gki_info,
+                           args.extra_args,
+                           args.extra_footer_args)
+
     return args
 
 
-def certify_bootimg(boot_img, output_img, algorithm, key, extra_args):
+def certify_bootimg(boot_img, output_img, algorithm, key, extra_args,
+                    extra_footer_args):
     """Certify a GKI boot image by generating and appending a boot_signature."""
     with tempfile.TemporaryDirectory() as temp_dir:
         boot_tmp = os.path.join(temp_dir, 'boot.tmp')
@@ -202,44 +257,53 @@
         add_certificate(boot_tmp, algorithm, key, extra_args)
 
         avb_partition_size = get_avb_image_size(boot_img)
-        add_avb_footer(boot_tmp, avb_partition_size)
+        add_avb_footer(boot_tmp, avb_partition_size, extra_footer_args)
 
         # We're done, copy the temp image to the final output.
         shutil.copy2(boot_tmp, output_img)
 
 
-def certify_bootimg_zip(boot_img_zip, output_zip, algorithm, key, extra_args):
-    """Similar to certify_bootimg(), but for a zip archive of boot images."""
-    with tempfile.TemporaryDirectory() as unzip_dir:
-        shutil.unpack_archive(boot_img_zip, unzip_dir)
+def certify_bootimg_archive(boot_img_archive, output_archive,
+                            algorithm, key, extra_args, extra_footer_args):
+    """Similar to certify_bootimg(), but for an archive of boot images."""
+    with tempfile.TemporaryDirectory() as unpack_dir:
+        shutil.unpack_archive(boot_img_archive, unpack_dir)
 
-        gki_info_file = os.path.join(unzip_dir, 'gki-info.txt')
+        gki_info_file = os.path.join(unpack_dir, 'gki-info.txt')
         if os.path.exists(gki_info_file):
-            info_dict = load_dict_from_file(gki_info_file)
-            if 'certify_bootimg_extra_args' in info_dict:
-                extra_args.extend(
-                    shlex.split(info_dict['certify_bootimg_extra_args']))
+            load_gki_info_file(gki_info_file, extra_args, extra_footer_args)
 
-        for boot_img in glob.glob(os.path.join(unzip_dir, 'boot-*.img')):
+        for boot_img in glob.glob(os.path.join(unpack_dir, 'boot*.img')):
             print(f'Certifying {os.path.basename(boot_img)} ...')
             certify_bootimg(boot_img=boot_img, output_img=boot_img,
-                            algorithm=algorithm, key=key, extra_args=extra_args)
+                            algorithm=algorithm, key=key, extra_args=extra_args,
+                            extra_footer_args=extra_footer_args)
 
-        print(f'Making certified archive: {output_zip}')
-        archive_base_name = os.path.splitext(output_zip)[0]
-        shutil.make_archive(archive_base_name, 'zip', unzip_dir)
+        print(f'Making certified archive: {output_archive}')
+        archive_file_name, archive_format = (
+            get_archive_name_and_format_for_shutil(output_archive))
+        built_archive = shutil.make_archive(archive_file_name,
+                                            archive_format,
+                                            unpack_dir)
+        # shutil.make_archive() builds *.tar.gz when then |archive_format| is
+        # 'gztar'. However, the end user might specify |output_archive| with
+        # *.tgz. Renaming *.tar.gz to *.tgz for this case.
+        if built_archive != os.path.realpath(output_archive):
+            print(f'Renaming {built_archive} -> {output_archive} ...')
+            os.rename(built_archive, output_archive)
 
 
 def main():
     """Parse arguments and certify the boot image."""
     args = parse_cmdline()
 
-    if args.boot_img_zip:
-        certify_bootimg_zip(args.boot_img_zip, args.output, args.algorithm,
-                            args.key, args.extra_args)
+    if args.boot_img_archive:
+        certify_bootimg_archive(args.boot_img_archive, args.output,
+                                args.algorithm, args.key, args.extra_args,
+                                args.extra_footer_args)
     else:
         certify_bootimg(args.boot_img, args.output, args.algorithm,
-                        args.key, args.extra_args)
+                        args.key, args.extra_args, args.extra_footer_args)
 
 
 if __name__ == '__main__':
diff --git a/gki/certify_bootimg_test.py b/gki/certify_bootimg_test.py
index 8c7c4d3..ec5f505 100644
--- a/gki/certify_bootimg_test.py
+++ b/gki/certify_bootimg_test.py
@@ -68,20 +68,27 @@
         subprocess.check_call(avbtool_cmd)
 
 
-def generate_test_boot_image_archive(output_zip, boot_img_info, gki_info=None):
-    """Generates a zip archive of test boot images.
+def generate_test_boot_image_archive(archive_file_name, archive_format,
+                                     boot_img_info, gki_info=None):
+    """Generates an archive of test boot images.
 
     It also adds a file gki-info.txt, which contains additional settings for
     for `certify_bootimg --extra_args`.
 
     Args:
-        output_zip: the output zip archive, e.g., /path/to/boot-img.zip.
+        archive_file_name: the name of the archive file to create, including the
+          path, minus any format-specific extension.
+        archive_format: the |format| parameter for shutil.make_archive().
+          e.g., 'zip', 'tar', or 'gztar', etc.
         boot_img_info: a list of (boot_image_name, kernel_size,
           partition_size) tuples. e.g.,
-          [('boot-1.0.img', 4096, 4 * 1024),
-           ('boot-2.0.img', 8192, 8 * 1024)].
+          [('boot.img', 4096, 4 * 1024),
+           ('boot-lz4.img', 8192, 8 * 1024)].
         gki_info: the file content to be written into 'gki-info.txt' in the
-          |output_zip|.
+          created archive.
+
+    Returns:
+        The full path of the created archive. e.g., /path/to/boot-img.tar.gz.
     """
     with tempfile.TemporaryDirectory() as temp_out_dir:
         for name, kernel_size, partition_size in boot_img_info:
@@ -96,8 +103,9 @@
             with open(gki_info_path, 'w', encoding='utf-8') as f:
                 f.write(gki_info)
 
-        archive_base_name = os.path.splitext(output_zip)[0]
-        shutil.make_archive(archive_base_name, 'zip', temp_out_dir)
+        return shutil.make_archive(archive_file_name,
+                                   archive_format,
+                                   temp_out_dir)
 
 
 def has_avb_footer(image):
@@ -175,21 +183,21 @@
         boot_signature_bytes = boot_signature_bytes[next_signature_size:]
 
 
-def extract_boot_archive_with_signatures(boot_img_zip, output_dir):
+def extract_boot_archive_with_signatures(boot_img_archive, output_dir):
     """Extracts boot images and signatures of a boot images archive.
 
-    Suppose there are two boot images in |boot_img_zip|: boot-1.0.img
-    and boot-2.0.img. This function then extracts each boot-*.img and
+    Suppose there are two boot images in |boot_img_archive|: boot.img
+    and boot-lz4.img. This function then extracts each boot*.img and
     their signatures as:
-      - |output_dir|/boot-1.0.img
-      - |output_dir|/boot-2.0.img
-      - |output_dir|/boot-1.0/boot_signature1
-      - |output_dir|/boot-1.0/boot_signature2
-      - |output_dir|/boot-2.0/boot_signature1
-      - |output_dir|/boot-2.0/boot_signature2
+      - |output_dir|/boot.img
+      - |output_dir|/boot-lz4.img
+      - |output_dir|/boot/boot_signature1
+      - |output_dir|/boot/boot_signature2
+      - |output_dir|/boot-lz4/boot_signature1
+      - |output_dir|/boot-lz4/boot_signature2
     """
-    shutil.unpack_archive(boot_img_zip, output_dir)
-    for boot_img in glob.glob(os.path.join(output_dir, 'boot-*.img')):
+    shutil.unpack_archive(boot_img_archive, output_dir)
+    for boot_img in glob.glob(os.path.join(output_dir, 'boot*.img')):
         img_name = os.path.splitext(os.path.basename(boot_img))[0]
         signature_output_dir = os.path.join(output_dir, img_name)
         os.mkdir(signature_output_dir, 0o777)
@@ -211,6 +219,197 @@
         # C0103: invalid-name for maxDiff.
         self.maxDiff = None  # pylint: disable=C0103
 
+        # For AVB footers, we don't sign it so the Authentication block
+        # is zero bytes and the Algorithm is NONE. The footer will be
+        # replaced by device-specific settings when being incorporated into
+        # a device codebase. The footer here is just to pass some GKI
+        # pre-release test.
+        self._EXPECTED_AVB_FOOTER_BOOT_CERTIFIED = (    # pylint: disable=C0103
+            'Footer version:           1.0\n'
+            'Image size:               131072 bytes\n'
+            'Original image size:      24576 bytes\n'
+            'VBMeta offset:            24576\n'
+            'VBMeta size:              576 bytes\n'
+            '--\n'
+            'Minimum libavb version:   1.0\n'
+            'Header Block:             256 bytes\n'
+            'Authentication Block:     0 bytes\n'
+            'Auxiliary Block:          320 bytes\n'
+            'Algorithm:                NONE\n'
+            'Rollback Index:           0\n'
+            'Flags:                    0\n'
+            'Rollback Index Location:  0\n'
+            "Release String:           'avbtool 1.2.0'\n"
+            'Descriptors:\n'
+            '    Hash descriptor:\n'
+            '      Image Size:            24576 bytes\n'
+            '      Hash Algorithm:        sha256\n'
+            '      Partition Name:        boot\n'
+            '      Salt:                  a11ba11b\n'
+            '      Digest:                '
+            'c9b4ad78fae6f72f7eff939dee6078ed'
+            '8a75132e53f6c11ba1ec0f4b57f9eab0\n'
+            '      Flags:                 0\n'
+            "    Prop: avb -> 'nice'\n"
+            "    Prop: avb_space -> 'nice to meet you'\n"
+        )
+
+        self._EXPECTED_AVB_FOOTER_BOOT_CERTIFIED_2 = (  # pylint: disable=C0103
+            'Footer version:           1.0\n'
+            'Image size:               131072 bytes\n'
+            'Original image size:      24576 bytes\n'
+            'VBMeta offset:            24576\n'
+            'VBMeta size:              576 bytes\n'
+            '--\n'
+            'Minimum libavb version:   1.0\n'
+            'Header Block:             256 bytes\n'
+            'Authentication Block:     0 bytes\n'
+            'Auxiliary Block:          320 bytes\n'
+            'Algorithm:                NONE\n'
+            'Rollback Index:           0\n'
+            'Flags:                    0\n'
+            'Rollback Index Location:  0\n'
+            "Release String:           'avbtool 1.2.0'\n"
+            'Descriptors:\n'
+            '    Hash descriptor:\n'
+            '      Image Size:            24576 bytes\n'
+            '      Hash Algorithm:        sha256\n'
+            '      Partition Name:        boot\n'
+            '      Salt:                  a11ba11b\n'
+            '      Digest:                '
+            'ae2538e78b2a30b1112cede30d858a5f'
+            '6f8dc2a1b109dd4a7bb28124b77d2ab0\n'
+            '      Flags:                 0\n'
+            "    Prop: avb -> 'nice'\n"
+            "    Prop: avb_space -> 'nice to meet you'\n"
+        )
+
+        self._EXPECTED_AVB_FOOTER_WITH_GKI_INFO = (     # pylint: disable=C0103
+            'Footer version:           1.0\n'
+            'Image size:               131072 bytes\n'
+            'Original image size:      24576 bytes\n'
+            'VBMeta offset:            24576\n'
+            'VBMeta size:              704 bytes\n'
+            '--\n'
+            'Minimum libavb version:   1.0\n'
+            'Header Block:             256 bytes\n'
+            'Authentication Block:     0 bytes\n'
+            'Auxiliary Block:          448 bytes\n'
+            'Algorithm:                NONE\n'
+            'Rollback Index:           0\n'
+            'Flags:                    0\n'
+            'Rollback Index Location:  0\n'
+            "Release String:           'avbtool 1.2.0'\n"
+            'Descriptors:\n'
+            '    Hash descriptor:\n'
+            '      Image Size:            24576 bytes\n'
+            '      Hash Algorithm:        sha256\n'
+            '      Partition Name:        boot\n'
+            '      Salt:                  a11ba11b\n'
+            '      Digest:                '
+            '363d4f246a4a5e1bba8ba8b86f5eb0cf'
+            '9817e4e51663ba26edccf71c3861090a\n'
+            '      Flags:                 0\n'
+            "    Prop: avb -> 'nice'\n"
+            "    Prop: avb_space -> 'nice to meet you'\n"
+            "    Prop: com.android.build.boot.os_version -> '13'\n"
+            "    Prop: com.android.build.boot.security_patch -> '2022-05-05'\n"
+        )
+
+        self._EXPECTED_AVB_FOOTER_BOOT = (              # pylint: disable=C0103
+            'Footer version:           1.0\n'
+            'Image size:               131072 bytes\n'
+            'Original image size:      28672 bytes\n'
+            'VBMeta offset:            28672\n'
+            'VBMeta size:              704 bytes\n'
+            '--\n'
+            'Minimum libavb version:   1.0\n'
+            'Header Block:             256 bytes\n'
+            'Authentication Block:     0 bytes\n'
+            'Auxiliary Block:          448 bytes\n'
+            'Algorithm:                NONE\n'
+            'Rollback Index:           0\n'
+            'Flags:                    0\n'
+            'Rollback Index Location:  0\n'
+            "Release String:           'avbtool 1.2.0'\n"
+            'Descriptors:\n'
+            '    Hash descriptor:\n'
+            '      Image Size:            28672 bytes\n'
+            '      Hash Algorithm:        sha256\n'
+            '      Partition Name:        boot\n'
+            '      Salt:                  a11ba11b\n'
+            '      Digest:                '
+            'b93084707ba2367120e19547f17f1073'
+            '4c7ad8e56008ec2159d5f01b950335ad\n'
+            '      Flags:                 0\n'
+            "    Prop: avb -> 'nice'\n"
+            "    Prop: avb_space -> 'nice to meet you'\n"
+            "    Prop: com.android.build.boot.os_version -> '13'\n"
+            "    Prop: com.android.build.boot.security_patch -> '2022-05-05'\n"
+        )
+
+        self._EXPECTED_AVB_FOOTER_BOOT_LZ4 = (          # pylint: disable=C0103
+            'Footer version:           1.0\n'
+            'Image size:               262144 bytes\n'
+            'Original image size:      36864 bytes\n'
+            'VBMeta offset:            36864\n'
+            'VBMeta size:              704 bytes\n'
+            '--\n'
+            'Minimum libavb version:   1.0\n'
+            'Header Block:             256 bytes\n'
+            'Authentication Block:     0 bytes\n'
+            'Auxiliary Block:          448 bytes\n'
+            'Algorithm:                NONE\n'
+            'Rollback Index:           0\n'
+            'Flags:                    0\n'
+            'Rollback Index Location:  0\n'
+            "Release String:           'avbtool 1.2.0'\n"
+            'Descriptors:\n'
+            '    Hash descriptor:\n'
+            '      Image Size:            36864 bytes\n'
+            '      Hash Algorithm:        sha256\n'
+            '      Partition Name:        boot\n'
+            '      Salt:                  a11ba11b\n'
+            '      Digest:                '
+            '6b3f583f1bc5fbc284102e0185d02c6b'
+            '294f675c95b9337e89ea1e6b743af2ab\n'
+            '      Flags:                 0\n'
+            "    Prop: avb -> 'nice'\n"
+            "    Prop: avb_space -> 'nice to meet you'\n"
+            "    Prop: com.android.build.boot.os_version -> '13'\n"
+            "    Prop: com.android.build.boot.security_patch -> '2022-05-05'\n"
+        )
+
+        self._EXPECTED_AVB_FOOTER_BOOT_GZ = (           # pylint: disable=C0103
+            'Footer version:           1.0\n'
+            'Image size:               131072 bytes\n'
+            'Original image size:      28672 bytes\n'
+            'VBMeta offset:            28672\n'
+            'VBMeta size:              576 bytes\n'
+            '--\n'
+            'Minimum libavb version:   1.0\n'
+            'Header Block:             256 bytes\n'
+            'Authentication Block:     0 bytes\n'
+            'Auxiliary Block:          320 bytes\n'
+            'Algorithm:                NONE\n'
+            'Rollback Index:           0\n'
+            'Flags:                    0\n'
+            'Rollback Index Location:  0\n'
+            "Release String:           'avbtool 1.2.0'\n"
+            'Descriptors:\n'
+            '    Hash descriptor:\n'
+            '      Image Size:            28672 bytes\n'
+            '      Hash Algorithm:        sha256\n'
+            '      Partition Name:        boot\n'
+            '      Salt:                  a11ba11b\n'
+            '      Digest:                '
+            'd2098d507e039afc6b4d7ec3de129a8d'
+            'd0e0cf889c9181ebee65ce2fb25de3f5\n'
+            '      Flags:                 0\n'
+            "    Prop: avb -> 'nice'\n"
+            "    Prop: avb_space -> 'nice to meet you'\n"
+        )
+
         self._EXPECTED_BOOT_SIGNATURE_RSA2048 = (       # pylint: disable=C0103
             'Minimum libavb version:   1.0\n'
             'Header Block:             256 bytes\n'
@@ -315,7 +514,69 @@
             "    Prop: space -> 'nice to meet you'\n"
         )
 
-        self._EXPECTED_BOOT_1_0_SIGNATURE1_RSA4096 = (   # pylint: disable=C0103
+        self._EXPECTED_BOOT_SIGNATURE_WITH_GKI_INFO = (  # pylint: disable=C0103
+            'Minimum libavb version:   1.0\n'
+            'Header Block:             256 bytes\n'
+            'Authentication Block:     576 bytes\n'
+            'Auxiliary Block:          1600 bytes\n'
+            'Public key (sha1):        '
+            '2597c218aae470a130f61162feaae70afd97f011\n'
+            'Algorithm:                SHA256_RSA4096\n' # RSA4096
+            'Rollback Index:           0\n'
+            'Flags:                    0\n'
+            'Rollback Index Location:  0\n'
+            "Release String:           'avbtool 1.2.0'\n"
+            'Descriptors:\n'
+            '    Hash descriptor:\n'
+            '      Image Size:            8192 bytes\n'
+            '      Hash Algorithm:        sha256\n'
+            '      Partition Name:        boot\n'        # boot
+            '      Salt:                  d00df00d\n'
+            '      Digest:                '
+            'faf1da72a4fba97ddab0b8f7a410db86'
+            '8fb72392a66d1440ff8bff490c73c771\n'
+            '      Flags:                 0\n'
+            "    Prop: gki -> 'nice'\n"
+            "    Prop: space -> 'nice to meet you'\n"
+            "    Prop: KERNEL_RELEASE -> '5.10.42-android13-0-00544-"
+            "ged21d463f856'\n"
+            "    Prop: BRANCH -> 'android13-5.10-2022-05'\n"
+            "    Prop: BUILD_NUMBER -> 'ab8295296'\n"
+            "    Prop: GKI_INFO -> 'added here'\n"
+        )
+
+        self._EXPECTED_KERNEL_SIGNATURE_WITH_GKI_INFO = (# pylint: disable=C0103
+            'Minimum libavb version:   1.0\n'
+            'Header Block:             256 bytes\n'
+            'Authentication Block:     576 bytes\n'
+            'Auxiliary Block:          1600 bytes\n'
+            'Public key (sha1):        '
+            '2597c218aae470a130f61162feaae70afd97f011\n'
+            'Algorithm:                SHA256_RSA4096\n' # RSA4096
+            'Rollback Index:           0\n'
+            'Flags:                    0\n'
+            'Rollback Index Location:  0\n'
+            "Release String:           'avbtool 1.2.0'\n"
+            'Descriptors:\n'
+            '    Hash descriptor:\n'
+            '      Image Size:            4096 bytes\n'
+            '      Hash Algorithm:        sha256\n'
+            '      Partition Name:        generic_kernel\n' # generic_kernel
+            '      Salt:                  d00df00d\n'
+            '      Digest:                '
+            '762c877f3af0d50a4a4fbc1385d5c7ce'
+            '52a1288db74b33b72217d93db6f2909f\n'
+            '      Flags:                 0\n'
+            "    Prop: gki -> 'nice'\n"
+            "    Prop: space -> 'nice to meet you'\n"
+            "    Prop: KERNEL_RELEASE -> '5.10.42-android13-0-00544-"
+            "ged21d463f856'\n"
+            "    Prop: BRANCH -> 'android13-5.10-2022-05'\n"
+            "    Prop: BUILD_NUMBER -> 'ab8295296'\n"
+            "    Prop: GKI_INFO -> 'added here'\n"
+        )
+
+        self._EXPECTED_BOOT_SIGNATURE1_RSA4096 = (       # pylint: disable=C0103
             'Minimum libavb version:   1.0\n'
             'Header Block:             256 bytes\n'
             'Authentication Block:     576 bytes\n'
@@ -334,8 +595,8 @@
             '      Partition Name:        boot\n'           # boot
             '      Salt:                  d00df00d\n'
             '      Digest:                '
-            '88465e463bffb9f7dfc0c1f46d01bcf3'
-            '15f7693e19bd188a0ca1feca2ed7b9df\n'
+            '30208b4d0a6d16db47fc13c9527bfe81'
+            'a168d3b3940325d1ca8d3439792bfe18\n'
             '      Flags:                 0\n'
             "    Prop: gki -> 'nice'\n"
             "    Prop: space -> 'nice to meet you'\n"
@@ -346,7 +607,7 @@
             "    Prop: SPACE -> 'nice to meet you'\n"
         )
 
-        self._EXPECTED_BOOT_1_0_SIGNATURE2_RSA4096 = (   # pylint: disable=C0103
+        self._EXPECTED_BOOT_SIGNATURE2_RSA4096 = (       # pylint: disable=C0103
             'Minimum libavb version:   1.0\n'
             'Header Block:             256 bytes\n'
             'Authentication Block:     576 bytes\n'
@@ -365,8 +626,8 @@
             '      Partition Name:        generic_kernel\n' # generic_kernel
             '      Salt:                  d00df00d\n'
             '      Digest:                '
-            '14ac8d0d233e57a317acd05cd458f2bb'
-            'cc78725ef9f66c1b38e90697fb09d943\n'
+            'd4c8847e7d9900a98f77e1f0b5272854'
+            '7bf9c1e428fea500d419275f72ec5bd6\n'
             '      Flags:                 0\n'
             "    Prop: gki -> 'nice'\n"
             "    Prop: space -> 'nice to meet you'\n"
@@ -377,7 +638,7 @@
             "    Prop: SPACE -> 'nice to meet you'\n"
         )
 
-        self._EXPECTED_BOOT_2_0_SIGNATURE1_RSA4096 = (   # pylint: disable=C0103
+        self._EXPECTED_BOOT_LZ4_SIGNATURE1_RSA4096 = (   # pylint: disable=C0103
             'Minimum libavb version:   1.0\n'
             'Header Block:             256 bytes\n'
             'Authentication Block:     576 bytes\n'
@@ -396,8 +657,8 @@
             '      Partition Name:        boot\n'           # boot
             '      Salt:                  d00df00d\n'
             '      Digest:                '
-            '3e6a9854a9d2350a7071083bc3f37376'
-            '37573fd87b1c72b146cb4870ac6af36f\n'
+            '9d3a0670a9fd3de66e940117ef97700f'
+            'ed5fd1c6fb90798fd3873af45fc91cb4\n'
             '      Flags:                 0\n'
             "    Prop: gki -> 'nice'\n"
             "    Prop: space -> 'nice to meet you'\n"
@@ -408,7 +669,7 @@
             "    Prop: SPACE -> 'nice to meet you'\n"
         )
 
-        self._EXPECTED_BOOT_2_0_SIGNATURE2_RSA4096 = (   # pylint: disable=C0103
+        self._EXPECTED_BOOT_LZ4_SIGNATURE2_RSA4096 = (   # pylint: disable=C0103
             'Minimum libavb version:   1.0\n'
             'Header Block:             256 bytes\n'
             'Authentication Block:     576 bytes\n'
@@ -427,8 +688,8 @@
             '      Partition Name:        generic_kernel\n' # generic_kernel
             '      Salt:                  d00df00d\n'
             '      Digest:                '
-            '92fb8443cd284b67a4cbf5ce00348b50'
-            '1c657e0aedf4e2181c92ad7fc8b5224f\n'
+            '7d109e3dccca9e30e04249162d07e58c'
+            '62fdf269804b35857b956fba339b2679\n'
             '      Flags:                 0\n'
             "    Prop: gki -> 'nice'\n"
             "    Prop: space -> 'nice to meet you'\n"
@@ -439,7 +700,7 @@
             "    Prop: SPACE -> 'nice to meet you'\n"
         )
 
-        self._EXPECTED_BOOT_3_0_SIGNATURE1_RSA4096 = (   # pylint: disable=C0103
+        self._EXPECTED_BOOT_GZ_SIGNATURE1_RSA4096 = (    # pylint: disable=C0103
             'Minimum libavb version:   1.0\n'
             'Header Block:             256 bytes\n'
             'Authentication Block:     576 bytes\n'
@@ -458,14 +719,14 @@
             '      Partition Name:        boot\n'           # boot
             '      Salt:                  d00df00d\n'
             '      Digest:                '
-            '9b9cd845a367d7fc9b61d6ac02b0e7c9'
-            'dc3d3b219abf60dd6e19359f0353c917\n'
+            '6fcddc6167ae3c2037b424d35c3ef107'
+            'f586510dbb2d652d7c08b88e6ea52fc6\n'
             '      Flags:                 0\n'
             "    Prop: gki -> 'nice'\n"
             "    Prop: space -> 'nice to meet you'\n"
         )
 
-        self._EXPECTED_BOOT_3_0_SIGNATURE2_RSA4096 = (   # pylint: disable=C0103
+        self._EXPECTED_BOOT_GZ_SIGNATURE2_RSA4096 = (    # pylint: disable=C0103
             'Minimum libavb version:   1.0\n'
             'Header Block:             256 bytes\n'
             'Authentication Block:     576 bytes\n'
@@ -484,8 +745,8 @@
             '      Partition Name:        generic_kernel\n' # generic_kernel
             '      Salt:                  d00df00d\n'
             '      Digest:                '
-            '0cd7d331ed9b32dcd92f00e2cac75595'
-            '52199170afe788a8fcf1954f9ea072d0\n'
+            '7a6a43eb4048b783346fb6d039103647'
+            '6c4313146da521467af282dff1838d0e\n'
             '      Flags:                 0\n'
             "    Prop: gki -> 'nice'\n"
             "    Prop: space -> 'nice to meet you'\n"
@@ -577,6 +838,8 @@
                 '--key', './testdata/testkey_rsa2048.pem',
                 '--extra_args', '--prop gki:nice '
                 '--prop space:"nice to meet you"',
+                '--extra_footer_args', '--salt a11ba11b --prop avb:nice '
+                '--prop avb_space:"nice to meet you"',
                 '--output', boot_certified_img,
             ]
             subprocess.run(certify_bootimg_cmds, check=True, cwd=self._exec_dir)
@@ -585,7 +848,13 @@
             self.assertTrue(has_avb_footer(boot_certified_img))
             self.assertEqual(os.path.getsize(boot_img),
                              os.path.getsize(boot_certified_img))
+            # Checks the content in the AVB footer.
+            self._test_boot_signatures(
+                temp_out_dir,
+                {'boot-certified.img':
+                    self._EXPECTED_AVB_FOOTER_BOOT_CERTIFIED})
 
+            # Checks the content in the GKI certificate.
             extract_boot_signatures(boot_certified_img, temp_out_dir)
             self._test_boot_signatures(
                 temp_out_dir,
@@ -602,6 +871,8 @@
                 '--key', './testdata/testkey_rsa4096.pem',
                 '--extra_args', '--prop gki:nice '
                 '--prop space:"nice to meet you"',
+                '--extra_footer_args', '--salt a11ba11b --prop avb:nice '
+                '--prop avb_space:"nice to meet you"',
                 '--output', boot_certified2_img,
             ]
             subprocess.run(certify_bootimg_cmds, check=True, cwd=self._exec_dir)
@@ -610,13 +881,77 @@
             self.assertTrue(has_avb_footer(boot_certified2_img))
             self.assertEqual(os.path.getsize(boot_certified_img),
                              os.path.getsize(boot_certified2_img))
+            # Checks the content in the AVB footer.
+            self._test_boot_signatures(
+                temp_out_dir,
+                {'boot-certified2.img':
+                    self._EXPECTED_AVB_FOOTER_BOOT_CERTIFIED_2})
 
+            # Checks the content in the GKI certificate.
             extract_boot_signatures(boot_certified2_img, temp_out_dir)
             self._test_boot_signatures(
                 temp_out_dir,
                 {'boot_signature1': self._EXPECTED_BOOT_SIGNATURE_RSA4096,
                  'boot_signature2': self._EXPECTED_KERNEL_SIGNATURE_RSA4096})
 
+    def test_certify_bootimg_with_gki_info(self):
+        """Tests certify_bootimg with --gki_info."""
+        with tempfile.TemporaryDirectory() as temp_out_dir:
+            boot_img = os.path.join(temp_out_dir, 'boot.img')
+            generate_test_boot_image(boot_img=boot_img,
+                                     avb_partition_size=128 * 1024)
+            self.assertTrue(has_avb_footer(boot_img))
+
+            gki_info = ('certify_bootimg_extra_args='
+                        '--prop KERNEL_RELEASE:5.10.42'
+                        '-android13-0-00544-ged21d463f856 '
+                        '--prop BRANCH:android13-5.10-2022-05 '
+                        '--prop BUILD_NUMBER:ab8295296 '
+                        '--prop GKI_INFO:"added here"\n'
+                        'certify_bootimg_extra_footer_args='
+                        '--prop com.android.build.boot.os_version:13 '
+                        '--prop com.android.build.boot.security_patch:'
+                        '2022-05-05\n')
+            gki_info_path = os.path.join(temp_out_dir, 'gki-info.txt')
+            with open(gki_info_path, 'w', encoding='utf-8') as f:
+                f.write(gki_info)
+
+            # Certifies the boot image with --gki_info.
+            boot_certified_img = os.path.join(temp_out_dir,
+                                              'boot-certified.img')
+            certify_bootimg_cmds = [
+                'certify_bootimg',
+                '--boot_img', boot_img,
+                '--algorithm', 'SHA256_RSA4096',
+                '--key', './testdata/testkey_rsa4096.pem',
+                '--extra_args', '--prop gki:nice '
+                '--prop space:"nice to meet you"',
+                '--extra_footer_args', '--salt a11ba11b --prop avb:nice '
+                '--prop avb_space:"nice to meet you"',
+                '--gki_info', gki_info_path,
+                '--output', boot_certified_img,
+            ]
+            subprocess.run(certify_bootimg_cmds, check=True, cwd=self._exec_dir)
+
+            # Checks an AVB footer exists and the image size remains.
+            self.assertTrue(has_avb_footer(boot_certified_img))
+            self.assertEqual(os.path.getsize(boot_img),
+                             os.path.getsize(boot_certified_img))
+
+            # Checks the content in the AVB footer.
+            self._test_boot_signatures(
+                temp_out_dir,
+                {'boot-certified.img': self._EXPECTED_AVB_FOOTER_WITH_GKI_INFO})
+
+            # Checks the content in the GKI certificate.
+            extract_boot_signatures(boot_certified_img, temp_out_dir)
+            self._test_boot_signatures(
+                temp_out_dir,
+                {'boot_signature1':
+                    self._EXPECTED_BOOT_SIGNATURE_WITH_GKI_INFO,
+                 'boot_signature2':
+                    self._EXPECTED_KERNEL_SIGNATURE_WITH_GKI_INFO})
+
     def test_certify_bootimg_exceed_size(self):
         """Tests the boot signature size exceeded max size of the signature."""
         with tempfile.TemporaryDirectory() as temp_out_dir:
@@ -647,121 +982,147 @@
                               err.stderr)
 
     def test_certify_bootimg_archive(self):
-        """Tests certify_bootimg for a boot-img.zip."""
+        """Tests certify_bootimg for a boot images archive.."""
         with tempfile.TemporaryDirectory() as temp_out_dir:
-            boot_img_zip = os.path.join(temp_out_dir, 'boot-img.zip')
+            boot_img_archive_name = os.path.join(temp_out_dir, 'boot-img')
             gki_info = ('certify_bootimg_extra_args='
                         '--prop KERNEL_RELEASE:5.10.42'
                         '-android13-0-00544-ged21d463f856 '
                         '--prop BRANCH:android13-5.10-2022-05 '
                         '--prop BUILD_NUMBER:ab8295296 '
-                        '--prop SPACE:"nice to meet you"\n')
-            generate_test_boot_image_archive(
-                boot_img_zip,
+                        '--prop SPACE:"nice to meet you"\n'
+                        'certify_bootimg_extra_footer_args='
+                        '--prop com.android.build.boot.os_version:13 '
+                        '--prop com.android.build.boot.security_patch:'
+                        '2022-05-05\n')
+            boot_img_archive_path = generate_test_boot_image_archive(
+                boot_img_archive_name,
+                'gztar',
                 # A list of (boot_img_name, kernel_size, partition_size).
-                [('boot-1.0.img', 8 * 1024, 128 * 1024),
-                 ('boot-2.0.img', 16 * 1024, 256 * 1024)],
+                [('boot.img', 8 * 1024, 128 * 1024),
+                 ('boot-lz4.img', 16 * 1024, 256 * 1024)],
                 gki_info)
 
             # Certify the boot image archive, with a RSA4096 key.
-            boot_certified_img_zip = os.path.join(temp_out_dir,
-                                                  'boot-certified-img.zip')
+            boot_certified_img_archive = os.path.join(
+                temp_out_dir, 'boot-certified-img.tar.gz')
             certify_bootimg_cmds = [
                 'certify_bootimg',
-                '--boot_img_zip', boot_img_zip,
+                '--boot_img_archive', boot_img_archive_path,
                 '--algorithm', 'SHA256_RSA4096',
                 '--key', './testdata/testkey_rsa4096.pem',
                 '--extra_args', '--prop gki:nice '
                 '--prop space:"nice to meet you"',
-                '--output', boot_certified_img_zip,
+                '--extra_footer_args', '--salt a11ba11b --prop avb:nice '
+                '--prop avb_space:"nice to meet you"',
+                '--output', boot_certified_img_archive,
             ]
             subprocess.run(certify_bootimg_cmds, check=True, cwd=self._exec_dir)
 
-            extract_boot_archive_with_signatures(boot_certified_img_zip,
+            extract_boot_archive_with_signatures(boot_certified_img_archive,
                                                  temp_out_dir)
 
             # Checks an AVB footer exists and the image size remains.
-            boot_1_img = os.path.join(temp_out_dir, 'boot-1.0.img')
-            self.assertTrue(has_avb_footer(boot_1_img))
-            self.assertEqual(os.path.getsize(boot_1_img), 128 * 1024)
+            boot_img = os.path.join(temp_out_dir, 'boot.img')
+            self.assertTrue(has_avb_footer(boot_img))
+            self.assertEqual(os.path.getsize(boot_img), 128 * 1024)
 
-            boot_2_img = os.path.join(temp_out_dir, 'boot-2.0.img')
-            self.assertTrue(has_avb_footer(boot_2_img))
-            self.assertEqual(os.path.getsize(boot_2_img), 256 * 1024)
+            boot_lz4_img = os.path.join(temp_out_dir, 'boot-lz4.img')
+            self.assertTrue(has_avb_footer(boot_lz4_img))
+            self.assertEqual(os.path.getsize(boot_lz4_img), 256 * 1024)
 
+            # Checks the content in the AVB footer.
             self._test_boot_signatures(
                 temp_out_dir,
-                {'boot-1.0/boot_signature1':
-                    self._EXPECTED_BOOT_1_0_SIGNATURE1_RSA4096,
-                 'boot-1.0/boot_signature2':
-                    self._EXPECTED_BOOT_1_0_SIGNATURE2_RSA4096,
-                 'boot-2.0/boot_signature1':
-                    self._EXPECTED_BOOT_2_0_SIGNATURE1_RSA4096,
-                 'boot-2.0/boot_signature2':
-                    self._EXPECTED_BOOT_2_0_SIGNATURE2_RSA4096})
+                {'boot.img': self._EXPECTED_AVB_FOOTER_BOOT,
+                 'boot-lz4.img': self._EXPECTED_AVB_FOOTER_BOOT_LZ4})
+
+            # Checks the content in the GKI certificate.
+            self._test_boot_signatures(
+                temp_out_dir,
+                {'boot/boot_signature1':
+                    self._EXPECTED_BOOT_SIGNATURE1_RSA4096,
+                 'boot/boot_signature2':
+                    self._EXPECTED_BOOT_SIGNATURE2_RSA4096,
+                 'boot-lz4/boot_signature1':
+                    self._EXPECTED_BOOT_LZ4_SIGNATURE1_RSA4096,
+                 'boot-lz4/boot_signature2':
+                    self._EXPECTED_BOOT_LZ4_SIGNATURE2_RSA4096})
 
     def test_certify_bootimg_archive_without_gki_info(self):
-        """Tests certify_bootimg for a boot-img.zip."""
+        """Tests certify_bootimg for a boot images archive."""
         with tempfile.TemporaryDirectory() as temp_out_dir:
-            boot_img_zip = os.path.join(temp_out_dir, 'boot-img.zip')
+            boot_img_archive_name = os.path.join(temp_out_dir, 'boot-img')
 
-            # Checks ceritfy_bootimg works for a boot-img.zip without a
-            # gki-info.txt.
-            generate_test_boot_image_archive(
-                boot_img_zip,
+            # Checks ceritfy_bootimg works for a boot images archive without a
+            # gki-info.txt. Using *.zip -> *.tar.
+            boot_img_archive_path = generate_test_boot_image_archive(
+                boot_img_archive_name,
+                'zip',
                 # A list of (boot_img_name, kernel_size, partition_size).
-                [('boot-3.0.img', 8 * 1024, 128 * 1024)],
+                [('boot-gz.img', 8 * 1024, 128 * 1024)],
                 gki_info=None)
             # Certify the boot image archive, with a RSA4096 key.
-            boot_certified_img_zip = os.path.join(temp_out_dir,
-                                                  'boot-certified-img.zip')
+            boot_certified_img_archive = os.path.join(
+                temp_out_dir, 'boot-certified-img.tar')
             certify_bootimg_cmds = [
                 'certify_bootimg',
-                '--boot_img_zip', boot_img_zip,
+                '--boot_img_archive', boot_img_archive_path,
                 '--algorithm', 'SHA256_RSA4096',
                 '--key', './testdata/testkey_rsa4096.pem',
                 '--extra_args', '--prop gki:nice '
                 '--prop space:"nice to meet you"',
-                '--output', boot_certified_img_zip,
+                '--extra_footer_args', '--salt a11ba11b --prop avb:nice '
+                '--prop avb_space:"nice to meet you"',
+                '--output', boot_certified_img_archive,
             ]
             subprocess.run(certify_bootimg_cmds, check=True, cwd=self._exec_dir)
 
-            # Checks ceritfy_bootimg works for a boot-img.zip with a special
-            # gki-info.txt.
-            generate_test_boot_image_archive(
-                boot_img_zip,
+            # Checks ceritfy_bootimg works for a boot images archive with a
+            # special gki-info.txt. Using *.tar -> *.tgz.
+            boot_img_archive_path = generate_test_boot_image_archive(
+                boot_img_archive_name,
+                'tar',
                 # A list of (boot_img_name, kernel_size, partition_size).
-                [('boot-3.0.img', 8 * 1024, 128 * 1024)],
+                [('boot-gz.img', 8 * 1024, 128 * 1024)],
                 gki_info='a=b\n'
                          'c=d\n')
             # Certify the boot image archive, with a RSA4096 key.
-            boot_certified_img_zip = os.path.join(temp_out_dir,
-                                                  'boot-certified-img.zip')
+            boot_certified_img_archive2 = os.path.join(
+                temp_out_dir, 'boot-certified-img.tgz')
             certify_bootimg_cmds = [
                 'certify_bootimg',
-                '--boot_img_zip', boot_img_zip,
+                '--boot_img_archive', boot_img_archive_path,
                 '--algorithm', 'SHA256_RSA4096',
                 '--key', './testdata/testkey_rsa4096.pem',
                 '--extra_args', '--prop gki:nice '
                 '--prop space:"nice to meet you"',
-                '--output', boot_certified_img_zip,
+                '--extra_footer_args', '--salt a11ba11b --prop avb:nice '
+                '--prop avb_space:"nice to meet you"',
+                '--output', boot_certified_img_archive2,
             ]
             subprocess.run(certify_bootimg_cmds, check=True, cwd=self._exec_dir)
 
-            extract_boot_archive_with_signatures(boot_certified_img_zip,
+            extract_boot_archive_with_signatures(boot_certified_img_archive2,
                                                  temp_out_dir)
 
             # Checks an AVB footer exists and the image size remains.
-            boot_3_img = os.path.join(temp_out_dir, 'boot-3.0.img')
+            boot_3_img = os.path.join(temp_out_dir, 'boot-gz.img')
             self.assertTrue(has_avb_footer(boot_3_img))
             self.assertEqual(os.path.getsize(boot_3_img), 128 * 1024)
 
+            # Checks the content in the AVB footer.
             self._test_boot_signatures(
                 temp_out_dir,
-                {'boot-3.0/boot_signature1':
-                    self._EXPECTED_BOOT_3_0_SIGNATURE1_RSA4096,
-                 'boot-3.0/boot_signature2':
-                    self._EXPECTED_BOOT_3_0_SIGNATURE2_RSA4096})
+                {'boot-gz.img': self._EXPECTED_AVB_FOOTER_BOOT_GZ})
+
+            # Checks the content in the GKI certificate.
+            self._test_boot_signatures(
+                temp_out_dir,
+                {'boot-gz/boot_signature1':
+                    self._EXPECTED_BOOT_GZ_SIGNATURE1_RSA4096,
+                 'boot-gz/boot_signature2':
+                    self._EXPECTED_BOOT_GZ_SIGNATURE2_RSA4096})
 
 
 # I don't know how, but we need both the logger configuration and verbosity
diff --git a/gki/retrofit_gki.sh b/gki/retrofit_gki.sh
deleted file mode 100755
index 01af7fa..0000000
--- a/gki/retrofit_gki.sh
+++ /dev/null
@@ -1,231 +0,0 @@
-#!/bin/bash
-#
-# Copyright (C) 2022 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-#
-# Retrofits GKI boot images for upgrading devices.
-#
-
-set -eo errtrace
-
-usage() {
-  cat <<EOF
-Usage:
-  $0 --boot BOOT --init_boot INIT_BOOT --version {3,4} -o OUTPUT
-  $0 --boot BOOT --init_boot INIT_BOOT --vendor_boot VENDOR_BOOT --version 2 -o OUTPUT
-
-Options:
-  --boot FILE
-    Path to the generic boot image.
-  --init_boot FILE
-    Path to the generic init_boot image.
-  --vendor_boot FILE
-    Path to the vendor boot image.
-  --version {2,3,4}
-    Boot image header version to retrofit to.
-  -o, --output FILE
-    Path to the output boot image.
-  -v, --verbose
-    Show debug messages.
-  -h, --help, --usage
-    Show this help message.
-EOF
-}
-
-die() {
-  echo >&2 "ERROR:" "${@}"
-  exit 1
-}
-
-file_size() {
-  stat -c '%s' "$1"
-}
-
-get_arg() {
-  local arg="$1"
-  shift
-  while [[ "$#" -gt 0 ]]; do
-    if [[ "$1" == "${arg}" ]]; then
-      shift
-      echo "$1"
-      return
-    fi
-    shift
-  done
-}
-
-TEMP_DIR="$(mktemp -d --tmpdir retrofit_gki.XXXXXXXX)"
-readonly TEMP_DIR
-
-exit_handler() {
-  readonly EXIT_CODE="$?"
-  rm -rf "${TEMP_DIR}" ||:
-  exit "${EXIT_CODE}"
-}
-
-trap exit_handler EXIT
-trap 'die "line ${LINENO}, ${FUNCNAME:-<main>}(): \"${BASH_COMMAND}\" returned \"$?\"" ' ERR
-
-while [[ "$1" =~ ^- ]]; do
-  case "$1" in
-    --boot )
-      shift
-      BOOT_IMAGE="$1"
-      ;;
-    --init_boot )
-      shift
-      INIT_BOOT_IMAGE="$1"
-      ;;
-    --vendor_boot )
-      shift
-      VENDOR_BOOT_IMAGE="$1"
-      ;;
-    --version )
-      shift
-      OUTPUT_BOOT_IMAGE_VERSION="$1"
-      ;;
-    -o | --output )
-      shift
-      OUTPUT_BOOT_IMAGE="$1"
-      ;;
-    -v | --verbose )
-      VERBOSE=true
-      ;;
-    -- )
-      shift
-      break
-      ;;
-    -h | --help | --usage )
-      usage
-      exit 0
-      ;;
-    * )
-      echo >&2 "Unexpected flag: '$1'"
-      usage >&2
-      exit 1
-      ;;
-  esac
-  shift
-done
-
-declare -ir OUTPUT_BOOT_IMAGE_VERSION
-readonly BOOT_IMAGE
-readonly INIT_BOOT_IMAGE
-readonly VENDOR_BOOT_IMAGE
-readonly OUTPUT_BOOT_IMAGE
-readonly VERBOSE
-
-# Make sure the input arguments make sense.
-[[ -f "${BOOT_IMAGE}" ]] ||
-  die "argument '--boot': not a regular file: '${BOOT_IMAGE}'"
-[[ -f "${INIT_BOOT_IMAGE}" ]] ||
-  die "argument '--init_boot': not a regular file: '${INIT_BOOT_IMAGE}'"
-if [[ "${OUTPUT_BOOT_IMAGE_VERSION}" -lt 2 ]] || [[ "${OUTPUT_BOOT_IMAGE_VERSION}" -gt 4 ]]; then
-  die "argument '--version': valid choices are {2, 3, 4}"
-elif [[ "${OUTPUT_BOOT_IMAGE_VERSION}" -eq 2 ]]; then
-  [[ -f "${VENDOR_BOOT_IMAGE}" ]] ||
-    die "argument '--vendor_boot': not a regular file: '${VENDOR_BOOT_IMAGE}'"
-fi
-[[ -z "${OUTPUT_BOOT_IMAGE}" ]] &&
-  die "argument '--output': cannot be empty"
-
-readonly BOOT_IMAGE_WITHOUT_AVB_FOOTER="${TEMP_DIR}/boot.img.without_avb_footer"
-readonly BOOT_DIR="${TEMP_DIR}/boot"
-readonly INIT_BOOT_DIR="${TEMP_DIR}/init_boot"
-readonly VENDOR_BOOT_DIR="${TEMP_DIR}/vendor_boot"
-readonly VENDOR_BOOT_MKBOOTIMG_ARGS="${TEMP_DIR}/vendor_boot.mkbootimg_args"
-readonly OUTPUT_RAMDISK="${TEMP_DIR}/out.ramdisk"
-readonly OUTPUT_BOOT_SIGNATURE="${TEMP_DIR}/out.boot_signature"
-
-readonly AVBTOOL="${AVBTOOL:-avbtool}"
-readonly MKBOOTIMG="${MKBOOTIMG:-mkbootimg}"
-readonly UNPACK_BOOTIMG="${UNPACK_BOOTIMG:-unpack_bootimg}"
-
-# Fixed boot signature size for easy discovery in VTS.
-readonly BOOT_SIGNATURE_SIZE=$(( 16 << 10 ))
-
-
-#
-# Preparations are done. Now begin the actual work.
-#
-
-# Copy the boot image because `avbtool erase_footer` edits the file in-place.
-cp "${BOOT_IMAGE}" "${BOOT_IMAGE_WITHOUT_AVB_FOOTER}"
-( [[ -n "${VERBOSE}" ]] && set -x
-  "${AVBTOOL}" erase_footer --image "${BOOT_IMAGE_WITHOUT_AVB_FOOTER}" 2>/dev/null ||:
-  tail -c "${BOOT_SIGNATURE_SIZE}" "${BOOT_IMAGE_WITHOUT_AVB_FOOTER}" > "${OUTPUT_BOOT_SIGNATURE}"
-  "${UNPACK_BOOTIMG}" --boot_img "${BOOT_IMAGE}" --out "${BOOT_DIR}" >/dev/null
-  "${UNPACK_BOOTIMG}" --boot_img "${INIT_BOOT_IMAGE}" --out "${INIT_BOOT_DIR}" >/dev/null
-)
-if [[ "$(file_size "${OUTPUT_BOOT_SIGNATURE}")" -ne "${BOOT_SIGNATURE_SIZE}" ]]; then
-  die "boot signature size must be equal to ${BOOT_SIGNATURE_SIZE}"
-fi
-
-declare -a mkbootimg_args=()
-
-if [[ "${OUTPUT_BOOT_IMAGE_VERSION}" -eq 4 ]]; then
-  mkbootimg_args+=( \
-    --header_version 4 \
-    --kernel "${BOOT_DIR}/kernel" \
-    --ramdisk "${INIT_BOOT_DIR}/ramdisk" \
-  )
-elif [[ "${OUTPUT_BOOT_IMAGE_VERSION}" -eq 3 ]]; then
-  mkbootimg_args+=( \
-    --header_version 3 \
-    --kernel "${BOOT_DIR}/kernel" \
-    --ramdisk "${INIT_BOOT_DIR}/ramdisk" \
-  )
-elif [[ "${OUTPUT_BOOT_IMAGE_VERSION}" -eq 2 ]]; then
-  ( [[ -n "${VERBOSE}" ]] && set -x
-    "${UNPACK_BOOTIMG}" --boot_img "${VENDOR_BOOT_IMAGE}" --out "${VENDOR_BOOT_DIR}" \
-      --format=mkbootimg -0 > "${VENDOR_BOOT_MKBOOTIMG_ARGS}"
-    cat "${VENDOR_BOOT_DIR}/vendor_ramdisk" "${INIT_BOOT_DIR}/ramdisk" > "${OUTPUT_RAMDISK}"
-  )
-
-  declare -a vendor_boot_args=()
-  while IFS= read -r -d '' ARG; do
-    vendor_boot_args+=("${ARG}")
-  done < "${VENDOR_BOOT_MKBOOTIMG_ARGS}"
-
-  pagesize="$(get_arg --pagesize "${vendor_boot_args[@]}")"
-  kernel_offset="$(get_arg --kernel_offset "${vendor_boot_args[@]}")"
-  ramdisk_offset="$(get_arg --ramdisk_offset "${vendor_boot_args[@]}")"
-  tags_offset="$(get_arg --tags_offset "${vendor_boot_args[@]}")"
-  dtb_offset="$(get_arg --dtb_offset "${vendor_boot_args[@]}")"
-  kernel_cmdline="$(get_arg --vendor_cmdline "${vendor_boot_args[@]}")"
-
-  mkbootimg_args+=( \
-    --header_version 2 \
-    --base 0 \
-    --kernel_offset "${kernel_offset}" \
-    --ramdisk_offset "${ramdisk_offset}" \
-    --second_offset 0 \
-    --tags_offset "${tags_offset}" \
-    --dtb_offset "${dtb_offset}" \
-    --cmdline "${kernel_cmdline}" \
-    --pagesize "${pagesize}" \
-    --kernel "${BOOT_DIR}/kernel" \
-    --ramdisk "${OUTPUT_RAMDISK}" \
-  )
-  if [[ -f "${VENDOR_BOOT_DIR}/dtb" ]]; then
-    mkbootimg_args+=(--dtb "${VENDOR_BOOT_DIR}/dtb")
-  fi
-fi
-
-( [[ -n "${VERBOSE}" ]] && set -x
-  "${MKBOOTIMG}" "${mkbootimg_args[@]}" --output "${OUTPUT_BOOT_IMAGE}"
-  cat "${OUTPUT_BOOT_SIGNATURE}" >> "${OUTPUT_BOOT_IMAGE}"
-)
diff --git a/gki/retrofit_gki_test.sh b/gki/retrofit_gki_test.sh
deleted file mode 100755
index b3cb0a5..0000000
--- a/gki/retrofit_gki_test.sh
+++ /dev/null
@@ -1,144 +0,0 @@
-#!/bin/bash
-#
-# Copyright (C) 2022 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-set -eo errtrace
-
-die() {
-  echo >&2 "ERROR:" "${@}"
-  exit 1
-}
-
-trap 'die "line ${LINENO}, ${FUNCNAME:-<main>}(): \"${BASH_COMMAND}\" returned \"$?\"" ' ERR
-
-# Figure out where we are and where to look for test executables.
-cd "$(dirname "${BASH_SOURCE[0]}")"
-TEST_DIR="$(pwd)"
-readonly TEST_DIR
-readonly TEMP_DIR="${TEST_DIR}/stage.retrofit_gki_test"
-
-export PATH="${TEST_DIR}:${PATH}"
-rm -rf "${TEMP_DIR}"
-mkdir -p "${TEMP_DIR}"
-
-# Generate some test files.
-readonly TEST_DTB="${TEMP_DIR}/dtb"
-readonly TEST_KERNEL="${TEMP_DIR}/kernel"
-readonly TEST_RAMDISK="${TEMP_DIR}/ramdisk"
-readonly TEST_VENDOR_RAMDISK="${TEMP_DIR}/vendor_ramdisk"
-readonly TEST_BOOT_SIGNATURE="${TEMP_DIR}/boot.boot_signature"
-readonly TEST_V2_RETROFITTED_RAMDISK="${TEMP_DIR}/retrofitted.ramdisk"
-readonly TEST_BOOT_IMAGE="${TEMP_DIR}/boot.img"
-readonly TEST_INIT_BOOT_IMAGE="${TEMP_DIR}/init_boot.img"
-readonly TEST_VENDOR_BOOT_IMAGE="${TEMP_DIR}/vendor_boot.img"
-
-( # Run these in subshell because dd is noisy.
-  dd if=/dev/urandom of="${TEST_DTB}" bs=1024 count=10
-  dd if=/dev/urandom of="${TEST_KERNEL}" bs=1024 count=10
-  dd if=/dev/urandom of="${TEST_RAMDISK}" bs=1024 count=10
-  dd if=/dev/urandom of="${TEST_VENDOR_RAMDISK}" bs=1024 count=10
-  dd if=/dev/urandom of="${TEST_BOOT_SIGNATURE}" bs=1024 count=16
-) 2> /dev/null
-
-cat "${TEST_VENDOR_RAMDISK}" "${TEST_RAMDISK}" > "${TEST_V2_RETROFITTED_RAMDISK}"
-
-mkbootimg \
-  --header_version 4 \
-  --kernel "${TEST_KERNEL}" \
-  --output "${TEST_BOOT_IMAGE}"
-cat "${TEST_BOOT_SIGNATURE}" >> "${TEST_BOOT_IMAGE}"
-avbtool add_hash_footer --image "${TEST_BOOT_IMAGE}" --partition_name boot --partition_size $((20 << 20))
-
-mkbootimg \
-  --header_version 4 \
-  --ramdisk "${TEST_RAMDISK}" \
-  --output "${TEST_INIT_BOOT_IMAGE}"
-mkbootimg \
-  --header_version 4 \
-  --pagesize 4096 \
-  --dtb "${TEST_DTB}" \
-  --vendor_ramdisk "${TEST_VENDOR_RAMDISK}" \
-  --vendor_boot "${TEST_VENDOR_BOOT_IMAGE}"
-
-readonly RETROFITTED_IMAGE="${TEMP_DIR}/retrofitted_boot.img"
-readonly RETROFITTED_IMAGE_DIR="${TEMP_DIR}/retrofitted_boot.img.unpack"
-readonly BOOT_SIGNATURE_SIZE=$(( 16 << 10 ))
-
-
-#
-# Begin test.
-#
-echo >&2 "TEST: retrofit to boot v4"
-
-retrofit_gki.sh \
-  --boot "${TEST_BOOT_IMAGE}" \
-  --init_boot "${TEST_INIT_BOOT_IMAGE}" \
-  --version 4 \
-  --output "${RETROFITTED_IMAGE}"
-
-rm -rf "${RETROFITTED_IMAGE_DIR}"
-unpack_bootimg --boot_img "${RETROFITTED_IMAGE}" --out "${RETROFITTED_IMAGE_DIR}" > /dev/null
-tail -c "${BOOT_SIGNATURE_SIZE}" "${RETROFITTED_IMAGE}" > "${RETROFITTED_IMAGE_DIR}/boot_signature"
-
-cmp -s "${TEST_KERNEL}" "${RETROFITTED_IMAGE_DIR}/kernel" ||
-  die "unexpected diff: kernel"
-cmp -s "${TEST_RAMDISK}" "${RETROFITTED_IMAGE_DIR}/ramdisk" ||
-  die "unexpected diff: ramdisk"
-cmp -s "${TEST_BOOT_SIGNATURE}" "${RETROFITTED_IMAGE_DIR}/boot_signature" ||
-  die "unexpected diff: boot signature"
-
-
-echo >&2 "TEST: retrofit to boot v3"
-
-retrofit_gki.sh \
-  --boot "${TEST_BOOT_IMAGE}" \
-  --init_boot "${TEST_INIT_BOOT_IMAGE}" \
-  --version 3 \
-  --output "${RETROFITTED_IMAGE}"
-
-rm -rf "${RETROFITTED_IMAGE_DIR}"
-unpack_bootimg --boot_img "${RETROFITTED_IMAGE}" --out "${RETROFITTED_IMAGE_DIR}" > /dev/null
-tail -c "${BOOT_SIGNATURE_SIZE}" "${RETROFITTED_IMAGE}" > "${RETROFITTED_IMAGE_DIR}/boot_signature"
-
-cmp -s "${TEST_KERNEL}" "${RETROFITTED_IMAGE_DIR}/kernel" ||
-  die "unexpected diff: kernel"
-cmp -s "${TEST_RAMDISK}" "${RETROFITTED_IMAGE_DIR}/ramdisk" ||
-  die "unexpected diff: ramdisk"
-cmp -s "${TEST_BOOT_SIGNATURE}" "${RETROFITTED_IMAGE_DIR}/boot_signature" ||
-  die "unexpected diff: boot signature"
-
-
-echo >&2 "TEST: retrofit to boot v2"
-
-retrofit_gki.sh \
-  --boot "${TEST_BOOT_IMAGE}" \
-  --init_boot "${TEST_INIT_BOOT_IMAGE}" \
-  --vendor_boot "${TEST_VENDOR_BOOT_IMAGE}" \
-  --version 2 \
-  --output "${RETROFITTED_IMAGE}"
-
-rm -rf "${RETROFITTED_IMAGE_DIR}"
-unpack_bootimg --boot_img "${RETROFITTED_IMAGE}" --out "${RETROFITTED_IMAGE_DIR}" > /dev/null
-tail -c "${BOOT_SIGNATURE_SIZE}" "${RETROFITTED_IMAGE}" > "${RETROFITTED_IMAGE_DIR}/boot_signature"
-
-cmp -s "${TEST_DTB}" "${RETROFITTED_IMAGE_DIR}/dtb" ||
-  die "unexpected diff: dtb"
-cmp -s "${TEST_KERNEL}" "${RETROFITTED_IMAGE_DIR}/kernel" ||
-  die "unexpected diff: kernel"
-cmp -s "${TEST_V2_RETROFITTED_RAMDISK}" "${RETROFITTED_IMAGE_DIR}/ramdisk" ||
-  die "unexpected diff: ramdisk"
-cmp -s "${TEST_BOOT_SIGNATURE}" "${RETROFITTED_IMAGE_DIR}/boot_signature" ||
-  die "unexpected diff: boot signature"
diff --git a/unpack_bootimg.py b/unpack_bootimg.py
index 462190f..a3f1a50 100755
--- a/unpack_bootimg.py
+++ b/unpack_bootimg.py
@@ -404,9 +404,6 @@
     ramdisk_offset_base = page_size * num_boot_header_pages
     image_info_list = []
 
-    image_info_list.append(
-        (ramdisk_offset_base, info.vendor_ramdisk_size, 'vendor_ramdisk'))
-
     if info.header_version > 3:
         info.vendor_ramdisk_table_size = unpack('I', boot_img.read(4))[0]
         vendor_ramdisk_table_entry_num = unpack('I', boot_img.read(4))[0]
@@ -449,6 +446,9 @@
             + num_vendor_ramdisk_table_pages)
         image_info_list.append((bootconfig_offset, info.vendor_bootconfig_size,
             'bootconfig'))
+    else:
+        image_info_list.append(
+            (ramdisk_offset_base, info.vendor_ramdisk_size, 'vendor_ramdisk'))
 
     dtb_offset = page_size * (num_boot_header_pages + num_boot_ramdisk_pages
                              ) # header + vendor_ramdisk