Crypto: Add IPC compatibility

This patch introduces compatibility in the Crypto
service with the IPC infrastructure of TF-M.

Change-Id: I5a095780e1f2bd489c83cfbca138ca6dd0bfe9ba
Signed-off-by: Antonio de Angelis <antonio.deangelis@arm.com>
diff --git a/secure_fw/services/crypto/crypto_hash.c b/secure_fw/services/crypto/crypto_hash.c
index cd546b9..36e5759 100644
--- a/secure_fw/services/crypto/crypto_hash.c
+++ b/secure_fw/services/crypto/crypto_hash.c
@@ -9,6 +9,12 @@
 #include "crypto_engine.h"
 #include "tfm_crypto_struct.h"
 
+/* FixMe: Use PSA_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.
+ */
+
 /**
  * \brief Release all resources associated with a hash operation.
  *
@@ -17,7 +23,7 @@
  *
  * \return Return values as described in \ref tfm_crypto_err_t
  */
-static psa_status_t tfm_crypto_hash_release(psa_hash_operation_t *operation,
+static psa_status_t tfm_crypto_hash_release(uint32_t *handle,
                                             struct tfm_hash_operation_s *ctx)
 {
     psa_status_t status = PSA_SUCCESS;
@@ -29,7 +35,7 @@
     }
 
     /* Release the operation context */
-    return tfm_crypto_operation_release(TFM_CRYPTO_HASH_OPERATION, operation);
+    return tfm_crypto_operation_release(handle);
 }
 
 /*!
@@ -51,13 +57,17 @@
         return PSA_CONNECTION_REFUSED;
     }
 
-    if ((out_vec[0].len != sizeof(psa_hash_operation_t)) ||
-        (in_vec[0].len != sizeof(psa_algorithm_t))) {
+    if ((out_vec[0].len != sizeof(uint32_t)) ||
+        (in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec))) {
         return PSA_CONNECTION_REFUSED;
     }
+    const struct tfm_crypto_pack_iovec *iov = in_vec[0].base;
+    uint32_t handle = iov->handle;
+    uint32_t *handle_out = out_vec[0].base;
+    psa_algorithm_t alg = iov->alg;
 
-    psa_hash_operation_t *operation = out_vec[0].base;
-    psa_algorithm_t alg = *((psa_algorithm_t *)in_vec[0].base);
+    /* Init the handle in the operation with the one passed from the iov */
+    *handle_out = iov->handle;
 
     if (PSA_ALG_IS_HASH(alg) == 0) {
         return PSA_ERROR_INVALID_ARGUMENT;
@@ -71,12 +81,14 @@
 
     /* Allocate the operation context in the secure world */
     status = tfm_crypto_operation_alloc(TFM_CRYPTO_HASH_OPERATION,
-                                        operation,
+                                        &handle,
                                         (void **)&ctx);
     if (status != PSA_SUCCESS) {
         return status;
     }
 
+    *handle_out = handle;
+
     /* Bind the algorithm to the hash context */
     ctx->alg = alg;
 
@@ -84,7 +96,7 @@
     status = tfm_crypto_engine_hash_start(&(ctx->engine_ctx), &engine_info);
     if (status != PSA_SUCCESS) {
         /* Release the operation context, ignore if the operation fails. */
-        (void)tfm_crypto_hash_release(operation, ctx);
+      (void)tfm_crypto_hash_release(&handle, ctx);
         return status;
     }
 
@@ -99,21 +111,26 @@
     psa_status_t status = PSA_SUCCESS;
     struct tfm_hash_operation_s *ctx = NULL;
 
-    if ((in_len != 1) || (out_len != 1)) {
+    if ((in_len != 2) || (out_len != 1)) {
         return PSA_CONNECTION_REFUSED;
     }
 
-    if ((out_vec[0].len != sizeof(psa_hash_operation_t))) {
+    if ((in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec)) ||
+        (out_vec[0].len != sizeof(uint32_t))) {
         return PSA_CONNECTION_REFUSED;
     }
+    const struct tfm_crypto_pack_iovec *iov = in_vec[0].base;
+    uint32_t handle = iov->handle;
+    uint32_t *handle_out = out_vec[0].base;
+    const uint8_t *input = in_vec[1].base;
+    size_t input_length = in_vec[1].len;
 
-    psa_hash_operation_t *operation = out_vec[0].base;
-    const uint8_t *input = in_vec[0].base;
-    size_t input_length = in_vec[0].len;
+    /* Init the handle in the operation with the one passed from the iov */
+    *handle_out = iov->handle;
 
     /* Look up the corresponding operation context */
     status = tfm_crypto_operation_lookup(TFM_CRYPTO_HASH_OPERATION,
-                                         operation,
+                                         handle,
                                          (void **)&ctx);
     if (status != PSA_SUCCESS) {
         return status;
@@ -124,7 +141,9 @@
                                            input,
                                            input_length);
     if (status != PSA_SUCCESS) {
-        (void)tfm_crypto_hash_release(operation, ctx);
+        if (tfm_crypto_hash_release(&handle, ctx) == PSA_SUCCESS) {
+            *handle_out = handle;
+        }
         return status;
     }
 
@@ -139,59 +158,80 @@
     psa_status_t status = PSA_SUCCESS;
     struct tfm_hash_operation_s *ctx = NULL;
 
-    if ((in_len != 0) || (out_len != 2)) {
+    if ((in_len != 1) || (out_len != 2)) {
         return PSA_CONNECTION_REFUSED;
     }
 
-    if ((out_vec[0].len != sizeof(psa_hash_operation_t))) {
+    if ((in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec)) ||
+        (out_vec[0].len != sizeof(uint32_t))) {
         return PSA_CONNECTION_REFUSED;
     }
-
-    psa_hash_operation_t *operation = out_vec[0].base;
+    const struct tfm_crypto_pack_iovec *iov = in_vec[0].base;
+    uint32_t handle = iov->handle;
+    uint32_t *handle_out = out_vec[0].base;
     uint8_t *hash = out_vec[1].base;
     size_t hash_size = out_vec[1].len;
 
+    /* Init the handle in the operation with the one passed from the iov */
+    *handle_out = iov->handle;
+
     /* Initialise hash_length to zero */
     out_vec[1].len = 0;
 
     /* Look up the corresponding operation context */
     status = tfm_crypto_operation_lookup(TFM_CRYPTO_HASH_OPERATION,
-                                         operation,
+                                         handle,
                                          (void **)&ctx);
     if (status != PSA_SUCCESS) {
         return status;
     }
 
     if (hash_size < PSA_HASH_SIZE(ctx->alg)) {
-        (void)tfm_crypto_hash_release(operation, ctx);
+        if (tfm_crypto_hash_release(&handle, ctx) == PSA_SUCCESS) {
+            *handle_out = handle;
+        }
         return PSA_ERROR_BUFFER_TOO_SMALL;
     }
 
     /* Finalise the hash value using the engine */
     status = tfm_crypto_engine_hash_finish(&(ctx->engine_ctx), hash);
     if (status != PSA_SUCCESS) {
-        (void)tfm_crypto_hash_release(operation, ctx);
+        if (tfm_crypto_hash_release(&handle, ctx) == PSA_SUCCESS) {
+            *handle_out = handle;
+        }
         return status;
     }
 
     /* Set the length of the hash that has been produced */
     out_vec[1].len = PSA_HASH_SIZE(ctx->alg);
 
-    return tfm_crypto_hash_release(operation, ctx);
+    status = tfm_crypto_hash_release(&handle, ctx);
+    if (status == PSA_SUCCESS) {
+        *handle_out = handle;
+    }
+    return status;
 }
 
-static psa_status_t _psa_hash_finish(psa_hash_operation_t *operation,
+static psa_status_t _psa_hash_finish(uint32_t *handle,
                                      uint8_t *hash,
                                      size_t hash_size,
                                      size_t *hash_length)
 {
     psa_status_t status;
+    struct tfm_crypto_pack_iovec iov = {
+        .sfn_id = TFM_CRYPTO_HASH_FINISH_SFID,
+        .handle = *handle,
+    };
+
+    psa_invec in_vec[] = {
+        {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)},
+    };
     psa_outvec out_vec[] = {
-        {.base = operation, .len = sizeof(psa_hash_operation_t)},
+        {.base = handle, .len = sizeof(uint32_t)},
         {.base = hash, .len = hash_size},
     };
 
-    status = tfm_crypto_hash_finish(NULL, 0,
+    status = tfm_crypto_hash_finish(in_vec, sizeof(in_vec)/sizeof(in_vec[0]),
                    out_vec, sizeof(out_vec)/sizeof(out_vec[0]));
     *hash_length = out_vec[1].len;
 
@@ -208,20 +248,21 @@
     size_t digest_length;
     uint32_t idx, comp_mismatch = 0;
 
-    if ((in_len != 1) || (out_len != 1)) {
+    if ((in_len != 2) || (out_len != 1)) {
         return PSA_CONNECTION_REFUSED;
     }
 
-    if ((out_vec[0].len != sizeof(psa_hash_operation_t))) {
+    if ((in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec)) ||
+        (out_vec[0].len != sizeof(uint32_t))) {
         return PSA_CONNECTION_REFUSED;
     }
 
-    psa_hash_operation_t *operation = out_vec[0].base;
-    const uint8_t *hash = in_vec[0].base;
-    size_t hash_length = in_vec[0].len;
+    uint32_t *handle_out = out_vec[0].base;
+    const uint8_t *hash = in_vec[1].base;
+    size_t hash_length = in_vec[1].len;
 
     /* Finalise the hash operation */
-    status = _psa_hash_finish(operation,
+    status = _psa_hash_finish(handle_out,
                               digest,
                               PSA_HASH_MAX_SIZE,
                               &digest_length);
@@ -257,24 +298,33 @@
     psa_status_t status = PSA_SUCCESS;
     struct tfm_hash_operation_s *ctx = NULL;
 
-    if ((in_len != 0) || (out_len != 1)) {
+    if ((in_len != 1) || (out_len != 1)) {
         return PSA_CONNECTION_REFUSED;
     }
 
-    if ((out_vec[0].len != sizeof(psa_hash_operation_t))) {
+    if ((in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec)) ||
+        (out_vec[0].len != sizeof(uint32_t))) {
         return PSA_CONNECTION_REFUSED;
     }
+    const struct tfm_crypto_pack_iovec *iov = in_vec[0].base;
+    uint32_t handle = iov->handle;
+    uint32_t *handle_out = out_vec[0].base;
 
-    psa_hash_operation_t *operation = out_vec[0].base;
+    /* Init the handle in the operation with the one passed from the iov */
+    *handle_out = iov->handle;
 
     /* Look up the corresponding operation context */
     status = tfm_crypto_operation_lookup(TFM_CRYPTO_HASH_OPERATION,
-                                         operation,
+                                         handle,
                                          (void **)&ctx);
     if (status != PSA_SUCCESS) {
         return status;
     }
 
-    return tfm_crypto_hash_release(operation, ctx);
+    status = tfm_crypto_hash_release(&handle, ctx);
+    if (status == PSA_SUCCESS) {
+        *handle_out = handle;
+    }
+    return status;
 }
 /*!@}*/