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;
     }