| /* |
| * Copyright (c) 2019-2020, 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_crypto_private.h" |
| |
| /*! |
| * \defgroup public_psa Public functions, PSA |
| * |
| */ |
| |
| /*!@{*/ |
| psa_status_t tfm_crypto_sign_hash(psa_invec in_vec[], |
| size_t in_len, |
| psa_outvec out_vec[], |
| size_t out_len) |
| { |
| #ifdef TFM_CRYPTO_ASYMMETRIC_MODULE_DISABLED |
| return PSA_ERROR_NOT_SUPPORTED; |
| #else |
| CRYPTO_IN_OUT_LEN_VALIDATE(in_len, 1, 2, out_len, 0, 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_handle_t handle = iov->key_handle; |
| psa_algorithm_t alg = iov->alg; |
| const uint8_t *hash = in_vec[1].base; |
| size_t hash_length = in_vec[1].len; |
| uint8_t *signature = out_vec[0].base; |
| size_t signature_size = out_vec[0].len; |
| psa_status_t status = tfm_crypto_check_handle_owner(handle, NULL); |
| |
| if (status != PSA_SUCCESS) { |
| return status; |
| } |
| |
| return psa_sign_hash(handle, alg, hash, hash_length, |
| signature, signature_size, &(out_vec[0].len)); |
| #endif /* TFM_CRYPTO_ASYMMETRIC_MODULE_DISABLED */ |
| } |
| |
| psa_status_t tfm_crypto_verify_hash(psa_invec in_vec[], |
| size_t in_len, |
| psa_outvec out_vec[], |
| size_t out_len) |
| { |
| #ifdef TFM_CRYPTO_ASYMMETRIC_MODULE_DISABLED |
| return PSA_ERROR_NOT_SUPPORTED; |
| #else |
| CRYPTO_IN_OUT_LEN_VALIDATE(in_len, 1, 3, out_len, 0, 0); |
| |
| 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_handle_t handle = iov->key_handle; |
| psa_algorithm_t alg = iov->alg; |
| const uint8_t *hash = in_vec[1].base; |
| size_t hash_length = in_vec[1].len; |
| const uint8_t *signature = in_vec[2].base; |
| size_t signature_length = in_vec[2].len; |
| psa_status_t status = tfm_crypto_check_handle_owner(handle, NULL); |
| |
| if (status != PSA_SUCCESS) { |
| return status; |
| } |
| |
| return psa_verify_hash(handle, alg, hash, hash_length, |
| signature, signature_length); |
| #endif /* TFM_CRYPTO_ASYMMETRIC_MODULE_DISABLED */ |
| } |
| |
| psa_status_t tfm_crypto_asymmetric_encrypt(psa_invec in_vec[], |
| size_t in_len, |
| psa_outvec out_vec[], |
| size_t out_len) |
| { |
| #ifdef TFM_CRYPTO_ASYMMETRIC_MODULE_DISABLED |
| return PSA_ERROR_NOT_SUPPORTED; |
| #else |
| psa_status_t status; |
| |
| CRYPTO_IN_OUT_LEN_VALIDATE(in_len, 1, 3, out_len, 0, 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_handle_t handle = iov->key_handle; |
| psa_algorithm_t alg = iov->alg; |
| const uint8_t *input = in_vec[1].base; |
| size_t input_length = in_vec[1].len; |
| const uint8_t *salt = in_vec[2].base; |
| size_t salt_length = in_vec[2].len; |
| uint8_t *output = out_vec[0].base; |
| size_t output_size = out_vec[0].len; |
| psa_key_type_t type; |
| size_t key_bits; |
| psa_key_attributes_t key_attributes = PSA_KEY_ATTRIBUTES_INIT; |
| |
| status = tfm_crypto_check_handle_owner(handle, NULL); |
| if (status != PSA_SUCCESS) { |
| return status; |
| } |
| |
| status = psa_get_key_attributes(handle, &key_attributes); |
| if (status != PSA_SUCCESS) { |
| return status; |
| } |
| |
| key_bits = psa_get_key_bits(&key_attributes); |
| type = psa_get_key_type(&key_attributes); |
| |
| psa_reset_key_attributes(&key_attributes); |
| |
| /* Check that the output buffer is large enough */ |
| if (output_size < PSA_ASYMMETRIC_ENCRYPT_OUTPUT_SIZE(type, key_bits, alg)) { |
| return PSA_ERROR_BUFFER_TOO_SMALL; |
| } |
| |
| return psa_asymmetric_encrypt(handle, alg, input, input_length, |
| salt, salt_length, |
| output, output_size, &(out_vec[0].len)); |
| #endif /* TFM_CRYPTO_ASYMMETRIC_MODULE_DISABLED */ |
| } |
| |
| psa_status_t tfm_crypto_asymmetric_decrypt(psa_invec in_vec[], |
| size_t in_len, |
| psa_outvec out_vec[], |
| size_t out_len) |
| { |
| #ifdef TFM_CRYPTO_ASYMMETRIC_MODULE_DISABLED |
| return PSA_ERROR_NOT_SUPPORTED; |
| #else |
| |
| CRYPTO_IN_OUT_LEN_VALIDATE(in_len, 1, 3, out_len, 0, 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_handle_t handle = iov->key_handle; |
| psa_algorithm_t alg = iov->alg; |
| const uint8_t *input = in_vec[1].base; |
| size_t input_length = in_vec[1].len; |
| const uint8_t *salt = in_vec[2].base; |
| size_t salt_length = in_vec[2].len; |
| uint8_t *output = out_vec[0].base; |
| size_t output_size = out_vec[0].len; |
| psa_status_t status; |
| |
| status = tfm_crypto_check_handle_owner(handle, NULL); |
| if (status != PSA_SUCCESS) { |
| return status; |
| } |
| |
| return psa_asymmetric_decrypt(handle, alg, input, input_length, |
| salt, salt_length, |
| output, output_size, &(out_vec[0].len)); |
| #endif /* TFM_CRYPTO_ASYMMETRIC_MODULE_DISABLED */ |
| } |
| /*!@}*/ |