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
- Example:
- VBMeta Digest: A SHA-256 cryptographic digest that ties the different pieces
of the factory images together
- Example:
4d5e41b7c675a821de81f7d2c744623fe808c8c2d3e19a83e894dab5d0829dbe
- Example:
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.