Crypto: Align to Mbed Crypto 3.0.1

This patch upgrades the Crypto service to be able
to use Mbed Crypto 3.0.1:

- Updates the PSA crypto headers to latest available in mbed-crypto
- Updates the service implementation
- Updates the test suites where needed
- Updates the SST and Attestation interfaces
  towards cryptographic functionalities
- Updates documentation to reflect updated
  requirements, and changes in the integration guide

This patch migrates the use of psa_asymmetric_sign() and
psa_asymmetric_verify() to the non-deprecated versions of
the API psa_sign_hash() and psa_verify_hash().

Signed-off-by: Antonio de Angelis <antonio.deangelis@arm.com>
Change-Id: I7d8275def2336c1b5cfb8847b2842c305cfab116
diff --git a/secure_fw/services/crypto/crypto_key_derivation.c b/secure_fw/services/crypto/crypto_key_derivation.c
new file mode 100644
index 0000000..80958f5
--- /dev/null
+++ b/secure_fw/services/crypto/crypto_key_derivation.c
@@ -0,0 +1,447 @@
+/*
+ * Copyright (c) 2019, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <stddef.h>
+#include <stdint.h>
+
+/* FixMe: Use PSA_ERROR_CONNECTION_REFUSED when performing parameter
+ *        integrity checks but this will have to be revised
+ *        when the full set of error codes mandated by PSA FF
+ *        is available.
+ */
+#include "tfm_mbedcrypto_include.h"
+
+#include "tfm_crypto_api.h"
+#include "tfm_crypto_defs.h"
+
+/*!
+ * \defgroup public_psa Public functions, PSA
+ *
+ */
+
+/*!@{*/
+psa_status_t tfm_crypto_key_derivation_setup(psa_invec in_vec[],
+                                             size_t in_len,
+                                             psa_outvec out_vec[],
+                                             size_t out_len)
+{
+#ifdef TFM_CRYPTO_KEY_DERIVATION_MODULE_DISABLED
+    return PSA_ERROR_NOT_SUPPORTED;
+#else
+    psa_status_t status = PSA_SUCCESS;
+    psa_key_derivation_operation_t *operation = NULL;
+
+    if ((in_len != 1) || (out_len != 1)) {
+        return PSA_ERROR_CONNECTION_REFUSED;
+    }
+
+    if ((out_vec[0].len != sizeof(uint32_t)) ||
+        (in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec))) {
+        return PSA_ERROR_CONNECTION_REFUSED;
+    }
+    const struct tfm_crypto_pack_iovec *iov = in_vec[0].base;
+    uint32_t handle = iov->op_handle;
+    uint32_t *handle_out = out_vec[0].base;
+    psa_algorithm_t alg = iov->alg;
+
+    /* Allocate the operation context in the secure world */
+    status = tfm_crypto_operation_alloc(TFM_CRYPTO_KEY_DERIVATION_OPERATION,
+                                        &handle,
+                                        (void **)&operation);
+    if (status != PSA_SUCCESS) {
+        return status;
+    }
+
+    *handle_out = handle;
+
+    status = psa_key_derivation_setup(operation, alg);
+    if (status != PSA_SUCCESS) {
+        /* Release the operation context, ignore if the operation fails. */
+        (void)tfm_crypto_operation_release(handle_out);
+        return status;
+    }
+
+    return status;
+#endif /* TFM_CRYPTO_KEY_DERIVATION_MODULE_DISABLED */
+}
+
+psa_status_t tfm_crypto_key_derivation_get_capacity(psa_invec in_vec[],
+                                                    size_t in_len,
+                                                    psa_outvec out_vec[],
+                                                    size_t out_len)
+{
+#ifdef TFM_CRYPTO_KEY_DERIVATION_MODULE_DISABLED
+    return PSA_ERROR_NOT_SUPPORTED;
+#else
+    psa_status_t status;
+    if ((in_len != 1) || (out_len != 1)) {
+        return PSA_ERROR_CONNECTION_REFUSED;
+    }
+
+    if ((in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec)) ||
+        (out_vec[0].len != sizeof(size_t))) {
+        return PSA_ERROR_CONNECTION_REFUSED;
+    }
+    const struct tfm_crypto_pack_iovec *iov = in_vec[0].base;
+
+    uint32_t handle = iov->op_handle;
+    size_t *capacity = out_vec[0].base;
+    psa_key_derivation_operation_t *operation = NULL;
+
+    /* Look up the corresponding operation context */
+    status = tfm_crypto_operation_lookup(TFM_CRYPTO_KEY_DERIVATION_OPERATION,
+                                         handle,
+                                         (void **)&operation);
+    if (status != PSA_SUCCESS) {
+        *capacity = 0;
+        return status;
+    }
+
+    return psa_key_derivation_get_capacity(operation, capacity);
+#endif /* TFM_CRYPTO_KEY_DERIVATION_MODULE_DISABLED */
+}
+
+psa_status_t tfm_crypto_key_derivation_set_capacity(psa_invec in_vec[],
+                                                    size_t in_len,
+                                                    psa_outvec out_vec[],
+                                                    size_t out_len)
+{
+#ifdef TFM_CRYPTO_KEY_DERIVATION_MODULE_DISABLED
+    return PSA_ERROR_NOT_SUPPORTED;
+#else
+    psa_status_t status;
+    if ((in_len != 1) || (out_len != 0)) {
+        return PSA_ERROR_CONNECTION_REFUSED;
+    }
+
+    if ((in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec))) {
+        return PSA_ERROR_CONNECTION_REFUSED;
+    }
+    const struct tfm_crypto_pack_iovec *iov = in_vec[0].base;
+
+    uint32_t handle = iov->op_handle;
+    size_t capacity = iov->capacity;
+    psa_key_derivation_operation_t *operation = NULL;
+
+    /* Look up the corresponding operation context */
+    status = tfm_crypto_operation_lookup(TFM_CRYPTO_KEY_DERIVATION_OPERATION,
+                                         handle,
+                                         (void **)&operation);
+    if (status != PSA_SUCCESS) {
+        return status;
+    }
+
+    return psa_key_derivation_set_capacity(operation, capacity);
+#endif /* TFM_CRYPTO_KEY_DERIVATION_MODULE_DISABLED */
+}
+
+psa_status_t tfm_crypto_key_derivation_input_bytes(psa_invec in_vec[],
+                                                   size_t in_len,
+                                                   psa_outvec out_vec[],
+                                                   size_t out_len)
+{
+#ifdef TFM_CRYPTO_KEY_DERIVATION_MODULE_DISABLED
+    return PSA_ERROR_NOT_SUPPORTED;
+#else
+    psa_status_t status;
+    if ((in_len != 2) || (out_len != 0)) {
+        return PSA_ERROR_CONNECTION_REFUSED;
+    }
+
+    if ((in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec))) {
+        return PSA_ERROR_CONNECTION_REFUSED;
+    }
+    const struct tfm_crypto_pack_iovec *iov = in_vec[0].base;
+
+    uint32_t handle = iov->op_handle;
+    psa_key_derivation_step_t step = iov->step;
+    const uint8_t *data = in_vec[1].base;
+    size_t data_length = in_vec[1].len;
+    psa_key_derivation_operation_t *operation = NULL;
+
+    /* Look up the corresponding operation context */
+    status = tfm_crypto_operation_lookup(TFM_CRYPTO_KEY_DERIVATION_OPERATION,
+                                         handle,
+                                         (void **)&operation);
+    if (status != PSA_SUCCESS) {
+        return status;
+    }
+
+    return psa_key_derivation_input_bytes(operation, step, data, data_length);
+#endif /* TFM_CRYPTO_KEY_DERIVATION_MODULE_DISABLED */
+}
+
+psa_status_t tfm_crypto_key_derivation_output_bytes(psa_invec in_vec[],
+                                                    size_t in_len,
+                                                    psa_outvec out_vec[],
+                                                    size_t out_len)
+{
+#ifdef TFM_CRYPTO_KEY_DERIVATION_MODULE_DISABLED
+    return PSA_ERROR_NOT_SUPPORTED;
+#else
+    psa_status_t status;
+    if ((in_len != 1) || (out_len != 1)) {
+        return PSA_ERROR_CONNECTION_REFUSED;
+    }
+
+    if ((in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec))) {
+        return PSA_ERROR_CONNECTION_REFUSED;
+    }
+    const struct tfm_crypto_pack_iovec *iov = in_vec[0].base;
+
+    uint32_t handle = iov->op_handle;
+    uint8_t *output = out_vec[0].base;
+    size_t output_length = out_vec[0].len;
+    psa_key_derivation_operation_t *operation = NULL;
+
+    /* Look up the corresponding operation context */
+    status = tfm_crypto_operation_lookup(TFM_CRYPTO_KEY_DERIVATION_OPERATION,
+                                         handle,
+                                         (void **)&operation);
+    if (status != PSA_SUCCESS) {
+        return status;
+    }
+
+    return psa_key_derivation_output_bytes(operation, output, output_length);
+#endif /* TFM_CRYPTO_KEY_DERIVATION_MODULE_DISABLED */
+}
+
+psa_status_t tfm_crypto_key_derivation_input_key(psa_invec in_vec[],
+                                                 size_t in_len,
+                                                 psa_outvec out_vec[],
+                                                 size_t out_len)
+{
+#ifdef TFM_CRYPTO_KEY_DERIVATION_MODULE_DISABLED
+    return PSA_ERROR_NOT_SUPPORTED;
+#else
+    psa_status_t status;
+    if ((in_len != 1) || (out_len != 0)) {
+        return PSA_ERROR_CONNECTION_REFUSED;
+    }
+
+    if ((in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec))) {
+        return PSA_ERROR_CONNECTION_REFUSED;
+    }
+    const struct tfm_crypto_pack_iovec *iov = in_vec[0].base;
+
+    uint32_t handle = iov->op_handle;
+    psa_key_handle_t key_handle = iov->key_handle;
+    psa_key_derivation_step_t step = iov->step;
+    psa_key_derivation_operation_t *operation = NULL;
+
+    status = tfm_crypto_check_handle_owner(key_handle, NULL);
+    if (status != PSA_SUCCESS) {
+        return status;
+    }
+
+    /* Look up the corresponding operation context */
+    status = tfm_crypto_operation_lookup(TFM_CRYPTO_KEY_DERIVATION_OPERATION,
+                                         handle,
+                                         (void **)&operation);
+    if (status != PSA_SUCCESS) {
+        return status;
+    }
+
+    return psa_key_derivation_input_key(operation, step, key_handle);
+#endif /* TFM_CRYPTO_KEY_DERIVATION_MODULE_DISABLED */
+}
+
+psa_status_t tfm_crypto_key_derivation_output_key(psa_invec in_vec[],
+                                                  size_t in_len,
+                                                  psa_outvec out_vec[],
+                                                  size_t out_len)
+{
+#ifdef TFM_CRYPTO_KEY_DERIVATION_MODULE_DISABLED
+    return PSA_ERROR_NOT_SUPPORTED;
+#else
+    psa_status_t status;
+    if ((in_len != 2) || (out_len != 1)) {
+        return PSA_ERROR_CONNECTION_REFUSED;
+    }
+
+    if ((in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec)) ||
+        (in_vec[1].len != sizeof(psa_key_attributes_t)) ||
+        (out_vec[0].len != sizeof(psa_key_handle_t))) {
+        return PSA_ERROR_CONNECTION_REFUSED;
+    }
+    const struct tfm_crypto_pack_iovec *iov = in_vec[0].base;
+
+    uint32_t handle = iov->op_handle;
+    const psa_key_attributes_t *key_attributes = in_vec[1].base;
+    psa_key_derivation_operation_t *operation = NULL;
+    psa_key_handle_t *key_handle = out_vec[0].base;
+    //int32_t partition_id = 0;
+    //uint32_t index = 0;
+
+    /* Look up the corresponding operation context */
+    status = tfm_crypto_operation_lookup(TFM_CRYPTO_KEY_DERIVATION_OPERATION,
+                                         handle,
+                                         (void **)&operation);
+    if (status != PSA_SUCCESS) {
+        return status;
+    }
+    /*
+    status = tfm_crypto_check_key_storage(&partition_id, &index);
+    if (status != PSA_SUCCESS) {
+        return status;
+    }
+    */
+    status = psa_key_derivation_output_key(key_attributes, operation, key_handle);
+    /*
+    if (status == PSA_SUCCESS) {
+        status = tfm_crypto_set_key_storage(partition_id, index, *key_handle);
+    }
+    */
+    return status;
+#endif /* TFM_CRYPTO_KEY_DERIVATION_MODULE_DISABLED */
+}
+
+psa_status_t tfm_crypto_key_derivation_abort(psa_invec in_vec[],
+                                             size_t in_len,
+                                             psa_outvec out_vec[],
+                                             size_t out_len)
+{
+#ifdef TFM_CRYPTO_KEY_DERIVATION_MODULE_DISABLED
+    return PSA_ERROR_NOT_SUPPORTED;
+#else
+    psa_status_t status;
+    if ((in_len != 1) || (out_len != 1)) {
+        return PSA_ERROR_CONNECTION_REFUSED;
+    }
+
+    if ((in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec)) ||
+        (out_vec[0].len != sizeof(uint32_t))) {
+        return PSA_ERROR_CONNECTION_REFUSED;
+    }
+    const struct tfm_crypto_pack_iovec *iov = in_vec[0].base;
+
+    uint32_t handle = iov->op_handle;
+    uint32_t *handle_out = out_vec[0].base;
+    psa_key_derivation_operation_t *operation = NULL;
+
+    /* Init the handle in the operation with the one passed from the iov */
+    *handle_out = iov->op_handle;
+
+    /* Look up the corresponding operation context */
+    status = tfm_crypto_operation_lookup(TFM_CRYPTO_KEY_DERIVATION_OPERATION,
+                                         handle,
+                                         (void **)&operation);
+    if (status != PSA_SUCCESS) {
+        /* Operation does not exist, so abort has no effect */
+        return PSA_SUCCESS;
+    }
+
+    *handle_out = handle;
+
+    status = psa_key_derivation_abort(operation);
+    if (status != PSA_SUCCESS) {
+        /* Release the operation context, ignore if the operation fails. */
+        (void)tfm_crypto_operation_release(handle_out);
+        return status;
+    }
+
+    status = tfm_crypto_operation_release(handle_out);
+
+    return status;
+#endif /* TFM_CRYPTO_KEY_DERIVATION_MODULE_DISABLED */
+}
+
+psa_status_t tfm_crypto_key_derivation_key_agreement(psa_invec in_vec[],
+                                                     size_t in_len,
+                                                     psa_outvec out_vec[],
+                                                     size_t out_len)
+{
+#ifdef TFM_CRYPTO_KEY_DERIVATION_MODULE_DISABLED
+    return PSA_ERROR_NOT_SUPPORTED;
+#else
+    psa_status_t status;
+    if ((in_len != 2) || (out_len != 0)) {
+        return PSA_ERROR_CONNECTION_REFUSED;
+    }
+
+    if ((in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec))) {
+        return PSA_ERROR_CONNECTION_REFUSED;
+    }
+    const struct tfm_crypto_pack_iovec *iov = in_vec[0].base;
+
+    uint32_t handle = iov->op_handle;
+    psa_key_handle_t private_key = iov->key_handle;
+    const uint8_t *peer_key = in_vec[1].base;
+    size_t peer_key_length = in_vec[1].len;
+    psa_key_derivation_operation_t *operation = NULL;
+    psa_key_derivation_step_t step = iov->step;
+
+    status = tfm_crypto_check_handle_owner(private_key, NULL);
+    if (status != PSA_SUCCESS) {
+        return status;
+    }
+
+    /* Look up the corresponding operation context */
+    status = tfm_crypto_operation_lookup(TFM_CRYPTO_KEY_DERIVATION_OPERATION,
+                                         handle,
+                                         (void **)&operation);
+    if (status != PSA_SUCCESS) {
+        return status;
+    }
+
+    return psa_key_derivation_key_agreement(operation, step,
+                                            private_key,
+                                            peer_key,
+                                            peer_key_length);
+#endif /* TFM_CRYPTO_KEY_DERIVATION_MODULE_DISABLED */
+}
+
+psa_status_t tfm_crypto_generate_random(psa_invec in_vec[],
+                                        size_t in_len,
+                                        psa_outvec out_vec[],
+                                        size_t out_len)
+{
+#ifdef TFM_CRYPTO_KEY_DERIVATION_MODULE_DISABLED
+    return PSA_ERROR_NOT_SUPPORTED;
+#else
+    if ((in_len != 1) || (out_len != 1)) {
+        return PSA_ERROR_CONNECTION_REFUSED;
+    }
+
+    if (in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec)) {
+        return PSA_ERROR_CONNECTION_REFUSED;
+    }
+    uint8_t *output = out_vec[0].base;
+    size_t output_size = out_vec[0].len;
+
+    return psa_generate_random(output, output_size);
+#endif /* TFM_CRYPTO_KEY_DERIVATION_MODULE_DISABLED */
+}
+
+psa_status_t tfm_crypto_raw_key_agreement(psa_invec in_vec[],
+                                          size_t in_len,
+                                          psa_outvec out_vec[],
+                                          size_t out_len)
+{
+#ifdef TFM_CRYPTO_KEY_DERIVATION_MODULE_DISABLED
+    return PSA_ERROR_NOT_SUPPORTED;
+#else
+    if ((in_len != 2) || (out_len != 1)) {
+        return PSA_ERROR_CONNECTION_REFUSED;
+    }
+
+    if (in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec)) {
+        return PSA_ERROR_CONNECTION_REFUSED;
+    }
+    const struct tfm_crypto_pack_iovec *iov = in_vec[0].base;
+    uint8_t *output = out_vec[0].base;
+    size_t output_size = out_vec[0].len;
+    psa_algorithm_t alg = iov->alg;
+    psa_key_handle_t private_key = iov->key_handle;
+    const uint8_t *peer_key = in_vec[1].base;
+    size_t peer_key_length = in_vec[1].len;
+
+    return psa_raw_key_agreement(alg, private_key, peer_key, peer_key_length,
+                                 output, output_size, &out_vec[0].len);
+#endif /* TFM_CRYPTO_KEY_DERIVATION_MODULE_DISABLED */
+}
+/*!@}*/