Crypto: Check ownership of context

This patch introduces additional checks in the Crypto service
to make sure that a multipart operation context user is consistent
between calls. The same concept is extended to key handles which
are allocated subsequently and can be easily guessed.

Signed-off-by: Antonio de Angelis <antonio.deangelis@arm.com>
Change-Id: I16a9469682f203083a07ec623127fea71fd9f1e6
diff --git a/secure_fw/services/crypto/crypto_init.c b/secure_fw/services/crypto/crypto_init.c
index 73574c8..c719d07 100644
--- a/secure_fw/services/crypto/crypto_init.c
+++ b/secure_fw/services/crypto/crypto_init.c
@@ -16,6 +16,10 @@
  */
 #include "mbedtls/memory_buffer_alloc.h"
 
+#ifndef TFM_PSA_API
+#include "tfm_secure_api.h"
+#endif
+
 #ifdef TFM_PSA_API
 #include "psa_service.h"
 #include "tfm_crypto_signal.h"
@@ -58,8 +62,21 @@
     __attribute__((__aligned__(TFM_CRYPTO_IOVEC_ALIGNMENT)))
     uint8_t buf[TFM_CRYPTO_IOVEC_BUFFER_SIZE];
     uint32_t alloc_index;
+    int32_t owner;
 } scratch = {.buf = {0}, .alloc_index = 0};
 
+static psa_status_t tfm_crypto_set_scratch_owner(int32_t id)
+{
+    scratch.owner = id;
+    return PSA_SUCCESS;
+}
+
+static psa_status_t tfm_crypto_get_scratch_owner(int32_t *id)
+{
+    *id = scratch.owner;
+    return PSA_SUCCESS;
+}
+
 static psa_status_t tfm_crypto_alloc_scratch(size_t requested_size, void **buf)
 {
     /* Ensure alloc_index remains aligned to the required iovec alignment */
@@ -81,6 +98,7 @@
 static psa_status_t tfm_crypto_clear_scratch(void)
 {
     scratch.alloc_index = 0;
+    scratch.owner = 0;
     (void)tfm_memset(scratch.buf, 0, sizeof(scratch.buf));
 
     return PSA_SUCCESS;
@@ -114,6 +132,7 @@
         /* Allocate necessary space in the internal scratch */
         status = tfm_crypto_alloc_scratch(msg->in_size[i], &alloc_buf_ptr);
         if (status != PSA_SUCCESS) {
+            (void)tfm_crypto_clear_scratch();
             return status;
         }
         /* Read from the IPC framework inputs into the scratch */
@@ -132,6 +151,7 @@
         /* Allocate necessary space for the output in the internal scratch */
         status = tfm_crypto_alloc_scratch(msg->out_size[i], &alloc_buf_ptr);
         if (status != PSA_SUCCESS) {
+            (void)tfm_crypto_clear_scratch();
             return status;
         }
         /* Populate the fields of the output to the secure function */
@@ -139,6 +159,9 @@
         out_vec[i].len = msg->out_size[i];
     }
 
+    /* Set the owner of the data in the scratch */
+    (void)tfm_crypto_set_scratch_owner(msg->client_id);
+
     /* Call the uniform signature API */
     status = sfid_func_table[sfn_id](in_vec, in_len, out_vec, out_len);
 
@@ -271,6 +294,22 @@
     return tfm_crypto_init_alloc();
 }
 
+psa_status_t tfm_crypto_get_caller_id(int32_t *id)
+{
+#ifdef TFM_PSA_API
+    return tfm_crypto_get_scratch_owner(id);
+#else
+    int32_t res;
+
+    res = tfm_core_get_caller_client_id(id);
+    if (res != TFM_SUCCESS) {
+        return PSA_ERROR_NOT_PERMITTED;
+    } else {
+        return PSA_SUCCESS;
+    }
+#endif
+}
+
 psa_status_t tfm_crypto_init(void)
 {
     psa_status_t status;