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