aboutsummaryrefslogtreecommitdiff
path: root/secure_fw/partitions
diff options
context:
space:
mode:
authorRaef Coles <raef.coles@arm.com>2022-03-02 13:48:20 +0000
committerAnton Komlev <Anton.Komlev@arm.com>2022-08-07 23:42:33 +0200
commit79809c74f163c4b67b2dcb9b4be69b19b6d494fe (patch)
treecee5def6bed05c180bb70753a7f3f0de10a03805 /secure_fw/partitions
parent6e8dfd2cbad9075f101046dc3c085df41c1ba004 (diff)
downloadtrusted-firmware-m-79809c74f163c4b67b2dcb9b4be69b19b6d494fe.tar.gz
Crypto: Implement PSA builtin keys
Implement builtin key driver, and add HAL apis to load HUK and IAK into this driver. Add necessary funtions to route PSA crypto calls into this driver. Add fixed builtin key IDs into the interface, and a mechanism to allow platforms to add extra keys. Change-Id: I7ffc16eb14215dd6b323baeb53b40ccb1c0ce126 Signed-off-by: Raef Coles <raef.coles@arm.com>
Diffstat (limited to 'secure_fw/partitions')
-rw-r--r--secure_fw/partitions/crypto/CMakeLists.txt10
-rw-r--r--secure_fw/partitions/crypto/crypto_init.c14
-rw-r--r--secure_fw/partitions/crypto/psa_driver_api/tfm_builtin_key_loader.c208
-rw-r--r--secure_fw/partitions/crypto/psa_driver_api/tfm_builtin_key_loader.h78
-rw-r--r--secure_fw/partitions/crypto/tfm_mbedcrypto_builtin_keys.c31
5 files changed, 340 insertions, 1 deletions
diff --git a/secure_fw/partitions/crypto/CMakeLists.txt b/secure_fw/partitions/crypto/CMakeLists.txt
index c7926931a2..7721daf66e 100644
--- a/secure_fw/partitions/crypto/CMakeLists.txt
+++ b/secure_fw/partitions/crypto/CMakeLists.txt
@@ -27,6 +27,8 @@ target_sources(tfm_psa_rot_partition_crypto
crypto_key_derivation.c
crypto_key_management.c
crypto_rng.c
+ tfm_mbedcrypto_builtin_keys.c
+ $<$<BOOL:CRYPTO_TFM_BUILTIN_KEYS_DRIVER>:psa_driver_api/tfm_builtin_key_loader.c>
)
# The generated sources
@@ -72,6 +74,9 @@ target_compile_definitions(tfm_psa_rot_partition_crypto
$<$<BOOL:${CRYPTO_ASYM_SIGN_MODULE_DISABLED}>:TFM_CRYPTO_ASYM_SIGN_MODULE_DISABLED>
$<$<BOOL:${CRYPTO_ASYM_ENCRYPT_MODULE_DISABLED}>:TFM_CRYPTO_ASYM_ENCRYPT_MODULE_DISABLED>
$<$<BOOL:${CRYPTO_KEY_DERIVATION_MODULE_DISABLED}>:TFM_CRYPTO_KEY_DERIVATION_MODULE_DISABLED>
+ MBEDTLS_PSA_CRYPTO_DRIVERS
+ MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS
+ $<$<BOOL:CRYPTO_BUILTIN_KEYS>:PSA_CRYPTO_DRIVER_TFM_BUILTIN_KEY>
PRIVATE
$<$<BOOL:${CRYPTO_ENGINE_BUF_SIZE}>:TFM_CRYPTO_ENGINE_BUF_SIZE=${CRYPTO_ENGINE_BUF_SIZE}>
$<$<BOOL:${CRYPTO_CONC_OPER_NUM}>:TFM_CRYPTO_CONC_OPER_NUM=${CRYPTO_CONC_OPER_NUM}>
@@ -142,6 +147,10 @@ target_compile_definitions(crypto_service_mbedcrypto_config
$<$<OR:$<STREQUAL:${TFM_SYSTEM_ARCHITECTURE},armv8-m.base>,$<STREQUAL:${TFM_SYSTEM_ARCHITECTURE},armv6-m>>:MULADDC_CANNOT_USE_R7>
$<$<BOOL:${CRYPTO_NV_SEED}>:CRYPTO_NV_SEED>
$<$<BOOL:${PLATFORM_DEFAULT_NV_SEED}>:PLATFORM_DEFAULT_NV_SEED>
+ $<$<BOOL:${PLATFORM_DEFAULT_CRYPTO_KEYS}>:PLATFORM_DEFAULT_CRYPTO_KEYS>
+ MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS
+ MBEDTLS_PSA_CRYPTO_DRIVERS
+ $<$<BOOL:CRYPTO_TFM_BUILTIN_KEYS_DRIVER>:PSA_CRYPTO_DRIVER_TFM_BUILTIN_KEY_LOADER>
)
cmake_policy(SET CMP0079 NEW)
@@ -175,6 +184,7 @@ endif()
target_include_directories(${MBEDTLS_TARGET_PREFIX}mbedcrypto
PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}
+ ${CMAKE_CURRENT_SOURCE_DIR}/psa_driver_api
)
# Fix platform_s and crypto_service_mbedcrypto libraries cyclic linking
diff --git a/secure_fw/partitions/crypto/crypto_init.c b/secure_fw/partitions/crypto/crypto_init.c
index 898418ed51..1af64cc39a 100644
--- a/secure_fw/partitions/crypto/crypto_init.c
+++ b/secure_fw/partitions/crypto/crypto_init.c
@@ -12,6 +12,7 @@
#include "tfm_crypto_defs.h"
#include "tfm_sp_log.h"
#include "crypto_check_config.h"
+#include "tfm_plat_crypto_keys.h"
/*
* \brief This Mbed TLS include is needed to initialise the memory allocator
@@ -345,6 +346,7 @@ static psa_status_t tfm_crypto_module_init(void)
psa_status_t tfm_crypto_init(void)
{
psa_status_t status;
+ enum tfm_plat_err_t plat_err;
/* Initialise other modules of the service */
status = tfm_crypto_module_init();
@@ -353,7 +355,17 @@ psa_status_t tfm_crypto_init(void)
}
/* Initialise the engine layer */
- return tfm_crypto_engine_init();
+ status = tfm_crypto_engine_init();
+ if (status != PSA_SUCCESS) {
+ return status;
+ }
+
+ plat_err = tfm_plat_load_builtin_keys();
+ if (plat_err != TFM_PLAT_ERR_SUCCESS) {
+ return PSA_ERROR_GENERIC_ERROR;
+ }
+
+ return PSA_SUCCESS;
}
#ifdef TFM_PSA_API
diff --git a/secure_fw/partitions/crypto/psa_driver_api/tfm_builtin_key_loader.c b/secure_fw/partitions/crypto/psa_driver_api/tfm_builtin_key_loader.c
new file mode 100644
index 0000000000..fd0d58e80e
--- /dev/null
+++ b/secure_fw/partitions/crypto/psa_driver_api/tfm_builtin_key_loader.c
@@ -0,0 +1,208 @@
+/*
+ * Copyright (c) 2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include "tfm_builtin_key_loader.h"
+
+#include "psa/error.h"
+#include "tfm_mbedcrypto_include.h"
+#include "tfm_crypto_defs.h"
+#include "mbedtls/hkdf.h"
+#include "psa_manifest/pid.h"
+#include "tfm_plat_crypto_keys.h"
+
+#include <string.h>
+
+#define TFM_BUILTIN_MAX_KEY_LEN 48
+#define TFM_BUILTIN_MAX_KEYS 8
+
+struct tfm_builtin_key_t {
+ uint8_t key[TFM_BUILTIN_MAX_KEY_LEN];
+ size_t key_len;
+ psa_key_attributes_t attr;
+ uint32_t is_loaded;
+ psa_drv_slot_number_t slot_number;
+};
+
+static struct tfm_builtin_key_t builtin_key_slots[TFM_BUILTIN_MAX_KEYS] = {0};
+
+psa_status_t tfm_builtin_key_loader_load_key(uint8_t *buf, size_t key_len,
+ psa_key_attributes_t *attr)
+{
+ psa_status_t err;
+ psa_drv_slot_number_t slot_number;
+ psa_key_lifetime_t lifetime;
+ mbedtls_svc_key_id_t key_id;
+
+ /* Set the owner to 0, as we handle permissions on a granular basis. Having
+ * builtin keys being defined with different owners seems to cause a memory
+ * leak in the MbedTLS core.
+ */
+ key_id = psa_get_key_id(attr);
+ key_id.MBEDTLS_PRIVATE(owner) = 0;
+ psa_set_key_id(attr, key_id);
+
+ if (key_len > TFM_BUILTIN_MAX_KEY_LEN) {
+ return PSA_ERROR_BUFFER_TOO_SMALL;
+ }
+
+ err = mbedtls_psa_platform_get_builtin_key(psa_get_key_id(attr), &lifetime,
+ &slot_number);
+ if (err != PSA_SUCCESS) {
+ return err;
+ }
+
+ memcpy(&(builtin_key_slots[slot_number].attr), attr,
+ sizeof(psa_key_attributes_t));
+ memcpy(&(builtin_key_slots[slot_number].key), buf, key_len);
+ builtin_key_slots[slot_number].key_len = key_len;
+ builtin_key_slots[slot_number].is_loaded = 1;
+
+ return PSA_SUCCESS;
+}
+
+psa_status_t tfm_builtin_key_loader_get_key_buffer_size(
+ mbedtls_svc_key_id_t key_id, size_t *len)
+{
+ psa_status_t err;
+ psa_drv_slot_number_t slot_number;
+ psa_key_lifetime_t lifetime;
+
+ err = mbedtls_psa_platform_get_builtin_key(key_id, &lifetime, &slot_number);
+ if (err != PSA_SUCCESS) {
+ return err;
+ }
+
+ *len = builtin_key_slots[slot_number].key_len;
+ return PSA_SUCCESS;
+}
+
+static psa_status_t builtin_key_get_attributes(
+ struct tfm_builtin_key_t *key_slot, psa_key_attributes_t *attr)
+{
+ enum tfm_plat_err_t plat_err;
+ /* Preserve the key id and lifetime */
+ mbedtls_svc_key_id_t key_id = psa_get_key_id(attr);
+ psa_key_lifetime_t lifetime = psa_get_key_lifetime(attr);
+ psa_key_usage_t usage = psa_get_key_usage_flags(attr);
+
+ memcpy(attr, &(key_slot->attr), sizeof(psa_key_attributes_t));
+
+ plat_err = tfm_plat_builtin_key_get_usage(
+ MBEDTLS_SVC_KEY_ID_GET_KEY_ID(key_id),
+ MBEDTLS_SVC_KEY_ID_GET_OWNER_ID(key_id), &usage);
+ if (plat_err != TFM_PLAT_ERR_SUCCESS) {
+ return PSA_ERROR_NOT_PERMITTED;
+ }
+
+ psa_set_key_id(attr, key_id);
+ psa_set_key_lifetime(attr, lifetime);
+ psa_set_key_usage_flags(attr, usage);
+
+ return PSA_SUCCESS;
+}
+
+static psa_status_t derive_subkey_into_buffer(
+ struct tfm_builtin_key_t *key_slot, mbedtls_key_owner_id_t owner,
+ uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length)
+{
+ int mbedtls_err;
+
+#ifdef TFM_PARTITION_TEST_PS
+ /* Hack to allow the PS tests to work, since they directly call
+ * ps_system_prepare from the test partition which would otherwise derive a
+ * different key.
+ */
+ if (owner == TFM_SP_PS_TEST) {
+ owner = TFM_SP_PS;
+ }
+#endif /* TFM_PARTITION_TEST_PS */
+
+ /* FIXME this should be moved to using the PSA APIs once key derivation is
+ * implemented in the PSA driver wrapper. Using the external PSA apis
+ * directly creates a keyslot and we'd need to read the data from it and
+ * then destroy it, so isn't ideal. In order to avoid infinite recursion,
+ * it'll be necessary to add a special case (probably if owner == 0) to make
+ * sure the new PSA derivation request doesn't end up back here.
+ */
+ mbedtls_err = mbedtls_hkdf(mbedtls_md_info_from_type(MBEDTLS_MD_SHA256),
+ NULL, 0, key_slot->key, key_slot->key_len,
+ (uint8_t *)&owner, sizeof(owner), key_buffer,
+ key_buffer_size);
+ if (mbedtls_err) {
+ return PSA_ERROR_GENERIC_ERROR;
+ }
+
+ *key_buffer_length = key_buffer_size;
+
+ return PSA_SUCCESS;
+}
+
+static psa_status_t builtin_key_copy_to_buffer(
+ struct tfm_builtin_key_t *key_slot, uint8_t *key_buffer,
+ size_t key_buffer_size, size_t *key_buffer_length)
+{
+ memcpy(key_buffer, key_slot->key, key_slot->key_len);
+ *key_buffer_length = key_slot->key_len;
+
+ return PSA_SUCCESS;
+}
+
+psa_status_t tfm_builtin_key_loader_get_key_buffer(
+ psa_drv_slot_number_t slot_number, psa_key_attributes_t *attributes,
+ uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length)
+{
+ psa_status_t err;
+ struct tfm_builtin_key_t *key_slot;
+ mbedtls_svc_key_id_t key_id;
+
+ if ((uint32_t)slot_number >= TFM_BUILTIN_MAX_KEYS) {
+ return PSA_ERROR_DOES_NOT_EXIST;
+ }
+
+ key_slot = &builtin_key_slots[slot_number];
+
+ if (!key_slot->is_loaded) {
+ return PSA_ERROR_DOES_NOT_EXIST;
+ }
+
+ if (attributes == NULL) {
+ return PSA_ERROR_INVALID_ARGUMENT;
+ }
+
+ err = builtin_key_get_attributes(key_slot, attributes);
+ if (err != PSA_SUCCESS) {
+ return err;
+ }
+
+ if (key_buffer_size < key_slot->key_len) {
+ return PSA_ERROR_BUFFER_TOO_SMALL;
+ }
+
+ if (key_buffer == NULL || key_buffer_length == NULL) {
+ return PSA_ERROR_INVALID_ARGUMENT;
+ }
+
+ key_id = psa_get_key_id(attributes);
+
+ /* If a key can be used for derivation, we derive a further subkey for each
+ * owner to prevent multiple owners deriving the same keys as each other.
+ * For keys for encryption and signing, it's assumed that if multiple
+ * partitions have access to the key, there is a good reason and therefore
+ * they both need access to the raw builtin key.
+ */
+ if (psa_get_key_usage_flags(attributes) & PSA_KEY_USAGE_DERIVE) {
+ err = derive_subkey_into_buffer(key_slot,
+ MBEDTLS_SVC_KEY_ID_GET_OWNER_ID(key_id),
+ key_buffer, key_buffer_size,
+ key_buffer_length);
+ } else {
+ err = builtin_key_copy_to_buffer(key_slot, key_buffer, key_buffer_size,
+ key_buffer_length);
+ }
+
+ return err;
+}
diff --git a/secure_fw/partitions/crypto/psa_driver_api/tfm_builtin_key_loader.h b/secure_fw/partitions/crypto/psa_driver_api/tfm_builtin_key_loader.h
new file mode 100644
index 0000000000..1220f2aaaa
--- /dev/null
+++ b/secure_fw/partitions/crypto/psa_driver_api/tfm_builtin_key_loader.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef TFM_BUILTIN_KEY_LOADER_H
+#define TFM_BUILTIN_KEY_LOADER_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "tfm_mbedcrypto_include.h"
+
+#ifdef PLATFORM_DEFAULT_CRYPTO_KEYS
+enum psa_drv_slot_number_t {
+ TFM_BUILTIN_KEY_SLOT_HUK = 0,
+ TFM_BUILTIN_KEY_SLOT_IAK,
+ TFM_BUILTIN_KEY_SLOT_DAK_SEED,
+ TFM_BUILTIN_KEY_SLOT_MAX,
+};
+#else
+#include "platform_builtin_key_loader_ids.h"
+#endif
+
+/**
+ * \brief Load a key into the builtin key driver
+ *
+ * \note This should be called for all slots that are required on initial boot,
+ * from the tfm_plat_load_builtin_keys function.
+ *
+ * \param[in] buf Buffer containing key material.
+ * \param[in] key_len Size of the key in bytes.
+ * \param[in] attr The attributes of the key.
+ *
+ * \return Returns error code specified in \ref psa_status_t
+ */
+psa_status_t tfm_builtin_key_loader_load_key(uint8_t *buf, size_t key_len,
+ psa_key_attributes_t *attr);
+
+/**
+ * \brief Returns the length of a key from the builtin driver.
+ *
+ * \note This function is called by the psa crypto driver wrapper.
+ *
+ * \param[in] key_id The ID of the key to return the length of
+ * \param[out] len The length of the key.
+ *
+ * \return Returns error code specified in \ref psa_status_t
+ */
+psa_status_t tfm_builtin_key_loader_get_key_buffer_size(
+ mbedtls_svc_key_id_t key_id, size_t *len);
+
+/**
+ * \brief Returns the attributes and key material of a key from the builtin
+ * driver
+ *
+ * \note This function is called by the psa crypto driver wrapper.
+ *
+ * \param[in] slot_number The slot of the key
+ * \param[out] attributes The attributes of the key.
+ * \param[out] key_buffer The buffer to output the key material into.
+ * \param[in] key_buffer_size The size of the key material buffer.
+ * \param[out] key_buffer_length The length of the key material returned.
+ *
+ * \return Returns error code specified in \ref psa_status_t
+ */
+psa_status_t tfm_builtin_key_loader_get_key_buffer(
+ psa_drv_slot_number_t slot_number, psa_key_attributes_t *attributes,
+ uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* TFM_BUILTIN_KEY_LOADER_H */
diff --git a/secure_fw/partitions/crypto/tfm_mbedcrypto_builtin_keys.c b/secure_fw/partitions/crypto/tfm_mbedcrypto_builtin_keys.c
new file mode 100644
index 0000000000..49ce43909f
--- /dev/null
+++ b/secure_fw/partitions/crypto/tfm_mbedcrypto_builtin_keys.c
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include "tfm_mbedcrypto_include.h"
+#include "tfm_crypto_defs.h"
+#include "tfm_plat_crypto_keys.h"
+
+/* This function is required by MbedTLS to enable builtin key support, it maps
+ * builtin key IDs to cryptographic drivers and slots. The actual data is
+ * deferred to a platform function, as different platforms may have different
+ * key storage capabilities.
+ */
+psa_status_t mbedtls_psa_platform_get_builtin_key(
+ mbedtls_svc_key_id_t key_id,
+ psa_key_lifetime_t *lifetime,
+ psa_drv_slot_number_t *slot_number)
+{
+ enum tfm_plat_err_t plat_err;
+
+ plat_err = tfm_plat_builtin_key_get_lifetime_and_slot(key_id, lifetime,
+ slot_number);
+ if (plat_err != TFM_PLAT_ERR_SUCCESS) {
+ return PSA_ERROR_DOES_NOT_EXIST;
+ }
+
+ return PSA_SUCCESS;
+}