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