blob: be8e83c5578c619215505dcefdf349b27df35ff4 [file] [log] [blame]
/*
* Copyright (c) 2018-2022, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*
*/
#include <stddef.h>
#include <stdint.h>
#include "tfm_mbedcrypto_include.h"
#include "tfm_crypto_api.h"
#include "tfm_crypto_defs.h"
#include "tfm_memory_utils.h"
/**
* \def TFM_CRYPTO_CONC_OPER_NUM
*
* \brief This is the default value for the maximum number of concurrent
* operations that can be active (allocated) at any time, supported
* by the implementation
*/
#ifndef TFM_CRYPTO_CONC_OPER_NUM
#define TFM_CRYPTO_CONC_OPER_NUM (8)
#endif
struct tfm_crypto_operation_s {
uint32_t in_use; /*!< Indicates if the operation is in use */
int32_t owner; /*!< Indicates an ID of the owner of
* the context
*/
enum tfm_crypto_operation_type type; /*!< Type of the operation */
union {
psa_cipher_operation_t cipher; /*!< Cipher operation context */
psa_mac_operation_t mac; /*!< MAC operation context */
psa_hash_operation_t hash; /*!< Hash operation context */
psa_key_derivation_operation_t key_deriv; /*!< Key derivation operation context */
psa_aead_operation_t aead; /*!< AEAD operation context */
} operation;
};
static struct tfm_crypto_operation_s operation[TFM_CRYPTO_CONC_OPER_NUM] ={{0}};
/*
* \brief Function used to clear the memory associated to a backend context
*
* \param[in] index Numerical index in the database of the backend contexts
*
* \return None
*
*/
static void memset_operation_context(uint32_t index)
{
uint32_t mem_size;
uint8_t *mem_ptr = (uint8_t *) &(operation[index].operation);
switch(operation[index].type) {
case TFM_CRYPTO_CIPHER_OPERATION:
mem_size = sizeof(psa_cipher_operation_t);
break;
case TFM_CRYPTO_MAC_OPERATION:
mem_size = sizeof(psa_mac_operation_t);
break;
case TFM_CRYPTO_HASH_OPERATION:
mem_size = sizeof(psa_hash_operation_t);
break;
case TFM_CRYPTO_KEY_DERIVATION_OPERATION:
mem_size = sizeof(psa_key_derivation_operation_t);
break;
case TFM_CRYPTO_AEAD_OPERATION:
mem_size = sizeof(psa_aead_operation_t);
break;
case TFM_CRYPTO_OPERATION_NONE:
default:
mem_size = 0;
break;
}
/* Clear the contents of the backend context */
(void)tfm_memset(mem_ptr, 0, mem_size);
}
/*!
* \defgroup public Public functions
*
*/
/*!@{*/
psa_status_t tfm_crypto_init_alloc(void)
{
/* Clear the contents of the local contexts */
(void)tfm_memset(operation, 0, sizeof(operation));
return PSA_SUCCESS;
}
psa_status_t tfm_crypto_operation_alloc(enum tfm_crypto_operation_type type,
uint32_t *handle,
void **ctx)
{
uint32_t i = 0;
int32_t partition_id = 0;
psa_status_t status;
status = tfm_crypto_get_caller_id(&partition_id);
if (status != PSA_SUCCESS) {
return status;
}
/* Handle must be initialised before calling a setup function */
if (*handle != TFM_CRYPTO_INVALID_HANDLE) {
if ((*handle <= TFM_CRYPTO_CONC_OPER_NUM) &&
(operation[*handle - 1].in_use == TFM_CRYPTO_IN_USE) &&
(operation[*handle - 1].owner == partition_id)) {
/* The handle is a valid one for already in progress operation */
return PSA_ERROR_BAD_STATE;
}
return PSA_ERROR_INVALID_HANDLE;
}
/* Init to invalid values */
if (ctx == NULL) {
return PSA_ERROR_INVALID_ARGUMENT;
}
*ctx = NULL;
for (i=0; i<TFM_CRYPTO_CONC_OPER_NUM; i++) {
if (operation[i].in_use == TFM_CRYPTO_NOT_IN_USE) {
operation[i].in_use = TFM_CRYPTO_IN_USE;
operation[i].owner = partition_id;
operation[i].type = type;
*handle = i + 1;
*ctx = (void *) &(operation[i].operation);
return PSA_SUCCESS;
}
}
return PSA_ERROR_NOT_PERMITTED;
}
psa_status_t tfm_crypto_operation_release(uint32_t *handle)
{
uint32_t h_val = *handle;
int32_t partition_id = 0;
psa_status_t status;
status = tfm_crypto_get_caller_id(&partition_id);
if (status != PSA_SUCCESS) {
return status;
}
if ( (h_val != TFM_CRYPTO_INVALID_HANDLE) &&
(h_val <= TFM_CRYPTO_CONC_OPER_NUM) &&
(operation[h_val - 1].in_use == TFM_CRYPTO_IN_USE) &&
(operation[h_val - 1].owner == partition_id)) {
memset_operation_context(h_val - 1);
operation[h_val - 1].in_use = TFM_CRYPTO_NOT_IN_USE;
operation[h_val - 1].type = TFM_CRYPTO_OPERATION_NONE;
operation[h_val - 1].owner = 0;
*handle = TFM_CRYPTO_INVALID_HANDLE;
return PSA_SUCCESS;
}
return PSA_ERROR_INVALID_ARGUMENT;
}
psa_status_t tfm_crypto_operation_lookup(enum tfm_crypto_operation_type type,
uint32_t handle,
void **ctx)
{
int32_t partition_id = 0;
psa_status_t status;
status = tfm_crypto_get_caller_id(&partition_id);
if (status != PSA_SUCCESS) {
return status;
}
if ( (handle != TFM_CRYPTO_INVALID_HANDLE) &&
(handle <= TFM_CRYPTO_CONC_OPER_NUM) &&
(operation[handle - 1].in_use == TFM_CRYPTO_IN_USE) &&
(operation[handle - 1].type == type) &&
(operation[handle - 1].owner == partition_id)) {
*ctx = (void *) &(operation[handle - 1].operation);
return PSA_SUCCESS;
}
return PSA_ERROR_BAD_STATE;
}
/*!@}*/