Android 7.0 and higher supports file-based encryption (FBE).
File-based encryption allows different files to be encrypted
with different keys that can be unlocked independently.
This article describes how to enable file-based encryption on new devices
and how system applications can use the Direct Boot APIs to offer users
the best, most secure experience possible.
All devices launching with Android 10 and higher are
required to use file-based encryption.
Direct Boot
File-based encryption enables a new feature introduced in Android 7.0 called
Direct
Boot
. Direct Boot allows encrypted devices to boot straight to the lock
screen. Previously, on encrypted devices using
full-disk
encryption
(FDE), users needed to provide credentials before any data could
be accessed, preventing the phone from performing all but the most basic of
operations. For example, alarms could not operate, accessibility services were
unavailable, and phones could not receive calls but were limited to only basic
emergency dialer operations.
With the introduction of file-based encryption (FBE) and new APIs to make
applications aware of encryption, it is possible for these apps to operate
within a limited context. This can happen before users have provided their
credentials while still protecting private user information.
On an FBE-enabled device, each user of the device has two storage locations
available to applications:
- Credential Encrypted (CE) storage, which is the default storage location
and only available after the user has unlocked the device.
- Device Encrypted (DE) storage, which is a storage location available both
during Direct Boot mode and after the user has unlocked the device.
This separation makes work profiles more secure because it allows more than one
user to be protected at a time as the encryption is no longer based solely on a
boot time password.
The Direct Boot API allows encryption-aware applications to access each of these
areas. There are changes to the application lifecycle to accommodate the need to
notify applications when a user’s CE storage is
unlocked
in response to
first entering credentials at the lock screen, or in the case of work profile
providing a
work
challenge
. Devices running Android 7.0 must support these new APIs and
lifecycles regardless of whether or not they implement FBE. Although, without
FBE, DE and CE storage will always be in the unlocked state.
A complete implementation of file-based encryption on the Ext4 and F2FS file
systems is provided in the Android Open Source Project (AOSP) and needs only be
enabled on devices that meet the requirements. Manufacturers electing to use FBE
may wish to explore ways of optimizing the feature based on the system on chip
(SoC) used.
All the necessary packages in AOSP have been updated to be direct-boot aware.
However, where device manufacturers use customized versions of these apps, they
will want to ensure at a minimum there are direct-boot aware packages providing
the following services:
- Telephony Services and Dialer
- Input method for entering passwords into the lock screen
Examples and source
Android provides a reference implementation of file-based encryption, in which
vold (
system/vold
)
provides the functionality for managing storage devices and
volumes on Android. The addition of FBE provides vold with several new commands
to support key management for the CE and DE keys of multiple users. In addition
to the core changes to use the
file-based
encryption capabilities in the kernel
, many system packages including the
lockscreen and the SystemUI have been modified to support the FBE and Direct
Boot features. These include:
- AOSP Dialer (packages/apps/Dialer)
- Desk Clock (packages/apps/DeskClock)
- LatinIME (packages/inputmethods/LatinIME)*
- Settings App (packages/apps/Settings)*
- SystemUI (frameworks/base/packages/SystemUI)*
* System applications that use the
defaultToDeviceProtectedStorage
manifest attribute
More examples of applications and services that are encryption aware can be
found by running the command
mangrep directBootAware
in the
frameworks or packages directory of the AOSP
source tree.
Dependencies
To use the AOSP implementation of FBE securely, a device needs to meet the
following dependencies:
- Kernel Support
for Ext4 encryption or F2FS encryption.
- Keymaster
Support
with HAL version 1.0 or higher. There is no support for
Keymaster 0.3 as that does not provide the necessary capabilities or assure
sufficient protection for encryption keys.
- Keymaster/
Keystore
and
Gatekeeper
must be implemented in a
Trusted Execution
Environment
(TEE) to provide protection for the DE keys so that an
unauthorized OS (custom OS flashed onto the device) cannot simply request the
DE keys.
- Hardware Root of Trust
and
Verified Boot
bound to the Keymaster initialization is required to ensure that DE keys are not
accessible by an unauthorized operating system.
Implementation
First and foremost, apps such as alarm clocks, phone, and accessibility features
should be made android:directBootAware according to the
Direct
Boot
developer documentation.
Kernel support
Kernel support for Ext4 and F2FS encryption is available in the Android common
kernels, version 3.18 and higher. To enable it in a kernel that is version 5.1
or higher, use:
CONFIG_FS_ENCRYPTION=y
For older kernels, use
CONFIG_EXT4_ENCRYPTION=y
if your device's
userdata
filesystem is Ext4, or use
CONFIG_F2FS_FS_ENCRYPTION=y
if your device's
userdata
filesystem is F2FS.
If your device will support
adoptable
storage
or will use
metadata
encryption
on internal storage, also enable the kernel configuration options
needed for metadata encryption as described in the
metadata encryption documentation
.
In addition to functional support for Ext4 or F2FS encryption, device
manufacturers should also enable cryptographic acceleration to speed up
file-based encryption and improve the user experience. For example, on
ARM64-based devices, ARMv8 CE (Cryptography Extensions) acceleration can be
enabled by setting the following kernel configuration options:
CONFIG_CRYPTO_AES_ARM64_CE_BLK=y
CONFIG_CRYPTO_SHA2_ARM64_CE=y
To further improve performance and reduce power usage, device manufacturers may
also consider implementing
inline encryption hardware
, which
encrypts/decrypts the data while it is on the way to/from the storage device.
The Android common kernels (version 4.14 and higher) contain a framework that
allows inline encryption to be used when hardware and vendor driver support is
available. The inline encryption framework can be enabled by setting the
following kernel configuration options:
CONFIG_BLK_INLINE_ENCRYPTION=y
CONFIG_FS_ENCRYPTION=y
CONFIG_FS_ENCRYPTION_INLINE_CRYPT=y
If your device uses UFS-based storage, also enable:
CONFIG_SCSI_UFS_CRYPTO=y
If your device uses eMMC-based storage, also enable:
CONFIG_MMC_CRYPTO=y
Enabling file-based encryption
Enabling FBE on a device requires enabling it on the internal storage
(
userdata
). This also automatically enables FBE on adoptable
storage; however, the encryption format on adoptable storage may be overridden
if necessary.
Internal storage
FBE is enabled by adding the option
fileencryption=contents_encryption_mode[:filenames_encryption_mode[:flags]]
to the
fs_mgr_flags
column of the
fstab
line for
userdata
. This option defines the encryption format on internal
storage. It contains up to three colon-separated parameters:
- The
contents_encryption_mode
parameter defines which
cryptographic algorithm is used to encrypt file contents. It can be either
aes-256-xts
or
adiantum
. Since Android
11 it can also be left empty to specify the
default algorithm, which is
aes-256-xts
.
- The
filenames_encryption_mode
parameter defines which
cryptographic algorithm is used to encrypt file names. It can be either
aes-256-cts
,
aes-256-heh
,
adiantum
, or
aes-256-hctr2
. If not specified, it defaults to
aes-256-cts
if
contents_encryption_mode
is
aes-256-xts
, or to
adiantum
if
contents_encryption_mode
is
adiantum
.
- The
flags
parameter, new in Android
11, is a list of flags separated by the
+
character. The following flags are supported:
- The
v1
flag selects version 1 encryption policies; the
v2
flag selects version 2 encryption policies. Version
2 encryption policies use a more secure and flexible
key derivation function
. The default is v2 if
the device launched on Android 11 or higher
(as determined by
ro.product.first_api_level
), or v1 if
the device launched on Android 10 or
lower.
- The
inlinecrypt_optimized
flag selects an encryption
format that is optimized for inline encryption hardware that doesn't
handle large numbers of keys efficiently. It does this by deriving
just one file contents encryption key per CE or DE key, rather than
one per file. The generation of IVs (initialization vectors) is
adjusted accordingly.
- The
emmc_optimized
flag is similar to
inlinecrypt_optimized
, but it also selects an IV
generation method that limits IVs to 32 bits. This flag should only
be used on inline encryption hardware that is compliant with the
JEDEC eMMC v5.2 specification and therefore supports only 32-bit
IVs. On other inline encryption hardware, use
inlinecrypt_optimized
instead. This flag should never
be used on UFS-based storage; the UFS specification allows the use
of 64-bit IVs.
- On devices that support
hardware-wrapped
keys
, the
wrappedkey_v0
flag enables the use of
hardware-wrapped keys for FBE. This can only be used in combination
with the
inlinecrypt
mount option, and either the
inlinecrypt_optimized
or
emmc_optimized
flag.
- The
dusize_4k
flag forces the encryption data unit size
to be 4096 bytes even when the filesystem block size is not 4096
bytes. The encryption data unit size is the granularity of file
contents encryption. This flag is available since Android
15 (AOSP experimental). This flag should only be used to enable
the use of inline encryption hardware that does not support data
units larger than 4096 bytes, on a device that uses a page size
larger than 4096 bytes and that uses the f2fs filesystem.
If you aren't using inline encryption hardware the recommended setting for most
devices is
fileencryption=aes-256-xts
. If you are using inline
encryption hardware the recommended setting for most devices is
fileencryption=aes-256-xts:aes-256-cts:inlinecrypt_optimized
(or equivalently
fileencryption=::inlinecrypt_optimized
). On
devices without any form of AES acceleration,
Adiantum
may be used instead of AES by
setting
fileencryption=adiantum
.
Since Android 14, AES-HCTR2 is the preferred mode of filenames encryption
for devices with accelerated cryptography instructions. However, only newer Android kernels support
AES-HCTR2. In a future Android release, it is planned to become the default mode for filenames
encryption. If your kernel has AES-HCTR2 support, it can be enabled for filenames encryption by
setting
filenames_encryption_mode
to
aes-256-hctr2
. In the simplest case
this would be done with
fileencryption=aes-256-xts:aes-256-hctr2
.
On devices that launched with Android 10 or lower,
fileencryption=ice
is also accepted to specify the use of the
FSCRYPT_MODE_PRIVATE
file contents encryption mode. This mode is
unimplemented by the Android common kernels, but it could be implemented by
vendors using custom kernel patches. The on-disk format produced by this mode
was vendor-specific. On devices launching with Android
11 or higher, this mode is no longer allowed and a
standard encryption format must be used instead.
By default, file contents encryption is done using the Linux kernel's
cryptography API. If you want to use inline encryption hardware instead, also
add the
inlinecrypt
mount option. For example, a full
fstab
line might look like:
/dev/block/by-name/userdata /data f2fs nodev,noatime,nosuid,errors=panic
,inlinecrypt
wait
,fileencryption=aes-256-xts:aes-256-cts:inlinecrypt_optimized
Adoptable storage
Since Android 9, FBE and
adoptable storage
can be used together.
Specifying the
fileencryption
fstab option for
userdata
also automatically enables both FBE and
metadata encryption
on adoptable
storage. However, you may override the FBE and/or metadata encryption formats on
adoptable storage by setting properties in
PRODUCT_PROPERTY_OVERRIDES
.
On devices that launched with Android 11 or higher, use
the following properties:
ro.crypto.volume.options
(new in Android
11) selects the FBE encryption format on
adoptable storage. It has the same syntax as the argument to the
fileencryption
fstab option, and it uses the same defaults.
See the recommendations for
fileencryption
above for what to
use here.
ro.crypto.volume.metadata.encryption
selects the metadata
encryption format on adoptable storage. See the
metadata
encryption documentation
.
On devices that launched with Android 10 or lower, use
the following properties:
ro.crypto.volume.contents_mode
selects the contents
encryption mode. This is equivalent to the first colon-separated field of
ro.crypto.volume.options
.
ro.crypto.volume.filenames_mode
selects the filenames
encryption mode. This is equivalent to the second colon-separated field of
ro.crypto.volume.options
, except that the default on devices
that launched with Android 10 or lower is
aes-256-heh
. On most devices, this needs to be explicitly
overridden to
aes-256-cts
.
ro.crypto.fde_algorithm
and
ro.crypto.fde_sector_size
select the metadata encryption
format on adoptable storage. See the
metadata
encryption documentation
.
Integrating with Keymaster
The Keymaster HAL should be started as part of the
early_hal
class.
This is because FBE requires that Keymaster be ready to handle requests by the
post-fs-data
boot phase, which is when
vold
sets up
the initial keys.
Excluding directories
init
applies the
system DE key
to
all top-level directories of
/data
, except for directories that
must be unencrypted such as the directory that contains the system DE key
itself and directories that contain user CE or DE directories. Encryption keys
apply recursively and cannot be overridden by subdirectories.
In Android 11 and higher, the key that
init
applies to directories can be controlled by the
encryption=<action>
argument to the
mkdir
command in init scripts. The possible values of
<action>
are
documented in the
README for the Android init language
.
In Android 10, the
init
encryption actions
were hardcoded into the following location:
/system/extras/libfscrypt/fscrypt_init_extensions.cpp
In Android 9 and earlier, the location was:
/system/extras/ext4_utils/ext4_crypt_init_extensions.cpp
It is possible to add exceptions to prevent certain directories from being
encrypted at all. If modifications of this sort are made then the device
manufacturer should include
SELinux policies
that only grant access to the
applications that need to use the unencrypted directory. This should exclude all
untrusted applications.
The only known acceptable use case for this is in support of legacy OTA
capabilities.
Supporting Direct Boot in system applications
Making applications Direct Boot aware
To facilitate rapid migration of system apps, there are two new attributes that
can be set at the application level. The
defaultToDeviceProtectedStorage
attribute is available only to
system apps. The
directBootAware
attribute is available to all.
<application
android:directBootAware="true"
android:defaultToDeviceProtectedStorage="true">
The
directBootAware
attribute at the application level is shorthand for marking
all components in the app as being encryption aware.
The
defaultToDeviceProtectedStorage
attribute redirects the default
app storage location to point at DE storage instead of pointing at CE storage.
System apps using this flag must carefully audit all data stored in the default
location, and change the paths of sensitive data to use CE storage. Device
manufactures using this option should carefully inspect the data that they are
storing to ensure that it contains no personal information.
When running in this mode, the following System APIs are
available to explicitly manage a Context backed by CE storage when needed, which
are equivalent to their Device Protected counterparts.
Context.createCredentialProtectedStorageContext()
Context.isCredentialProtectedStorage()
Supporting multiple users
Each user in a multi-user environment gets a separate encryption key. Every user
gets two keys: a DE and a CE key. User 0 must log into the device first as it is
a special user. This is pertinent for
Device
Administration
uses.
Crypto-aware applications interact across users in this manner:
INTERACT_ACROSS_USERS
and
INTERACT_ACROSS_USERS_FULL
allow an application to act across all the users on the device. However, those
apps will be able to access only CE-encrypted directories for users that are
already unlocked.
An application may be able to interact freely across the DE areas, but one user
unlocked does not mean that all the users on the device are unlocked. The
application should check this status before trying to access these areas.
Each work profile user ID also gets two keys: DE and CE. When the work challenge
is met, the profile user is unlocked and the Keymaster (in TEE) can provide the
profile’s TEE key.
Handling updates
The recovery partition is unable to access the DE-protected storage on the
userdata partition. Devices implementing FBE are strongly recommended to support
OTA using
A/B system updates
. As
the OTA can be applied during normal operation there is no need for recovery to
access data on the encrypted drive.
When using a legacy OTA solution, which requires recovery to access the OTA file
on the
userdata
partition:
- Create a top-level directory (for example
misc_ne
) in the
userdata
partition.
- Configure this top-level directory to be unencrypted (see
Excluding directories
).
- Create a directory within the top-level directory to hold OTA packages.
- Add an SELinux rule and file contexts to control access to this directory and
it contents. Only the process or applications receiving OTA updates should be
able to read and write to this directory. No other application or process
should have access to this directory.
Validation
To ensure the implemented version of the feature works as intended, first run
the many CTS encryption tests, such as
DirectBootHostTest
and
EncryptionTest
.
If the device is running Android 11 or higher, also run
vts_kernel_encryption_test
:
atest vts_kernel_encryption_test
or:
vts-tradefed run vts -m vts_kernel_encryption_test
In addition, device manufacturers may perform the following manual tests. On a
device with FBE enabled:
- Check that
ro.crypto.state
exists
- Ensure
ro.crypto.state
is encrypted
- Check that
ro.crypto.type
exists
- Ensure
ro.crypto.type
is set to
file
Additionally, testers can verify that CE storage is locked before the device has
been unlocked for the first time since boot. To do this, use a
userdebug
or
eng
build, set a PIN, pattern, or
password on the main user, and reboot the device. Before unlocking the device,
run the following command to check the CE storage of the main user. If the
device uses
Headless System
User Mode
(most Automotive devices), the main user is user 10, so run:
adb root; adb shell ls /data/user/10
On other devices (most non-Automotive devices), the main user is user 0, so
run:
adb root; adb shell ls /data/user/0
Verify that the listed filenames are Base64-encoded, indicating that the
filenames are encrypted and the key to decrypt them is not yet available.
If the filenames are listed in plaintext, something is wrong.
Device manufacturers are also encouraged to explore running the
upstream Linux tests for fscrypt
on their devices or
kernels. These tests are part of the xfstests filesystem test suite. However,
these upstream tests are not offically supported by Android.
AOSP implementation details
This section provides details on the AOSP implementation and describes how
file-based encryption works. It should not be necessary for device manufacturers
to make any changes here to use FBE and Direct Boot on their devices.
fscrypt encryption
The AOSP implementation uses "fscrypt" encryption (supported by ext4 and f2fs)
in the kernel and normally is configured to:
- Encrypt file contents with AES-256 in XTS mode
- Encrypt file names with AES-256 in CBC-CTS mode
Adiantum encryption
is also
supported. When Adiantum encryption is enabled, both file contents and file names
are encrypted with Adiantum.
fscrypt supports two versions of encryption policies: version 1 and version 2.
Version 1 is deprecated, and the CDD requirements for devices launching with
Android 11 and higher are only compatible with version
2. Version 2 encryption policies use
HKDF-SHA512
to derive the actual encryption keys from the userspace-supplied keys.
For more information about fscrypt, see the
upstream kernel documentation
.
Storage classes
The following table lists the FBE keys and the directories they protect in more
detail:
Storage class
|
Description
|
Directories
|
Unencrypted
|
Directories in
/data
that can't be or don't need to be
protected by FBE. On devices that use
metadata
encryption
, these directories aren't truly unencrypted but rather
are protected by the metadata encryption key which is equivalent to
System DE.
|
/data/apex
, excluding
/data/apex/decompressed
and
/data/apex/ota_reserved
which are system DE
/data/lost+found
/data/preloads
/data/unencrypted
- All directories whose subdirectories use different FBE keys. For
example, since each
/data/user/${user_id}
directory
uses a per-user key,
/data/user
uses no key
itself.
|
System DE
|
Device-encrypted data not tied to a particular user
|
/data/apex/decompressed
/data/apex/ota_reserved
/data/app
/data/misc
/data/system
/data/vendor
- All other subdirectories of
/data
that this table
doesn't mention as having a different class
|
Per-boot
|
Ephemeral system files that don't need to survive a reboot
|
/data/per_boot
|
User CE (internal)
|
Per-user credential-encrypted data on internal storage
|
/data/data
(alias of
/data/user/0
)
/data/media/${user_id}
/data/misc_ce/${user_id}
/data/system_ce/${user_id}
/data/user/${user_id}
/data/vendor_ce/${user_id}
|
User DE (internal)
|
Per-user device-encrypted data on internal storage
|
/data/misc_de/${user_id}
/data/system_de/${user_id}
/data/user_de/${user_id}
/data/vendor_de/${user_id}
|
User CE (adoptable)
|
Per-user credential-encrypted data on adoptable storage
|
/mnt/expand/${volume_uuid}/media/${user_id}
/mnt/expand/${volume_uuid}/misc_ce/${user_id}
/mnt/expand/${volume_uuid}/user/${user_id}
|
User DE (adoptable)
|
Per-user device-encrypted data on adoptable storage
|
/mnt/expand/${volume_uuid}/misc_de/${user_id}
/mnt/expand/${volume_uuid}/user_de/${user_id}
|
Key storage and protection
All FBE keys are managed by
vold
and are stored encrypted on-disk,
except for the per-boot key which is not stored at all. The following table
lists the locations in which the various FBE keys are stored:
Key type
|
Key location
|
Storage class of key location
|
System DE key
|
/data/unencrypted
|
Unencrypted
|
User CE (internal) keys
|
/data/misc/vold/user_keys/ce/${user_id}
|
System DE
|
User DE (internal) keys
|
/data/misc/vold/user_keys/de/${user_id}
|
System DE
|
User CE (adoptable) keys
|
/data/misc_ce/${user_id}/vold/volume_keys/${volume_uuid}
|
User CE (internal)
|
User DE (adoptable) keys
|
/data/misc_de/${user_id}/vold/volume_keys/${volume_uuid}
|
User DE (internal)
|
As shown in the preceding table, most FBE keys are stored in directories that
are encrypted by another FBE key. Keys cannot be unlocked until the storage
class that contains them has been unlocked.
vold
also applies a layer of encryption to all FBE keys. Every key
besides CE keys for internal storage is encrypted with AES-256-GCM using its own
Keystore
key that is not
exposed outside the TEE. This ensures that FBE keys cannot be unlocked unless a
trusted operating system has booted, as enforced by
Verified Boot
.
Rollback
resistance
is also requested on the Keystore key, which allows FBE keys to
be securely deleted on devices where Keymaster supports rollback resistance. As
a best-effort fallback for when rollback resistance is unavailable, the SHA-512
hash of 16384 random bytes stored in the
secdiscardable
file stored
alongside the key is used as the
application ID
tag
of the Keystore key. All these bytes need to be recovered to recover an
FBE key.
CE keys for internal storage receive a stronger level of protection that ensures
they cannot be unlocked without knowing either the user's
Lock Screen
Knowledge Factor (LSKF)
(PIN, pattern, or password), a
secure
passcode reset token
, or both the client-side and server-side keys for a
Resume-on-Reboot
operation.
Passcode reset tokens are only allowed to be created for
work profiles
and
fully
managed devices
.
To achieve this,
vold
encrypts each CE key for internal storage
using an AES-256-GCM key derived from the user's
synthetic password
.
The synthetic password is an immutable high-entropy cryptographic secret that is
randomly generated for each user.
LockSettingsService
in
system_server
manages the synthetic password and the ways in which
it is protected.
To protect the synthetic password with the LSKF,
LockSettingsService
first stretches the LSKF by passing it through
scrypt
, targeting a time of about 25 ms and a
memory usage of about 2 MiB. Since LSKFs are usually short, this step usually
does not provide much security. The main layer of security is the
Secure
Element (SE)
or TEE-enforced ratelimiting described below.
If the device has a Secure Element (SE), then
LockSettingsService
maps the stretched LSKF to a high-entropy random secret stored in the SE using
the
Weaver HAL
.
LockSettingsService
then encrypts
the synthetic password twice: first with a software key derived from the
stretched LSKF and the Weaver secret, and second with a non-auth-bound Keystore
key. This provides SE-enforced ratelimiting of LSKF guesses.
If the device doesn't have a SE, then
LockSettingsService
instead
uses the stretched LSKF as a
Gatekeeper
password.
LockSettingsService
then encrypts the synthetic password
twice: first with a software key derived from the stretched LSKF and the hash of
a secdiscardable file, and second with a Keystore key that is auth-bound to the
Gatekeeper enrollment. This provides TEE-enforced ratelimiting of LSKF guesses.
When the LSKF is changed,
LockSettingsService
deletes all
information associated with the binding of the synthetic password to the old
LSKF. On devices that support Weaver or rollback resistant Keystore keys, this
guarantees secure deletion of the old binding. For this reason, the protections
described here are applied even when the user does not have an LSKF.