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_alloc.c b/secure_fw/services/crypto/crypto_alloc.c
index e8b95c9..685ea0a 100644
--- a/secure_fw/services/crypto/crypto_alloc.c
+++ b/secure_fw/services/crypto/crypto_alloc.c
@@ -27,6 +27,9 @@
 
 struct tfm_crypto_operation_s {
     uint32_t in_use;                /*!< Indicates if the operation is in use */
+    int32_t owner;                  /*!< Indicates an ID of the owner of
+                                     *   the context
+                                     */
     enum tfm_crypto_operation_type type; /*!< Type of the operation */
     union {
         psa_cipher_operation_t cipher;    /*!< Cipher operation context */
@@ -93,6 +96,13 @@
                                         void **ctx)
 {
     uint32_t i = 0;
+    int32_t partition_id = 0;
+    psa_status_t status;
+
+    status = tfm_crypto_get_caller_id(&partition_id);
+    if (status != PSA_SUCCESS) {
+        return status;
+    }
 
     /* Handle must be initialised before calling a setup function */
     if (*handle != TFM_CRYPTO_INVALID_HANDLE) {
@@ -108,6 +118,7 @@
     for (i=0; i<TFM_CRYPTO_CONC_OPER_NUM; i++) {
         if (operation[i].in_use == TFM_CRYPTO_NOT_IN_USE) {
             operation[i].in_use = TFM_CRYPTO_IN_USE;
+            operation[i].owner = partition_id;
             operation[i].type = type;
             *handle = i + 1;
             *ctx = (void *) &(operation[i].operation);
@@ -121,14 +132,23 @@
 psa_status_t tfm_crypto_operation_release(uint32_t *handle)
 {
     uint32_t h_val = *handle;
+    int32_t partition_id = 0;
+    psa_status_t status;
+
+    status = tfm_crypto_get_caller_id(&partition_id);
+    if (status != PSA_SUCCESS) {
+        return status;
+    }
 
     if ( (h_val != TFM_CRYPTO_INVALID_HANDLE) &&
          (h_val <= TFM_CRYPTO_CONC_OPER_NUM) &&
-         (operation[h_val - 1].in_use == TFM_CRYPTO_IN_USE) ) {
+         (operation[h_val - 1].in_use == TFM_CRYPTO_IN_USE) &&
+         (operation[h_val - 1].owner == partition_id)) {
 
         memset_operation_context(h_val - 1);
         operation[h_val - 1].in_use = TFM_CRYPTO_NOT_IN_USE;
         operation[h_val - 1].type = TFM_CRYPTO_OPERATION_NONE;
+        operation[h_val - 1].owner = 0;
         *handle = TFM_CRYPTO_INVALID_HANDLE;
         return PSA_SUCCESS;
     }
@@ -140,10 +160,19 @@
                                          uint32_t handle,
                                          void **ctx)
 {
+    int32_t partition_id = 0;
+    psa_status_t status;
+
+    status = tfm_crypto_get_caller_id(&partition_id);
+    if (status != PSA_SUCCESS) {
+        return status;
+    }
+
     if ( (handle != TFM_CRYPTO_INVALID_HANDLE) &&
          (handle <= TFM_CRYPTO_CONC_OPER_NUM) &&
          (operation[handle - 1].in_use == TFM_CRYPTO_IN_USE) &&
-         (operation[handle - 1].type == type) ) {
+         (operation[handle - 1].type == type) &&
+         (operation[handle - 1].owner == partition_id)) {
 
         *ctx = (void *) &(operation[handle - 1].operation);
         return PSA_SUCCESS;