Galanakis, Minos | 41f8597 | 2019-09-30 15:56:40 +0100 | [diff] [blame] | 1 | ====================================== |
| 2 | Internal Trusted Storage (ITS) Service |
| 3 | ====================================== |
Jamie Fox | 6925765 | 2019-07-03 17:53:13 +0100 | [diff] [blame] | 4 | |
| 5 | :Author: Jamie Fox |
| 6 | :Organization: Arm Limited |
| 7 | :Contact: Jamie Fox <jamie.fox@arm.com> |
| 8 | :Status: Accepted |
| 9 | |
| 10 | PSA Internal Trusted Storage |
| 11 | ============================ |
| 12 | PSA Internal Trusted Storage (ITS) is a PSA RoT Service for storing the most |
| 13 | security-critical device data (e.g. cryptographic keys) in internal storage, |
| 14 | which is trusted to provide data confidentiality and authenticity. This |
| 15 | contrasts with PSA Protected Storage, which is an Application RoT service that |
| 16 | allows larger data sets to be stored securely in external flash, with the option |
| 17 | for encryption, authentication and rollback protection to protect the |
| 18 | data-at-rest. |
| 19 | |
| 20 | Current TF-M Secure Storage |
| 21 | =========================== |
| 22 | Currently, the TF-M Secure Storage service implements PSA Protected Storage |
| 23 | version 1.0-beta2. There is not yet an implementation of PSA Internal Trusted |
| 24 | Storage in TF-M. |
| 25 | |
| 26 | New TF-M service |
| 27 | ================ |
| 28 | The proposal is to implement the *PSA Internal Trusted Storage API* with the |
| 29 | *TF-M Internal Trusted Storage service*. It can be abbreviated to *TF-M ITS |
| 30 | service* in general and to ``its`` in code. This name has the advantage of |
| 31 | making clear the correspondence between the service and the API it implements. |
| 32 | |
| 33 | If this name is adopted, then it may make sense to rename the *Secure Storage |
| 34 | service* to the *Protected Storage service* in the future to match. Then "secure |
| 35 | storage" could refer to the two services as a collective. |
| 36 | |
| 37 | The TF-M ITS service will implement PSA ITS version 1.0. It will be provided by |
| 38 | a separate partition to Protected Storage, for a couple of reasons: |
| 39 | |
| 40 | - To permit isolation between the services. |
| 41 | |
| 42 | - ITS is a PSA RoT Service, while Protected Storage is an Application RoT |
| 43 | Service. |
| 44 | |
| 45 | - To avoid circular dependencies. |
| 46 | |
| 47 | - The PSA Firmware Framework does not permit circular dependencies between |
| 48 | partitions, which would occur if Protected Storage and ITS were provided by |
| 49 | the same partition. Protected Storage depends on Crypto, which in turn |
| 50 | depends on ITS. |
| 51 | |
| 52 | The existing SST filesystem will be reused to provide the backend of the |
| 53 | service, with the flash layer modified to direct storage to internal flash, |
| 54 | rather than external. |
| 55 | |
| 56 | Compared to Protected Storage, encryption, authentication and rollback |
| 57 | protection are not required, so the SST encrypted object layer and the crypto |
| 58 | and NV counter interfaces are not required. The rollback protection feature of |
| 59 | the object table is also not required. |
| 60 | |
| 61 | Code structure |
| 62 | ============== |
| 63 | The code structure of the service will be as follows: |
| 64 | |
Kevin Peng | 1a2f365 | 2020-07-30 15:17:05 +0800 | [diff] [blame] | 65 | TF-M repo: |
| 66 | |
Jamie Fox | 6925765 | 2019-07-03 17:53:13 +0100 | [diff] [blame] | 67 | ``interface/`` |
| 68 | |
| 69 | - ``include/psa/internal_trusted_storage.h`` - PSA ITS API |
| 70 | - ``src/tfm_its_api.c`` - PSA ITS API implementation for NSPE |
| 71 | |
| 72 | ``secure_fw/ns_callable/tfm_veneers.c`` - ITS veneers (auto-generated from |
| 73 | manifest) |
| 74 | |
Ken Liu | 738a4b0 | 2020-06-04 14:52:38 +0800 | [diff] [blame] | 75 | ``secure_fw/partitions/internal_trusted_storage/`` |
Jamie Fox | 6925765 | 2019-07-03 17:53:13 +0100 | [diff] [blame] | 76 | |
| 77 | - ``tfm_internal_trusted_storage.yaml`` - Partition manifest |
| 78 | - ``tfm_its_secure_api.c`` - PSA ITS API implementation for SPE |
| 79 | - ``tfm_its_req_mngr.c`` - Uniform secure functions and IPC request handlers |
| 80 | - ``tfm_internal_trusted_storage.h`` - TF-M ITS API (with client_id parameter) |
| 81 | - ``tfm_internal_trusted_storage.c`` - TF-M ITS implementation, using the |
| 82 | flash_fs as a backend |
| 83 | - ``flash_fs/`` - Filesystem |
| 84 | - ``flash/`` - Flash interface |
| 85 | |
Kevin Peng | 1a2f365 | 2020-07-30 15:17:05 +0800 | [diff] [blame] | 86 | tf-m-tests repo: |
| 87 | |
Jamie Fox | 6925765 | 2019-07-03 17:53:13 +0100 | [diff] [blame] | 88 | ``test/suites/its/`` |
| 89 | |
| 90 | - ``non_secure/psa_its_ns_interface_testsuite.c`` - Non-secure interface tests |
| 91 | - ``secure/psa_its_s_interface_testsuite.c`` - Secure interface tests |
| 92 | |
| 93 | TF-M ITS implementation |
| 94 | ----------------------- |
| 95 | The following APIs will be exposed by ``tfm_internal_trusted_storage.h``:: |
| 96 | |
| 97 | psa_status_t tfm_its_init(void); |
| 98 | |
| 99 | psa_status_t tfm_its_set(int32_t client_id, |
| 100 | psa_storage_uid_t uid, |
| 101 | size_t data_length, |
| 102 | const void *p_data, |
| 103 | psa_storage_create_flags_t create_flags); |
| 104 | |
| 105 | psa_status_t tfm_its_get(int32_t client_id, |
| 106 | psa_storage_uid_t uid, |
| 107 | size_t data_offset, |
| 108 | size_t data_size, |
| 109 | void *p_data, |
| 110 | size_t *p_data_length); |
| 111 | |
| 112 | psa_status_t tfm_its_get_info(int32_t client_id, |
| 113 | psa_storage_uid_t uid, |
| 114 | struct psa_storage_info_t *p_info); |
| 115 | |
| 116 | psa_status_t tfm_its_remove(int32_t client_id, |
| 117 | psa_storage_uid_t uid); |
| 118 | |
| 119 | That is, the TF-M ITS APIs will have the same prototypes as the PSA ITS APIs, |
| 120 | but with the addition of a ``client_id`` parameter, which will be passed from |
| 121 | the ITS request manager. A ``tfm_its_init`` function will also be present, which |
| 122 | will be called at initialisation time and not exposed through a veneer or SID. |
| 123 | |
| 124 | The implementation in ``tfm_internal_trusted_storage.c`` must validate the |
| 125 | parameters (excepting memory references, which are validated by the SPM), |
| 126 | translate the UID and client ID into a file ID and then make appropriate calls |
| 127 | to the filesystem layer. It must also take care ensure that any PSA Storage |
| 128 | flags associated with the UID are honoured. |
| 129 | |
| 130 | Filesystem |
| 131 | ---------- |
| 132 | The ITS filesystem will be copied and modified from the SST filesystem. The |
| 133 | modifications required will be to rename symbols from ``sst`` to ``its`` and to |
| 134 | update the implementation to be aligned with the latest version of the PSA |
| 135 | Storage spec (which consists mainly of moving to the ``psa_status_t`` error type |
| 136 | and using common error codes from ``psa/error.h``). |
| 137 | |
| 138 | The filesystem will also be modified to align the size of each file stored to |
| 139 | the alignment requirement exposed by the flash interface, by adding appropriate |
| 140 | padding. |
| 141 | |
| 142 | The filesystem code will be de-duplicated again once the ITS service is |
| 143 | implemented (see below). |
| 144 | |
| 145 | Flash layer |
| 146 | ----------- |
| 147 | The flash layer will be copied from SST, and modified to direct writes to the |
| 148 | internal flash device. It too needs to be updated to use ``psa_status_t`` error |
| 149 | types. |
| 150 | |
| 151 | Platform layer |
| 152 | -------------- |
| 153 | The TF-M platform layer must be be updated to distinguish between the external |
| 154 | flash device used for Protected Storage and internal flash device used for ITS. |
| 155 | A flash region for the relevant storage service needs to be allocated in each. |
| 156 | |
| 157 | On test platforms these may just be two distinct regions of the same flash |
| 158 | device, but in general they will separate devices with their own drivers. |
| 159 | |
| 160 | Detailed design considerations |
| 161 | ============================== |
| 162 | |
| 163 | Mapping UID onto file ID |
| 164 | ------------------------ |
| 165 | The ITS APIs identify assets with 64-bit UIDs, to which the ITS service must |
| 166 | append the 32-bit client ID of the calling partition for access control. The |
| 167 | existing filesystem uses 32-bit file IDs to identify files, so some mapping |
| 168 | would be required to convert between the identifiers. |
| 169 | |
| 170 | SST uses the object table to do the mapping from client ID, UID pairs to file |
| 171 | IDs, which means making an extra filesystem read/write for each get/set |
| 172 | operation. This mapping has minimal overhead for SST though, because object |
| 173 | table lookups are already required for rollback protection. |
| 174 | |
| 175 | For ITS, no rollback protection feature is required, so there are two options: |
| 176 | |
| 177 | - Keep a simplified version of the SST object table that just maps from |
| 178 | (client ID, UID) to file ID |
| 179 | |
| 180 | - Modify the filesystem to take (at least) 96-bit file IDs, in the form of a |
| 181 | fixed-length char buffer. |
| 182 | |
| 183 | The advantage of the former is that it would require no extra modification to |
| 184 | the existing filesystem code, and the existing SST object table could be cut |
| 185 | down for ITS. However, it would mean that every ITS request would invoke twice |
| 186 | the number of filesystem operations, increasing latency and flash wear. The code |
| 187 | size of the ITS partition would be increased, as would RAM usage as the table |
| 188 | would need to be read into RAM. |
| 189 | |
| 190 | The latter option would make the filesystem slightly more complex: the size of a |
| 191 | metadata entry would be increased by 64-bits and the 96-bit fids would need to |
| 192 | be copied and compared with ``memcpy`` and ``memcmp`` calls. On the other hand, |
| 193 | mapping onto file IDs would incur only the cost of copying the UID and client ID |
| 194 | values into the file ID buffer. |
| 195 | |
| 196 | A third, even more general, solution would be to use arbitrary-length |
| 197 | null-terminated strings as the file IDs. This is the standard solution in |
| 198 | full-featured filesystems, but we do not currently require this level of |
| 199 | complexity in secure storage. |
| 200 | |
| 201 | With this in mind, the proposed option is the second. |
| 202 | |
| 203 | Storing create flags |
| 204 | -------------------- |
| 205 | The ITS APIs provide a 32-bit ``create_flags`` parameter, which contains bit |
| 206 | flags that determine the properties of the stored data. Only one flag is |
| 207 | currently defined for ITS: ``PSA_STORAGE_FLAG_WRITE_ONCE``, which prevents a UID |
| 208 | from being modified or deleted after it is set for the first time. |
| 209 | |
| 210 | There are two places that these flags could be stored: in the file data or as |
| 211 | part of the file metadata. |
| 212 | |
| 213 | For the first option, the ITS implementation would need to copy to the flags |
| 214 | into the buffer containing the data, and adjust the size accordingly, for each |
| 215 | set operation, and the reverse for each get. Every get_info operation would need |
| 216 | to read some of the file data, rather than just the metadata, implying a second |
| 217 | flash read. A potential downside is that many of the cryptographic assets stored |
| 218 | in ITS will be aligned to power-of-two sizes; adding an extra 32-bits would |
| 219 | misalign the size, which may reduce flash performance or necessitate adding |
| 220 | padding to align to the flash page size. |
| 221 | |
| 222 | To implement the second option, a 32-bit ``flag`` field would be added to the |
| 223 | filesystem's metadata structure, whose interpretation is defined by the user. |
| 224 | This field would clearly be catered towards the PSA Storage APIs, even if |
| 225 | nominally generic, and alternative filesystems may not have any such field. |
| 226 | However, it is a more intuitive solution and would simplify both flash alignment |
| 227 | and get_info operations. |
| 228 | |
| 229 | Overall, it seems more beneficial to store the flags in the metadata, so this is |
| 230 | the proposed solution. |
| 231 | |
| 232 | Code sharing between Protected Storage and ITS |
| 233 | ---------------------------------------------- |
| 234 | To de-duplicate the filesystem code used by both Protected Storage and ITS, it |
| 235 | is proposed that Protected Storage calls ITS APIs as its backend filesystem. |
| 236 | |
| 237 | Protected Storage essentially becomes an encryption, authentication and rollback |
| 238 | protection layer on top of ITS. It makes IPC requests or secure function calls |
| 239 | to the ITS service to do filesystem operations on its behalf. |
| 240 | |
| 241 | This has a couple of advantages: |
| 242 | |
| 243 | - It shrinks Protected Storage's stack size, because the filesystem and flash |
| 244 | layer stack is only in ITS. |
| 245 | |
| 246 | - It automatically solves the problem of ensuring mutual exclusion in the |
| 247 | filesystem and flash layers when Protected Storage and ITS are called |
| 248 | concurrently. The second request to ITS will just be made to wait by the SPM. |
| 249 | |
| 250 | The disadvantage of this approach is that it will increase the latency of |
| 251 | Protected Storage requests, due to the extra overhead associated with making a |
| 252 | second IPC request or secure function call. It also limits Protected Storage to |
| 253 | using only the ITS APIs, unless extra veneers are added solely for Protected |
| 254 | Storage to use. This, for example, prevents Protected Storage from doing partial |
| 255 | writes to file without reading and re-writing the whole file. |
| 256 | |
| 257 | ITS will need to be modified to direct calls from Protected Storage to a |
| 258 | different flash device. It can use the client ID to detect when the caller is |
| 259 | Protected Storage, and pass down the identity of the flash device to use to the |
| 260 | flash layer, which then calls the appropriate driver. |
| 261 | |
| 262 | An open question is what to do if Protected Storage itself wants to store |
| 263 | something in internal storage in the future (e.g. rollback counters, hash |
| 264 | tree/table or top hash). A couple of possible solutions would be: |
| 265 | |
| 266 | - Divide up the UIDs, so certain UIDs from Protected Storage refer to assets in |
| 267 | internal storage, and others to ones in external storage. |
| 268 | |
| 269 | - Use the ``type`` field of ``psa_call`` in IPC model and extra veneers in |
| 270 | library model to distinguish between internal and external storage requests. |
| 271 | |
| 272 | The other option for code sharing would be for Protected Storage and ITS to |
| 273 | directly share filesystem code, which would be placed in a shared code region. |
| 274 | With this approach, mutual exclusion to the flash device would need to be |
| 275 | implemented separately, as would some way of isolating static memory belonging |
| 276 | to each partition but not the code. Because of these complications, this option |
| 277 | has not been considered further at this time. |
| 278 | |
| 279 | -------------- |
| 280 | |
| 281 | *Copyright (c) 2019, Arm Limited. All rights reserved.* |