I would like to revise how data is encrypted on SFOS and design an approach that would protect our data better. The description below is my understanding of the state and suggesting solutions to the problem. I am giving some background as well, something I’ve learned recently and probably few of us are on the same boat as me. It is mainly targeting fellow developers and consider this as RFC. As it is about data safety, it would be great o get the more eyes looking through it.
Current state
While I do not have any official device and cannot confirm it myself, here is the information from fellow users as far as I understand it. On the devices with encryption of home partition, we use LUKS with the PIN entered by user to encrypt the data. Cryptsetup/LUKS would protect your password/PIN by stretching it through number of iterations. Usually, number of iterations is found by doing them for some period of time, 2s for example. However, assuming that mobile phone CPU is weak, we get rather small number of iterations performed. With the attacker having ability to load and boot any image on our devices (open bootloader), we can expect that LUKS header and data is easy to extract. As PINs are short, number of combinations is small and, when attack is done on PC with more powerful CPU, we can expect that the brute force attack is fast in unencrypting the data.
In other words, data can be considered as not encrypted for most of the cases.
Aim
Aim is to design an approach that would allow us to enter relatively short password (6 chars,numbers,symbols) and have data encrypted with the high entropy key.
Example with TPM
On PC, equipped with TPM, it is rather trivial to secure encryption keys. You could either generate them on TPM or just store them on TPM. By adding access protection with the password, even short one, makes it very difficult to access the key due to the lockout mechanism in TPM. Namely, after a number of tries, 10 or more, you would not be able to try again during some defined period of time (1 hour, for example). As a result, brute force approach is rather inefficient and would protect your data from most of the attackers we could experience in practice.
SFOS has a similar profile to PC - as we cannot lock our bootloaders. So, probably similar approach is needed.
Encrypting data
On SFOS official devices and ports following them, LVM is used to manage partitions allowing us to encrypt /home partition using LUKS/cryptsetup. On unofficial ports based on LOS, it is still possible to encrypt data. Here, fscrypt can be used for devices with newer kernels. Alternative is to use loopback device for home data and encrypt with LUKS/cryptsetup.
FSCrypt and LUKS allow you to specify multiple passwords. As a result, we could use one “recovery” password and one hardware backed password. The latter will be used in practice while the former can be accessed when hardware keys are wiped or for other reasons.
In principle, data encryption protection boils down to protecting your keys. Below, two cases are considered.
Hybris ports with Android Keystore
Android Keystore provides the means to store keys in hardware backed stores. In practice, it is frequently realized via TEE of Qualcomm. On newer devices, we may get “secure element” (strongbox or similar) that would offload key storage to separate hardware.
Looking into Android Keystore API, I didn’t find any means to protect the key with PIN/password and having something similar to lockout used by TPM. Key usage limitations are are implemented via Android and are out of our usage case with the attacker having root access. Which means that we have to design the protection by tying it to hardware limitations. However, it can be assumed that the user with root access cannot obtain the key stored in the hardware but can just use it. The latter assumption means that we rely on Qualcomm to implement hardware based keystore according to its specs. Bugs in TEE could creep in, which users should be aware of.
I propose the following scheme for encryption / decryption.
EDIT 9 Aug 2021: For updated proposal, see RFC: Revision of /home encryption on SFOS - #23 by rinigus
Original proposal: For key generation and encryption:
- create hardware backed AES256 private key using Android keystore, name it “HWkey”
- create random key (32 bytes) used for LUKS encryption, name it “LUKSkey”
- create salt and store in /etc
- generate user password key using salt and user password. PBKDF2 or scrypt can be used for that user key generation, name key USERkey.
- determine hardware performance in decrypting some smaller encrypted data blob encrypted earlier by HWkey. Should find how many times per second (N) can data be decrypted on device.
- encrypt LUKSkey using HWkey at least K times (nested encryption) and, after that, encrypt using USERkey once. Store encrypted blob, K, and salt. Ensure that K is >= N
For opening LUKS container :
- get user password from user’s input
- generate user key from password and salt
- decrypt encrypted blob once using userkey and K times using HWkey
Decryption would take time, depending on K selection, a second or more. The scheme ties decryption to used hardware and would limit brute force approaches to use the device for cracking user password. Depending on user password, fully random alphanumeric sequence of 5 symbols takes (26*2+10)**5/24/60/60/365 ~ 29 years to get through.
USB keys
Alternative to hybris would be to use external USB devices to keep LUKS encryption key. It can be combined with the user password, similar to hybris approach. I guess we can design approaches with plain USB key holding decryption key (hoping that phone gets stolen without USB key) or have some extra protection from USB devices designed to keep encryption keys. If USB device is made to support encryption through device only, approach similar to the one proposed for hybris can be used to limit brute force attacks. But that would probably require checking and taking into account available API/hw support.
Other approaches
Other ways of combining keys are possible, such as NFC smart cards, QR with a part of encryption key, for example. So, design of the applications responsible for encryption support should be flexible and allow us later to add plugins. Together with USB keys, these approaches are of special interest to native ports (PinePhone) where Android keystore is not available. Or to the users who would prefer it instead of Android Keystores.
Implementation
It seems that we will need to write:
- an application that provides decryption key to LUKS or FSCrypt with the support for multiple key providers
- an application handling user provided keys
Again, as I don’t have official device with encryption, I don’t know how flexible current solution is. I don’t even know whether currently used applications are open source. If we cannot use them, I suggest to write applications immediately using cross-platform approach that would allow it to be used on SFOS, Plasma Mobile, and maybe UbuntuTouch.
EDIT 9 Aug 2021: For updated proposal, see RFC: Revision of /home encryption on SFOS - #23 by rinigus