Android 7.0 and higher supports
file-based encryption
(FBE). FBE
allows different files to be encrypted with different keys that can be unlocked
independently. These keys are used to encrypt both file contents and file names.
When FBE is used, other information, such as directory layouts, file sizes,
permissions, and creation/modification times, is not encrypted. Collectively,
this other information is known as filesystem metadata.
Android 9 introduced support for metadata encryption.
With metadata encryption, a single key present at boot time encrypts whatever
content is not encrypted by FBE. This key is protected by Keymaster, which in
turn is protected by verified boot.
Metadata encryption is always enabled on
adoptable storage
whenever FBE is enabled.
Metadata encryption can also be enabled on internal storage. Devices launched
with Android 11 or higher must have metadata encryption
on internal storage enabled.
Implementation on internal storage
You can set up metadata encryption on the internal storage of new devices by
setting up the
metadata
filesystem, changing the init sequence, and
enabling metadata encryption in the device's fstab file.
Prerequisites
Metadata encryption can only be set up when the data partition is first
formatted. As a result, this feature is only for new devices; this is not
something an OTA should change.
Metadata encryption requires that the
dm-default-key
module be
enabled in your kernel. In Android 11 and higher,
dm-default-key
is supported by the Android common kernels, version
4.14 and higher. This version of
dm-default-key
uses a hardware and
vendor-independent encryption framework called
blk-crypto
.
To enable
dm-default-key
, use:
CONFIG_BLK_INLINE_ENCRYPTION=y
CONFIG_FS_ENCRYPTION_INLINE_CRYPT=y
CONFIG_DM_DEFAULT_KEY=y
dm-default-key
uses inline encryption hardware (hardware that
encrypts/decrypts data while it is on the way to/from the storage device) when
available. If you will
not
be using inline encryption hardware, it is
also necessary to enable a fallback to the kernel's cryptography API:
CONFIG_BLK_INLINE_ENCRYPTION_FALLBACK=y
When not using inline encryption hardware you should also enable any available
CPU-based acceleration as recommended in the
FBE documentation
.
In Android 10 and lower,
dm-default-key
was not supported by the Android common kernel. It was therefore up to vendors
to implement
dm-default-key
.
Because nothing in the userdata partition can be read until the metadata
encryption key is present, the partition table must set aside a separate
partition called the "metadata partition" for storing the keymaster blobs that
protect this key. The metadata partition should be 16MB.
fstab.hardware
must include an entry for the metadata filesystem
that lives on that partition mounting it at
/metadata
, including
the
formattable
flag to ensure it is formatted at boot time. The
f2fs filesystem does not work on smaller partitions; we recommend using ext4
instead. For example:
/dev/block/bootdevice/by-name/metadata /metadata ext4 noatime,nosuid,nodev,discard wait,check,formattable
To ensure the
/metadata
mount point exists, add the following line
to
BoardConfig-common.mk
:
BOARD_USES_METADATA_PARTITION := true
Changes to the init sequence
When metadata encryption is used,
vold
must be running before
/data
is mounted. To ensure that it is started early enough, add
the following stanza to
init.hardware.rc
:
# We need vold early for metadata encryption
on early-fs
start vold
Keymaster must be running and ready before init attempts to mount
/data
.
init.hardware.rc
should already contain a
mount_all
instruction which mounts
/data
itself in the
on
late-fs
stanza. Before this line, add the directive to exec the
wait_for_keymaster
service:
on late-fs
…
# Wait for keymaster
exec_start wait_for_keymaster
# Mount RW partitions which need run fsck
mount_all /vendor/etc/fstab.${ro.boot.hardware.platform} --late
Finally add
keydirectory=/metadata/vold/metadata_encryption
to the
fs_mgr_flags
column of the
fstab
entry for
userdata
. For example, a full fstab line might look like:
/dev/block/bootdevice/by-name/userdata /data f2fs noatime,nosuid,nodev,discard,inlinecrypt latemount,wait,check,fileencryption=aes-256-xts:aes-256-cts:inlinecrypt_optimized
,keydirectory=/metadata/vold/metadata_encryption
,quota,formattable
By default, the metadata encryption algorithm on internal storage is
AES-256-XTS. This can be overridden by setting the
metadata_encryption
option, also in the
fs_mgr_flags
column:
- On devices that lack AES acceleration,
Adiantum encryption
may be
enabled by setting
metadata_encryption=adiantum
.
- On devices that support
hardware-wrapped keys
,
the metadata encryption key can be made hardware-wrapped by setting
metadata_encryption=aes-256-xts:wrappedkey_v0
(or
equivalently
metadata_encryption=:wrappedkey_v0
, as
aes-256-xts
is the default algorithm).
Because the kernel interface to
dm-default-key
changed in Android
11, you also need to ensure that you have set the
correct value for
PRODUCT_SHIPPING_API_LEVEL
in
device.mk
. For example, if your device launches with Android
11 (API level 30),
device.mk
should
contain:
PRODUCT_SHIPPING_API_LEVEL := 30
You can also set the following system property to force the use of the new
dm-default-key
API regardless of shipping API level:
PRODUCT_PROPERTY_OVERRIDES += \
ro.crypto.dm_default_key.options_format.version=2
Validation
To verify that metadata encryption is enabled and is working correctly, run the
tests described below. Also be mindful of the
common
issues
described below.
Tests
Start by running the following command to verify that metadata encryption is
enabled on internal storage:
adb root
adb shell dmctl table userdata
The output should be similar to:
Targets in the device-mapper table for userdata:
0-4194304: default-key, aes-xts-plain64 - 0 252:2 0 3 allow_discards sector_size:4096 iv_large_sectors
If you overrode the default encryption settings by setting the
metadata_encryption
option in the device's
fstab
, then
the output will differ slightly from the above. For example, if you enabled
Adiantum encryption
, then the third
field will be
xchacha12,aes-adiantum-plain64
instead of
aes-xts-plain64
.
Next, run
vts_kernel_encryption_test
to verify the correctness of metadata encryption and FBE:
atest vts_kernel_encryption_test
or:
vts-tradefed run vts -m vts_kernel_encryption_test
Common issues
During the call to
mount_all
, which mounts the metadata-encrypted
/data
partition,
init
executes the vdc tool. The vdc
tool connects to
vold
over
binder
to set up the
metadata-encrypted device and mount the partition. For the duration of this
call,
init
is blocked, and attempts to either read or set
init
properties will block until
mount_all
finishes.
If, at this stage, any part of
vold
's work is directly or
indirectly blocked on reading or setting a property, deadlock will result. It is
important to ensure that
vold
can complete the work of reading the
keys, interacting with Keymaster, and mounting the data directory without
interacting further with
init
.
If Keymaster is not fully started when
mount_all
runs, it will not
respond to
vold
until it has read certain properties from
init
, resulting in exactly the deadlock described. Placing
exec_start wait_for_keymaster
above the relevant
mount_all
invocation as set out ensures that Keymaster is fully
running in advance and so avoids this deadlock.
Configuration on adoptable storage
Since Android 9, a form of metadata encryption is
always enabled on
adoptable storage
whenever FBE is enabled, even when metadata encryption is not enabled on
internal storage.
In AOSP, there are two implementations of metadata encryption on adoptable
storage: a deprecated one based on
dm-crypt
, and a newer one based
on
dm-default-key
. To ensure that the correct implementation is
selected for your device, ensure that you have set the correct value for
PRODUCT_SHIPPING_API_LEVEL
in
device.mk
. For example,
if your device launches with Android 11 (API level 30),
device.mk
should contain:
PRODUCT_SHIPPING_API_LEVEL := 30
You can also set the following system properties to force the use of the new
volume metadata encryption method (and the new default FBE policy version)
regardless of shipping API level:
PRODUCT_PROPERTY_OVERRIDES += \
ro.crypto.volume.metadata.method=dm-default-key \
ro.crypto.dm_default_key.options_format.version=2 \
ro.crypto.volume.options=::v2
Current method
On devices launching with Android 11 or higher,
metadata encryption on adoptable storage uses the
dm-default-key
kernel module, just like on internal storage. See the
prerequisites
above for which kernel configuration
options to enable. Note that inline encryption hardware that works on the
device's internal storage may be unavailable on adoptable storage, and thus
CONFIG_BLK_INLINE_ENCRYPTION_FALLBACK=y
may be required.
By default, the
dm-default-key
volume metadata encryption method
uses the AES-256-XTS encryption algorithm with 4096-byte crypto sectors. The
algorithm can be overridden by setting the
ro.crypto.volume.metadata.encryption
system property. This
property's value has the same syntax as the
metadata_encryption
fstab option described above. For example, on devices that lack AES
acceleration,
Adiantum encryption
may be enabled by setting
ro.crypto.volume.metadata.encryption=adiantum
.
Legacy method
On devices launching with Android 10 or lower, metadata
encryption on adoptable storage uses the
dm-crypt
kernel module
rather than
dm-default-key
:
CONFIG_DM_CRYPT=y
Unlike the
dm-default-key
method, the
dm-crypt
method
causes file contents to be encrypted twice: once with a FBE key and once with
the metadata encryption key. This double encryption reduces performance and is
not required to achieve the security goals of metadata encryption, since Android
ensures that FBE keys are at least as hard to compromise as the metadata
encryption key. Vendors can make kernel customizations to avoid the double
encryption, in particular by implementing the
allow_encrypt_override
option which Android will pass to
dm-crypt
when the system property
ro.crypto.allow_encrypt_override
is set to
true
.
These customizations are not supported by the Android common kernel.
By default, the
dm-crypt
volume metadata encryption method uses the
AES-128-CBC encryption algorithm with ESSIV and 512-byte crypto sectors. This
can be overridden by setting the following system properties (which are also
used for FDE):
ro.crypto.fde_algorithm
selects the metadata encryption
algorithm. The choices are
aes-128-cbc
and
adiantum
.
Adiantum
may be used only if the
device lacks AES acceleration.
ro.crypto.fde_sector_size
selects the crypto sector size.
The choices are 512, 1024, 2048, and 4096. For Adiantum encryption, use
4096.