Home | History | Annotate | only in /external/libese/apps/boot
Up to higher level directory
NameDateSize
Android.bp21-Aug-20181.5K
boot.c21-Aug-201826.5K
boot_private.h21-Aug-20181.3K
card/21-Aug-2018
ese_boot_tool.cpp21-Aug-201814.8K
include/21-Aug-2018
README.md21-Aug-201814.3K
tests/21-Aug-2018

README.md

      1 # Verified Boot Storage Applet for AVB 2.0
      2 
      3   - Status: Draft as of April 6, 2017
      4 
      5 ## Introduction
      6 
      7 The application and support libraries in this directory provide
      8 a mechanism for a device's bootloader, using [AVB](https://android.googlesource.com/platform/external/avb/),
      9 to store sensitive information.  For a bootloader, sensitive information
     10 includes whether the device is unlocked or locked, whether it is unlockable,
     11 and what the minimum version of the OS/kernel is allowed to be booted.  It
     12 may also store other sensitive flags.
     13 
     14 The verified boot storage applet provides a mechanism to store this
     15 data in a way that enforce the expected policies even if the higher level
     16 operating system is compromised or operates in an unexpected fashion.
     17 
     18 
     19 ## Design Overview
     20 
     21 The Verified Boot Storage Applet, VBSA, provides three purpose-built
     22 interfaces:
     23 
     24   - Lock storage and policy enforcement
     25   - Rollback index storage
     26   - Applet state
     27 
     28 Each will be detailed below.
     29 
     30 ### Locks
     31 
     32 There are four supported lock types:
     33 
     34   - `LOCK_CARRIER`
     35   - `LOCK_DEVICE`
     36   - `LOCK_BOOT`
     37   - `LOCK_OWNER`
     38 
     39 Each lock has a single byte of "lock" storage.  If that byte is 0x0, then it is
     40 unlocked, or cleared.  If it is non-zero, then the lock is locked.  Any
     41 non-zero value is valid and may be used by the bootloader if any additional
     42 internal flagging is necessary.
     43 
     44 In addition, a lock may have associated metadata which must be supplied during
     45 lock or unlock, or both.
     46 
     47 See `ese_boot_lock_*` in include/ese/app/boot.h for the specific interfaces.
     48 
     49 
     50 #### LOCK\_CARRIER
     51 
     52 The Carrier Lock implements a lock which can only be set when the device is not
     53 in production and can only be unlocked if provided a cryptographic signature.
     54 
     55 This lock is available for use to implement "sim locking" or "phone locking"
     56 such that the carrier can determine if the device is allowed to boot an
     57 unsigned or unknown system image.
     58 
     59 To provision this lock, device-specific data must be provided in an exact
     60 format.  An example of this can be found in
     61 `'ese-boot-tool.cpp':collect_device_data()`.  This data is then provided to
     62 the applet using `ese_boot_lock_xset()`.
     63 
     64 ##### Metadata format for locking/provisioning
     65 
     66 The following system attributes must be collected in the given order:
     67 
     68   - ro.product.brand
     69   - ro.product.device
     70   - ro.build.product
     71   - ro.serialno
     72   - [Modem ID: MEID or IMEI]
     73   - ro.product.manufacturer
     74   - ro.product.model
     75 
     76 The data is serialized as follows:
     77 
     78     \[length||string\]\[...\]
     79 
     80 The length is a `uint8_t` and the value is appended as a stream of
     81 `uint8_t` values.
     82 
     83 This data is then prefixed with the desired non-zero lock value before
     84 being submitted to the applet.  If successful, the applet will have
     85 stored a SHA256 hash of the device data
     86 
     87 Note, `LOCK_CARRIER` can only be locked (non-zero lock value) when the
     88 applet is not in 'production' mode.
     89 
     90 ##### Clearing/unlocking
     91 
     92 If `LOCK_CARRIER` is set to a non-zero value and the applet is in
     93 production mode, then clearing the lock value requires authorization.
     94 
     95 Authorization comes in the form of a `RSA_SHA256-PKCS#1` signature over
     96 the provisioned device data SHA256 hash and a supplied montonically
     97 increasing "nonce".
     98 
     99 The nonce value must be higher than the last seen nonce value and the
    100 signature must validate using public key internally stored in the
    101 applet (`CarrierLock.java:PK_MOD`).
    102 
    103 To perform a clear, `ese_boot_lock_xset()` must be called with lock
    104 data that begins with 0x0, to clear the lock, and then contains data of
    105 the following format:
    106 
    107 ```
    108     unlockToken = VERSION || NONCE || SIGNATURE
    109 
    110     SIGNATURE = RSA_Sign(SHA256(deviceData))
    111 ```
    112 
    113   - The version is a little endian `uint64_t` (8 bytes).
    114   - The nonce is a little endian `uint64_t` (8 bytes).
    115   - The signature is a RSA 2048-bit with SHA-256 PKCS#1 v1.5 (256 bytes).
    116 
    117 On unlock, the device data hash is cleared.
    118 
    119 ##### Testing
    120 
    121 It is possible to test the key with a valid signature but a fake
    122 internal nonce and fake internal device data using
    123 `ese_boot_carrier_lock_test()`.  When using this interface, it
    124 expects the same unlock token as in the prior but prefixes with the
    125 fake data:
    126 
    127 ```
    128     testVector = LAST_NONCE || DEVICE_DATA || unlockToken
    129 ```
    130 
    131   - The last nonce is the value the nonce is compared against (8 bytes).
    132   - Device data is a replacement for the internally stored SHA-256
    133     hash of the deviec data. (32 bytes).
    134 
    135 #### LOCK\_DEVICE
    136 
    137 The device lock is one of the setting used by the bootloader to
    138 determine if the boot lock can be changed.  It may only be set by the
    139 operating system and is meant to protect the device from being reflashed
    140 by someone that cannot unlock or access the OS.  This may also be used
    141 by an enterprise administrator to control lock policy for managed
    142 devices.
    143 
    144 As `LOCK_DEVICE` has not metadata, it can be set and retrieved using
    145 `ese_boot_lock_set()` and `ese_boot_lock_get()`.
    146 
    147 #### LOCK\_BOOT
    148 
    149 The boot lock is used by the bootloader to control whether it should
    150 only boot verified system software or not.  When the lock value
    151 is cleared (0x0), the bootloader will boot anything.  When the lock
    152 value is non-zero, it should only boot software that is signed by a key
    153 stored in the bootloader except if `LOCK_OWNER` is set.  Discussion of
    154 `LOCK_OWNER` will follow.
    155 
    156 `LOCK_BOOT` can only be toggled when in the bootloader/fastboot and if
    157 both `LOCK_CARRIER` and `LOCK_DEVICE` are cleared/unlocked.
    158 
    159 As with `LOCK_DEVICE`, `LOCK_BOOT` has no metadata so it does not need the
    160 extended accessors.
    161 
    162 #### LOCK\_OWNER
    163 
    164 The owner lock is used by the bootloader to support an alternative
    165 OS signing key provided by the device owner.  `LOCK_OWNER` can only be
    166 toggled if `LOCK_BOOT` is cleared. `LOCK_OWNER` does not require
    167 any metadata to unlock, but to lock, it requires a blob of up to 2048
    168 bytes be provided.  This is just secure storage for use by the
    169 bootloader.  `LOCK_OWNER` may be toggled in the bootloader or the
    170 operating system.  This allows an unlocked device (`LOCK_BOOT=0x0`) to
    171 install an owner key using fastboot or using software on the operating
    172 system itself.
    173 
    174 Before `LOCK_OWNER`'s key should be honored by the bootloader, `LOCK_BOOT`
    175 should be set (in the bootloader) to enforce use of the key and to keep
    176 malicious software in the operating system from changing it.
    177 
    178 (Note, that the owner key should not be treated as equivalent to the
    179 bootloader's internally stored key in that the device user should have a
    180 means of knowing if an owner key is in use, but the requirement for the
    181 device to be unlocked implies both physical access the `LOCK_DEVICE`
    182 being cleared.)
    183 
    184 
    185 ### Rollback storage
    186 
    187 Verifying an operating system kernel and image is useful both for system
    188 reliability and for ensuring that the software has not been modified by
    189 a malicious party.  However, if the system software is updated,
    190 malicious software may attempt to "roll" a device back to an older
    191 version in order to take advantage of mistakes in the older, verified
    192 code.
    193 
    194 Rollback index values, or versions, may be stored securely by the bootloader
    195 to prevent these problems.  The Verified Boot Storage applet provides
    196 eight 64-bit slots for storing a value.  They may be read at any time,
    197 but they may only be written to when the device is in the bootloader (or
    198 fastboot).
    199 
    200 Rollback storage is written to using
    201 `ese_boot_rollback_index_write()` and read using
    202 `ese_boot_rollback_index_read()`.
    203 
    204 ### Applet state
    205 
    206 The applet supports two operational states:
    207 
    208   - production=true
    209   - production=false
    210 
    211 On initial installation, production is false.  When the applet is not
    212 in production mode, it does not enforce a number of security boundaries,
    213 such as requiring bootloader or hlos mode for lock toggling or
    214 CarrierLock verification.  This allows the factory tools to run in any
    215 mode and properly configure a default lock state.
    216 
    217 To transition to "production", a call to `ese_boot_set_production(true)`
    218 is necessary.
    219 
    220 To check the state and collect debugging information, the call
    221 `ese_boot_get_state()` will return the current bootloader value,
    222 the production state, any errors codes from lock initialization, and the
    223 contents of lock storage.
    224 
    225 #### Example applet provisioning
    226 
    227 After the applet is installed, a flow as follows would prepare the
    228 applet for use:
    229 
    230   - `ese_boot_session_init();`
    231   - `ese_boot_session_open();`
    232   - `ese_boot_session_lock_xset(LOCK_OWNER, {0, ...});`
    233   - `ese_boot_session_lock_set(LOCK_BOOT, 0x1);`
    234   - `ese_boot_session_lock_set(LOCK_DEVICE, 0x1);`
    235   - [collect device data]
    236   - `ese_boot_session_lock_set(LOCK_CARRIER, {1, deviceData});`
    237   - `ese_boot_session_set_production(true);`
    238   - `ese_boot_session_close();`
    239 
    240 ### Additional details
    241 
    242 #### Bootloader mode
    243 
    244 Bootloader mode detection depends on hardware support to signal the
    245 applet that the application processor has been reset.  Additionally,
    246 there is a mechanism for the bootloader to indicate that is loading the
    247 main OS where it flips the value.  This signal provides the assurances
    248 around when storage is mutable or not during the time a device is
    249 powered on.
    250 
    251 #### Error results
    252 
    253 EseAppResult is an enum that all `ese_boot_*` functions return.  The
    254 enum only covers the lower 16-bits.  The upper 16-bits are reserved for
    255 passing applet and secure element OS status for debugging and analysis.
    256 When the lower 16-bits are `ESE_APP_RESULT_ERROR_APPLET`, then the
    257 upper bytes will be the applet code. That code can then be
    258 cross-referenced in the applet by function and code.  If the lower
    259 bytes are `ESE_APP_RESULT_ERROR_OS`, then the status code are the
    260 ISO7816 code from an uncaught exception or OS-level error.
    261 
    262 ##### Cooldown
    263 
    264 `ESE_APP_RESULT_ERROR_COOLDOWN` indicates that the secure element needs to
    265 stay powered on for a period of time -- either at the end of use or before the
    266 requested command can be serviced.  As the behavior is implementation specific,
    267 the only effective option is to keep the secure element powered for the number of
    268 seconds specified by the response `uint32_t`.
    269 
    270 For chips that support it, like the one this applet is being tested on, the
    271 cooldown time can be requested with a special APDU to `ese_transceive()`:
    272 
    273 ```
    274     FFE10000
    275 ```
    276 
    277 In response, a 6 byte response will contain a `uint32_t` and a successful status
    278 code (`90 00`).  The unsigned little-endian integer indicates how many seconds
    279 the chip needs to stay powered and unused to cooldown.  If this happens before
    280 the locks or rollback storage can be read, the bootloader will need to
    281 determine a safe delay or recovery path until boot can proceed securely.
    282 
    283 ## Examples
    284 
    285 There are many ways to integrate this library and the associated applet.
    286 Below are some concrete examples to guide standard approach.
    287 
    288 ### Configuration in factory
    289 
    290 - Install configure the secure element and install the applets  
    291 (outside of the scope of this document).
    292 - Boot to an environment to run the ese-boot-tool.
    293 - Leave the inBootloader() signal asserted (recommended but not required).
    294 - Configure the desired lock states:
    295   - `# ese-boot-tool lock set carrier 1 modem-imei-string`
    296   - `# ese-boot-tool lock set device 1`
    297   - `# ese-boot-tool lock set boot 1`
    298   - `# ese-boot-tool lock set owner 0`
    299 - To move from factory mode to production mode call:
    300   - `# ese-boot-tool production set true`
    301 
    302 ### Configuration during repair
    303 
    304 - Boot to an environment to run the ese-boot-tool.
    305 - Leave inBootloader() signal asserted or implement the steps below in  
    306   the bootloader.
    307 - Transition out of production mode:
    308   - `# ese-boot-tool production set false`
    309 - If a `LOCK_CARRIER` problem is being repaired, it is possible to reset the  
    310   internal nonce counter and all lock state with the command below.  A full  
    311   lock reset is not expected in most cases.
    312   - `# ese-boot-tool lock reset`
    313 - Reconfigure the lock states:
    314   - `# ese-boot-tool lock set carrier 1 modem-imei-string`
    315   - `# ese-boot-tool lock set device 1`
    316   - `# ese-boot-tool lock set boot 1`
    317   - `# ese-boot-tool lock set owner 0`
    318     (To clear data from the owner lock, set owner 1 must be called with  
    319      4096 00s.)
    320 - Then move back to production mode:
    321   - `# ese-boot-tool production set true`
    322 
    323 ### Use during boot
    324 
    325 Do not load any non-repair or non-factory OS without clearing the inBootloader
    326 signal as the applet may be transitioned out of production mode and/or the
    327 rollback state may be changed.
    328 
    329 #### Checking rollback values
    330 
    331 - Read and write rollback values as per libavb using the API
    332   - `ese_boot_rollback_index_write()`
    333   - `ese_boot_rollback_index_read()`
    334 - Prior to leaving the bootloader, clear the inBootloader signal.
    335 
    336 As rollback index values can only be written when inBootloader signal is set,
    337 it is critical to clear it when leaving the bootloader.
    338 
    339 #### Checking locks
    340 
    341 The pseudo-code and comments below should outline the basic algorithm, but it
    342 does not include integration into libavb or include use of rollback index
    343 value checking:
    344 
    345 ```
    346 // Read LOCK_BOOT
    347 ese_boot_lock_get(session, kEseBootLockIdBoot, &lockBoot);
    348 
    349 if (lockBoot != 0x0) {  // Boot is LOCKED.
    350     // Read the LOCK_OWNER
    351     ese_boot_lock_xget(session, kEseBootLockIdOwner, &lockOwner);
    352     if (lockOwner != 0x0) {  // Owner is LOCKED
    353       // Get the lock owner value with metadata.
    354       // This is done as a second stage to avoid wasted copying when it
    355       // is not locked.
    356       uint8_t ownerData[kEseBootOwnerKeyMax + 1];
    357       ese_boot_lock_xget(session, kEseBootLockIdOwner, ownerData
    358                          sizeof(ownerData), &ownerDataUsed);
    359       // lockOwner == ownerData[0]
    360       // Parse the stored metadata into a key as per your bootloader
    361       // design.
    362       SomeBootKey key;
    363       parseDeviceOwnerKeyForBooting(ownerData + 1, ownerDataUsed, &key);
    364       // Boot using the supplied owner key
    365       // (E.g., as part of avb_validate_vbmeta_public_key())
    366       setDeviceOwnerKeyForBooting(&key);
    367       continueBootFlow();
    368 } else {  // Boot is UNLOCKED (0x0)
    369     // Perform the boot flow.
    370     setBootIsUnverified();
    371     continueBootFlow();
    372 }
    373 ```
    374 
    375 ### In fastboot
    376 
    377 - `LOCK_BOOT` may be toggled by a fastboot command.  If the conditions of  
    378   unlock are not allowed by applet policy, it will fail.
    379 - `LOCK_OWNER`may be toggled and set a boot key from a fastboot command  
    380   or from an unlocked OS image.
    381 - If the verified boot design dictates that rollback indices are clear on  
    382   lock/unlock, this can be done by calling
    383   - `ese_boot_rollback_index_write()` on each slot with the value of 0.
    384 
    385 Note, `LOCK_DEVICE` and `LOCK_CARRIER` should not need to be used by fastboot.
    386 
    387 For debugging and support, it may be desirable to connect the
    388 `ese_boot_get_state()` to allow fastboot to return the current value of
    389 production, inbootloader, and the lock metadata.
    390 
    391