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/CommonConfig.cmake b/CommonConfig.cmake
index eb49a41..9815d94 100644
--- a/CommonConfig.cmake
+++ b/CommonConfig.cmake
@@ -160,7 +160,12 @@
 if (CORE_TEST_IPC)
 	add_definitions(-DCORE_TEST_IPC)
 	set(TFM_PARTITION_TEST_SECURE_SERVICES ON)
-	set(TEST_FRAMEWORK_NS ON)
+	# If PSA_API_TEST is enabled, don't run TF-M test framework from NS
+	if (PSA_API_TEST)
+	  set(TEST_FRAMEWORK_NS OFF)
+	else()
+	  set(TEST_FRAMEWORK_NS ON)
+	endif()
 endif()
 
 if (SERVICE_TEST_S)
diff --git a/ConfigCoreIPC.cmake b/ConfigCoreIPC.cmake
index 3a350b2..c06d0c9 100644
--- a/ConfigCoreIPC.cmake
+++ b/ConfigCoreIPC.cmake
@@ -29,6 +29,7 @@
 set (REGRESSION True)
 set (CORE_TEST False)
 set (CORE_IPC True)
+set (PSA_API_TEST False)
 
 # TF-M isolation level: 1..3
 set (TFM_LVL 1)
diff --git a/ConfigPsaApiTest.cmake b/ConfigPsaApiTest.cmake
index 0c7bf46..b63b373 100644
--- a/ConfigPsaApiTest.cmake
+++ b/ConfigPsaApiTest.cmake
@@ -14,7 +14,7 @@
 elseif(${TARGET_PLATFORM} STREQUAL "AN521")
 	set(PLATFORM_CMAKE_FILE "${CMAKE_CURRENT_LIST_DIR}/platform/ext/Mps2AN521.cmake")
 elseif(${TARGET_PLATFORM} STREQUAL "AN519")
-	set (PLATFORM_CMAKE_FILE "${CMAKE_CURRENT_LIST_DIR}/platform/ext/Mps2AN519.cmake")
+	set(PLATFORM_CMAKE_FILE "${CMAKE_CURRENT_LIST_DIR}/platform/ext/Mps2AN519.cmake")
 elseif(${TARGET_PLATFORM} STREQUAL "MUSCA_A")
 	set(PLATFORM_CMAKE_FILE "${CMAKE_CURRENT_LIST_DIR}/platform/ext/musca_a.cmake")
 elseif(${TARGET_PLATFORM} STREQUAL "MUSCA_B1")
@@ -28,6 +28,7 @@
 #definitions) based on these.
 set (REGRESSION False)
 set (CORE_TEST False)
+set (CORE_IPC False)
 set (PSA_API_TEST True)
 
 #TF-M isolation level: 1..3
diff --git a/interface/include/tfm_crypto_defs.h b/interface/include/tfm_crypto_defs.h
index 02e9770..8d926c2 100644
--- a/interface/include/tfm_crypto_defs.h
+++ b/interface/include/tfm_crypto_defs.h
@@ -18,10 +18,95 @@
 #include "psa_crypto.h"
 
 /**
+ * \brief This type is used to overcome a limitation in the number of maximum
+ *        IOVECs that can be used especially in psa_aead_encrypt and
+ *        psa_aead_decrypt. To be removed in case the AEAD APIs number of
+ *        parameters passed gets restructured
+ */
+#define TFM_CRYPTO_MAX_NONCE_LENGTH (16u)
+struct tfm_crypto_aead_pack_input {
+    uint8_t nonce[TFM_CRYPTO_MAX_NONCE_LENGTH];
+    uint32_t nonce_length;
+};
+
+/**
+ * \brief Structure used to pack non-pointer types in a call
+ *
+ */
+struct tfm_crypto_pack_iovec {
+    uint32_t sfn_id;             /*!< Secure function ID used to dispatch the
+                                  *   request
+                                  */
+    psa_key_slot_t key;          /*!< Key slot */
+    psa_key_type_t type;         /*!< Key type */
+    psa_key_usage_t usage;       /*!< Usage policy for a key */
+    psa_algorithm_t alg;         /*!< Algorithm */
+    psa_key_lifetime_t lifetime; /*!< Lifetime policy for a key */
+    uint32_t handle;             /*!< Frontend context handle associated to a
+                                  *   multipart operation
+                                  */
+
+    struct tfm_crypto_aead_pack_input aead_in; /*!< FixMe: Temporarily used for
+                                                *   AEAD until the API is
+                                                *   restructured
+                                                */
+};
+
+/**
+ * \brief Define a numerical value for each SFID which can be used when
+ *        dispatching the requests to the service
+ */
+#define TFM_CRYPTO_IMPORT_KEY_SFID               (0u)
+#define TFM_CRYPTO_DESTROY_KEY_SFID              (1u)
+#define TFM_CRYPTO_GET_KEY_INFORMATION_SFID      (2u)
+#define TFM_CRYPTO_EXPORT_KEY_SFID               (3u)
+#define TFM_CRYPTO_KEY_POLICY_INIT_SFID          (4u)
+#define TFM_CRYPTO_KEY_POLICY_SET_USAGE_SFID     (5u)
+#define TFM_CRYPTO_KEY_POLICY_GET_USAGE_SFID     (6u)
+#define TFM_CRYPTO_KEY_POLICY_GET_ALGORITHM_SFID (7u)
+#define TFM_CRYPTO_SET_KEY_POLICY_SFID           (8u)
+#define TFM_CRYPTO_GET_KEY_POLICY_SFID           (9u)
+#define TFM_CRYPTO_SET_KEY_LIFETIME_SFID         (10u)
+#define TFM_CRYPTO_GET_KEY_LIFETIME_SFID         (11u)
+#define TFM_CRYPTO_CIPHER_SET_IV_SFID            (12u)
+#define TFM_CRYPTO_CIPHER_ENCRYPT_SETUP_SFID     (13u)
+#define TFM_CRYPTO_CIPHER_DECRYPT_SETUP_SFID     (14u)
+#define TFM_CRYPTO_CIPHER_UPDATE_SFID            (15u)
+#define TFM_CRYPTO_CIPHER_ABORT_SFID             (16u)
+#define TFM_CRYPTO_CIPHER_FINISH_SFID            (17u)
+#define TFM_CRYPTO_HASH_SETUP_SFID               (18u)
+#define TFM_CRYPTO_HASH_UPDATE_SFID              (19u)
+#define TFM_CRYPTO_HASH_FINISH_SFID              (20u)
+#define TFM_CRYPTO_HASH_VERIFY_SFID              (21u)
+#define TFM_CRYPTO_HASH_ABORT_SFID               (22u)
+#define TFM_CRYPTO_MAC_SIGN_SETUP_SFID           (23u)
+#define TFM_CRYPTO_MAC_VERIFY_SETUP_SFID         (24u)
+#define TFM_CRYPTO_MAC_UPDATE_SFID               (25u)
+#define TFM_CRYPTO_MAC_SIGN_FINISH_SFID          (26u)
+#define TFM_CRYPTO_MAC_VERIFY_FINISH_SFID        (27u)
+#define TFM_CRYPTO_MAC_ABORT_SFID                (28u)
+#define TFM_CRYPTO_AEAD_ENCRYPT_SFID             (29u)
+#define TFM_CRYPTO_AEAD_DECRYPT_SFID             (30u)
+
+/**
+ * \brief Define the SID values and minor versions to match the ones defined in
+ *        the service manifest files
+ */
+#define TFM_CRYPTO_SID     (0x00004000u)
+#define TFM_CRYPTO_MIN_VER (0x0001)
+
+/**
+ * \brief Define the maximum value based on the previous list, and
+ *        an invalid value
+ */
+#define TFM_CRYPTO_SFID_MAX (TFM_CRYPTO_AEAD_DECRYPT_SFID + 1u)
+#define TFM_CRYPTO_SFID_INVALID (~0x0u)
+
+/**
  * \brief This value is used to mark an handle as invalid.
  *
  */
-#define TFM_CRYPTO_INVALID_HANDLE (0xFFFFFFFF)
+#define TFM_CRYPTO_INVALID_HANDLE (~0x0u)
 
 /**
  * \brief Define miscellaneous literal constants that are used in the service
@@ -32,19 +117,6 @@
     TFM_CRYPTO_IN_USE = 1
 };
 
-/**
- * \brief This type is used to overcome a limitation in the number of maximum
- *        IOVECs that can be used especially in psa_aead_encrypt and
- *        psa_aead_decrypt. To be removed in case the AEAD APIs number of
- *        parameters passed gets restructured
- */
-#define TFM_CRYPTO_MAX_NONCE_LENGTH (16u)
-struct tfm_crypto_aead_pack_input {
-    psa_key_slot_t key;
-    psa_algorithm_t alg;
-    uint8_t nonce[TFM_CRYPTO_MAX_NONCE_LENGTH];
-};
-
 #ifdef __cplusplus
 }
 #endif
diff --git a/interface/src/tfm_crypto_api.c b/interface/src/tfm_crypto_api.c
index 3b70d49..19dc6f4 100644
--- a/interface/src/tfm_crypto_api.c
+++ b/interface/src/tfm_crypto_api.c
@@ -10,24 +10,44 @@
 #include "psa_crypto.h"
 #include "tfm_ns_lock.h"
 
-#define NS_LOCK_DISPATCH(sfn_name)                                   \
-    tfm_ns_lock_dispatch((veneer_fn)tfm_##sfn_name##_veneer,         \
-        (uint32_t)in_vec, sizeof(in_vec)/sizeof(in_vec[0]),          \
-        (uint32_t)out_vec, sizeof(out_vec)/sizeof(out_vec[0]))
+#define ARRAY_SIZE(arr) (sizeof(arr)/sizeof(arr[0]))
 
-#define NS_LOCK_DISPATCH_NO_INVEC(sfn_name)                          \
-    tfm_ns_lock_dispatch((veneer_fn)tfm_##sfn_name##_veneer,         \
-        (uint32_t)NULL, 0,                                           \
-        (uint32_t)out_vec, sizeof(out_vec)/sizeof(out_vec[0]))
+#ifdef TFM_PSA_API
+#include "psa_client.h"
 
-#define NS_LOCK_DISPATCH_NO_OUTVEC(sfn_name)                         \
-    tfm_ns_lock_dispatch((veneer_fn)tfm_##sfn_name##_veneer,         \
-        (uint32_t)in_vec, sizeof(in_vec)/sizeof(in_vec[0]),          \
+/* Macro to check for a valid PSA handle */
+/* FixMe: Here temporarily until it's added to the framework headers */
+#define PSA_IS_HANDLE_VALID(handle) ((handle) > (psa_handle_t)0)
+
+#define PSA_CONNECT(service)                                \
+    psa_handle_t handle;                                    \
+    handle = psa_connect(service##_SID, service##_MIN_VER); \
+    if (!PSA_IS_HANDLE_VALID(handle)) {                     \
+        return PSA_ERROR_UNKNOWN_ERROR;                     \
+    }                                                       \
+
+#define PSA_CLOSE() psa_close(handle)
+
+#define API_DISPATCH(sfn_name, sfn_id)                     \
+    psa_call(handle, /*PSA_IPC_CALL,*/                     \
+        in_vec, ARRAY_SIZE(in_vec),                        \
+        out_vec, ARRAY_SIZE(out_vec))
+
+#define API_DISPATCH_NO_OUTVEC(sfn_name, sfn_id)           \
+    psa_call(handle, /*PSA_IPC_CALL,*/                     \
+        in_vec, ARRAY_SIZE(in_vec),                        \
+        (psa_outvec *)NULL, 0)
+#else
+#define API_DISPATCH(sfn_name, sfn_id)                         \
+    tfm_ns_lock_dispatch((veneer_fn)tfm_##sfn_name##_veneer,   \
+        (uint32_t)in_vec, ARRAY_SIZE(in_vec),                  \
+        (uint32_t)out_vec, ARRAY_SIZE(out_vec))
+
+#define API_DISPATCH_NO_OUTVEC(sfn_name, sfn_id)               \
+    tfm_ns_lock_dispatch((veneer_fn)tfm_##sfn_name##_veneer,   \
+        (uint32_t)in_vec, ARRAY_SIZE(in_vec),                  \
         (uint32_t)NULL, 0)
-
-#define API_DISPATCH(sfn_name) NS_LOCK_DISPATCH(sfn_name)
-#define API_DISPATCH_NO_INVEC(sfn_name) NS_LOCK_DISPATCH_NO_INVEC(sfn_name)
-#define API_DISPATCH_NO_OUTVEC(sfn_name) NS_LOCK_DISPATCH_NO_OUTVEC(sfn_name)
+#endif
 
 psa_status_t psa_crypto_init(void)
 {
@@ -43,13 +63,25 @@
                             size_t data_length)
 {
     psa_status_t status;
+    struct tfm_crypto_pack_iovec iov = {
+        .sfn_id = TFM_CRYPTO_IMPORT_KEY_SFID,
+        .key = key,
+        .type = type,
+    };
     psa_invec in_vec[] = {
-        {.base = &key, .len = sizeof(psa_key_slot_t)},
-        {.base = &type, .len = sizeof(psa_key_type_t)},
+        {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)},
         {.base = data, .len = data_length}
     };
 
-    status = API_DISPATCH_NO_OUTVEC(tfm_crypto_import_key);
+#ifdef TFM_PSA_API
+    PSA_CONNECT(TFM_CRYPTO);
+#endif
+
+    status = API_DISPATCH_NO_OUTVEC(tfm_crypto_import_key,
+                                    TFM_CRYPTO_IMPORT_KEY);
+#ifdef TFM_PSA_API
+    PSA_CLOSE();
+#endif
 
     return status;
 }
@@ -57,11 +89,23 @@
 psa_status_t psa_destroy_key(psa_key_slot_t key)
 {
     psa_status_t status;
+    struct tfm_crypto_pack_iovec iov = {
+        .sfn_id = TFM_CRYPTO_DESTROY_KEY_SFID,
+        .key = key,
+    };
     psa_invec in_vec[] = {
-        {.base = &key, .len = sizeof(psa_key_slot_t)},
+        {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)},
     };
 
-    status = API_DISPATCH_NO_OUTVEC(tfm_crypto_destroy_key);
+#ifdef TFM_PSA_API
+    PSA_CONNECT(TFM_CRYPTO);
+#endif
+
+    status = API_DISPATCH_NO_OUTVEC(tfm_crypto_destroy_key,
+                                    TFM_CRYPTO_DESTROY_KEY);
+#ifdef TFM_PSA_API
+    PSA_CLOSE();
+#endif
 
     return status;
 }
@@ -71,15 +115,27 @@
                                      size_t *bits)
 {
     psa_status_t status;
+    struct tfm_crypto_pack_iovec iov = {
+        .sfn_id = TFM_CRYPTO_GET_KEY_INFORMATION_SFID,
+        .key = key,
+    };
     psa_invec in_vec[] = {
-        {.base = &key, .len = sizeof(psa_key_slot_t)},
+        {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)},
     };
     psa_outvec out_vec[] = {
         {.base = type, .len = sizeof(psa_key_type_t)},
         {.base = bits, .len = sizeof(size_t)}
     };
 
-    status = API_DISPATCH(tfm_crypto_get_key_information);
+#ifdef TFM_PSA_API
+    PSA_CONNECT(TFM_CRYPTO);
+#endif
+
+    status = API_DISPATCH(tfm_crypto_get_key_information,
+                          TFM_CRYPTO_GET_KEY_INFORMATION);
+#ifdef TFM_PSA_API
+    PSA_CLOSE();
+#endif
 
     return status;
 }
@@ -90,17 +146,30 @@
                             size_t *data_length)
 {
     psa_status_t status;
+    struct tfm_crypto_pack_iovec iov = {
+        .sfn_id = TFM_CRYPTO_EXPORT_KEY_SFID,
+        .key = key,
+    };
     psa_invec in_vec[] = {
-        {.base = &key, .len = sizeof(psa_key_slot_t)},
+        {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)},
     };
     psa_outvec out_vec[] = {
         {.base = data, .len = data_size}
     };
 
-    status = API_DISPATCH(tfm_crypto_export_key);
+#ifdef TFM_PSA_API
+    PSA_CONNECT(TFM_CRYPTO);
+#endif
+
+    status = API_DISPATCH(tfm_crypto_export_key,
+                          TFM_CRYPTO_EXPORT_KEY);
 
     *data_length = out_vec[0].len;
 
+#ifdef TFM_PSA_API
+    PSA_CLOSE();
+#endif
+
     return status;
 }
 
@@ -121,12 +190,31 @@
 void psa_key_policy_init(psa_key_policy_t *policy)
 {
     psa_status_t status;
+    struct tfm_crypto_pack_iovec iov = {
+        .sfn_id = TFM_CRYPTO_KEY_POLICY_INIT_SFID,
+    };
+    psa_invec in_vec[] = {
+        {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)},
+    };
     psa_outvec out_vec[] = {
         {.base = policy, .len = sizeof(psa_key_policy_t)},
     };
 
+#ifdef TFM_PSA_API
+    psa_handle_t handle;
+    handle = psa_connect(TFM_CRYPTO_SID,
+                         TFM_CRYPTO_MIN_VER);
+    if (!PSA_IS_HANDLE_VALID(handle)) {
+        return;
+    }
+#endif
+
     /* PSA API returns void so just ignore error value returned */
-    status = API_DISPATCH_NO_INVEC(tfm_crypto_key_policy_init);
+    status = API_DISPATCH(tfm_crypto_key_policy_init,
+                          TFM_CRYPTO_KEY_POLICY_INIT);
+#ifdef TFM_PSA_API
+    PSA_CLOSE();
+#endif
 }
 
 void psa_key_policy_set_usage(psa_key_policy_t *policy,
@@ -134,16 +222,33 @@
                               psa_algorithm_t alg)
 {
     psa_status_t status;
+    struct tfm_crypto_pack_iovec iov = {
+        .sfn_id = TFM_CRYPTO_KEY_POLICY_SET_USAGE_SFID,
+        .usage = usage,
+        .alg = alg,
+    };
     psa_invec in_vec[] = {
-        {.base = &usage, .len = sizeof(psa_key_usage_t)},
-        {.base = &alg, .len = sizeof(psa_algorithm_t)}
+        {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)},
     };
     psa_outvec out_vec[] = {
         {.base = policy, .len = sizeof(psa_key_policy_t)},
     };
 
+#ifdef TFM_PSA_API
+    psa_handle_t handle;
+    handle = psa_connect(TFM_CRYPTO_SID,
+                         TFM_CRYPTO_MIN_VER);
+    if (!PSA_IS_HANDLE_VALID(handle)) {
+        return;
+    }
+#endif
+
     /* PSA API returns void so just ignore error value returned */
-    status = API_DISPATCH(tfm_crypto_key_policy_set_usage);
+    status = API_DISPATCH(tfm_crypto_key_policy_set_usage,
+                          TFM_CRYPTO_KEY_POLICY_SET_USAGE);
+#ifdef TFM_PSA_API
+    PSA_CLOSE();
+#endif
 }
 
 psa_key_usage_t psa_key_policy_get_usage(const psa_key_policy_t *policy)
@@ -151,20 +256,33 @@
     psa_status_t status;
     psa_key_usage_t usage;
 
-    /* Initialise to a sensible default to avoid returning an uninitialised
-     * value in case the secure function fails.
-     */
-    usage = 0;
+    struct tfm_crypto_pack_iovec iov = {
+        .sfn_id = TFM_CRYPTO_KEY_POLICY_GET_USAGE_SFID,
+    };
 
     psa_invec in_vec[] = {
+        {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)},
         {.base = policy, .len = sizeof(psa_key_policy_t)},
     };
     psa_outvec out_vec[] = {
         {.base = &usage, .len = sizeof(psa_key_usage_t)},
     };
 
+    /* Initialise to a sensible default to avoid returning an uninitialised
+     * value in case the secure function fails.
+     */
+    usage = 0;
+
+#ifdef TFM_PSA_API
+    PSA_CONNECT(TFM_CRYPTO);
+#endif
+
     /* The PSA API does not return an error, so ignore any error from TF-M */
-    status = API_DISPATCH(tfm_crypto_key_policy_get_usage);
+    status = API_DISPATCH(tfm_crypto_key_policy_get_usage,
+                          TFM_CRYPTO_KEY_POLICY_GET_USAGE);
+#ifdef TFM_PSA_API
+    PSA_CLOSE();
+#endif
 
     return usage;
 }
@@ -174,20 +292,33 @@
     psa_status_t status;
     psa_algorithm_t alg;
 
-    /* Initialise to a sensible default to avoid returning an uninitialised
-     * value in case the secure function fails.
-     */
-    alg = 0;
+    struct tfm_crypto_pack_iovec iov = {
+        .sfn_id = TFM_CRYPTO_KEY_POLICY_GET_ALGORITHM_SFID,
+    };
 
     psa_invec in_vec[] = {
+        {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)},
         {.base = policy, .len = sizeof(psa_key_policy_t)},
     };
     psa_outvec out_vec[] = {
         {.base = &alg, .len = sizeof(psa_algorithm_t)},
     };
 
+    /* Initialise to a sensible default to avoid returning an uninitialised
+     * value in case the secure function fails.
+     */
+    alg = 0;
+
+#ifdef TFM_PSA_API
+    PSA_CONNECT(TFM_CRYPTO);
+#endif
+
     /* The PSA API does not return an error, so ignore any error from TF-M */
-    status = API_DISPATCH(tfm_crypto_key_policy_get_algorithm);
+    status = API_DISPATCH(tfm_crypto_key_policy_get_algorithm,
+                          TFM_CRYPTO_KEY_POLICY_GET_ALGORITHM);
+#ifdef TFM_PSA_API
+    PSA_CLOSE();
+#endif
 
     return alg;
 }
@@ -196,12 +327,25 @@
                                 const psa_key_policy_t *policy)
 {
     psa_status_t status;
+    struct tfm_crypto_pack_iovec iov = {
+        .sfn_id = TFM_CRYPTO_SET_KEY_POLICY_SFID,
+        .key = key,
+    };
+
     psa_invec in_vec[] = {
-        {.base = &key, .len = sizeof(psa_key_slot_t)},
+        {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)},
         {.base = policy, .len = sizeof(psa_key_policy_t)},
     };
 
-    status = API_DISPATCH_NO_OUTVEC(tfm_crypto_set_key_policy);
+#ifdef TFM_PSA_API
+    PSA_CONNECT(TFM_CRYPTO);
+#endif
+
+    status = API_DISPATCH_NO_OUTVEC(tfm_crypto_set_key_policy,
+                                    TFM_CRYPTO_SET_KEY_POLICY);
+#ifdef TFM_PSA_API
+    PSA_CLOSE();
+#endif
 
     return status;
 }
@@ -210,14 +354,27 @@
                                 psa_key_policy_t *policy)
 {
     psa_status_t status;
+    struct tfm_crypto_pack_iovec iov = {
+        .sfn_id = TFM_CRYPTO_GET_KEY_POLICY_SFID,
+        .key = key,
+    };
+
     psa_invec in_vec[] = {
-        {.base = &key, .len = sizeof(psa_key_slot_t)},
+        {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)},
     };
     psa_outvec out_vec[] = {
         {.base = policy, .len = sizeof(psa_key_policy_t)},
     };
 
-    status = API_DISPATCH(tfm_crypto_get_key_policy);
+#ifdef TFM_PSA_API
+    PSA_CONNECT(TFM_CRYPTO);
+#endif
+
+    status = API_DISPATCH(tfm_crypto_get_key_policy,
+                          TFM_CRYPTO_GET_KEY_POLICY);
+#ifdef TFM_PSA_API
+    PSA_CLOSE();
+#endif
 
     return status;
 }
@@ -226,12 +383,25 @@
                                   psa_key_lifetime_t lifetime)
 {
     psa_status_t status;
-    psa_invec in_vec[] = {
-        {.base = &key, .len = sizeof(psa_key_slot_t)},
-        {.base = &lifetime, .len = sizeof(psa_key_lifetime_t)},
+    struct tfm_crypto_pack_iovec iov = {
+        .sfn_id = TFM_CRYPTO_SET_KEY_LIFETIME_SFID,
+        .key = key,
+        .lifetime = lifetime,
     };
 
-    status = API_DISPATCH_NO_OUTVEC(tfm_crypto_set_key_lifetime);
+    psa_invec in_vec[] = {
+        {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)},
+    };
+
+#ifdef TFM_PSA_API
+    PSA_CONNECT(TFM_CRYPTO);
+#endif
+
+    status = API_DISPATCH_NO_OUTVEC(tfm_crypto_set_key_lifetime,
+                                    TFM_CRYPTO_SET_KEY_LIFETIME);
+#ifdef TFM_PSA_API
+    PSA_CLOSE();
+#endif
 
     return status;
 }
@@ -240,14 +410,27 @@
                                   psa_key_lifetime_t *lifetime)
 {
     psa_status_t status;
+    struct tfm_crypto_pack_iovec iov = {
+        .sfn_id = TFM_CRYPTO_GET_KEY_LIFETIME_SFID,
+        .key = key,
+    };
+
     psa_invec in_vec[] = {
-        {.base = &key, .len = sizeof(psa_key_slot_t)},
+        {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)},
     };
     psa_outvec out_vec[] = {
         {.base = lifetime, .len = sizeof(psa_key_lifetime_t)},
     };
 
-    status = API_DISPATCH(tfm_crypto_get_key_lifetime);
+#ifdef TFM_PSA_API
+    PSA_CONNECT(TFM_CRYPTO);
+#endif
+
+    status = API_DISPATCH(tfm_crypto_get_key_lifetime,
+                          TFM_CRYPTO_GET_KEY_LIFETIME);
+#ifdef TFM_PSA_API
+    PSA_CLOSE();
+#endif
 
     return status;
 }
@@ -257,14 +440,28 @@
                                size_t iv_length)
 {
     psa_status_t status;
+    struct tfm_crypto_pack_iovec iov = {
+        .sfn_id = TFM_CRYPTO_CIPHER_SET_IV_SFID,
+        .handle = operation->handle,
+    };
+
     psa_invec in_vec[] = {
+        {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)},
         {.base = iv, .len = iv_length},
     };
     psa_outvec out_vec[] = {
-        {.base = operation, .len = sizeof(psa_cipher_operation_t)},
+        {.base = &(operation->handle), .len = sizeof(uint32_t)},
     };
 
-    status = API_DISPATCH(tfm_crypto_cipher_set_iv);
+#ifdef TFM_PSA_API
+    PSA_CONNECT(TFM_CRYPTO);
+#endif
+
+    status = API_DISPATCH(tfm_crypto_cipher_set_iv,
+                          TFM_CRYPTO_CIPHER_SET_IV);
+#ifdef TFM_PSA_API
+    PSA_CLOSE();
+#endif
 
     return status;
 }
@@ -274,15 +471,29 @@
                                       psa_algorithm_t alg)
 {
     psa_status_t status;
-    psa_invec in_vec[] = {
-        {.base = &key, .len = sizeof(psa_key_slot_t)},
-        {.base = &alg, .len = sizeof(psa_algorithm_t)},
-    };
-    psa_outvec out_vec[] = {
-        {.base = operation, .len = sizeof(psa_cipher_operation_t)},
+    struct tfm_crypto_pack_iovec iov = {
+        .sfn_id = TFM_CRYPTO_CIPHER_ENCRYPT_SETUP_SFID,
+        .key = key,
+        .alg = alg,
+        .handle = operation->handle,
     };
 
-    status = API_DISPATCH(tfm_crypto_cipher_encrypt_setup);
+    psa_invec in_vec[] = {
+        {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)},
+    };
+    psa_outvec out_vec[] = {
+        {.base = &(operation->handle), .len = sizeof(uint32_t)},
+    };
+
+#ifdef TFM_PSA_API
+    PSA_CONNECT(TFM_CRYPTO);
+#endif
+
+    status = API_DISPATCH(tfm_crypto_cipher_encrypt_setup,
+                          TFM_CRYPTO_CIPHER_ENCRYPT_SETUP);
+#ifdef TFM_PSA_API
+    PSA_CLOSE();
+#endif
 
     return status;
 }
@@ -292,15 +503,29 @@
                                       psa_algorithm_t alg)
 {
     psa_status_t status;
-    psa_invec in_vec[] = {
-        {.base = &key, .len = sizeof(psa_key_slot_t)},
-        {.base = &alg, .len = sizeof(psa_algorithm_t)},
-    };
-    psa_outvec out_vec[] = {
-        {.base = operation, .len = sizeof(psa_cipher_operation_t)},
+    struct tfm_crypto_pack_iovec iov = {
+        .sfn_id = TFM_CRYPTO_CIPHER_DECRYPT_SETUP_SFID,
+        .key = key,
+        .alg = alg,
+        .handle = operation->handle,
     };
 
-    status = API_DISPATCH(tfm_crypto_cipher_decrypt_setup);
+    psa_invec in_vec[] = {
+        {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)},
+    };
+    psa_outvec out_vec[] = {
+        {.base = &(operation->handle), .len = sizeof(uint32_t)},
+    };
+
+#ifdef TFM_PSA_API
+    PSA_CONNECT(TFM_CRYPTO);
+#endif
+
+    status = API_DISPATCH(tfm_crypto_cipher_decrypt_setup,
+                          TFM_CRYPTO_CIPHER_DECRYPT_SETUP);
+#ifdef TFM_PSA_API
+    PSA_CLOSE();
+#endif
 
     return status;
 }
@@ -313,29 +538,60 @@
                                size_t *output_length)
 {
     psa_status_t status;
+    struct tfm_crypto_pack_iovec iov = {
+        .sfn_id = TFM_CRYPTO_CIPHER_UPDATE_SFID,
+        .handle = operation->handle,
+    };
+
     psa_invec in_vec[] = {
+        {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)},
         {.base = input, .len = input_length},
     };
     psa_outvec out_vec[] = {
-        {.base = operation, .len = sizeof(psa_cipher_operation_t)},
+        {.base = &(operation->handle), .len = sizeof(uint32_t)},
         {.base = output, .len = output_size}
     };
 
-    status = API_DISPATCH(tfm_crypto_cipher_update);
+#ifdef TFM_PSA_API
+    PSA_CONNECT(TFM_CRYPTO);
+#endif
+
+    status = API_DISPATCH(tfm_crypto_cipher_update,
+                          TFM_CRYPTO_CIPHER_UPDATE);
 
     *output_length = out_vec[1].len;
 
+#ifdef TFM_PSA_API
+    PSA_CLOSE();
+#endif
+
     return status;
 }
 
 psa_status_t psa_cipher_abort(psa_cipher_operation_t *operation)
 {
     psa_status_t status;
-    psa_outvec out_vec[] = {
-        {.base = operation, .len = sizeof(psa_cipher_operation_t)},
+    struct tfm_crypto_pack_iovec iov = {
+        .sfn_id = TFM_CRYPTO_CIPHER_ABORT_SFID,
+        .handle = operation->handle,
     };
 
-    status = API_DISPATCH_NO_INVEC(tfm_crypto_cipher_abort);
+    psa_invec in_vec[] = {
+        {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)},
+    };
+    psa_outvec out_vec[] = {
+        {.base = &(operation->handle), .len = sizeof(uint32_t)},
+    };
+
+#ifdef TFM_PSA_API
+    PSA_CONNECT(TFM_CRYPTO);
+#endif
+
+    status = API_DISPATCH(tfm_crypto_cipher_abort,
+                          TFM_CRYPTO_CIPHER_ABORT);
+#ifdef TFM_PSA_API
+    PSA_CLOSE();
+#endif
 
     return status;
 }
@@ -346,15 +602,32 @@
                                size_t *output_length)
 {
     psa_status_t status;
+    struct tfm_crypto_pack_iovec iov = {
+        .sfn_id = TFM_CRYPTO_CIPHER_FINISH_SFID,
+        .handle = operation->handle,
+    };
+
+    psa_invec in_vec[] = {
+        {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)},
+    };
     psa_outvec out_vec[] = {
-        {.base = operation, .len = sizeof(psa_cipher_operation_t)},
+        {.base = &(operation->handle), .len = sizeof(uint32_t)},
         {.base = output, .len = output_size},
     };
 
-    status = API_DISPATCH_NO_INVEC(tfm_crypto_cipher_finish);
+#ifdef TFM_PSA_API
+    PSA_CONNECT(TFM_CRYPTO);
+#endif
+
+    status = API_DISPATCH(tfm_crypto_cipher_finish,
+                          TFM_CRYPTO_CIPHER_FINISH);
 
     *output_length = out_vec[1].len;
 
+#ifdef TFM_PSA_API
+    PSA_CLOSE();
+#endif
+
     return status;
 }
 
@@ -362,14 +635,29 @@
                             psa_algorithm_t alg)
 {
     psa_status_t status;
-    psa_invec in_vec[] = {
-        {.base = &alg, .len = sizeof(psa_algorithm_t)},
-    };
-    psa_outvec out_vec[] = {
-        {.base = operation, .len = sizeof(psa_hash_operation_t)},
+    struct tfm_crypto_pack_iovec iov = {
+        .sfn_id = TFM_CRYPTO_HASH_SETUP_SFID,
+        .alg = alg,
+        .handle = operation->handle,
     };
 
-    status = API_DISPATCH(tfm_crypto_hash_setup);
+    psa_invec in_vec[] = {
+        {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)},
+    };
+    psa_outvec out_vec[] = {
+        {.base = &(operation->handle), .len = sizeof(uint32_t)},
+    };
+
+#ifdef TFM_PSA_API
+    PSA_CONNECT(TFM_CRYPTO);
+#endif
+
+    status = API_DISPATCH(tfm_crypto_hash_setup,
+                          TFM_CRYPTO_HASH_SETUP);
+
+#ifdef TFM_PSA_API
+    PSA_CLOSE();
+#endif
 
     return status;
 }
@@ -379,14 +667,29 @@
                              size_t input_length)
 {
     psa_status_t status;
+    struct tfm_crypto_pack_iovec iov = {
+        .sfn_id = TFM_CRYPTO_HASH_UPDATE_SFID,
+        .handle = operation->handle,
+    };
+
     psa_invec in_vec[] = {
+        {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)},
         {.base = input, .len = input_length},
     };
     psa_outvec out_vec[] = {
-        {.base = operation, .len = sizeof(psa_hash_operation_t)},
+        {.base = &(operation->handle), .len = sizeof(uint32_t)},
     };
 
-    status = API_DISPATCH(tfm_crypto_hash_update);
+#ifdef TFM_PSA_API
+    PSA_CONNECT(TFM_CRYPTO);
+#endif
+
+    status = API_DISPATCH(tfm_crypto_hash_update,
+                          TFM_CRYPTO_HASH_UPDATE);
+
+#ifdef TFM_PSA_API
+    PSA_CLOSE();
+#endif
 
     return status;
 }
@@ -397,15 +700,32 @@
                              size_t *hash_length)
 {
     psa_status_t status;
+    struct tfm_crypto_pack_iovec iov = {
+        .sfn_id = TFM_CRYPTO_HASH_FINISH_SFID,
+        .handle = operation->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 = &(operation->handle), .len = sizeof(uint32_t)},
         {.base = hash, .len = hash_size},
     };
 
-    status = API_DISPATCH_NO_INVEC(tfm_crypto_hash_finish);
+#ifdef TFM_PSA_API
+    PSA_CONNECT(TFM_CRYPTO);
+#endif
+
+    status = API_DISPATCH(tfm_crypto_hash_finish,
+                          TFM_CRYPTO_HASH_FINISH);
 
     *hash_length = out_vec[1].len;
 
+#ifdef TFM_PSA_API
+    PSA_CLOSE();
+#endif
+
     return status;
 }
 
@@ -414,14 +734,28 @@
                              size_t hash_length)
 {
     psa_status_t status;
+    struct tfm_crypto_pack_iovec iov = {
+        .sfn_id = TFM_CRYPTO_HASH_VERIFY_SFID,
+        .handle = operation->handle,
+    };
+
     psa_invec in_vec[] = {
+        {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)},
         {.base = hash, .len = hash_length},
     };
     psa_outvec out_vec[] = {
-        {.base = operation, .len = sizeof(psa_hash_operation_t)},
+        {.base = &(operation->handle), .len = sizeof(uint32_t)},
     };
 
-    status = API_DISPATCH(tfm_crypto_hash_verify);
+#ifdef TFM_PSA_API
+    PSA_CONNECT(TFM_CRYPTO);
+#endif
+
+    status = API_DISPATCH(tfm_crypto_hash_verify,
+                          TFM_CRYPTO_HASH_VERIFY);
+#ifdef TFM_PSA_API
+    PSA_CLOSE();
+#endif
 
     return status;
 }
@@ -429,11 +763,27 @@
 psa_status_t psa_hash_abort(psa_hash_operation_t *operation)
 {
     psa_status_t status;
-    psa_outvec out_vec[] = {
-        {.base = operation, .len = sizeof(psa_hash_operation_t)},
+    struct tfm_crypto_pack_iovec iov = {
+        .sfn_id = TFM_CRYPTO_HASH_ABORT_SFID,
+        .handle = operation->handle,
     };
 
-    status = API_DISPATCH_NO_INVEC(tfm_crypto_hash_abort);
+    psa_invec in_vec[] = {
+        {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)},
+    };
+    psa_outvec out_vec[] = {
+        {.base = &(operation->handle), .len = sizeof(uint32_t)},
+    };
+
+#ifdef TFM_PSA_API
+    PSA_CONNECT(TFM_CRYPTO);
+#endif
+
+    status = API_DISPATCH(tfm_crypto_hash_abort,
+                          TFM_CRYPTO_HASH_ABORT);
+#ifdef TFM_PSA_API
+    PSA_CLOSE();
+#endif
 
     return status;
 }
@@ -443,15 +793,29 @@
                                 psa_algorithm_t alg)
 {
     psa_status_t status;
-    psa_invec in_vec[] = {
-        {.base = &key, .len = sizeof(psa_key_slot_t)},
-        {.base = &alg, .len = sizeof(psa_algorithm_t)}
-    };
-    psa_outvec out_vec[] = {
-        {.base = operation, .len = sizeof(psa_mac_operation_t)},
+    struct tfm_crypto_pack_iovec iov = {
+        .sfn_id = TFM_CRYPTO_MAC_SIGN_SETUP_SFID,
+        .key = key,
+        .alg = alg,
+        .handle = operation->handle,
     };
 
-    status = API_DISPATCH(tfm_crypto_mac_sign_setup);
+    psa_invec in_vec[] = {
+        {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)},
+    };
+    psa_outvec out_vec[] = {
+        {.base = &(operation->handle), .len = sizeof(uint32_t)},
+    };
+
+#ifdef TFM_PSA_API
+    PSA_CONNECT(TFM_CRYPTO);
+#endif
+
+    status = API_DISPATCH(tfm_crypto_mac_sign_setup,
+                          TFM_CRYPTO_MAC_SIGN_SETUP);
+#ifdef TFM_PSA_API
+    PSA_CLOSE();
+#endif
 
     return status;
 }
@@ -461,15 +825,29 @@
                                   psa_algorithm_t alg)
 {
     psa_status_t status;
-    psa_invec in_vec[] = {
-        {.base = &key, .len = sizeof(psa_key_slot_t)},
-        {.base = &alg, .len = sizeof(psa_algorithm_t)}
-    };
-    psa_outvec out_vec[] = {
-        {.base = operation, .len = sizeof(psa_mac_operation_t)},
+    struct tfm_crypto_pack_iovec iov = {
+        .sfn_id = TFM_CRYPTO_MAC_VERIFY_SETUP_SFID,
+        .key = key,
+        .alg = alg,
+        .handle = operation->handle,
     };
 
-    status = API_DISPATCH(tfm_crypto_mac_verify_setup);
+    psa_invec in_vec[] = {
+        {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)},
+    };
+    psa_outvec out_vec[] = {
+        {.base = &(operation->handle), .len = sizeof(uint32_t)},
+    };
+
+#ifdef TFM_PSA_API
+    PSA_CONNECT(TFM_CRYPTO);
+#endif
+
+    status = API_DISPATCH(tfm_crypto_mac_verify_setup,
+                          TFM_CRYPTO_MAC_VERIFY_SETUP);
+#ifdef TFM_PSA_API
+    PSA_CLOSE();
+#endif
 
     return status;
 }
@@ -479,14 +857,28 @@
                             size_t input_length)
 {
     psa_status_t status;
+    struct tfm_crypto_pack_iovec iov = {
+        .sfn_id = TFM_CRYPTO_MAC_UPDATE_SFID,
+        .handle = operation->handle,
+    };
+
     psa_invec in_vec[] = {
+        {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)},
         {.base = input, .len = input_length},
     };
     psa_outvec out_vec[] = {
-        {.base = operation, .len = sizeof(psa_mac_operation_t)},
+        {.base = &(operation->handle), .len = sizeof(uint32_t)},
     };
 
-    status = API_DISPATCH(tfm_crypto_mac_update);
+#ifdef TFM_PSA_API
+    PSA_CONNECT(TFM_CRYPTO);
+#endif
+
+    status = API_DISPATCH(tfm_crypto_mac_update,
+                          TFM_CRYPTO_MAC_UPDATE);
+#ifdef TFM_PSA_API
+    PSA_CLOSE();
+#endif
 
     return status;
 }
@@ -497,15 +889,32 @@
                                  size_t *mac_length)
 {
     psa_status_t status;
+    struct tfm_crypto_pack_iovec iov = {
+        .sfn_id = TFM_CRYPTO_MAC_SIGN_FINISH_SFID,
+        .handle = operation->handle,
+    };
+
+    psa_invec in_vec[] = {
+        {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)},
+    };
     psa_outvec out_vec[] = {
-        {.base = operation, .len = sizeof(psa_mac_operation_t)},
+        {.base = &(operation->handle), .len = sizeof(uint32_t)},
         {.base = mac, .len = mac_size},
     };
 
-    status = API_DISPATCH_NO_INVEC(tfm_crypto_mac_sign_finish);
+#ifdef TFM_PSA_API
+    PSA_CONNECT(TFM_CRYPTO);
+#endif
+
+    status = API_DISPATCH(tfm_crypto_mac_sign_finish,
+                          TFM_CRYPTO_MAC_SIGN_FINISH);
 
     *mac_length = out_vec[1].len;
 
+#ifdef TFM_PSA_API
+    PSA_CLOSE();
+#endif
+
     return status;
 }
 
@@ -514,14 +923,29 @@
                                    size_t mac_length)
 {
     psa_status_t status;
+    struct tfm_crypto_pack_iovec iov = {
+        .sfn_id = TFM_CRYPTO_MAC_VERIFY_FINISH_SFID,
+        .handle = operation->handle,
+    };
+
     psa_invec in_vec[] = {
+        {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)},
         {.base = mac, .len = mac_length},
     };
     psa_outvec out_vec[] = {
-        {.base = operation, .len = sizeof(psa_mac_operation_t)},
+        {.base = &(operation->handle), .len = sizeof(uint32_t)},
     };
 
-    status = API_DISPATCH(tfm_crypto_mac_verify_finish);
+#ifdef TFM_PSA_API
+    PSA_CONNECT(TFM_CRYPTO);
+#endif
+
+    status = API_DISPATCH(tfm_crypto_mac_verify_finish,
+                          TFM_CRYPTO_MAC_VERIFY_FINISH);
+
+#ifdef TFM_PSA_API
+    PSA_CLOSE();
+#endif
 
     return status;
 }
@@ -529,11 +953,27 @@
 psa_status_t psa_mac_abort(psa_mac_operation_t *operation)
 {
     psa_status_t status;
-    psa_outvec out_vec[] = {
-        {.base = operation, .len = sizeof(psa_mac_operation_t)},
+    struct tfm_crypto_pack_iovec iov = {
+        .sfn_id = TFM_CRYPTO_MAC_ABORT_SFID,
+        .handle = operation->handle,
     };
 
-    status = API_DISPATCH_NO_INVEC(tfm_crypto_mac_abort);
+    psa_invec in_vec[] = {
+        {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)},
+    };
+    psa_outvec out_vec[] = {
+        {.base = &(operation->handle), .len = sizeof(uint32_t)},
+    };
+
+#ifdef TFM_PSA_API
+    PSA_CONNECT(TFM_CRYPTO);
+#endif
+
+    status = API_DISPATCH(tfm_crypto_mac_abort,
+                          TFM_CRYPTO_MAC_ABORT);
+#ifdef TFM_PSA_API
+    PSA_CLOSE();
+#endif
 
     return status;
 }
@@ -551,17 +991,18 @@
                               size_t *ciphertext_length)
 {
     psa_status_t status;
-    struct tfm_crypto_aead_pack_input input_s = {
-      .key = key,
-      .alg = alg,
-      .nonce = {0},
+    struct tfm_crypto_pack_iovec iov = {
+        .sfn_id = TFM_CRYPTO_AEAD_ENCRYPT_SFID,
+        .key = key,
+        .alg = alg,
+        .aead_in = {.nonce = {0}, .nonce_length = nonce_length}
     };
+
     size_t idx = 0;
     psa_invec in_vec[] = {
-        {.base = &input_s, .len = nonce_length + sizeof(psa_key_slot_t)
-                                               + sizeof(psa_algorithm_t)},
-        {.base = additional_data, .len = additional_data_length},
+        {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)},
         {.base = plaintext, .len = plaintext_length},
+        {.base = additional_data, .len = additional_data_length},
     };
     psa_outvec out_vec[] = {
         {.base = ciphertext, .len = ciphertext_size},
@@ -573,14 +1014,32 @@
 
     if (nonce != NULL) {
         for (idx = 0; idx < nonce_length; idx++) {
-            input_s.nonce[idx] = nonce[idx];
+            iov.aead_in.nonce[idx] = nonce[idx];
         }
     }
 
-    status = API_DISPATCH(tfm_crypto_aead_encrypt);
+#ifdef TFM_PSA_API
+    PSA_CONNECT(TFM_CRYPTO);
+#endif
+
+#ifdef TFM_PSA_API
+    size_t in_len = sizeof(in_vec)/sizeof(in_vec[0]);
+    if (additional_data == NULL) {
+      in_len--;
+    }
+    status = psa_call(handle, in_vec, in_len,
+                      out_vec, sizeof(out_vec)/sizeof(out_vec[0]));
+#else
+    status = API_DISPATCH(tfm_crypto_aead_encrypt,
+                          TFM_CRYPTO_AEAD_ENCRYPT);
+#endif
 
     *ciphertext_length = out_vec[0].len;
 
+#ifdef TFM_PSA_API
+    PSA_CLOSE();
+#endif
+
     return status;
 }
 
@@ -597,17 +1056,18 @@
                               size_t *plaintext_length)
 {
     psa_status_t status;
-    struct tfm_crypto_aead_pack_input input_s = {
-      .key = key,
-      .alg = alg,
-      .nonce = {0},
+    struct tfm_crypto_pack_iovec iov = {
+        .sfn_id = TFM_CRYPTO_AEAD_DECRYPT_SFID,
+        .key = key,
+        .alg = alg,
+        .aead_in = {.nonce = {0}, .nonce_length = nonce_length}
     };
+
     size_t idx = 0;
     psa_invec in_vec[] = {
-        {.base = &input_s, .len = nonce_length + sizeof(psa_key_slot_t)
-                                               + sizeof(psa_algorithm_t)},
-        {.base = additional_data, .len = additional_data_length},
+        {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)},
         {.base = ciphertext, .len = ciphertext_length},
+        {.base = additional_data, .len = additional_data_length},
     };
     psa_outvec out_vec[] = {
         {.base = plaintext, .len = plaintext_size},
@@ -619,13 +1079,31 @@
 
     if (nonce != NULL) {
         for (idx = 0; idx < nonce_length; idx++) {
-            input_s.nonce[idx] = nonce[idx];
+            iov.aead_in.nonce[idx] = nonce[idx];
         }
     }
 
-    status = API_DISPATCH(tfm_crypto_aead_decrypt);
+#ifdef TFM_PSA_API
+    PSA_CONNECT(TFM_CRYPTO);
+#endif
+
+#ifdef TFM_PSA_API
+    size_t in_len = sizeof(in_vec)/sizeof(in_vec[0]);
+    if (additional_data == NULL) {
+      in_len--;
+    }
+    status = psa_call(handle, in_vec, in_len,
+                      out_vec, sizeof(out_vec)/sizeof(out_vec[0]));
+#else
+    status = API_DISPATCH(tfm_crypto_aead_decrypt,
+                          TFM_CRYPTO_AEAD_DECRYPT);
+#endif
 
     *plaintext_length = out_vec[0].len;
 
+#ifdef TFM_PSA_API
+    PSA_CLOSE();
+#endif
+
     return status;
 }
diff --git a/secure_fw/core/ipc/include/tfm_spm_signal_defs.h b/secure_fw/core/ipc/include/tfm_spm_signal_defs.h
index c0c4bf4..1402bd0 100644
--- a/secure_fw/core/ipc/include/tfm_spm_signal_defs.h
+++ b/secure_fw/core/ipc/include/tfm_spm_signal_defs.h
@@ -10,7 +10,8 @@
 #include "test/test_services/tfm_ipc_service/tfm_ipc_service_partition.h"
 #include "test/test_services/tfm_core_test/tfm_ss_core_test_signal.h"
 #include "test/test_services/tfm_core_test_2/tfm_ss_core_test_2_signal.h"
+#include "secure_fw/services/crypto/tfm_crypto_signal.h"
 #include "secure_fw/services/secure_storage/tfm_sst_signal.h"
 #include "test/test_services/tfm_secure_client_service/tfm_sec_client_ser_sig.h"
 
-#endif
+#endif /* __TFM_SPM_SIGNAL_DEFS_H__ */
diff --git a/secure_fw/services/crypto/CMakeLists.inc b/secure_fw/services/crypto/CMakeLists.inc
index dc70627..6a65652 100644
--- a/secure_fw/services/crypto/CMakeLists.inc
+++ b/secure_fw/services/crypto/CMakeLists.inc
@@ -81,6 +81,13 @@
   else()
     message("- CRYPTO_ENGINE_BUF_SIZE: " ${CRYPTO_ENGINE_BUF_SIZE})
   endif()
+  if (TFM_PSA_API)
+    if (NOT DEFINED CRYPTO_IOVEC_BUFFER_SIZE)
+      message("- CRYPTO_IOVEC_BUFFER_SIZE using default value")
+    else()
+      message("- CRYPTO_IOVEC_BUFFER_SIZE: " ${CRYPTO_IOVEC_BUFFER_SIZE})
+    endif()
+  endif()
 
 else()
   message(FATAL_ERROR "Build system currently doesn't support selectively disabling of a service.")
diff --git a/secure_fw/services/crypto/CMakeLists.txt b/secure_fw/services/crypto/CMakeLists.txt
index 04bda24..0cce934 100644
--- a/secure_fw/services/crypto/CMakeLists.txt
+++ b/secure_fw/services/crypto/CMakeLists.txt
@@ -62,6 +62,9 @@
 if (DEFINED CRYPTO_ENGINE_BUF_SIZE)
   list(APPEND TFM_CRYPTO_C_DEFINES_LIST TFM_CRYPTO_ENGINE_BUF_SIZE=${CRYPTO_ENGINE_BUF_SIZE})
 endif()
+if (TFM_PSA_API AND DEFINED CRYPTO_IOVEC_BUFFER_SIZE)
+  list(APPEND TFM_CRYPTO_C_DEFINES_LIST TFM_CRYPTO_IOVEC_BUFFER_SIZE=${CRYPTO_IOVEC_BUFFER_SIZE})
+endif()
 
 if (CRYPTO_ENGINE_MBEDTLS)
   #Set mbed TLS compiler flags
diff --git a/secure_fw/services/crypto/crypto_aead.c b/secure_fw/services/crypto/crypto_aead.c
index 7978d7f..4926b28 100644
--- a/secure_fw/services/crypto/crypto_aead.c
+++ b/secure_fw/services/crypto/crypto_aead.c
@@ -7,13 +7,15 @@
 
 #include <limits.h>
 
-#include "tfm_crypto_defs.h"
-
-#include "crypto_engine.h"
-
-#include "psa_crypto.h"
-
 #include "tfm_crypto_api.h"
+#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.
+ */
 
 /**
  * \def CRYPTO_AEAD_MAX_KEY_LENGTH
@@ -29,17 +31,24 @@
                                              psa_key_type_t *type,
                                              size_t *bits)
 {
+    psa_status_t status;
+    struct tfm_crypto_pack_iovec iov = {
+        .sfn_id = TFM_CRYPTO_GET_KEY_INFORMATION_SFID,
+        .key = key,
+    };
     psa_invec in_vec[] = {
-        {.base = &key, .len = sizeof(psa_key_slot_t)},
+        {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)},
     };
     psa_outvec out_vec[] = {
         {.base = type, .len = sizeof(psa_key_type_t)},
         {.base = bits, .len = sizeof(size_t)}
     };
 
-    return tfm_crypto_get_key_information(
+    status = tfm_crypto_get_key_information(
                  in_vec, sizeof(in_vec)/sizeof(in_vec[0]),
                  out_vec, sizeof(out_vec)/sizeof(out_vec[0]));
+
+    return status;
 }
 
 /*!
@@ -58,28 +67,31 @@
     uint32_t key_size;
     psa_key_type_t key_type;
 
-    if ((in_len != 3) || (out_len != 1)) {
+    if ( !((in_len == 2) || (in_len == 3)) || (out_len != 1)) {
         return PSA_CONNECTION_REFUSED;
     }
 
-    if ((in_vec[0].len < (sizeof(psa_key_slot_t) + sizeof(psa_algorithm_t))) ||
-        (in_vec[0].len > (TFM_CRYPTO_MAX_NONCE_LENGTH
-                       + (sizeof(psa_key_slot_t) + sizeof(psa_algorithm_t))))) {
+    if ((in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec))) {
         return PSA_CONNECTION_REFUSED;
     }
-
-    const struct tfm_crypto_aead_pack_input *input_s = in_vec[0].base;
-    psa_key_slot_t key = input_s->key;
-    psa_algorithm_t alg = input_s->alg;
-    const uint8_t *nonce = input_s->nonce;
-    size_t nonce_length = in_vec[0].len - sizeof(psa_key_slot_t)
-                                        - sizeof(psa_algorithm_t);
-    const uint8_t *additional_data = in_vec[1].base;
-    size_t additional_data_length = in_vec[1].len;
-    const uint8_t *plaintext = in_vec[2].base;
-    size_t plaintext_length = in_vec[2].len;
+    const struct tfm_crypto_pack_iovec *iov = in_vec[0].base;
+    const struct tfm_crypto_aead_pack_input *aead_pack_input = &iov->aead_in;
+    psa_key_slot_t key = iov->key;
+    psa_algorithm_t alg = iov->alg;
+    const uint8_t *nonce = aead_pack_input->nonce;
+    size_t nonce_length = aead_pack_input->nonce_length;
+    const uint8_t *plaintext = in_vec[1].base;
+    size_t plaintext_length = in_vec[1].len;
     uint8_t *ciphertext = out_vec[0].base;
     size_t ciphertext_size = out_vec[0].len;
+    const uint8_t *additional_data = NULL;
+    size_t additional_data_length = 0;
+
+    /* Check if additional data has been passed and initialise it */
+    if (in_len == 3) {
+        additional_data = in_vec[2].base;
+        additional_data_length = in_vec[2].len;
+    }
 
     /* Initialise ciphertext_length to zero */
     out_vec[0].len = 0;
@@ -158,24 +170,31 @@
     uint32_t key_size;
     psa_key_type_t key_type;
 
-    if ((in_vec[0].len < (sizeof(psa_key_slot_t) + sizeof(psa_algorithm_t))) ||
-        (in_vec[0].len > (TFM_CRYPTO_MAX_NONCE_LENGTH
-                       + (sizeof(psa_key_slot_t) + sizeof(psa_algorithm_t))))) {
+    if ( !((in_len == 2) || (in_len == 3)) || (out_len != 1)) {
         return PSA_CONNECTION_REFUSED;
     }
 
-    const struct tfm_crypto_aead_pack_input *input_s = in_vec[0].base;
-    psa_key_slot_t key = input_s->key;
-    psa_algorithm_t alg = input_s->alg;
-    const uint8_t *nonce = input_s->nonce;
-    size_t nonce_length = in_vec[0].len - sizeof(psa_key_slot_t)
-                                        - sizeof(psa_algorithm_t);
-    const uint8_t *additional_data = in_vec[1].base;
-    size_t additional_data_length = in_vec[1].len;
-    const uint8_t *ciphertext = in_vec[2].base;
-    size_t ciphertext_length = in_vec[2].len;
+    if ((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;
+    const struct tfm_crypto_aead_pack_input *aead_pack_input = &iov->aead_in;
+    psa_key_slot_t key = iov->key;
+    psa_algorithm_t alg = iov->alg;
+    const uint8_t *nonce = aead_pack_input->nonce;
+    size_t nonce_length = aead_pack_input->nonce_length;
+    const uint8_t *ciphertext = in_vec[1].base;
+    size_t ciphertext_length = in_vec[1].len;
     uint8_t *plaintext = out_vec[0].base;
     size_t plaintext_size = out_vec[0].len;
+    const uint8_t *additional_data = NULL;
+    size_t additional_data_length = 0;
+
+    /* Check if additional data has been passed and initialise it */
+    if (in_len == 3) {
+        additional_data = in_vec[2].base;
+        additional_data_length = in_vec[2].len;
+    }
 
     /* Initialise plaintext_length to zero */
     out_vec[0].len = 0;
diff --git a/secure_fw/services/crypto/crypto_alloc.c b/secure_fw/services/crypto/crypto_alloc.c
index 8705029..9726fa0 100644
--- a/secure_fw/services/crypto/crypto_alloc.c
+++ b/secure_fw/services/crypto/crypto_alloc.c
@@ -16,47 +16,6 @@
 #include "secure_fw/core/tfm_memory_utils.h"
 
 /**
- * \def LIST_OPERATION_LOOKUP
- *
- * \brief This is an X macro which enforces the correspondence
- *        between backend operation type (through the enum
- *        tfm_crypto_operation_type) and the corresponding frontend type
- */
-#define LIST_OPERATION_LOOKUP \
-    X(TFM_CRYPTO_CIPHER_OPERATION, psa_cipher_operation_t) \
-    X(TFM_CRYPTO_MAC_OPERATION, psa_mac_operation_t) \
-    X(TFM_CRYPTO_HASH_OPERATION, psa_hash_operation_t)
-
-/**
- * \def CHECK_ALIGNMENT
- *
- * \brief This macro checks the alignment of the operation object pointer which
- *        receives as input based on the requirement of the front end operation
- *        type. This macro expands in a case statement so it must be used in a
- *        switch-case construct. It sets the handle value it receives in input
- *        with the proper value or TFM_CRYPTO_INVALID_HANDLE in case the oper
- *        pointer does not satisfy alignment requirements of the front end type
- */
-#define CHECK_ALIGNMENT(e,t,oper,handle)                           \
-    case e:                                                        \
-        if ((uintptr_t)oper % offsetof(struct {char c; t x;},x)) { \
-            handle = TFM_CRYPTO_INVALID_HANDLE;                    \
-        } else {                                                   \
-            handle = ((t *)oper)->handle;                          \
-        }                                                          \
-        break;
-/**
- * \def GET_HANDLE_POINTER
- *
- * \brief This macro extracts the pointer to handle value from the object
- *        operation pointer it receives as input. This macro expands in a case
- *        statement so it must be used in a switch case-case construct.
- */
-#define GET_HANDLE_POINTER(e,t,oper,handle) \
-    case e:                                 \
-        handle = &(((t *)oper)->handle);    \
-        break;
-/**
  * \def TFM_CRYPTO_CONC_OPER_NUM
  *
  * \brief This value defines the maximum number of simultaneous operations
@@ -110,80 +69,6 @@
     (void)tfm_memset(mem_ptr, 0, mem_size);
 }
 
-/*
- * \brief Function used to extract the handle value from a pointer to a
- *        frontend operation
- *
- * \param[in] type Type of the operation context to extract from
- * \param[in] oper Pointer to the frontend operation
- *
- * \return handle 4-byte identifier associated to the context,
- *                TFM_CRYPTO_INVALID_HANDLE in case of problems
- *
- */
-static uint32_t get_handle(enum tfm_crypto_operation_type type,
-                           const void *oper)
-{
-    uint32_t handle = TFM_CRYPTO_INVALID_HANDLE;
-
-    /* Dereference the pointer */
-    switch(type) {
-    /* Generate the list of cases needed to check alignment for all the
-     * possible operation types listed in LIST_OPERATION_LOOKUP. The default
-     * case and TFM_CRYPTO_OPERATION_NONE must be created explicitly
-     */
-#define X(e,t) CHECK_ALIGNMENT(e,t,oper,handle)
-LIST_OPERATION_LOOKUP
-#undef X
-    case TFM_CRYPTO_OPERATION_NONE:
-    default:
-        break;
-    }
-
-    return handle;
-}
-
-/*
- * \brief Function used to set the handle value in a pointer to a
- *        frontend operation
- *
- * \param[in]  type Type of the operation context to extract from
- * \param[out] oper Pointer to the frontend operation
- *
- * \return handle 4-byte identifier associated to the context,
- *                TFM_CRYPTO_INVALID_HANDLE in case of problems
- *
- */
-static uint32_t set_handle(enum tfm_crypto_operation_type type,
-                           void *oper,
-                           uint32_t set_value)
-{
-    uint32_t *handle = NULL;
-
-    /* Extract the pointer value */
-    switch(type) {
-    /* Generate the list of cases needed to get the handle pointer for all the
-     * possible operation types listed in LIST_OPERATION_LOOKUP. The default
-     * case and TFM_CRYPTO_OPERATION_NONE must be created explicitly
-     */
-#define X(e,t) GET_HANDLE_POINTER(e,t,oper,handle)
-LIST_OPERATION_LOOKUP
-#undef X
-    case TFM_CRYPTO_OPERATION_NONE:
-    default:
-        break;
-    }
-
-    if (handle == NULL || ((uintptr_t)handle % sizeof(uint32_t))) {
-        return TFM_CRYPTO_INVALID_HANDLE;
-    }
-
-    /* Set the value by derefencing the pointer, alignment is correct */
-    *handle = set_value;
-
-    return set_value;
-}
-
 /*!
  * \defgroup public Public functions
  *
@@ -198,10 +83,10 @@
 }
 
 psa_status_t tfm_crypto_operation_alloc(enum tfm_crypto_operation_type type,
-                                        void *oper,
+                                        uint32_t *handle,
                                         void **ctx)
 {
-    uint32_t i = 0, handle;
+    uint32_t i = 0;
 
     /* Init to invalid values */
     if (ctx == NULL) {
@@ -213,30 +98,27 @@
         if (operation[i].in_use == TFM_CRYPTO_NOT_IN_USE) {
             operation[i].in_use = TFM_CRYPTO_IN_USE;
             operation[i].type = type;
-            handle = set_handle(type, oper, i);
-            if (handle == TFM_CRYPTO_INVALID_HANDLE) {
-                return PSA_ERROR_NOT_PERMITTED;
-            }
+            *handle = i;
             *ctx = (void *) &(operation[i].operation);
             return PSA_SUCCESS;
         }
     }
 
+    *handle = TFM_CRYPTO_INVALID_HANDLE;
     return PSA_ERROR_NOT_PERMITTED;
 }
 
-psa_status_t tfm_crypto_operation_release(enum tfm_crypto_operation_type type,
-                                          void *oper)
+psa_status_t tfm_crypto_operation_release(uint32_t *handle)
 {
-    uint32_t handle = get_handle(type, oper);
+    uint32_t h_val = *handle;
 
-    if ( (handle != TFM_CRYPTO_INVALID_HANDLE) &&
-         (handle < TFM_CRYPTO_CONC_OPER_NUM) &&
-         (operation[handle].in_use == TFM_CRYPTO_IN_USE) ) {
-        memset_operation_context(handle);
-        operation[handle].in_use = TFM_CRYPTO_NOT_IN_USE;
-        operation[handle].type = TFM_CRYPTO_OPERATION_NONE;
-        (void)set_handle(type, oper, TFM_CRYPTO_INVALID_HANDLE);
+    if ( (h_val != TFM_CRYPTO_INVALID_HANDLE) &&
+         (h_val < TFM_CRYPTO_CONC_OPER_NUM) &&
+         (operation[h_val].in_use == TFM_CRYPTO_IN_USE) ) {
+        memset_operation_context(h_val);
+        operation[h_val].in_use = TFM_CRYPTO_NOT_IN_USE;
+        operation[h_val].type = TFM_CRYPTO_OPERATION_NONE;
+        *handle = TFM_CRYPTO_INVALID_HANDLE;
         return PSA_SUCCESS;
     }
 
@@ -244,11 +126,9 @@
 }
 
 psa_status_t tfm_crypto_operation_lookup(enum tfm_crypto_operation_type type,
-                                         const void *oper,
+                                         uint32_t handle,
                                          void **ctx)
 {
-    uint32_t handle = get_handle(type, oper);
-
     if ( (handle != TFM_CRYPTO_INVALID_HANDLE) &&
          (handle < TFM_CRYPTO_CONC_OPER_NUM) &&
          (operation[handle].in_use == TFM_CRYPTO_IN_USE) &&
diff --git a/secure_fw/services/crypto/crypto_cipher.c b/secure_fw/services/crypto/crypto_cipher.c
index 05d8285..757ccc0 100644
--- a/secure_fw/services/crypto/crypto_cipher.c
+++ b/secure_fw/services/crypto/crypto_cipher.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.
+ */
+
 /**
  * \def CRYPTO_CIPHER_MAX_KEY_LENGTH
  *
@@ -23,17 +29,24 @@
                                              psa_key_type_t *type,
                                              size_t *bits)
 {
+    psa_status_t status;
+    struct tfm_crypto_pack_iovec iov = {
+        .sfn_id = TFM_CRYPTO_GET_KEY_INFORMATION_SFID,
+        .key = key,
+    };
     psa_invec in_vec[] = {
-        {.base = &key, .len = sizeof(psa_key_slot_t)},
+        {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)},
     };
     psa_outvec out_vec[] = {
         {.base = type, .len = sizeof(psa_key_type_t)},
         {.base = bits, .len = sizeof(size_t)}
     };
 
-    return tfm_crypto_get_key_information(
+    status = tfm_crypto_get_key_information(
                  in_vec, sizeof(in_vec)/sizeof(in_vec[0]),
                  out_vec, sizeof(out_vec)/sizeof(out_vec[0]));
+
+    return status;
 }
 
 /**
@@ -45,7 +58,7 @@
  * \return Return values as described in \ref tfm_crypto_err_t
  */
 static psa_status_t tfm_crypto_cipher_release(
-                                             psa_cipher_operation_t *operation,
+                                             uint32_t *handle,
                                              struct tfm_cipher_operation_s *ctx)
 {
     psa_status_t status = PSA_SUCCESS;
@@ -57,10 +70,10 @@
     }
 
     /* Release the operation context */
-    return tfm_crypto_operation_release(TFM_CRYPTO_CIPHER_OPERATION, operation);
+    return tfm_crypto_operation_release(handle);
 }
 
-static psa_status_t tfm_crypto_cipher_setup(psa_cipher_operation_t *operation,
+static psa_status_t tfm_crypto_cipher_setup(uint32_t *handle,
                                             psa_key_slot_t key,
                                             psa_algorithm_t alg,
                                             enum engine_cipher_mode_t c_mode)
@@ -105,7 +118,7 @@
 
     /* Allocate the operation context in the secure world */
     status = tfm_crypto_operation_alloc(TFM_CRYPTO_CIPHER_OPERATION,
-                                        operation,
+                                        handle,
                                         (void **)&ctx);
     if (status != PSA_SUCCESS) {
         return status;
@@ -121,7 +134,7 @@
     status = tfm_crypto_engine_cipher_start(&(ctx->engine_ctx), &engine_info);
     if (status != PSA_SUCCESS) {
         /* Release the operation context, ignore if this operation fails. */
-        (void)tfm_crypto_cipher_release(operation, ctx);
+        (void)tfm_crypto_cipher_release(handle, ctx);
         return status;
     }
 
@@ -138,7 +151,7 @@
                                 &key_size);
     if (status != PSA_SUCCESS) {
         /* Release the operation context, ignore if this operation fails. */
-        (void)tfm_crypto_cipher_release(operation, ctx);
+        (void)tfm_crypto_cipher_release(handle, ctx);
         return status;
     }
 
@@ -149,7 +162,7 @@
                                               &engine_info);
     if (status != PSA_SUCCESS) {
         /* Release the operation context, ignore if this operation fails. */
-        (void)tfm_crypto_cipher_release(operation, ctx);
+        (void)tfm_crypto_cipher_release(handle, ctx);
         return status;
     }
 
@@ -164,7 +177,7 @@
                                                            &engine_info);
         if (status != PSA_SUCCESS) {
             /* Release the operation context, ignore if this operation fails. */
-            (void)tfm_crypto_cipher_release(operation, ctx);
+            (void)tfm_crypto_cipher_release(handle, ctx);
             return status;
         }
     }
@@ -190,33 +203,42 @@
     psa_status_t status = PSA_SUCCESS;
     struct tfm_cipher_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_cipher_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 unsigned char *iv = in_vec[1].base;
+    size_t iv_length = in_vec[1].len;
 
-    psa_cipher_operation_t *operation = out_vec[0].base;
-    const unsigned char *iv = in_vec[0].base;
-    size_t iv_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_CIPHER_OPERATION,
-                                         operation,
+                                         handle,
                                          (void **)&ctx);
     if (status != PSA_SUCCESS) {
         return status;
     }
 
     if ((iv_length != ctx->block_size) || (iv_length > TFM_CIPHER_IV_MAX_SIZE)){
-        (void)tfm_crypto_cipher_release(operation, ctx);
+        if (tfm_crypto_cipher_release(&handle, ctx) == PSA_SUCCESS) {
+            *handle_out = handle;
+        }
         return PSA_ERROR_INVALID_ARGUMENT;
     }
 
     if ((ctx->iv_set == 1) || (ctx->iv_required == 0)) {
-        (void)tfm_crypto_cipher_release(operation, ctx);
+        if (tfm_crypto_cipher_release(&handle, ctx) == PSA_SUCCESS) {
+            *handle_out = handle;
+        }
         return PSA_ERROR_BAD_STATE;
     }
 
@@ -225,7 +247,9 @@
                                              iv,
                                              iv_length);
     if (status != PSA_SUCCESS) {
-        (void)tfm_crypto_cipher_release(operation, ctx);
+        if (tfm_crypto_cipher_release(&handle, ctx) == PSA_SUCCESS) {
+            *handle_out = handle;
+        }
         return status;
     }
 
@@ -235,45 +259,59 @@
     return PSA_SUCCESS;
 }
 
-static psa_status_t _psa_cipher_set_iv(psa_cipher_operation_t *operation,
+static psa_status_t _psa_cipher_set_iv(uint32_t *handle,
                                        const unsigned char *iv,
                                        size_t iv_length)
 {
     psa_status_t status;
+    struct tfm_crypto_pack_iovec iov = {
+        .sfn_id = TFM_CRYPTO_CIPHER_SET_IV_SFID,
+        .handle = *handle,
+    };
+
     psa_invec in_vec[] = {
+        {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)},
         {.base = iv, .len = iv_length},
     };
     psa_outvec out_vec[] = {
-        {.base = operation, .len = sizeof(psa_cipher_operation_t)},
+        {.base = handle, .len = sizeof(uint32_t)},
     };
 
     status = tfm_crypto_cipher_set_iv(in_vec, sizeof(in_vec)/sizeof(in_vec[0]),
                                    out_vec, sizeof(out_vec)/sizeof(out_vec[0]));
     return status;
 }
+
 psa_status_t tfm_crypto_cipher_encrypt_setup(psa_invec in_vec[],
                                              size_t in_len,
                                              psa_outvec out_vec[],
                                              size_t out_len)
 {
-    if ((in_len != 2) || (out_len != 1)) {
+    psa_status_t status = PSA_SUCCESS;
+    if ((in_len != 1) || (out_len != 1)) {
         return PSA_CONNECTION_REFUSED;
     }
 
-    if ((out_vec[0].len != sizeof(psa_cipher_operation_t)) ||
-        (in_vec[0].len != sizeof(psa_key_slot_t)) ||
-        (in_vec[1].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_key_slot_t key = iov->key;
+    psa_algorithm_t alg = iov->alg;
 
-    psa_cipher_operation_t *operation = out_vec[0].base;
-    psa_key_slot_t key = *((psa_key_slot_t *)in_vec[0].base);
-    psa_algorithm_t alg = *((psa_algorithm_t *)in_vec[1].base);
-
-    return tfm_crypto_cipher_setup(operation,
-                                   key,
-                                   alg,
-                                   ENGINE_CIPHER_MODE_ENCRYPT);
+    status = tfm_crypto_cipher_setup(&handle,
+                                     key,
+                                     alg,
+                                     ENGINE_CIPHER_MODE_ENCRYPT);
+    if (status == PSA_SUCCESS) {
+        *handle_out = handle;
+    } else {
+        *handle_out = iov->handle;
+    }
+    return status;
 }
 
 psa_status_t tfm_crypto_cipher_decrypt_setup(psa_invec in_vec[],
@@ -281,24 +319,29 @@
                                              psa_outvec out_vec[],
                                              size_t out_len)
 {
-    if ((in_len != 2) || (out_len != 1)) {
+    psa_status_t status = PSA_SUCCESS;
+    if ((in_len != 1) || (out_len != 1)) {
         return PSA_CONNECTION_REFUSED;
     }
 
-    if ((out_vec[0].len != sizeof(psa_cipher_operation_t)) ||
-        (in_vec[0].len != sizeof(psa_key_slot_t)) ||
-        (in_vec[1].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_key_slot_t key = iov->key;
+    psa_algorithm_t alg = iov->alg;
 
-    psa_cipher_operation_t *operation = out_vec[0].base;
-    psa_key_slot_t key = *((psa_key_slot_t *)in_vec[0].base);
-    psa_algorithm_t alg = *((psa_algorithm_t *)in_vec[1].base);
-
-    return tfm_crypto_cipher_setup(operation,
-                                   key,
-                                   alg,
-                                   ENGINE_CIPHER_MODE_DECRYPT);
+    status = tfm_crypto_cipher_setup(&handle,
+                                     key,
+                                     alg,
+                                     ENGINE_CIPHER_MODE_DECRYPT);
+    if (status == PSA_SUCCESS) {
+        *handle_out = handle;
+    }
+    return status;
 }
 
 psa_status_t tfm_crypto_cipher_update(psa_invec in_vec[],
@@ -309,26 +352,31 @@
     psa_status_t status = PSA_SUCCESS;
     struct tfm_cipher_operation_s *ctx = NULL;
 
-    if ((in_len != 1) || (out_len != 2)) {
+    if ((in_len != 2) || (out_len != 2)) {
         return PSA_CONNECTION_REFUSED;
     }
 
-    if ((out_vec[0].len != sizeof(psa_cipher_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_cipher_operation_t *operation = out_vec[0].base;
-    const uint8_t *input = in_vec[0].base;
-    size_t input_length = in_vec[0].len;
+    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;
     unsigned char *output = out_vec[1].base;
     size_t output_size = out_vec[1].len;
 
+    /* Init the handle in the operation with the one passed from the iov */
+    *handle_out = iov->handle;
+
     /* Initialise the output_length to zero */
     out_vec[1].len = 0;
 
     /* Look up the corresponding operation context */
     status = tfm_crypto_operation_lookup(TFM_CRYPTO_CIPHER_OPERATION,
-                                         operation,
+                                         handle,
                                          (void **)&ctx);
     if (status != PSA_SUCCESS) {
         return status;
@@ -338,17 +386,21 @@
     if ((ctx->iv_required == 1) && (ctx->iv_set == 0)) {
 
         if (ctx->cipher_mode != ENGINE_CIPHER_MODE_DECRYPT) {
-            (void)tfm_crypto_cipher_release(operation, ctx);
+            if (tfm_crypto_cipher_release(&handle, ctx) == PSA_SUCCESS) {
+                *handle_out = handle;
+            }
             return PSA_ERROR_BAD_STATE;
         }
 
         /* This call is used to set the IV on the object */
-        return _psa_cipher_set_iv(operation, input, input_length);
+        return _psa_cipher_set_iv(handle_out, 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);
+        if (tfm_crypto_cipher_release(&handle, ctx) == PSA_SUCCESS) {
+            *handle_out = handle;
+        }
         return PSA_ERROR_BAD_STATE;
     }
 
@@ -356,7 +408,9 @@
      *        of input data whose length is equal to the block size
      */
     if (input_length > output_size) {
-        (void)tfm_crypto_cipher_release(operation, ctx);
+        if (tfm_crypto_cipher_release(&handle, ctx) == PSA_SUCCESS) {
+            *handle_out = handle;
+        }
         return PSA_ERROR_BUFFER_TOO_SMALL;
     }
 
@@ -367,7 +421,9 @@
                                              output,
                                              (uint32_t *)&(out_vec[1].len));
     if (status != PSA_SUCCESS) {
-        (void)tfm_crypto_cipher_release(operation, ctx);
+        if (tfm_crypto_cipher_release(&handle, ctx) == PSA_SUCCESS) {
+	    *handle_out = handle;
+        }
         return status;
     }
 
@@ -382,24 +438,29 @@
     psa_status_t status = PSA_SUCCESS;
     struct tfm_cipher_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_cipher_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_cipher_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;
     unsigned char *output = out_vec[1].base;
     size_t output_size = out_vec[1].len;
 
+    /* Init the handle in the operation with the one passed from the iov */
+    *handle_out = iov->handle;
+
     /* Initialise the output_length to zero */
     out_vec[1].len = 0;
 
     /* Look up the corresponding operation context */
     status = tfm_crypto_operation_lookup(TFM_CRYPTO_CIPHER_OPERATION,
-                                         operation,
+                                         handle,
                                          (void **)&ctx);
     if (status != PSA_SUCCESS) {
         return status;
@@ -409,7 +470,9 @@
      * output data.
      */
     if (output_size < ctx->block_size) {
-        (void)tfm_crypto_cipher_release(operation, ctx);
+        if (tfm_crypto_cipher_release(&handle, ctx) == PSA_SUCCESS) {
+            *handle_out = handle;
+        }
         return PSA_ERROR_BUFFER_TOO_SMALL;
     }
 
@@ -419,11 +482,17 @@
                                              (uint32_t *)&(out_vec[1].len));
     if (status != PSA_SUCCESS) {
         out_vec[1].len = 0;
-        (void)tfm_crypto_cipher_release(operation, ctx);
+        if (tfm_crypto_cipher_release(&handle, ctx) == PSA_SUCCESS) {
+            *handle_out = handle;
+        }
         return status;
     }
 
-    return tfm_crypto_cipher_release(operation, ctx);
+    status = tfm_crypto_cipher_release(&handle, ctx);
+    if (status == PSA_SUCCESS) {
+        *handle_out = handle;
+    }
+    return status;
 }
 
 psa_status_t tfm_crypto_cipher_abort(psa_invec in_vec[],
@@ -434,24 +503,33 @@
     psa_status_t status = PSA_SUCCESS;
     struct tfm_cipher_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_cipher_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_cipher_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_CIPHER_OPERATION,
-                                         operation,
+                                         handle,
                                          (void **)&ctx);
     if (status != PSA_SUCCESS) {
         return status;
     }
 
-    return tfm_crypto_cipher_release(operation, ctx);
+    status = tfm_crypto_cipher_release(&handle, ctx);
+    if (status == PSA_SUCCESS) {
+        *handle_out = handle;
+    }
+    return status;
 }
 /*!@}*/
diff --git a/secure_fw/services/crypto/crypto_engine.h b/secure_fw/services/crypto/crypto_engine.h
index 6263aae..3130396 100644
--- a/secure_fw/services/crypto/crypto_engine.h
+++ b/secure_fw/services/crypto/crypto_engine.h
@@ -25,6 +25,7 @@
 #if !defined(MBEDTLS_CONFIG_FILE)
 #include "platform/ext/common/tfm_mbedtls_config.h"
 #else
+// cppcheck-suppress preprocessorErrorDirective
 #include MBEDTLS_CONFIG_FILE
 #endif
 
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;
 }
 /*!@}*/
diff --git a/secure_fw/services/crypto/crypto_init.c b/secure_fw/services/crypto/crypto_init.c
index 1ec7dee..aaabea8 100644
--- a/secure_fw/services/crypto/crypto_init.c
+++ b/secure_fw/services/crypto/crypto_init.c
@@ -8,6 +8,254 @@
 #include "tfm_crypto_api.h"
 #include "crypto_engine.h"
 
+#ifdef TFM_PSA_API
+#include "psa_service.h"
+#include "tfm_crypto_signal.h"
+#include "secure_fw/core/tfm_memory_utils.h"
+
+/**
+ * \brief Table containing all the Uniform Signature API exposed
+ *        by the TF-M Crypto partition
+ */
+static const tfm_crypto_us_t sfid_func_table[TFM_CRYPTO_SFID_MAX] = {
+    tfm_crypto_import_key,
+    tfm_crypto_destroy_key,
+    tfm_crypto_get_key_information,
+    tfm_crypto_export_key,
+    tfm_crypto_key_policy_init,
+    tfm_crypto_key_policy_set_usage,
+    tfm_crypto_key_policy_get_usage,
+    tfm_crypto_key_policy_get_algorithm,
+    tfm_crypto_set_key_policy,
+    tfm_crypto_get_key_policy,
+    tfm_crypto_set_key_lifetime,
+    tfm_crypto_get_key_lifetime,
+    tfm_crypto_cipher_set_iv,
+    tfm_crypto_cipher_encrypt_setup,
+    tfm_crypto_cipher_decrypt_setup,
+    tfm_crypto_cipher_update,
+    tfm_crypto_cipher_abort,
+    tfm_crypto_cipher_finish,
+    tfm_crypto_hash_setup,
+    tfm_crypto_hash_update,
+    tfm_crypto_hash_finish,
+    tfm_crypto_hash_verify,
+    tfm_crypto_hash_abort,
+    tfm_crypto_mac_sign_setup,
+    tfm_crypto_mac_verify_setup,
+    tfm_crypto_mac_update,
+    tfm_crypto_mac_sign_finish,
+    tfm_crypto_mac_verify_finish,
+    tfm_crypto_mac_abort,
+    tfm_crypto_aead_encrypt,
+    tfm_crypto_aead_decrypt
+};
+
+/**
+ * \brief Aligns a value x up to an alignment a.
+ */
+#define ALIGN(x, a) (((x) + ((a) - 1)) & ~((a) - 1))
+
+/**
+ * \brief Maximum alignment required by any iovec parameters to the TF-M Crypto
+ *        partition.
+ */
+#define TFM_CRYPTO_IOVEC_ALIGNMENT (4u)
+
+/**
+ * \brief Default size of the internal scratch buffer used for IOVec allocations
+ *        in bytes
+ */
+#ifndef TFM_CRYPTO_IOVEC_BUFFER_SIZE
+#define TFM_CRYPTO_IOVEC_BUFFER_SIZE (1024)
+#endif
+
+/**
+ * \brief Internal scratch used for IOVec allocations
+ *
+ */
+static struct tfm_crypto_scratch {
+    __attribute__((__aligned__(TFM_CRYPTO_IOVEC_ALIGNMENT)))
+    uint8_t buf[TFM_CRYPTO_IOVEC_BUFFER_SIZE];
+    uint32_t alloc_index;
+} scratch = {.buf = {0}, .alloc_index = 0};
+
+static psa_status_t tfm_crypto_alloc_scratch(size_t requested_size, void **buf)
+{
+    /* Ensure alloc_index remains aligned to the required iovec alignment */
+    requested_size = ALIGN(requested_size, TFM_CRYPTO_IOVEC_ALIGNMENT);
+
+    if (requested_size > (sizeof(scratch.buf) - scratch.alloc_index)) {
+        return PSA_ERROR_INSUFFICIENT_MEMORY;
+    }
+
+    /* Compute the pointer to the allocated space */
+    *buf = (void *)&scratch.buf[scratch.alloc_index];
+
+    /* Increase the allocated size */
+    scratch.alloc_index += requested_size;
+
+    return PSA_SUCCESS;
+}
+
+static psa_status_t tfm_crypto_clear_scratch(void)
+{
+    scratch.alloc_index = 0;
+    (void)tfm_memset(scratch.buf, 0, sizeof(scratch.buf));
+
+    return PSA_SUCCESS;
+}
+
+static psa_status_t tfm_crypto_call_sfn(psa_msg_t *msg,
+                                        struct tfm_crypto_pack_iovec *iov,
+                                        const uint32_t sfn_id)
+{
+    psa_status_t status = PSA_SUCCESS;
+    size_t in_len = 0, out_len = 0, i, read_size;
+    psa_invec in_vec[PSA_MAX_IOVEC] = { {0} };
+    psa_outvec out_vec[PSA_MAX_IOVEC] = { {0} };
+    void *alloc_buf_ptr = NULL;
+
+    /* Check the number of in_vec filled */
+    while ((in_len < PSA_MAX_IOVEC) && (msg->in_size[in_len] != 0)) {
+        in_len++;
+    }
+
+    /* There will always be a tfm_crypto_pack_iovec in the first iovec */
+    if (in_len < 1) {
+        return PSA_ERROR_UNKNOWN_ERROR;
+    }
+    /* Initialise the first iovec with the IOV read when parsing */
+    in_vec[0].base = iov;
+    in_vec[0].len = sizeof(struct tfm_crypto_pack_iovec);
+
+    /* Alloc/read from the second element as the first is read when parsing */
+    for (i = 1; i < in_len; i++) {
+        /* Allocate necessary space in the internal scratch */
+        status = tfm_crypto_alloc_scratch(msg->in_size[i], &alloc_buf_ptr);
+        if (status != PSA_SUCCESS) {
+            return status;
+        }
+        /* Read from the IPC framework inputs into the scratch */
+        read_size = psa_read(msg->handle, i, alloc_buf_ptr, msg->in_size[i]);
+        /* Populate the fields of the input to the secure function */
+        in_vec[i].base = alloc_buf_ptr;
+        in_vec[i].len = msg->in_size[i];
+    }
+
+    /* Check the number of out_vec filled */
+    while ((out_len < PSA_MAX_IOVEC) && (msg->out_size[out_len] != 0)) {
+        out_len++;
+    }
+
+    for (i = 0; i < out_len; i++) {
+        /* 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) {
+            return status;
+        }
+        /* Populate the fields of the output to the secure function */
+        out_vec[i].base = alloc_buf_ptr;
+        out_vec[i].len = msg->out_size[i];
+    }
+
+    /* Call the uniform signature API */
+    status = sfid_func_table[sfn_id](in_vec, in_len, out_vec, out_len);
+
+    /* Write into the IPC framework outputs from the scratch */
+    for (i = 0; i < out_len; i++) {
+        psa_write(msg->handle, i, out_vec[i].base, out_vec[i].len);
+    }
+
+    /* Clear the allocated internal scratch before returning */
+    if (tfm_crypto_clear_scratch() != PSA_SUCCESS) {
+        return PSA_ERROR_UNKNOWN_ERROR;
+    }
+
+    return status;
+}
+
+static psa_status_t tfm_crypto_parse_msg(psa_msg_t *msg,
+                                         struct tfm_crypto_pack_iovec *iov,
+                                         uint32_t *sfn_id_p)
+{
+    size_t read_size;
+
+    /* Read the in_vec[0] which holds the IOVEC always */
+    read_size = psa_read(msg->handle,
+                         0,
+                         iov,
+                         sizeof(struct tfm_crypto_pack_iovec));
+
+    if (read_size != sizeof(struct tfm_crypto_pack_iovec)) {
+        return PSA_ERROR_UNKNOWN_ERROR;
+    }
+
+    if (iov->sfn_id >= TFM_CRYPTO_SFID_MAX) {
+        *sfn_id_p = TFM_CRYPTO_SFID_INVALID;
+        return PSA_ERROR_UNKNOWN_ERROR;
+    }
+
+    *sfn_id_p = iov->sfn_id;
+
+    return PSA_SUCCESS;
+}
+
+static void tfm_crypto_ipc_handler(void)
+{
+    psa_signal_t signals = 0;
+    psa_msg_t msg;
+    psa_status_t status = PSA_SUCCESS;
+    uint32_t sfn_id = TFM_CRYPTO_SFID_INVALID;
+    struct tfm_crypto_pack_iovec iov = {0};
+
+    while (1) {
+        signals = psa_wait(PSA_WAIT_ANY, PSA_BLOCK);
+        if (signals & TFM_CRYPTO_SIG) {
+            /* Extract the message */
+            if (psa_get(TFM_CRYPTO_SIG, &msg) != PSA_SUCCESS) {
+                /* FIXME: Should be replaced by TF-M error handling */
+                while (1) {
+                    ;
+                }
+            }
+
+            /* Process the message type */
+            switch (msg.type) {
+            case PSA_IPC_CONNECT:
+            case PSA_IPC_DISCONNECT:
+                psa_reply(msg.handle, PSA_SUCCESS);
+                break;
+            case PSA_IPC_CALL:
+                /* Parse the message */
+                status = tfm_crypto_parse_msg(&msg, &iov, &sfn_id);
+                /* Call the dispatcher based on the SFID passed as type */
+                if (sfn_id != TFM_CRYPTO_SFID_INVALID) {
+                    status = tfm_crypto_call_sfn(&msg, &iov, sfn_id);
+                } else {
+                    status = PSA_ERROR_UNKNOWN_ERROR;
+                }
+                psa_reply(msg.handle, status);
+                break;
+            default:
+                /* FIXME: Should be replaced by TF-M error handling */
+                while (1) {
+                    ;
+                }
+            }
+        } else {
+            /* FIXME: Should be replaced by TF-M error handling */
+            while (1) {
+               ;
+            }
+        }
+    }
+
+    /* This is unreachable */
+    return;
+}
+#endif /* TFM_PSA_API */
+
 static psa_status_t tfm_crypto_module_init(void)
 {
     psa_status_t status = PSA_SUCCESS;
@@ -35,13 +283,13 @@
     /* Initialise the engine interface module */
     status = tfm_crypto_engine_init();
     if (status != PSA_SUCCESS) {
-        /* FIXME: For the time being, keep returning success even if the engine
-         * is not initialised correctly. This can be used to test corner cases
-         * without triggering any TF-M recovery mechanism during boot-up if it
-         * recognises that a service has not completed booting correctly.
-         */
-        return PSA_SUCCESS;
+        return status;
     }
 
-    return PSA_SUCCESS;
+#ifdef TFM_PSA_API
+    /* Should not return in normal operations */
+    tfm_crypto_ipc_handler();
+#endif
+
+    return status;
 }
diff --git a/secure_fw/services/crypto/crypto_key.c b/secure_fw/services/crypto/crypto_key.c
index 2bef9ca..dc55de6 100644
--- a/secure_fw/services/crypto/crypto_key.c
+++ b/secure_fw/services/crypto/crypto_key.c
@@ -13,6 +13,12 @@
 #include "tfm_crypto_defs.h"
 #include "secure_fw/core/tfm_memory_utils.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 This is the default value of maximum number of simultaneous
  *        key stores supported.
@@ -153,19 +159,19 @@
     struct tfm_crypto_key_storage_s *key_store = NULL;
     size_t i;
 
-    if ((in_len != 3) || (out_len != 0)) {
+    if ((in_len != 2) || (out_len != 0)) {
         return PSA_CONNECTION_REFUSED;
     }
 
-    if ((in_vec[0].len != sizeof(psa_key_slot_t)) ||
-        (in_vec[1].len != sizeof(psa_key_type_t))) {
+    if (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;
 
-    psa_key_slot_t key = *((psa_key_slot_t *)in_vec[0].base);
-    psa_key_type_t type = *((psa_key_type_t *)in_vec[1].base);
-    const uint8_t *data = in_vec[2].base;
-    size_t data_length = in_vec[2].len;
+    psa_key_slot_t key = iov->key;
+    psa_key_type_t type = iov->type;
+    const uint8_t *data = in_vec[1].base;
+    size_t data_length = in_vec[1].len;
 
     key_store = get_key_store(key);
     if (key_store == NULL) {
@@ -204,11 +210,12 @@
         return PSA_CONNECTION_REFUSED;
     }
 
-    if (in_vec[0].len != sizeof(psa_key_slot_t)) {
+    if (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;
 
-    psa_key_slot_t key = *((psa_key_slot_t *)in_vec[0].base);
+    psa_key_slot_t key = iov->key;
 
     key_store = get_key_store(key);
     if (key_store == NULL) {
@@ -240,13 +247,14 @@
         return PSA_CONNECTION_REFUSED;
     }
 
-    if ((in_vec[0].len != sizeof(psa_key_slot_t)) ||
+    if ((in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec)) ||
         (out_vec[0].len != sizeof(psa_key_type_t)) ||
         (out_vec[1].len != sizeof(size_t))) {
         return PSA_CONNECTION_REFUSED;
     }
+    const struct tfm_crypto_pack_iovec *iov = in_vec[0].base;
 
-    psa_key_slot_t key = *((psa_key_slot_t *)in_vec[0].base);
+    psa_key_slot_t key = iov->key;
     psa_key_type_t *type = out_vec[0].base;
     size_t *bits = out_vec[1].base;
 
@@ -279,11 +287,12 @@
         return PSA_CONNECTION_REFUSED;
     }
 
-    if (in_vec[0].len != sizeof(psa_key_slot_t)) {
+    if (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;
 
-    psa_key_slot_t key = *((psa_key_slot_t *)in_vec[0].base);
+    psa_key_slot_t key = iov->key;
     uint8_t *data = out_vec[0].base;
     size_t data_size = out_vec[0].len;
 
@@ -310,11 +319,12 @@
                                         psa_outvec out_vec[],
                                         size_t out_len)
 {
-    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_key_policy_t)) {
+    if ((out_vec[0].len != sizeof(psa_key_policy_t)) ||
+        (in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec))) {
         return PSA_CONNECTION_REFUSED;
     }
 
@@ -331,19 +341,19 @@
                                              psa_outvec out_vec[],
                                              size_t out_len)
 {
-    if ((in_len != 2) || (out_len != 1)) {
+    if ((in_len != 1) || (out_len != 1)) {
         return PSA_CONNECTION_REFUSED;
     }
 
     if ((out_vec[0].len != sizeof(psa_key_policy_t)) ||
-        (in_vec[0].len != sizeof(psa_key_usage_t))  ||
-        (in_vec[1].len != sizeof(psa_algorithm_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;
 
     psa_key_policy_t *policy = out_vec[0].base;
-    psa_key_usage_t usage = *((psa_key_usage_t *)in_vec[0].base);
-    psa_algorithm_t alg = *((psa_algorithm_t *)in_vec[1].base);
+    psa_key_usage_t usage = iov->usage;
+    psa_algorithm_t alg = iov->alg;
 
     policy->usage = usage;
     policy->alg = alg;
@@ -356,16 +366,17 @@
                                              psa_outvec out_vec[],
                                              size_t out_len)
 {
-    if ((in_len != 1) || (out_len != 1)) {
+    if ((in_len != 2) || (out_len != 1)) {
         return PSA_CONNECTION_REFUSED;
     }
 
-    if ((in_vec[0].len != sizeof(psa_key_policy_t)) ||
+    if ((in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec)) ||
+        (in_vec[1].len != sizeof(psa_key_policy_t)) ||
         (out_vec[0].len != sizeof(psa_key_usage_t))) {
         return PSA_CONNECTION_REFUSED;
     }
 
-    const psa_key_policy_t *policy = in_vec[0].base;
+    const psa_key_policy_t *policy = in_vec[1].base;
     psa_key_usage_t *usage = out_vec[0].base;
 
     *usage = policy->usage;
@@ -378,16 +389,17 @@
                                                  psa_outvec out_vec[],
                                                  size_t out_len)
 {
-    if ((in_len != 1) || (out_len != 1)) {
+    if ((in_len != 2) || (out_len != 1)) {
         return PSA_CONNECTION_REFUSED;
     }
 
-    if ((in_vec[0].len != sizeof(psa_key_policy_t)) ||
+    if ((in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec)) ||
+        (in_vec[1].len != sizeof(psa_key_policy_t)) ||
         (out_vec[0].len != sizeof(psa_algorithm_t))) {
         return PSA_CONNECTION_REFUSED;
     }
 
-    const psa_key_policy_t *policy = in_vec[0].base;
+    const psa_key_policy_t *policy = in_vec[1].base;
     psa_algorithm_t *alg = out_vec[0].base;
 
     *alg = policy->alg;
@@ -406,12 +418,13 @@
         return PSA_CONNECTION_REFUSED;
     }
 
-    if ((in_vec[0].len != sizeof(psa_key_slot_t)) ||
+    if ((in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec)) ||
         (in_vec[1].len != sizeof(psa_key_policy_t))) {
         return PSA_CONNECTION_REFUSED;
     }
+    const struct tfm_crypto_pack_iovec *iov = in_vec[0].base;
 
-    psa_key_slot_t key = *((psa_key_slot_t *)in_vec[0].base);
+    psa_key_slot_t key = iov->key;
     const psa_key_policy_t *policy = in_vec[1].base;
 
     /* Check that the policy is valid */
@@ -452,12 +465,13 @@
         return PSA_CONNECTION_REFUSED;
     }
 
-    if ((in_vec[0].len != sizeof(psa_key_slot_t)) ||
+    if ((in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec)) ||
         (out_vec[0].len != sizeof(psa_key_policy_t))) {
         return PSA_CONNECTION_REFUSED;
     }
+    const struct tfm_crypto_pack_iovec *iov = in_vec[0].base;
 
-    psa_key_slot_t key = *((psa_key_slot_t *)in_vec[0].base);
+    psa_key_slot_t key = iov->key;
     psa_key_policy_t *policy = out_vec[0].base;
 
     key_store = get_key_store(key);
@@ -477,17 +491,17 @@
 {
     struct tfm_crypto_key_storage_s *key_store = NULL;
 
-    if ((in_len != 2) || (out_len != 0)) {
+    if ((in_len != 1) || (out_len != 0)) {
         return PSA_CONNECTION_REFUSED;
     }
 
-    if ((in_vec[0].len != sizeof(psa_key_slot_t)) ||
-        (in_vec[1].len != sizeof(psa_key_lifetime_t))) {
+    if (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;
 
-    psa_key_slot_t key = *((psa_key_slot_t *)in_vec[0].base);
-    psa_key_lifetime_t lifetime = *((psa_key_lifetime_t *)in_vec[1].base);
+    psa_key_slot_t key = iov->key;
+    psa_key_lifetime_t lifetime = iov->lifetime;
 
     /* Check that the lifetime is valid */
     if (lifetime != PSA_KEY_LIFETIME_VOLATILE
@@ -529,12 +543,13 @@
         return PSA_CONNECTION_REFUSED;
     }
 
-    if ((in_vec[0].len != sizeof(psa_key_slot_t)) ||
+    if ((in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec)) ||
         (out_vec[0].len != sizeof(psa_key_lifetime_t))) {
         return PSA_CONNECTION_REFUSED;
     }
+    const struct tfm_crypto_pack_iovec *iov = in_vec[0].base;
 
-    psa_key_slot_t key = *((psa_key_slot_t *)in_vec[0].base);
+    psa_key_slot_t key = iov->key;
     psa_key_lifetime_t *lifetime = out_vec[0].base;
 
     key_store = get_key_store(key);
diff --git a/secure_fw/services/crypto/crypto_mac.c b/secure_fw/services/crypto/crypto_mac.c
index 7000b18..ae6a00b 100644
--- a/secure_fw/services/crypto/crypto_mac.c
+++ b/secure_fw/services/crypto/crypto_mac.c
@@ -10,78 +10,128 @@
 #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.
+ */
+
 static psa_status_t _psa_get_key_information(psa_key_slot_t key,
                                              psa_key_type_t *type,
                                              size_t *bits)
 {
+    psa_status_t status;
+    struct tfm_crypto_pack_iovec iov = {
+        .sfn_id = TFM_CRYPTO_GET_KEY_INFORMATION_SFID,
+        .key = key,
+    };
     psa_invec in_vec[] = {
-        {.base = &key, .len = sizeof(psa_key_slot_t)},
+        {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)},
     };
     psa_outvec out_vec[] = {
         {.base = type, .len = sizeof(psa_key_type_t)},
         {.base = bits, .len = sizeof(size_t)}
     };
 
-    return tfm_crypto_get_key_information(
+    status = tfm_crypto_get_key_information(
                  in_vec, sizeof(in_vec)/sizeof(in_vec[0]),
                  out_vec, sizeof(out_vec)/sizeof(out_vec[0]));
+
+    return status;
 }
 
-static psa_status_t _psa_hash_setup(psa_hash_operation_t *operation,
+static psa_status_t _psa_hash_setup(uint32_t *handle,
                                     psa_algorithm_t alg)
 {
+    psa_status_t status;
+    struct tfm_crypto_pack_iovec iov = {
+        .sfn_id = TFM_CRYPTO_HASH_SETUP_SFID,
+        .alg = alg,
+        .handle = *handle,
+    };
+
     psa_invec in_vec[] = {
-        {.base = &alg, .len = sizeof(psa_algorithm_t)},
+        {.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)},
     };
 
-    return tfm_crypto_hash_setup(in_vec, sizeof(in_vec)/sizeof(in_vec[0]),
+    status = tfm_crypto_hash_setup(in_vec, sizeof(in_vec)/sizeof(in_vec[0]),
                  out_vec, sizeof(out_vec)/sizeof(out_vec[0]));
+
+    return status;
 }
 
-static psa_status_t _psa_hash_update(psa_hash_operation_t *operation,
+static psa_status_t _psa_hash_update(uint32_t *handle,
                                      const uint8_t *input,
                                      size_t input_length)
 {
+    psa_status_t status;
+    struct tfm_crypto_pack_iovec iov = {
+        .sfn_id = TFM_CRYPTO_HASH_UPDATE_SFID,
+        .handle = *handle,
+    };
+
     psa_invec in_vec[] = {
+        {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)},
         {.base = input, .len = input_length},
     };
     psa_outvec out_vec[] = {
-        {.base = operation, .len = sizeof(psa_hash_operation_t)},
+        {.base = handle, .len = sizeof(uint32_t)},
     };
 
-    return tfm_crypto_hash_update(in_vec, sizeof(in_vec)/sizeof(in_vec[0]),
+    status = tfm_crypto_hash_update(in_vec, sizeof(in_vec)/sizeof(in_vec[0]),
                  out_vec, sizeof(out_vec)/sizeof(out_vec[0]));
+
+    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;
 
     return status;
 }
 
-static psa_status_t _psa_hash_abort(psa_hash_operation_t *operation)
+static psa_status_t _psa_hash_abort(uint32_t *handle)
 {
-    psa_outvec out_vec[] = {
-        {.base = operation, .len = sizeof(psa_hash_operation_t)},
+    psa_status_t status;
+    struct tfm_crypto_pack_iovec iov = {
+        .sfn_id = TFM_CRYPTO_HASH_ABORT_SFID,
+        .handle = *handle,
     };
 
-    return tfm_crypto_hash_abort(NULL, 0,
+    psa_invec in_vec[] = {
+        {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)},
+    };
+    psa_outvec out_vec[] = {
+        {.base = handle, .len = sizeof(uint32_t)},
+    };
+
+    status = tfm_crypto_hash_abort(in_vec, sizeof(in_vec)/sizeof(in_vec[0]),
                  out_vec, sizeof(out_vec)/sizeof(out_vec[0]));
+
+    return status;
 }
 
 /**
@@ -132,14 +182,14 @@
     }
 }
 
-static psa_status_t tfm_crypto_mac_release(psa_mac_operation_t *operation,
+static psa_status_t tfm_crypto_mac_release(uint32_t *handle,
                                            struct tfm_mac_operation_s *ctx)
 {
     /* No release necessary on the ctx related items for the time being */
     UNUSED_VAR(ctx);
 
     /* Release the operation context */
-    return tfm_crypto_operation_release(TFM_CRYPTO_MAC_OPERATION, operation);
+    return tfm_crypto_operation_release(handle);
 }
 
 static psa_status_t tfm_crypto_hmac_setup(struct tfm_mac_operation_s *ctx,
@@ -197,13 +247,13 @@
      */
     if (key_size > block_size) {
         /* Hash the key to reduce it to block size */
-        status = _psa_hash_setup(&(ctx->ctx.hmac.hash_operation),
+        status = _psa_hash_setup(&(ctx->ctx.hmac.hash_operation.handle),
                                  PSA_ALG_HMAC_HASH(alg));
         if (status != PSA_SUCCESS) {
             return status;
         }
 
-        status = _psa_hash_update(&(ctx->ctx.hmac.hash_operation),
+        status = _psa_hash_update(&(ctx->ctx.hmac.hash_operation.handle),
                                   &key_data[0],
                                   key_size);
         if (status != PSA_SUCCESS) {
@@ -211,7 +261,7 @@
         }
 
         /* Replace the key with the hashed key */
-        status = _psa_hash_finish(&(ctx->ctx.hmac.hash_operation),
+        status = _psa_hash_finish(&(ctx->ctx.hmac.hash_operation.handle),
                                   hashed_key,
                                   sizeof(hashed_key),
                                   &key_size);
@@ -237,7 +287,7 @@
     }
 
     /* Start hash1 = H(i_key_pad || message) */
-    status = _psa_hash_setup(&(ctx->ctx.hmac.hash_operation),
+    status = _psa_hash_setup(&(ctx->ctx.hmac.hash_operation.handle),
                              PSA_ALG_HMAC_HASH(alg));
     if (status != PSA_SUCCESS) {
         /* Clear key information on stack */
@@ -248,17 +298,13 @@
         return status;
     }
 
-    status = _psa_hash_update(&(ctx->ctx.hmac.hash_operation),
+    status = _psa_hash_update(&(ctx->ctx.hmac.hash_operation.handle),
                               ipad,
                               block_size);
-    if (status != PSA_SUCCESS) {
-        return status;
-    }
-
-    return PSA_SUCCESS;
+    return status;
 }
 
-static psa_status_t tfm_crypto_mac_setup(psa_mac_operation_t *operation,
+static psa_status_t tfm_crypto_mac_setup(uint32_t *handle,
                                          psa_key_slot_t key,
                                          psa_algorithm_t alg,
                                          uint8_t sign_operation)
@@ -272,7 +318,7 @@
 
     /* Allocate the operation context in the secure world */
     status = tfm_crypto_operation_alloc(TFM_CRYPTO_MAC_OPERATION,
-                                        operation,
+                                        handle,
                                         (void **)&ctx);
     if (status != PSA_SUCCESS) {
         return status;
@@ -294,7 +340,7 @@
         status = tfm_crypto_hmac_setup(ctx, key, alg);
         if (status != PSA_SUCCESS) {
             /* Release the operation context */
-            (void)tfm_crypto_mac_release(operation, ctx);
+            (void)tfm_crypto_mac_release(handle, ctx);
             return status;
         }
 
@@ -302,14 +348,14 @@
     } else {
         /* Other MAC types constructions are not supported */
         /* Release the operation context */
-        (void)tfm_crypto_mac_release(operation, ctx);
+      (void)tfm_crypto_mac_release(handle, ctx);
         return PSA_ERROR_NOT_SUPPORTED;
     }
 
     return PSA_SUCCESS;
 }
 
-static psa_status_t tfm_crypto_mac_finish(psa_mac_operation_t *operation,
+static psa_status_t tfm_crypto_mac_finish(uint32_t *handle,
                                           struct tfm_mac_operation_s *ctx,
                                           uint8_t *mac,
                                           size_t mac_size,
@@ -323,12 +369,12 @@
 
     /* Sanity checks */
     if (mac_size < ctx->mac_size) {
-        (void)tfm_crypto_mac_release(operation, ctx);
+      (void)tfm_crypto_mac_release(handle, ctx);
         return PSA_ERROR_BUFFER_TOO_SMALL;
     }
 
     if (!(ctx->has_input)) {
-        (void)tfm_crypto_mac_release(operation, ctx);
+        (void)tfm_crypto_mac_release(handle, ctx);
         return PSA_ERROR_BAD_STATE;
     }
 
@@ -337,49 +383,49 @@
         block_size = get_hash_block_size(PSA_ALG_HMAC_HASH(ctx->alg));
 
         /* finish the hash1 = H(ipad || message) */
-        status = _psa_hash_finish(&(ctx->ctx.hmac.hash_operation),
+        status = _psa_hash_finish(&(ctx->ctx.hmac.hash_operation.handle),
                                   hash1,
                                   sizeof(hash1),
                                   &hash_size);
         if (status != PSA_SUCCESS) {
-            (void)tfm_crypto_mac_release(operation, ctx);
+            (void)tfm_crypto_mac_release(handle, ctx);
             return status;
         }
 
         /* compute the final mac value = H(opad || hash1) */
-        status = _psa_hash_setup(&(ctx->ctx.hmac.hash_operation),
+        status = _psa_hash_setup(&(ctx->ctx.hmac.hash_operation.handle),
                                  PSA_ALG_HMAC_HASH(ctx->alg));
         if (status != PSA_SUCCESS) {
             mac_zeroize(hash1, sizeof(hash1));
-            (void)tfm_crypto_mac_release(operation, ctx);
+            (void)tfm_crypto_mac_release(handle, ctx);
             return status;
         }
 
-        status = _psa_hash_update(&(ctx->ctx.hmac.hash_operation),
+        status = _psa_hash_update(&(ctx->ctx.hmac.hash_operation.handle),
                                   opad,
                                   block_size);
         if (status != PSA_SUCCESS) {
             mac_zeroize(hash1, sizeof(hash1));
-            (void)tfm_crypto_mac_release(operation, ctx);
+            (void)tfm_crypto_mac_release(handle, ctx);
             return status;
         }
 
-        status = _psa_hash_update(&(ctx->ctx.hmac.hash_operation),
+        status = _psa_hash_update(&(ctx->ctx.hmac.hash_operation.handle),
                                   hash1,
                                   hash_size);
         if (status != PSA_SUCCESS) {
             mac_zeroize(hash1, sizeof(hash1));
-            (void)tfm_crypto_mac_release(operation, ctx);
+            (void)tfm_crypto_mac_release(handle, ctx);
             return status;
         }
 
-        status = _psa_hash_finish(&(ctx->ctx.hmac.hash_operation),
+        status = _psa_hash_finish(&(ctx->ctx.hmac.hash_operation.handle),
                                   mac,
                                   mac_size,
                                   mac_length);
         if (status != PSA_SUCCESS) {
             mac_zeroize(hash1, sizeof(hash1));
-            (void)tfm_crypto_mac_release(operation, ctx);
+            (void)tfm_crypto_mac_release(handle, ctx);
             return status;
         }
 
@@ -390,7 +436,7 @@
         return PSA_ERROR_INVALID_ARGUMENT;
     }
 
-    return tfm_crypto_mac_release(operation, ctx);
+    return tfm_crypto_mac_release(handle, ctx);
 }
 
 /*!
@@ -404,21 +450,28 @@
                                        psa_outvec out_vec[],
                                        size_t out_len)
 {
-    if ((in_len != 2) || (out_len != 1)) {
+    psa_status_t status = PSA_SUCCESS;
+    if ((in_len != 1) || (out_len != 1)) {
         return PSA_CONNECTION_REFUSED;
     }
 
-    if ((out_vec[0].len != sizeof(psa_mac_operation_t)) ||
-        (in_vec[0].len != sizeof(psa_key_slot_t)) ||
-        (in_vec[1].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_key_slot_t key = iov->key;
+    psa_algorithm_t alg = iov->alg;
 
-    psa_mac_operation_t *operation = out_vec[0].base;
-    psa_key_slot_t key = *((psa_key_slot_t *)in_vec[0].base);
-    psa_algorithm_t alg = *((psa_algorithm_t *)in_vec[1].base);
-
-    return tfm_crypto_mac_setup(operation, key, alg, 1);
+    status = tfm_crypto_mac_setup(&handle, key, alg, 1);
+    if (status == PSA_SUCCESS) {
+        *handle_out = handle;
+    } else {
+        *handle_out = iov->handle;
+    }
+    return status;
 }
 
 psa_status_t tfm_crypto_mac_verify_setup(psa_invec in_vec[],
@@ -426,21 +479,28 @@
                                          psa_outvec out_vec[],
                                          size_t out_len)
 {
-    if ((in_len != 2) || (out_len != 1)) {
+    psa_status_t status = PSA_SUCCESS;
+    if ((in_len != 1) || (out_len != 1)) {
         return PSA_CONNECTION_REFUSED;
     }
 
-    if ((out_vec[0].len != sizeof(psa_mac_operation_t)) ||
-        (in_vec[0].len != sizeof(psa_key_slot_t)) ||
-        (in_vec[1].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_key_slot_t key = iov->key;
+    psa_algorithm_t alg = iov->alg;
 
-    psa_mac_operation_t *operation = out_vec[0].base;
-    psa_key_slot_t key = *((psa_key_slot_t *)in_vec[0].base);
-    psa_algorithm_t alg = *((psa_algorithm_t *)in_vec[1].base);
-
-    return tfm_crypto_mac_setup(operation, key, alg, 0);
+    status = tfm_crypto_mac_setup(&handle, key, alg, 0);
+    if (status == PSA_SUCCESS) {
+        *handle_out = handle;
+    } else {
+        *handle_out = iov->handle;
+    }
+    return status;
 }
 
 psa_status_t tfm_crypto_mac_update(psa_invec in_vec[],
@@ -451,21 +511,26 @@
     psa_status_t status = PSA_SUCCESS;
     struct tfm_mac_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_mac_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_mac_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_MAC_OPERATION,
-                                         operation,
+                                         handle,
                                          (void **)&ctx);
     if (status != PSA_SUCCESS) {
         return status;
@@ -473,28 +538,36 @@
 
     /* Sanity check */
     if (!(ctx->key_set)) {
-        (void)tfm_crypto_mac_release(operation, ctx);
+        if (tfm_crypto_mac_release(&handle, ctx) == PSA_SUCCESS) {
+            *handle_out = handle;
+        }
         return PSA_ERROR_BAD_STATE;
     }
     if (input_length == 0) {
-        (void)tfm_crypto_mac_release(operation, ctx);
+        if (tfm_crypto_mac_release(&handle, ctx) == PSA_SUCCESS) {
+            *handle_out = handle;
+        }
         return PSA_ERROR_INVALID_ARGUMENT;
     }
 
     /* Process the input chunk */
     if (PSA_ALG_IS_HMAC(ctx->alg)) {
-        status = _psa_hash_update(&(ctx->ctx.hmac.hash_operation),
+        status = _psa_hash_update(&(ctx->ctx.hmac.hash_operation.handle),
                                   input,
                                   input_length);
         if (status != PSA_SUCCESS) {
-            (void)tfm_crypto_mac_release(operation, ctx);
+            if (tfm_crypto_mac_release(&handle, ctx) == PSA_SUCCESS) {
+                *handle_out = handle;
+            }
             return status;
         }
 
         /* Set this flag to avoid HMAC without data */
         ctx->has_input = 1;
     } else {
-        (void)tfm_crypto_mac_release(operation, ctx);
+        if (tfm_crypto_mac_release(&handle, ctx) == PSA_SUCCESS) {
+            *handle_out = handle;
+        }
         return PSA_ERROR_INVALID_ARGUMENT;
     }
 
@@ -509,18 +582,23 @@
     psa_status_t status = PSA_SUCCESS;
     struct tfm_mac_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_mac_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_mac_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 *mac = out_vec[1].base;
     size_t mac_size = out_vec[1].len;
 
+    /* Init the handle in the operation with the one passed from the iov */
+    *handle_out = iov->handle;
+
     /* Initialise mac_length to zero */
     out_vec[1].len = 0;
 
@@ -530,7 +608,7 @@
 
     /* Look up the corresponding operation context */
     status = tfm_crypto_operation_lookup(TFM_CRYPTO_MAC_OPERATION,
-                                         operation,
+                                         handle,
                                          (void **)&ctx);
     if (status != PSA_SUCCESS) {
         return status;
@@ -538,19 +616,17 @@
 
     if ((ctx->key_usage_sign == 1) && (ctx->key_usage_verify == 0)) {
         /* Finalise the mac operation */
-        status = tfm_crypto_mac_finish(operation,
+        status = tfm_crypto_mac_finish(&handle,
                        ctx, mac, mac_size, &(out_vec[1].len));
-        if (status != PSA_SUCCESS) {
-            return status;
-        }
-        /* A call to tfm_crypto_mac_finish() always releases the operation */
-
     } else {
-        (void)tfm_crypto_mac_release(operation, ctx);
+        if (tfm_crypto_mac_release(&handle, ctx) == PSA_SUCCESS) {
+            *handle_out = handle;
+        }
         return PSA_ERROR_BAD_STATE;
     }
 
-    return PSA_SUCCESS;
+    *handle_out = handle;
+    return status;
 }
 
 psa_status_t tfm_crypto_mac_verify_finish(psa_invec in_vec[],
@@ -565,17 +641,22 @@
     size_t i;
     uint32_t 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_mac_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 *mac = in_vec[1].base;
+    size_t mac_length = in_vec[1].len;
 
-    psa_mac_operation_t *operation = out_vec[0].base;
-    const uint8_t *mac = in_vec[0].base;
-    size_t mac_length = in_vec[0].len;
+    /* Init the handle in the operation with the one passed from the iov */
+    *handle_out = iov->handle;
 
     if (mac_length == 0) {
         return PSA_ERROR_INVALID_ARGUMENT;
@@ -583,7 +664,7 @@
 
     /* Look up the corresponding operation context */
     status = tfm_crypto_operation_lookup(TFM_CRYPTO_MAC_OPERATION,
-                                         operation,
+                                         handle,
                                          (void **)&ctx);
     if (status != PSA_SUCCESS) {
         return status;
@@ -591,15 +672,15 @@
 
     if ((ctx->key_usage_sign == 0) && (ctx->key_usage_verify == 1)) {
         /* Finalise the mac operation */
-        status = tfm_crypto_mac_finish(operation,
+        status = tfm_crypto_mac_finish(&handle,
                                        ctx,
                                        computed_mac,
                                        sizeof(computed_mac),
                                        &computed_mac_length);
+        *handle_out = handle;
         if (status != PSA_SUCCESS) {
             return status;
         }
-        /* A call to tfm_crypto_mac_finish() always releases the operation */
 
         /* Check that the computed mac match the expected one */
         if (computed_mac_length != mac_length) {
@@ -616,7 +697,9 @@
             return PSA_ERROR_INVALID_SIGNATURE;
         }
     } else {
-        (void)tfm_crypto_mac_release(operation, ctx);
+        if (tfm_crypto_mac_release(&handle, ctx) == PSA_SUCCESS) {
+            *handle_out = handle;
+        }
         return PSA_ERROR_BAD_STATE;
     }
 
@@ -631,19 +714,24 @@
     psa_status_t status = PSA_SUCCESS;
     struct tfm_mac_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_mac_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_mac_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_MAC_OPERATION,
-                                         operation,
+                                         handle,
                                          (void **)&ctx);
     if (status != PSA_SUCCESS) {
         return status;
@@ -653,7 +741,7 @@
         /* Check if the HMAC internal context needs to be deallocated */
         if (ctx->ctx.hmac.hash_operation.handle != TFM_CRYPTO_INVALID_HANDLE) {
             /* Clear hash context */
-            status = _psa_hash_abort(&(ctx->ctx.hmac.hash_operation));
+            status = _psa_hash_abort(&(ctx->ctx.hmac.hash_operation.handle));
             if (status != PSA_SUCCESS) {
                 return status;
             }
@@ -663,6 +751,10 @@
         return PSA_ERROR_NOT_SUPPORTED;
     }
 
-    return tfm_crypto_mac_release(operation, ctx);
+    status = tfm_crypto_mac_release(&handle, ctx);
+    if (status == PSA_SUCCESS) {
+        *handle_out = handle;
+    }
+    return status;
 }
 /*!@}*/
diff --git a/secure_fw/services/crypto/manifest.yaml b/secure_fw/services/crypto/manifest.yaml
index a3cba08..7964ba4 100644
--- a/secure_fw/services/crypto/manifest.yaml
+++ b/secure_fw/services/crypto/manifest.yaml
@@ -13,6 +13,7 @@
   "entry_point": "tfm_crypto_init",
   "stack_size": "0x2000",
   "heap_size": "0x0400",
+  "tfm_partition_ipc": true,
   "secure_functions": [
     {
       "sfid": "TFM_CRYPTO_IMPORT_KEY_SFID",
@@ -263,6 +264,16 @@
       "minor_policy": "strict"
     },
   ],
+  "services" : [
+    {
+      "name": "TFM_CRYPTO_SID",
+      "sid": "0x00004000",
+      "signal": "TFM_CRYPTO_SIG",
+      "non_secure_clients": "true",
+      "minor_version": 1,
+      "minor_policy": "STRICT"
+    },
+  ],
   "source_files": [
     "crypto_alloc.c",
     "crypto_cipher.c",
diff --git a/secure_fw/services/crypto/tfm_crypto_api.h b/secure_fw/services/crypto/tfm_crypto_api.h
index 5e6ffbd..36a0915 100644
--- a/secure_fw/services/crypto/tfm_crypto_api.h
+++ b/secure_fw/services/crypto/tfm_crypto_api.h
@@ -16,6 +16,15 @@
 #include "tfm_api.h"
 #include "tfm_crypto_defs.h"
 #include "psa_crypto.h"
+#ifdef TFM_PSA_API
+#include "psa_service.h"
+
+/**
+ * \brief This define is a function pointer type to the Uniform Signature API
+ *        prototype.
+ */
+typedef psa_status_t (*tfm_crypto_us_t)(psa_invec[],size_t,psa_outvec[],size_t);
+#endif
 
 #define UNIFORM_SIGNATURE_API(api_name) \
     psa_status_t api_name(psa_invec[], size_t, psa_outvec[], size_t)
@@ -60,38 +69,35 @@
 /**
  * \brief Allocate an operation context in the backend
  *
- * \param[in]  type Type of the operation context to allocate
- * \param[out] oper Pointer to the frontend operation
- * \param[out  ctx  Double pointer to the corresponding context
+ * \param[in]  type   Type of the operation context to allocate
+ * \param[out] handle Pointer to the hold the allocated handle
+ * \param[out  ctx    Double pointer to the corresponding context
  *
  * \return Return values as described in \ref psa_status_t
  */
 psa_status_t tfm_crypto_operation_alloc(enum tfm_crypto_operation_type type,
-                                        void *oper,
+                                        uint32_t *handle,
                                         void **ctx);
 /**
  * \brief Release an operation context in the backend
  *
- * \param[in]     type Type of the operation context to release
- * \param[in/out] oper Pointer to the frontend operation for the release
- *                     of the corresponding backend context
+ * \param[in] handle Pointer to the handle of the context to release
  *
  * \return Return values as described in \ref psa_status_t
  */
-psa_status_t tfm_crypto_operation_release(enum tfm_crypto_operation_type type,
-                                          void *oper);
+psa_status_t tfm_crypto_operation_release(uint32_t *handle);
 /**
  * \brief Look up an operation context in the backend for the corresponding
  *        frontend operation
  *
- * \param[in]  type Type of the operation context to look up
- * \param[in]  oper Pointer to the frontend operation
- * \param[out] ctx  Double pointer to the corresponding context
+ * \param[in]  type   Type of the operation context to look up
+ * \param[in]  handle Handle of the context to lookup
+ * \param[out] ctx    Double pointer to the corresponding context
  *
  * \return Return values as described in \ref psa_status_t
  */
 psa_status_t tfm_crypto_operation_lookup(enum tfm_crypto_operation_type type,
-                                         const void *oper,
+                                         uint32_t handle,
                                          void **ctx);
 /**
  * \brief Retrieve a key from the provided key slot according to the key
diff --git a/secure_fw/services/crypto/tfm_crypto_secure_api.c b/secure_fw/services/crypto/tfm_crypto_secure_api.c
index f04f470..4d6f726 100644
--- a/secure_fw/services/crypto/tfm_crypto_secure_api.c
+++ b/secure_fw/services/crypto/tfm_crypto_secure_api.c
@@ -9,24 +9,44 @@
 #include "tfm_crypto_defs.h"
 #include "psa_crypto.h"
 
-#define SFN_DISPATCH(sfn_name)                       \
-    tfm_##sfn_name##_veneer(                         \
-        in_vec, sizeof(in_vec)/sizeof(in_vec[0]),    \
-        out_vec, sizeof(out_vec)/sizeof(out_vec[0]))
+#define ARRAY_SIZE(arr) (sizeof(arr)/sizeof(arr[0]))
 
-#define SFN_DISPATCH_NO_INVEC(sfn_name)              \
-    tfm_##sfn_name##_veneer(                         \
-        NULL, 0,                                     \
-        out_vec, sizeof(out_vec)/sizeof(out_vec[0]))
+#ifdef TFM_PSA_API
+#include "psa_client.h"
 
-#define SFN_DISPATCH_NO_OUTVEC(sfn_name)             \
+/* Macro to check for a valid PSA handle */
+/* FixMe: Here temporarily until it's added to the framework headers */
+#define PSA_IS_HANDLE_VALID(handle) ((handle) > (psa_handle_t)0)
+
+#define PSA_CONNECT(service)                                \
+    psa_handle_t handle;                                    \
+    handle = psa_connect(service##_SID, service##_MIN_VER); \
+    if (!PSA_IS_HANDLE_VALID(handle)) {                     \
+        return PSA_ERROR_UNKNOWN_ERROR;                     \
+    }                                                       \
+
+#define PSA_CLOSE() psa_close(handle)
+
+#define API_DISPATCH(sfn_name, sfn_id)                     \
+    psa_call(handle, /*PSA_IPC_CALL,*/                     \
+        in_vec, ARRAY_SIZE(in_vec),                        \
+        out_vec, ARRAY_SIZE(out_vec))
+
+#define API_DISPATCH_NO_OUTVEC(sfn_name, sfn_id)           \
+    psa_call(handle, /*PSA_IPC_CALL,*/                     \
+        in_vec, ARRAY_SIZE(in_vec),                        \
+        (psa_outvec *)NULL, 0)
+#else
+#define API_DISPATCH(sfn_name, sfn_id)               \
     tfm_##sfn_name##_veneer(                         \
-        in_vec, sizeof(in_vec)/sizeof(in_vec[0]),    \
+        in_vec, ARRAY_SIZE(in_vec),                  \
+        out_vec, ARRAY_SIZE(out_vec))
+
+#define API_DISPATCH_NO_OUTVEC(sfn_name, sfn_id)     \
+    tfm_##sfn_name##_veneer(                         \
+        in_vec, ARRAY_SIZE(in_vec),                  \
         NULL, 0)
-
-#define API_DISPATCH(sfn_name) SFN_DISPATCH(sfn_name)
-#define API_DISPATCH_NO_INVEC(sfn_name) SFN_DISPATCH_NO_INVEC(sfn_name)
-#define API_DISPATCH_NO_OUTVEC(sfn_name) SFN_DISPATCH_NO_OUTVEC(sfn_name)
+#endif /* TFM_PSA_API */
 
 __attribute__(( section("SFN")))
 psa_status_t psa_crypto_init(void)
@@ -44,13 +64,25 @@
                             size_t data_length)
 {
     psa_status_t status;
+    struct tfm_crypto_pack_iovec iov = {
+        .sfn_id = TFM_CRYPTO_IMPORT_KEY_SFID,
+        .key = key,
+        .type = type,
+    };
     psa_invec in_vec[] = {
-        {.base = &key, .len = sizeof(psa_key_slot_t)},
-        {.base = &type, .len = sizeof(psa_key_type_t)},
+        {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)},
         {.base = data, .len = data_length}
     };
 
-    status = API_DISPATCH_NO_OUTVEC(tfm_crypto_import_key);
+#ifdef TFM_PSA_API
+    PSA_CONNECT(TFM_CRYPTO);
+#endif
+
+    status = API_DISPATCH_NO_OUTVEC(tfm_crypto_import_key,
+                                    TFM_CRYPTO_IMPORT_KEY);
+#ifdef TFM_PSA_API
+    PSA_CLOSE();
+#endif
 
     return status;
 }
@@ -59,11 +91,23 @@
 psa_status_t psa_destroy_key(psa_key_slot_t key)
 {
     psa_status_t status;
+    struct tfm_crypto_pack_iovec iov = {
+        .sfn_id = TFM_CRYPTO_DESTROY_KEY_SFID,
+        .key = key,
+    };
     psa_invec in_vec[] = {
-        {.base = &key, .len = sizeof(psa_key_slot_t)},
+        {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)},
     };
 
-    status = API_DISPATCH_NO_OUTVEC(tfm_crypto_destroy_key);
+#ifdef TFM_PSA_API
+    PSA_CONNECT(TFM_CRYPTO);
+#endif
+
+    status = API_DISPATCH_NO_OUTVEC(tfm_crypto_destroy_key,
+                                    TFM_CRYPTO_DESTROY_KEY);
+#ifdef TFM_PSA_API
+    PSA_CLOSE();
+#endif
 
     return status;
 }
@@ -74,15 +118,27 @@
                                      size_t *bits)
 {
     psa_status_t status;
+    struct tfm_crypto_pack_iovec iov = {
+        .sfn_id = TFM_CRYPTO_GET_KEY_INFORMATION_SFID,
+        .key = key,
+    };
     psa_invec in_vec[] = {
-        {.base = &key, .len = sizeof(psa_key_slot_t)},
+        {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)},
     };
     psa_outvec out_vec[] = {
         {.base = type, .len = sizeof(psa_key_type_t)},
         {.base = bits, .len = sizeof(size_t)}
     };
 
-    status = API_DISPATCH(tfm_crypto_get_key_information);
+#ifdef TFM_PSA_API
+    PSA_CONNECT(TFM_CRYPTO);
+#endif
+
+    status = API_DISPATCH(tfm_crypto_get_key_information,
+                          TFM_CRYPTO_GET_KEY_INFORMATION);
+#ifdef TFM_PSA_API
+    PSA_CLOSE();
+#endif
 
     return status;
 }
@@ -94,17 +150,30 @@
                             size_t *data_length)
 {
     psa_status_t status;
+    struct tfm_crypto_pack_iovec iov = {
+        .sfn_id = TFM_CRYPTO_EXPORT_KEY_SFID,
+        .key = key,
+    };
     psa_invec in_vec[] = {
-        {.base = &key, .len = sizeof(psa_key_slot_t)},
+        {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)},
     };
     psa_outvec out_vec[] = {
         {.base = data, .len = data_size}
     };
 
-    status = API_DISPATCH(tfm_crypto_export_key);
+#ifdef TFM_PSA_API
+    PSA_CONNECT(TFM_CRYPTO);
+#endif
+
+    status = API_DISPATCH(tfm_crypto_export_key,
+                          TFM_CRYPTO_EXPORT_KEY);
 
     *data_length = out_vec[0].len;
 
+#ifdef TFM_PSA_API
+    PSA_CLOSE();
+#endif
+
     return status;
 }
 
@@ -114,6 +183,11 @@
                                    size_t data_size,
                                    size_t *data_length)
 {
+    (void)key;
+    (void)data;
+    (void)data_size;
+    (void)data_length;
+
     /* TODO: This API is not supported yet */
     return PSA_ERROR_NOT_SUPPORTED;
 }
@@ -122,12 +196,31 @@
 void psa_key_policy_init(psa_key_policy_t *policy)
 {
     psa_status_t status;
+    struct tfm_crypto_pack_iovec iov = {
+        .sfn_id = TFM_CRYPTO_KEY_POLICY_INIT_SFID,
+    };
+    psa_invec in_vec[] = {
+        {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)},
+    };
     psa_outvec out_vec[] = {
         {.base = policy, .len = sizeof(psa_key_policy_t)},
     };
 
+#ifdef TFM_PSA_API
+    psa_handle_t handle;
+    handle = psa_connect(TFM_CRYPTO_SID,
+                         TFM_CRYPTO_MIN_VER);
+    if (!PSA_IS_HANDLE_VALID(handle)) {
+        return;
+    }
+#endif
+
     /* PSA API returns void so just ignore error value returned */
-    status = API_DISPATCH_NO_INVEC(tfm_crypto_key_policy_init);
+    status = API_DISPATCH(tfm_crypto_key_policy_init,
+                          TFM_CRYPTO_KEY_POLICY_INIT);
+#ifdef TFM_PSA_API
+    PSA_CLOSE();
+#endif
 }
 
 __attribute__(( section("SFN")))
@@ -136,16 +229,33 @@
                               psa_algorithm_t alg)
 {
     psa_status_t status;
+    struct tfm_crypto_pack_iovec iov = {
+        .sfn_id = TFM_CRYPTO_KEY_POLICY_SET_USAGE_SFID,
+        .usage = usage,
+        .alg = alg,
+    };
     psa_invec in_vec[] = {
-        {.base = &usage, .len = sizeof(psa_key_usage_t)},
-        {.base = &alg, .len = sizeof(psa_algorithm_t)}
+        {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)},
     };
     psa_outvec out_vec[] = {
         {.base = policy, .len = sizeof(psa_key_policy_t)},
     };
 
+#ifdef TFM_PSA_API
+    psa_handle_t handle;
+    handle = psa_connect(TFM_CRYPTO_SID,
+                         TFM_CRYPTO_MIN_VER);
+    if (!PSA_IS_HANDLE_VALID(handle)) {
+        return;
+    }
+#endif
+
     /* PSA API returns void so just ignore error value returned */
-    status = API_DISPATCH(tfm_crypto_key_policy_set_usage);
+    status = API_DISPATCH(tfm_crypto_key_policy_set_usage,
+                          TFM_CRYPTO_KEY_POLICY_SET_USAGE);
+#ifdef TFM_PSA_API
+    PSA_CLOSE();
+#endif
 }
 
 __attribute__(( section("SFN")))
@@ -154,20 +264,33 @@
     psa_status_t status;
     psa_key_usage_t usage;
 
-    /* Initialise to a sensible default to avoid returning an uninitialised
-     * value in case the secure function fails.
-     */
-    usage = 0;
+    struct tfm_crypto_pack_iovec iov = {
+        .sfn_id = TFM_CRYPTO_KEY_POLICY_GET_USAGE_SFID,
+    };
 
     psa_invec in_vec[] = {
+        {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)},
         {.base = policy, .len = sizeof(psa_key_policy_t)},
     };
     psa_outvec out_vec[] = {
         {.base = &usage, .len = sizeof(psa_key_usage_t)},
     };
 
+    /* Initialise to a sensible default to avoid returning an uninitialised
+     * value in case the secure function fails.
+     */
+    usage = 0;
+
+#ifdef TFM_PSA_API
+    PSA_CONNECT(TFM_CRYPTO);
+#endif
+
     /* The PSA API does not return an error, so ignore any error from TF-M */
-    status = API_DISPATCH(tfm_crypto_key_policy_get_usage);
+    status = API_DISPATCH(tfm_crypto_key_policy_get_usage,
+                          TFM_CRYPTO_KEY_POLICY_GET_USAGE);
+#ifdef TFM_PSA_API
+    PSA_CLOSE();
+#endif
 
     return usage;
 }
@@ -178,20 +301,33 @@
     psa_status_t status;
     psa_algorithm_t alg;
 
-    /* Initialise to a sensible default to avoid returning an uninitialised
-     * value in case the secure function fails.
-     */
-    alg = 0;
+    struct tfm_crypto_pack_iovec iov = {
+        .sfn_id = TFM_CRYPTO_KEY_POLICY_GET_ALGORITHM_SFID,
+    };
 
     psa_invec in_vec[] = {
+        {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)},
         {.base = policy, .len = sizeof(psa_key_policy_t)},
     };
     psa_outvec out_vec[] = {
         {.base = &alg, .len = sizeof(psa_algorithm_t)},
     };
 
+    /* Initialise to a sensible default to avoid returning an uninitialised
+     * value in case the secure function fails.
+     */
+    alg = 0;
+
+#ifdef TFM_PSA_API
+    PSA_CONNECT(TFM_CRYPTO);
+#endif
+
     /* The PSA API does not return an error, so ignore any error from TF-M */
-    status = API_DISPATCH(tfm_crypto_key_policy_get_algorithm);
+    status = API_DISPATCH(tfm_crypto_key_policy_get_algorithm,
+                          TFM_CRYPTO_KEY_POLICY_GET_ALGORITHM);
+#ifdef TFM_PSA_API
+    PSA_CLOSE();
+#endif
 
     return alg;
 }
@@ -201,12 +337,25 @@
                                 const psa_key_policy_t *policy)
 {
     psa_status_t status;
+    struct tfm_crypto_pack_iovec iov = {
+        .sfn_id = TFM_CRYPTO_SET_KEY_POLICY_SFID,
+        .key = key,
+    };
+
     psa_invec in_vec[] = {
-        {.base = &key, .len = sizeof(psa_key_slot_t)},
+        {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)},
         {.base = policy, .len = sizeof(psa_key_policy_t)},
     };
 
-    status = API_DISPATCH_NO_OUTVEC(tfm_crypto_set_key_policy);
+#ifdef TFM_PSA_API
+    PSA_CONNECT(TFM_CRYPTO);
+#endif
+
+    status = API_DISPATCH_NO_OUTVEC(tfm_crypto_set_key_policy,
+                                    TFM_CRYPTO_SET_KEY_POLICY);
+#ifdef TFM_PSA_API
+    PSA_CLOSE();
+#endif
 
     return status;
 }
@@ -216,14 +365,27 @@
                                 psa_key_policy_t *policy)
 {
     psa_status_t status;
+    struct tfm_crypto_pack_iovec iov = {
+        .sfn_id = TFM_CRYPTO_GET_KEY_POLICY_SFID,
+        .key = key,
+    };
+
     psa_invec in_vec[] = {
-        {.base = &key, .len = sizeof(psa_key_slot_t)},
+        {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)},
     };
     psa_outvec out_vec[] = {
         {.base = policy, .len = sizeof(psa_key_policy_t)},
     };
 
-    status = API_DISPATCH(tfm_crypto_get_key_policy);
+#ifdef TFM_PSA_API
+    PSA_CONNECT(TFM_CRYPTO);
+#endif
+
+    status = API_DISPATCH(tfm_crypto_get_key_policy,
+                          TFM_CRYPTO_GET_KEY_POLICY);
+#ifdef TFM_PSA_API
+    PSA_CLOSE();
+#endif
 
     return status;
 }
@@ -233,12 +395,25 @@
                                   psa_key_lifetime_t lifetime)
 {
     psa_status_t status;
-    psa_invec in_vec[] = {
-        {.base = &key, .len = sizeof(psa_key_slot_t)},
-        {.base = &lifetime, .len = sizeof(psa_key_lifetime_t)},
+    struct tfm_crypto_pack_iovec iov = {
+        .sfn_id = TFM_CRYPTO_SET_KEY_LIFETIME_SFID,
+        .key = key,
+        .lifetime = lifetime,
     };
 
-    status = API_DISPATCH_NO_OUTVEC(tfm_crypto_set_key_lifetime);
+    psa_invec in_vec[] = {
+        {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)},
+    };
+
+#ifdef TFM_PSA_API
+    PSA_CONNECT(TFM_CRYPTO);
+#endif
+
+    status = API_DISPATCH_NO_OUTVEC(tfm_crypto_set_key_lifetime,
+                                    TFM_CRYPTO_SET_KEY_LIFETIME);
+#ifdef TFM_PSA_API
+    PSA_CLOSE();
+#endif
 
     return status;
 }
@@ -248,14 +423,27 @@
                                   psa_key_lifetime_t *lifetime)
 {
     psa_status_t status;
+    struct tfm_crypto_pack_iovec iov = {
+        .sfn_id = TFM_CRYPTO_GET_KEY_LIFETIME_SFID,
+        .key = key,
+    };
+
     psa_invec in_vec[] = {
-        {.base = &key, .len = sizeof(psa_key_slot_t)},
+        {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)},
     };
     psa_outvec out_vec[] = {
         {.base = lifetime, .len = sizeof(psa_key_lifetime_t)},
     };
 
-    status = API_DISPATCH(tfm_crypto_get_key_lifetime);
+#ifdef TFM_PSA_API
+    PSA_CONNECT(TFM_CRYPTO);
+#endif
+
+    status = API_DISPATCH(tfm_crypto_get_key_lifetime,
+                          TFM_CRYPTO_GET_KEY_LIFETIME);
+#ifdef TFM_PSA_API
+    PSA_CLOSE();
+#endif
 
     return status;
 }
@@ -266,14 +454,28 @@
                                size_t iv_length)
 {
     psa_status_t status;
+    struct tfm_crypto_pack_iovec iov = {
+        .sfn_id = TFM_CRYPTO_CIPHER_SET_IV_SFID,
+        .handle = operation->handle,
+    };
+
     psa_invec in_vec[] = {
+        {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)},
         {.base = iv, .len = iv_length},
     };
     psa_outvec out_vec[] = {
-        {.base = operation, .len = sizeof(psa_cipher_operation_t)},
+        {.base = &(operation->handle), .len = sizeof(uint32_t)},
     };
 
-    status = API_DISPATCH(tfm_crypto_cipher_set_iv);
+#ifdef TFM_PSA_API
+    PSA_CONNECT(TFM_CRYPTO);
+#endif
+
+    status = API_DISPATCH(tfm_crypto_cipher_set_iv,
+                          TFM_CRYPTO_CIPHER_SET_IV);
+#ifdef TFM_PSA_API
+    PSA_CLOSE();
+#endif
 
     return status;
 }
@@ -284,15 +486,29 @@
                                       psa_algorithm_t alg)
 {
     psa_status_t status;
-    psa_invec in_vec[] = {
-        {.base = &key, .len = sizeof(psa_key_slot_t)},
-        {.base = &alg, .len = sizeof(psa_algorithm_t)},
-    };
-    psa_outvec out_vec[] = {
-        {.base = operation, .len = sizeof(psa_cipher_operation_t)},
+    struct tfm_crypto_pack_iovec iov = {
+        .sfn_id = TFM_CRYPTO_CIPHER_ENCRYPT_SETUP_SFID,
+        .key = key,
+        .alg = alg,
+        .handle = operation->handle,
     };
 
-    status = API_DISPATCH(tfm_crypto_cipher_encrypt_setup);
+    psa_invec in_vec[] = {
+        {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)},
+    };
+    psa_outvec out_vec[] = {
+        {.base = &(operation->handle), .len = sizeof(uint32_t)},
+    };
+
+#ifdef TFM_PSA_API
+    PSA_CONNECT(TFM_CRYPTO);
+#endif
+
+    status = API_DISPATCH(tfm_crypto_cipher_encrypt_setup,
+                          TFM_CRYPTO_CIPHER_ENCRYPT_SETUP);
+#ifdef TFM_PSA_API
+    PSA_CLOSE();
+#endif
 
     return status;
 }
@@ -303,15 +519,29 @@
                                       psa_algorithm_t alg)
 {
     psa_status_t status;
-    psa_invec in_vec[] = {
-        {.base = &key, .len = sizeof(psa_key_slot_t)},
-        {.base = &alg, .len = sizeof(psa_algorithm_t)},
-    };
-    psa_outvec out_vec[] = {
-        {.base = operation, .len = sizeof(psa_cipher_operation_t)},
+    struct tfm_crypto_pack_iovec iov = {
+        .sfn_id = TFM_CRYPTO_CIPHER_DECRYPT_SETUP_SFID,
+        .key = key,
+        .alg = alg,
+        .handle = operation->handle,
     };
 
-    status = API_DISPATCH(tfm_crypto_cipher_decrypt_setup);
+    psa_invec in_vec[] = {
+        {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)},
+    };
+    psa_outvec out_vec[] = {
+        {.base = &(operation->handle), .len = sizeof(uint32_t)},
+    };
+
+#ifdef TFM_PSA_API
+    PSA_CONNECT(TFM_CRYPTO);
+#endif
+
+    status = API_DISPATCH(tfm_crypto_cipher_decrypt_setup,
+                          TFM_CRYPTO_CIPHER_DECRYPT_SETUP);
+#ifdef TFM_PSA_API
+    PSA_CLOSE();
+#endif
 
     return status;
 }
@@ -325,18 +555,33 @@
                                size_t *output_length)
 {
     psa_status_t status;
+    struct tfm_crypto_pack_iovec iov = {
+        .sfn_id = TFM_CRYPTO_CIPHER_UPDATE_SFID,
+        .handle = operation->handle,
+    };
+
     psa_invec in_vec[] = {
+        {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)},
         {.base = input, .len = input_length},
     };
     psa_outvec out_vec[] = {
-        {.base = operation, .len = sizeof(psa_cipher_operation_t)},
+        {.base = &(operation->handle), .len = sizeof(uint32_t)},
         {.base = output, .len = output_size}
     };
 
-    status = API_DISPATCH(tfm_crypto_cipher_update);
+#ifdef TFM_PSA_API
+    PSA_CONNECT(TFM_CRYPTO);
+#endif
+
+    status = API_DISPATCH(tfm_crypto_cipher_update,
+                          TFM_CRYPTO_CIPHER_UPDATE);
 
     *output_length = out_vec[1].len;
 
+#ifdef TFM_PSA_API
+    PSA_CLOSE();
+#endif
+
     return status;
 }
 
@@ -344,11 +589,27 @@
 psa_status_t psa_cipher_abort(psa_cipher_operation_t *operation)
 {
     psa_status_t status;
-    psa_outvec out_vec[] = {
-        {.base = operation, .len = sizeof(psa_cipher_operation_t)},
+    struct tfm_crypto_pack_iovec iov = {
+        .sfn_id = TFM_CRYPTO_CIPHER_ABORT_SFID,
+        .handle = operation->handle,
     };
 
-    status = API_DISPATCH_NO_INVEC(tfm_crypto_cipher_abort);
+    psa_invec in_vec[] = {
+        {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)},
+    };
+    psa_outvec out_vec[] = {
+        {.base = &(operation->handle), .len = sizeof(uint32_t)},
+    };
+
+#ifdef TFM_PSA_API
+    PSA_CONNECT(TFM_CRYPTO);
+#endif
+
+    status = API_DISPATCH(tfm_crypto_cipher_abort,
+                          TFM_CRYPTO_CIPHER_ABORT);
+#ifdef TFM_PSA_API
+    PSA_CLOSE();
+#endif
 
     return status;
 }
@@ -360,15 +621,32 @@
                                size_t *output_length)
 {
     psa_status_t status;
+    struct tfm_crypto_pack_iovec iov = {
+        .sfn_id = TFM_CRYPTO_CIPHER_FINISH_SFID,
+        .handle = operation->handle,
+    };
+
+    psa_invec in_vec[] = {
+        {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)},
+    };
     psa_outvec out_vec[] = {
-        {.base = operation, .len = sizeof(psa_cipher_operation_t)},
+        {.base = &(operation->handle), .len = sizeof(uint32_t)},
         {.base = output, .len = output_size},
     };
 
-    status = API_DISPATCH_NO_INVEC(tfm_crypto_cipher_finish);
+#ifdef TFM_PSA_API
+    PSA_CONNECT(TFM_CRYPTO);
+#endif
+
+    status = API_DISPATCH(tfm_crypto_cipher_finish,
+                          TFM_CRYPTO_CIPHER_FINISH);
 
     *output_length = out_vec[1].len;
 
+#ifdef TFM_PSA_API
+    PSA_CLOSE();
+#endif
+
     return status;
 }
 
@@ -377,14 +655,29 @@
                             psa_algorithm_t alg)
 {
     psa_status_t status;
-    psa_invec in_vec[] = {
-        {.base = &alg, .len = sizeof(psa_algorithm_t)},
-    };
-    psa_outvec out_vec[] = {
-        {.base = operation, .len = sizeof(psa_hash_operation_t)},
+    struct tfm_crypto_pack_iovec iov = {
+        .sfn_id = TFM_CRYPTO_HASH_SETUP_SFID,
+        .alg = alg,
+        .handle = operation->handle,
     };
 
-    status = API_DISPATCH(tfm_crypto_hash_setup);
+    psa_invec in_vec[] = {
+        {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)},
+    };
+    psa_outvec out_vec[] = {
+        {.base = &(operation->handle), .len = sizeof(uint32_t)},
+    };
+
+#ifdef TFM_PSA_API
+    PSA_CONNECT(TFM_CRYPTO);
+#endif
+
+    status = API_DISPATCH(tfm_crypto_hash_setup,
+                          TFM_CRYPTO_HASH_SETUP);
+
+#ifdef TFM_PSA_API
+    PSA_CLOSE();
+#endif
 
     return status;
 }
@@ -395,14 +688,29 @@
                              size_t input_length)
 {
     psa_status_t status;
+    struct tfm_crypto_pack_iovec iov = {
+        .sfn_id = TFM_CRYPTO_HASH_UPDATE_SFID,
+        .handle = operation->handle,
+    };
+
     psa_invec in_vec[] = {
+        {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)},
         {.base = input, .len = input_length},
     };
     psa_outvec out_vec[] = {
-        {.base = operation, .len = sizeof(psa_hash_operation_t)},
+        {.base = &(operation->handle), .len = sizeof(uint32_t)},
     };
 
-    status = API_DISPATCH(tfm_crypto_hash_update);
+#ifdef TFM_PSA_API
+    PSA_CONNECT(TFM_CRYPTO);
+#endif
+
+    status = API_DISPATCH(tfm_crypto_hash_update,
+                          TFM_CRYPTO_HASH_UPDATE);
+
+#ifdef TFM_PSA_API
+    PSA_CLOSE();
+#endif
 
     return status;
 }
@@ -414,15 +722,32 @@
                              size_t *hash_length)
 {
     psa_status_t status;
+    struct tfm_crypto_pack_iovec iov = {
+        .sfn_id = TFM_CRYPTO_HASH_FINISH_SFID,
+        .handle = operation->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 = &(operation->handle), .len = sizeof(uint32_t)},
         {.base = hash, .len = hash_size},
     };
 
-    status = API_DISPATCH_NO_INVEC(tfm_crypto_hash_finish);
+#ifdef TFM_PSA_API
+    PSA_CONNECT(TFM_CRYPTO);
+#endif
+
+    status = API_DISPATCH(tfm_crypto_hash_finish,
+                          TFM_CRYPTO_HASH_FINISH);
 
     *hash_length = out_vec[1].len;
 
+#ifdef TFM_PSA_API
+    PSA_CLOSE();
+#endif
+
     return status;
 }
 
@@ -432,14 +757,28 @@
                              size_t hash_length)
 {
     psa_status_t status;
+    struct tfm_crypto_pack_iovec iov = {
+        .sfn_id = TFM_CRYPTO_HASH_VERIFY_SFID,
+        .handle = operation->handle,
+    };
+
     psa_invec in_vec[] = {
+        {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)},
         {.base = hash, .len = hash_length},
     };
     psa_outvec out_vec[] = {
-        {.base = operation, .len = sizeof(psa_hash_operation_t)},
+        {.base = &(operation->handle), .len = sizeof(uint32_t)},
     };
 
-    status = API_DISPATCH(tfm_crypto_hash_verify);
+#ifdef TFM_PSA_API
+    PSA_CONNECT(TFM_CRYPTO);
+#endif
+
+    status = API_DISPATCH(tfm_crypto_hash_verify,
+                          TFM_CRYPTO_HASH_VERIFY);
+#ifdef TFM_PSA_API
+    PSA_CLOSE();
+#endif
 
     return status;
 }
@@ -448,11 +787,27 @@
 psa_status_t psa_hash_abort(psa_hash_operation_t *operation)
 {
     psa_status_t status;
-    psa_outvec out_vec[] = {
-        {.base = operation, .len = sizeof(psa_hash_operation_t)},
+    struct tfm_crypto_pack_iovec iov = {
+        .sfn_id = TFM_CRYPTO_HASH_ABORT_SFID,
+        .handle = operation->handle,
     };
 
-    status = API_DISPATCH_NO_INVEC(tfm_crypto_hash_abort);
+    psa_invec in_vec[] = {
+        {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)},
+    };
+    psa_outvec out_vec[] = {
+        {.base = &(operation->handle), .len = sizeof(uint32_t)},
+    };
+
+#ifdef TFM_PSA_API
+    PSA_CONNECT(TFM_CRYPTO);
+#endif
+
+    status = API_DISPATCH(tfm_crypto_hash_abort,
+                          TFM_CRYPTO_HASH_ABORT);
+#ifdef TFM_PSA_API
+    PSA_CLOSE();
+#endif
 
     return status;
 }
@@ -463,15 +818,29 @@
                                 psa_algorithm_t alg)
 {
     psa_status_t status;
-    psa_invec in_vec[] = {
-        {.base = &key, .len = sizeof(psa_key_slot_t)},
-        {.base = &alg, .len = sizeof(psa_algorithm_t)}
-    };
-    psa_outvec out_vec[] = {
-        {.base = operation, .len = sizeof(psa_mac_operation_t)},
+    struct tfm_crypto_pack_iovec iov = {
+        .sfn_id = TFM_CRYPTO_MAC_SIGN_SETUP_SFID,
+        .key = key,
+        .alg = alg,
+        .handle = operation->handle,
     };
 
-    status = API_DISPATCH(tfm_crypto_mac_sign_setup);
+    psa_invec in_vec[] = {
+        {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)},
+    };
+    psa_outvec out_vec[] = {
+        {.base = &(operation->handle), .len = sizeof(uint32_t)},
+    };
+
+#ifdef TFM_PSA_API
+    PSA_CONNECT(TFM_CRYPTO);
+#endif
+
+    status = API_DISPATCH(tfm_crypto_mac_sign_setup,
+                          TFM_CRYPTO_MAC_SIGN_SETUP);
+#ifdef TFM_PSA_API
+    PSA_CLOSE();
+#endif
 
     return status;
 }
@@ -482,15 +851,29 @@
                                   psa_algorithm_t alg)
 {
     psa_status_t status;
-    psa_invec in_vec[] = {
-        {.base = &key, .len = sizeof(psa_key_slot_t)},
-        {.base = &alg, .len = sizeof(psa_algorithm_t)}
-    };
-    psa_outvec out_vec[] = {
-        {.base = operation, .len = sizeof(psa_mac_operation_t)},
+    struct tfm_crypto_pack_iovec iov = {
+        .sfn_id = TFM_CRYPTO_MAC_VERIFY_SETUP_SFID,
+        .key = key,
+        .alg = alg,
+        .handle = operation->handle,
     };
 
-    status = API_DISPATCH(tfm_crypto_mac_verify_setup);
+    psa_invec in_vec[] = {
+        {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)},
+    };
+    psa_outvec out_vec[] = {
+        {.base = &(operation->handle), .len = sizeof(uint32_t)},
+    };
+
+#ifdef TFM_PSA_API
+    PSA_CONNECT(TFM_CRYPTO);
+#endif
+
+    status = API_DISPATCH(tfm_crypto_mac_verify_setup,
+                          TFM_CRYPTO_MAC_VERIFY_SETUP);
+#ifdef TFM_PSA_API
+    PSA_CLOSE();
+#endif
 
     return status;
 }
@@ -501,14 +884,28 @@
                             size_t input_length)
 {
     psa_status_t status;
+    struct tfm_crypto_pack_iovec iov = {
+        .sfn_id = TFM_CRYPTO_MAC_UPDATE_SFID,
+        .handle = operation->handle,
+    };
+
     psa_invec in_vec[] = {
+        {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)},
         {.base = input, .len = input_length},
     };
     psa_outvec out_vec[] = {
-        {.base = operation, .len = sizeof(psa_mac_operation_t)},
+        {.base = &(operation->handle), .len = sizeof(uint32_t)},
     };
 
-    status = API_DISPATCH(tfm_crypto_mac_update);
+#ifdef TFM_PSA_API
+    PSA_CONNECT(TFM_CRYPTO);
+#endif
+
+    status = API_DISPATCH(tfm_crypto_mac_update,
+                          TFM_CRYPTO_MAC_UPDATE);
+#ifdef TFM_PSA_API
+    PSA_CLOSE();
+#endif
 
     return status;
 }
@@ -520,15 +917,32 @@
                                  size_t *mac_length)
 {
     psa_status_t status;
+    struct tfm_crypto_pack_iovec iov = {
+        .sfn_id = TFM_CRYPTO_MAC_SIGN_FINISH_SFID,
+        .handle = operation->handle,
+    };
+
+    psa_invec in_vec[] = {
+        {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)},
+    };
     psa_outvec out_vec[] = {
-        {.base = operation, .len = sizeof(psa_mac_operation_t)},
+        {.base = &(operation->handle), .len = sizeof(uint32_t)},
         {.base = mac, .len = mac_size},
     };
 
-    status = API_DISPATCH_NO_INVEC(tfm_crypto_mac_sign_finish);
+#ifdef TFM_PSA_API
+    PSA_CONNECT(TFM_CRYPTO);
+#endif
+
+    status = API_DISPATCH(tfm_crypto_mac_sign_finish,
+                          TFM_CRYPTO_MAC_SIGN_FINISH);
 
     *mac_length = out_vec[1].len;
 
+#ifdef TFM_PSA_API
+    PSA_CLOSE();
+#endif
+
     return status;
 }
 
@@ -538,14 +952,29 @@
                                    size_t mac_length)
 {
     psa_status_t status;
+    struct tfm_crypto_pack_iovec iov = {
+        .sfn_id = TFM_CRYPTO_MAC_VERIFY_FINISH_SFID,
+        .handle = operation->handle,
+    };
+
     psa_invec in_vec[] = {
+        {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)},
         {.base = mac, .len = mac_length},
     };
     psa_outvec out_vec[] = {
-        {.base = operation, .len = sizeof(psa_mac_operation_t)},
+        {.base = &(operation->handle), .len = sizeof(uint32_t)},
     };
 
-    status = API_DISPATCH(tfm_crypto_mac_verify_finish);
+#ifdef TFM_PSA_API
+    PSA_CONNECT(TFM_CRYPTO);
+#endif
+
+    status = API_DISPATCH(tfm_crypto_mac_verify_finish,
+                          TFM_CRYPTO_MAC_VERIFY_FINISH);
+
+#ifdef TFM_PSA_API
+    PSA_CLOSE();
+#endif
 
     return status;
 }
@@ -554,11 +983,27 @@
 psa_status_t psa_mac_abort(psa_mac_operation_t *operation)
 {
     psa_status_t status;
-    psa_outvec out_vec[] = {
-        {.base = operation, .len = sizeof(psa_mac_operation_t)},
+    struct tfm_crypto_pack_iovec iov = {
+        .sfn_id = TFM_CRYPTO_MAC_ABORT_SFID,
+        .handle = operation->handle,
     };
 
-    status = API_DISPATCH_NO_INVEC(tfm_crypto_mac_abort);
+    psa_invec in_vec[] = {
+        {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)},
+    };
+    psa_outvec out_vec[] = {
+        {.base = &(operation->handle), .len = sizeof(uint32_t)},
+    };
+
+#ifdef TFM_PSA_API
+    PSA_CONNECT(TFM_CRYPTO);
+#endif
+
+    status = API_DISPATCH(tfm_crypto_mac_abort,
+                          TFM_CRYPTO_MAC_ABORT);
+#ifdef TFM_PSA_API
+    PSA_CLOSE();
+#endif
 
     return status;
 }
@@ -577,17 +1022,18 @@
                               size_t *ciphertext_length)
 {
     psa_status_t status;
-    struct tfm_crypto_aead_pack_input input_s = {
-      .key = key,
-      .alg = alg,
-      .nonce = {0},
+    struct tfm_crypto_pack_iovec iov = {
+        .sfn_id = TFM_CRYPTO_AEAD_ENCRYPT_SFID,
+        .key = key,
+        .alg = alg,
+        .aead_in = {.nonce = {0}, .nonce_length = nonce_length}
     };
+
     size_t idx = 0;
     psa_invec in_vec[] = {
-        {.base = &input_s, .len = nonce_length + sizeof(psa_key_slot_t)
-                                               + sizeof(psa_algorithm_t)},
-        {.base = additional_data, .len = additional_data_length},
+        {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)},
         {.base = plaintext, .len = plaintext_length},
+        {.base = additional_data, .len = additional_data_length},
     };
     psa_outvec out_vec[] = {
         {.base = ciphertext, .len = ciphertext_size},
@@ -599,14 +1045,32 @@
 
     if (nonce != NULL) {
         for (idx = 0; idx < nonce_length; idx++) {
-            input_s.nonce[idx] = nonce[idx];
+            iov.aead_in.nonce[idx] = nonce[idx];
         }
     }
 
-    status = API_DISPATCH(tfm_crypto_aead_encrypt);
+#ifdef TFM_PSA_API
+    PSA_CONNECT(TFM_CRYPTO);
+#endif
+
+#ifdef TFM_PSA_API
+    size_t in_len = sizeof(in_vec)/sizeof(in_vec[0]);
+    if (additional_data == NULL) {
+      in_len--;
+    }
+    status = psa_call(handle, in_vec, in_len,
+                      out_vec, sizeof(out_vec)/sizeof(out_vec[0]));
+#else
+    status = API_DISPATCH(tfm_crypto_aead_encrypt,
+                          TFM_CRYPTO_AEAD_ENCRYPT);
+#endif
 
     *ciphertext_length = out_vec[0].len;
 
+#ifdef TFM_PSA_API
+    PSA_CLOSE();
+#endif
+
     return status;
 }
 
@@ -624,17 +1088,18 @@
                               size_t *plaintext_length)
 {
     psa_status_t status;
-    struct tfm_crypto_aead_pack_input input_s = {
-      .key = key,
-      .alg = alg,
-      .nonce = {0},
+    struct tfm_crypto_pack_iovec iov = {
+        .sfn_id = TFM_CRYPTO_AEAD_DECRYPT_SFID,
+        .key = key,
+        .alg = alg,
+        .aead_in = {.nonce = {0}, .nonce_length = nonce_length}
     };
+
     size_t idx = 0;
     psa_invec in_vec[] = {
-        {.base = &input_s, .len = nonce_length + sizeof(psa_key_slot_t)
-                                               + sizeof(psa_algorithm_t)},
-        {.base = additional_data, .len = additional_data_length},
+        {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)},
         {.base = ciphertext, .len = ciphertext_length},
+        {.base = additional_data, .len = additional_data_length},
     };
     psa_outvec out_vec[] = {
         {.base = plaintext, .len = plaintext_size},
@@ -646,13 +1111,31 @@
 
     if (nonce != NULL) {
         for (idx = 0; idx < nonce_length; idx++) {
-            input_s.nonce[idx] = nonce[idx];
+            iov.aead_in.nonce[idx] = nonce[idx];
         }
     }
 
-    status = API_DISPATCH(tfm_crypto_aead_decrypt);
+#ifdef TFM_PSA_API
+    PSA_CONNECT(TFM_CRYPTO);
+#endif
+
+#ifdef TFM_PSA_API
+    size_t in_len = sizeof(in_vec)/sizeof(in_vec[0]);
+    if (additional_data == NULL) {
+      in_len--;
+    }
+    status = psa_call(handle, in_vec, in_len,
+                      out_vec, sizeof(out_vec)/sizeof(out_vec[0]));
+#else
+    status = API_DISPATCH(tfm_crypto_aead_decrypt,
+                          TFM_CRYPTO_AEAD_DECRYPT);
+#endif
 
     *plaintext_length = out_vec[0].len;
 
+#ifdef TFM_PSA_API
+    PSA_CLOSE();
+#endif
+
     return status;
 }
diff --git a/secure_fw/services/crypto/tfm_crypto_signal.h b/secure_fw/services/crypto/tfm_crypto_signal.h
new file mode 100644
index 0000000..e632a8b
--- /dev/null
+++ b/secure_fw/services/crypto/tfm_crypto_signal.h
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2019, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef __TFM_CRYPTO_SIGNAL_H__
+#define __TFM_CRYPTO_SIGNAL_H__
+
+#define TFM_IPC_SIG_RESERVED_POS (4U)
+
+#define TFM_CRYPTO_SIG_POS (TFM_IPC_SIG_RESERVED_POS+0U)
+
+/**
+ * \brief Definitions for the signals available in the Crypto partition
+ *
+ */
+#define TFM_CRYPTO_SIG     (1U << TFM_CRYPTO_SIG_POS)
+
+#endif /* __TFM_CRYPTO_SIGNAL_H__ */
diff --git a/secure_fw/services/tfm_partition_list.inc b/secure_fw/services/tfm_partition_list.inc
index 06e2310..bd57977 100644
--- a/secure_fw/services/tfm_partition_list.inc
+++ b/secure_fw/services/tfm_partition_list.inc
@@ -26,6 +26,7 @@
 
 /******** TFM_SP_CRYPTO ********/
 PARTITION_DECLARE(TFM_SP_CRYPTO, 0
+    | SPM_PART_FLAG_IPC
     , "PSA-ROT", 0x00000102, NORMAL);
 PARTITION_ADD_INIT_FUNC(TFM_SP_CRYPTO, tfm_crypto_init);
 
diff --git a/secure_fw/services/tfm_service_list.inc b/secure_fw/services/tfm_service_list.inc
index c361ce8..a7c1e6a 100644
--- a/secure_fw/services/tfm_service_list.inc
+++ b/secure_fw/services/tfm_service_list.inc
@@ -58,6 +58,16 @@
 },
 
 
+/******** TFM_SP_CRYPTO ********/
+{
+        "TFM_CRYPTO_SID",
+        TFM_SP_CRYPTO_ID,
+        TFM_CRYPTO_SIG,
+        0x00004000,
+        true,
+        1,
+        TFM_VERSION_POLICY_STRICT
+},
 
 
 
diff --git a/test/framework/non_secure_suites.c b/test/framework/non_secure_suites.c
index 1554650..bc8a731 100644
--- a/test/framework/non_secure_suites.c
+++ b/test/framework/non_secure_suites.c
@@ -41,6 +41,9 @@
 
     {&register_testsuite_ns_psa_ps_interface, 0, 0, 0},
 
+    /* Non-secure Crypto test cases */
+    {&register_testsuite_ns_crypto_interface, 0, 0, 0},
+
 #ifndef TFM_PSA_API
     /*
      * FixMe: skip below test cases temporary since target service is not
@@ -49,9 +52,6 @@
     /* Non-secure Audit Logging test cases */
     {&register_testsuite_ns_audit_interface, 0, 0, 0},
 
-    /* Non-secure Crypto test cases */
-    {&register_testsuite_ns_crypto_interface, 0, 0, 0},
-
     /* Non-secure initial attestation service test cases */
     {&register_testsuite_ns_attestation_interface, 0, 0, 0},
 
diff --git a/test/framework/secure_suites.c b/test/framework/secure_suites.c
index b7426ec..80f7ee8 100644
--- a/test/framework/secure_suites.c
+++ b/test/framework/secure_suites.c
@@ -35,6 +35,9 @@
     {&register_testsuite_s_rollback_protection, 0, 0, 0},
 #endif
 
+    /* Crypto test cases */
+    {&register_testsuite_s_crypto_interface, 0, 0, 0},
+
 #ifndef TFM_PSA_API
     /*
      * FixMe: since the following partitions haven't implement the IPC model,
@@ -43,9 +46,6 @@
     /* Secure Audit Logging test cases */
     {&register_testsuite_s_audit_interface, 0, 0, 0},
 
-    /* Crypto test cases */
-    {&register_testsuite_s_crypto_interface, 0, 0, 0},
-
     /* Secure initial attestation service test cases */
     {&register_testsuite_s_attestation_interface, 0, 0, 0},
 #endif