Method of Verification

This page outlines a method (with the highest degree of confidence) to ensure that you can run a legitimate version of Pixel image on your Pixel device. This involves downloading a factory image onto your computer, and performing a log inclusion proof on the downloaded artifact before flashing it onto your device.

How to Verify Your Pixel Factory Image

Prerequisites to Verifying

Before proceeding to verify that the factory image that you have just downloaded is in accordance with our claim, you will need to do the following from a network-connected computer.

Golang

The verification tool is written in Go. To build it, install Go 1.17 or later from the Go site.

wget or curl

wget and curl are tools that can be used to retrieve or download files from the Internet. Be sure to have either of these tools installed on your system, as the rest of this guide and the script we provide relies one of them being present.

Avbtool

avbtool is used to compute the VBMeta digest of the factory images and verification of binaries.

You can download it from the AOSP repository using the command below and find more details in the linked documentation.

computer:~$ git clone https://android.googlesource.com/platform/external/avb

After cloning that repository, avbtool.py can be found within the cloned avb repository directory. Additionally, you should add this directory to your $PATH environment variable.

computer:~$ PATH=$PATH:DIRECTORY_CONTAINING_AVBTOOL

Inclusion Proof verifier

The inclusion proof verifier is a Go module which queries the Pixel Factory images transparency log and outputs whether an image is included in the log.

After cloning the AVB repository above, the source code of the verifier is found in tools/transparency/verify/

Fbpacktool

fbpacktool is a python script that is used to unpack individual components in Pixel's bootloader.img. This tool is important to allow avbtool.py to discover the required images for verification.

To make use of this tool, you should download the following three python scripts into the directory where your avbtool.py lives, make fbpacktool.py executable, and create a symlink named fbpacktool to fbpacktool.py for convenience.

If you have wget, you can issue the following command to download the three scripts:

computer:dir_to_avbtool$ wget https://source.android.com/devices/bootloader/tools/pixel/fw_unpack/fbpacktool.py \
https://source.android.com/devices/bootloader/tools/pixel/fw_unpack/fbpack.py \
https://source.android.com/devices/bootloader/tools/pixel/fw_unpack/packedstruct.py
computer:dir_to_avbtool$ chmod +x fbpacktool.py
computer:dir_to_avbtool$ ln -s fbpacktool.py fbpacktool

If you have curl, you can issue the following commands to download the three scripts:

computer:dir_to_avbtool$ curl -O https://source.android.com/devices/bootloader/tools/pixel/fw_unpack/fbpacktool.py
computer:dir_to_avbtool$ curl -O https://source.android.com/devices/bootloader/tools/pixel/fw_unpack/fbpack.py
computer:dir_to_avbtool$ curl -O https://source.android.com/devices/bootloader/tools/pixel/fw_unpack/packedstruct.py
computer:dir_to_avbtool$ chmod +x fbpacktool.py
computer:dir_to_avbtool$ ln -s fbpacktool.py fbpacktool

OpenSSL

You also need a tool named openssl to help perform various cryptographic operations using the terminal in the verification workflow. Make sure that it is installed on your system. You can do a check on your terminal by issuing the following command and make sure that the returned result is not empty. For example:

computer:~$ which openssl
/usr/bin/openssl

Construct the Payload for Verification

To verify the image you have on your device or a download from the Pixel Factory Image website, you must first construct the payload corresponding to that image from the Build Fingerprint and VBMeta Digest. There are two options, manual or automatic, as described below.

  • Build Fingerprint: A string identifier of the factory image
    • Example: google/oriole/oriole:12/SD1A.210817.015.A4/7697517:user/release-keys
  • VBMeta Digest: A SHA-256 cryptographic digest that ties the different pieces of the factory images together
    • Example: 4d5e41b7c675a821de81f7d2c744623fe808c8c2d3e19a83e894dab5d0829dbe

Manual Payload Construction

To manually generate the payload for verification you need to create a text file, payload.txt that contains the build fingerprint on one line and then the VBMeta digest on the next line, with an empty new line (please refer to the Log Content section for exact format).

After following the steps from Factory Image website, the content of the payload.txt file should look like this:

google/oriole/oriole:12/SD1A.210817.015.A4/7697517:user/release-keys
4d5e41b7c675a821de81f7d2c744623fe808c8c2d3e19a83e894dab5d0829dbe
Extracting the VBMeta Digest and Build Fingerprint from Pixel Factory Image website

When you download a factory image from Pixel Factory Image website, you will need to unzip the downloaded file, which will create another folder in place. Navigate to the newly created folder, and unzip the associated image-*.zip file to obtain individual *.img files. These binaries are partition images. Make sure that a vbmeta.img file exists among the img files. You should see something like this:

computer:oriole-sd1a.210817.015.a4$ unzip image-oriole-sd1a.210817.015.a4.zip
Archive:  image-oriole-sd1a.210817.015.a4.zip
  inflating: android-info.txt
  inflating: boot.img
  inflating: vendor_boot.img
  inflating: system.img
  inflating: vendor.img
  inflating: product.img
  inflating: system_ext.img
  inflating: system_other.img
  inflating: dtbo.img
  inflating: vbmeta_system.img
  inflating: vbmeta.img
  inflating: super_empty.img

You can extract the build fingerprint and compute the VBMeta digest from all the downloaded files.

After avbtool.py has been made available to your $PATH, you can then issue the following commands from your terminal to extract the build fingerprint and compute the VBMeta digest of the factory image that you have just downloaded:

computer:dir_containing_unzipped_factory_image~$ grep -a 'ro\..*build\.fingerprint=google/.*/release-keys' system.img | cut -f2 -d'='
google/oriole/oriole:12/SD1A.210817.015.A4/7697517:user/release-keys
computer:dir_containing_unzipped_factory_image$ avbtool.py calculate_vbmeta_digest --image vbmeta.img
4d5e41b7c675a821de81f7d2c744623fe808c8c2d3e19a83e894dab5d0829dbe
Manual Verification of Downloaded Factory Image

In order to correctly verify the downloaded factory image, you will need to download fbpacktool.py and two other python files it depends on (fbpack.py and packedstruct.py) to unpack the components in bootloader.img, as they are individually described in the VBMeta struct. Once you have the unpacker, you can make use of the fbpacktool.py to unpack the bootloader image. For example:

computer:dir_containing_unzipped_images$ python3 fbpacktool.py unpack bootloader-oriole-slider-1.0-7683913.img

You should be able to see additional .img files appearing in that directory. Now, you can proceed to use avbtool.py to manually verify that the signatures of the various partitions match.

computer:dir_containing_unzipped_images$ avbtool.py verify_image --image vbmeta.img --follow_chain_partitions
Verifying image vbmeta.img using embedded public key
vbmeta: Successfully verified SHA256_RSA4096 vbmeta struct in vbmeta.img
vbmeta_system: Chained but ROLLBACK_SLOT (which is 1) and KEY (which has sha1 df529646b7225015196a714006346f0768b87fcf) not specified
--
Verifying image vbmeta_system.img using embedded public key
vbmeta: Successfully verified SHA256_RSA4096 vbmeta struct in vbmeta_system.img
product: Successfully verified sha256 hashtree of product.img for image of 2700468224 bytes
system: Successfully verified sha256 hashtree of system.img for image of 878493696 bytes
system_ext: Successfully verified sha256 hashtree of system_ext.img for image of 251334656 bytes
vbmeta_vendor: Chained but ROLLBACK_SLOT (which is 3) and KEY (which has sha1 85322346680a860c091fa14a64cef1fe4a3ffe31) not specified
--
Verifying image vbmeta_vendor.img using embedded public key
vbmeta: Successfully verified SHA256_RSA4096 vbmeta struct in vbmeta_vendor.img
vendor: Successfully verified sha256 hashtree of vendor.img for image of 472940544 bytes
boot: Chained but ROLLBACK_SLOT (which is 2) and KEY (which has sha1 85322346680a860c091fa14a64cef1fe4a3ffe31) not specified
--
Verifying image boot.img using embedded public key
vbmeta: Successfully verified footer and SHA256_RSA4096 vbmeta struct in boot.img
boot: Successfully verified sha256 hash of boot.img for image of 24481792 bytes
abl: Successfully verified sha256 hash of abl.img for image of 1744896 bytes
bl1: Successfully verified sha256 hash of bl1.img for image of 12288 bytes
bl2: Successfully verified sha256 hash of bl2.img for image of 544768 bytes
bl31: Successfully verified sha256 hash of bl31.img for image of 86016 bytes
dtbo: Successfully verified sha256 hash of dtbo.img for image of 2152234 bytes
gsa: Successfully verified sha256 hash of gsa.img for image of 262144 bytes
ldfw: Successfully verified sha256 hash of ldfw.img for image of 4096000 bytes
pbl: Successfully verified sha256 hash of pbl.img for image of 49152 bytes
tzsw: Successfully verified sha256 hash of tzsw.img for image of 4304896 bytes
vendor_boot: Successfully verified sha256 hash of vendor_boot.img for image of 25718784 bytes
vendor_dlkm: Successfully verified sha256 hashtree of vendor_dlkm.img for image of 54505472 bytes

If you don't see any error or failure messages, this means that the VBMeta of the downloaded image has now been successfully verified.

Automatic Payload Construction

For your convenience, we have also provided a python script you can use. With this tool, rather than manually fetching and unzipping files, you only need to specify the URL to the factory image.

computer:dir_to_avb_repo/tools/transparency$ python3 ./pixel_factory_image_verify.py https://dl.google.com/dl/android/aosp/oriole-sd1a.210817.015.a4-factory-074b7f51.zip
Fetching file from: https://dl.google.com/dl/android/aosp/oriole-sd1a.210817.015.a4-factory-074b7f51.zip
Successfully downloaded file.
Successfully unpacked factory image.
Successfully unpacked factory image partitions.
Successfully unpacked bootloader image.
Successfully verified VBmeta.
Successfully extracted build fingerprint.
Successfully calculated VBMeta Digest.
The build fingerprint for factory image is: google/oriole/oriole:12/SD1A.210817.015.A4/7697517:user/release-keys
The VBMeta Digest for factory image is: 4d5e41b7c675a821de81f7d2c744623fe808c8c2d3e19a83e894dab5d0829dbe

A corresponding "payload.txt" file has been created.

Executing the command above will download the factory image bundle, unzip the bundle, and verify the signatures of the signed partitions. Upon successful verification, it will create a new file named payload.txt, and its content should look similar to below:

google/oriole/oriole:12/SD1A.210817.015.A4/7697517:user/release-keys
4d5e41b7c675a821de81f7d2c744623fe808c8c2d3e19a83e894dab5d0829dbe

After your payload.txt is successfully created you can start the verification of image inclusion steps.

Verifying Image Inclusion (Inclusion Proof)

Once you've constructed your payload, set a shell variable (e.g. $PAYLOAD_PATH) to point to the path to the payload.

An inclusion proof tool has been published in the avb repository within the Android Open Source Project. To run it:

computer:external/avb/tools/transparency/verify$ PAYLOAD_PATH=../payload.txt
computer:external/avb/tools/transparency/verify$ go build cmd/verifier/verifier.go
computer:external/avb/tools/transparency/verify$ ./verifier --payload_path=${PAYLOAD_PATH}

The verifier uses the checkpoint and the log contents (found at the tile directory) to check that your image payload is in the transparency log, that is, that it is published by Google.

The output of the command is written to stdout:

  • OK if the image is included in the log,
  • FAILURE if it isn't.