Home | History | Annotate | Download | only in encryption
      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 
     22 If you want to enable encryption on your device based on Android 3.0
     23 aka Honeycomb, there are only a few requirements:
     24 
     25 1.  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 
     30 2.  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 
     38 3.  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 
     59 Disk encryption on Android is based on dm-crypt, which is a kernel feature that
     60 works at the block device layer.  Therefore, it is not usable with YAFFS, which
     61 talks directly to a raw nand flash chip, but does work with emmc and similar
     62 flash devices which present themselves to the kernel as a block device.  The
     63 current preferred filesystem to use on these devices is ext4, though that is
     64 independent of whether encryption is used or not.
     65 
     66 While the actual encryption work is a standard linux kernel feature, enabling it
     67 on an Android device proved somewhat tricky.  The Android system tries to avoid
     68 incorporating GPL components, so using the cryptsetup command or libdevmapper
     69 were not available options.  So making the appropriate ioctl(2) calls into the
     70 kernel was the best choice.  The Android volume daemon (vold) already did this
     71 to support moving apps to the SD card, so I chose to leverage that work
     72 for whole disk encryption.  The actual encryption used for the filesystem for
     73 first release is 128 AES with CBC and ESSIV:SHA256.  The master key is
     74 encrypted with 128 bit AES via calls to the openssl library.
     75 
     76 Once it was decided to put the smarts in vold, it became obvious that invoking
     77 the encryption features would be done like invoking other vold commands, by
     78 adding a new module to vold (called cryptfs) and teaching it various commands.
     79 The commands are checkpw, restart, enablecrypto, changepw and cryptocomplete.
     80 They will be described in more detail below.
     81 
     82 The other big issue was how to get the password from the user on boot.  The
     83 initial plan was to implement a minimal UI that could be invoked from init
     84 in the initial ramdisk, and then init would decrypt and mount /data.  However,
     85 the UI engineer said that was a lot of work, and suggested instead that init
     86 communicate upon startup to tell the framework to pop up the password entry
     87 screen, get the password, and then shutdown and have the real framework started.
     88 It was decided to go this route, and this then led to a host of other decisions
     89 described below.  In particular, init set a property to tell the framework to go
     90 into the special password entry mode, and that set the stage for much
     91 communication between vold, init and the framework using properties.  The
     92 details are described below.
     93 
     94 Finally, there were problems around killing and restarting various services
     95 so that /data could be unmounted and remounted.  Bringing up the temporary
     96 framework to get the user password requires that a tmpfs /data filesystem be
     97 mounted, otherwise the framework will not run.  But to unmount the tmpfs /data
     98 filesystem so the real decrypted /data filesystem could be mounted meant that
     99 every process that had open files on the tmpfs /data filesystem had to be killed
    100 and restarted on the real /data filesystem.  This magic was accomplished by
    101 requiring all services to be in 1 of 3 groups: core, main and late_start.
    102 Core services are never shut down after starting.  main services are shutdown
    103 and then restarted after the disk password is entered.  late_start services
    104 are not started until after /data has been decrypted and mounted.  The magic
    105 to trigger these actions is by setting the property vold.decrypt to various
    106 magic strings, which is described below.  Also, a new init command "class_reset"
    107 was 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
    109 new command "class_reset" the flag SVC_DISABLED was added to the state of
    110 any service stopped, which means it would not be started when the command
    111 class_start was used on its class.
    112 
    113 ## Booting an encrypted system.
    114 
    115 1.  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 
    132 2.  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     
    144 3.  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 
    153 4.  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 
    174 For first release, we only support encrypt in place, which requires the
    175 framework to be shutdown, /data unmounted, and then every sector of the
    176 device encrypted, after which the device reboots to go through the process
    177 described above.  Here are the details:
    178 
    179 1.  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 
    190 2.  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     
    196 3.  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 
    205 4.  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 
    223 5.  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 
    235 6.  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 
    242 7.  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 
    259 To 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
    261 key with the new password.
    262 
    263 ## Summary of related properties
    264 
    265 Here is a table summarizing the various properties, their possible values,
    266 and 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 
    349 A 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