Revisiting Android disk encryption
In iOS 8, Apple has expanded the scope of data encryption and now mixes in the user's passcode with an unextractable hardware UID when deriving an encryption key, making it harder to extract data from iOS 8 devices. This has been somewhat of a hot topic lately, with opinions ranging from praise for Apple's new focus on serious security, to demands for "golden keys" to mobile devices to be magically conjured up. Naturally, the debate has spread to other OS's, and Google has announced that the upcoming Android L release will also have disk encryption enabled by default. Consequently, questions and speculation about the usefulness and strength of Android's disk encryption have sprung up on multiple forums, so this seems like a good time to take another look at its implementation. While Android L still hasn't been released yet, some of the improvements to disk encryption it introduces are apparent in the preview release, so this post will briefly introduce them as well.
This post will focus on the security level of disk encryption, for more details on its integration with the platform, see Chapter 10 of my book -- 'Android Security Internals' (early access full PDF is available now, print books should ship by end of October).
As you can see, the footer now includes an explicit
Bruteforcing the master key now requires parsing the crypto footer, initializing scrypt and generating all target PIN or password combinations. As the 1.2 crypto footer still does not include a master key checksum, checking whether the tried PIN or password is correct again requires looking for known plaintext in the ext4 superblock.
While hashcat does support scrypt since version 1.30, it is not much more efficient (and in fact can be slower) than running scrypt on a CPU. Additionally, the Android 4.4 crypto footer format is not supported, so hashcat cannot be used to recover Android 4.4 disk encryption passphrases as is.
Instead, the Santoku Linux FDE bruteforcer Python script can be extended to support the 1.2 crypto footer format and the scrypt KDF. A sample (and not particularly efficient) implementation can be found here. It might produce the following output when run on a 3.50GHz Intel Core i7 CPU:
As you can see, trying 1200 PIN combinations requires almost 5 minutes, so recovering a simple PIN is no longer instantaneous. That said, cracking a short PIN or password is still very much feasible, so choosing a strong locksreen password (or a dedicated disk encryption password, when possible) is still very important.
This post will focus on the security level of disk encryption, for more details on its integration with the platform, see Chapter 10 of my book -- 'Android Security Internals' (early access full PDF is available now, print books should ship by end of October).
Android 3.0-4.3
Full disk encryption (FDE) for Android was introduced in version 3.0 (Honeycomb) and didn't change much until version 4.4 (discussed in the next section). Android's FDE uses the dm-crypt target of Linux's device mapper framework to implement transparent disk encryption for the userdata (mounted as
Android uses a so called 'crypto footer' structure to store encryption parameters. It is very similar to the encrypted partition header used by LUKS (Linux Unified Key Setup), but is simpler and omits several LUKS features. While LUKS supports multiple key slots, allowing for decryption using multiple passphrases, Android's crypto footer only stores a single copy of the encrypted master key and thus supports a single decryption passphrase. Additionally, while LUKS splits the encrypted key in multiple 'stripes' in order to reduce the probability of recovering the full key after it has been deleted from disk, Android has no such feature. Finally, LUKS includes a master key checksum (derived by running the master key through PBKDF2), which allows to check whether the entered passphrase is correct without decrypting any of the disk data. Android's crypto footer doesn't include a master key checksum, so the only way to check whether the entered passphrase is correct is to try and mount the encrypted partition. If the mount succeeds, the passphrase is considered correct.
Here's how the crypto footer looks in Android 4.3 (version 1.0).
The structure includes the version of the FDE scheme, the key size, some flags and the name of the actual disk encryption cipher mode (aes-cbc-essiv:sha256). The crypto footer is immediately followed by the encrypted key and a 16-bit random salt value. In this initial version, a lot of the parameters are implicit and are therefore not included in the crypto footer. The master key is encrypted using an 128-bit AES key (key encryption key, or KEK) derived from an user-supplied passphrase using 2000 iteration of PBKDF2. The derivation process also generates an IV, which is used to encrypt the master key in CBC mode. When an encrypted device is booted, Android takes the passphrase the user has entered, runs it through PBKDF2, decrypts the encrypted master key and passes it to dm-crypt in order to mount the encrypted userdata partition.
Bruteforcing on the device is obviously impractical due to the limited processing resources of Android devices and the built-in rate limiting after several unsuccessful attempts. A much more practical approach is to obtain a copy of the crypto footer and the encrypted userdata partition and try to guess the passphrase offline, using much more powerful hardware. Obtaining a raw copy of a disk partition is usually not possible on most commercial devices, but can be achieved by booting a specialized data acquisition boot image signed by the device manufacturer, exploiting a flaw in the bootloader that allows unsigned images to be booted (such as this one), or simply by booting a custom recovery image on devices with an unlocked bootloader (a typical first step to 'rooting').
Once the device has been booted, obtaining a copy of the userdata partition is straightforward. The crypto footer however, despite its name, typically resides on a dedicated partition on recent devices. The name of the partition is specified using the
Once we know the name of the partition that stores the crypto footer it can be copied simply by using the
Very short passcodes (for example a 4-digit PIN) can be successfully bruteforced using a script (this particular one is included in Santoku Linux) that runs on a desktop CPU. However, much better performance can be achieved on a GPU, which has been specifically designed to execute multiple tasks in parallel. PBKDF2 is an iterative algorithm based on SHA-1 (SHA-2 can also be used) that requires very little memory for execution and lends itself to paralellization. One GPU-based, high-performance PBKDF2 implementation is found in the popular password recovery tool hashcat. Version 1.30 comes with a built-in Android FDE module, so recovering an Android disk encryption key is as simple as parsing the crypto footer and feeding the encrypted key, salt, and the first several sectors of the encrypted partition to hashcat. As we noted in the previous section, the crypto footer does not include any checksum of the master key, so the only way to check whether the decrypted master key is the correct one is to try to decrypt the disk partition and look for some known data. Because most current Android devices use the ext4 filesystem, hashcat (and other similar tools) look for patterns in the ext4 superblock in order to confirm whether the tried passphrase is correct.
The Android FDE input for hashcat includes the salt, encrypted master key and the first 3 sectors of the encrypted partition (which contain a copy of the 1024-byte ext4 superblock). The hashcat input file might look like this (taken from the hashcat example hash):
On a device that uses a six-digit lockscreen PIN, the PIN, and consequently the FDE master key can be recovered with the following command:
Even when run on the GPU of a mobile computer (NVIDIA GeForce 730M), hashcat can achieve more than 20,000 PBKDF2 hashes per second, and recovering a 6 digit PIN takes less than 10 seconds. On the same hardware, a 6-letter (lowercase only) password takes about 4 hours.
As you can see, bruteforcing a simple PIN or password is very much feasible, so choosing a strong lockscreen password is vital. Lockscreen password strength can be enforced by installing a device administrator that sets password complexity requirements. Alternatively, a dedicated disk encryption password can be set on rooted devices using the shell or a dedicated application. CyanogenMod 11 supports setting a dedicated disk encryption password out of the box, and one can be set via system Settings, as shown below.
/data
) partition. Once encryption is enabled, all writes to disk automatically encrypt data before committing it to disk and all reads automatically decrypt data before returning it to the calling process. The disk encryption key (128-bit, called the 'master key') is randomly generated and protected by the lockscreen password. Individual disk sectors are encrypted by the master key using AES in CBC mode, with ESSIV:SHA256 to derive sector IVs.Android uses a so called 'crypto footer' structure to store encryption parameters. It is very similar to the encrypted partition header used by LUKS (Linux Unified Key Setup), but is simpler and omits several LUKS features. While LUKS supports multiple key slots, allowing for decryption using multiple passphrases, Android's crypto footer only stores a single copy of the encrypted master key and thus supports a single decryption passphrase. Additionally, while LUKS splits the encrypted key in multiple 'stripes' in order to reduce the probability of recovering the full key after it has been deleted from disk, Android has no such feature. Finally, LUKS includes a master key checksum (derived by running the master key through PBKDF2), which allows to check whether the entered passphrase is correct without decrypting any of the disk data. Android's crypto footer doesn't include a master key checksum, so the only way to check whether the entered passphrase is correct is to try and mount the encrypted partition. If the mount succeeds, the passphrase is considered correct.
Here's how the crypto footer looks in Android 4.3 (version 1.0).
struct crypt_mnt_ftr { __le32 magic; __le16 major_version; __le16 minor_version; __le32 ftr_size; __le32 flags; __le32 keysize; __le32 spare1; __le64 fs_size; __le32 failed_decrypt_count; unsigned char crypto_type_name[MAX_CRYPTO_TYPE_NAME_LEN]; };
The structure includes the version of the FDE scheme, the key size, some flags and the name of the actual disk encryption cipher mode (aes-cbc-essiv:sha256). The crypto footer is immediately followed by the encrypted key and a 16-bit random salt value. In this initial version, a lot of the parameters are implicit and are therefore not included in the crypto footer. The master key is encrypted using an 128-bit AES key (key encryption key, or KEK) derived from an user-supplied passphrase using 2000 iteration of PBKDF2. The derivation process also generates an IV, which is used to encrypt the master key in CBC mode. When an encrypted device is booted, Android takes the passphrase the user has entered, runs it through PBKDF2, decrypts the encrypted master key and passes it to dm-crypt in order to mount the encrypted userdata partition.
Bruteforcing FDE 1.0
The encryption scheme described in the previous section is considered relatively secure, but because it is implemented entirely in software, it's security depends entirely on the complexity of the disk encryption passphrase. If it is sufficiently long and complex, bruteforcing the encrypted master key could take years. However, because Android has chosen to reuse the losckreen PIN or password (maximum length 16 characters), in practice most people are likely to end up with a relatively short or low-entropy disk encryption password. While the PBKDF2 key derivation algorithm has been designed to work with low-entropy input, and requires considerable computational effort to bruteforce, 2000 iterations are not a significant hurdle even to current off-the-shelf hardware. Let's see how hard it is to bruteforce Android FDE 1.0 in practice.Bruteforcing on the device is obviously impractical due to the limited processing resources of Android devices and the built-in rate limiting after several unsuccessful attempts. A much more practical approach is to obtain a copy of the crypto footer and the encrypted userdata partition and try to guess the passphrase offline, using much more powerful hardware. Obtaining a raw copy of a disk partition is usually not possible on most commercial devices, but can be achieved by booting a specialized data acquisition boot image signed by the device manufacturer, exploiting a flaw in the bootloader that allows unsigned images to be booted (such as this one), or simply by booting a custom recovery image on devices with an unlocked bootloader (a typical first step to 'rooting').
Once the device has been booted, obtaining a copy of the userdata partition is straightforward. The crypto footer however, despite its name, typically resides on a dedicated partition on recent devices. The name of the partition is specified using the
encryptable
flag in the device's fstab
file. For example, on the Galaxy Nexus, the footer is on the metadata partition as shown below./dev/block/platform/omap/omap_hsmmc.0/by-name/userdata /data ext4 \ noatime,nosuid,nodev,nomblk_io_submit,errors=panic \ wait,check,encryptable=/dev/block/platform/omap/omap_hsmmc.0/by-name/metadata
Once we know the name of the partition that stores the crypto footer it can be copied simply by using the
dd
command.Very short passcodes (for example a 4-digit PIN) can be successfully bruteforced using a script (this particular one is included in Santoku Linux) that runs on a desktop CPU. However, much better performance can be achieved on a GPU, which has been specifically designed to execute multiple tasks in parallel. PBKDF2 is an iterative algorithm based on SHA-1 (SHA-2 can also be used) that requires very little memory for execution and lends itself to paralellization. One GPU-based, high-performance PBKDF2 implementation is found in the popular password recovery tool hashcat. Version 1.30 comes with a built-in Android FDE module, so recovering an Android disk encryption key is as simple as parsing the crypto footer and feeding the encrypted key, salt, and the first several sectors of the encrypted partition to hashcat. As we noted in the previous section, the crypto footer does not include any checksum of the master key, so the only way to check whether the decrypted master key is the correct one is to try to decrypt the disk partition and look for some known data. Because most current Android devices use the ext4 filesystem, hashcat (and other similar tools) look for patterns in the ext4 superblock in order to confirm whether the tried passphrase is correct.
The Android FDE input for hashcat includes the salt, encrypted master key and the first 3 sectors of the encrypted partition (which contain a copy of the 1024-byte ext4 superblock). The hashcat input file might look like this (taken from the hashcat example hash):
$fde$16$ca56e82e7b5a9c2fc1e3b5a7d671c2f9$16$7c124af19ac913be0fc137b75a34b20d$eac806ae7277c8d4...
On a device that uses a six-digit lockscreen PIN, the PIN, and consequently the FDE master key can be recovered with the following command:
$ cudaHashcat64 -m 8800 -a 3 android43fde.txt ?d?d?d?d?d?d ... Session.Name...: cudaHashcat Status.........: Cracked Input.Mode.....: Mask (?d?d?d?d?d?d) [6] Hash.Target....: $fde$16$aca5f840... Hash.Type......: Android FDE Time.Started...: Sun Oct 05 19:06:23 2014 (6 secs) Speed.GPU.#1...: 20629 H/s Recovered......: 1/1 (100.00%) Digests, 1/1 (100.00%) Salts Progress.......: 122880/1000000 (12.29%) Skipped........: 0/122880 (0.00%) Rejected.......: 0/122880 (0.00%) HWMon.GPU.#1...: 0% Util, 48c Temp, N/A Fan Started: Sun Oct 05 19:06:23 2014 Stopped: Sun Oct 05 19:06:33 2014
Even when run on the GPU of a mobile computer (NVIDIA GeForce 730M), hashcat can achieve more than 20,000 PBKDF2 hashes per second, and recovering a 6 digit PIN takes less than 10 seconds. On the same hardware, a 6-letter (lowercase only) password takes about 4 hours.
As you can see, bruteforcing a simple PIN or password is very much feasible, so choosing a strong lockscreen password is vital. Lockscreen password strength can be enforced by installing a device administrator that sets password complexity requirements. Alternatively, a dedicated disk encryption password can be set on rooted devices using the shell or a dedicated application. CyanogenMod 11 supports setting a dedicated disk encryption password out of the box, and one can be set via system Settings, as shown below.
Android 4.4
Android 4.4 adds several improvements to disk encryption, but the most important one is replacing the PBKDF2 key derivation function (KDF) with scrypt. scrypt has been specifically designed to be hard to crack on GPUs by requiring a large (and configurable) amount of memory. Because GPUs have a limited amount of memory, executing multiple scrypt tasks in parallel is no longer feasible, and thus cracking scrypt is much slower than PBKDF2 (or similar hash-based KDFs). As part of the upgrade process to 4.4, Android automatically updates the crypto footer to use scrypt and re-encrypts the master key. Thus every device running Android 4.4 (devices using a vendor-proprietary FDE scheme excluded) should have its FDE master key protected using an scrypt-derived key.
The Android 4.4 crypto footer looks like this (version 1.2):
The Android 4.4 crypto footer looks like this (version 1.2):
struct crypt_mnt_ftr { __le32 magic; __le16 major_version; __le16 minor_version; __le32 ftr_size; __le32 flags; __le32 keysize; __le32 spare1; __le64 fs_size; __le32 failed_decrypt_count; unsigned char crypto_type_name[MAX_CRYPTO_TYPE_NAME_LEN]; __le32 spare2; unsigned char master_key[MAX_KEY_LEN]; unsigned char salt[SALT_LEN]; __le64 persist_data_offset[2]; __le32 persist_data_size; __le8 kdf_type; /* scrypt parameters. See www.tarsnap.com/scrypt/scrypt.pdf */ __le8 N_factor; /* (1 << N) */ __le8 r_factor; /* (1 << r) */ __le8 p_factor; /* (1 << p) */ };
As you can see, the footer now includes an explicit
kdf_type
which specifies the KDF used to derive the master key KEK. The values of the scrypt initialization parameters (N, r and p) are also included. The master key size (128-bit) and disk sector encryption mode (aes-cbc-essiv:sha256) are the same as in 4.3.Bruteforcing the master key now requires parsing the crypto footer, initializing scrypt and generating all target PIN or password combinations. As the 1.2 crypto footer still does not include a master key checksum, checking whether the tried PIN or password is correct again requires looking for known plaintext in the ext4 superblock.
While hashcat does support scrypt since version 1.30, it is not much more efficient (and in fact can be slower) than running scrypt on a CPU. Additionally, the Android 4.4 crypto footer format is not supported, so hashcat cannot be used to recover Android 4.4 disk encryption passphrases as is.
Instead, the Santoku Linux FDE bruteforcer Python script can be extended to support the 1.2 crypto footer format and the scrypt KDF. A sample (and not particularly efficient) implementation can be found here. It might produce the following output when run on a 3.50GHz Intel Core i7 CPU:
$ time python bruteforce_stdcrypto.py header footer 4 Android FDE crypto footer ------------------------- Magic : 0xD0B5B1C4 Major Version : 1 Minor Version : 2 Footer Size : 192 bytes Flags : 0x00000000 Key Size : 128 bits Failed Decrypts: 0 Crypto Type : aes-cbc-essiv:sha256 Encrypted Key : 0x66C446E04854202F9F43D69878929C4A Salt : 0x3AB4FA74A1D6E87FAFFB74D4BC2D4013 KDF : scrypt N_factor : 15 (N=32768) r_factor : 3 (r=8) p_factor : 1 (p=2) ------------------------- Trying to Bruteforce Password... please wait Trying: 0000 Trying: 0001 Trying: 0002 Trying: 0003 ... Trying: 1230 Trying: 1231 Trying: 1232 Trying: 1233 Trying: 1234 Found PIN!: 1234 real 4m43.985s user 4m34.156s sys 0m9.759s
As you can see, trying 1200 PIN combinations requires almost 5 minutes, so recovering a simple PIN is no longer instantaneous. That said, cracking a short PIN or password is still very much feasible, so choosing a strong locksreen password (or a dedicated disk encryption password, when possible) is still very important.
Android L
A preview release of the upcoming Android version (referred to as 'L') has been available for several months now, so we can observe some of expected changes to disk encryption. If we run the crypto footer obtained from an encrypted Android L device through the script introduced in the previous section, we may get the following output:
As you can see above, the crypto footer version has been upped to 1.3, but the disk encryption cipher mode and key size have not changed. However, version 1.3 uses a new, unknown KDF specified with the constant 3 (1 is PBKDF2, 2 is scrypt). Additionally, encrypting a device no longer requires setting a lockscreen PIN or password, which suggests that the master key KEK is no longer directly derived from the lockscreen password. Starting the encryption process produces the following logcat output:
As discussed in a previous post, 'QSEE' stands for Qualcomm Secure Execution Environment, which is an ARM TrustZone-based implementation of a TEE. QSEE provides the hardware-backed credential store on most devices that use recent Qualcomm SoCs. From the log above, it appears that Android's keymaster HAL module has been extended to store the disk encryption key KEK in hardware-backed storage (Cf. 'Using scrypt with keymaster for cryptfs KDF' in the log above). The log also mentions scrypt, so it is possible that the lockscreen password (if present) along with some key (or seed) stored in the TEE are fed to the KDF to produce the final master key KEK. However, since no source code is currently available, we cannot confirm this. That said, setting an unlock pattern on an encrypted Android L device produces the following output, which suggests that the pattern is indeed used when generating the encryption key:
As you can be see in the listing above, the
$ ./bruteforce_stdcrypto.py header L_footer 4 Android FDE crypto footer ------------------------- Magic : 0xD0B5B1C4 Major Version : 1 Minor Version : 3 Footer Size : 2288 bytes Flags : 0x00000000 Key Size : 128 bits Failed Decrypts: 0 Crypto Type : aes-cbc-essiv:sha256 Encrypted Key : 0x825F3F10675C6F8B7A6F425599D9ECD7 Salt : 0x0B9C7E8EA34417ED7425C3A3CFD2E928 KDF : unknown (3) N_factor : 15 (N=32768) r_factor : 3 (r=8) p_factor : 1 (p=2) ------------------------- ...
As you can see above, the crypto footer version has been upped to 1.3, but the disk encryption cipher mode and key size have not changed. However, version 1.3 uses a new, unknown KDF specified with the constant 3 (1 is PBKDF2, 2 is scrypt). Additionally, encrypting a device no longer requires setting a lockscreen PIN or password, which suggests that the master key KEK is no longer directly derived from the lockscreen password. Starting the encryption process produces the following logcat output:
D/QSEECOMAPI: ( 178): QSEECom_start_app sb_length = 0x2000 D/QSEECOMAPI: ( 178): App is already loaded QSEE and app id = 1 D/QSEECOMAPI: ( 178): QSEECom_shutdown_app D/QSEECOMAPI: ( 178): QSEECom_shutdown_app, app_id = 1 ... I/Cryptfs ( 178): Using scrypt with keymaster for cryptfs KDF D/QSEECOMAPI: ( 178): QSEECom_start_app sb_length = 0x2000 D/QSEECOMAPI: ( 178): App is already loaded QSEE and app id = 1 D/QSEECOMAPI: ( 178): QSEECom_shutdown_app D/QSEECOMAPI: ( 178): QSEECom_shutdown_app, app_id = 1
As discussed in a previous post, 'QSEE' stands for Qualcomm Secure Execution Environment, which is an ARM TrustZone-based implementation of a TEE. QSEE provides the hardware-backed credential store on most devices that use recent Qualcomm SoCs. From the log above, it appears that Android's keymaster HAL module has been extended to store the disk encryption key KEK in hardware-backed storage (Cf. 'Using scrypt with keymaster for cryptfs KDF' in the log above). The log also mentions scrypt, so it is possible that the lockscreen password (if present) along with some key (or seed) stored in the TEE are fed to the KDF to produce the final master key KEK. However, since no source code is currently available, we cannot confirm this. That said, setting an unlock pattern on an encrypted Android L device produces the following output, which suggests that the pattern is indeed used when generating the encryption key:
D/VoldCmdListener( 173): cryptfs changepw pattern {} D/QSEECOMAPI: ( 173): QSEECom_start_app sb_length = 0x2000 D/QSEECOMAPI: ( 173): App is already loaded QSEE and app id = 1 ... D/QSEECOMAPI: ( 173): QSEECom_shutdown_app D/QSEECOMAPI: ( 173): QSEECom_shutdown_app, app_id = 1 I/Cryptfs ( 173): Using scrypt with keymaster for cryptfs KDF D/QSEECOMAPI: ( 173): QSEECom_start_app sb_length = 0x2000 D/QSEECOMAPI: ( 173): App is already loaded QSEE and app id = 1 D/QSEECOMAPI: ( 173): QSEECom_shutdown_app D/QSEECOMAPI: ( 173): QSEECom_shutdown_app, app_id = 1 E/VoldConnector( 756): NDC Command {5 cryptfs changepw pattern [scrubbed]} took too long (6210ms)
As you can be see in the listing above, the
cryptfs changepw
command, which is used to send instructions to Android's vold
daemon, has been extended to support a pattern, in addition to the previously supported PIN/password. Additionally, the amount of time the password change takes (6 seconds) suggests that the KDF (scrypt) is indeed being executed to generate a new encryption key. Once we've set a lockscreen unlock pattern, booting the device now requires entering the pattern, as can be seen in the screenshot below. Another subtle change introduced in Android L, is that when booting an encrypted device the lockscreen pattern, PIN or password needs to be entered only once (at boot time), and not twice (once more on the lockscreen, after Android boots) as it was in previous versions.
While no definitive details are available, it is fairly certain that (at least on high-end devices), Android's disk encryption key(s) will have some hardware protection in Android L. Assuming that the implementation is similar to that of the hardware-backed credential store, disk encryption keys should be encrypted by an unextractable key encryption key stored in the SoC, so obtaining a copy of the crypto footer and the encrypted userdata partition, and bruteforcing the lockscreen passphrase should no longer be sufficient to decrypt disk contents. Disk encryption in the Android L preview (at least on a Nexus 7 2013) feels significantly faster (encrypting the 16GB data partition takes about 10 minutes), so it is most probably hardware-accelerated as well (or the initial encryption is only encrypting disk blocks that are actually in use, and not every single block as in previous versions). However, it remains to be seen whether high-end Android L devices will include a dedicated crypto co-processor akin to Apple's 'Secure Enclave'. While the current TrustZone-based key protection is much better than the software only implementation found in previous versions, a flaw in the secure TEE OS or any of the trusted TEE applications could lead to extracting hardware-protected keys or otherwise compromising the integrity of the system.
Update 2014/11/4: The official documentation about disk encryption has been updated, including details about KEK protection. Quote:
Update 2014/11/4: The official documentation about disk encryption has been updated, including details about KEK protection. Quote:
The encrypted key is stored in the crypto metadata. Hardware backing is implemented by using Trusted Execution Environment’s (TEE) signing capability. Previously, we encrypted the master key with a key generated by applying scrypt to the user's password and the stored salt. In order to make the key resilient against off-box attacks, we extend this algorithm by signing the resultant key with a stored TEE key. The resultant signature is then turned into an appropriate length key by one more application of scrypt. This key is then used to encrypt and decrypt the master key. To store this key:
Here's a diagram that visualizes this process:
- Generate random 16-byte disk encryption key (DEK) and 16-byte salt.
- Apply scrypt to the user password and the salt to produce 32-byte intermediate key 1 (IK1).
- Pad IK1 with zero bytes to the size of the hardware-bound private key (HBK). Specifically, we pad as: 00 || IK1 || 00..00; one zero byte, 32 IK1 bytes, 223 zero bytes.
- Sign padded IK1 with HBK to produce 256-byte IK2.
- Apply scrypt to IK2 and salt (same salt as step 2) to produce 32-byte IK3.
- Use the first 16 bytes of IK3 as KEK and the last 16 bytes as IV.
- Encrypt DEK with AES_CBC, with key KEK, and initialization vector IV.
Summary
Android has included full disk encryption (FDE) support since version 3.0, but versions prior to 4.4 used a fairly easy to bruteforce key derivation function (PBKDF2 with 2000 iterations). Additionally, because the disk encryption password is the same as the lockscreen one, most users tend to use simple PINs or passwords (unless a device administrator enforces password complexity rules), which further facilitates bruteforcing. Android 4.4 replaced the disk encryption KDF with scrypt, which is much harder to crack and cannot be implemented efficiently on off-the-shelf GPU hardware. In addition to enabling FDE out of the box, Android L is expected to include hardware protection for disk encryption keys, as well as hardware acceleration for encrypted disk access. These two features should make FDE on Android both more secure and much faster.
[Note that the discussion in this post is based on "stock Android" as released by Google (references source code is from AOSP). Some device vendors implement slightly different encryption schemes, and hardware-backed key storage and/or hardware acceleration are already available via vendor extensions on some high-end devices.]
[Note that the discussion in this post is based on "stock Android" as released by Google (references source code is from AOSP). Some device vendors implement slightly different encryption schemes, and hardware-backed key storage and/or hardware acceleration are already available via vendor extensions on some high-end devices.]
Comments
As usual your articles are very interesting.
You took an example with a platform that uses Trustzone and HW-based crypto module.
What will happen is Release L runs on top of a platform that does not support these features? Will it run the same FDE that can be found in Android 4.4?
Regards,
Fabrice.
I read your blog post but to be honest, most of it I don't understand.
However, on Linux I use LUKS/dm-crypt which allows me to use a password for the disk encryption and a seperate one for my user account. So, I chose a long password for the disk encryption and a less long one for my user account.
As you pointed out, up to 4.4 android used the same password for encryption as for screen unlock. So I really welcomed the change in 4.4.
However now in Android L this seems to have changed again. The screen unlock password seems to be part of the disk encryption password again - sorry, maybe I just don't really understand what it does.
So, I wonder, how secure is L encryption then? For me having two seperate passwords, one for encryption which is really long, seems to be way more secure. HOwever you said something about the screen unlock password being padded to 16 characters. Does that mean that also a "short" password provides good security?
https://f-droid.org/repository/browse/?fdfilter=encpasschanger&fdid=com.kibab.android.EncPassChanger
I would welcome it if you could post some instruction how to access the data on the data partition you dumped off your Android device (up to 4.4), that is using i.e. cryptsetup and scrypt. If you could enhance your python script for this task this would be even cooler!
http://nelenkov.blogspot.jp/2012/08/changing-androids-disk-encryption.html
Once you decrypt the partition, you can simply mount as ext4, etc.
However in L it seems that you can't seperate those two anymore.
vdc cryptfs changepw NEW_PASSWORD
However that isn't working in L anymore. Do you have any idea how I can have different passwords for the encryption and screen unlock in L?
From what I can tell, the encrypted key is still persisted to the crypto footer partition, and is stored fully decrypted in the RAM space of vold once booted. I was hopeful the TEE backing meant the decrypted key would be stored there instead of RAM. Does that seem correct to you?
I'm also curious if you saw any direct references to vold now requiring (or at least leveraging when available) hardware crypto functions to speed up dm-crypt?
# vdc cryptfs changepw password
There you say that one might need to run supolicy command because of selinux:
# supolicy --live 'allow vdc devpts chr_file {read write getattr ioctl}'
I run it but I still get command not found.... for supolicy and for vdc.
http://images.sjau.ch/img/2e7756e5.png
There you say that one might need to run supolicy command because of selinux:
# supolicy --live 'allow vdc devpts chr_file {read write getattr ioctl}'
I run it but I still get command not found.... for supolicy and for vdc.
http://images.sjau.ch/img/2e7756e5.png
Is there any rate limiting involved in the part of the process that involves the 'hardware-bound' key? Surely there would have to be for this to be of any use?
After the 2 x 30 second wait and the count down from 10 to reset to factory starts, is there a way to re-set the failed attempts?
I can get into recovery mode and from ADB can start a shell, from there I can mount /system BUT NOT /data as it's encrypted.
Unfortunately unlike your example above where you see
"encryptable=/dev/block/platform/omap/omap_hsmmc.0/by-name/metadata"
I only have "encryptable=footer", if I understand correctly it should be the last 16Kb of the undecrypted userdata-partition (but I cannot mount /data).
How can I view or chance the crytpfooter to reset failed attempts to 0. I am on the last attempt, my thinking is if I can reset it back to 10 or 9 attempts (0 or 1 failed) I will be able to try a few regular p/w's and get back into the phone without loosing anything. I am trying this on a Samsung S5.
Once you have a backup image, you can play with the footer. Alternatively, just use a recovery that supports your device. I don't *think* the recovery will auto-wipe, but you have to check the source to be sure.
end to end encryption