Joakim Bech | 8e5c5b3 | 2018-10-25 08:18:32 +0200 | [diff] [blame] | 1 | .. _secure_storage: |
| 2 | |
| 3 | ############## |
| 4 | Secure storage |
| 5 | ############## |
| 6 | |
| 7 | Background |
| 8 | ********** |
| 9 | Secure Storage in OP-TEE is implemented according to what has been defined in |
Matteus Silva | 9f50635 | 2019-09-03 12:41:44 -0300 | [diff] [blame] | 10 | GlobalPlatform's :ref:`tee_internal_core_api` (here called Trusted Storage). |
Joakim Bech | 8e5c5b3 | 2018-10-25 08:18:32 +0200 | [diff] [blame] | 11 | This specification mandates that it should be possible to store general-purpose |
| 12 | data and key material that guarantees confidentiality and integrity of the data |
| 13 | stored and the atomicity of the operations that modifies the storage (atomicity |
| 14 | here means that either the entire operation completes successfully or no write |
| 15 | is done). |
| 16 | |
| 17 | There are currently two secure storage implementations in OP-TEE: |
| 18 | |
| 19 | - The first one relies on the normal world (REE) file system. It is |
| 20 | described in this document and is the default implementation. It is |
| 21 | enabled at compile time by ``CFG_REE_FS=y``. |
| 22 | |
| 23 | - The second one makes use of the Replay Protected Memory Block (RPMB) |
| 24 | partition of an eMMC device, and is enabled by setting ``CFG_RPMB_FS=y``. |
Markus S. Wamser | 4587daa | 2019-09-13 14:03:02 +0200 | [diff] [blame] | 25 | It is described in :ref:`rpmb`. |
Joakim Bech | 8e5c5b3 | 2018-10-25 08:18:32 +0200 | [diff] [blame] | 26 | |
| 27 | It is possible to use the normal world file systems and the RPMB implementations |
| 28 | simultaneously. For this, two OP-TEE specific storage identifiers have been |
| 29 | defined: ``TEE_STORAGE_PRIVATE_REE`` and ``TEE_STORAGE_PRIVATE_RPMB``. Depending |
| 30 | on the compile-time configuration, one or several values may be used. The value |
| 31 | ``TEE_STORAGE_PRIVATE`` selects the REE FS when available, otherwise the RPMB FS |
| 32 | (in this order). |
| 33 | |
| 34 | REE FS Secure Storage |
| 35 | ********************* |
| 36 | .. figure:: ../images/secure_storage/secure_storage_system_architecture.png |
| 37 | :figclass: align-center |
| 38 | |
| 39 | Secure Storage System Architecture |
| 40 | |
| 41 | **Source Files in OP-TEE OS** |
| 42 | |
| 43 | .. list-table:: Secure storage files |
| 44 | :header-rows: 1 |
| 45 | :widths: 1 6 |
| 46 | |
| 47 | * - Source file |
| 48 | - Purpose |
| 49 | |
| 50 | * - `core/tee/tee_svc_storage.c`_ |
| 51 | - TEE trusted storage service calls |
| 52 | |
| 53 | * - `core/tee/tee_ree_fs.c`_ |
| 54 | - TEE file system & REE file operation interface |
| 55 | |
| 56 | * - `core/tee/fs_htree.c`_ |
| 57 | - Hash tree |
| 58 | |
| 59 | * - `core/tee/tee_fs_key_manager.c`_ |
| 60 | - Key manager |
| 61 | |
| 62 | * - `lib/libutee/`_ |
| 63 | - GlobalPlatform Internal API library |
| 64 | |
| 65 | Basic File Operation Flow |
| 66 | ========================= |
| 67 | When a TA is calling the write function provided by GP Trusted Storage API to |
| 68 | write data to a persistent object, a corresponding syscall implemented in TEE |
| 69 | Trusted Storage Service will be called, which in turn will invoke a series of |
| 70 | TEE file operations to store the data. TEE file system will then encrypt the |
| 71 | data and send REE file operation commands and the encrypted data to TEE |
| 72 | supplicant by a series of RPC messages. TEE supplicant will receive the messages |
| 73 | and store the encrypted data accordingly to the Linux file system. Reading files |
| 74 | are handled in a similar manner. |
| 75 | |
| 76 | GlobalPlatform Trusted Storage Requirement |
| 77 | ========================================== |
| 78 | Below is an excerpt from the specification, listing the most vital requirements: |
| 79 | |
| 80 | .. code-block:: none |
| 81 | |
| 82 | 1. The Trusted Storage may be backed by non-secure resources as long as |
| 83 | suitable cryptographic protection is applied, which MUST be as strong as |
| 84 | the means used to protect the TEE code and data itself. |
| 85 | |
| 86 | 2. The Trusted Storage MUST be bound to a particular device, which means |
| 87 | that it MUST be accessible or modifiable only by authorized TAs |
| 88 | running in the same TEE and on the same device as when the data was |
| 89 | created. |
| 90 | |
| 91 | 3. Ability to hide sensitive key material from the TA itself. |
| 92 | |
| 93 | 4. Each TA has access to its own storage space that is shared among all the |
| 94 | instances of that TA but separated from the other TAs. |
| 95 | |
| 96 | 5. The Trusted Storage must provide a minimum level of protection against |
| 97 | rollback attacks. It is accepted that the actually physical storage |
| 98 | may be in an insecure area and so is vulnerable to actions from |
| 99 | outside of the TEE. Typically, an implementation may rely on the REE |
| 100 | for that purpose (protection level 100) or on hardware assets |
| 101 | controlled by the TEE (protection level 1000). |
| 102 | |
| 103 | (see GP TEE Internal Core API section 2.5 and 5.2) |
| 104 | |
| 105 | If configured with ``CFG_RPMB_FS=y`` the protection against rollback is |
| 106 | controlled by the TEE and is set to 1000. If ``CFG_RPMB_FS=n``, there's no |
| 107 | protection against rollback, and the protection level is set to 0. |
| 108 | |
| 109 | TEE File Structure in Linux File System |
| 110 | ======================================= |
| 111 | OP-TEE by default uses ``/data/tee/`` as the secure storage space in the Linux |
| 112 | file system. Each persistent object is assigned an internal identifier. It is an |
| 113 | integer which is visible in the Linux file system as ``/data/tee/<file |
| 114 | number>``. |
| 115 | |
| 116 | A directory file, ``/data/tee/dirf.db``, lists all the objects that are in the |
| 117 | secure storage. All normal world files are integrity protected and encrypted, as |
| 118 | described below. |
| 119 | |
| 120 | Key Manager |
| 121 | *********** |
Matthias Stauber | 87c4919 | 2020-03-06 20:18:04 +0100 | [diff] [blame] | 122 | Key manager is a component in TEE file system, and is responsible for handling |
Joakim Bech | 8e5c5b3 | 2018-10-25 08:18:32 +0200 | [diff] [blame] | 123 | data encryption and decryption and also management of the sensitive key |
| 124 | materials. There are three types of keys used by the key manager: the Secure |
| 125 | Storage Key (`SSK`), the TA Storage Key (`TSK`) and the File Encryption Key |
| 126 | (`FEK`). |
| 127 | |
| 128 | Secure Storage Key (SSK) |
| 129 | ======================== |
| 130 | SSK is a per-device key and is generated and stored in secure memory when OP-TEE |
| 131 | is booting. SSK is used to derive the TA Storage Key (TSK). |
| 132 | |
| 133 | SSK is derived by |
| 134 | |
| 135 | SSK = HMAC\ :sub:`SHA256` (HUK, Chip ID || "static string") |
| 136 | |
| 137 | The functions to get :ref:`hardware_unique_key` (HUK) and chip ID depends on the |
| 138 | platform implementation. Currently, in OP-TEE OS we only have a per-device key, |
| 139 | SSK, which is used for secure storage subsystem, but, for the future we might |
| 140 | need to create different per-device keys for different subsystems using the same |
| 141 | algorithm as we generate the SSK; An easy way to generate different per-device |
| 142 | keys for different subsystems is using different static strings to generate the |
| 143 | keys. |
| 144 | |
| 145 | Trusted Application Storage Key (TSK) |
| 146 | ===================================== |
| 147 | The TSK is a per-Trusted Application key, which is generated from the SSK and |
| 148 | the TA's identifier (UUID). It is used to protect the FEK, in other words, to |
| 149 | encrypt/decrypt the FEK. |
| 150 | |
| 151 | TSK is derived by: |
| 152 | |
| 153 | TSK = HMAC\ :sub:`SHA256` (SSK, TA_UUID) |
| 154 | |
| 155 | File Encryption Key (FEK) |
| 156 | ========================= |
| 157 | When a new TEE file is created, key manager will generate a new FEK by PRNG |
| 158 | (pesudo random number generator) for the TEE file and store the encrypted FEK in |
| 159 | meta file. FEK is used for encrypting/decrypting the TEE file information stored |
| 160 | in meta file or the data stored in block file. |
| 161 | |
| 162 | Hash Tree |
| 163 | ********* |
| 164 | The hash tree is responsible for handling data encryption and decryption of a |
| 165 | secure storage file. The hash tree is implemented as a binary tree where each |
| 166 | node (``struct tee_fs_htree_node_image`` below) in the tree protects its two |
| 167 | child nodes and a data block. The meta data is stored in a header (``struct |
| 168 | tee_fs_htree_image`` below) which also protects the top node. |
| 169 | |
| 170 | All fields (header, nodes, and blocks) are duplicated with two versions, 0 and |
| 171 | 1, to ensure atomic updates. See `core/tee/fs_htree.c`_ for details. |
| 172 | |
| 173 | Meta Data Encryption Flow |
| 174 | ========================= |
| 175 | .. figure:: ../images/secure_storage/meta_data_encryption.png |
| 176 | :figclass: align-center |
| 177 | |
| 178 | Meta data encryption |
| 179 | |
| 180 | A new meta IV will be generated by PRNG when a meta data needs to be updated. |
| 181 | The size of meta IV is defined in `core/include/tee/fs_htree.h`_, likewise are |
| 182 | the data structures of meta data and node data are defined in fs_htree.h as |
| 183 | follows: |
| 184 | |
| 185 | .. code-block:: c |
| 186 | |
| 187 | struct tee_fs_htree_node_image { |
| 188 | uint8_t hash[TEE_FS_HTREE_HASH_SIZE]; |
| 189 | uint8_t iv[TEE_FS_HTREE_IV_SIZE]; |
| 190 | uint8_t tag[TEE_FS_HTREE_TAG_SIZE]; |
| 191 | uint16_t flags; |
| 192 | }; |
| 193 | |
| 194 | struct tee_fs_htree_meta { |
| 195 | uint64_t length; |
| 196 | }; |
| 197 | |
| 198 | struct tee_fs_htree_imeta { |
| 199 | struct tee_fs_htree_meta meta; |
| 200 | uint32_t max_node_id; |
| 201 | }; |
| 202 | |
| 203 | struct tee_fs_htree_image { |
| 204 | uint8_t iv[TEE_FS_HTREE_IV_SIZE]; |
| 205 | uint8_t tag[TEE_FS_HTREE_TAG_SIZE]; |
| 206 | uint8_t enc_fek[TEE_FS_HTREE_FEK_SIZE]; |
| 207 | uint8_t imeta[sizeof(struct tee_fs_htree_imeta)]; |
| 208 | uint32_t counter; |
| 209 | }; |
| 210 | |
| 211 | Block Data Encryption Flow |
| 212 | ========================== |
| 213 | .. figure:: ../images/secure_storage/block_data_encryption.png |
| 214 | :figclass: align-center |
| 215 | |
| 216 | Block data encryption |
| 217 | |
| 218 | A new block IV will be generated by PRNG when a block data needs to be updated. |
| 219 | The size of block IV is defined in `core/include/tee/fs_htree.h`_. |
| 220 | |
| 221 | Atomic Operation |
| 222 | **************** |
| 223 | According to GlobalPlatform Trusted Storage requirement of the atomicity, the |
| 224 | following operations should support atomic update:: |
| 225 | |
| 226 | Write, Truncate, Rename, Create and Delete |
| 227 | |
| 228 | The strategy used in OP-TEE secure storage to guarantee the atomicity is |
| 229 | out-of-place update. |
| 230 | |
| 231 | .. _rpmb: |
| 232 | |
| 233 | RPMB Secure Storage |
| 234 | ******************* |
| 235 | This document describes the RPMB secure storage implementation in OP-TEE, which |
| 236 | is enabled by setting ``CFG_RPMB_FS=y``. Trusted Applications may use this |
| 237 | implementation by passing a storage ID equal to ``TEE_STORAGE_PRIVATE_RPMB``, or |
| 238 | ``TEE_STORAGE_PRIVATE`` if ``CFG_REE_FS`` is disabled. For details about RPMB, |
| 239 | please refer to the JEDEC eMMC specification (JESD84-B51). |
| 240 | |
| 241 | The architecture is depicted below. |
| 242 | |
| 243 | .. code-block:: none |
| 244 | |
| 245 | | NORMAL WORLD : SECURE WORLD | |
| 246 | : |
| 247 | U tee-supplicant : Trusted application |
| 248 | S (rpmb.c) : (secure storage API) |
| 249 | E ^ ^ : ^ |
| 250 | R | | : | |
| 251 | ~~~~~~~ ioctl ~~~~~~~|~~~~~~~~~~~~:~~~~~~~~~~~~~~~~~~|~~~~~~~~~~~~~~~~~~~~ |
| 252 | K | | : OP-TEE |
| 253 | E v v : (tee_svc_storage.c) |
| 254 | R MMC/SD subsys. OP-TEE driver : (tee_rpmb_fs.c, tee_fs_key_manager.c) |
| 255 | N ^ ^ : ^ |
| 256 | E | | : | |
| 257 | L v | : | |
| 258 | Controller driver | : | |
| 259 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~|~~~~~~~~~~~~~~~~~~~~~~~~|~~~~~~~~~~~~~~~~~~~~ |
| 260 | v v |
| 261 | Secure monitor / EL3 firmware |
| 262 | |
| 263 | For information about the ``ioctl()`` interface to the MMC/SD subsystem in the |
| 264 | Linux kernel, see the Linux core MMC header file `linux/mmc/core.h`_ and the |
| 265 | mmc-utils_ repository. |
| 266 | |
| 267 | The Secure Storage API |
| 268 | ====================== |
| 269 | This part is common with the REE-based filesystem. The interface between the |
| 270 | system calls in `core/tee/tee_svc_storage.c`_ and the RPMB filesystem is the |
| 271 | `tee_file_operations`, namely ``struct tee_file_ops``. |
| 272 | |
| 273 | The RPMB filesystem |
| 274 | =================== |
| 275 | The FS implementation is entirely in `core/tee/tee_rpmb_fs.c`_ and the RPMB |
| 276 | partition is divided in three parts: |
| 277 | |
| 278 | - The first 128 bytes are reserved for partition data (``struct |
| 279 | rpmb_fs_partition``). |
| 280 | |
| 281 | - At offset 512 is the File Allocation Table (FAT). It is an array of |
| 282 | ``struct rpmb_fat_entry`` elements, one per file. The FAT grows |
| 283 | dynamically as files are added to the filesystem. Among other things, each |
| 284 | entry has the start address for the file data, its size, and the filename. |
| 285 | |
| 286 | - Starting from the end of the RPMB partition and extending downwards is the |
| 287 | file data area. |
| 288 | |
| 289 | Space in the partition is allocated by the general-purpose allocator functions, |
| 290 | ``tee_mm_alloc(...)`` and ``tee_mm_alloc2(...)``. |
| 291 | |
| 292 | All file operations are atomic. This is achieved thanks to the following |
| 293 | properties: |
| 294 | |
| 295 | - Writing one single block of data to the RPMB partition is guaranteed to be |
| 296 | atomic by the eMMC specification. |
| 297 | |
| 298 | - The FAT block for the modified file is always updated last, after data |
| 299 | have been written successfully. |
| 300 | |
| 301 | - Updates to file content is done in-place only if the data do not span more |
| 302 | than the "reliable write block count" blocks. Otherwise, or if the file |
| 303 | needs to be extended, a new file is created. |
| 304 | |
| 305 | Device access |
| 306 | ============= |
| 307 | There is no eMMC controller driver in OP-TEE. The device operations all have to |
| 308 | go through the normal world. They are handled by the ``tee-supplicant`` process |
| 309 | which further relies on the kernel's ``ioctl()`` interface to access the device. |
| 310 | ``tee-supplicant`` also has an emulation mode which implements a virtual RPMB |
| 311 | device for test purposes. |
| 312 | |
| 313 | RPMB operations are the following: |
| 314 | - Reading device information (partition size, reliable write block count). |
| 315 | |
| 316 | - Programming the security key. This key is used for authentication |
| 317 | purposes. Note that it is different from the Secure Storage Key (SSK) |
| 318 | defined below, which is used for encryption. Like the SSK however, the |
| 319 | security key is also derived from a hardware unique key or identifier. |
| 320 | Currently, the function ``tee_otp_get_hw_unique_key()`` is used to |
| 321 | generate the RPMB security key. |
| 322 | |
| 323 | - Reading the write counter value. The write counter is used in the HMAC |
| 324 | computation during read and write requests. The value is read at |
| 325 | initialization time, and stored in ``struct tee_rpmb_ctx``, i.e., |
| 326 | ``rpmb_ctx->wr_cnt``. |
| 327 | |
| 328 | - Reading or writing blocks of data. |
| 329 | |
| 330 | RPMB operations are initiated on request from the FS layer. Memory buffers for |
| 331 | requests and responses are allocated in shared memory using |
| 332 | ``thread_rpc_alloc_payload(...)``. Buffers are passed to the normal world in |
| 333 | a ``TEE_RPC_RPMB_CMD`` message, thanks to the ``thread_rpc_cmd()`` function. |
| 334 | Most RPMB requests and responses use the data frame format defined by the JEDEC |
| 335 | eMMC specification. HMAC authentication is implemented here also. |
| 336 | |
| 337 | Encryption |
| 338 | ========== |
| 339 | The FS encryption routines are in `core/tee/tee_fs_key_manager.c`_. Block |
| 340 | encryption protects file data. The algorithm is 128-bit AES in Cipher Block |
| 341 | Chaining (CBC) mode with Encrypted Salt-Sector Initialization Vector (ESSIV), |
| 342 | see CBC-ESSIV_ for details. |
| 343 | |
| 344 | - During OP-TEE initialization, a 128-bit AES Secure Storage Key (SSK) is |
| 345 | derived from a :ref:`hardware_unique_key` (HUK). It is kept in secure |
| 346 | memory and never written to disk. A Trusted Application Storage Key is |
| 347 | derived from the SSK and the TA UUID. |
| 348 | |
| 349 | - For each file, a 128-bit encrypted File Encryption Key (FEK) is randomly |
| 350 | generated when the file is created, encrypted with the TSK and stored in |
| 351 | the FAT entry for the file. |
| 352 | |
| 353 | - Each 256-byte block of data is then encrypted in CBC mode. The |
| 354 | initialization vector is obtained by the ESSIV algorithm, that is, by |
| 355 | encrypting the block number with a hash of the FEK. This allows direct |
| 356 | access to any block in the file, as follows: |
| 357 | |
| 358 | .. code-block:: none |
| 359 | |
| 360 | FEK = AES-Decrypt(TSK, encrypted FEK); |
| 361 | k = SHA256(FEK); |
| 362 | IV = AES-Encrypt(128 bits of k, block index padded to 16 bytes) |
| 363 | Encrypted block = AES-CBC-Encrypt(FEK, IV, block data); |
| 364 | Decrypted block = AES-CBC-Decrypt(FEK, IV, encrypted block data); |
| 365 | |
| 366 | |
| 367 | SSK, TSK and FEK handling is common with the REE-based secure storage, while the |
| 368 | AES CBC block encryption is used only for RPMB (the REE implementation uses |
| 369 | GCM). The FAT is not encrypted. |
| 370 | |
| 371 | REE FS hash state |
| 372 | ================= |
| 373 | If configured with both ``CFG_REE_FS=y`` and ``CFG_RPMB_FS=y`` the REE FS will |
| 374 | create a special file, ``dirfile.db.hash`` in RPMB which hold a hash |
| 375 | representing the state of REE FS. |
| 376 | |
| 377 | Important caveats |
| 378 | ***************** |
| 379 | .. warning:: |
| 380 | Currently **no OP-TEE platform** is able to support retrieval of the |
| 381 | Hardware Unique Key or Chip ID required for secure operation. For all |
| 382 | platforms, a constant key is used, resulting in no protection against |
| 383 | decryption, or Secure Storage duplication to other devices. This is because |
| 384 | information about how to retrieve key data from the SoC is considered |
| 385 | sensitive by the vendors and it is not publicly available. |
| 386 | |
| 387 | In OP-TEE, there are APIs for reading keys generically from |
| 388 | One-Time-Programmable (OTP) memory. But there are no existing platform |
| 389 | implementations. |
| 390 | |
| 391 | To allow Secure Storage to operate securely on your platform, you must define |
| 392 | implementations in your platform code for: |
| 393 | |
| 394 | .. code-block:: c |
| 395 | |
| 396 | void tee_otp_get_hw_unique_key(struct tee_hw_unique_key *hwkey); |
| 397 | |
| 398 | int tee_otp_get_die_id(uint8_t *buffer, size_t len); |
| 399 | |
| 400 | These implementations should fetch the key data from your SoC-specific e-fuses, |
| 401 | or crypto unit according to the method defined by your SoC vendor. |
| 402 | |
| 403 | References |
| 404 | ********** |
| 405 | For more information about secure storage, please see SFO15-503, LAS16-504, |
| 406 | SFO17-309 at :ref:`presentations` and the :ref:`tee_internal_core_api` |
| 407 | specification. |
| 408 | |
| 409 | .. _CBC-ESSIV: https://en.wikipedia.org/wiki/Disk_encryption_theory#Cipher-block_chaining_(CBC) |
| 410 | .. _linux/mmc/core.h: https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/include/linux/mmc/core.h |
| 411 | .. _mmc-utils: http://git.kernel.org/cgit/linux/kernel/git/cjb/mmc-utils.git |
| 412 | |
| 413 | .. _core/tee/tee_svc_storage.c: https://github.com/OP-TEE/optee_os/blob/master/core/tee/tee_svc_storage.c |
| 414 | .. _core/tee/tee_ree_fs.c: https://github.com/OP-TEE/optee_os/blob/master/core/tee/tee_ree_fs.c |
| 415 | .. _core/tee/fs_htree.c: https://github.com/OP-TEE/optee_os/blob/master/core/tee/fs_htree.c |
| 416 | .. _core/include/tee/fs_htree.h: https://github.com/OP-TEE/optee_os/blob/master/core/include/tee/fs_htree.h |
| 417 | .. _core/tee/tee_fs_key_manager.c: https://github.com/OP-TEE/optee_os/blob/master/core/tee/tee_fs_key_manager.c |
| 418 | .. _core/tee/tee_rpmb_fs.c: https://github.com/OP-TEE/optee_os/blob/master/core/tee/tee_rpmb_fs.c |
| 419 | .. _lib/libutee/: https://github.com/OP-TEE/optee_os/blob/master/lib/libutee/ |