Android Verified Boot (AVB)
What is AVB?
Android Verified Boot(AVB) is an implementation of the verified boot process for Android, with the current version (since Android 8 Oreo) being AVB 2.0. Verified boot is a process of assuring the end user of the integrity of the software running on a device. It typically starts with a read-only portion of the device firmware which loads code and executes it only after cryptographically verifying that the code is authentic. It also helps in implementing rollback protection.
Implementation details
It is implemented inside libavb - simple C library, that can be used both inside userspace programs (Android's avbctl?) and by kernel space (bootloader). Heart of the system is VBMeta struct, which contains both checksums of contents of several important partitions, and the public key used to cryptographically sign them. Several important partitions include boot
, recovery
, dtbo
, vendor
and system
. Public key is meant to be verified by bootloader to the one that is embedded inside it, to be trusted.
The vbmeta struct is described in libavb/avb_vbmeta_image.h. It contains header, auth data (reference to public key) and references to descriptors for several paritions. Read the comment above its declaration for more info.
Verified boot process
When device is locked, bootloader loads vbmeta struct from vbmeta partition. And then it calls avb_slot_verify()
for each partition mentioned inside vbmeta struct. If some partition fails this check, then bootloader can know that system files were modified. From the result of this test bootloader sets boot state:
- YELLOW: Warning screen for LOCKED devices with custom root of trust set
- ORANGE: Warning screen for UNLOCKED devices
- RED (eio): Warning screen for dm-verity corruption
- RED (no os found): No valid OS found
And then it can display warnings on the screen, and reflect boot state in kernel command line, like for example androidboot.verifiedbootstate=orange
.
For unlocked device bootloader skips the verification for boot partition, but can still verify others. See relevant LK aboot code.
Example bootloader debug output regarding verified boot process with original boot.img
, unlocked device:
Booting Into Mission Mode avb_slot_verify.c:432: DEBUG: Loading vbmeta struct from partition 'vbmeta'. Partition found: vbmeta avb_slot_verify.c:186: DEBUG: dtbo: Loading entire partition. Partition found: dtbo avb_slot_verify.c:186: DEBUG: boot: Loading entire partition. Partition found: boot Device is unlocked, Skipping boot verification State: Unlocked, AvbSlotVerify returned OK, continue boot VB2: Authenticate complete! boot state is: orange VB2: boot state: orange(1)
Example bootloader debug output regarding verified boot process with custom boot.img
, unlocked device:
Booting Into Mission Mode avb_slot_verify.c:432: DEBUG: Loading vbmeta struct from partition 'vbmeta'. Partition found: vbmeta avb_slot_verify.c:186: DEBUG: dtbo: Loading entire partition. Partition found: dtbo avb_slot_verify.c:186: DEBUG: boot: Loading entire partition. Partition found: boot avb_slot_verify.c:242: ERROR: boot: Hash of data does not match digest in descriptor. State: Unlocked, AvbSlotVerify returned ERROR_VERIFICATION, continue boot VB2: Authenticate complete! boot state is: orange VB2: boot state: orange(1) Display menu is not enabled! Device is unlocked, Skipping boot verification VB2: BootState = 1
Using avbtool
avbtool is a python script that can be used to view, create and edit images for AVB process.
Use avbtool --help
to get list of commands, and avbtool <command> --help
to view help on specific command.
Examining contents of stock images
avbtool info_image
command can be used to query headers of vbmeta struct, or for partition images it will show contents of vbmeta footer signature. Example usage:
avbtool info_image --image /path/to/vbmeta.img avbtool info_image --image /path/to/boot.img
Signing & checksumming the partitions
For small partition images (boot, dtbo, recovery) you can add checksum/signature with: avbtool add_hash_footer
.
For larger partitions (vendor, system) you should use avbtool add_hashtree_footer
. Arguments are the same. Example:
avbtool add_hash_footer --partition_name PARTITION_NAME --partition_size PARTITION_SIZE --image IMAGE [--key /path/to/key_used_for_signing_or_pub_key] avbtool add_hash_footer --partition_name boot --partition_size 67108864 --image boot.img-postmarketos-qcom-sdm660
PARTITION_NAME will be written into vbmeta struct later and used by bootloader during verification process.
PARTITION_SIZE should be equal to partition size in bytes. Image file will be padded to this size and vbmeta footer will be addded at the end of it.
Creating vbmeta image
vbmeta.img is an image file that is intended to be flashed into vbmeta partition. It is used by bootloader as source for checksums in verification process.
First you should checksum/sign all other partition images that are part of your AVB process (for example, boot, system, etc)! See example just above.
avbtool make_vbmeta_image
Is the command that you will use in this case:
avbtool make_vbmeta_image \ --output my_vbmeta.img \ --padding_size 4096 \ --include_descriptors_from_image ./boot.img-postmarketos-qcom-sdm660 \ --include_descriptors_from_image ./path/to/some_another_image.img \ ... [--key /path/to/key_used_for_signing_or_pub_key]
This command will create my_vbmeta.img
file, at least 4096 bytes in size, that will contain hash/hashtree descriptors from all the partition images specified in --include_descriptors_from_image
parameters.
Disabling verified boot
To disable verified boot you should create an empty vbmeta.img, which does not contain any hash/hashtree desriptors and specified a special flag in vbmeta header. The command for it should look like this:
avbtool make_vbmeta_image --flags 2 --padding_size 4096 --output vbmeta_disabled.img
Mysterious flag 2 is AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED, which is documented as:
AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED: If this flag is set, verification will be disabled and descriptors will not be parsed.
Example bootloader output when booting with vbmeta_disabled.img flashed to vbmeta partition:
Booting Into Mission Mode avb_slot_verify.c:432: DEBUG: Loading vbmeta struct from partition 'vbmeta'. Partition found: vbmeta avb_slot_verify.c:544: ERROR: vbmeta: Error verifying vbmeta image: OK_NOT_SIGNED avb_slot_verify.c:704: DEBUG: vbmeta: VERIFICATION_DISABLED bit is set. avb_slot_verify.c:317: DEBUG: boot: Loading entire partition. Partition found: boot avb_slot_verify.c:317: DEBUG: dtbo: Loading entire partition. Partition found: dtbo State: Unlocked, AvbSlotVerify returned ERROR_VERIFICATION, continue boot VB2: Authenticate complete! boot state is: orange VB2: boot state: orange(1)
Note VERIFICATION_DISABLED bit is set
. Apparently bootloader can detect that verification is disabled, but its reaction to this mode may be device specific?
Links
- Google official documentation: platform/external/avb/README.md
- Google official documentation: Verified boot flow (boot states)
- Commit in LK introducing verified boot and boot states
- merge request that shed some light on disabling verified boot