[Nothing Phone 1] AVB Delenda Est:
The Nothing Phone uses Android Verified Boot 2.0, which includes a rollback protection mechanism that combines anti-tamper storage and a verified boot flow to prevent downgrades.

This guide shows how to bypass this protection on an unlocked device. The guide assumes some familiarity with platform tools and the command line, so not all steps have long explanations. In other words, it's not a full tutorial for complete beginners, a little bit of knowledge is assumed.

Also, there's quite a bit of setup required, this isn't a 5 minute procedure, so brace yourself for a wall of text =)

How it works:

In theory, a bootloader in UNLOCKED state should ignore rollback protection (according to the documentation).

However, the Nothing Phone bootloader seemingly refuse to boot to fastbootd userspace without a valid vbmeta, even in UNLOCKED state.

Even with rollback protection, since the bootloader is unlocked it will still accept any signature key (otherwise you couldn't root the phone or install alternative OSes).

So we can just feed it an old version with the rollback index of a new version, sign it with a random key, and as far as the bootloader is concerned the rollback index hasn't changed, so boot can continue.

(And this is why Android specifies that rollback should be ignored in UNLOCKED state, it's pointless to try to block downgrades when the root of trust is the user)

We do this by flashing the first part of a stock full OTA of an older version, then crafting custom vbmeta and vbmeta_system partitions with AVB tools to get to fastbootd userspace.

Then we can flash the rest of the OTA, wipe data, and reboot into the OS.

Prerequisites:

- Backups of your data, downgrades almost always require a wipe

- A working, unlocked bootloader (non-userspace fastboot)

- A full OTA .zip that you want to rollback to

- If you want to rollback to a version that only has an incremental OTA, start by rolling back to the next older full OTA, then sideload the updates to that version.

- The android platform tools and driver, to send fastboot commands

- The openssl command line tool (https://wiki.openssl.org/index.php/Binaries), to generate VBMeta keys

- ssut's payload-dumper-go (https://github.com/ssut/payload-dumper-go) to extract the OTA partition images

- The android AVB 2.0 tools (https://android.googlesource.com/platform/external/avb/), to forge the two VBMeta partitions

- Either of:

- The rollback index number corresponding to your version of the OS (if you know it)

- A fully booted and rooted device on the same version as your current device, to extract the rollback index from the vbmeta partition on the phone

- A full OTA of a version at least as new as the one on your phone, to read the rollback index from vbmeta.img

Procedure:

WARNING: Despite the phone having A/B slots, flashing an older OTA is LIKELY to break both slots. Do not attempt this if you're not ready to go all the way and do a full wipe.

Part I: Prepare the target full OTA image to rollback to

- Create an empty folder to hold the working files we'll use during the guide.

- Open a command shell into that folder, the rest of the guide assumes all paths are relative to this folder

- Download the full OTA .zip you want to flash and save it at ./target-ota.zip (in the folder you created above)

- Extract the partitions from the OTA using payload-dumper-go: payload-dumper-go -o target-ota target-ota.zip

(This assumes payload-dumper-go is in your PATH, if not use the correct path to payload-dumper-go from your command line)

Part 2: Get the rollback index of your current version

Each time you upgrade, the rollback protection keeps track of a number called the "rollback index" (it actually can keep track of several, but the nothing phone only really uses one).

In the next steps, we will need to edit to older target OTA with the rollback index that matches the version currently on your phone.

If the rollback index you use is too low, the bootloader will refuse to boot. If it's too high, your phone will be stuck at that version and reject official OTAs and custom ROMs until they increment their rollback index above yours.

If you don't already know the rollback index of your current version from a public list, you can extract it from your current vbmeta partition:

a) On a rooted phone (either your phone, or a phone with the _same version_ as yours) dump the vbmeta and vbmeta_system partitions for the current slot

If you don't have any special tool to dump partitions, you can do it with just the platform tools and a root shell:

- On a root shell on the phone, run ls -la /dev/block/bootdevice/by-name, and note the path to your current slot's vbmeta and vbmeta_system partitions (e.g. /dev/block/sde14 and /dev/block/sda7 on my phone)

- On your computer, use adb shell and dd to dump the partitions, replacing the /dev/block/$DEV values by the paths you found in the last command:

adb shell "su -c 'stty raw; dd if=/dev/block/$DEV'" > vbmeta.img

adb shell "su -c 'stty raw; dd if=/dev/block/$DEV'" > vbmeta_system.img

b) If you have the full OTA of the version currently running on your phone:

- Extract the OTA with payload-dumper-go (as above) and copy the vbmeta.img and vbmeta_system.img to the working directory

Now that you have vbmeta.img and vbmeta_system.img, use the AVB 2.0 tools (see prerequisites) to read the image info:

./avb/avbtool.py info_image --image vbmeta.img

./avb/avbtool.py info_image --image vbmeta_system.img

These two command will each print the contents of the VBMeta structure. Look for the "Rollback Index" and "Rollback Index Location" values in the output

The vbmeta image should have location 0 and index 0, and a "Chain Partition descriptor" that points to vbmeta_system with "Rollback Index Location" value 2

The vbmeta_system should have location 0, and a large number (timestamp) in the rollback index. This is the rollback index value we care about, keep a note of it.

For instance, for my 1.1.4 EEA version, the rollback index of vbmeta_system is 1661990400.

If the other values aren't 0, 0, and 2 for the chain descriptor, you may need to adapt later commands to pass those newer values. If you're unsure, stop.

Flashing bad rollback indexes may cause your phone to reject future legitimate ROMs that have a lower index.

Part 3: Forge the vbmeta partitions

- Using the openssl command line tools, generate two new keys to sign the vbmeta partition:

openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 -outform PEM -out rsa_vbmeta_system.pem

openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:4096 -outform PEM -out rsa_vbmeta.pem

- Using AVB tools (see prerequisites), generate a forged vbmeta_system image:

(Don't forget to replace the $ROLLBACK_INDEX in the command by the value you found above)

./avb/avbtool.py make_vbmeta_image --output vbmeta_system_forged.img --rollback_index $ROLLBACK_INDEX --rollback_index_location 0 --algorithm SHA256_RSA2048 --key rsa_vbmeta_system.pem --include_descriptors_from_image target-ota/product.img --include_descriptors_from_image target-ota/system.img --include_descriptors_from_image target-ota/system_ext.img

And a forged vbmeta image:

./avb/avbtool.py make_vbmeta_image --output forged/vbmeta_forged.img --rollback_index 0 --rollback_index_location 0 --algorithm SHA256_RSA4096 --key forged/rsa_vbmeta.pem --chain_partition vbmeta_system:2:forged/vbmeta_system_forged.img --set_hashtree_disabled_flag --include_descriptors_from_image target-ota/boot.img --include_descriptors_from_image target-ota/dtbo.img --include_descriptors_from_image target-ota/vendor_boot.img --include_descriptors_from_image target-ota/odm.img --include_descriptors_from_image target-ota/vendor.img

Part 4: Reach usperspace fastbootd

Time to flash the first part of the stock OTA and our forged vbmeta.

Reboot into the bootloader (either adb reboot bootloader, fastboot reboot bootloader, or manually).

Pick the A/B slot you want with fastboot, for instance fastboot set_active a

In your command prompt, flash these partitions from the target stock OTA. (Make sure you have a recent enough version of fastboot from the platform tools):

fastboot flash abl target-ota/abl.img
fastboot flash aop target-ota/aop.img
fastboot flash bluetooth target-ota/bluetooth.img
fastboot flash boot target-ota/boot.img
fastboot flash vendor_boot target-ota/vendor_boot.img
fastboot flash cpucp target-ota/cpucp.img
fastboot flash devcfg target-ota/devcfg.img
fastboot flash dsp target-ota/dsp.img
fastboot flash dtbo target-ota/dtbo.img
fastboot flash featenabler target-ota/featenabler.img
fastboot flash hyp target-ota/hyp.img
fastboot flash imagefv target-ota/imagefv.img
fastboot flash keymaster target-ota/keymaster.img
fastboot flash modem target-ota/modem.img
fastboot flash multiimgoem target-ota/multiimgoem.img
fastboot flash qupfw target-ota/qupfw.img
fastboot flash shrm target-ota/shrm.img
fastboot flash tz target-ota/tz.img
fastboot flash uefisecapp target-ota/uefisecapp.img
fastboot flash xbl target-ota/xbl.img
fastboot flash xbl_config target-ota/xbl_config.img

Flash our forged vbmeta:

fastboot --disable-verity --disable-verification flash vbmeta_system vbmeta_system_forged.img
fastboot --disable-verity --disable-verification flash vbmeta vbmeta_forged.img

And now you should be able to reboot to userspace fastbootd:

fastboot reboot fastboot

If your device reboots to bootloader (you do not see fastbootd at the top of the screen, and fastboot getvar is-userspace says no), something went wrong. Stop, make sure you understood the steps correctly, and try again.

Part 5: Flash the rest, wipe data, and boot into the OS

Now that we're in userspace fastbootd, we can flash the virtual partitions that require a running kernel. Make sure the slot hasn't changed, and run:

fastboot flash odm target-ota/odm.img
fastboot flash product target-ota/product.img
fastboot flash system target-ota/system.img
fastboot flash system_ext target-ota/system_ext.img
fastboot flash vendor target-ota/vendor.img

When this is done, reboot the device.

If the device reboots to bootloader, something went wrong. Stop and try the steps above again.

If you reach a screen saying "Can't load android system, your data may be corrupt", that is normal.

This means we successfully booted into the kernel, bypassed the rollback protection, but the older OTA we flashed can't run with your current data partition (either because of incompatibility, or the encryption ratchet's separate anti-rollback)

Wipe the data partition using the menu option.

On next reboot you'll reach the Android setup wizard.