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.
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
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
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.
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 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:
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
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:
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:
If your device uses eMMC-based storage, also enable:
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
FBE is enabled by adding the option
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:
contents_encryption_modeparameter defines which cryptographic algorithm is used to encrypt file contents. It can be either
adiantum. Since Android 11 it can also be left empty to specify the default algorithm, which is
filenames_encryption_modeparameter defines which cryptographic algorithm is used to encrypt file names. It can be either
aes-256-hctr2. If not specified, it defaults to
aes-256-xts, or to
flagsparameter, new in Android 11, is a list of flags separated by the
+character. The following flags are supported:
v1flag selects version 1 encryption policies; the
v2flag 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.
inlinecrypt_optimizedflag 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.
emmc_optimizedflag 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_optimizedinstead. 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
wrappedkey_v0flag enables the use of hardware-wrapped keys for FBE. This can only be used in combination with the
inlinecryptmount option, and either the
If you aren't using inline encryption hardware the recommended setting for most
fileencryption=aes-256-xts. If you are using inline
encryption hardware the recommended setting for most devices is
devices without any form of AES acceleration, Adiantum may be used instead of AES by
Since Android 14 (AOSP experimental), 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
aes-256-hctr2. In the simplest case
this would be done with
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
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
Since Android 9, FBE and adoptable storage can be used together.
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
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
fileencryptionfstab option, and it uses the same defaults. See the recommendations for
fileencryptionabove for what to use here.
ro.crypto.volume.metadata.encryptionselects 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_modeselects the contents encryption mode. This is equivalent to the first colon-separated field of
ro.crypto.volume.filenames_modeselects 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
ro.crypto.fde_sector_sizeselect 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
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.
init applies the system DE key to
all top-level directories of
/data, except for directories that
must be unencrypted: 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
command in init scripts. The possible values of
documented in the
README for the Android init language.
In Android 10, the
init encryption actions
were hardcoded into the following location:
In Android 9 and earlier, the location was:
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">
directBootAware attribute at the application level is shorthand for marking
all components in the app as being encryption aware.
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.
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:
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
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.
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
- Create a top-level directory (for example
misc_ne) in the
- 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.
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:
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
- Check that
ro.crypto.typeis set to
Additionally, testers can boot a
userdebug instance with a lockscreen set on the
primary user. Then
adb shell into the device and use
su to become root. Make sure
encrypted filenames; if it does not, 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.
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.
The following table lists the FBE keys and the directories they protect in more detail:
|System DE||Device-encrypted data not tied to a particular user||
|Per-boot||Ephemeral system files that don't need to survive a reboot||
|User CE (internal)||Per-user credential-encrypted data on internal storage||
|User DE (internal)||Per-user device-encrypted data on internal storage||
|User CE (adoptable)||Per-user credential-encrypted data on adoptable storage||
|User DE (adoptable)||Per-user device-encrypted data on adoptable storage||
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||
|User CE (internal) keys||
|User DE (internal) keys||
|User CE (adoptable) keys||
||User CE (internal)|
|User DE (adoptable) keys||
||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
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.
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
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
uses the stretched LSKF as a Gatekeeper
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.