Crypto: Refactor the API dispatcher interface to reduce code size
This patch restructures the way the underlying APIs that
implements the PSA Crypto APIs are interfaced to the TF-M
Crypto service through a thin shim layer. The size of this
layer is reduced by nearly 45% on the default configuration.
Also, it removes the check for parameter number and size on
each function call as that is a redundant check as per the
overall threat model of the interaction between the crypto
service and the partition manager.
Signed-off-by: Antonio de Angelis <antonio.deangelis@arm.com>
Change-Id: I07165bad00346cd12cf63620532f55da0c5d1262
diff --git a/secure_fw/partitions/crypto/crypto_init.c b/secure_fw/partitions/crypto/crypto_init.c
index 476bea5..077fceb 100644
--- a/secure_fw/partitions/crypto/crypto_init.c
+++ b/secure_fw/partitions/crypto/crypto_init.c
@@ -4,6 +4,7 @@
* SPDX-License-Identifier: BSD-3-Clause
*
*/
+#include <stdbool.h>
#include "tfm_mbedcrypto_include.h"
@@ -13,7 +14,7 @@
/*
* \brief This Mbed TLS include is needed to initialise the memory allocator
- * inside the Mbed TLS layer of Mbed Crypto
+ * of the library used for internal allocations
*/
#include "mbedtls/memory_buffer_alloc.h"
@@ -29,6 +30,40 @@
#include "crypto_hw.h"
#endif /* CRYPTO_HW_ACCELERATOR */
+#ifndef MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER
+#error "MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER must be selected in Mbed TLS config file"
+#endif
+
+/**
+ * \brief Type describing the properties of each function identifier, i.e. the
+ * group ID and the function type
+ */
+struct tfm_crypto_api_descriptor {
+ uint8_t group_id : 6; /*!< Value from \ref tfm_crypto_group_id */
+ uint8_t function_type: 2; /*!< Value from \ref tfm_crypto_function_type */
+};
+
+/**
+ * \brief This table contains the description of each of the function IDs
+ * defined by \ref tfm_crypto_function_id
+ */
+#define X(_function_id, _group_id, _function_type) \
+ [_function_id] = {.group_id = _group_id, .function_type = _function_type},
+static const struct tfm_crypto_api_descriptor tfm_crypto_api_descriptor[] = {
+ TFM_CRYPTO_SERVICE_API_DESCRIPTION
+};
+#undef X
+
+enum tfm_crypto_function_type get_function_type_from_descriptor(enum tfm_crypto_function_id func)
+{
+ return tfm_crypto_api_descriptor[func].function_type;
+}
+
+enum tfm_crypto_group_id get_group_id_from_descriptor(enum tfm_crypto_function_id func)
+{
+ return tfm_crypto_api_descriptor[func].group_id;
+}
+
#ifdef TFM_PSA_API
#include <string.h>
#include "psa/framework_feature.h"
@@ -36,16 +71,6 @@
#include "psa_manifest/tfm_crypto.h"
/**
- * \brief Table containing all the Uniform Signature API exposed
- * by the TF-M Crypto partition
- */
-static const tfm_crypto_us_t sfid_func_table[TFM_CRYPTO_SID_MAX] = {
-#define X(api_name) api_name,
-LIST_TFM_CRYPTO_UNIFORM_SIGNATURE_API
-#undef X
-};
-
-/**
* \brief Aligns a value x up to an alignment a.
*/
#define ALIGN(x, a) (((x) + ((a) - 1)) & ~((a) - 1))
@@ -235,10 +260,6 @@
return PSA_ERROR_GENERIC_ERROR;
}
- if (iov.srv_id >= TFM_CRYPTO_SID_MAX) {
- return PSA_ERROR_GENERIC_ERROR;
- }
-
/* Initialise the first iovec with the IOV read when parsing */
in_vec[0].base = &iov;
in_vec[0].len = sizeof(struct tfm_crypto_pack_iovec);
@@ -250,8 +271,8 @@
tfm_crypto_set_caller_id(msg->client_id);
- /* Call the uniform signature API */
- status = sfid_func_table[iov.srv_id](in_vec, in_len, out_vec, out_len);
+ /* Call the dispatcher to the functions that implement the PSA Crypto API */
+ status = tfm_crypto_api_dispatcher(in_vec, in_len, out_vec, out_len);
#if PSA_FRAMEWORK_HAS_MM_IOVEC == 1
for (i = 0; i < out_len; i++) {
@@ -301,33 +322,34 @@
static psa_status_t tfm_crypto_engine_init(void)
{
-
#ifdef CRYPTO_NV_SEED
+ LOG_INFFMT("[INF][Crypto] ");
#ifdef TFM_PSA_API
+ LOG_INFFMT("Provisioning entropy seed... ");
if (tfm_plat_crypto_provision_entropy_seed() != TFM_CRYPTO_NV_SEED_SUCCESS) {
return PSA_ERROR_GENERIC_ERROR;
}
+ LOG_INFFMT("\033[0;32mcomplete.\033[0m\r\n");
#else
- LOG_INFFMT("\033[1;31m[Crypto] ");
LOG_INFFMT("TF-M in library mode uses a dummy NV seed. ");
LOG_INFFMT("This is not suitable for production! ");
- LOG_INFFMT("This device is \033[1;1mNOT SECURE");
- LOG_INFFMT("\033[0m\r\n");
+ LOG_INFFMT("This device is \033[1;31mNOT SECURE\033[0m\r\n");
#endif /* TFM_PSA_API */
#endif /* CRYPTO_NV_SEED */
- /* Initialise the Mbed Crypto memory allocator to use static
- * memory allocation from the provided buffer instead of using
- * the heap
+ /* Initialise the Mbed Crypto memory allocator to use static memory
+ * allocation from the provided buffer instead of using the heap
*/
mbedtls_memory_buffer_alloc_init(mbedtls_mem_buf,
TFM_CRYPTO_ENGINE_BUF_SIZE);
/* Initialise the crypto accelerator if one is enabled */
#ifdef CRYPTO_HW_ACCELERATOR
+ LOG_INFFMT("[INF][Crypto] Initialising HW accelerator... ");
if (crypto_hw_accelerator_init() != 0) {
return PSA_ERROR_HARDWARE_FAILURE;
}
+ LOG_INFFMT("\033[0;32mcomplete.\033[0m\r\n");
#endif /* CRYPTO_HW_ACCELERATOR */
/* Previous function does not return any value, so just call the
@@ -370,3 +392,79 @@
return PSA_ERROR_GENERIC_ERROR;
}
#endif
+
+psa_status_t tfm_crypto_api_dispatcher(psa_invec in_vec[],
+ size_t in_len,
+ psa_outvec out_vec[],
+ size_t out_len)
+{
+ psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+ const struct tfm_crypto_pack_iovec *iov = in_vec[0].base;
+ int32_t caller_id = 0;
+ mbedtls_svc_key_id_t encoded_key = MBEDTLS_SVC_KEY_ID_INIT;
+ bool is_key_required = false;
+
+ if (in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec)) {
+ return PSA_ERROR_PROGRAMMER_ERROR;
+ }
+
+ is_key_required = !(TFM_CRYPTO_IS_GROUP_ID(
+ iov->function_id, TFM_CRYPTO_GROUP_ID_HASH) ||
+ (iov->function_id == TFM_CRYPTO_GENERATE_RANDOM_SID));
+
+ if (is_key_required) {
+ status = tfm_crypto_get_caller_id(&caller_id);
+ if (status != PSA_SUCCESS) {
+ return status;
+ }
+ /* The caller_id being set in the owner field is the partition ID
+ * of the calling partition
+ */
+ encoded_key = mbedtls_svc_key_id_make(caller_id, iov->key_id);
+ }
+
+ /* Dispatch to each sub-module based on the Group ID */
+ if (TFM_CRYPTO_IS_GROUP_ID(
+ iov->function_id, TFM_CRYPTO_GROUP_ID_KEY_MANAGEMENT)) {
+ status = tfm_crypto_key_management_interface(in_vec,
+ out_vec,
+ &encoded_key);
+ } else if (TFM_CRYPTO_IS_GROUP_ID(
+ iov->function_id, TFM_CRYPTO_GROUP_ID_HASH)) {
+ status = tfm_crypto_hash_interface(in_vec, out_vec);
+ } else if (TFM_CRYPTO_IS_GROUP_ID(
+ iov->function_id, TFM_CRYPTO_GROUP_ID_MAC)) {
+ status = tfm_crypto_mac_interface(in_vec,
+ out_vec,
+ &encoded_key);
+ } else if (TFM_CRYPTO_IS_GROUP_ID(
+ iov->function_id, TFM_CRYPTO_GROUP_ID_CIPHER)) {
+ status = tfm_crypto_cipher_interface(in_vec,
+ out_vec,
+ &encoded_key);
+ } else if (TFM_CRYPTO_IS_GROUP_ID(
+ iov->function_id, TFM_CRYPTO_GROUP_ID_AEAD)) {
+ status = tfm_crypto_aead_interface(in_vec,
+ out_vec,
+ &encoded_key);
+ } else if (TFM_CRYPTO_IS_GROUP_ID(
+ iov->function_id, TFM_CRYPTO_GROUP_ID_ASYM_SIGN) ||
+ TFM_CRYPTO_IS_GROUP_ID(
+ iov->function_id, TFM_CRYPTO_GROUP_ID_ASYM_ENCRYPT)) {
+ status = tfm_crypto_asymmetric_interface(in_vec,
+ out_vec,
+ &encoded_key);
+ } else if (TFM_CRYPTO_IS_GROUP_ID(
+ iov->function_id, TFM_CRYPTO_GROUP_ID_KEY_DERIVATION)) {
+ status = tfm_crypto_key_derivation_interface(in_vec,
+ out_vec,
+ &encoded_key);
+ } else if (iov->function_id == TFM_CRYPTO_GENERATE_RANDOM_SID) {
+ status = tfm_crypto_random_interface(in_vec, out_vec);
+ } else {
+ LOG_ERRFMT("[ERR][Crypto] Unsupported request!\r\n");
+ status = PSA_ERROR_NOT_SUPPORTED;
+ }
+
+ return status;
+}