blob: e577984a9cb8bdbede04265beb0a3942cb37dbe5 [file] [log] [blame]
/*
* Copyright (c) 2019-2022, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*
*/
#include <stddef.h>
#include <stdint.h>
#include <string.h>
#include "config_tfm.h"
#include "tfm_sp_log.h"
#include "tfm_mbedcrypto_include.h"
#include "tfm_crypto_api.h"
#include "tfm_crypto_key.h"
#include "tfm_crypto_defs.h"
#include "crypto_library.h"
/*!
* \addtogroup tfm_crypto_api_shim_layer
*
*/
/*!@{*/
#if CRYPTO_KEY_DERIVATION_MODULE_ENABLED
psa_status_t tfm_crypto_key_derivation_interface(psa_invec in_vec[],
psa_outvec out_vec[],
struct tfm_crypto_key_id_s *encoded_key)
{
const struct tfm_crypto_pack_iovec *iov = in_vec[0].base;
psa_status_t status = PSA_ERROR_NOT_SUPPORTED;
psa_key_derivation_operation_t *operation = NULL;
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_RAW_KEY_AGREEMENT_SID) {
uint8_t *output = out_vec[0].base;
size_t output_size = out_vec[0].len;
const uint8_t *peer_key = in_vec[1].base;
size_t peer_key_length = in_vec[1].len;
return psa_raw_key_agreement(iov->alg, library_key,
peer_key, peer_key_length,
output, output_size, &out_vec[0].len);
}
if (sid == TFM_CRYPTO_KEY_DERIVATION_SETUP_SID) {
p_handle = out_vec[0].base;
*p_handle = iov->op_handle;
status = tfm_crypto_operation_alloc(TFM_CRYPTO_KEY_DERIVATION_OPERATION,
out_vec[0].base,
(void **)&operation);
} else {
status = tfm_crypto_operation_lookup(
TFM_CRYPTO_KEY_DERIVATION_OPERATION,
iov->op_handle,
(void **)&operation);
}
if ((status != PSA_SUCCESS) &&
(sid != TFM_CRYPTO_KEY_DERIVATION_ABORT_SID)) {
return status;
}
switch (sid) {
case TFM_CRYPTO_KEY_DERIVATION_SETUP_SID:
{
status = psa_key_derivation_setup(operation, iov->alg);
if (status != PSA_SUCCESS) {
goto release_operation_and_return;
}
}
break;
case TFM_CRYPTO_KEY_DERIVATION_GET_CAPACITY_SID:
{
size_t *capacity = out_vec[0].base;
return psa_key_derivation_get_capacity(operation, capacity);
}
case TFM_CRYPTO_KEY_DERIVATION_SET_CAPACITY_SID:
{
return psa_key_derivation_set_capacity(operation, iov->capacity);
}
case TFM_CRYPTO_KEY_DERIVATION_INPUT_BYTES_SID:
{
const uint8_t *data = in_vec[1].base;
size_t data_length = in_vec[1].len;
return psa_key_derivation_input_bytes(operation, iov->step, data,
data_length);
}
case TFM_CRYPTO_KEY_DERIVATION_INPUT_INTEGER_SID:
{
return psa_key_derivation_input_integer(operation, iov->step, iov->value);
}
case TFM_CRYPTO_KEY_DERIVATION_OUTPUT_BYTES_SID:
{
uint8_t *output = out_vec[0].base;
size_t output_length = out_vec[0].len;
return psa_key_derivation_output_bytes(operation,
output, output_length);
}
case TFM_CRYPTO_KEY_DERIVATION_INPUT_KEY_SID:
{
return psa_key_derivation_input_key(operation,
iov->step, library_key);
}
case TFM_CRYPTO_KEY_DERIVATION_OUTPUT_KEY_SID:
{
psa_key_id_t *key_handle = out_vec[0].base;
psa_key_attributes_t srv_key_attr;
memcpy(&srv_key_attr, in_vec[1].base, in_vec[1].len);
tfm_crypto_library_get_library_key_id_set_owner(encoded_key->owner, &srv_key_attr);
status = psa_key_derivation_output_key(&srv_key_attr, operation,
&library_key);
*key_handle = CRYPTO_LIBRARY_GET_KEY_ID(library_key);
}
break;
case TFM_CRYPTO_KEY_DERIVATION_ABORT_SID:
{
p_handle = out_vec[0].base;
*p_handle = iov->op_handle;
if (status != PSA_SUCCESS) {
/*
* If lookup() failed to find out a valid operation, it is not
* an error for _abort(), as it is allowed to be called multiple
* times, and it is likely the operation has just already been
* aborted.
*/
return PSA_SUCCESS;
}
status = psa_key_derivation_abort(operation);
goto release_operation_and_return;
}
case TFM_CRYPTO_KEY_DERIVATION_KEY_AGREEMENT_SID:
{
const uint8_t *peer_key = in_vec[1].base;
size_t peer_key_length = in_vec[1].len;
return psa_key_derivation_key_agreement(operation, iov->step,
library_key,
peer_key,
peer_key_length);
}
break;
default:
return PSA_ERROR_NOT_SUPPORTED;
}
return status;
release_operation_and_return:
/* Release the operation context, ignore if the operation fails. */
(void)tfm_crypto_operation_release(p_handle);
return status;
}
#else /* CRYPTO_KEY_DERIVATION_MODULE_ENABLED */
psa_status_t tfm_crypto_key_derivation_interface(psa_invec in_vec[],
psa_outvec out_vec[],
struct tfm_crypto_key_id_s *encoded_key)
{
(void)in_vec;
(void)out_vec;
(void)encoded_key;
return PSA_ERROR_NOT_SUPPORTED;
}
#endif /* CRYPTO_KEY_DERIVATION_MODULE_ENABLED */
/*!@}*/