Crypto: Add secure API interface
Adds a secure API interface to the Crypto service, so that secure
callers can call the PSA API interface directly without the workaround
of calling the TF-M Crypto veneers.
Change-Id: Icdcc12e460418835c2fd48c0720f8577241ba24a
Signed-off-by: Jamie Fox <jamie.fox@arm.com>
diff --git a/secure_fw/services/crypto/CMakeLists.inc b/secure_fw/services/crypto/CMakeLists.inc
index 3cf8dc2..c4b02cc 100644
--- a/secure_fw/services/crypto/CMakeLists.inc
+++ b/secure_fw/services/crypto/CMakeLists.inc
@@ -51,6 +51,7 @@
"${CRYPTO_DIR}/crypto_utils.c"
"${CRYPTO_DIR}/crypto_engine.c"
"${CRYPTO_DIR}/crypto_aead.c"
+ "${CRYPTO_DIR}/tfm_crypto_secure_api.c"
)
#Append all our source files to global lists.
diff --git a/secure_fw/services/crypto/tfm_crypto_secure_api.c b/secure_fw/services/crypto/tfm_crypto_secure_api.c
new file mode 100644
index 0000000..b1645c2
--- /dev/null
+++ b/secure_fw/services/crypto/tfm_crypto_secure_api.c
@@ -0,0 +1,462 @@
+/*
+ * Copyright (c) 2019, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include "tfm_crypto_veneers.h"
+#include "psa_crypto.h"
+#include "crypto_psa_wrappers.h"
+
+__attribute__(( section("SFN")))
+psa_status_t psa_crypto_init(void)
+{
+ /* Service init is performed during TFM boot up,
+ * so application level initialisation is empty
+ */
+ return PSA_SUCCESS;
+}
+
+__attribute__(( section("SFN")))
+psa_status_t psa_import_key(psa_key_slot_t key,
+ psa_key_type_t type,
+ const uint8_t *data,
+ size_t data_length)
+{
+ enum tfm_crypto_err_t err;
+
+ err = tfm_crypto_veneer_import_key(key, type, data, data_length);
+
+ return TFM_CRYPTO_ERR_TO_PSA_STATUS(err);
+}
+
+__attribute__(( section("SFN")))
+psa_status_t psa_destroy_key(psa_key_slot_t key)
+{
+ enum tfm_crypto_err_t err;
+
+ err = tfm_crypto_veneer_destroy_key(key);
+
+ return TFM_CRYPTO_ERR_TO_PSA_STATUS(err);
+}
+
+__attribute__(( section("SFN")))
+psa_status_t psa_get_key_information(psa_key_slot_t key,
+ psa_key_type_t *type,
+ size_t *bits)
+{
+ enum tfm_crypto_err_t err;
+
+ err = tfm_crypto_veneer_get_key_information(key, type, bits);
+
+ return TFM_CRYPTO_ERR_TO_PSA_STATUS(err);
+}
+
+__attribute__(( section("SFN")))
+psa_status_t psa_export_key(psa_key_slot_t key,
+ uint8_t *data,
+ size_t data_size,
+ size_t *data_length)
+{
+ enum tfm_crypto_err_t err;
+
+ err = tfm_crypto_veneer_export_key(key, data, data_size, data_length);
+
+ return TFM_CRYPTO_ERR_TO_PSA_STATUS(err);
+}
+
+__attribute__(( section("SFN")))
+psa_status_t psa_export_public_key(psa_key_slot_t key,
+ uint8_t *data,
+ size_t data_size,
+ size_t *data_length)
+{
+ /* TODO: This API is not supported yet */
+ return PSA_ERROR_NOT_SUPPORTED;
+}
+
+__attribute__(( section("SFN")))
+void psa_key_policy_init(psa_key_policy_t *policy)
+{
+ /* PSA API returns void so just ignore error value returned */
+ (void)tfm_crypto_veneer_key_policy_init(policy);
+}
+
+__attribute__(( section("SFN")))
+void psa_key_policy_set_usage(psa_key_policy_t *policy,
+ psa_key_usage_t usage,
+ psa_algorithm_t alg)
+{
+ /* PSA API returns void so just ignore error value returned */
+ (void)tfm_crypto_veneer_key_policy_set_usage(policy, usage, alg);
+}
+
+__attribute__(( section("SFN")))
+psa_key_usage_t psa_key_policy_get_usage(const psa_key_policy_t *policy)
+{
+ psa_key_usage_t usage;
+
+ /* Initialise to a sensible default to avoid returning an uninitialised
+ * value in case the secure function fails.
+ */
+ usage = 0;
+
+ /* The PSA API does not return an error, so ignore any error from TF-M */
+ (void)tfm_crypto_veneer_key_policy_get_usage(policy, &usage);
+
+ return usage;
+}
+
+__attribute__(( section("SFN")))
+psa_algorithm_t psa_key_policy_get_algorithm(const psa_key_policy_t *policy)
+{
+ psa_algorithm_t alg;
+
+ /* Initialise to a sensible default to avoid returning an uninitialised
+ * value in case the secure function fails.
+ */
+ alg = 0;
+
+ /* The PSA API does not return an error, so ignore any error from TF-M */
+ (void)tfm_crypto_veneer_key_policy_get_algorithm(policy, &alg);
+
+ return alg;
+}
+
+__attribute__(( section("SFN")))
+psa_status_t psa_set_key_policy(psa_key_slot_t key,
+ const psa_key_policy_t *policy)
+{
+ enum tfm_crypto_err_t err;
+
+ err = tfm_crypto_veneer_set_key_policy(key, policy);
+
+ return TFM_CRYPTO_ERR_TO_PSA_STATUS(err);
+}
+
+__attribute__(( section("SFN")))
+psa_status_t psa_get_key_policy(psa_key_slot_t key,
+ psa_key_policy_t *policy)
+{
+ enum tfm_crypto_err_t err;
+
+ err = tfm_crypto_veneer_get_key_policy(key, policy);
+
+ return TFM_CRYPTO_ERR_TO_PSA_STATUS(err);
+}
+
+__attribute__(( section("SFN")))
+psa_status_t psa_set_key_lifetime(psa_key_slot_t key,
+ psa_key_lifetime_t lifetime)
+{
+ enum tfm_crypto_err_t err;
+
+ err = tfm_crypto_veneer_set_key_lifetime(key, lifetime);
+
+ return TFM_CRYPTO_ERR_TO_PSA_STATUS(err);
+}
+
+__attribute__(( section("SFN")))
+psa_status_t psa_get_key_lifetime(psa_key_slot_t key,
+ psa_key_lifetime_t *lifetime)
+{
+ enum tfm_crypto_err_t err;
+
+ err = tfm_crypto_veneer_get_key_lifetime(key, lifetime);
+
+ return TFM_CRYPTO_ERR_TO_PSA_STATUS(err);
+}
+
+__attribute__(( section("SFN")))
+psa_status_t psa_cipher_set_iv(psa_cipher_operation_t *operation,
+ const unsigned char *iv,
+ size_t iv_length)
+{
+ enum tfm_crypto_err_t err;
+
+ err = tfm_crypto_veneer_cipher_set_iv(operation, iv, iv_length);
+
+ return TFM_CRYPTO_ERR_TO_PSA_STATUS(err);
+}
+
+__attribute__(( section("SFN")))
+psa_status_t psa_cipher_encrypt_setup(psa_cipher_operation_t *operation,
+ psa_key_slot_t key,
+ psa_algorithm_t alg)
+{
+ enum tfm_crypto_err_t err;
+
+ err = tfm_crypto_veneer_cipher_encrypt_setup(operation, key, alg);
+
+ return TFM_CRYPTO_ERR_TO_PSA_STATUS(err);
+}
+
+__attribute__(( section("SFN")))
+psa_status_t psa_cipher_decrypt_setup(psa_cipher_operation_t *operation,
+ psa_key_slot_t key,
+ psa_algorithm_t alg)
+{
+ enum tfm_crypto_err_t err;
+
+ err = tfm_crypto_veneer_cipher_decrypt_setup(operation, key, alg);
+
+ return TFM_CRYPTO_ERR_TO_PSA_STATUS(err);
+}
+
+__attribute__(( section("SFN")))
+psa_status_t psa_cipher_update(psa_cipher_operation_t *operation,
+ const uint8_t *input,
+ size_t input_length,
+ unsigned char *output,
+ size_t output_size,
+ size_t *output_length)
+{
+ enum tfm_crypto_err_t err;
+
+ /* Packing in structures is needed to overcome the 4 parameters
+ * per call limit
+ */
+ struct psa_cipher_update_input input_s = {.input = input,
+ .input_length = input_length};
+ struct psa_cipher_update_output output_s = {.output = output,
+ .output_size = output_size,
+ .output_length =
+ output_length};
+
+ err = tfm_crypto_veneer_cipher_update(operation, &input_s, &output_s);
+
+ return TFM_CRYPTO_ERR_TO_PSA_STATUS(err);
+}
+
+__attribute__(( section("SFN")))
+psa_status_t psa_cipher_abort(psa_cipher_operation_t *operation)
+{
+ enum tfm_crypto_err_t err;
+
+ err = tfm_crypto_veneer_cipher_abort(operation);
+
+ return TFM_CRYPTO_ERR_TO_PSA_STATUS(err);
+}
+
+__attribute__(( section("SFN")))
+psa_status_t psa_cipher_finish(psa_cipher_operation_t *operation,
+ uint8_t *output,
+ size_t output_size,
+ size_t *output_length)
+{
+ enum tfm_crypto_err_t err;
+
+ err = tfm_crypto_veneer_cipher_finish(operation, output, output_size,
+ output_length);
+
+ return TFM_CRYPTO_ERR_TO_PSA_STATUS(err);
+}
+
+__attribute__(( section("SFN")))
+psa_status_t psa_hash_setup(psa_hash_operation_t *operation,
+ psa_algorithm_t alg)
+{
+ enum tfm_crypto_err_t err;
+
+ err = tfm_crypto_veneer_hash_setup(operation, alg);
+
+ return TFM_CRYPTO_ERR_TO_PSA_STATUS(err);
+}
+
+__attribute__(( section("SFN")))
+psa_status_t psa_hash_update(psa_hash_operation_t *operation,
+ const uint8_t *input,
+ size_t input_length)
+{
+ enum tfm_crypto_err_t err;
+
+ err = tfm_crypto_veneer_hash_update(operation, input, input_length);
+
+ return TFM_CRYPTO_ERR_TO_PSA_STATUS(err);
+}
+
+__attribute__(( section("SFN")))
+psa_status_t psa_hash_finish(psa_hash_operation_t *operation,
+ uint8_t *hash,
+ size_t hash_size,
+ size_t *hash_length)
+{
+ enum tfm_crypto_err_t err;
+
+ err = tfm_crypto_veneer_hash_finish(operation, hash, hash_size,
+ hash_length);
+
+ return TFM_CRYPTO_ERR_TO_PSA_STATUS(err);
+}
+
+__attribute__(( section("SFN")))
+psa_status_t psa_hash_verify(psa_hash_operation_t *operation,
+ const uint8_t *hash,
+ size_t hash_length)
+{
+ enum tfm_crypto_err_t err;
+
+ err = tfm_crypto_veneer_hash_verify(operation, hash, hash_length);
+
+ return TFM_CRYPTO_ERR_TO_PSA_STATUS(err);
+}
+
+__attribute__(( section("SFN")))
+psa_status_t psa_hash_abort(psa_hash_operation_t *operation)
+{
+ enum tfm_crypto_err_t err;
+
+ err = tfm_crypto_veneer_hash_abort(operation);
+
+ return TFM_CRYPTO_ERR_TO_PSA_STATUS(err);
+}
+
+__attribute__(( section("SFN")))
+psa_status_t psa_mac_sign_setup(psa_mac_operation_t *operation,
+ psa_key_slot_t key,
+ psa_algorithm_t alg)
+{
+ enum tfm_crypto_err_t err;
+
+ err = tfm_crypto_veneer_mac_sign_setup(operation, key, alg);
+
+ return TFM_CRYPTO_ERR_TO_PSA_STATUS(err);
+}
+
+__attribute__(( section("SFN")))
+psa_status_t psa_mac_verify_setup(psa_mac_operation_t *operation,
+ psa_key_slot_t key,
+ psa_algorithm_t alg)
+{
+ enum tfm_crypto_err_t err;
+
+ err = tfm_crypto_veneer_mac_verify_setup(operation, key, alg);
+
+ return TFM_CRYPTO_ERR_TO_PSA_STATUS(err);
+}
+
+__attribute__(( section("SFN")))
+psa_status_t psa_mac_update(psa_mac_operation_t *operation,
+ const uint8_t *input,
+ size_t input_length)
+{
+ enum tfm_crypto_err_t err;
+
+ err = tfm_crypto_veneer_mac_update(operation, input, input_length);
+
+ return TFM_CRYPTO_ERR_TO_PSA_STATUS(err);
+}
+
+__attribute__(( section("SFN")))
+psa_status_t psa_mac_sign_finish(psa_mac_operation_t *operation,
+ uint8_t *mac,
+ size_t mac_size,
+ size_t *mac_length)
+{
+ enum tfm_crypto_err_t err;
+
+ err = tfm_crypto_veneer_mac_sign_finish(operation, mac, mac_size,
+ mac_length);
+
+ return TFM_CRYPTO_ERR_TO_PSA_STATUS(err);
+}
+
+__attribute__(( section("SFN")))
+psa_status_t psa_mac_verify_finish(psa_mac_operation_t *operation,
+ const uint8_t *mac,
+ size_t mac_length)
+{
+ enum tfm_crypto_err_t err;
+
+ err = tfm_crypto_veneer_mac_verify_finish(operation, mac, mac_length);
+
+ return TFM_CRYPTO_ERR_TO_PSA_STATUS(err);
+}
+
+__attribute__(( section("SFN")))
+psa_status_t psa_mac_abort(psa_mac_operation_t *operation)
+{
+ enum tfm_crypto_err_t err;
+
+ err = tfm_crypto_veneer_mac_abort(operation);
+
+ return TFM_CRYPTO_ERR_TO_PSA_STATUS(err);
+}
+
+__attribute__(( section("SFN")))
+psa_status_t psa_aead_encrypt(psa_key_slot_t key,
+ psa_algorithm_t alg,
+ const uint8_t *nonce,
+ size_t nonce_length,
+ const uint8_t *additional_data,
+ size_t additional_data_length,
+ const uint8_t *plaintext,
+ size_t plaintext_length,
+ uint8_t *ciphertext,
+ size_t ciphertext_size,
+ size_t *ciphertext_length)
+{
+ enum tfm_crypto_err_t err;
+
+ /* Packing in structures is needed to overcome the 4 parameters
+ * per call limit
+ */
+ struct psa_aead_encrypt_input input_s = {.key = key,
+ .alg = alg,
+ .nonce = nonce,
+ .nonce_length = nonce_length,
+ .additional_data = additional_data,
+ .additional_data_length =
+ additional_data_length,
+ .plaintext = plaintext,
+ .plaintext_length =
+ plaintext_length};
+ struct psa_aead_encrypt_output output_s = {.ciphertext = ciphertext,
+ .ciphertext_size =
+ ciphertext_size,
+ .ciphertext_length =
+ ciphertext_length};
+
+ err = tfm_crypto_veneer_aead_encrypt(&input_s, &output_s);
+
+ return TFM_CRYPTO_ERR_TO_PSA_STATUS(err);
+}
+
+__attribute__(( section("SFN")))
+psa_status_t psa_aead_decrypt(psa_key_slot_t key,
+ psa_algorithm_t alg,
+ const uint8_t *nonce,
+ size_t nonce_length,
+ const uint8_t *additional_data,
+ size_t additional_data_length,
+ const uint8_t *ciphertext,
+ size_t ciphertext_length,
+ uint8_t *plaintext,
+ size_t plaintext_size,
+ size_t *plaintext_length)
+{
+ enum tfm_crypto_err_t err;
+
+ /* Packing in structures is needed to overcome the 4 parameters
+ * per call limit
+ */
+ struct psa_aead_decrypt_input input_s = {.key = key,
+ .alg = alg,
+ .nonce = nonce,
+ .nonce_length = nonce_length,
+ .additional_data = additional_data,
+ .additional_data_length =
+ additional_data_length,
+ .ciphertext = ciphertext,
+ .ciphertext_length =
+ ciphertext_length};
+ struct psa_aead_decrypt_output output_s = {.plaintext = plaintext,
+ .plaintext_size = plaintext_size,
+ .plaintext_length =
+ plaintext_length};
+
+ err = tfm_crypto_veneer_aead_decrypt(&input_s, &output_s);
+
+ return TFM_CRYPTO_ERR_TO_PSA_STATUS(err);
+}
diff --git a/test/suites/crypto/secure/crypto_sec_interface_testsuite.c b/test/suites/crypto/secure/crypto_sec_interface_testsuite.c
index 24a85f1..16b62f8 100644
--- a/test/suites/crypto/secure/crypto_sec_interface_testsuite.c
+++ b/test/suites/crypto/secure/crypto_sec_interface_testsuite.c
@@ -8,7 +8,7 @@
#include <stdio.h>
#include "test/framework/test_framework_helpers.h"
-#include "tfm_crypto_veneers.h"
+#include "psa_crypto.h"
#define BIT_SIZE_TEST_KEY (128)
#define BYTE_SIZE_TEST_KEY (BIT_SIZE_TEST_KEY/8)
@@ -38,7 +38,7 @@
*/
static void tfm_crypto_test_5001(struct test_result_t *ret)
{
- enum tfm_crypto_err_t err;
+ psa_status_t status;
uint32_t i = 0;
const psa_key_slot_t slot = TEST_KEY_SLOT;
uint8_t data[] = "THIS IS MY KEY1";
@@ -49,26 +49,22 @@
psa_key_policy_t policy;
/* Setup the key policy */
- tfm_crypto_veneer_key_policy_init(&policy);
- tfm_crypto_veneer_key_policy_set_usage(&policy, PSA_KEY_USAGE_EXPORT, 0);
- err = tfm_crypto_veneer_set_key_policy(slot, &policy);
- if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
+ psa_key_policy_init(&policy);
+ psa_key_policy_set_usage(&policy, PSA_KEY_USAGE_EXPORT, 0);
+ status = psa_set_key_policy(slot, &policy);
+ if (status != PSA_SUCCESS) {
TEST_FAIL("Failed to set key policy");
return;
}
- err = tfm_crypto_veneer_import_key(slot,
- PSA_KEY_TYPE_AES,
- data,
- sizeof(data));
-
- if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
+ status = psa_import_key(slot, PSA_KEY_TYPE_AES, data, sizeof(data));
+ if (status != PSA_SUCCESS) {
TEST_FAIL("Error importing a key");
return;
}
- err = tfm_crypto_veneer_get_key_information(slot, &type, &bits);
- if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
+ status = psa_get_key_information(slot, &type, &bits);
+ if (status != PSA_SUCCESS) {
TEST_FAIL("Error getting key metadata");
return;
}
@@ -83,12 +79,12 @@
return;
}
- err = tfm_crypto_veneer_export_key(slot,
- exported_data,
- sizeof(data),
- &exported_data_size);
+ status = psa_export_key(slot,
+ exported_data,
+ sizeof(data),
+ &exported_data_size);
- if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
+ if (status != PSA_SUCCESS) {
TEST_FAIL("Error exporting a key");
return;
}
@@ -106,14 +102,14 @@
}
}
- err = tfm_crypto_veneer_destroy_key(slot);
- if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
+ status = psa_destroy_key(slot);
+ if (status != PSA_SUCCESS) {
TEST_FAIL("Error destroying the key");
return;
}
- err = tfm_crypto_veneer_get_key_information(slot, &type, &bits);
- if (err != TFM_CRYPTO_ERR_PSA_ERROR_EMPTY_SLOT) {
+ status = psa_get_key_information(slot, &type, &bits);
+ if (status != PSA_ERROR_EMPTY_SLOT) {
TEST_FAIL("Key slot should be empty now");
return;
}