blob: c27d2ca1cf24b52d2104a7ac6e561e283cb49333 [file] [log] [blame]
#################
TF-M builtin keys
#################
:Author: Raef Coles
:Organization: Arm Limited
:Contact: raef.coles@arm.com
************
Introduction
************
TF-M has several keys that are bound to the device itself instead of a secure
partition. These keys must be accessed through a HAL function, either loading
them from OTP or another platform-specific location. These keys are henceforth
referred to as "builtin keys", and include (but are not limited to):
1) The Hardware Unique Key (HUK)
2) The Initial Attestation Key (IAK)
Currently, the IAK is loaded by the attestation partition as a transient key,
which requires some key-loading logic to be implemented by that partition. The
HUK is not loaded in the crypto service, and is instead used by an
implementation of a TF-M specific KDF algorithm which then loads the key and
invokes Mbed TLS directly.
****************
PSA builtin keys
****************
The PSA Cryptographic API provides a mechanism for accessing keys that are
stored in platform-specific locations (often hardware accelerators or OTP). One
of the properties of builtin keys is that they are accessed via a predefined
handle, which can be leveraged to allow TF-M to define a set of handles for the
builtin keys that it provides.
Defining these constant handles allows these keys to be used by secure partition
and non-secure callers (subject to access policy), via the standard PSA crypto
interfaces.
Ideally, it would be possible to just have PSA builtin keys that are stored in
crypto service RAM, in the same way that volatile keys are. Mbed TLS does not
support this and only supports builtin keys as part of the code flow that
interfaces with hardware accelerators.
*********************
PSA crypto driver API
*********************
The PSA crypto driver API allows most PSA Crypto APIs to defer their operation
to an accelerator driver in preference of the software implementation. It also
adds the concept of storage locations for keys, which is used to access keys
stored on hardware accelerators.
The TF-M builtin keys code leverages the PSA crypto driver API by creating a new
driver that provides no acceleration, only a key storage location. This storage
location is not backed by hardware, but is instead inside the RAM of the crypto
partition.
This is done by hooking two functions into the
``library/psa_crypto_driver_wrappers.c`` file. These functions are:
1) ``tfm_key_loader_get_builtin_key``
2) ``tfm_key_loader_get_builtin_key_len``
The flow for these functions being used is:
1) A request is made to a PSA Crypto API that references a key by a key
handle.
2) The PSA Crypto core layer checks that the handle is inside the builtin keys
region, and then if the key has not yet been loaded into a transient Mbed
TLS keyslot calls ``tfm_plat_builtin_key_get_lifetime_and_slot`` (which is a
wrapper around ``mbedtls_psa_platform_get_builtin_key``), which is defined
in ``crypto_keys.h``. This function maps each builtin key to a driver, which
in most cases is the default ``tfm_builtin_key_loader`` via
``TFM_BUILTIN_KEY_LOADER_KEY_LOCATION``. The function also returns a slot
number, which is a driver-specific index to specify the key.
3) This location and slot index then calls
``psa_driver_wrapper_get_builtin_key``, which for the key location
``TFM_BUILTIN_KEY_LOADER_KEY_LOCATION`` (the new location value that is bound
to the TF-M builtin keys driver) calls the previously hooked function
``tfm_key_loader_get_builtin_key``.
4) This function, along with its counterpart
``tfm_key_loader_get_builtin_key_len``, allow Mbed TLS to copy the
key material into an internal keyslot, which is then used whenever further
calls to using that same builtin key ID are made.
In order to load the keys into the tfm_key_loader memory (in the crypto
partition), ``crypto_keys.h`` defines a function ``tfm_plat_load_builtin_keys``
which is responsible for loading all builtin keys into and driver that requires
loading.
*****************
Technical details
*****************
------------------------------
Builtin key IDs and overriding
------------------------------
TF-M builtin key IDs are defined in ``interface/include/tfm_crypto_defs.h`` by
the enum ``tfm_key_id_builtin_t``. They are allocated inside the range that PSA
considers to be builtin keys. A platform can specify extra builtin key IDs by
setting the ``PLATFORM_DEFAULT_CRYPTO_KEYS`` variable to ``OFF``, creating the
header ``platform_builtin_key_ids.h``, and specifying new keys and IDs.
--------------------------
Builtin key access control
--------------------------
Builtin keys by default can be used by any caller since the key handle is
public information. TF-M must mediate access to the keys, which is done in the
function ``tfm_plat_builtin_key_get_usage`` (part of ``crypto_keys.h``). This
function maps the caller ID to a particular key usage, which allows granular key
permissions. The function returns ``PSA_ERROR_NOT_PERMITTED`` if a caller does
not have permission to use the key.
------------------------------
Multi-partition key derivation
------------------------------
The HUK is used for key derivation by any secure partition or NS caller that
requires keys that are bound to a particular context. For example, Protected
Storage derives keys uniquely for each user of the service which are used to
encrypt each user's files. In order to provide HUK derivation to every secure
partition / NS caller, it must be ensured that no service that utilises HUK
derivation can derive the same key as another service (simply by inputting the
same KDF inputs).
This is accomplished by deriving a further "platform key" for each builtin key
that can be used for key derivation. These platform keys are derived from the
builtin key, using the partition ID as a KDF input, and can then be used for
further derivation by the partition (or NS caller) with the further derived keys
being unique for each partition even if the KDF inputs are the same.
.. Note::
If the NS client ID feature is disabled, all NS callers share a partition ID
of ``-1``, and therefore will share a platform key and be therefore be able
to derive the same keys as other NS callers.
For keys that are not exposed outside the device, this is transparent to the
service that is using the key derivation, as they have no access to the builtin
key material and cannot distinguish between keys derived directly from it and
keys derived from the platform key. For some builtin keys, deriving platform
keys is not acceptable, as the key is used outside the device (i.e. the IAK
public key is used to verify attestation tokens) so the actual builtin key is
used.
The decision has been taken to derive platform keys for any key that can be used
for key derivation (``PSA_KEY_USAGE_DERIVE``), and not derive platform keys
otherwise. For builtin keys that do not derive platform keys but are directly
used, care must be taken with access control where multiple partitions have
access.
---------------------------------
Mbed TLS transparent builtin keys
---------------------------------
Mbed TLS does not natively support transparent builtin keys (transparent keys
are keys where the key material is directly accessible to the PSA Crypto core),
so some modifications had to be made. Opaque keyslots have the same basic
structure as standard transparent keyslots, and can be passed to the functions
usually reserved for transparent keys, though this behaviour is not defined and
may not continue to work in future versions. Therefore, the only modification
required currently is to force keys that have the location
``TFM_BUILTIN_KEY_LOADER_KEY_LOCATION`` to be passed to the functions that only
usually accept keys with the location ``PSA_KEY_LOCATION_LOCAL_STORAGE``.
--------------
*Copyright (c) 2022, Arm Limited. All rights reserved.*