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