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_cipher.c b/secure_fw/partitions/crypto/crypto_cipher.c
index a45d239..70ce182c 100644
--- a/secure_fw/partitions/crypto/crypto_cipher.c
+++ b/secure_fw/partitions/crypto/crypto_cipher.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018-2021, Arm Limited. All rights reserved.
+ * Copyright (c) 2018-2022, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*
@@ -12,400 +12,145 @@
#include "tfm_crypto_api.h"
#include "tfm_crypto_defs.h"
-#include "tfm_crypto_private.h"
/*!
- * \defgroup public_psa Public functions, PSA
+ * \addtogroup tfm_crypto_api_shim_layer
*
*/
/*!@{*/
-psa_status_t tfm_crypto_cipher_generate_iv(psa_invec in_vec[],
- size_t in_len,
- psa_outvec out_vec[],
- size_t out_len)
+psa_status_t tfm_crypto_cipher_interface(psa_invec in_vec[],
+ psa_outvec out_vec[],
+ mbedtls_svc_key_id_t *encoded_key)
{
#ifdef TFM_CRYPTO_CIPHER_MODULE_DISABLED
return PSA_ERROR_NOT_SUPPORTED;
-#else
- psa_status_t status = PSA_SUCCESS;
- psa_cipher_operation_t *operation = NULL;
-
- CRYPTO_IN_OUT_LEN_VALIDATE(in_len, 1, 1, out_len, 1, 2);
-
- if ((in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec)) ||
- (out_vec[0].len != sizeof(uint32_t))) {
- return PSA_ERROR_PROGRAMMER_ERROR;
- }
-
+#endif
const struct tfm_crypto_pack_iovec *iov = in_vec[0].base;
- uint32_t handle = iov->op_handle;
- uint32_t *handle_out = out_vec[0].base;
- unsigned char *iv = out_vec[1].base;
- size_t iv_size = out_vec[1].len;
-
- /* Init the handle in the operation with the one passed from the iov */
- *handle_out = iov->op_handle;
-
- /* Look up the corresponding operation context */
- status = tfm_crypto_operation_lookup(TFM_CRYPTO_CIPHER_OPERATION,
- handle,
- (void **)&operation);
- if (status != PSA_SUCCESS) {
- return status;
- }
-
- *handle_out = handle;
-
- return psa_cipher_generate_iv(operation, iv, iv_size, &out_vec[1].len);
-#endif /* TFM_CRYPTO_CIPHER_MODULE_DISABLED */
-}
-
-psa_status_t tfm_crypto_cipher_set_iv(psa_invec in_vec[],
- size_t in_len,
- psa_outvec out_vec[],
- size_t out_len)
-{
-#ifdef TFM_CRYPTO_CIPHER_MODULE_DISABLED
- return PSA_ERROR_NOT_SUPPORTED;
-#else
- psa_status_t status = PSA_SUCCESS;
+ psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
psa_cipher_operation_t *operation = NULL;
-
- CRYPTO_IN_OUT_LEN_VALIDATE(in_len, 1, 2, out_len, 1, 1);
-
- if ((in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec)) ||
- (out_vec[0].len != sizeof(uint32_t))) {
- return PSA_ERROR_PROGRAMMER_ERROR;
- }
- const struct tfm_crypto_pack_iovec *iov = in_vec[0].base;
uint32_t handle = iov->op_handle;
- uint32_t *handle_out = out_vec[0].base;
- const unsigned char *iv = in_vec[1].base;
- size_t iv_length = in_vec[1].len;
+ uint32_t *handle_out = NULL;
+ enum tfm_crypto_function_type function_type =
+ TFM_CRYPTO_GET_FUNCTION_TYPE(iov->function_id);
- /* Init the handle in the operation with the one passed from the iov */
- *handle_out = iov->op_handle;
-
- /* Look up the corresponding operation context */
- status = tfm_crypto_operation_lookup(TFM_CRYPTO_CIPHER_OPERATION,
- handle,
- (void **)&operation);
- if (status != PSA_SUCCESS) {
- return status;
+ if (function_type != TFM_CRYPTO_FUNCTION_TYPE_NON_MULTIPART) {
+ handle_out = (out_vec && out_vec[0].base != NULL) ?
+ out_vec[0].base : &handle;
+ *handle_out = handle;
+ status = tfm_crypto_operation_handling(TFM_CRYPTO_CIPHER_OPERATION,
+ function_type,
+ handle_out,
+ (void **)&operation);
+ if (status != PSA_SUCCESS) {
+ return (iov->function_id == TFM_CRYPTO_CIPHER_ABORT_SID) ?
+ PSA_SUCCESS : status;
+ }
}
- return psa_cipher_set_iv(operation, iv, iv_length);
-#endif /* TFM_CRYPTO_CIPHER_MODULE_DISABLED */
-}
+ switch (iov->function_id) {
+ case TFM_CRYPTO_CIPHER_GENERATE_IV_SID:
+ {
+ unsigned char *iv = out_vec[0].base;
+ size_t iv_size = out_vec[0].len;
-psa_status_t tfm_crypto_cipher_encrypt_setup(psa_invec in_vec[],
- size_t in_len,
- psa_outvec out_vec[],
- size_t out_len)
-{
-#ifdef TFM_CRYPTO_CIPHER_MODULE_DISABLED
- return PSA_ERROR_NOT_SUPPORTED;
-#else
- psa_status_t status = PSA_SUCCESS;
- psa_cipher_operation_t *operation = NULL;
-
- CRYPTO_IN_OUT_LEN_VALIDATE(in_len, 1, 1, out_len, 1, 1);
-
- if ((out_vec[0].len != sizeof(uint32_t)) ||
- (in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec))) {
- return PSA_ERROR_PROGRAMMER_ERROR;
+ status = psa_cipher_generate_iv(operation,
+ iv, iv_size, &out_vec[0].len);
}
- const struct tfm_crypto_pack_iovec *iov = in_vec[0].base;
- uint32_t handle = iov->op_handle;
- uint32_t *handle_out = out_vec[0].base;
- psa_key_id_t key_id = iov->key_id;
- psa_algorithm_t alg = iov->alg;
- mbedtls_svc_key_id_t encoded_key;
+ break;
+ case TFM_CRYPTO_CIPHER_SET_IV_SID:
+ {
+ const unsigned char *iv = in_vec[1].base;
+ size_t iv_length = in_vec[1].len;
- /* Allocate the operation context in the secure world */
- status = tfm_crypto_operation_alloc(TFM_CRYPTO_CIPHER_OPERATION,
- &handle,
- (void **)&operation);
- if (status != PSA_SUCCESS) {
- return status;
+ status = psa_cipher_set_iv(operation, iv, iv_length);
}
- *handle_out = handle;
-
- status = tfm_crypto_encode_id_and_owner(key_id, &encoded_key);
- if (status != PSA_SUCCESS) {
- goto exit;
+ break;
+ case TFM_CRYPTO_CIPHER_ENCRYPT_SETUP_SID:
+ {
+ status = psa_cipher_encrypt_setup(operation, *encoded_key, iov->alg);
+ if (status != PSA_SUCCESS) {
+ goto release_operation_and_return;
+ }
}
+ break;
+ case TFM_CRYPTO_CIPHER_DECRYPT_SETUP_SID:
+ {
+ status = psa_cipher_decrypt_setup(operation, *encoded_key, iov->alg);
+ if (status != PSA_SUCCESS) {
+ goto release_operation_and_return;
+ }
+ }
+ break;
+ case TFM_CRYPTO_CIPHER_UPDATE_SID:
+ {
+ const uint8_t *input = in_vec[1].base;
+ size_t input_length = in_vec[1].len;
+ unsigned char *output = out_vec[0].base;
+ size_t output_size = out_vec[0].len;
+ /* Initialise the output_length to zero */
+ out_vec[0].len = 0;
- status = psa_cipher_encrypt_setup(operation, encoded_key, alg);
- if (status != PSA_SUCCESS) {
- goto exit;
+ status = psa_cipher_update(operation, input, input_length,
+ output, output_size, &out_vec[0].len);
+ }
+ break;
+ case TFM_CRYPTO_CIPHER_FINISH_SID:
+ {
+ uint8_t *output = out_vec[1].base;
+ size_t output_size = out_vec[1].len;
+ /* Initialise the output_length to zero */
+ out_vec[1].len = 0;
+
+ status = psa_cipher_finish(operation,
+ output, output_size, &out_vec[1].len);
+ if (status == PSA_SUCCESS) {
+ /* In case of success automatically release the operation */
+ goto release_operation_and_return;
+ }
+ }
+ break;
+ case TFM_CRYPTO_CIPHER_ABORT_SID:
+ {
+ status = psa_cipher_abort(operation);
+
+ if (status != PSA_SUCCESS) {
+ goto release_operation_and_return;
+ } else {
+ status = tfm_crypto_operation_release(handle_out);
+ }
+ }
+ break;
+ case TFM_CRYPTO_CIPHER_ENCRYPT_SID:
+ {
+ const uint8_t *input = in_vec[1].base;
+ size_t input_length = in_vec[1].len;
+ uint8_t *output = out_vec[0].base;
+ size_t output_size = out_vec[0].len;
+
+ status = psa_cipher_encrypt(*encoded_key, iov->alg, input, input_length,
+ output, output_size, &out_vec[0].len);
+ }
+ break;
+ case TFM_CRYPTO_CIPHER_DECRYPT_SID:
+ {
+ const uint8_t *input = in_vec[1].base;
+ size_t input_length = in_vec[1].len;
+ uint8_t *output = out_vec[0].base;
+ size_t output_size = out_vec[0].len;
+
+ status = psa_cipher_decrypt(*encoded_key, iov->alg, input, input_length,
+ output, output_size, &out_vec[0].len);
+ }
+ break;
+ default:
+ status = PSA_ERROR_NOT_SUPPORTED;
}
return status;
-
-exit:
+release_operation_and_return:
/* Release the operation context, ignore if the operation fails. */
(void)tfm_crypto_operation_release(handle_out);
return status;
-#endif /* TFM_CRYPTO_CIPHER_MODULE_DISABLED */
-}
-
-psa_status_t tfm_crypto_cipher_decrypt_setup(psa_invec in_vec[],
- size_t in_len,
- psa_outvec out_vec[],
- size_t out_len)
-{
-#ifdef TFM_CRYPTO_CIPHER_MODULE_DISABLED
- return PSA_ERROR_NOT_SUPPORTED;
-#else
- psa_status_t status = PSA_SUCCESS;
- psa_cipher_operation_t *operation = NULL;
-
- CRYPTO_IN_OUT_LEN_VALIDATE(in_len, 1, 1, out_len, 1, 1);
-
- if ((out_vec[0].len != sizeof(uint32_t)) ||
- (in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec))) {
- return PSA_ERROR_PROGRAMMER_ERROR;
- }
- const struct tfm_crypto_pack_iovec *iov = in_vec[0].base;
- uint32_t handle = iov->op_handle;
- uint32_t *handle_out = out_vec[0].base;
- psa_key_id_t key_id = iov->key_id;
- psa_algorithm_t alg = iov->alg;
- mbedtls_svc_key_id_t encoded_key;
-
- /* Allocate the operation context in the secure world */
- status = tfm_crypto_operation_alloc(TFM_CRYPTO_CIPHER_OPERATION,
- &handle,
- (void **)&operation);
- if (status != PSA_SUCCESS) {
- return status;
- }
-
- *handle_out = handle;
- status = tfm_crypto_encode_id_and_owner(key_id, &encoded_key);
- if (status != PSA_SUCCESS) {
- goto exit;
- }
-
- status = psa_cipher_decrypt_setup(operation, encoded_key, alg);
- if (status != PSA_SUCCESS) {
- goto exit;
- }
-
- return status;
-
-exit:
- /* Release the operation context, ignore if the operation fails. */
- (void)tfm_crypto_operation_release(handle_out);
- return status;
-#endif /* TFM_CRYPTO_CIPHER_MODULE_DISABLED */
-}
-
-psa_status_t tfm_crypto_cipher_update(psa_invec in_vec[],
- size_t in_len,
- psa_outvec out_vec[],
- size_t out_len)
-{
-#ifdef TFM_CRYPTO_CIPHER_MODULE_DISABLED
- return PSA_ERROR_NOT_SUPPORTED;
-#else
- psa_status_t status = PSA_SUCCESS;
- psa_cipher_operation_t *operation = NULL;
-
- CRYPTO_IN_OUT_LEN_VALIDATE(in_len, 1, 2, out_len, 1, 2);
-
- if ((in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec)) ||
- (out_vec[0].len != sizeof(uint32_t))) {
- return PSA_ERROR_PROGRAMMER_ERROR;
- }
-
- const struct tfm_crypto_pack_iovec *iov = in_vec[0].base;
- uint32_t handle = iov->op_handle;
- uint32_t *handle_out = out_vec[0].base;
- const uint8_t *input = in_vec[1].base;
- size_t input_length = in_vec[1].len;
- unsigned char *output = out_vec[1].base;
- size_t output_size = out_vec[1].len;
-
- /* Init the handle in the operation with the one passed from the iov */
- *handle_out = iov->op_handle;
-
- /* Initialise the output_length to zero */
- out_vec[1].len = 0;
-
- /* Look up the corresponding operation context */
- status = tfm_crypto_operation_lookup(TFM_CRYPTO_CIPHER_OPERATION,
- handle,
- (void **)&operation);
- if (status != PSA_SUCCESS) {
- return status;
- }
-
- return psa_cipher_update(operation, input, input_length,
- output, output_size, &out_vec[1].len);
-#endif /* TFM_CRYPTO_CIPHER_MODULE_DISABLED */
-}
-
-psa_status_t tfm_crypto_cipher_finish(psa_invec in_vec[],
- size_t in_len,
- psa_outvec out_vec[],
- size_t out_len)
-{
-#ifdef TFM_CRYPTO_CIPHER_MODULE_DISABLED
- return PSA_ERROR_NOT_SUPPORTED;
-#else
- psa_status_t status = PSA_SUCCESS;
- psa_cipher_operation_t *operation = NULL;
-
- CRYPTO_IN_OUT_LEN_VALIDATE(in_len, 1, 1, out_len, 1, 2);
-
- if ((in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec)) ||
- (out_vec[0].len != sizeof(uint32_t))) {
- return PSA_ERROR_PROGRAMMER_ERROR;
- }
- const struct tfm_crypto_pack_iovec *iov = in_vec[0].base;
- uint32_t handle = iov->op_handle;
- uint32_t *handle_out = out_vec[0].base;
- unsigned char *output = out_vec[1].base;
- size_t output_size = out_vec[1].len;
-
- /* Init the handle in the operation with the one passed from the iov */
- *handle_out = iov->op_handle;
-
- /* Initialise the output_length to zero */
- out_vec[1].len = 0;
-
- /* Look up the corresponding operation context */
- status = tfm_crypto_operation_lookup(TFM_CRYPTO_CIPHER_OPERATION,
- handle,
- (void **)&operation);
- if (status != PSA_SUCCESS) {
- return status;
- }
-
- status = psa_cipher_finish(operation, output, output_size, &out_vec[1].len);
- if (status == PSA_SUCCESS) {
- /* Release the operation context, ignore if the operation fails. */
- (void)tfm_crypto_operation_release(handle_out);
- }
-
- return status;
-#endif /* TFM_CRYPTO_CIPHER_MODULE_DISABLED */
-}
-
-psa_status_t tfm_crypto_cipher_abort(psa_invec in_vec[],
- size_t in_len,
- psa_outvec out_vec[],
- size_t out_len)
-{
-#ifdef TFM_CRYPTO_CIPHER_MODULE_DISABLED
- return PSA_ERROR_NOT_SUPPORTED;
-#else
- psa_status_t status = PSA_SUCCESS;
- psa_cipher_operation_t *operation = NULL;
-
- CRYPTO_IN_OUT_LEN_VALIDATE(in_len, 1, 1, out_len, 1, 1);
-
- if ((in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec)) ||
- (out_vec[0].len != sizeof(uint32_t))) {
- return PSA_ERROR_PROGRAMMER_ERROR;
- }
- const struct tfm_crypto_pack_iovec *iov = in_vec[0].base;
- uint32_t handle = iov->op_handle;
- uint32_t *handle_out = out_vec[0].base;
-
- /* Init the handle in the operation with the one passed from the iov */
- *handle_out = iov->op_handle;
-
- /* Look up the corresponding operation context */
- status = tfm_crypto_operation_lookup(TFM_CRYPTO_CIPHER_OPERATION,
- handle,
- (void **)&operation);
- if (status != PSA_SUCCESS) {
- /* Operation does not exist, so abort has no effect */
- return PSA_SUCCESS;
- }
-
- status = psa_cipher_abort(operation);
-
- if (status != PSA_SUCCESS) {
- /* Release the operation context, ignore if the operation fails. */
- (void)tfm_crypto_operation_release(handle_out);
- return status;
- }
-
- return tfm_crypto_operation_release(handle_out);
-#endif /* TFM_CRYPTO_CIPHER_MODULE_DISABLED */
-}
-
-psa_status_t tfm_crypto_cipher_encrypt(psa_invec in_vec[],
- size_t in_len,
- psa_outvec out_vec[],
- size_t out_len)
-{
-#ifdef TFM_CRYPTO_CIPHER_MODULE_DISABLED
- return PSA_ERROR_NOT_SUPPORTED;
-#else
- psa_status_t status = PSA_SUCCESS;
-
- CRYPTO_IN_OUT_LEN_VALIDATE(in_len, 1, 2, out_len, 1, 1);
-
- if (in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec)) {
- return PSA_ERROR_PROGRAMMER_ERROR;
- }
-
- const struct tfm_crypto_pack_iovec *iov = in_vec[0].base;
- psa_key_id_t key_id = iov->key_id;
- psa_algorithm_t alg = iov->alg;
- const uint8_t *input = in_vec[1].base;
- size_t input_length = in_vec[1].len;
- uint8_t *output = out_vec[0].base;
- size_t output_size = out_vec[0].len;
- mbedtls_svc_key_id_t encoded_key;
-
- status = tfm_crypto_encode_id_and_owner(key_id, &encoded_key);
- if (status != PSA_SUCCESS) {
- return status;
- }
-
- return psa_cipher_encrypt(encoded_key, alg, input, input_length, output,
- output_size, &out_vec[0].len);
-#endif /* TFM_CRYPTO_CIPHER_MODULE_DISABLED */
-}
-
-psa_status_t tfm_crypto_cipher_decrypt(psa_invec in_vec[],
- size_t in_len,
- psa_outvec out_vec[],
- size_t out_len)
-{
-#ifdef TFM_CRYPTO_CIPHER_MODULE_DISABLED
- return PSA_ERROR_NOT_SUPPORTED;
-#else
- psa_status_t status = PSA_SUCCESS;
-
- CRYPTO_IN_OUT_LEN_VALIDATE(in_len, 1, 2, out_len, 1, 1);
-
- if (in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec)) {
- return PSA_ERROR_PROGRAMMER_ERROR;
- }
- const struct tfm_crypto_pack_iovec *iov = in_vec[0].base;
- psa_key_id_t key_id = iov->key_id;
- psa_algorithm_t alg = iov->alg;
- const uint8_t *input = in_vec[1].base;
- size_t input_length = in_vec[1].len;
- uint8_t *output = out_vec[0].base;
- size_t output_size = out_vec[0].len;
- mbedtls_svc_key_id_t encoded_key;
-
- status = tfm_crypto_encode_id_and_owner(key_id, &encoded_key);
- if (status != PSA_SUCCESS) {
- return status;
- }
-
- return psa_cipher_decrypt(encoded_key, alg, input, input_length, output,
- output_size, &out_vec[0].len);
-#endif /* TFM_CRYPTO_CIPHER_MODULE_DISABLED */
}
/*!@}*/