原文地址:https://source.android.com/security/encryption/full-disk.html
Full-disk encryption is the process of encoding all user data on an Android device using anencrypted key. Once a device is encrypted, all user-created data isautomatically encrypted before committing it to disk and all readsautomatically decrypt data before returning it to the calling process.
Full-disk encryption was introduced to Android in 4.4, but Android 5.0 introducedthese new features:
forceencrypt
fstab flag to encrypt on first boot. Caution: Devices upgraded to Android 5.0 and thenencrypted may be returned to an unencrypted state by factory data reset. New Android 5.0devices encrypted at first boot cannot be returned to an unencrypted state.
Android full-disk encryption is based on dm-crypt
, which is a kernelfeature that works at the block device layer. Because ofthis, encryption works with Embedded MultiMediaCard (eMMC) andsimilar flash devices that present themselves to the kernel as blockdevices. Encryption is not possible with YAFFS, which talks directly to a rawNAND flash chip.
The encryption algorithm is 128 Advanced Encryption Standard (AES) withcipher-block chaining (CBC) and ESSIV:SHA256. The master key is encrypted with128-bit AES via calls to the OpenSSL library. You must use 128 bits or more forthe key (with 256 being optional).
Note: OEMs can use 128-bit or higher to encrypt the master key.
In the Android 5.0 release, there are four kinds of encryption states:
Upon first boot, the device creates a randomly generated 128-bit master keyand then hashes it with a default password and stored salt. The default password is: "default_password"However, the resultant hash is also signed through a TEE (such as TrustZone),which uses a hash of the signature to encrypt the master key.
You can find the default password defined in the Android Open Source Project cryptfs.cfile.
When the user sets the PIN/pass or password on the device, only the 128-bit keyis re-encrypted and stored. (ie. user PIN/pass/pattern changes do NOT causere-encryption of userdata.) Note thatmanaged devicemay be subject to PIN, pattern, or password restrictions.
Encryption is managed by init
and vold
.init
calls vold
, and vold sets properties to triggerevents in init. Other parts of the systemalso look at the properties to conduct tasks such as report status, ask for apassword, or prompt to factory reset in the case of a fatal error. To invokeencryption features in vold
, the system uses the command line toolvdc
’s cryptfs
commands: checkpw
,restart
, enablecrypto
, changepw
,cryptocomplete
, verifypw
, setfield
,getfield
, mountdefaultencrypted
, getpwtype
,getpw
, and clearpw
.
In order to encrypt, decrypt or wipe /data
, /data
must not be mounted. However, in order to show any user interface (UI), theframework must start and the framework requires /data
to run. Toresolve this conundrum, a temporary filesystem is mounted on /data
.This allows Android to prompt for passwords, show progress, or suggest a datawipe as needed. It does impose the limitation that in order to switch from thetemporary filesystem to the true /data
filesystem, the system muststop every process with open files on the temporary filesystem and restart thoseprocesses on the real /data
filesystem. To do this, all servicesmust be in one of three groups: core
, main
, andlate_start
.
core
: Never shut down after starting. main
: Shut down and then restart after the disk password is entered. late_start
: Does not start until after /data
has been decrypted and mounted.To trigger these actions, the vold.decrypt
property is set tovarious strings.To kill and restart services, the init
commands are:
class_reset
: Stops a service but allows it to be restarted with class_start. class_start
: Restarts a service. class_stop
: Stops a service and adds a SVC_DISABLED
flag. Stopped services do not respond to class_start
.There are four flows for an encrypted device. A device is encrypted just onceand then follows a normal boot flow.
forceencrypt
: Mandatory encryption at first boot (starting in Android L). In addition to these flows, the device can also fail to encrypt /data
.Each of the flows are explained in detail below.
This is the normal first boot for an Android 5.0 device.
forceencrypt
flag /data
is not encrypted but needs to be because forceencrypt
mandates it.Unmount /data
.
/data
vold.decrypt = "trigger_encryption"
triggers init.rc
,which will cause vold
to encrypt /data
with no password.(None is set because this should be a new device.)
vold
mounts a tmpfs /data
(using the tmpfs options fromro.crypto.tmpfs_options
) and sets the property vold.encrypt_progress
to 0.vold
prepepares the tmpfs /data
for booting an encrypted system and sets theproperty vold.decrypt
to: trigger_restart_min_framework
Because the device has virtually no data to encrypt, the progress bar willoften not actually appear because encryption happens so quickly. SeeEncrypt an existing device for moredetails about the progress UI.
/data
is encrypted, take down the framework vold
sets vold.decrypt
totrigger_default_encryption
which starts thedefaultcrypto
service. (This starts the flow below for mounting adefault encrypted userdata.) trigger_default_encryption
checks theencryption type to see if /data
is encrypted with or without apassword. Because Android 5.0 devices are encrypted on first boot, there shouldbe no password set; therefore we decrypt and mount /data
.
/data
init
then mounts /data
on a tmpfs RAMDisk usingparameters it picks up from ro.crypto.tmpfs_options
, which is setin init.rc
.
Set vold
to trigger_restart_framework
, whichcontinues the usual boot process.
This is what happens when you encrypt an unencrypted Android K or earlierdevice that has been migrated to L.
This process is user-initiated and is referred to as “inplace encryption” inthe code. When a user selects to encrypt a device, the UI makes sure thebattery is fully charged and the AC adapter is plugged in so there is enoughpower to finish the encryption process.
Warning: If the device runs out of power and shuts down before it has finishedencrypting, file data is left in a partially encrypted state. The device mustbe factory reset and all data is lost.
To enable inplace encryption, vold
starts a loop to read eachsector of the real block device and then write itto the crypto block device. vold
checks to see if a sector is inuse before reading and writing it, which makesencryption much faster on a new device that has little to no data.
State of device: Set ro.crypto.state = "unencrypted"
and execute the on nonencrypted
init
trigger to continue booting.
The UI calls vold
with the command cryptfs enablecrypto inplace
where passwd
is the user's lock screen password.
vold
checks for errors, returns -1 if it can't encrypt, andprints a reason in the log. If it can encrypt, it sets the property vold.decrypt
to trigger_shutdown_framework
. This causes init.rc
tostop services in the classes late_start
and main
.
/data
vold
then sets up the crypto mapping, which creates a virtual crypto block devicethat maps onto the real block device but encrypts each sector as it is written,and decrypts each sector as it is read. vold
then creates and writesout the crypto metadata.
vold
mounts a tmpfs /data
(using the tmpfs optionsfrom ro.crypto.tmpfs_options
) and sets the propertyvold.encrypt_progress
to 0. vold
prepares the tmpfs/data
for booting an encrypted system and sets the propertyvold.decrypt
to: trigger_restart_min_framework
trigger_restart_min_framework
causes init.rc
tostart the main
class of services. When the framework sees thatvold.encrypt_progress
is set to 0, it brings up the progress barUI, which queries that property every five seconds and updates a progress bar.The encryption loop updates vold.encrypt_progress
every time itencrypts another percent of the partition.
/data
is encrypted, update the crypto footer When /data
is successfully encrypted, vold
clearsthe flag ENCRYPTION_IN_PROGRESS
in the metadata.
When the device is successfully unlocked, the password is then used toencrypt the master key and the crypto footer is updated.
If the reboot fails for some reason, vold
sets the propertyvold.encrypt_progress
to error_reboot_failed
andthe UI should display a message asking the user to press a button toreboot. This is not expected to ever occur.
This is what happens when you boot up an encrypted device with no password.Because Android 5.0 devices are encrypted on first boot, there should be no setpassword and therefore this is the default encryption state.
/data
with no password Detect that the Android device is encrypted because /data
cannot be mounted and one of the flags encryptable
orforceencrypt
is set.
vold
sets vold.decrypt
totrigger_default_encryption
, which starts thedefaultcrypto
service. trigger_default_encryption
checks the encryption type to see if /data
is encrypted with orwithout a password.
Creates the dm-crypt
device over the block device so the deviceis ready for use.
vold
then mounts the decrypted real /data
partitionand then prepares the new partition. It sets the propertyvold.post_fs_data_done
to 0 and then sets vold.decrypt
to trigger_post_fs_data
. This causes init.rc
to runits post-fs-data
commands. They will create any necessary directoriesor links and then set vold.post_fs_data_done
to 1.
Once vold
sees the 1 in that property, it sets the propertyvold.decrypt
to: trigger_restart_framework.
Thiscauses init.rc
to start services in class main
again and also start services in class late_start
for the firsttime since boot.
Now the framework boots all its services using the decrypted /data
,and the system is ready for use.
This is what happens when you boot up an encrypted device that has a setpassword. The device’s password can be a pin, pattern, or password.
Detect that the Android device is encrypted because the flagro.crypto.state = "encrypted"
vold
sets vold.decrypt
totrigger_restart_min_framework
because /data
isencrypted with a password.
init
sets five properties to save the initial mount optionsgiven for /data
with parameters passed from init.rc
.vold
uses these properties to set up the crypto mapping:
ro.crypto.fs_type
ro.crypto.fs_real_blkdev
ro.crypto.fs_mnt_point
ro.crypto.fs_options
ro.crypto.fs_flags
(ASCII 8-digit hex number preceded by 0x) The framework starts up and sees that vold.decrypt
is set totrigger_restart_min_framework
. This tells the framework that it isbooting on a tmpfs /data
disk and it needs to get the user password.
First, however, it needs to make sure that the disk was properly encrypted. Itsends the command cryptfs cryptocomplete
to vold
.vold
returns 0 if encryption was completed successfully, -1 on internal error, or-2 if encryption was not completed successfully. vold
determinesthis by looking in the crypto metadata for the CRYPTO_ENCRYPTION_IN_PROGRESS
flag. If it's set, the encryption process was interrupted, and there is nousable data on the device. If vold
returns an error, the UI shoulddisplay a message to the user to reboot and factory reset the device, and givethe user a button to press to do so.
Once cryptfs cryptocomplete
is successful, the frameworkdisplays a UI asking for the disk password. The UI checks the password bysending the command cryptfs checkpw
to vold
. If thepassword is correct (which is determined by successfully mounting thedecrypted /data
at a temporary location, then unmounting it),vold
saves the name of the decrypted block device in the propertyro.crypto.fs_crypto_blkdev
and returns status 0 to the UI. If thepassword is incorrect, it returns -1 to the UI.
The UI puts up a crypto boot graphic and then calls vold
withthe command cryptfs restart
. vold
sets the propertyvold.decrypt
to trigger_reset_main
, which causesinit.rc
to do class_reset main
. This stops all servicesin the main class, which allows the tmpfs /data
to be unmounted.
/data
vold
then mounts the decrypted real /data
partitionand prepares the new partition (which may never have been prepared ifit was encrypted with the wipe option, which is not supported on firstrelease). It sets the property vold.post_fs_data_done
to 0 and thensets vold.decrypt
to trigger_post_fs_data
. This causesinit.rc
to run its post-fs-data
commands. They willcreate any necessary directories or links and then setvold.post_fs_data_done
to 1. Once vold
sees the 1 inthat property, it sets the property vold.decrypt
totrigger_restart_framework
. This causes init.rc
to startservices in class main
again and also start services in classlate_start
for the first time since boot.
Now the framework boots all its services using the decrypted /data
filesystem, and the system is ready for use.
A device that fails to decrypt might be awry for a few reasons. The devicestarts with the normal series of steps to boot:
But after the framework opens, the device can encounter some errors:
If these errors are not resolved, prompt user to factory wipe:
If vold
detects an error during the encryption process, and ifno data has been destroyed yet and the framework is up, vold
setsthe property vold.encrypt_progress
to error_not_encrypted
.The UI prompts the user to reboot and alerts them the encryption processnever started. If the error occurs after the framework has been torn down, butbefore the progress bar UI is up, vold
will reboot the system. Ifthe reboot fails, it sets vold.encrypt_progress
toerror_shutting_down
and returns -1; but there will not be anythingto catch the error. This is not expected to happen.
If vold
detects an error during the encryption process, it setsvold.encrypt_progress
to error_partially_encrypted
and returns -1. The UI should then display a message saying the encryptionfailed and provide a button for the user to factory reset the device.
The encrypted key is stored in the crypto metadata. Hardware backing isimplemented by using Trusted Execution Environment’s (TEE) signing capability.Previously, we encrypted the master key with a key generated by applying scryptto the user's password and the stored salt. In order to make the key resilientagainst off-box attacks, we extend this algorithm by signing the resultant keywith a stored TEE key. The resultant signature is then turned into an appropriatelength key by one more application of scrypt. This key is then used to encryptand decrypt the master key. To store this key:
When a user elects to change or remove their password in settings, the UI sendsthe command cryptfs changepw
to vold
, andvold
re-encrypts the disk master key with the new password.
vold
and init
communicate with each other bysetting properties. Here is a list of available properties for encryption.
Property | Description |
---|---|
vold.decrypt trigger_encryption | Encrypt the drive with no password. |
vold.decrypt trigger_default_encryption | Check the drive to see if it is encrypted with no password.If it is, decrypt and mount it,else set vold.decrypt to trigger_restart_min_framework. |
vold.decrypt trigger_reset_main | Set by vold to shutdown the UI asking for the disk password. |
vold.decrypt trigger_post_fs_data | Set by vold to prep /data with necessary directories, et al. |
vold.decrypt trigger_restart_framework | Set by vold to start the real framework and all services. |
vold.decrypt trigger_shutdown_framework | Set by vold to shutdown the full framework to start encryption. |
vold.decrypt trigger_restart_min_framework | Set by vold to start theprogress bar UI for encryption orprompt for password, depending onthe value of ro.crypto.state . |
vold.encrypt_progress | When the framework starts up,if this property is set, enterthe progress bar UI mode. |
vold.encrypt_progress 0 to 100 | The progress bar UI shoulddisplay the percentage value set. |
vold.encrypt_progress error_partially_encrypted | The progress bar UI should display a message that the encryption failed, andgive the user an option tofactory reset the device. |
vold.encrypt_progress error_reboot_failed | The progress bar UI should display a message saying encryption completed, and give the user a button to reboot the device. This error is not expected to happen. |
vold.encrypt_progress error_not_encrypted | The progress bar UI shoulddisplay a message saying an erroroccurred, no data was encrypted orlost, and give the user a button to reboot the system. |
vold.encrypt_progress error_shutting_down | The progress bar UI is not running, so it is unclear who will respond to this error. And it should never happen anyway. |
vold.post_fs_data_done 0 | Set by vold just before setting vold.decrypt to trigger_post_fs_data . |
vold.post_fs_data_done 1 | Set by init.rc or init.rc just after finishing the task post-fs-data . |
Property | Description |
---|---|
ro.crypto.fs_crypto_blkdev | Set by the vold command checkpw for later use by the vold command restart . |
ro.crypto.state unencrypted | Set by init to say this system is running with an unencrypted /data ro.crypto.state encrypted . Set by init to say this system is running with an encrypted /data . |
| These five properties are set by init when it tries to mount /data with parameters passed in from init.rc . vold uses these to setup the crypto mapping. |
ro.crypto.tmpfs_options | Set by init.rc with the options init should use when mounting the tmpfs /data filesystem. |
on post-fs-data on nonencrypted on property:vold.decrypt=trigger_reset_main on property:vold.decrypt=trigger_post_fs_data on property:vold.decrypt=trigger_restart_min_framework on property:vold.decrypt=trigger_restart_framework on property:vold.decrypt=trigger_shutdown_framework on property:vold.decrypt=trigger_encryption on property:vold.decrypt=trigger_default_encryption