Have you ever booted up an Android-based device using Ubuntu Touch and wondered how to get rid of the warnings at boot? "Help, I'm unlocked! Don't trust me!" the device screams at you while loading the kernel to proceed. This is due to the state of the boot process not being verifiable anymore after unlocking the device for installation of an operating system alternative to Android.
Missing verified boot capabilities is a known security deficiency on GNU/Linux-based mobile operating systems like Ubuntu Touch. We have paid little attention to the tight integration of operating system security features of Android paired with capabilities that hardware vendors provide as part of their bootloaders, partly because it is hard to do while staying fair across a variety of different devices from different generations.
Ideally Ubuntu Touch devices bring the same level of security as Android while staying true to the licenses that comprise the software, keeping the ability to replace GPLv3 components as the user chooses. Those goals might be mutually exclusive but users should be able to choose between exercising their rights and higher level of security as they wish.
Since devices based on Halium are inherently Android devices and follow standards set by Google to enforce security policy, it is necessary to bend the operating system in a way that fits both the use case of those Android devices as well as keeping the ability to run on mainline devices as well.
Now verified boot in itself is not the means to an end, it is a single step in the direction of increasing security of the platform on devices that support those capabilities. Encryption of user data is another important feature without which verified boot won't be able to produce the desired results.
Devices released with Android 8.0 and up ship with a feature called Android Verified Boot 2.0. Simply speaking, it allows signature verification of partitions to keep integrity of the boot process intact. This is done by inspecting and using the contents of the
vbmeta partition as per this desciption in the AOSP repository: https://android.googlesource.com/platform/external/avb/+/master/README.md#The-VBMeta-struct
Using the Pixel 3a as a reference implementation of Ubuntu Touch with this functionality allows for great possibilities, since it shipped with Android 9.0, has AVB 2.0 enabled and ships with all the dm-verity support in the kernel. Checks all the boxes, but how do we marry those features with Ubuntu Touch?
To achieve the goal we need to rethink the way that the operating system currently handles system updates. Without security measures in place it was easy to provide an update mechanism that was solely based on verifying the update package itself. Currently the update mechanism works as follows:
- Download a set of tarballs
- Tell the recovery system which tarballs to install
- The recovery system verifies validity via GPG
- It then proceeds to unpack tarballs, flash boot partitions, etc.
With AVB 2.0 we need a mechanism to tell the bootloader that the operating system has not been tampered with, that means signing the final result of an operating system update for verification by the bootloader. For that to happen we roughly need a scheme similar to this one:
- At the time of first installing the OS, generate a key that can be flashed onto the
avb_custom_keyvirtual partition via fastboot
- Injecting the .pem file required to sign the
vbmetacontents into a known location on the writable (and encryptable) data partition
- Verify update package contents as before, using GPG
- Unpack the tarballs into the target partition
- Flash partitions as required for booting up
- Creating and signing a
vbmetaimage based on the system, boot and vendor partitions
- Flashing the just-created vbmeta image
Doing so might be harder to do than necessary inside of the existing recovery machinery, which implies a limited set of tools. Since the reference
avbtool used to create
vbmeta images is written in Python it seems like a no-brainer to reuse whatever Google has already created for phones that primarily ship with their platform by default.
But how do we update the running system if Ubuntu Touch doesn't make use of a package manager to install OS updates? For that it's required to take the update mechanism to a whole new level by making use of the A/B slot system that most newer Android phones ship with. Using A/B slots we can unpack the tarballs from within the running system into a secondary partition, leaving the running system alone, and having atomic update behavior after flipping over to the newly installed slot. This would all happen in the background while allowing normal use of the operating system. After a reboot your phone will boot into the freshly updated slot, allowing verifiability along the way.
Juggling security with freedom
Detection of a tampered with system brings up one question though, and that is how to allow replacing operating system components in this scenario?
Right now my best answer is "don't, by default", with the simple explanation that manually replacing operating system components while keeping integrity is a hard to solve problem. Users that wish to remount the operating system to a writable state need to take care of the system by themselves. This means recreating, signing and flashing a vbmeta image for every change the user chooses to do on their own machine.
So for user experience reasons, and to keep the GPLv3 obligations intact, there would be a checkbox in the System Settings application, off by default, that determines whether to enable those security features. This is good for two reasons:
- Allowing installation of the system on an unlocked device, to get rid of an extra step to re-unlock the phone after installation
- Allowing the personal decision to further lock down the device as necessary, via
fastboot flashing lock
Once activated the lock state cannot be changed anymore.
Getting rid of the bootloader warnings at startup has been a pain for many users for years, but solving that problem is not going to increase the security of Ubuntu Touch completely. To achieve this we need to redo a handful of things with regards to updating the system, which inherently modifies the OS partitions. Implementation of user data encryption is an additional hard requirement to provide a fully locked down and secure phone to those who wish to have it. But as with all things: with one problem solved we can focus on the next task.