SST: IPC compatibility for Protected Storage

- Add IPC implementation for both secure and non-secure PS APIs.
- Update Secure Storage manifest to support IPC model.
- Add wrapper function for IPC model in tfm_sst_req_mngr.c.
- Increase the stack size to pass the test cases.
- Skip some test cases which are not supported in IPC model.

Change-Id: I80ba50fb6d46af773bbda2519e76c20776984951
Signed-off-by: Summer Qin <summer.qin@arm.com>
diff --git a/interface/include/tfm_sst_defs.h b/interface/include/tfm_sst_defs.h
index 9132cce..c997d64 100644
--- a/interface/include/tfm_sst_defs.h
+++ b/interface/include/tfm_sst_defs.h
@@ -15,6 +15,23 @@
 /* Invalid UID */
 #define TFM_SST_INVALID_UID 0
 
+#ifdef TFM_PSA_API
+/*
+ * Defines for SID and minor version number. These SIDs should align with the
+ * value in service manifest file.
+ */
+#define TFM_SST_SET_SID              (0x00002000)
+#define TFM_SST_SET_MIN_VER          (0x0001)
+#define TFM_SST_GET_SID              (0x00002001)
+#define TFM_SST_GET_MIN_VER          (0x0001)
+#define TFM_SST_GET_INFO_SID         (0x00002002)
+#define TFM_SST_GET_INFO_MIN_VER     (0x0001)
+#define TFM_SST_REMOVE_SID           (0x00002003)
+#define TFM_SST_REMOVE_MIN_VER       (0x0001)
+#define TFM_SST_GET_SUPPORT_SID      (0x00002004)
+#define TFM_SST_GET_SUPPORT_MIN_VER  (0x0001)
+#endif
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/interface/src/tfm_sst_api.c b/interface/src/tfm_sst_api.c
index 260dbc2..0da82d0 100644
--- a/interface/src/tfm_sst_api.c
+++ b/interface/src/tfm_sst_api.c
@@ -9,8 +9,11 @@
 
 #include "tfm_ns_lock.h"
 #include "tfm_veneers.h"
+#include "tfm_sst_defs.h"
 
 #define IOVEC_LEN(x) (uint32_t)(sizeof(x)/sizeof(x[0]))
+/* FixMe: Check if PSA framework header would provide similar macro. */
+#define TFM_PSA_HANDLE_IS_VALID(handle)  ((handle) > (psa_handle_t)0)
 
 psa_ps_status_t psa_ps_set(psa_ps_uid_t uid,
                            uint32_t data_length,
@@ -19,6 +22,9 @@
 {
     psa_status_t status;
     psa_ps_status_t err;
+#ifdef TFM_PSA_API
+    psa_handle_t handle;
+#endif
 
     psa_invec in_vec[] = {
         { .base = &uid,   .len = sizeof(uid) },
@@ -30,12 +36,32 @@
         { .base = &err , .len = sizeof(err) }
     };
 
+#ifdef TFM_PSA_API
+    if (p_data == NULL) {
+        return PSA_PS_ERROR_INVALID_ARGUMENT;
+    }
+
+    handle = psa_connect(TFM_SST_SET_SID, TFM_SST_SET_MIN_VER);
+    if (!TFM_PSA_HANDLE_IS_VALID(handle)) {
+        return PSA_PS_ERROR_OPERATION_FAILED;
+    }
+
+    status = psa_call(handle, in_vec, IOVEC_LEN(in_vec), out_vec,
+                      IOVEC_LEN(out_vec));
+
+    psa_close(handle);
+
+    if (status != PSA_SUCCESS) {
+        return PSA_PS_ERROR_OPERATION_FAILED;
+    }
+#else
     status = tfm_ns_lock_dispatch((veneer_fn)tfm_tfm_sst_set_req_veneer,
                                   (uint32_t)in_vec,  IOVEC_LEN(in_vec),
                                   (uint32_t)out_vec, IOVEC_LEN(out_vec));
     if (status != PSA_SUCCESS) {
         return PSA_PS_ERROR_OPERATION_FAILED;
     }
+#endif
 
     return err;
 }
@@ -47,6 +73,9 @@
 {
     psa_status_t status;
     psa_ps_status_t err;
+#ifdef TFM_PSA_API
+    psa_handle_t handle;
+#endif
 
     psa_invec in_vec[] = {
         { .base = &uid, .len = sizeof(uid) },
@@ -58,6 +87,25 @@
         { .base = p_data, .len = data_length }
     };
 
+#ifdef TFM_PSA_API
+    if (p_data == NULL) {
+        return PSA_PS_ERROR_INVALID_ARGUMENT;
+    }
+
+    handle = psa_connect(TFM_SST_GET_SID, TFM_SST_GET_MIN_VER);
+    if (!TFM_PSA_HANDLE_IS_VALID(handle)) {
+        return PSA_PS_ERROR_OPERATION_FAILED;
+    }
+
+    status = psa_call(handle, in_vec, IOVEC_LEN(in_vec), out_vec,
+                      IOVEC_LEN(out_vec));
+
+    psa_close(handle);
+
+    if (status != PSA_SUCCESS) {
+        return PSA_PS_ERROR_OPERATION_FAILED;
+    }
+#else
     status = tfm_ns_lock_dispatch((veneer_fn)tfm_tfm_sst_get_req_veneer,
                                   (uint32_t)in_vec,  IOVEC_LEN(in_vec),
                                   (uint32_t)out_vec, IOVEC_LEN(out_vec));
@@ -65,6 +113,7 @@
     if (status != PSA_SUCCESS) {
         return PSA_PS_ERROR_OPERATION_FAILED;
     }
+#endif
 
     return err;
 }
@@ -73,6 +122,9 @@
 {
     psa_status_t status;
     psa_ps_status_t err;
+#ifdef TFM_PSA_API
+    psa_handle_t handle;
+#endif
 
     psa_invec in_vec[] = {
         { .base = &uid, .len = sizeof(uid) }
@@ -83,6 +135,21 @@
         { .base = p_info, .len = sizeof(*p_info) }
     };
 
+#ifdef TFM_PSA_API
+    handle = psa_connect(TFM_SST_GET_INFO_SID, TFM_SST_GET_INFO_MIN_VER);
+    if (!TFM_PSA_HANDLE_IS_VALID(handle)) {
+        return PSA_PS_ERROR_OPERATION_FAILED;
+    }
+
+    status = psa_call(handle, in_vec, IOVEC_LEN(in_vec), out_vec,
+                      IOVEC_LEN(out_vec));
+
+    psa_close(handle);
+
+    if (status != PSA_SUCCESS) {
+        return PSA_PS_ERROR_OPERATION_FAILED;
+    }
+#else
     status = tfm_ns_lock_dispatch((veneer_fn)tfm_tfm_sst_get_info_req_veneer,
                                   (uint32_t)in_vec,  IOVEC_LEN(in_vec),
                                   (uint32_t)out_vec, IOVEC_LEN(out_vec));
@@ -90,6 +157,7 @@
     if (status != PSA_SUCCESS) {
         return PSA_PS_ERROR_OPERATION_FAILED;
     }
+#endif
 
     return err;
 }
@@ -98,6 +166,9 @@
 {
     psa_status_t status;
     psa_ps_status_t err;
+#ifdef TFM_PSA_API
+    psa_handle_t handle;
+#endif
 
     psa_invec in_vec[] = {
         { .base = &uid, .len = sizeof(uid) }
@@ -107,6 +178,21 @@
         { .base = &err, .len = sizeof(err) }
     };
 
+#ifdef TFM_PSA_API
+    handle = psa_connect(TFM_SST_REMOVE_SID, TFM_SST_REMOVE_MIN_VER);
+    if (!TFM_PSA_HANDLE_IS_VALID(handle)) {
+        return PSA_PS_ERROR_OPERATION_FAILED;
+    }
+
+    status = psa_call(handle, in_vec, IOVEC_LEN(in_vec), out_vec,
+                      IOVEC_LEN(out_vec));
+
+    psa_close(handle);
+
+    if (status != PSA_SUCCESS) {
+        return PSA_PS_ERROR_OPERATION_FAILED;
+    }
+#else
     status = tfm_ns_lock_dispatch((veneer_fn)tfm_tfm_sst_remove_req_veneer,
                                   (uint32_t)in_vec,  IOVEC_LEN(in_vec),
                                   (uint32_t)out_vec, IOVEC_LEN(out_vec));
@@ -114,6 +200,7 @@
     if (status != PSA_SUCCESS) {
         return PSA_PS_ERROR_OPERATION_FAILED;
     }
+#endif
 
     return err;
 }
@@ -145,6 +232,9 @@
      * uninitialised value in case the secure function fails.
      */
     uint32_t support_flags = 0;
+#ifdef TFM_PSA_API
+    psa_handle_t handle;
+#endif
 
     psa_outvec out_vec[] = {
         { .base = &support_flags, .len = sizeof(support_flags) }
@@ -153,9 +243,20 @@
     /* The PSA API does not return an error, so any error from TF-M is
      * ignored.
      */
+#ifdef TFM_PSA_API
+    handle = psa_connect(TFM_SST_GET_SUPPORT_SID, TFM_SST_GET_SUPPORT_MIN_VER);
+    if (!TFM_PSA_HANDLE_IS_VALID(handle)) {
+        return support_flags;
+    }
+
+    (void)psa_call(handle, NULL, 0, out_vec, IOVEC_LEN(out_vec));
+
+    psa_close(handle);
+#else
     (void)tfm_ns_lock_dispatch((veneer_fn)tfm_tfm_sst_get_support_req_veneer,
                                (uint32_t)NULL,  0,
                                (uint32_t)out_vec, IOVEC_LEN(out_vec));
+#endif
 
     return support_flags;
 }
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 924de1f..0c1f01f 100644
--- a/secure_fw/core/ipc/include/tfm_spm_signal_defs.h
+++ b/secure_fw/core/ipc/include/tfm_spm_signal_defs.h
@@ -10,5 +10,6 @@
 #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/secure_storage/tfm_sst_signal.h"
 
 #endif
diff --git a/secure_fw/services/secure_storage/manifest.yaml b/secure_fw/services/secure_storage/manifest.yaml
index cc65894..86cefe0 100644
--- a/secure_fw/services/secure_storage/manifest.yaml
+++ b/secure_fw/services/secure_storage/manifest.yaml
@@ -10,9 +10,10 @@
   "type": "PSA-ROT",
   "priority": "NORMAL",
   "id": "0x00000100",
-  "entry_point": "tfm_sst_init",
+  "entry_point": "tfm_sst_req_mngr_init",
   "stack_size": "0x2000",
   "heap_size": "0x0400",
+  "tfm_partition_ipc": true,
   "secure_functions": [
     {
       "sfid": "TFM_SST_SET_SFID",
@@ -55,6 +56,47 @@
       "minor_policy": "strict"
     }
   ],
+  "services" : [{
+    "name": "TFM_SST_SET_SID",
+    "sid": "0x00002000",
+    "signal": "TFM_SST_SET_SIG",
+    "non_secure_clients": "true",
+    "minor_version": 1,
+    "minor_policy": "STRICT"
+   },
+   {
+    "name": "TFM_SST_GET_SID",
+    "sid": "0x00002001",
+    "signal": "TFM_SST_GET_SIG",
+    "non_secure_clients": "true",
+    "minor_version": 1,
+    "minor_policy": "STRICT"
+   },
+   {
+    "name": "TFM_SST_GET_INFO_SID",
+    "sid": "0x00002002",
+    "signal": "TFM_SST_GET_INFO_SIG",
+    "non_secure_clients": "true",
+    "minor_version": 1,
+    "minor_policy": "STRICT"
+   },
+   {
+    "name": "TFM_SST_REMOVE_SID",
+    "sid": "0x00002003",
+    "signal": "TFM_SST_REMOVE_SIG",
+    "non_secure_clients": "true",
+    "minor_version": 1,
+    "minor_policy": "STRICT"
+   },
+   {
+    "name": "TFM_SST_GET_SUPPORT_SID",
+    "sid": "0x00002004",
+    "signal": "TFM_SST_GET_SUPPORT_SIG",
+    "non_secure_clients": "true",
+    "minor_version": 1,
+    "minor_policy": "STRICT"
+   }
+  ],
   "source_files": [
     "sst_encrypted_object.c",
     "sst_object_system.c",
diff --git a/secure_fw/services/secure_storage/tfm_sst_req_mngr.c b/secure_fw/services/secure_storage/tfm_sst_req_mngr.c
index e00ab7c..8c7e577 100644
--- a/secure_fw/services/secure_storage/tfm_sst_req_mngr.c
+++ b/secure_fw/services/secure_storage/tfm_sst_req_mngr.c
@@ -10,6 +10,12 @@
 #include "secure_fw/core/tfm_secure_api.h"
 #include "tfm_api.h"
 #include "tfm_protected_storage.h"
+#ifdef TFM_PSA_API
+#include "psa_client.h"
+#include "psa_service.h"
+#include "tfm_sst_signal.h"
+#include "flash_layout.h"
+#endif
 
 psa_status_t tfm_sst_set_req(struct psa_invec *in_vec, size_t in_len,
                              struct psa_outvec *out_vec, size_t out_len)
@@ -219,3 +225,232 @@
 
     return PSA_SUCCESS;
 }
+
+#ifdef TFM_PSA_API
+typedef psa_status_t (*sst_func_t)(const psa_msg_t *msg);
+static uint8_t asset_data[SST_MAX_ASSET_SIZE] = {0};
+
+static psa_status_t tfm_sst_set_ipc(const psa_msg_t *msg)
+{
+    psa_ps_uid_t uid;
+    int32_t client_id;
+    psa_ps_create_flags_t create_flags;
+    size_t in_size[3], out_size, num = 0;
+    psa_ps_status_t err;
+
+    client_id = msg->client_id;
+    in_size[0] = msg->in_size[0];
+    in_size[1] = msg->in_size[1];
+    in_size[2] = msg->in_size[2];
+    out_size = msg->out_size[0];
+    if (in_size[0] != sizeof(psa_ps_uid_t) ||
+        in_size[2] != sizeof(psa_ps_create_flags_t) ||
+        out_size != sizeof(psa_ps_status_t)) {
+        /* The size of one of the arguments is incorrect */
+        return PSA_PS_ERROR_INVALID_ARGUMENT;
+    }
+
+    num = psa_read(msg->handle, 0, &uid, in_size[0]);
+    if (num != in_size[0]) {
+        return PSA_PS_ERROR_INVALID_ARGUMENT;
+    }
+
+    if (in_size[1] > SST_MAX_ASSET_SIZE) {
+        num = psa_read(msg->handle, 1, &asset_data, SST_MAX_ASSET_SIZE);
+        if (num != SST_MAX_ASSET_SIZE) {
+            return PSA_PS_ERROR_INVALID_ARGUMENT;
+        }
+    } else {
+        num = psa_read(msg->handle, 1, &asset_data, in_size[1]);
+        if (num != in_size[1]) {
+            return PSA_PS_ERROR_INVALID_ARGUMENT;
+        }
+    }
+
+    num = psa_read(msg->handle, 2, &create_flags, in_size[2]);
+    if (num != in_size[2]) {
+        return PSA_PS_ERROR_INVALID_ARGUMENT;
+    }
+
+    err = tfm_sst_set(client_id, uid, in_size[1], asset_data, create_flags);
+    psa_write(msg->handle, 0, &err, out_size);
+    return PSA_SUCCESS;
+}
+
+static psa_status_t tfm_sst_get_ipc(const psa_msg_t *msg)
+{
+    psa_ps_uid_t uid;
+    int32_t client_id;
+    uint32_t data_offset;
+    size_t in_size[2], out_size[2], num = 0;
+    psa_ps_status_t err;
+
+    client_id = msg->client_id;
+    in_size[0] = msg->in_size[0];
+    in_size[1] = msg->in_size[1];
+    out_size[0] = msg->out_size[0];
+    out_size[1] = msg->out_size[1];
+    if (in_size[0] != sizeof(psa_ps_uid_t) ||
+        in_size[1] != sizeof(uint32_t) ||
+        out_size[0] != sizeof(psa_ps_status_t)) {
+        /* The size of one of the arguments is incorrect */
+        return PSA_PS_ERROR_INVALID_ARGUMENT;
+    }
+
+    num = psa_read(msg->handle, 0, &uid, in_size[0]);
+    if (num != in_size[0]) {
+        return PSA_PS_ERROR_INVALID_ARGUMENT;
+    }
+
+    num = psa_read(msg->handle, 1, &data_offset, in_size[1]);
+    if (num != in_size[1]) {
+        return PSA_PS_ERROR_INVALID_ARGUMENT;
+    }
+
+    err = tfm_sst_get(client_id, uid, data_offset, out_size[1], asset_data);
+    psa_write(msg->handle, 0, &err, out_size[0]);
+    if (err == PSA_PS_SUCCESS) {
+        psa_write(msg->handle, 1, asset_data, out_size[1]);
+    }
+    return PSA_SUCCESS;
+}
+
+static psa_status_t tfm_sst_get_info_ipc(const psa_msg_t *msg)
+{
+    psa_ps_uid_t uid;
+    int32_t client_id;
+    struct psa_ps_info_t info;
+    size_t in_size, out_size[2], num = 0;
+    psa_ps_status_t err;
+
+    client_id = msg->client_id;
+    in_size = msg->in_size[0];
+    out_size[0] = msg->out_size[0];
+    out_size[1] = msg->out_size[1];
+    if (in_size != sizeof(psa_ps_uid_t) ||
+        out_size[0] != sizeof(psa_ps_status_t) ||
+        out_size[1] != sizeof(struct psa_ps_info_t)) {
+        /* The size of one of the arguments is incorrect */
+        return PSA_PS_ERROR_INVALID_ARGUMENT;
+    }
+
+    num = psa_read(msg->handle, 0, &uid, in_size);
+    if (num != in_size) {
+        return PSA_PS_ERROR_INVALID_ARGUMENT;
+    }
+
+    err = tfm_sst_get_info(client_id, uid, &info);
+    psa_write(msg->handle, 0, &err, out_size[0]);
+    if (err == PSA_PS_SUCCESS) {
+        psa_write(msg->handle, 1, &info, out_size[1]);
+    }
+    return PSA_SUCCESS;
+}
+
+static psa_status_t tfm_sst_remove_ipc(const psa_msg_t *msg)
+{
+    psa_ps_uid_t uid;
+    int32_t client_id;
+    size_t in_size, out_size, num = 0;
+    psa_ps_status_t err;
+
+    client_id = msg->client_id;
+    in_size = msg->in_size[0];
+    out_size = msg->out_size[0];
+    if (in_size != sizeof(psa_ps_uid_t) ||
+        out_size != sizeof(psa_ps_status_t)) {
+        /* The size of one of the arguments is incorrect */
+        return PSA_PS_ERROR_INVALID_ARGUMENT;
+    }
+
+    num = psa_read(msg->handle, 0, &uid, in_size);
+    if (num != in_size) {
+        return PSA_PS_ERROR_INVALID_ARGUMENT;
+    }
+
+    err = tfm_sst_remove(client_id, uid);
+    psa_write(msg->handle, 0, &err, out_size);
+    return PSA_SUCCESS;
+}
+
+static psa_status_t tfm_sst_get_support_ipc(const psa_msg_t *msg)
+{
+    size_t out_size;
+    uint32_t support_flags;
+
+    out_size = msg->out_size[0];
+    if (out_size != sizeof(support_flags)) {
+        /* The output argument size is incorrect */
+        return PSA_PS_ERROR_INVALID_ARGUMENT;
+    }
+
+    support_flags = tfm_sst_get_support();
+    psa_write(msg->handle, 0, &support_flags, out_size);
+    return PSA_SUCCESS;
+}
+
+/*
+ * Fixme: Temporarily implement abort as infinite loop,
+ * will replace it later.
+ */
+static void tfm_abort(void)
+{
+    while (1)
+        ;
+}
+
+static void ps_signal_handle(psa_signal_t signal, sst_func_t pfn)
+{
+    psa_msg_t msg;
+    psa_status_t status;
+
+    status = psa_get(signal, &msg);
+    switch (msg.type) {
+    case PSA_IPC_CONNECT:
+        psa_reply(msg.handle, PSA_SUCCESS);
+        break;
+    case PSA_IPC_CALL:
+        status = pfn(&msg);
+        psa_reply(msg.handle, status);
+        break;
+    case PSA_IPC_DISCONNECT:
+        psa_reply(msg.handle, PSA_SUCCESS);
+        break;
+    default:
+        tfm_abort();
+    }
+}
+#endif /* TFM_PSA_API */
+
+psa_ps_status_t tfm_sst_req_mngr_init(void)
+{
+    psa_ps_status_t err;
+#ifdef TFM_PSA_API
+    psa_signal_t signals = 0;
+#endif
+
+    err = tfm_sst_init();
+    if (err != PSA_PS_SUCCESS) {
+        return err;
+    }
+
+#ifdef TFM_PSA_API
+    while (1) {
+        signals = psa_wait(PSA_WAIT_ANY, PSA_BLOCK);
+        if (signals & TFM_SST_SET_SIG) {
+            ps_signal_handle(TFM_SST_SET_SIG, tfm_sst_set_ipc);
+        } else if (signals & TFM_SST_GET_SIG) {
+            ps_signal_handle(TFM_SST_GET_SIG, tfm_sst_get_ipc);
+        } else if (signals & TFM_SST_GET_INFO_SIG) {
+            ps_signal_handle(TFM_SST_GET_INFO_SIG, tfm_sst_get_info_ipc);
+        } else if (signals & TFM_SST_REMOVE_SIG) {
+            ps_signal_handle(TFM_SST_REMOVE_SIG, tfm_sst_remove_ipc);
+        } else if (signals & TFM_SST_GET_SUPPORT_SIG) {
+            ps_signal_handle(TFM_SST_GET_SUPPORT_SIG, tfm_sst_get_support_ipc);
+        } else {
+            tfm_abort();
+        }
+    }
+#endif
+    return err;
+}
diff --git a/secure_fw/services/secure_storage/tfm_sst_secure_api.c b/secure_fw/services/secure_storage/tfm_sst_secure_api.c
index 905767e..d38bc5f 100644
--- a/secure_fw/services/secure_storage/tfm_sst_secure_api.c
+++ b/secure_fw/services/secure_storage/tfm_sst_secure_api.c
@@ -7,8 +7,11 @@
 
 #include "psa_protected_storage.h"
 #include "tfm_veneers.h"
+#include "tfm_sst_defs.h"
 
 #define IOVEC_LEN(x) (sizeof(x)/sizeof(x[0]))
+/* FixMe: Check if PSA framework header would provide similar macro. */
+#define TFM_PSA_HANDLE_IS_VALID(handle)  ((handle) > (psa_handle_t)0)
 
 __attribute__((section("SFN")))
 psa_ps_status_t psa_ps_set(psa_ps_uid_t uid,
@@ -18,6 +21,9 @@
 {
     psa_status_t status;
     psa_ps_status_t err;
+#ifdef TFM_PSA_API
+    psa_handle_t handle;
+#endif
 
     psa_invec in_vec[] = {
         { .base = &uid,   .len = sizeof(uid) },
@@ -29,11 +35,31 @@
         { .base = &err , .len = sizeof(err) }
     };
 
+#ifdef TFM_PSA_API
+    if (p_data == NULL) {
+        return PSA_PS_ERROR_INVALID_ARGUMENT;
+    }
+
+    handle = psa_connect(TFM_SST_SET_SID, TFM_SST_SET_MIN_VER);
+    if (!TFM_PSA_HANDLE_IS_VALID(handle)) {
+        return PSA_PS_ERROR_OPERATION_FAILED;
+    }
+
+    status = psa_call(handle, in_vec, IOVEC_LEN(in_vec), out_vec,
+                      IOVEC_LEN(out_vec));
+
+    psa_close(handle);
+
+    if (status != PSA_SUCCESS) {
+        return PSA_PS_ERROR_OPERATION_FAILED;
+    }
+#else
     status = tfm_tfm_sst_set_req_veneer(in_vec, IOVEC_LEN(in_vec),
                                         out_vec, IOVEC_LEN(out_vec));
     if (status != PSA_SUCCESS) {
         return PSA_PS_ERROR_OPERATION_FAILED;
     }
+#endif
 
     return err;
 }
@@ -46,6 +72,9 @@
 {
     psa_status_t status;
     psa_ps_status_t err;
+#ifdef TFM_PSA_API
+    psa_handle_t handle;
+#endif
 
     psa_invec in_vec[] = {
         { .base = &uid, .len = sizeof(uid) },
@@ -57,11 +86,31 @@
         { .base = p_data, .len = data_length }
     };
 
+#ifdef TFM_PSA_API
+    if (p_data == NULL) {
+        return PSA_PS_ERROR_INVALID_ARGUMENT;
+    }
+
+    handle = psa_connect(TFM_SST_GET_SID, TFM_SST_GET_MIN_VER);
+    if (!TFM_PSA_HANDLE_IS_VALID(handle)) {
+        return PSA_PS_ERROR_OPERATION_FAILED;
+    }
+
+    status = psa_call(handle, in_vec, IOVEC_LEN(in_vec), out_vec,
+                      IOVEC_LEN(out_vec));
+
+    psa_close(handle);
+
+    if (status != PSA_SUCCESS) {
+        return PSA_PS_ERROR_OPERATION_FAILED;
+    }
+#else
     status = tfm_tfm_sst_get_req_veneer(in_vec, IOVEC_LEN(in_vec),
                                         out_vec, IOVEC_LEN(out_vec));
     if (status != PSA_SUCCESS) {
         return PSA_PS_ERROR_OPERATION_FAILED;
     }
+#endif
 
     return err;
 }
@@ -71,6 +120,9 @@
 {
     psa_status_t status;
     psa_ps_status_t err;
+#ifdef TFM_PSA_API
+    psa_handle_t handle;
+#endif
 
     psa_invec in_vec[] = {
         { .base = &uid, .len = sizeof(uid) }
@@ -81,12 +133,28 @@
         { .base = p_info, .len = sizeof(*p_info) }
     };
 
+#ifdef TFM_PSA_API
+    handle = psa_connect(TFM_SST_GET_INFO_SID, TFM_SST_GET_INFO_MIN_VER);
+    if (!TFM_PSA_HANDLE_IS_VALID(handle)) {
+        return PSA_PS_ERROR_OPERATION_FAILED;
+    }
+
+    status = psa_call(handle, in_vec, IOVEC_LEN(in_vec), out_vec,
+                      IOVEC_LEN(out_vec));
+
+    psa_close(handle);
+
+    if (status != PSA_SUCCESS) {
+        return PSA_PS_ERROR_OPERATION_FAILED;
+    }
+#else
     status = tfm_tfm_sst_get_info_req_veneer(in_vec, IOVEC_LEN(in_vec),
                                              out_vec, IOVEC_LEN(out_vec));
 
     if (status != PSA_SUCCESS) {
         return PSA_PS_ERROR_OPERATION_FAILED;
     }
+#endif
 
     return err;
 }
@@ -96,6 +164,9 @@
 {
     psa_status_t status;
     psa_ps_status_t err;
+#ifdef TFM_PSA_API
+    psa_handle_t handle;
+#endif
 
     psa_invec in_vec[] = {
         { .base = &uid, .len = sizeof(uid) }
@@ -105,12 +176,28 @@
         { .base = &err, .len = sizeof(err) }
     };
 
+#ifdef TFM_PSA_API
+    handle = psa_connect(TFM_SST_REMOVE_SID, TFM_SST_REMOVE_MIN_VER);
+    if (!TFM_PSA_HANDLE_IS_VALID(handle)) {
+        return PSA_PS_ERROR_OPERATION_FAILED;
+    }
+
+    status = psa_call(handle, in_vec, IOVEC_LEN(in_vec), out_vec,
+                      IOVEC_LEN(out_vec));
+
+    psa_close(handle);
+
+    if (status != PSA_SUCCESS) {
+        return PSA_PS_ERROR_OPERATION_FAILED;
+    }
+#else
     status = tfm_tfm_sst_remove_req_veneer(in_vec, IOVEC_LEN(in_vec),
                                            out_vec, IOVEC_LEN(out_vec));
 
     if (status != PSA_SUCCESS) {
         return PSA_PS_ERROR_OPERATION_FAILED;
     }
+#endif
 
     return err;
 }
@@ -145,6 +232,9 @@
      * uninitialised value in case the secure function fails.
      */
     uint32_t support_flags = 0;
+#ifdef TFM_PSA_API
+    psa_handle_t handle;
+#endif
 
     psa_outvec out_vec[] = {
         { .base = &support_flags, .len = sizeof(support_flags) }
@@ -153,8 +243,19 @@
     /* The PSA API does not return an error, so any error from TF-M is
      * ignored.
      */
+#ifdef TFM_PSA_API
+    handle = psa_connect(TFM_SST_GET_SUPPORT_SID, TFM_SST_GET_SUPPORT_MIN_VER);
+    if (!TFM_PSA_HANDLE_IS_VALID(handle)) {
+        return support_flags;
+    }
+
+    (void)psa_call(handle, NULL, 0, out_vec, IOVEC_LEN(out_vec));
+
+    psa_close(handle);
+#else
     (void)tfm_tfm_sst_get_support_req_veneer(NULL, 0,
                                              out_vec, IOVEC_LEN(out_vec));
+#endif
 
     return support_flags;
 }
diff --git a/secure_fw/services/secure_storage/tfm_sst_signal.h b/secure_fw/services/secure_storage/tfm_sst_signal.h
new file mode 100644
index 0000000..3e7eb1b
--- /dev/null
+++ b/secure_fw/services/secure_storage/tfm_sst_signal.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2019, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef __TFM_SST_SIGNAL_H__
+#define __TFM_SST_SIGNAL_H__
+
+/*
+ * FixMe: hardcode it now, will add support to autogenerate these signal
+ * definitons later.
+ */
+/*
+ * Each Secure Partition has up to 32 different signals. A signal is represented
+ * as a single-bit value within a 32-bit integer.
+ * The following signals are reserved in all Secure Partitions:
+ *  - 0x00000001U
+ *  - 0x00000002U
+ *  - 0x00000004U
+ *  - 0x00000008U
+ * The remaining 28 general signals can be associated with other inputs to the
+ * Secure Partition.
+ */
+#define TFM_SST_SET_SIG         (1 << (0 + 4))
+#define TFM_SST_GET_SIG         (1 << (1 + 4))
+#define TFM_SST_GET_INFO_SIG    (1 << (2 + 4))
+#define TFM_SST_REMOVE_SIG      (1 << (3 + 4))
+#define TFM_SST_GET_SUPPORT_SIG (1 << (4 + 4))
+
+#endif /* __TFM_SST_SIGNAL_H__ */
diff --git a/secure_fw/services/tfm_partition_list.inc b/secure_fw/services/tfm_partition_list.inc
index 72da66f..228336b 100644
--- a/secure_fw/services/tfm_partition_list.inc
+++ b/secure_fw/services/tfm_partition_list.inc
@@ -12,8 +12,9 @@
 
 /******** TFM_SP_STORAGE ********/
 PARTITION_DECLARE(TFM_SP_STORAGE, 0
+    | SPM_PART_FLAG_IPC
     , "PSA-ROT", 0x00000100, NORMAL);
-PARTITION_ADD_INIT_FUNC(TFM_SP_STORAGE, tfm_sst_init);
+PARTITION_ADD_INIT_FUNC(TFM_SP_STORAGE, tfm_sst_req_mngr_init);
 
 /******** TFM_SP_AUDIT_LOG ********/
 PARTITION_DECLARE(TFM_SP_AUDIT_LOG, 0
diff --git a/secure_fw/services/tfm_service_list.inc b/secure_fw/services/tfm_service_list.inc
index 696724b..1486c76 100644
--- a/secure_fw/services/tfm_service_list.inc
+++ b/secure_fw/services/tfm_service_list.inc
@@ -11,6 +11,11 @@
 #define __TFM_SERVICE_LIST_INC__
 
 /******** TFM_SP_STORAGE ********/
+{"TFM_SST_SET_SID", TFM_SP_STORAGE_ID, TFM_SST_SET_SIG, 0x00002000, true, 1, TFM_VERSION_POLICY_STRICT},
+{"TFM_SST_GET_SID", TFM_SP_STORAGE_ID, TFM_SST_GET_SIG, 0x00002001, true, 1, TFM_VERSION_POLICY_STRICT},
+{"TFM_SST_GET_INFO_SID", TFM_SP_STORAGE_ID, TFM_SST_GET_INFO_SIG, 0x00002002, true, 1, TFM_VERSION_POLICY_STRICT},
+{"TFM_SST_REMOVE_SID", TFM_SP_STORAGE_ID, TFM_SST_REMOVE_SIG, 0x00002003, true, 1, TFM_VERSION_POLICY_STRICT},
+{"TFM_SST_GET_SUPPORT_SID", TFM_SP_STORAGE_ID, TFM_SST_GET_SUPPORT_SIG, 0x00002004, true, 1, TFM_VERSION_POLICY_STRICT},
 
 /******** TFM_SP_AUDIT_LOG ********/
 
diff --git a/secure_fw/spm/spm_db.h b/secure_fw/spm/spm_db.h
index 6b28f94..7bfaa3c 100644
--- a/secure_fw/spm/spm_db.h
+++ b/secure_fw/spm/spm_db.h
@@ -21,7 +21,7 @@
 #define TFM_PARTITION_TYPE_APP   "APPLICATION-ROT"
 #define TFM_PARTITION_TYPE_PSA   "PSA-ROT"
 
-#define TFM_STACK_SIZE  1024
+#define TFM_STACK_SIZE           (1024 * 5)
 
 #ifdef TFM_PSA_API
 enum tfm_partition_priority {
diff --git a/test/suites/sst/secure/psa_ps_s_interface_testsuite.c b/test/suites/sst/secure/psa_ps_s_interface_testsuite.c
index 4993604..d8950eb 100644
--- a/test/suites/sst/secure/psa_ps_s_interface_testsuite.c
+++ b/test/suites/sst/secure/psa_ps_s_interface_testsuite.c
@@ -227,6 +227,7 @@
  */
 static void tfm_sst_test_2003(struct test_result_t *ret)
 {
+#ifndef TFM_PSA_API
     psa_ps_status_t status;
     const psa_ps_uid_t uid = TEST_UID_3;
     const psa_ps_create_flags_t flags = PSA_PS_FLAG_NONE;
@@ -245,6 +246,7 @@
         return;
     }
 
+#endif
     ret->val = TEST_PASSED;
 }
 
@@ -254,6 +256,7 @@
  */
 static void tfm_sst_test_2004(struct test_result_t *ret)
 {
+#ifndef TFM_PSA_API
     psa_ps_status_t status;
     const psa_ps_uid_t uid = TEST_UID_1;
     const psa_ps_create_flags_t flags = PSA_PS_FLAG_NONE;
@@ -274,6 +277,7 @@
         return;
     }
 
+#endif
     ret->val = TEST_PASSED;
 }
 
@@ -570,6 +574,7 @@
         return;
     }
 
+#ifndef TFM_PSA_API
     /* Get with data length and offset set to invalid values */
     read_len = INVALID_DATA_LEN;
     offset = INVALID_OFFSET;
@@ -592,6 +597,7 @@
         TEST_FAIL("Read data should be equal to original read data");
         return;
     }
+#endif
 
     /* Call remove to clean up storage for the next test */
     status = psa_ps_remove(uid);
@@ -613,7 +619,9 @@
     const psa_ps_uid_t uid = TEST_UID_3;
     const psa_ps_create_flags_t flags = PSA_PS_FLAG_NONE;
     const uint32_t data_len = WRITE_DATA_SIZE;
+#ifndef TFM_PSA_API
     const uint32_t offset = 0;
+#endif
     uint8_t write_data[] = WRITE_DATA;
 
     status = psa_ps_set(uid, data_len, write_data, flags);
@@ -629,11 +637,13 @@
      */
 
     /* Get with NULL data pointer */
+#ifndef TFM_PSA_API
     status = psa_ps_get(uid, offset, data_len, NULL);
     if (status != PSA_PS_ERROR_OPERATION_FAILED) {
         TEST_FAIL("Get should not succeed with NULL data pointer");
         return;
     }
+#endif
 
     /* Call remove to clean up storage for the next test */
     status = psa_ps_remove(uid);
@@ -798,11 +808,13 @@
      */
 
     /* Get info with NULL info pointer */
+#ifndef TFM_PSA_API
     status = psa_ps_get_info(uid, NULL);
     if (status != PSA_PS_ERROR_OPERATION_FAILED) {
         TEST_FAIL("Get info should not succeed with NULL info pointer");
         return;
     }
+#endif
 
     /* Call remove to clean up storage for the next test */
     status = psa_ps_remove(uid);