Raef Coles | 6b69255 | 2022-03-15 13:38:16 +0000 | [diff] [blame] | 1 | ################# |
| 2 | TF-M builtin keys |
| 3 | ################# |
| 4 | |
| 5 | :Author: Raef Coles |
| 6 | :Organization: Arm Limited |
| 7 | :Contact: raef.coles@arm.com |
| 8 | |
| 9 | ************ |
| 10 | Introduction |
| 11 | ************ |
| 12 | |
Antonio de Angelis | 01a93bc | 2023-01-20 11:17:14 +0000 | [diff] [blame] | 13 | When TF-M is integrated on a platform, the platform itself can provide several |
| 14 | keys for usage which are bound to the device instead of being owned by a |
| 15 | specific secure partition. When those keys are readable by the secure |
| 16 | processing environment, the platform must provide a function to load these keys |
| 17 | in the HAL layer, either loading them from OTP or another platform specific |
| 18 | location or subsystem. These keys are henceforth referred to as "builtin keys", |
| 19 | and might include (but are not limited to) the following: |
Raef Coles | 6b69255 | 2022-03-15 13:38:16 +0000 | [diff] [blame] | 20 | |
Antonio de Angelis | 01a93bc | 2023-01-20 11:17:14 +0000 | [diff] [blame] | 21 | 1. The Hardware Unique Key (HUK) |
| 22 | 2. The Initial Attestation Key (IAK) |
Raef Coles | 6b69255 | 2022-03-15 13:38:16 +0000 | [diff] [blame] | 23 | |
Antonio de Angelis | 01a93bc | 2023-01-20 11:17:14 +0000 | [diff] [blame] | 24 | The ``tfm_builtin_key_loader`` component implements a mechanism to discover |
| 25 | those keys and make them available to the PSA Crypto APIs for usage. Note that |
| 26 | if a key is stored in a subsystem which can't be read by the secure |
| 27 | processing environment, a full opaque driver must be used to be able to use |
| 28 | those keys through the PSA Crypto APIs. This document focuses only on the case |
| 29 | where the keys can be read by the SPE and processed by the driver described in |
| 30 | this document. |
| 31 | |
| 32 | In TF-M's legacy solution, the IAK is loaded by the attestation service as a |
| 33 | volatile key, which requires some key-loading logic to be implemented by that |
| 34 | partition. The HUK is not loaded in the crypto service, and is instead used by |
| 35 | an implementation of a TF-M specific KDF algorithm which then loads the key and |
| 36 | invokes Mbed TLS directly. Both solutions are far from ideal as they require an |
| 37 | effort to load (and duplicate) the keys per each user, or require a dedicated |
| 38 | code in TF-M that directly interacts with the HAL layer and invokes functions |
| 39 | from the crypto library bypassing the PSA Crypto interface. The aim of the |
| 40 | ``tfm_builtin_key_loader`` driver is to provide a uniform interface to use the |
| 41 | builtin keys available in a platform. |
| 42 | |
| 43 | Implementing a driver to deal with builtin keys allows to expand the legacy |
| 44 | solution for dealing with this type of keys in several ways. For example, it |
| 45 | avoid the need for partitions to implement dedicated mechanisms for probing the |
| 46 | HAL layer for builtin keys and load them as volatile. It removes the need to |
| 47 | have implementation specific call flows for deriving keys from the HUK (as that |
| 48 | requirement now is fulfilled by the driver itself transparently). It allows |
| 49 | uniform access to the keys also from the NS world (in any case, subject to the |
| 50 | policy dictated by the platform). Correctly abstracts away details of the key |
| 51 | handling mechanism from TF-M partitions into the PSA Crypto core key management |
| 52 | subsystem. |
Raef Coles | 6b69255 | 2022-03-15 13:38:16 +0000 | [diff] [blame] | 53 | |
| 54 | **************** |
| 55 | PSA builtin keys |
| 56 | **************** |
| 57 | |
| 58 | The PSA Cryptographic API provides a mechanism for accessing keys that are |
Antonio de Angelis | 01a93bc | 2023-01-20 11:17:14 +0000 | [diff] [blame] | 59 | stored in platform-specific locations (often hardware accelerators or OTP). A |
| 60 | builtin key is assigned a specific key_id, i.e. a handle, which is hardcoded at |
| 61 | build time and must be selected in the range [MBEDTLS_PSA_KEY_ID_BUILTIN_MIN, |
| 62 | MBEDLTS_PSA_KEY_ID_BUILTIN_MAX]. A user of the PSA Crypto API can reference |
| 63 | those keys directly by using these handles. It is up to the platform to specify |
| 64 | policy restrictions for specific users of the keys, e.g. an NS entity, or a |
| 65 | secure partition. The PSA Crypto core will then check those policies to grant |
| 66 | or deny access to the builtin key for that user. |
Raef Coles | 6b69255 | 2022-03-15 13:38:16 +0000 | [diff] [blame] | 67 | |
Antonio de Angelis | 01a93bc | 2023-01-20 11:17:14 +0000 | [diff] [blame] | 68 | ****************************** |
| 69 | PSA cryptoprocessor driver API |
| 70 | ****************************** |
Raef Coles | 6b69255 | 2022-03-15 13:38:16 +0000 | [diff] [blame] | 71 | |
Antonio de Angelis | 01a93bc | 2023-01-20 11:17:14 +0000 | [diff] [blame] | 72 | The PSA specification allows the PSA Crypto APIs to defer their operation to an |
| 73 | accelerator driver, through a mechanism described in the PSA cryptoprocessor |
| 74 | driver interface specification [1]_. This specification defines the concept of |
| 75 | PSA Crypto core, i.e. "An implementation of the PSA Cryptography API is |
| 76 | composed of a core and zero or more drivers". The PSA specification also has |
| 77 | the concept of storage locations for keys, through the type |
| 78 | ``psa_key_location_t``, which is used to access keys that don't have local |
| 79 | storage [2]_. This is leveraged mainly by opaque drivers mainly that use keys |
| 80 | for which the key material is not readable by the PSA crypto core layer. |
Raef Coles | 6b69255 | 2022-03-15 13:38:16 +0000 | [diff] [blame] | 81 | |
Antonio de Angelis | 01a93bc | 2023-01-20 11:17:14 +0000 | [diff] [blame] | 82 | TF-M defines a software driver called ``tfm_builtin_key_loader`` that provides |
| 83 | no acceleration but just defines a dedicated key location defined through the |
| 84 | ``TFM_BUILTIN_KEY_LOADER_KEY_LOCATION`` define. By resorting to the entry points |
| 85 | provided by this driver, the PSA Crypto core slot management subsystem can |
| 86 | access keys stored in the underlying platform, validate key usage policies and |
| 87 | allow PSA Crypto APIs to uniformly access builtin keys using the same call flows |
| 88 | used with traditional local-storage keys. |
Raef Coles | 6b69255 | 2022-03-15 13:38:16 +0000 | [diff] [blame] | 89 | |
Antonio de Angelis | 01a93bc | 2023-01-20 11:17:14 +0000 | [diff] [blame] | 90 | This is implemented by hooking the entry points defined by the driver into the |
| 91 | ``library/psa_crypto_driver_wrappers.c`` file provided by the PSA Crypto core. |
| 92 | This is currently done manually but eventually could be just autogenerated by |
| 93 | parsing a description of the driver entry points in the JSON format. These entry |
| 94 | points are: |
Raef Coles | 6b69255 | 2022-03-15 13:38:16 +0000 | [diff] [blame] | 95 | |
Antonio de Angelis | 01a93bc | 2023-01-20 11:17:14 +0000 | [diff] [blame] | 96 | 1. ``tfm_builtin_key_loader_init`` |
| 97 | 2. ``tfm_builtin_key_loader_get_key_buffer_size`` |
| 98 | 3. ``tfm_builtin_key_loader_get_builtin_key`` |
Raef Coles | 6b69255 | 2022-03-15 13:38:16 +0000 | [diff] [blame] | 99 | |
Antonio de Angelis | 01a93bc | 2023-01-20 11:17:14 +0000 | [diff] [blame] | 100 | The call flow for the entry points from the driver wrapper layer is as follows: |
Raef Coles | 6b69255 | 2022-03-15 13:38:16 +0000 | [diff] [blame] | 101 | |
Antonio de Angelis | 01a93bc | 2023-01-20 11:17:14 +0000 | [diff] [blame] | 102 | 1. During the driver initialisation phase started by the PSA Crypto Core init, |
| 103 | the ``tfm_builtin_key_loader_init`` function is called to probe the |
| 104 | platform HAL and retrieve the builtin keys. Those keys are described by |
| 105 | the types defined in the HAL layer interface header |
| 106 | ``tfm_plat_crypto_keys.h``. In particular global tables describing key |
| 107 | properties and user policies must be implemented by each platform and are |
| 108 | retrieved by the two accessor functions |
| 109 | ``tfm_plat_builtin_key_get_desc_table_ptr()`` and |
| 110 | ``tfm_plat_builtin_key_get_policy_table_ptr()``. The keys are loaded from |
| 111 | the platform in secure RAM in the TF-M Crypto partition with associated |
| 112 | metadata. It's worth to note that the keys are loaded through callback |
| 113 | functions which the platform lists in the key descriptor table. |
| 114 | 2. Once the TF-M Crypto service is initialised, at runtime it might receive a |
| 115 | request through an API call to use one of the builtin key IDs. Those IDs |
| 116 | are described in the ``tfm_builtin_key_ids.h`` header. Platforms can |
| 117 | override the default values providing their own header. |
| 118 | 3. When the PSA Crypto core in the ``psa_get_and_lock_key_slot()`` function |
| 119 | checks that the ``key_id`` being requested is in the builtin range region, |
| 120 | it probes the platform through the function |
| 121 | ``mbedtls_psa_platform_get_builtin_key`` which must be implemented by the |
| 122 | TF-M Crypto service library abstraction layer. This function just checks |
| 123 | the key descriptor table from the HAL to understand if such ``key_id`` is |
| 124 | available in the platform and what are the corresponding ``slot`` and |
| 125 | ``lifetime`` values associated to it. The lifetime contains the location of |
| 126 | the key, which determines which driver is responsible for dealing with it |
| 127 | (for the ``tfm_builtin_key_loader`` driver, that is |
| 128 | ``TFM_BUILTIN_KEY_LOADER_KEY_LOCATION``), while the ``slot`` value maps the |
| 129 | key to the slot in the driver internal storage. |
| 130 | 4. At this point, the PSA Crypto core knows that the key exists and is bound |
| 131 | to the location associated to the driver. By calling into the driver |
| 132 | wrappers layer is then able to retrieve the key attributes stored in the |
| 133 | platform for that key ID, and the size required to allocate in its |
| 134 | internal slot management system in order to load the key material in the |
| 135 | core. This is done by calling ``tfm_builtin_key_loader_get_builtin_key`` |
| 136 | just with a valid key attributes pointer (and nothing else), to retrieve |
| 137 | the attributes. Once the attributes are available, the required size is |
| 138 | retrieved through the driver wrapper by calling |
| 139 | ``tfm_builtin_key_loader_get_key_buffer_size``. |
| 140 | 5. At this stage, the slot management subsystem calls again into the driver |
| 141 | wrapper layer through ``tfm_builtin_key_loader_get_builtin_key`` with a |
| 142 | valid buffer to hold the key material returned by the |
| 143 | ``tfm_builtin_key_loader`` driver. When loading the key, the user |
| 144 | requiring that key_id is validated by the driver code against the policies |
| 145 | defined by the platform. If the policies match, the builtin key material |
| 146 | and metadata is loaded and is used like a transparent key available to the |
| 147 | PSA Crypto core slot management subsystem. |
Raef Coles | 6b69255 | 2022-03-15 13:38:16 +0000 | [diff] [blame] | 148 | |
| 149 | ***************** |
| 150 | Technical details |
| 151 | ***************** |
| 152 | |
| 153 | ------------------------------ |
| 154 | Builtin key IDs and overriding |
| 155 | ------------------------------ |
| 156 | |
Antonio de Angelis | 01a93bc | 2023-01-20 11:17:14 +0000 | [diff] [blame] | 157 | TF-M builtin key IDs are defined in |
| 158 | ``interface/include/crypto_keys/tfm_builtin_key_ids.h`` through the enum |
| 159 | ``tfm_key_id_builtin_t``. They are allocated inside the range that PSA |
| 160 | specifies for the builtin keys, i.e. between ``MBEDTLS_PSA_KEY_ID_BUILTIN_MIN`` |
| 161 | and ``MBEDLTS_PSA_KEY_ID_BUILTIN_MAX``. A platform can specify extra builtin key |
| 162 | IDs by setting the ``PLATFORM_DEFAULT_CRYPTO_KEYS`` variable to ``OFF``, |
| 163 | creating the header ``tfm_builtin_key_ids.h``, and specifying new keys and IDs. |
Raef Coles | 6b69255 | 2022-03-15 13:38:16 +0000 | [diff] [blame] | 164 | |
| 165 | -------------------------- |
| 166 | Builtin key access control |
| 167 | -------------------------- |
| 168 | |
Antonio de Angelis | 01a93bc | 2023-01-20 11:17:14 +0000 | [diff] [blame] | 169 | A builtin key is accessible by all callers since the ``key_id`` associated to it |
| 170 | is public information. Access to the keys must be mediated, which is done by |
| 171 | matching the user requesting the ``key_id`` against the policies available for |
| 172 | that user on that particular key in the policy table. If no policies are |
| 173 | specified for a specific combination of user and ``key_id``, the usage flags in |
| 174 | the key attributes will be all set to zeros, meaning the key will be unusable |
| 175 | for any operation for that particular user. |
Raef Coles | 6b69255 | 2022-03-15 13:38:16 +0000 | [diff] [blame] | 176 | |
| 177 | ------------------------------ |
| 178 | Multi-partition key derivation |
| 179 | ------------------------------ |
| 180 | |
| 181 | The HUK is used for key derivation by any secure partition or NS caller that |
| 182 | requires keys that are bound to a particular context. For example, Protected |
| 183 | Storage derives keys uniquely for each user of the service which are used to |
Antonio de Angelis | 01a93bc | 2023-01-20 11:17:14 +0000 | [diff] [blame] | 184 | encrypt user files. In order to provide HUK derivation to every secure |
Raef Coles | 6b69255 | 2022-03-15 13:38:16 +0000 | [diff] [blame] | 185 | partition / NS caller, it must be ensured that no service that utilises HUK |
Antonio de Angelis | 01a93bc | 2023-01-20 11:17:14 +0000 | [diff] [blame] | 186 | derivation can derive the same key as another service (simply by using the same |
| 187 | inputs for the KDF APIs, i.e. accessing the same base key for derivation). |
Raef Coles | 6b69255 | 2022-03-15 13:38:16 +0000 | [diff] [blame] | 188 | |
| 189 | This is accomplished by deriving a further "platform key" for each builtin key |
Antonio de Angelis | 01a93bc | 2023-01-20 11:17:14 +0000 | [diff] [blame] | 190 | that has ``PSA_KEY_USAGE_DERIVE`` set in its attributes. These platform keys |
| 191 | are derived from the builtin key, using the partition ID as a KDF input, and |
| 192 | can then be used for safely for further derivations by the user, without risks |
| 193 | to derive the same keys as other users. This is enforced directly by the |
| 194 | ``tfm_builtin_key_loader`` driver. |
Raef Coles | 6b69255 | 2022-03-15 13:38:16 +0000 | [diff] [blame] | 195 | |
| 196 | .. Note:: |
| 197 | If the NS client ID feature is disabled, all NS callers share a partition ID |
| 198 | of ``-1``, and therefore will share a platform key and be therefore be able |
| 199 | to derive the same keys as other NS callers. |
| 200 | |
| 201 | For keys that are not exposed outside the device, this is transparent to the |
| 202 | service that is using the key derivation, as they have no access to the builtin |
| 203 | key material and cannot distinguish between keys derived directly from it and |
| 204 | keys derived from the platform key. For some builtin keys, deriving platform |
| 205 | keys is not acceptable, as the key is used outside the device (i.e. the IAK |
| 206 | public key is used to verify attestation tokens) so the actual builtin key is |
| 207 | used. |
| 208 | |
| 209 | The decision has been taken to derive platform keys for any key that can be used |
| 210 | for key derivation (``PSA_KEY_USAGE_DERIVE``), and not derive platform keys |
| 211 | otherwise. For builtin keys that do not derive platform keys but are directly |
| 212 | used, care must be taken with access control where multiple partitions have |
Antonio de Angelis | 01a93bc | 2023-01-20 11:17:14 +0000 | [diff] [blame] | 213 | access to the same raw key material. |
Raef Coles | 6b69255 | 2022-03-15 13:38:16 +0000 | [diff] [blame] | 214 | |
| 215 | --------------------------------- |
| 216 | Mbed TLS transparent builtin keys |
| 217 | --------------------------------- |
| 218 | |
| 219 | Mbed TLS does not natively support transparent builtin keys (transparent keys |
Antonio de Angelis | 01a93bc | 2023-01-20 11:17:14 +0000 | [diff] [blame] | 220 | are keys where the key material is directly accessible by the PSA Crypto core), |
Raef Coles | 6b69255 | 2022-03-15 13:38:16 +0000 | [diff] [blame] | 221 | so some modifications had to be made. Opaque keyslots have the same basic |
Antonio de Angelis | 01a93bc | 2023-01-20 11:17:14 +0000 | [diff] [blame] | 222 | structure as standard transparent key slots, and can be passed to the functions |
| 223 | usually reserved for transparent keys, though this is a private implementation |
| 224 | detail of the mbed TLS library and is not specified in the driver interface. |
| 225 | Therefore, the only modification required currently is to allow keys that have |
| 226 | the location ``TFM_BUILTIN_KEY_LOADER_KEY_LOCATION`` to be passed to the |
| 227 | functions that usually accept transparent keys only, i.e. with the location |
| 228 | ``PSA_KEY_LOCATION_LOCAL_STORAGE``. This is due to the fact that the standard |
| 229 | assumption of the PSA Crypto core is that, if a driver that provides an |
| 230 | additional location, will also provide dedicated cryptographic mechanisms to act |
| 231 | on those keys, but this is not the case of the ``tfm_builtin_key_loader``, as it |
| 232 | just provides a mechanism to load keys (which act as a transparent key with |
| 233 | local storage, once loaded), but mbed TLS does not support such "transparent |
| 234 | builtin key" concept. |
| 235 | |
| 236 | References |
| 237 | ---------- |
| 238 | |
| 239 | .. [1] PSA cryptoprocessor driver interface: \ https://github.com/Mbed-TLS/mbedtls/blob/development/docs/proposed/psa-driver-interface.md |
| 240 | .. [2] Definition of psa_key_location_t type in the PSA spec: \ https://armmbed.github.io/mbed-crypto/html/api/keys/lifetimes.html#c.psa_key_location_t |
Raef Coles | 6b69255 | 2022-03-15 13:38:16 +0000 | [diff] [blame] | 241 | |
| 242 | -------------- |
| 243 | |
Antonio de Angelis | 01a93bc | 2023-01-20 11:17:14 +0000 | [diff] [blame] | 244 | *Copyright (c) 2022-2023, Arm Limited. All rights reserved.* |