Page Summary
-
This page outlines a method to ensure you can run a legitimate version of a Pixel image on your Pixel device.
-
The process involves downloading a factory image and performing a log inclusion proof on the downloaded artifact before flashing it.
-
Prerequisites for verification include installing Golang, wget or curl, avbtool, the inclusion proof verifier, fbpacktool, and OpenSSL.
-
The payload for verification is constructed from the build fingerprint and VBMeta digest, which can be extracted manually or automatically.
-
Verifying image inclusion involves running a Go verifier tool with the constructed payload to check if the image is present in the transparency log.
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
Verification Prerequisites
Before proceeding to verify that the artifact (firmware or APK) is in accordance with the claim, ensure that the following tools are available on a network-connected computer. Depending on the verification target, you might not need all of them.
Golang
The verification tool is written in Go. To build it, install Go 1.24 or later from the Go site.
Android Debug Bridge (ADB)
ADB is a tool that communicates with an Android device to inspect the image or
extract APKs, available on the Android SDK Platform Tools website.
Inclusion Proof verifier
The inclusion proof verifier is a Go module that queries the transparency log
and outputs whether an artifact is included in the log.
It's published in the android-binary-transparency GitHub repository at
https://github.com/android/android-binary-transparency/tree/main
To clone the AOSP avb repository:
computer:~$ git clone https://android.googlesource.com/platform/external/avb
To clone the android-binary-transparency GitHub repository:
computer:~$ git clone https://github.com/android/android-binary-transparency
AAPT2
AAPT2 (Android Asset Packaging Tool) is a build tool used to compile and package an Android app's resources. It can be found as a standalone tool in Android SDK Build Tools version 26.0.2 and higher.
bundletool
bundletool is a tool used to build an Android App Bundle (AAB). It can also be
used to verify APK code signatures.
It can be downloaded from GitHub.
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, as the verification scripts may rely on them.
Avbtool
avbtool
is used to compute the VBMeta digest of the factory images and verification of
binaries.
After cloning the avb repository (as shown in the Inclusion Proof verifier
section), avbtool.py can be found within the cloned avb directory.
You should add this directory to your $PATH environment variable.
computer:~$ PATH=$PATH:DIRECTORY_CONTAINING_AVBTOOL
Fbpacktool
fbpacktool
is a Python script used to unpack individual components in Pixel's
bootloader.img.
You don't need this if you are verifying APKs.
This tool is important because it lets avbtool.py 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:
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:
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
openssl helps perform various cryptographic operations using the terminal in the verification workflow. Make sure it's installed on your system. You can check on your terminal by running the following command and making sure the returned result isn't empty:
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} --log_type=pixel
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. inclusion check success!if the image is included in the log,FAILUREif it isn't.