[Android Software/Hacking General [Developers Only]] Chainfire:
Various Android devices support Android Verified Boot (AVB). A part of this is more commonly known as dm-verity, which verifies system (and vendor) partition integrity. AVB can however also verify boot images, and stock firmwares generally include signed boot images. Of course this does not mean that all signed boot images are using AVB, many OEMs have their own signature verification scheme.

Note: AOSP is moving towards the use of avbtool (taken from Brillo), the following is the old way for signing boot images.

Bootloaders might or might not accept unsigned boot images, and might or might not accept boot images signed with our own keys (rather than the OEM's keys). This depends on the device, bootloader version, and bootloader unlock state.

For example, with the bootloader unlocked, the Google Pixel (and XL) devices accepted unsigned boot images up to (but not including) the May 2017 release. From the May 2017 release onwards, the boot images must be signed if flashed (booted works without), but may be signed with your own key rather than the OEM's.

Note: The situation changes when you re-lock the bootloader. I have not tested this, but documentation implies that (one of) the keys used in the current boot image must be used for future flashes until it is unlocked again.

Generating custom signing keys

The following openssl commands generate all the keys we need. Execute them line-by-line rather than copying the whole block, as you will be asked for input.

# private key
openssl genrsa -f4 -out verifiedboot.pem 2048
openssl pkcs8 -in verifiedboot.pem -topk8 -outform DER -out verifiedboot.pk8 -nocrypt

# public key
openssl req -new -x509 -sha256 -key verifiedboot.pem -out verifiedboot.x509.pem
openssl x509 -outform DER -in verifiedboot.x509.pem -out verifiedboot.x509.der

For future signings, you do not need the .pem files, and they can safely be deleted once the .pk8 and .der files are generated. In AOSP's implementation, they were never even written to disk in the first place.

Security-wise, documentation states it is advisable to use a different set of keys for each device you support; though obviously this doesn't matter much if the device is running with the bootloader in unlocked state.

Signing the boot image

Download the attached BootSignature.jar file (built from AOSP sources), and sign the boot image using the keys generated above with the following commands:

java -jar BootSignature.jar /boot boot.img verifiedboot.pk8 verifiedboot.x509.der boot_signed.img
java -jar BootSignature.jar -verify boot_signed.img

Instead of /boot, /recovery and other values may be used. Their use should be obvious.

From Android

Attached is also BootSignature_Android.jar, which is a version ProGuard-reduced against SDK 21 and then dexed. Provided /system is mounted as is usual on Android (on the Pixel (XL), TWRP mounts this differently by default!), it can be used like this:

dalvikvm -cp BootSignature_Android.jar com.android.verity.BootSignature /boot boot.img verifiedboot.pk8 verifiedboot.x509.der boot_signed.img
dalvikvm -cp BootSignature_Android.jar com.android.verity.BootSignature -verify boot_signed.img

The base command can be extended as follows to make it able to run without any precompiled files present on the device:

/system/bin/dalvikvm -Xbootclasspath:/system/framework/core-oj.jar:/system/framework/core-libart.jar:/system/framework/conscrypt.jar:/system/framework/bouncycastle.jar -Xnodex2oat -Xnoimage-dex2oat -cp BootSignature_Android.jar com.android.verity.BootSignature ...

Flashable ZIP

Attached is also VerifiedBootSigner.zip, this is a flashable ZIP for FlashFire/TWRP/etc that signs the currently flashed boot image, if it isn't signed already. You can simply flash this after installing a SuperSU version or custom boot image or whatever that doesn't sign the boot image itself already.

I've tried to make it very portable (borrowing ample script from the SuperSU ZIP, as well as its signing keys), but I have only tested it on my Pixel XL.

Note that it does depend on Android files in the system partition, so if (aside from the unsigned boot image) your system isn't functional, the ZIP may not work either.

If the boot image is already signed when you flash the ZIP, it will offer to abort or force re-sign.

If you place custom.pk8 and custom.x509.der files inside the ZIP, these keys will be used for flashing instead of SuperSU's default keys. Additionally, /tmp/avb/custom.pk8 and /tmp/avb/custom.x509.der will override any keys from the ZIP.

There is some more documentation in the update-binary file inside the ZIP as well.

Note: If you're using TWRP's manual slot selection on the Pixel (XL), you must be using TWRP-v3.1.0-RC2 or newer, or it will not work as expected.

Todo

- test what happens when the bootloader is re-locked on multiple devices supporting AVB

- test what happens when dm-verity is kept enabled on a custom/modified boot image with a different image signature than dm-verity signature