Crypto: Make operations inactive as per PSA API

Updates the cipher, hash and MAC modules to make operations inactive
when required by the PSA Crypto API.

Change-Id: I008b70c86aa410a1b9adefca5c3b8734d7521fb6
Signed-off-by: Jamie Fox <jamie.fox@arm.com>
diff --git a/secure_fw/services/crypto/crypto_cipher.c b/secure_fw/services/crypto/crypto_cipher.c
index a88f4a8..b53ace0 100644
--- a/secure_fw/services/crypto/crypto_cipher.c
+++ b/secure_fw/services/crypto/crypto_cipher.c
@@ -28,6 +28,36 @@
 #define CRYPTO_CIPHER_MAX_KEY_LENGTH (32)
 #endif
 
+/**
+ * \brief Release all resources associated with a cipher operation.
+ *
+ * \param[in] operation  Frontend cipher operation context
+ * \param[in] ctx        Backend cipher operation context
+ *
+ * \return Return values as described in \ref tfm_crypto_err_t
+ */
+static enum tfm_crypto_err_t tfm_crypto_cipher_release(
+                                             psa_cipher_operation_t *operation,
+                                             struct tfm_cipher_operation_s *ctx)
+{
+    psa_status_t status;
+    enum tfm_crypto_err_t err;
+
+    /* Release resources in the engine */
+    status = tfm_crypto_engine_cipher_release(&(ctx->engine_ctx));
+    if (status != PSA_SUCCESS) {
+        return PSA_STATUS_TO_TFM_CRYPTO_ERR(status);
+    }
+
+    /* Release the operation context */
+    err = tfm_crypto_operation_release(&(operation->handle));
+    if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
+        return err;
+    }
+
+    return TFM_CRYPTO_ERR_PSA_SUCCESS;
+}
+
 static enum tfm_crypto_err_t tfm_crypto_cipher_setup(
                                            psa_cipher_operation_t *operation,
                                            psa_key_slot_t key,
@@ -94,7 +124,7 @@
                                       (void **)&ctx);
     if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
         /* Release the operation context */
-        tfm_crypto_operation_release(&(operation->handle));
+        (void)tfm_crypto_operation_release(&(operation->handle));
         return err;
     }
 
@@ -108,7 +138,7 @@
     status = tfm_crypto_engine_cipher_start(&(ctx->engine_ctx), &engine_info);
     if (status != PSA_SUCCESS) {
         /* Release the operation context */
-        tfm_crypto_operation_release(&(operation->handle));
+        (void)tfm_crypto_cipher_release(operation, ctx);
         return PSA_STATUS_TO_TFM_CRYPTO_ERR(status);
     }
 
@@ -125,7 +155,7 @@
                              &key_size);
     if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
         /* Release the operation context */
-        tfm_crypto_operation_release(&(operation->handle));
+        (void)tfm_crypto_cipher_release(operation, ctx);
         return err;
     }
 
@@ -136,7 +166,7 @@
                                               &engine_info);
     if (status != PSA_SUCCESS) {
         /* Release the operation context */
-        tfm_crypto_operation_release(&(operation->handle));
+        (void)tfm_crypto_cipher_release(operation, ctx);
         return PSA_STATUS_TO_TFM_CRYPTO_ERR(status);
     }
 
@@ -151,7 +181,7 @@
                                                            &engine_info);
         if (status != PSA_SUCCESS) {
             /* Release the operation context */
-            tfm_crypto_operation_release(&(operation->handle));
+            (void)tfm_crypto_cipher_release(operation, ctx);
             return PSA_STATUS_TO_TFM_CRYPTO_ERR(status);
         }
     }
@@ -199,10 +229,12 @@
     }
 
     if ((iv_length != ctx->block_size) || (iv_length > TFM_CIPHER_IV_MAX_SIZE)){
+        (void)tfm_crypto_cipher_release(operation, ctx);
         return TFM_CRYPTO_ERR_PSA_ERROR_INVALID_ARGUMENT;
     }
 
     if ((ctx->iv_set == 1) || (ctx->iv_required == 0)) {
+        (void)tfm_crypto_cipher_release(operation, ctx);
         return TFM_CRYPTO_ERR_PSA_ERROR_BAD_STATE;
     }
 
@@ -211,6 +243,7 @@
                                              iv,
                                              iv_length);
     if (status != PSA_SUCCESS) {
+        (void)tfm_crypto_cipher_release(operation, ctx);
         return PSA_STATUS_TO_TFM_CRYPTO_ERR(status);
     }
 
@@ -295,17 +328,17 @@
     if ((ctx->iv_required == 1) && (ctx->iv_set == 0)) {
 
         if (ctx->cipher_mode != ENGINE_CIPHER_MODE_DECRYPT) {
+            (void)tfm_crypto_cipher_release(operation, ctx);
             return TFM_CRYPTO_ERR_PSA_ERROR_BAD_STATE;
         }
 
         /* This call is used to set the IV on the object */
-        err = tfm_crypto_cipher_set_iv(operation, input, input_length);
-
-        return err;
+        return tfm_crypto_cipher_set_iv(operation, input, input_length);
     }
 
     /* If the key is not set, setup phase has not been completed */
     if (ctx->key_set == 0) {
+        (void)tfm_crypto_cipher_release(operation, ctx);
         return TFM_CRYPTO_ERR_PSA_ERROR_BAD_STATE;
     }
 
@@ -313,6 +346,7 @@
      *        of input data whose length is equal to the block size
      */
     if (input_length > output_size) {
+        (void)tfm_crypto_cipher_release(operation, ctx);
         return TFM_CRYPTO_ERR_PSA_ERROR_BUFFER_TOO_SMALL;
     }
 
@@ -323,6 +357,7 @@
                                              output,
                                              (uint32_t *)output_length);
     if (status != PSA_SUCCESS) {
+        (void)tfm_crypto_cipher_release(operation, ctx);
         return PSA_STATUS_TO_TFM_CRYPTO_ERR(status);
     }
 
@@ -371,6 +406,7 @@
      * output data.
      */
     if (output_size < ctx->block_size) {
+        (void)tfm_crypto_cipher_release(operation, ctx);
         return TFM_CRYPTO_ERR_PSA_ERROR_BUFFER_TOO_SMALL;
     }
 
@@ -380,27 +416,15 @@
                                              (uint32_t *)output_length);
     if (status != PSA_SUCCESS) {
         *output_length = 0;
+        (void)tfm_crypto_cipher_release(operation, ctx);
         return PSA_STATUS_TO_TFM_CRYPTO_ERR(status);
     }
 
-    /* Release resources on the crypto engine */
-    status = tfm_crypto_engine_cipher_release(&(ctx->engine_ctx));
-    if (status != PSA_SUCCESS) {
-        return PSA_STATUS_TO_TFM_CRYPTO_ERR(status);
-    }
-
-    /* Release the operation context */
-    err = tfm_crypto_operation_release(&(operation->handle));
-    if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
-        return err;
-    }
-
-    return TFM_CRYPTO_ERR_PSA_SUCCESS;
+    return tfm_crypto_cipher_release(operation, ctx);
 }
 
 enum tfm_crypto_err_t tfm_crypto_cipher_abort(psa_cipher_operation_t *operation)
 {
-    psa_status_t status = PSA_SUCCESS;
     enum tfm_crypto_err_t err;
     struct tfm_cipher_operation_s *ctx = NULL;
 
@@ -420,18 +444,6 @@
         return err;
     }
 
-    /* Release resources on the engine */
-    status = tfm_crypto_engine_cipher_release(&(ctx->engine_ctx));
-    if (status != PSA_SUCCESS) {
-        return PSA_STATUS_TO_TFM_CRYPTO_ERR(status);
-    }
-
-    /* Release the operation context */
-    err = tfm_crypto_operation_release(&(operation->handle));
-    if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
-        return err;
-    }
-
-    return TFM_CRYPTO_ERR_PSA_SUCCESS;
+    return tfm_crypto_cipher_release(operation, ctx);
 }
 /*!@}*/
diff --git a/secure_fw/services/crypto/crypto_hash.c b/secure_fw/services/crypto/crypto_hash.c
index 265385b..54550cc 100644
--- a/secure_fw/services/crypto/crypto_hash.c
+++ b/secure_fw/services/crypto/crypto_hash.c
@@ -16,6 +16,36 @@
 #include "tfm_crypto_api.h"
 #include "crypto_utils.h"
 
+/**
+ * \brief Release all resources associated with a hash operation.
+ *
+ * \param[in] operation  Frontend hash operation context
+ * \param[in] ctx        Backend hash operation context
+ *
+ * \return Return values as described in \ref tfm_crypto_err_t
+ */
+static enum tfm_crypto_err_t tfm_crypto_hash_release(
+                                               psa_hash_operation_t *operation,
+                                               struct tfm_hash_operation_s *ctx)
+{
+    psa_status_t status;
+    enum tfm_crypto_err_t err;
+
+    /* Release resources in the engine */
+    status = tfm_crypto_engine_hash_release(&(ctx->engine_ctx));
+    if (status != PSA_SUCCESS) {
+        return PSA_STATUS_TO_TFM_CRYPTO_ERR(status);
+    }
+
+    /* Release the operation context */
+    err = tfm_crypto_operation_release(&(operation->handle));
+    if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
+        return err;
+    }
+
+    return TFM_CRYPTO_ERR_PSA_SUCCESS;
+}
+
 /*!
  * \defgroup public_psa Public functions, PSA
  *
@@ -61,7 +91,7 @@
                                       (void **)&ctx);
     if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
         /* Release the operation context */
-        tfm_crypto_operation_release(&(operation->handle));
+        (void)tfm_crypto_operation_release(&(operation->handle));
         return err;
     }
 
@@ -72,7 +102,7 @@
     status = tfm_crypto_engine_hash_start(&(ctx->engine_ctx), &engine_info);
     if (status != PSA_SUCCESS) {
         /* Release the operation context */
-        tfm_crypto_operation_release(&(operation->handle));
+        (void)tfm_crypto_hash_release(operation, ctx);
         return PSA_STATUS_TO_TFM_CRYPTO_ERR(status);
     }
 
@@ -114,6 +144,7 @@
                                            input,
                                            input_length);
     if (status != PSA_SUCCESS) {
+        (void)tfm_crypto_hash_release(operation, ctx);
         return PSA_STATUS_TO_TFM_CRYPTO_ERR(status);
     }
 
@@ -158,31 +189,21 @@
     }
 
     if (hash_size < PSA_HASH_SIZE(ctx->alg)) {
+        (void)tfm_crypto_hash_release(operation, ctx);
         return TFM_CRYPTO_ERR_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) {
-        return PSA_STATUS_TO_TFM_CRYPTO_ERR(status);
-    }
-
-    /* Release engine resources */
-    status = tfm_crypto_engine_hash_release(&(ctx->engine_ctx));
-    if (status != PSA_SUCCESS) {
+        (void)tfm_crypto_hash_release(operation, ctx);
         return PSA_STATUS_TO_TFM_CRYPTO_ERR(status);
     }
 
     /* Set the length of the hash that has been produced */
     *hash_length = PSA_HASH_SIZE(ctx->alg);
 
-    /* Release the operation context */
-    err = tfm_crypto_operation_release(&(operation->handle));
-    if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
-        return err;
-    }
-
-    return TFM_CRYPTO_ERR_PSA_SUCCESS;
+    return tfm_crypto_hash_release(operation, ctx);
 }
 
 enum tfm_crypto_err_t tfm_crypto_hash_verify(psa_hash_operation_t *operation,
@@ -228,7 +249,6 @@
 
 enum tfm_crypto_err_t tfm_crypto_hash_abort(psa_hash_operation_t *operation)
 {
-    psa_status_t status = PSA_SUCCESS;
     enum tfm_crypto_err_t err;
     struct tfm_hash_operation_s *ctx = NULL;
 
@@ -248,18 +268,6 @@
         return err;
     }
 
-    /* Release engine resources */
-    status = tfm_crypto_engine_hash_release(&(ctx->engine_ctx));
-    if (status != PSA_SUCCESS) {
-        return PSA_STATUS_TO_TFM_CRYPTO_ERR(status);
-    }
-
-    /* Release the operation context */
-    err = tfm_crypto_operation_release(&(operation->handle));
-    if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
-        return err;
-    }
-
-    return TFM_CRYPTO_ERR_PSA_SUCCESS;
+    return tfm_crypto_hash_release(operation, ctx);
 }
 /*!@}*/
diff --git a/secure_fw/services/crypto/crypto_mac.c b/secure_fw/services/crypto/crypto_mac.c
index a13a00b..45a7eae 100644
--- a/secure_fw/services/crypto/crypto_mac.c
+++ b/secure_fw/services/crypto/crypto_mac.c
@@ -122,7 +122,6 @@
                                      &key_data[0],
                                      key_size);
         if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
-            tfm_crypto_hash_abort(&(ctx->ctx.hmac.hash_operation));
             return err;
         }
 
@@ -131,7 +130,6 @@
                                      hashed_key, sizeof(hashed_key),
                                      &key_size);
         if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
-            tfm_crypto_hash_abort(&(ctx->ctx.hmac.hash_operation));
             return err;
         }
     } else {
@@ -168,7 +166,6 @@
                                  ipad,
                                  block_size);
     if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
-        tfm_crypto_hash_abort(&(ctx->ctx.hmac.hash_operation));
         return err;
     }
 
@@ -209,7 +206,7 @@
                                       (void **)&ctx);
     if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
         /* Release the operation context */
-        tfm_crypto_operation_release(&(operation->handle));
+        (void)tfm_crypto_operation_release(&(operation->handle));
         return err;
     }
 
@@ -229,7 +226,7 @@
         err = tfm_crypto_hmac_setup(ctx, key, alg);
         if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
             /* Release the operation context */
-            tfm_crypto_operation_release(&(operation->handle));
+            (void)tfm_crypto_operation_release(&(operation->handle));
             return err;
         }
 
@@ -237,7 +234,7 @@
     } else {
         /* Other MAC types constructions are not supported */
         /* Release the operation context */
-        tfm_crypto_operation_release(&(operation->handle));
+        (void)tfm_crypto_operation_release(&(operation->handle));
         return TFM_CRYPTO_ERR_PSA_ERROR_NOT_SUPPORTED;
     }
 
@@ -318,9 +315,6 @@
         return TFM_CRYPTO_ERR_PSA_ERROR_INVALID_ARGUMENT;
     }
 
-    /* Clear the mac context */
-    mac_zeroize(ctx, sizeof(struct tfm_mac_operation_s));
-
     return TFM_CRYPTO_ERR_PSA_SUCCESS;
 }
 
@@ -382,6 +376,7 @@
 
     /* Sanity check */
     if (!(ctx->key_set)) {
+        (void)tfm_crypto_operation_release(&(operation->handle));
         return TFM_CRYPTO_ERR_PSA_ERROR_BAD_STATE;
     }
 
@@ -391,12 +386,14 @@
                                      input,
                                      input_length);
         if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
+            (void)tfm_crypto_operation_release(&(operation->handle));
             return err;
         }
 
         /* Set this flag to avoid HMAC without data */
         ctx->has_input = 1;
     } else {
+        (void)tfm_crypto_operation_release(&(operation->handle));
         return TFM_CRYPTO_ERR_PSA_ERROR_INVALID_ARGUMENT;
     }
 
@@ -449,6 +446,7 @@
         /* Finalise the mac operation */
         err = tfm_crypto_mac_finish(ctx, mac, mac_size, mac_length);
         if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
+            (void)tfm_crypto_operation_release(&(operation->handle));
             return err;
         }
         /* Release the operation context */
@@ -457,6 +455,7 @@
             return err;
         }
     } else {
+        (void)tfm_crypto_operation_release(&(operation->handle));
         return TFM_CRYPTO_ERR_PSA_ERROR_BAD_STATE;
     }
 
@@ -509,6 +508,7 @@
                                     sizeof(computed_mac),
                                     &computed_mac_length);
         if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
+            (void)tfm_crypto_operation_release(&(operation->handle));
             return err;
         }
         /* Release the operation context */
@@ -532,6 +532,7 @@
             return TFM_CRYPTO_ERR_PSA_ERROR_INVALID_SIGNATURE;
         }
     } else {
+        (void)tfm_crypto_operation_release(&(operation->handle));
         return TFM_CRYPTO_ERR_PSA_ERROR_BAD_STATE;
     }
 
@@ -570,7 +571,10 @@
         }
 
         /* Release the operation context */
-        tfm_crypto_operation_release(&(operation->handle));
+        err = tfm_crypto_operation_release(&(operation->handle));
+        if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
+            return err;
+        }
     } else {
         /* MACs other than HMACs not currently supported */
         return TFM_CRYPTO_ERR_PSA_ERROR_NOT_SUPPORTED;