• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1<!--
2   Copyright 2011 The Android Open Source Project
3
4   Licensed under the Apache License, Version 2.0 (the "License");
5   you may not use this file except in compliance with the License.
6   You may obtain a copy of the License at
7
8       http://www.apache.org/licenses/LICENSE-2.0
9
10   Unless required by applicable law or agreed to in writing, software
11   distributed under the License is distributed on an "AS IS" BASIS,
12   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   See the License for the specific language governing permissions and
14   limitations under the License.
15-->
16
17# Notes on the implementation of encryption in Android 3.0
18<br />
19
20## Quick summary for 3rd parties.
21
22If you want to enable encryption on your device based on Android 3.0
23aka Honeycomb, there are only a few requirements:
24
251.  The /data filesystem must be on a device that presents a block device
26    interface.  eMMC is used in the first devices.  This is because the
27    encryption is done by the dm-crypt layer in the kernel, which works
28    at the block device layer.
29
302.  The function get_fs_size() in system/vold/cryptfs.c assumes the filesystem
31    used for /data is ext4.  It's just error checking code to make sure the
32    filesystem doesn't extend into the last 16 Kbytes of the partition where
33    the crypto footer is kept.  It was useful for development when sizes were
34    changing, but should not be required for release.  If you are not using
35    ext4, you can either delete it and the call to it, or fix it to understand
36    the filesystem you are using.
37
383.  Most of the code to handle the setup and teardown of the temporary framework
39    is in files that are not usually required to be changed on a per device
40    basis.  However, the init.<device>.rc file will require some changes.  All
41    services must be put in one of three classes: core, main or late_state.
42    Services in the core class are not shutdown and restarted when the
43    temporary framework gets the disk password.  Services in the main class
44    are restarted when the framework is restarted.  Services in late_start are
45    not started until after the temporary framework is restarted.  Put services
46    here that are not required to be running while the temporary framework
47    gets the disk password.
48
49    Also any directories that need to be created on /data that are device
50    specific need to be in the Action for post-fs-data, and that Action must end
51    with the command "setprop vold.post_fs_data_done 1".  If your
52    init.<device>.rc file does not have a post-fs-data Action, then the
53    post-fs-data Action in the main init.rc file must end with the command
54    "setprop vold.post_fs_data_done 1".
55
56
57## How Android encryption works
58
59Disk encryption on Android is based on dm-crypt, which is a kernel feature that
60works at the block device layer.  Therefore, it is not usable with YAFFS, which
61talks directly to a raw nand flash chip, but does work with emmc and similar
62flash devices which present themselves to the kernel as a block device.  The
63current preferred filesystem to use on these devices is ext4, though that is
64independent of whether encryption is used or not.
65
66While the actual encryption work is a standard linux kernel feature, enabling it
67on an Android device proved somewhat tricky.  The Android system tries to avoid
68incorporating GPL components, so using the cryptsetup command or libdevmapper
69were not available options.  So making the appropriate ioctl(2) calls into the
70kernel was the best choice.  The Android volume daemon (vold) already did this
71to support moving apps to the SD card, so I chose to leverage that work
72for whole disk encryption.  The actual encryption used for the filesystem for
73first release is 128 AES with CBC and ESSIV:SHA256.  The master key is
74encrypted with 128 bit AES via calls to the openssl library.
75
76Once it was decided to put the smarts in vold, it became obvious that invoking
77the encryption features would be done like invoking other vold commands, by
78adding a new module to vold (called cryptfs) and teaching it various commands.
79The commands are checkpw, restart, enablecrypto, changepw and cryptocomplete.
80They will be described in more detail below.
81
82The other big issue was how to get the password from the user on boot.  The
83initial plan was to implement a minimal UI that could be invoked from init
84in the initial ramdisk, and then init would decrypt and mount /data.  However,
85the UI engineer said that was a lot of work, and suggested instead that init
86communicate upon startup to tell the framework to pop up the password entry
87screen, get the password, and then shutdown and have the real framework started.
88It was decided to go this route, and this then led to a host of other decisions
89described below.  In particular, init set a property to tell the framework to go
90into the special password entry mode, and that set the stage for much
91communication between vold, init and the framework using properties.  The
92details are described below.
93
94Finally, there were problems around killing and restarting various services
95so that /data could be unmounted and remounted.  Bringing up the temporary
96framework to get the user password requires that a tmpfs /data filesystem be
97mounted, otherwise the framework will not run.  But to unmount the tmpfs /data
98filesystem so the real decrypted /data filesystem could be mounted meant that
99every process that had open files on the tmpfs /data filesystem had to be killed
100and restarted on the real /data filesystem.  This magic was accomplished by
101requiring all services to be in 1 of 3 groups: core, main and late_start.
102Core services are never shut down after starting.  main services are shutdown
103and then restarted after the disk password is entered.  late_start services
104are not started until after /data has been decrypted and mounted.  The magic
105to trigger these actions is by setting the property vold.decrypt to various
106magic strings, which is described below.  Also, a new init command "class_reset"
107was invented to stop a service, but allow it to be restarted with a
108"class_start" command.  If the command "class_stop" was used instead of the
109new command "class_reset" the flag SVC_DISABLED was added to the state of
110any service stopped, which means it would not be started when the command
111class_start was used on its class.
112
113## Booting an encrypted system.
114
1151.  When init fails to mount /data, it assumes the filesystem  is encrypted,
116    and sets several properties:
117      ro.crypto.state = "encrypted"
118      vold.decrypt = 1
119    It then mounts a /data on a tmpfs ramdisk, using parameters it picks
120    up from ro.crypto.tmpfs_options, which is set in init.rc.
121
122    If init was able to mount /data, it sets ro.crypto.state to "unencrypted".
123
124    In either case, init then sets 5 properties to save the initial mount
125    options given for /data in these properties:
126        ro.crypto.fs_type
127        ro.crypto.fs_real_blkdev
128        ro.crypto.fs_mnt_point
129        ro.crypto.fs_options
130        ro.crypto.fs_flags (saved as an ascii 8 digit hex number preceded by 0x)
131
1322.  The framework starts up, and sees that vold.decrypt is set to "1".  This
133    tells the framework that it is booting on a tmpfs /data disk, and it needs
134    to get the user password.  First, however, it needs to make sure that the
135    disk was properly encrypted.  It sends the command "cryptfs cryptocomplete"
136    to vold, and vold returns 0 if encryption was completed successfully, or -1
137    on internal error, or -2 if encryption was not completed successfully.
138    Vold determines this by looking in the crypto footer for the
139    CRYPTO_ENCRYPTION_IN_PROGRESS flag.  If it's set, the encryption process
140    was interrupted, and there is no usable data on the device.  If vold returns
141    an error, the UI should pop up a message saying the user needs to reboot and
142    factory reset the device, and give the user a button to press to do so.
143
1443.  Assuming the "cryptfs cryptocomplete" command returned success, the
145    framework should pop up a UI asking for the disk password.  The UI then
146    sends the command "cryptfs checkpw <passwd>" to vold.  If the password
147    is correct (which is determined by successfully mounting the decrypted
148    at a temporary location, then unmounting it), vold saves the name of the
149    decrypted block device in the property ro.crypto.fs_crypto_blkdev, and
150    returns status 0 to the UI.  If the password is incorrect, it returns -1
151    to the UI.
152
1534.  The UI puts up a crypto boot graphic, and then calls vold with the command
154    "cryptfs restart".  vold sets the property vold.decrypt to
155    "trigger_reset_main", which causes init.rc to do "class_reset main".  This
156    stops all services in the main class, which allows the tmpfs /data to be
157    unmounted.  vold then mounts the decrypted real /data partition, and then
158    preps the new partition (which may never have been prepped if it was
159    encrypted with the wipe option, which is not supported on first release).
160    It sets the property vold.post_fs_data_done to "0", and then sets
161    vold.decrypt to "trigger_post_fs_dat".  This causes init.rc to run the
162    post-fs-data commands in init.rc and init.<device>.rc.  They will create
163    any necessary directories, links, et al, and then set vold.post_fs_data_done
164    to "1".  Vold waits until it sees the "1" in that property.  Finally, vold
165    sets the property vold.decrypt to "trigger_restart_framework" which causes
166    init.rc to start services in class main again, and also start services
167    in class late_start for the first time since boot.
168
169    Now the framework boots all its services using the decrypted /data
170    filesystem, and the system is ready for use.
171
172## Enabling encryption on the device.
173
174For first release, we only support encrypt in place, which requires the
175framework to be shutdown, /data unmounted, and then every sector of the
176device encrypted, after which the device reboots to go through the process
177described above.  Here are the details:
178
1791.  From the UI, the user selects to encrypt the device.  The UI ensures that
180    there is a full charge on the battery, and the AC adapter is plugged in.
181    It does this to make sure there is enough power to finish the encryption
182    process, because if the device runs out of power and shuts down before it
183    has finished encrypting, file data is left in a partially encrypted state,
184    and the device must be factory reset (and all data lost).
185
186    Once the user presses the final button to encrypt the device, the UI calls
187    vold with the command "cryptfs enablecrypto inplace <passwd>" where passwd
188    is the user's lock screen password.
189
1902.  vold does some error checking, and returns -1 if it can't encrypt, and
191    prints a reason in the log.  If it thinks it can, it sets the property
192    vold.decrypt to "trigger_shutdown_framework".  This causes init.rc to
193    stop services in the classes late_start and main.  vold then unmounts
194    /mnt/sdcard and then /data.
195
1963.  If doing an inplace encryption, vold then mounts a tmpfs /data (using the
197    tmpfs options from ro.crypto.tmpfs_options) and sets the property
198    vold.encrypt_progress to "0".  It then preps the tmpfs /data filesystem as
199    mentioned in step 3 for booting an encrypted system, and then sets the
200    property vold.decrypt to "trigger_restart_min_framework".  This causes
201    init.rc to start the main class of services.  When the framework sees that
202    vold.encrypt_progress is set to "0", it will bring up the progress bar UI,
203    which queries that property every 5 seconds and updates a progress bar.
204
2054.  vold then sets up the crypto mapping, which creates a virtual crypto block
206    device that maps onto the real block device, but encrypts each sector as it
207    is written, and decrypts each sector as it is read.  vold then creates and
208    writes out the crypto footer.
209
210    The crypto footer contains details on the type of encryption, and an
211    encrypted copy of the master key to decrypt the filesystem.  The master key
212    is a 128 bit number created by reading from /dev/urandom.  It is encrypted
213    with a hash of the user password created with the PBKDF2 function from the
214    SSL library.  The footer also contains a random salt (also read from
215    /dev/urandom) used to add entropy to the hash from PBKDF2, and prevent
216    rainbow table attacks on the password.  Also, the flag
217    CRYPT_ENCRYPTION_IN_PROGRESS is set in the crypto footer to detect failure
218    to complete the encryption process.  See the file cryptfs.h for details
219    on the crypto footer layout.  The crypto footer is kept in the last 16
220    Kbytes of the partition, and the /data filesystem cannot extend into that
221    part of the partition.
222
2235.  If told was to enable encryption with wipe, vold invokes the command
224    "make_ext4fs" on the crypto block device, taking care to not include
225    the last 16 Kbytes of the partition in the filesystem.
226
227    If the command was to enable inplace, vold starts a loop to read each sector
228    of the real block device, and then write it to the crypto block device.
229    This takes about an hour on a 30 Gbyte partition on the Motorola Xoom.
230    This will vary on other hardware.  The loop updates the property
231    vold.encrypt_progress every time it encrypts another 1 percent of the
232    partition.  The UI checks this property every 5 seconds and updates
233    the progress bar when it changes.
234
2356.  When either encryption method has finished successfully, vold clears the
236    flag ENCRYPTION_IN_PROGRESS in the footer, and reboots the system.
237    If the reboot fails for some reason, vold sets the property
238    vold.encrypt_progress to "error_reboot_failed" and the UI should
239    display a message asking the user to press a button to reboot.
240    This is not expected to ever occur.
241
2427.  If vold detects an error during the encryption process, and if no data has
243    been destroyed yet and the framework is up, vold sets the property
244    vold.encrypt_progress to "error_not_encrypted" and the UI should give the
245    user the option to reboot, telling them that the encryption process
246    never started.  If the error occurs after the framework has been torn
247    down, but before the progress bar UI is up, vold will just reboot the
248    system.  If the reboot fails, it sets vold.encrypt_progress to
249    "error_shutting_down" and returns -1, but there will not be anyone
250    to catch the error.  This is not expected to happen.
251
252    If vold detects an error during the encryption process, it sets
253    vold.encrypt_progress to "error_partially_encrypted" and returns -1.
254    The UI should then display a message saying the encryption failed, and
255    provide a button for the user to factory reset the device.
256
257## Changing the password
258
259To change the password for the disk encryption, the UI sends the command
260"cryptfs changepw <newpw>" to vold, and vold re-encrypts the disk master
261key with the new password.
262
263## Summary of related properties
264
265Here is a table summarizing the various properties, their possible values,
266and what they mean:
267
268
269    vold.decrypt  1                               Set by init to tell the UI to ask
270                                                  for the disk pw
271
272    vold.decrypt  trigger_reset_main              Set by vold to shutdown the UI
273                                                  asking for the disk password
274
275    vold.decrypt  trigger_post_fs_data            Set by vold to prep /data with
276                                                  necessary dirs, et al.
277
278    vold.decrypt  trigger_restart_framework       Set by vold to start the real
279                                                  framework and all services
280
281    vold.decrypt  trigger_shutdown_framework      Set by vold to shutdown the full
282                                                  framework to start encryption
283
284    vold.decrypt  trigger_restart_min_framework   Set by vold to start the progress
285                                                  bar UI for encryption.
286
287    vold.enrypt_progress                          When the framework starts up, if
288                                                  this property is set, enter the
289                                                  progress bar UI mode.
290
291    vold.encrypt_progress  0 to 100               The progress bar UI should display
292                                                  the percentage value set.
293
294    vold.encrypt_progress  error_partially_encrypted  The progress bar UI should
295                                                      display a message that the
296                                                      encryption failed, and give
297                                                      the user an option to factory
298                                                      reset the device.
299
300    vold.encrypt_progress  error_reboot_failed    The progress bar UI should display
301                                                  a message saying encryption
302                                                  completed, and give the user a
303                                                  button to reboot the device.
304                                                  This error is not expected to
305                                                  happen.
306
307    vold.encrypt_progress  error_not_encrypted    The progress bar UI should display
308                                                  a message saying an error occured,
309                                                  and no data was encrypted or lost,
310                                                  and give the user a button to
311                                                  reboot the system.
312
313    vold.encrypt_progress  error_shutting_down    The progress bar UI is not
314                                                  running, so it's unclear who
315                                                  will respond to this error,
316                                                  and it should never happen
317                                                  anyway.
318
319    vold.post_fs_data_done  0                     Set by vold just before setting
320                                                  vold.decrypt to
321                                                  trigger_post_fs_data.
322
323    vold.post_fs_data_done  1                     Set by init.rc or init.<device>.rc
324                                                  just after finishing the task
325                                                  post-fs-data.
326
327    ro.crypto.fs_crypto_blkdev                    Set by the vold command checkpw
328                                                  for later use by the vold command
329                                                  restart.
330
331    ro.crypto.state unencrypted                   Set by init to say this system is
332                                                  running with an unencrypted /data
333
334    ro.crypto.state encrypted                     Set by init to say this system is
335                                                  running with an encrypted /data
336
337    ro.crypto.fs_type                             These 5 properties are set by init
338    ro.crypto.fs_real_blkdev                      when it tries to mount /data with
339    ro.crypto.fs_mnt_point                        parameters passed in from init.rc.
340    ro.crypto.fs_options                          vold uses these to setup the
341    ro.crypto.fs_flags                            crypto mapping.
342
343    ro.crypto.tmpfs_options                       Set by init.rc with the options
344                                                  init should use when mounting
345                                                  the tmpfs /data filesystem.
346
347## Summary of new init actions
348
349A list of the new Actions that are added to init.rc and/or init.<device>.rc:
350
351    on post-fs-data
352    on nonencrypted
353    on property:vold.decrypt=trigger_reset_main
354    on property:vold.decrypt=trigger_post_fs_data
355    on property:vold.decrypt=trigger_restart_min_framework
356    on property:vold.decrypt=trigger_restart_framework
357    on property:vold.decrypt=trigger_shutdown_framework
358
359
360