aboutsummaryrefslogtreecommitdiff
path: root/secure_fw/partitions/crypto/crypto_cipher.c
diff options
context:
space:
mode:
Diffstat (limited to 'secure_fw/partitions/crypto/crypto_cipher.c')
-rw-r--r--secure_fw/partitions/crypto/crypto_cipher.c518
1 files changed, 167 insertions, 351 deletions
diff --git a/secure_fw/partitions/crypto/crypto_cipher.c b/secure_fw/partitions/crypto/crypto_cipher.c
index 03849dfd97..b664b9902f 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
*
@@ -8,383 +8,199 @@
#include <stddef.h>
#include <stdint.h>
+#include "config_tfm.h"
#include "tfm_mbedcrypto_include.h"
#include "tfm_crypto_api.h"
+#include "tfm_crypto_key.h"
#include "tfm_crypto_defs.h"
-#include "tfm_crypto_private.h"
+
+#include "crypto_library.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)
+#if CRYPTO_CIPHER_MODULE_ENABLED
+psa_status_t tfm_crypto_cipher_interface(psa_invec in_vec[],
+ psa_outvec out_vec[],
+ struct tfm_crypto_key_id_s *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;
- }
-
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;
-
- status = psa_cipher_generate_iv(operation, iv, iv_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;
- }
-
- return status;
-#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_NOT_SUPPORTED;
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;
-
- /* 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;
- }
-
- status = psa_cipher_set_iv(operation, iv, iv_length);
- if (status != PSA_SUCCESS) {
- /* Release the operation context, ignore if the operation fails. */
- (void)tfm_crypto_operation_release(handle_out);
- return status;
- }
-
- return status;
-#endif /* TFM_CRYPTO_CIPHER_MODULE_DISABLED */
-}
-
-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;
+ uint32_t *p_handle = NULL;
+ uint16_t sid = iov->function_id;
+
+ tfm_crypto_library_key_id_t library_key = tfm_crypto_library_key_id_init(
+ encoded_key->owner, encoded_key->key_id);
+ if (sid == TFM_CRYPTO_CIPHER_ENCRYPT_SID) {
+#if CRYPTO_SINGLE_PART_FUNCS_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;
-
- status = tfm_crypto_check_handle_owner(key_id, NULL);
- if (status != PSA_SUCCESS) {
- return status;
- }
-
- /* 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;
+ 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 = tfm_crypto_encode_id_and_owner(key_id, &encoded_key);
- if (status != PSA_SUCCESS) {
+ status = psa_cipher_encrypt(library_key, iov->alg, input, input_length,
+ output, output_size, &out_vec[0].len);
+ if (status != PSA_SUCCESS) {
+ out_vec[0].len = 0;
+ }
return status;
+#endif
}
- status = psa_cipher_encrypt_setup(operation, encoded_key, alg);
- if (status != PSA_SUCCESS) {
- /* Release the operation context, ignore if the operation fails. */
- (void)tfm_crypto_operation_release(handle_out);
- return status;
- }
-
- 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;
+ if (sid == TFM_CRYPTO_CIPHER_DECRYPT_SID) {
+#if CRYPTO_SINGLE_PART_FUNCS_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;
-
- status = tfm_crypto_check_handle_owner(key_id, NULL);
- if (status != PSA_SUCCESS) {
- return status;
- }
-
- /* 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;
+ 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(library_key, iov->alg, input, input_length,
+ output, output_size, &out_vec[0].len);
+ if (status != PSA_SUCCESS) {
+ out_vec[0].len = 0;
+ }
+ return status;
+#endif
+ }
+
+ if ((sid == TFM_CRYPTO_CIPHER_ENCRYPT_SETUP_SID) ||
+ (sid == TFM_CRYPTO_CIPHER_DECRYPT_SETUP_SID)) {
+ p_handle = out_vec[0].base;
+ *p_handle = iov->op_handle;
+ status = tfm_crypto_operation_alloc(TFM_CRYPTO_CIPHER_OPERATION,
+ out_vec[0].base,
+ (void **)&operation);
+ } else {
+ status = tfm_crypto_operation_lookup(TFM_CRYPTO_CIPHER_OPERATION,
+ iov->op_handle,
+ (void **)&operation);
+ if ((sid == TFM_CRYPTO_CIPHER_FINISH_SID) ||
+ (sid == TFM_CRYPTO_CIPHER_ABORT_SID)) {
+ /*
+ * finish()/abort() interface put handle in out_vec[0].
+ * Therefore, out_vec[0] shall be specially set to original handle
+ * value. Otherwise, the garbage data in message out_vec[0] may
+ * override the original handle value in client, after lookup fails.
+ */
+ p_handle = out_vec[0].base;
+ *p_handle = iov->op_handle;
+ }
+ }
+ if (status != PSA_SUCCESS) {
+ if (sid == TFM_CRYPTO_CIPHER_ABORT_SID) {
+ /*
+ * Mbed TLS psa_cipher_abort() will return a misleading error code
+ * if it is called with invalid operation content, since it
+ * doesn't validate the operation handle.
+ * It is neither necessary to call tfm_crypto_operation_release()
+ * with an invalid handle.
+ * Therefore return PSA_SUCCESS directly as psa_cipher_abort() can
+ * be called multiple times.
+ */
+ return PSA_SUCCESS;
+ }
+ return status;
+ }
+
+ switch (sid) {
+ case TFM_CRYPTO_CIPHER_GENERATE_IV_SID:
+ {
+ unsigned char *iv = out_vec[0].base;
+ size_t iv_size = out_vec[0].len;
+
+ status = psa_cipher_generate_iv(operation, iv, iv_size, &out_vec[0].len);
+ if (status != PSA_SUCCESS) {
+ out_vec[0].len = 0;
+ }
+ return status;
+ }
+ case TFM_CRYPTO_CIPHER_SET_IV_SID:
+ {
+ const unsigned char *iv = in_vec[1].base;
+ size_t iv_length = in_vec[1].len;
+
+ return psa_cipher_set_iv(operation, iv, iv_length);
+ }
+ case TFM_CRYPTO_CIPHER_ENCRYPT_SETUP_SID:
+ {
+ status = psa_cipher_encrypt_setup(operation, library_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, library_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;
+
+ status = psa_cipher_update(operation, input, input_length,
+ output, output_size, &out_vec[0].len);
+ if (status != PSA_SUCCESS) {
+ out_vec[0].len = 0;
+ }
+ return status;
+ }
+ case TFM_CRYPTO_CIPHER_FINISH_SID:
+ {
+ uint8_t *output = out_vec[1].base;
+ size_t output_size = out_vec[1].len;
+
+ 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;
+ } else {
+ out_vec[1].len = 0;
+ }
+ }
+ break;
+ case TFM_CRYPTO_CIPHER_ABORT_SID:
+ {
+ status = psa_cipher_abort(operation);
+ goto release_operation_and_return;
+ }
+ default:
+ return PSA_ERROR_NOT_SUPPORTED;
}
- *handle_out = handle;
- status = tfm_crypto_encode_id_and_owner(key_id, &encoded_key);
- if (status != PSA_SUCCESS) {
- return status;
- }
-
- status = psa_cipher_decrypt_setup(operation, encoded_key, alg);
- if (status != PSA_SUCCESS) {
- /* Release the operation context, ignore if the operation fails. */
- (void)tfm_crypto_operation_release(handle_out);
- return status;
- }
-
- 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;
- }
-
- status = psa_cipher_update(operation, input, input_length,
- 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;
- }
-
- return status;
-#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;
- }
-
- status = 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;
- }
-
- status = tfm_crypto_operation_release(handle_out);
+release_operation_and_return:
+ /* Release the operation context, ignore if the operation fails. */
+ (void)tfm_crypto_operation_release(p_handle);
return status;
-#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)
+#else /* CRYPTO_CIPHER_MODULE_ENABLED */
+psa_status_t tfm_crypto_cipher_interface(psa_invec in_vec[],
+ psa_outvec out_vec[],
+ struct tfm_crypto_key_id_s *encoded_key)
{
- /* FixMe: To be implemented */
- return PSA_ERROR_NOT_SUPPORTED;
-}
+ (void)in_vec;
+ (void)out_vec;
+ (void)encoded_key;
-psa_status_t tfm_crypto_cipher_decrypt(psa_invec in_vec[],
- size_t in_len,
- psa_outvec out_vec[],
- size_t out_len)
-{
- /* FixMe: To be implemented */
return PSA_ERROR_NOT_SUPPORTED;
}
+#endif /* CRYPTO_CIPHER_MODULE_ENABLED */
/*!@}*/