Extend storage components for PSA PS

The secure-storage access protocol and storage backend interface are
extended to support additional API operations for PSA Protected
Storage.  A new psa ps storage front end is added that allows
clients to use the standard ps API to access secure storage.
Component test cases are extended to cover the extra API
operations.  Tests are now applied to different frontend/
backend combinations, including an intermediate proxy.

Signed-off-by: Julian Hall <julian.hall@arm.com>
Change-Id: Ic29f74274baceb73fb7b88a636f319c0980de6a7
diff --git a/components/service/common/psa/protected_storage.h b/components/service/common/psa/protected_storage.h
new file mode 100644
index 0000000..ff827b1
--- /dev/null
+++ b/components/service/common/psa/protected_storage.h
@@ -0,0 +1,282 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+/* This file describes the PSA Protected Storage API */
+
+#ifndef PROTECTED_STORAGE_H
+#define PROTECTED_STORAGE_H
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include "psa/error.h"
+#include "psa/storage_common.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief PSA_PS_API_VERSION version
+ *
+ * Major and minor PSA_PS_API_VERSION numbers
+ */
+#define PSA_PS_API_VERSION_MAJOR  1
+#define PSA_PS_API_VERSION_MINOR  0
+
+// This version of the header file is associated with 1.0 final release
+
+/**
+ * \brief Create a new, or modify an existing, uid/value pair
+ *
+ * Stores data in the protected storage.
+ *
+ * \param[in] uid           The identifier for the data
+ * \param[in] data_length   The size in bytes of the data in `p_data`
+ * \param[in] p_data        A buffer containing the data
+ * \param[in] create_flags  The flags that the data will be stored with
+ *
+ * \return A status indicating the success/failure of the operation
+ *
+ * \retval PSA_SUCCESS                     The operation completed successfully
+ * \retval PSA_ERROR_NOT_PERMITTED         The operation failed because the
+ *                                         provided `uid` value was already
+ *                                         created with
+ *                                         PSA_STORAGE_FLAG_WRITE_ONCE
+ * \retval PSA_ERROR_INVALID_ARGUMENT      The operation failed because one
+ *                                         of the provided pointers(`p_data`)
+ *                                         is invalid, for example is `NULL` or
+ *                                         references memory the caller cannot
+ *                                         access
+ * \retval PSA_ERROR_NOT_SUPPORTED         The operation failed because one or
+ *                                         more of the flags provided in
+ *                                         `create_flags` is not supported or is
+ *                                         not valid
+ * \retval PSA_ERROR_INSUFFICIENT_STORAGE  The operation failed because there
+ *                                         was insufficient space on the
+ *                                         storage medium
+ * \retval PSA_ERROR_STORAGE_FAILURE       The operation failed because the
+ *                                         physical storage has failed (Fatal
+ *                                         error)
+ * \retval PSA_ERROR_GENERIC_ERROR         The operation failed because of an
+ *                                         unspecified internal failure
+ */
+psa_status_t psa_ps_set(psa_storage_uid_t uid,
+						size_t data_length,
+						const void *p_data,
+						psa_storage_create_flags_t create_flags);
+
+/**
+ * \brief Retrieve data associated with a provided uid
+ *
+ * Retrieves up to `data_size` bytes of the data associated with `uid`, starting
+ * at `data_offset` bytes from the beginning of the data. Upon successful
+ * completion, the data will be placed in the `p_data` buffer, which must be at
+ * least `data_size` bytes in size. The length of the data returned will be in
+ * `p_data_length`. If `data_size` is 0, the contents of `p_data_length` will
+ * be set to zero.
+ *
+ * \param[in]  uid            The uid value
+ * \param[in]  data_offset    The starting offset of the data requested
+ * \param[in]  data_size      The amount of data requested
+ * \param[out] p_data         On success, the buffer where the data will
+ *                            be placed
+ * \param[out] p_data_length  On success, this will contain size of the data
+ *                            placed in `p_data`
+ *
+ * \return A status indicating the success/failure of the operation
+ *
+ * \retval PSA_SUCCESS                 The operation completed successfully
+ * \retval PSA_ERROR_INVALID_ARGUMENT  The operation failed because one of the
+ *                                     provided arguments (`p_data`,
+ *                                     `p_data_length`) is invalid, for example
+ *                                     is `NULL` or references memory the
+ *                                     caller cannot access. In addition, this
+ *                                     can also happen if `data_offset` is
+ *                                     larger than the size of the data
+ *                                     associated with `uid`
+ * \retval PSA_ERROR_DOES_NOT_EXIST    The operation failed because the
+ *                                     provided `uid` value was not found in
+ *                                     the storage
+ * \retval PSA_ERROR_STORAGE_FAILURE   The operation failed because the
+ *                                     physical storage has failed (Fatal
+ *                                     error)
+ * \retval PSA_ERROR_GENERIC_ERROR     The operation failed because of an
+ *                                     unspecified internal failure
+ * \retval PSA_ERROR_DATA_CORRUPT      The operation failed because the data
+ *                                     associated with the UID was corrupt
+ * \retval PSA_ERROR_INVALID_SIGNATURE The operation failed because the data
+ *                                     associated with the UID failed
+ *                                     authentication
+ */
+psa_status_t psa_ps_get(psa_storage_uid_t uid,
+						size_t data_offset,
+						size_t data_size,
+						void *p_data,
+						size_t *p_data_length);
+
+/**
+ * \brief Retrieve the metadata about the provided uid
+ *
+ * Retrieves the metadata stored for a given `uid`
+ *
+ * \param[in]  uid     The `uid` value
+ * \param[out] p_info  A pointer to the `psa_storage_info_t` struct that will
+ *                     be populated with the metadata
+ *
+ * \return A status indicating the success/failure of the operation
+ *
+ * \retval PSA_SUCCESS                 The operation completed successfully
+ * \retval PSA_ERROR_INVALID_ARGUMENT  The operation failed because one of the
+ *                                     provided pointers(`p_info`)
+ *                                     is invalid, for example is `NULL` or
+ *                                     references memory the caller cannot
+ *                                     access
+ * \retval PSA_ERROR_DOES_NOT_EXIST    The operation failed because the provided
+ *                                     uid value was not found in the storage
+ * \retval PSA_ERROR_STORAGE_FAILURE   The operation failed because the physical
+ *                                     storage has failed (Fatal error)
+ * \retval PSA_ERROR_GENERIC_ERROR     The operation failed because of an
+ *                                     unspecified internal failure
+ * \retval PSA_ERROR_DATA_CORRUPT      The operation failed because the data
+ *                                     associated with the UID was corrupt
+ */
+psa_status_t psa_ps_get_info(psa_storage_uid_t uid,
+							 struct psa_storage_info_t *p_info);
+
+/**
+ * \brief Remove the provided uid and its associated data from the storage
+ *
+ * Removes previously stored data and any associated metadata,
+ * including rollback protection data.
+ *
+ * \param[in] uid  The `uid` value
+ *
+ * \return A status indicating the success/failure of the operation
+ *
+ * \retval PSA_SUCCESS                 The operation completed successfully
+ * \retval PSA_ERROR_INVALID_ARGUMENT  The operation failed because one or more
+ *                                     of the given arguments were invalid (null
+ *                                     pointer, wrong flags and so on)
+ * \retval PSA_ERROR_DOES_NOT_EXIST    The operation failed because the provided
+ *                                     uid value was not found in the storage
+ * \retval PSA_ERROR_NOT_PERMITTED     The operation failed because the provided
+ *                                     uid value was created with
+ *                                     PSA_STORAGE_FLAG_WRITE_ONCE
+ * \retval PSA_ERROR_STORAGE_FAILURE   The operation failed because the physical
+ *                                     storage has failed (Fatal error)
+ * \retval PSA_ERROR_GENERIC_ERROR     The operation failed because of an
+ *                                     unspecified internal failure
+ */
+psa_status_t psa_ps_remove(psa_storage_uid_t uid);
+
+/**
+ * \brief Reserves storage for the specified uid
+ *
+ * Upon success, the capacity of the storage will be capacity, and the size
+ * will be 0. It is only necessary to call this function for assets that will
+ * be written with the psa_ps_set_extended function. If only the psa_ps_set
+ * function is needed, calls to this function are redundant.
+ *
+ * \param[in] uid           The `uid` value
+ * \param[in] capacity      The capacity to be allocated in bytes
+ * \param[in] create_flags  Flags indicating properties of storage
+ *
+ * \return A status indicating the success/failure of the operation
+ *
+ * \retval PSA_SUCCESS                     The operation completed successfully
+ * \retval PSA_ERROR_STORAGE_FAILURE       The operation failed because the
+ *                                         physical storage has failed
+ *                                         (Fatal error)
+ * \retval PSA_ERROR_INSUFFICIENT_STORAGE  The operation failed because the
+ *                                         capacity is bigger than the current
+ *                                         available space
+ * \retval PSA_ERROR_NOT_SUPPORTED         The operation failed because the
+ *                                         function is not implemented or one
+ *                                         or more create_flags are not
+ *                                         supported.
+ * \retval PSA_ERROR_INVALID_ARGUMENT      The operation failed because uid was
+ *                                         0 or create_flags specified flags
+ *                                         that are not defined in the API.
+ * \retval PSA_ERROR_GENERIC_ERROR         The operation failed due to an
+ *                                         unspecified error
+ * \retval PSA_ERROR_ALREADY_EXISTS        Storage for the specified uid
+ *                                         already exists
+ */
+psa_status_t psa_ps_create(psa_storage_uid_t uid,
+						   size_t capacity,
+						   psa_storage_create_flags_t create_flags);
+
+/**
+ * \brief Sets partial data into an asset
+ *
+ * Before calling this function, the storage must have been reserved with a call
+ * to psa_ps_create. It can also be used to overwrite data in an asset that was
+ * created with a call to psa_ps_set. Calling this function with data_length = 0
+ * is permitted, which will make no change to the stored data.This function can
+ * overwrite existing data and/or extend it up to the capacity for the uid
+ * specified in psa_ps_create, but cannot create gaps.
+ *
+ * That is, it has preconditions:
+ * - data_offset <= size
+ * - data_offset + data_length <= capacity
+ * and postconditions:
+ * - size = max(size, data_offset + data_length)
+ * - capacity unchanged.
+ *
+ * \param[in] uid          The `uid` value
+ * \param[in] data_offset  Offset within the asset to start the write
+ * \param[in] data_length  The size in bytes of the data in p_data to write
+ * \param[in] p_data       Pointer to a buffer which contains the data to write
+ *
+ * \return A status indicating the success/failure of the operation
+ *
+ * \retval PSA_SUCCESS                  The asset exists, the input parameters
+ *                                      are correct and the data is correctly
+ *                                      written in the physical storage.
+ * \retval PSA_ERROR_STORAGE_FAILURE    The data was not written correctly in
+ *                                      the physical storage
+ * \retval PSA_ERROR_INVALID_ARGUMENT   The operation failed because one or more
+ *                                      of the preconditions listed above
+ *                                      regarding data_offset, size, or
+ *                                      data_length was violated.
+ * \retval PSA_ERROR_DOES_NOT_EXIST     The specified uid was not found
+ * \retval PSA_ERROR_NOT_SUPPORTED      The implementation of the API does not
+ *                                      support this function
+ * \retval PSA_ERROR_GENERIC_ERROR      The operation failed due to an
+ *                                      unspecified error
+ * \retval PSA_ERROR_DATA_CORRUPT       The operation failed because the
+ *                                      existing data has been corrupted.
+ * \retval PSA_ERROR_INVALID_SIGNATURE  The operation failed because the
+ *                                      existing data failed authentication
+ *                                      (MAC check failed).
+ * \retval PSA_ERROR_NOT_PERMITTED      The operation failed because it was
+ *                                      attempted on an asset which was written
+ *                                      with the flag
+ *                                      PSA_STORAGE_FLAG_WRITE_ONCE
+ */
+psa_status_t psa_ps_set_extended(psa_storage_uid_t uid,
+								 size_t data_offset,
+								 size_t data_length,
+								 const void *p_data);
+
+/**
+ * \brief Lists optional features.
+ *
+ * \return                              A bitmask with flags set for all of
+ *                                      the optional features supported by the
+ *                                      implementation.Currently defined flags
+ *                                      are limited to
+ *                                      PSA_STORAGE_SUPPORT_SET_EXTENDED
+ */
+uint32_t psa_ps_get_support(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* PROTECTED_STORAGE_H */
diff --git a/components/service/secure_storage/backend/mock_store/mock_store.c b/components/service/secure_storage/backend/mock_store/mock_store.c
index a3a2d94..f701e01 100644
--- a/components/service/secure_storage/backend/mock_store/mock_store.c
+++ b/components/service/secure_storage/backend/mock_store/mock_store.c
@@ -9,7 +9,7 @@
 #include <stdlib.h>
 #include <string.h>
 
-static struct mock_store_slot *find_slot(struct mock_store *context, uint32_t id);
+static struct mock_store_slot *find_slot(struct mock_store *context, uint64_t uid);
 static struct mock_store_slot *find_empty_slot(struct mock_store *context);
 static void free_slot(struct mock_store_slot *slot);
 
@@ -21,20 +21,27 @@
                             const void *p_data,
                             uint32_t create_flags)
 {
-    psa_status_t psa_status = PSA_ERROR_INSUFFICIENT_MEMORY;
+    psa_status_t psa_status = PSA_ERROR_INSUFFICIENT_STORAGE;
     struct mock_store *this_context = (struct mock_store*)context;
 
+    /* Check length limit */
+    if (data_length > MOCK_STORE_ITEM_SIZE_LIMIT) return psa_status;
+
     /* Replace existing or add new item */
     struct mock_store_slot *slot = find_slot(this_context, uid);
     if (slot) free_slot(slot);
     else slot = find_empty_slot(this_context);
 
     if (slot) {
-        slot->id = uid;
-        slot->flags = create_flags;
-        slot->len = data_length;
-        slot->item = malloc(slot->len);
+
+        slot->item = malloc(data_length);
+
         if (slot->item) {
+
+            slot->uid = uid;
+            slot->flags = create_flags;
+            slot->len = slot->capacity = data_length;
+
             memcpy(slot->item, p_data, slot->len);
             psa_status = PSA_SUCCESS;
         }
@@ -110,13 +117,96 @@
     return psa_status;
 }
 
+static psa_status_t mock_store_create(void *context,
+                            uint32_t client_id,
+                            uint64_t uid,
+                            size_t capacity,
+                            uint32_t create_flags)
+{
+    psa_status_t psa_status = PSA_ERROR_ALREADY_EXISTS;
+    struct mock_store *this_context = (struct mock_store*)context;
+    struct mock_store_slot *slot;
+
+    slot = find_slot(this_context, uid);
+
+    if (!slot) {
+
+        slot = find_empty_slot(this_context);
+
+        if (slot) {
+
+            slot->item = malloc(capacity);
+
+            if (slot->item) {
+
+                slot->uid = uid;
+                slot->flags = create_flags;
+                slot->capacity = capacity;
+                slot->len = 0;
+
+                memset(slot->item, slot->capacity, 0);
+                psa_status = PSA_SUCCESS;
+            }
+            else  {
+
+                psa_status = PSA_ERROR_INSUFFICIENT_STORAGE;
+            }
+        }
+    }
+
+    return psa_status;
+}
+
+static psa_status_t mock_store_set_extended(void *context,
+                            uint32_t client_id,
+                            uint64_t uid,
+                            size_t data_offset,
+                            size_t data_length,
+                            const void *p_data)
+{
+    psa_status_t psa_status = PSA_ERROR_DOES_NOT_EXIST;
+    struct mock_store *this_context = (struct mock_store*)context;
+    struct mock_store_slot *slot;
+
+    slot = find_slot(this_context, uid);
+
+    if (slot && slot->item) {
+
+        if (p_data && slot->capacity >= data_offset + data_length) {
+
+            memcpy(&slot->item[data_offset], p_data, data_length);
+
+            if (data_offset + data_length > slot->len) slot->len = data_offset + data_length;
+
+            psa_status = PSA_SUCCESS;
+        }
+        else  {
+
+            psa_status = PSA_ERROR_INVALID_ARGUMENT;
+        }
+    }
+
+    return psa_status;
+}
+
+static uint32_t mock_store_get_support(void *context,
+                            uint32_t client_id)
+{
+    (void)context;
+    (void)client_id;
+
+    return PSA_STORAGE_SUPPORT_SET_EXTENDED;
+}
+
+
 struct storage_backend *mock_store_init(struct mock_store *context)
 {
     for (int i = 0; i < MOCK_STORE_NUM_SLOTS; ++i) {
 
         context->slots[i].len = 0;
+        context->slots[i].capacity = 0;
         context->slots[i].flags = 0;
-        context->slots[i].id = (uint32_t)(-1);
+        context->slots[i].uid = (uint64_t)(-1);
         context->slots[i].item = NULL;
     }
 
@@ -125,7 +215,10 @@
         mock_store_set,
         mock_store_get,
         mock_store_get_info,
-        mock_store_remove
+        mock_store_remove,
+        mock_store_create,
+        mock_store_set_extended,
+        mock_store_get_support
     };
 
     context->backend.context = context;
@@ -145,12 +238,12 @@
         free_slot(&context->slots[i]);
 }
 
-bool mock_store_exists(const struct mock_store *context, uint32_t id)
+bool mock_store_exists(const struct mock_store *context, uint64_t uid)
 {
     bool exists = false;
 
     for (int i = 0; !exists && i < MOCK_STORE_NUM_SLOTS; ++i) {
-        exists = context->slots[i].item && (context->slots[i].id == id);
+        exists = context->slots[i].item && (context->slots[i].uid == uid);
     }
 
     return exists;
@@ -167,12 +260,12 @@
     return count;
 }
 
-static struct mock_store_slot *find_slot(struct mock_store *context, uint32_t id)
+static struct mock_store_slot *find_slot(struct mock_store *context, uint64_t uid)
 {
     struct mock_store_slot *slot = NULL;
 
     for (int i = 0; i < MOCK_STORE_NUM_SLOTS; ++i) {
-        if (context->slots[i].item && (context->slots[i].id == id)) {
+        if (context->slots[i].item && (context->slots[i].uid == uid)) {
             slot = &context->slots[i];
             break;
         }
@@ -200,8 +293,9 @@
     if (slot->item) {
         free(slot->item);
         slot->len = 0;
+        slot->capacity = 0;
         slot->flags = 0;
-        slot->id = (uint32_t)(-1);
+        slot->uid = (uint64_t)(-1);
         slot->item = NULL;
     }
 }
\ No newline at end of file
diff --git a/components/service/secure_storage/backend/mock_store/mock_store.h b/components/service/secure_storage/backend/mock_store/mock_store.h
index 787e6bc..54ccd6a 100644
--- a/components/service/secure_storage/backend/mock_store/mock_store.h
+++ b/components/service/secure_storage/backend/mock_store/mock_store.h
@@ -17,12 +17,14 @@
 #endif
 
 #define MOCK_STORE_NUM_SLOTS        (100)
+#define MOCK_STORE_ITEM_SIZE_LIMIT  (10000)
 
 struct mock_store_slot
 {
-    uint64_t id;
+    uint64_t uid;
     uint32_t flags;
     size_t len;
+    size_t capacity;
     uint8_t *item;
 };
 
@@ -37,7 +39,7 @@
 
 /* Test support methods */
 void mock_store_reset(struct mock_store *context);
-bool mock_store_exists(const struct mock_store *context, uint32_t id);
+bool mock_store_exists(const struct mock_store *context, uint64_t uid);
 size_t mock_store_num_items(const struct mock_store *context);
 
 #ifdef __cplusplus
diff --git a/components/service/secure_storage/test/component.cmake b/components/service/secure_storage/backend/mock_store/test/component.cmake
similarity index 74%
copy from components/service/secure_storage/test/component.cmake
copy to components/service/secure_storage/backend/mock_store/test/component.cmake
index 8ea41cf..ee779ae 100644
--- a/components/service/secure_storage/test/component.cmake
+++ b/components/service/secure_storage/backend/mock_store/test/component.cmake
@@ -1,5 +1,5 @@
 #-------------------------------------------------------------------------------
-# Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.
+# Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -9,6 +9,6 @@
 endif()
 
 target_sources(${TGT} PRIVATE
-	"${CMAKE_CURRENT_LIST_DIR}/its_tests.cpp"
+	"${CMAKE_CURRENT_LIST_DIR}/mock_store_tests.cpp"
 	)
 
diff --git a/components/service/secure_storage/backend/mock_store/test/mock_store_tests.cpp b/components/service/secure_storage/backend/mock_store/test/mock_store_tests.cpp
new file mode 100644
index 0000000..54513be
--- /dev/null
+++ b/components/service/secure_storage/backend/mock_store/test/mock_store_tests.cpp
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2020-2021, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <CppUTest/TestHarness.h>
+#include <service/secure_storage/frontend/psa/its/its_frontend.h>
+#include <service/secure_storage/frontend/psa/its/test/its_api_tests.h>
+#include <service/secure_storage/frontend/psa/ps/ps_frontend.h>
+#include <service/secure_storage/frontend/psa/ps/test/ps_api_tests.h>
+#include <service/secure_storage/backend/mock_store/mock_store.h>
+
+
+TEST_GROUP(MockStoreTests)
+{
+    void setup()
+    {
+        struct storage_backend *storage_backend = mock_store_init(&m_mock_store);
+
+        psa_its_frontend_init(storage_backend);
+        psa_ps_frontend_init(storage_backend);
+    }
+
+    void teardown()
+    {
+        mock_store_deinit(&m_mock_store);
+    }
+
+    struct mock_store m_mock_store;
+};
+
+TEST(MockStoreTests, itsStoreNewItem)
+{
+    its_api_tests::storeNewItem();
+}
+
+TEST(MockStoreTests, itsStorageLimitTest)
+{
+    its_api_tests::storageLimitTest(MOCK_STORE_ITEM_SIZE_LIMIT);
+}
+
+TEST(MockStoreTests, psCreateAndSet)
+{
+    ps_api_tests::createAndSet();
+}
+
+TEST(MockStoreTests, psCreateAndSetExtended)
+{
+    ps_api_tests::createAndSetExtended();
+}
diff --git a/components/service/secure_storage/backend/secure_flash_store/secure_flash_store.c b/components/service/secure_storage/backend/secure_flash_store/secure_flash_store.c
index 69796cf..5e7dea5 100644
--- a/components/service/secure_storage/backend/secure_flash_store/secure_flash_store.c
+++ b/components/service/secure_storage/backend/secure_flash_store/secure_flash_store.c
@@ -264,6 +264,71 @@
     return sfs_flash_fs_file_delete(&fs_ctx_sfs, g_fid);
 }
 
+static psa_status_t sfs_create(void *context,
+                            uint32_t client_id,
+                            uint64_t uid,
+                            size_t capacity,
+                            uint32_t create_flags)
+{
+    psa_status_t status;
+
+    /* Check that the UID is valid */
+    if (uid == SFS_INVALID_UID) {
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    /* Check that the create_flags does not contain any unsupported flags */
+    if (create_flags & ~(PSA_STORAGE_FLAG_WRITE_ONCE |
+                         PSA_STORAGE_FLAG_NO_CONFIDENTIALITY |
+                         PSA_STORAGE_FLAG_NO_REPLAY_PROTECTION)) {
+        return PSA_ERROR_NOT_SUPPORTED;
+    }
+
+    /* Set file id */
+    sfs_get_fid(client_id, uid, g_fid);
+
+    /* Read file info */
+    status = sfs_flash_fs_file_get_info(&fs_ctx_sfs, g_fid, &g_file_info);
+    if (status == PSA_SUCCESS) {
+        return PSA_ERROR_ALREADY_EXISTS;
+    }
+
+    /* Create the file in the file system */
+    status = sfs_flash_fs_file_create(&fs_ctx_sfs, g_fid, capacity,
+                                      0, (uint32_t)create_flags,
+                                      NULL);
+
+    return status;
+}
+
+static psa_status_t sfs_set_extended(void *context,
+                            uint32_t client_id,
+                            uint64_t uid,
+                            size_t data_offset,
+                            size_t data_length,
+                            const void *p_data)
+{
+    /* Optional function not supported by this backend */
+    (void)context;
+    (void)client_id;
+    (void)uid;
+    (void)data_offset;
+    (void)data_length;
+    (void)p_data;
+
+    return PSA_ERROR_NOT_SUPPORTED;
+}
+
+static uint32_t sfs_get_support(void *context, uint32_t client_id)
+{
+    (void)context;
+    (void)client_id;
+
+    /* No optional functions supported */
+    return 0;
+}
+
+
 struct storage_backend *sfs_init(void)
 {
     psa_status_t status;
@@ -307,7 +372,10 @@
         sfs_set,
         sfs_get,
         sfs_get_info,
-        sfs_remove
+        sfs_remove,
+        sfs_create,
+        sfs_set_extended,
+        sfs_get_support
     };
 
     static struct storage_backend backend;
diff --git a/components/service/secure_storage/test/component.cmake b/components/service/secure_storage/backend/secure_flash_store/test/component.cmake
similarity index 76%
rename from components/service/secure_storage/test/component.cmake
rename to components/service/secure_storage/backend/secure_flash_store/test/component.cmake
index 8ea41cf..67a6211 100644
--- a/components/service/secure_storage/test/component.cmake
+++ b/components/service/secure_storage/backend/secure_flash_store/test/component.cmake
@@ -1,5 +1,5 @@
 #-------------------------------------------------------------------------------
-# Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.
+# Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -9,6 +9,6 @@
 endif()
 
 target_sources(${TGT} PRIVATE
-	"${CMAKE_CURRENT_LIST_DIR}/its_tests.cpp"
+	"${CMAKE_CURRENT_LIST_DIR}/sfs_tests.cpp"
 	)
 
diff --git a/components/service/secure_storage/backend/secure_flash_store/test/sfs_tests.cpp b/components/service/secure_storage/backend/secure_flash_store/test/sfs_tests.cpp
new file mode 100644
index 0000000..33bdcde
--- /dev/null
+++ b/components/service/secure_storage/backend/secure_flash_store/test/sfs_tests.cpp
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <CppUTest/TestHarness.h>
+#include <service/secure_storage/frontend/psa/its/its_frontend.h>
+#include <service/secure_storage/frontend/psa/its/test/its_api_tests.h>
+#include <service/secure_storage/frontend/psa/ps/ps_frontend.h>
+#include <service/secure_storage/frontend/psa/ps/test/ps_api_tests.h>
+#include <service/secure_storage/backend/secure_flash_store/secure_flash_store.h>
+
+
+TEST_GROUP(SfsTests)
+{
+    void setup()
+    {
+        struct storage_backend *storage_backend = sfs_init();
+
+        psa_its_frontend_init(storage_backend);
+        psa_ps_frontend_init(storage_backend);
+    }
+};
+
+TEST(SfsTests, itsStoreNewItem)
+{
+    its_api_tests::storeNewItem();
+}
+
+TEST(SfsTests, itsStorageLimitTest)
+{
+    its_api_tests::storageLimitTest(5000);
+}
+
+TEST(SfsTests, psCreateAndSet)
+{
+    ps_api_tests::createAndSet();
+}
+
+TEST(SfsTests, psCreateAndSetExtended)
+{
+    ps_api_tests::createAndSetExtended();
+}
diff --git a/components/service/secure_storage/backend/secure_storage_client/secure_storage_client.c b/components/service/secure_storage/backend/secure_storage_client/secure_storage_client.c
index b2bfc56..fcbc996 100644
--- a/components/service/secure_storage/backend/secure_storage_client/secure_storage_client.c
+++ b/components/service/secure_storage/backend/secure_storage_client/secure_storage_client.c
@@ -28,6 +28,8 @@
 	rpc_status_t rpc_status = TS_RPC_CALL_ACCEPTED;
 	psa_status_t psa_status = PSA_SUCCESS;
 
+	(void)client_id;
+
 	/* Validating input parameters */
 	if (p_data == NULL)
 		return PSA_ERROR_INVALID_ARGUMENT;
@@ -84,6 +86,8 @@
 	rpc_status_t rpc_status = TS_RPC_CALL_ACCEPTED;
 	psa_status_t psa_status = PSA_SUCCESS;
 
+	(void)client_id;
+
 	/* Validating input parameters */
 	if (p_data == NULL)
 		return PSA_ERROR_INVALID_ARGUMENT;
@@ -137,6 +141,8 @@
 	rpc_status_t rpc_status;
 	psa_status_t psa_status = PSA_ERROR_GENERIC_ERROR;
 
+	(void)client_id;
+
 	/* Validating input parameters */
 	if (p_info == NULL)
 		return PSA_ERROR_INVALID_ARGUMENT;
@@ -193,6 +199,8 @@
 	rpc_status_t rpc_status = TS_RPC_CALL_ACCEPTED;
 	psa_status_t psa_status = PSA_SUCCESS;
 
+	(void)client_id;
+
 	handle = rpc_caller_begin(this_context->rpc_caller, &request, sizeof(*request_desc));
 
 	if (handle) {
@@ -219,6 +227,154 @@
 	return psa_status;
 }
 
+static psa_status_t secure_storage_client_create(void *context,
+                            uint32_t client_id,
+                            uint64_t uid,
+                            size_t capacity,
+                            uint32_t create_flags)
+{
+	struct secure_storage_client *this_context = (struct secure_storage_client*)context;
+	uint8_t *request;
+	uint8_t *response;
+	size_t request_length = 0;
+	size_t response_length = 0;
+	struct secure_storage_request_create *request_desc;
+	rpc_call_handle handle;
+	rpc_status_t rpc_status = TS_RPC_CALL_ACCEPTED;
+	psa_status_t psa_status = PSA_SUCCESS;
+
+	(void)client_id;
+
+	request_length = sizeof(*request_desc);
+
+	handle = rpc_caller_begin(this_context->rpc_caller, &request, request_length);
+
+	if (handle) {
+
+		request_desc = (struct secure_storage_request_create*)request;
+		request_desc->uid = uid;
+		request_desc->capacity = capacity;
+		request_desc->create_flags = create_flags;
+
+		rpc_status = rpc_caller_invoke(this_context->rpc_caller, handle,
+						TS_SECURE_STORAGE_OPCODE_CREATE,
+						(uint32_t *)&psa_status, &response,
+						&response_length);
+
+		if (rpc_status != TS_RPC_CALL_ACCEPTED) {
+			/* RPC failure */
+			psa_status = PSA_ERROR_GENERIC_ERROR;
+		}
+
+		rpc_caller_end(this_context->rpc_caller, handle);
+	}
+	else {
+		psa_status = PSA_ERROR_GENERIC_ERROR;
+	}
+
+	return psa_status;
+}
+
+static psa_status_t secure_storage_set_extended(void *context,
+                            uint32_t client_id,
+                            uint64_t uid,
+                            size_t data_offset,
+                            size_t data_length,
+                            const void *p_data)
+{
+	struct secure_storage_client *this_context = (struct secure_storage_client*)context;
+	uint8_t *request;
+	uint8_t *response;
+	size_t request_length = 0;
+	size_t response_length = 0;
+	struct secure_storage_request_set_extended *request_desc;
+	rpc_call_handle handle;
+	rpc_status_t rpc_status = TS_RPC_CALL_ACCEPTED;
+	psa_status_t psa_status = PSA_SUCCESS;
+
+	(void)client_id;
+
+	/* Validating input parameters */
+	if (p_data == NULL)
+		return PSA_ERROR_INVALID_ARGUMENT;
+
+	request_length = sizeof(*request_desc) + data_length;
+	if (request_length < data_length) {
+		/* size_t overflow */
+		return PSA_ERROR_INVALID_ARGUMENT;
+	}
+
+	handle = rpc_caller_begin(this_context->rpc_caller, &request, request_length);
+
+	if (handle) {
+		/* Populating request descriptor */
+		request_desc = (struct secure_storage_request_set_extended *)request;
+		request_desc->uid = uid;
+		request_desc->data_offset = data_offset;
+		request_desc->data_length = data_length;
+		memcpy(&request_desc->p_data, p_data, data_length);
+
+		rpc_status = rpc_caller_invoke(this_context->rpc_caller, handle,
+						TS_SECURE_STORAGE_OPCODE_SET_EXTENDED,
+						(uint32_t *)&psa_status, &response,
+						&response_length);
+
+		if (rpc_status != TS_RPC_CALL_ACCEPTED) {
+			/* RPC failure */
+			psa_status = PSA_ERROR_GENERIC_ERROR;
+		}
+
+		rpc_caller_end(this_context->rpc_caller, handle);
+	}
+	else {
+		psa_status = PSA_ERROR_GENERIC_ERROR;
+	}
+
+	return psa_status;
+}
+
+static uint32_t secure_storage_get_support(void *context, uint32_t client_id)
+{
+	struct secure_storage_client *this_context = (struct secure_storage_client*)context;
+	uint8_t *request;
+	uint8_t *response;
+	size_t response_length = 0;
+	struct secure_storage_response_get_support *response_desc;
+	rpc_call_handle handle;
+	rpc_status_t rpc_status;
+	psa_status_t psa_status = PSA_ERROR_GENERIC_ERROR;
+	uint32_t feature_map = 0;
+
+	(void)client_id;
+
+	handle = rpc_caller_begin(this_context->rpc_caller, &request, 0);
+
+	if (handle) {
+
+		rpc_status = rpc_caller_invoke(this_context->rpc_caller, handle,
+						TS_SECURE_STORAGE_OPCODE_GET_SUPPORT,
+						(uint32_t *)&psa_status, &response,
+						&response_length);
+
+		if (rpc_status != TS_RPC_CALL_ACCEPTED) {
+			/* RPC failure */
+			psa_status = PSA_ERROR_GENERIC_ERROR;
+		} else if (response_length < sizeof(*response_desc)) {
+			psa_status = PSA_ERROR_GENERIC_ERROR;
+		}
+
+		if (psa_status == PSA_SUCCESS) {
+			response_desc = (struct secure_storage_response_get_support*)response;
+			feature_map = response_desc->support;
+		}
+
+		rpc_caller_end(this_context->rpc_caller, handle);
+	}
+
+	return feature_map;
+}
+
+
 struct storage_backend *secure_storage_client_init(struct secure_storage_client *context,
 								struct rpc_caller *caller)
 {
@@ -229,7 +385,10 @@
 		secure_storage_client_set,
 		secure_storage_client_get,
 		secure_storage_client_get_info,
-		secure_storage_client_remove
+		secure_storage_client_remove,
+		secure_storage_client_create,
+		secure_storage_set_extended,
+		secure_storage_get_support
 	};
 
 	context->backend.context = context;
diff --git a/components/service/secure_storage/test/component.cmake b/components/service/secure_storage/backend/secure_storage_client/test/component.cmake
similarity index 64%
copy from components/service/secure_storage/test/component.cmake
copy to components/service/secure_storage/backend/secure_storage_client/test/component.cmake
index 8ea41cf..92376f1 100644
--- a/components/service/secure_storage/test/component.cmake
+++ b/components/service/secure_storage/backend/secure_storage_client/test/component.cmake
@@ -1,5 +1,5 @@
 #-------------------------------------------------------------------------------
-# Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.
+# Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -9,6 +9,7 @@
 endif()
 
 target_sources(${TGT} PRIVATE
-	"${CMAKE_CURRENT_LIST_DIR}/its_tests.cpp"
+	"${CMAKE_CURRENT_LIST_DIR}/secure_storage_client_tests.cpp"
+	"${CMAKE_CURRENT_LIST_DIR}/secure_storage_proxy_tests.cpp"
 	)
 
diff --git a/components/service/secure_storage/backend/secure_storage_client/test/secure_storage_client_tests.cpp b/components/service/secure_storage/backend/secure_storage_client/test/secure_storage_client_tests.cpp
new file mode 100644
index 0000000..7cd887e
--- /dev/null
+++ b/components/service/secure_storage/backend/secure_storage_client/test/secure_storage_client_tests.cpp
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <CppUTest/TestHarness.h>
+#include <rpc/direct/direct_caller.h>
+#include <service/secure_storage/frontend/psa/its/its_frontend.h>
+#include <service/secure_storage/frontend/psa/its/test/its_api_tests.h>
+#include <service/secure_storage/frontend/psa/ps/ps_frontend.h>
+#include <service/secure_storage/frontend/psa/ps/test/ps_api_tests.h>
+#include <service/secure_storage/frontend/secure_storage_provider/secure_storage_provider.h>
+#include <service/secure_storage/backend/secure_storage_client/secure_storage_client.h>
+#include <service/secure_storage/backend/mock_store/mock_store.h>
+
+
+TEST_GROUP(SecureStorageClientTests)
+{
+    /* Runs ITS and PS API tests against a typical service configuration
+     * comprising:
+     * its/ps_frontend->secure_storage_client->secure_storage_provider->mock_store
+     */
+    void setup()
+    {
+        struct storage_backend *storage_provider_backend =
+            mock_store_init(&m_mock_store);
+        struct rpc_interface *storage_ep =
+            secure_storage_provider_init(&m_storage_provider, storage_provider_backend);
+        struct rpc_caller *storage_caller =
+            direct_caller_init_default(&m_storage_caller, storage_ep);
+        struct storage_backend *storage_client_backend =
+            secure_storage_client_init(&m_storage_client, storage_caller);
+
+        psa_its_frontend_init(storage_client_backend);
+        psa_ps_frontend_init(storage_client_backend);
+    }
+
+    void teardown()
+    {
+        mock_store_deinit(&m_mock_store);
+        secure_storage_provider_deinit(&m_storage_provider);
+        secure_storage_client_deinit(&m_storage_client);
+        direct_caller_deinit(&m_storage_caller);
+    }
+
+    struct mock_store m_mock_store;
+    struct secure_storage_provider m_storage_provider;
+    struct secure_storage_client m_storage_client;
+    struct direct_caller m_storage_caller;
+};
+
+TEST(SecureStorageClientTests, itsStoreNewItem)
+{
+    its_api_tests::storeNewItem();
+}
+
+TEST(SecureStorageClientTests, itsStorageLimitTest)
+{
+    its_api_tests::storageLimitTest(MOCK_STORE_ITEM_SIZE_LIMIT);
+}
+
+TEST(SecureStorageClientTests, psCreateAndSet)
+{
+    ps_api_tests::createAndSet();
+}
+
+TEST(SecureStorageClientTests, psCreateAndSetExtended)
+{
+    ps_api_tests::createAndSetExtended();
+}
diff --git a/components/service/secure_storage/backend/secure_storage_client/test/secure_storage_proxy_tests.cpp b/components/service/secure_storage/backend/secure_storage_client/test/secure_storage_proxy_tests.cpp
new file mode 100644
index 0000000..c028776
--- /dev/null
+++ b/components/service/secure_storage/backend/secure_storage_client/test/secure_storage_proxy_tests.cpp
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <CppUTest/TestHarness.h>
+#include <rpc/direct/direct_caller.h>
+#include <service/secure_storage/frontend/psa/its/its_frontend.h>
+#include <service/secure_storage/frontend/psa/its/test/its_api_tests.h>
+#include <service/secure_storage/frontend/psa/ps/ps_frontend.h>
+#include <service/secure_storage/frontend/psa/ps/test/ps_api_tests.h>
+#include <service/secure_storage/frontend/secure_storage_provider/secure_storage_provider.h>
+#include <service/secure_storage/backend/secure_storage_client/secure_storage_client.h>
+#include <service/secure_storage/backend/mock_store/mock_store.h>
+
+
+TEST_GROUP(SecureStorageProxyTests)
+{
+    /* Runs ITS and PS API tests against a service provider, accessed via a
+     * proxy.  The frontend/backend chain looks like this:
+     * its/ps_frontend->secure_storage_client->secure_storage_provider->secure_storage_client
+     * ->secure_storage_provider->mock_store
+     */
+    void setup()
+    {
+        /* Initialise the actual storage provider */
+        struct storage_backend *storage_provider_backend =
+            mock_store_init(&m_mock_store);
+        struct rpc_interface *storage_ep =
+            secure_storage_provider_init(&m_storage_provider, storage_provider_backend);
+        struct rpc_caller *storage_caller =
+            direct_caller_init_default(&m_storage_caller, storage_ep);
+
+        /* Initialise the intermediate proxy */
+        struct storage_backend *proxy_backend =
+            secure_storage_client_init(&m_proxy_client, storage_caller);
+        struct rpc_interface *proxy_ep =
+            secure_storage_provider_init(&m_proxy_provider, proxy_backend);
+        struct rpc_caller *proxy_caller =
+            direct_caller_init_default(&m_proxy_caller, proxy_ep);
+
+        /* Initialise the client-side backend that talks to the proxy */
+        struct storage_backend *storage_client_backend =
+            secure_storage_client_init(&m_storage_client, proxy_caller);
+
+        psa_its_frontend_init(storage_client_backend);
+        psa_ps_frontend_init(storage_client_backend);
+    }
+
+    void teardown()
+    {
+        mock_store_deinit(&m_mock_store);
+        secure_storage_provider_deinit(&m_storage_provider);
+
+        secure_storage_client_deinit(&m_proxy_client);
+        secure_storage_provider_deinit(&m_proxy_provider);
+
+        secure_storage_client_deinit(&m_storage_client);
+
+        direct_caller_deinit(&m_proxy_caller);
+        direct_caller_deinit(&m_storage_caller);
+    }
+
+    struct mock_store m_mock_store;
+    struct secure_storage_provider m_storage_provider;
+    struct secure_storage_client m_proxy_client;
+    struct secure_storage_provider m_proxy_provider;
+    struct secure_storage_client m_storage_client;
+    struct direct_caller m_storage_caller;
+    struct direct_caller m_proxy_caller;
+};
+
+TEST(SecureStorageProxyTests, itsStoreNewItem)
+{
+    its_api_tests::storeNewItem();
+}
+
+TEST(SecureStorageProxyTests, itsStorageLimitTest)
+{
+    its_api_tests::storageLimitTest(MOCK_STORE_ITEM_SIZE_LIMIT);
+}
+
+TEST(SecureStorageProxyTests, psCreateAndSet)
+{
+    ps_api_tests::createAndSet();
+}
+
+TEST(SecureStorageProxyTests, psCreateAndSetExtended)
+{
+    ps_api_tests::createAndSetExtended();
+}
diff --git a/components/service/secure_storage/backend/storage_backend.h b/components/service/secure_storage/backend/storage_backend.h
index 682451c..b4cd80e 100644
--- a/components/service/secure_storage/backend/storage_backend.h
+++ b/components/service/secure_storage/backend/storage_backend.h
@@ -41,7 +41,7 @@
      * \retval PSA_ERROR_NOT_PERMITTED         The operation failed because the
      *                                         provided `uid` value was already
      *                                         created with
-     *                                         TS_SECURE_STORAGE_FLAG_WRITE_ONCE
+     *                                         PSA_STORAGE_FLAG_WRITE_ONCE
      * \retval PSA_ERROR_NOT_SUPPORTED         The operation failed because one or
      *                                         more of the flags provided in
      *                                         `create_flags` is not supported or is
@@ -158,13 +158,103 @@
      *                                     uid value was not found in the storage
      * \retval PSA_ERROR_NOT_PERMITTED     The operation failed because the provided
      *                                     uid value was created with
-     *                                     TS_SECURE_STORAGE_FLAG_WRITE_ONCE
+     *                                     PSA_STORAGE_FLAG_WRITE_ONCE
      * \retval PSA_ERROR_STORAGE_FAILURE   The operation failed because the physical
      *                                     storage has failed (Fatal error)
      */
     psa_status_t (*remove)(void *context,
                                 uint32_t client_id,
                                 uint64_t uid);
+
+    /**
+     * \brief Reserves storage for a new asset
+     *
+     * Creates a new asset of length zero but with the specified space reserved.
+     *
+     * \param[in] context       The concrete backend context
+     * \param[in] client_id     Identifier of the asset's owner (client)
+     * \param[in] uid           The identifier for the data
+     * \param[in] capacity      The space to reserve
+     * \param[in] create_flags  The flags that the data will be stored with
+     *
+     * \return A status indicating the success/failure of the operation
+     *
+     * \retval PSA_SUCCESS                     The operation completed successfully
+     * \retval PSA_ERROR_NOT_SUPPORTED         The operation failed because one or
+     *                                         more of the flags provided in
+     *                                         `create_flags` is not supported or is
+     *                                         not valid
+     * \retval PSA_ERROR_INSUFFICIENT_STORAGE  The operation failed because there
+     *                                         was insufficient space on the
+     *                                         storage medium
+     * \retval PSA_ERROR_STORAGE_FAILURE       The operation failed because the
+     *                                         physical storage has failed (Fatal
+     *                                         error)
+     * \retval PSA_ERROR_INVALID_ARGUMENT      The operation failed because one
+     *                                         of the provided pointers (`p_data`)
+     *                                         is invalid, for example is `NULL` or
+     *                                         references memory the caller cannot
+     *                                         access
+     * \retval PSA_ERROR_ALREADY_EXISTS        The specified uuid already exists
+     */
+    psa_status_t (*create)(void *context,
+                            uint32_t client_id,
+                            uint64_t uid,
+                            size_t capacity,
+                            uint32_t create_flags);
+
+    /**
+     * \brief Set partial data for an existing asset
+     *
+     * \param[in] context       The concrete backend context
+     * \param[in] client_id     Identifier of the asset's owner (client)
+     * \param[in] uid           The identifier for the data
+     * \param[in] data_offset   Offset into asset for start of write
+     * \param[in] data_length   The size in bytes of the data in `p_data`
+     *
+     * \return A status indicating the success/failure of the operation
+     *
+     * \retval PSA_SUCCESS                     The operation completed successfully
+     *
+     * \retval PSA_ERROR_NOT_PERMITTED         The operation failed because the
+     *                                         provided `uid` value was already
+     *                                         created with
+     *                                         PSA_STORAGE_FLAG_WRITE_ONCE
+     * \retval PSA_ERROR_NOT_SUPPORTED         The operation failed because one or
+     *                                         more of the flags provided in
+     *                                         `create_flags` is not supported or is
+     *                                         not valid
+     * \retval PSA_ERROR_STORAGE_FAILURE       The operation failed because the
+     *                                         physical storage has failed (Fatal
+     *                                         error)
+     * \retval PSA_ERROR_INVALID_ARGUMENT      The operation failed because one
+     *                                         of the provided pointers (`p_data`)
+     *                                         is invalid, for example is `NULL` or
+     *                                         references memory the caller cannot
+     *                                         access
+     * \retval PSA_ERROR_DOES_NOT_EXIST        The specified uuid was not found
+     * \retval PSA_ERROR_DOES_DATA_CORRUPT     Existing data is corrupted
+     * \retval PSA_ERROR_INVALID_SIGNATURE     MAC check failed on existing data
+     */
+    psa_status_t (*set_extended)(void *context,
+                            uint32_t client_id,
+                            uint64_t uid,
+                            size_t data_offset,
+                            size_t data_length,
+                            const void *p_data);
+
+    /**
+     * \brief Get supported features
+     *
+     * Returns a bit map of optional features supported by the backend
+     *
+     * \param[in] context       The concrete backend context
+     * \param[in] client_id     Identifier of the asset's owner (client)
+     *
+     * \return Bit map of supported features (defined in psa/storage_common.h)
+     */
+    uint32_t (*get_support)(void *context,
+                            uint32_t client_id);
 };
 
 /**
diff --git a/components/service/secure_storage/test/component.cmake b/components/service/secure_storage/frontend/psa/its/test/component.cmake
similarity index 75%
copy from components/service/secure_storage/test/component.cmake
copy to components/service/secure_storage/frontend/psa/its/test/component.cmake
index 8ea41cf..488ab02 100644
--- a/components/service/secure_storage/test/component.cmake
+++ b/components/service/secure_storage/frontend/psa/its/test/component.cmake
@@ -1,5 +1,5 @@
 #-------------------------------------------------------------------------------
-# Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.
+# Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -9,6 +9,5 @@
 endif()
 
 target_sources(${TGT} PRIVATE
-	"${CMAKE_CURRENT_LIST_DIR}/its_tests.cpp"
+	"${CMAKE_CURRENT_LIST_DIR}/its_api_tests.cpp"
 	)
-
diff --git a/components/service/secure_storage/frontend/psa/its/test/its_api_tests.cpp b/components/service/secure_storage/frontend/psa/its/test/its_api_tests.cpp
new file mode 100644
index 0000000..53a6442
--- /dev/null
+++ b/components/service/secure_storage/frontend/psa/its/test/its_api_tests.cpp
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#include <cstring>
+#include <CppUTest/TestHarness.h>
+#include <psa/internal_trusted_storage.h>
+#include "its_api_tests.h"
+
+void its_api_tests::storeNewItem()
+{
+    psa_status_t status;
+    psa_storage_uid_t uid = 10;
+    struct psa_storage_info_t storage_info;
+    static const size_t ITEM_SIZE = 68;
+    uint8_t item[ITEM_SIZE];
+    uint8_t read_item[ITEM_SIZE];
+
+    memset(item, 0x55, sizeof(item));
+
+    /* Probe to check item does not exist */
+    status = psa_its_get_info(uid, &storage_info);
+    CHECK_EQUAL(PSA_ERROR_DOES_NOT_EXIST, status);
+
+    /* Store the item */
+    status = psa_its_set(uid, sizeof(item), item, PSA_STORAGE_FLAG_NONE);
+    CHECK_EQUAL(PSA_SUCCESS, status);
+
+    /* Probe to check item now exists */
+    status = psa_its_get_info(uid, &storage_info);
+    CHECK_EQUAL(PSA_SUCCESS, status);
+    CHECK_EQUAL(sizeof(item), storage_info.size);
+
+    /* Get the item */
+    size_t read_len = 0;
+    status = psa_its_get(uid, 0, sizeof(read_item), read_item, &read_len);
+    CHECK_EQUAL(PSA_SUCCESS, status);
+    CHECK_EQUAL(sizeof(item), read_len);
+    CHECK(memcmp(item, read_item, sizeof(item)) == 0);
+
+    /* Remove the item */
+    status = psa_its_remove(uid);
+    CHECK_EQUAL(PSA_SUCCESS, status);
+
+    /* Expect it to have gone */
+    status = psa_its_get_info(uid, &storage_info);
+    CHECK_EQUAL(PSA_ERROR_DOES_NOT_EXIST, status);
+}
+
+void its_api_tests::storageLimitTest(size_t size_limit)
+{
+    psa_status_t status;
+    psa_storage_uid_t uid = 10;
+    struct psa_storage_info_t storage_info;
+    static const size_t MAX_ITEM_SIZE = 10000;
+    uint8_t item[MAX_ITEM_SIZE];
+    uint8_t read_item[MAX_ITEM_SIZE];
+
+    memset(item, 0x55, sizeof(item));
+
+    /* Probe to check item does not exist */
+    status = psa_its_get_info(uid, &storage_info);
+    CHECK_EQUAL(PSA_ERROR_DOES_NOT_EXIST, status);
+
+    /* Attempt to store an item that just exceeds the store's limit*/
+    status = psa_its_set(uid, size_limit + 1, item, PSA_STORAGE_FLAG_NONE);
+    CHECK(PSA_SUCCESS != status);
+
+    /* Attempt to store a stupidly big item */
+    status = psa_its_set(uid, static_cast<size_t>(-1), item, PSA_STORAGE_FLAG_NONE);
+    CHECK(PSA_SUCCESS != status);
+
+    /* Attempt to store a zero length item */
+    status = psa_its_set(uid, 0, item, PSA_STORAGE_FLAG_NONE);
+    CHECK_EQUAL(PSA_SUCCESS, status);
+
+    /* Remove the item */
+    status = psa_its_remove(uid);
+    CHECK_EQUAL(PSA_SUCCESS, status);
+}
\ No newline at end of file
diff --git a/components/service/secure_storage/frontend/psa/its/test/its_api_tests.h b/components/service/secure_storage/frontend/psa/its/test/its_api_tests.h
new file mode 100644
index 0000000..df88de5
--- /dev/null
+++ b/components/service/secure_storage/frontend/psa/its/test/its_api_tests.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#ifndef ITS_API_TESTS_H
+#define ITS_API_TESTS_H
+
+#include <cstddef>
+
+/*
+ * API level tests for accessing a secure store via the PSA Internal
+ * Trusted Storage API.  Test scenarios are intended to be reused
+ * with different storage backends.
+ */
+class its_api_tests
+{
+public:
+
+    static void storeNewItem();
+    static void storageLimitTest(size_t size_limit);
+};
+
+#endif /* ITS_API_TESTS_H */
\ No newline at end of file
diff --git a/components/service/secure_storage/test/component.cmake b/components/service/secure_storage/frontend/psa/ps/component.cmake
similarity index 75%
copy from components/service/secure_storage/test/component.cmake
copy to components/service/secure_storage/frontend/psa/ps/component.cmake
index 8ea41cf..2fb5b76 100644
--- a/components/service/secure_storage/test/component.cmake
+++ b/components/service/secure_storage/frontend/psa/ps/component.cmake
@@ -1,5 +1,5 @@
 #-------------------------------------------------------------------------------
-# Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.
+# Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -9,6 +9,5 @@
 endif()
 
 target_sources(${TGT} PRIVATE
-	"${CMAKE_CURRENT_LIST_DIR}/its_tests.cpp"
+	"${CMAKE_CURRENT_LIST_DIR}/ps_frontend.c"
 	)
-
diff --git a/components/service/secure_storage/frontend/psa/ps/ps_frontend.c b/components/service/secure_storage/frontend/psa/ps/ps_frontend.c
new file mode 100644
index 0000000..0756a20
--- /dev/null
+++ b/components/service/secure_storage/frontend/psa/ps/ps_frontend.c
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include "ps_frontend.h"
+#include <psa/protected_storage.h>
+
+
+/* Singleton instance data */
+static struct psa_ps_frontend
+{
+	struct storage_backend *backend;
+	uint32_t client_id;
+} instance;
+
+psa_status_t psa_ps_frontend_init(struct storage_backend *backend)
+{
+	instance.backend = backend;
+	instance.client_id = 0;
+
+	return PSA_SUCCESS;
+}
+
+psa_status_t psa_ps_set(psa_storage_uid_t uid,
+			 size_t data_length,
+			 const void *p_data,
+			 psa_storage_create_flags_t create_flags)
+{
+	return instance.backend->interface->set(
+				instance.backend->context,
+				instance.client_id,
+				uid,
+				data_length,
+				p_data,
+				create_flags);
+}
+
+psa_status_t psa_ps_get(psa_storage_uid_t uid,
+			 size_t data_offset,
+			 size_t data_size,
+			 void *p_data,
+			 size_t *p_data_length)
+{
+	return instance.backend->interface->get(
+				instance.backend->context,
+				instance.client_id,
+				uid,
+				data_offset,
+				data_size,
+				p_data,
+				p_data_length);
+}
+
+psa_status_t psa_ps_get_info(psa_storage_uid_t uid,
+				  struct psa_storage_info_t *p_info)
+{
+	return instance.backend->interface->get_info(
+				instance.backend->context,
+				instance.client_id,
+				uid,
+				p_info);
+}
+
+psa_status_t psa_ps_remove(psa_storage_uid_t uid)
+{
+	return instance.backend->interface->remove(
+				instance.backend->context,
+				instance.client_id,
+				uid);
+}
+
+psa_status_t psa_ps_create(psa_storage_uid_t uid,
+                size_t capacity,
+                psa_storage_create_flags_t create_flags)
+{
+	return instance.backend->interface->create(
+				instance.backend->context,
+				instance.client_id,
+				uid,
+				capacity,
+				create_flags);
+}
+
+psa_status_t psa_ps_set_extended(psa_storage_uid_t uid,
+                size_t data_offset,
+                size_t data_length,
+                const void *p_data)
+{
+	return instance.backend->interface->set_extended(
+				instance.backend->context,
+				instance.client_id,
+				uid,
+				data_offset,
+				data_length,
+				p_data);
+}
+
+uint32_t psa_ps_get_support(void)
+{
+	return instance.backend->interface->get_support(
+				instance.backend->context,
+				instance.client_id);
+}
\ No newline at end of file
diff --git a/components/service/secure_storage/frontend/psa/ps/ps_frontend.h b/components/service/secure_storage/frontend/psa/ps/ps_frontend.h
new file mode 100644
index 0000000..03a1414
--- /dev/null
+++ b/components/service/secure_storage/frontend/psa/ps/ps_frontend.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PS_FRONTEND_H
+#define PS_FRONTEND_H
+
+#include <psa/error.h>
+#include <service/secure_storage/backend/storage_backend.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief      Assigns a concrete storage backend to the PS frontend and initialises
+ *             the singleton PS frontend instance
+ *
+ * Provides an implementation of the PSA PS API as a storage frontend.  Any
+ * suitable storage backend may be used.
+ *
+ * @param[in]  backend Storage backend to use
+ *
+ * @return     A status indicating the success/failure of the operation
+ */
+psa_status_t psa_ps_frontend_init(struct storage_backend *backend);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* PS_FRONTEND_H */
diff --git a/components/service/secure_storage/test/component.cmake b/components/service/secure_storage/frontend/psa/ps/test/component.cmake
similarity index 75%
copy from components/service/secure_storage/test/component.cmake
copy to components/service/secure_storage/frontend/psa/ps/test/component.cmake
index 8ea41cf..9133638 100644
--- a/components/service/secure_storage/test/component.cmake
+++ b/components/service/secure_storage/frontend/psa/ps/test/component.cmake
@@ -1,5 +1,5 @@
 #-------------------------------------------------------------------------------
-# Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.
+# Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -9,6 +9,5 @@
 endif()
 
 target_sources(${TGT} PRIVATE
-	"${CMAKE_CURRENT_LIST_DIR}/its_tests.cpp"
+	"${CMAKE_CURRENT_LIST_DIR}/ps_api_tests.cpp"
 	)
-
diff --git a/components/service/secure_storage/frontend/psa/ps/test/ps_api_tests.cpp b/components/service/secure_storage/frontend/psa/ps/test/ps_api_tests.cpp
new file mode 100644
index 0000000..e4c2cb1
--- /dev/null
+++ b/components/service/secure_storage/frontend/psa/ps/test/ps_api_tests.cpp
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#include <cstring>
+#include <CppUTest/TestHarness.h>
+#include <psa/protected_storage.h>
+#include "ps_api_tests.h"
+
+/**
+ * Creates a new slot and sets its contents in one go.  Uses
+ * mandatory PS API operations only.
+ */
+void ps_api_tests::createAndSet()
+{
+    psa_status_t status;
+    psa_storage_uid_t uid = 10;
+    struct psa_storage_info_t storage_info;
+    static const size_t ITEM_SIZE = 68;
+    uint8_t item[ITEM_SIZE];
+    uint8_t read_item[ITEM_SIZE];
+
+    memset(item, 0x55, sizeof(item));
+
+    /* Probe to check item does not exist */
+    status = psa_ps_get_info(uid, &storage_info);
+    CHECK_EQUAL(PSA_ERROR_DOES_NOT_EXIST, status);
+
+    /* Create empty store record with capcity for the item */
+    status = psa_ps_create(uid, sizeof(item), PSA_STORAGE_FLAG_NONE);
+    CHECK_EQUAL(PSA_SUCCESS, status);
+
+    /* Store the item */
+    status = psa_ps_set(uid, sizeof(item), item, PSA_STORAGE_FLAG_NONE);
+    CHECK_EQUAL(PSA_SUCCESS, status);
+
+    /* Probe to check item now exists */
+    status = psa_ps_get_info(uid, &storage_info);
+    CHECK_EQUAL(PSA_SUCCESS, status);
+    CHECK_EQUAL(sizeof(item), storage_info.size);
+
+    /* Get the item */
+    size_t read_len = 0;
+    status = psa_ps_get(uid, 0, sizeof(read_item), read_item, &read_len);
+    CHECK_EQUAL(PSA_SUCCESS, status);
+    CHECK_EQUAL(sizeof(item), read_len);
+    CHECK(memcmp(item, read_item, sizeof(item)) == 0);
+
+    /* Remove the item */
+    status = psa_ps_remove(uid);
+    CHECK_EQUAL(PSA_SUCCESS, status);
+
+    /* Expect it to have gone */
+    status = psa_ps_get_info(uid, &storage_info);
+    CHECK_EQUAL(PSA_ERROR_DOES_NOT_EXIST, status);
+}
+
+/**
+ * Creates a new slot and if supported, uses the psa_ps_set_extended()
+ * method to set the object value in chunks.
+ */
+void ps_api_tests::createAndSetExtended()
+{
+    psa_status_t status;
+    psa_storage_uid_t uid = 0xffff1;
+    struct psa_storage_info_t storage_info;
+    static const size_t ITEM_SIZE = 100;
+    uint8_t item[ITEM_SIZE];
+    uint8_t read_item[ITEM_SIZE];
+
+    memset(item, 0xaa, sizeof(item));
+
+    /* Probe to check item does not exist */
+    status = psa_ps_get_info(uid, &storage_info);
+    CHECK_EQUAL(PSA_ERROR_DOES_NOT_EXIST, status);
+
+    /* Create empty store record with capcity for the item */
+    status = psa_ps_create(uid, sizeof(item), PSA_STORAGE_FLAG_NONE);
+    CHECK_EQUAL(PSA_SUCCESS, status);
+
+    /* The psa_ps_set_extended() method is optional so respect
+     * the feature capabilities advertised.
+     */
+    uint32_t supported_features = psa_ps_get_support();
+
+    if (supported_features & PSA_STORAGE_SUPPORT_SET_EXTENDED) {
+
+        size_t offset = 0;
+        size_t chunk_len = 10;
+
+        while (offset + chunk_len <= ITEM_SIZE) {
+
+            status = psa_ps_set_extended(uid, offset, chunk_len, &item[offset]);
+            CHECK_EQUAL(PSA_SUCCESS, status);
+
+            offset += chunk_len;
+        }
+
+        /* Expect the item to have been saved in its entirety  */
+        size_t read_len = 0;
+        status = psa_ps_get(uid, 0, sizeof(read_item), read_item, &read_len);
+        CHECK_EQUAL(PSA_SUCCESS, status);
+        CHECK_EQUAL(sizeof(item), read_len);
+        CHECK(memcmp(item, read_item, sizeof(item)) == 0);
+    }
+
+    /* Remove the item */
+    status = psa_ps_remove(uid);
+    CHECK_EQUAL(PSA_SUCCESS, status);
+
+    /* Expect it to have gone */
+    status = psa_ps_get_info(uid, &storage_info);
+    CHECK_EQUAL(PSA_ERROR_DOES_NOT_EXIST, status);
+}
\ No newline at end of file
diff --git a/components/service/secure_storage/frontend/psa/ps/test/ps_api_tests.h b/components/service/secure_storage/frontend/psa/ps/test/ps_api_tests.h
new file mode 100644
index 0000000..1f107f6
--- /dev/null
+++ b/components/service/secure_storage/frontend/psa/ps/test/ps_api_tests.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#ifndef PS_API_TESTS_H
+#define PS_API_TESTS_H
+
+/*
+ * API level tests for accessing a secure store via the PSA Protected
+ * Storage API.  Test scenarios are intended to be reused with different
+ * storage backends.
+ */
+class ps_api_tests
+{
+public:
+
+    static void createAndSet();
+    static void createAndSetExtended();
+};
+
+#endif /* ITS_API_TESTS_H */
diff --git a/components/service/secure_storage/frontend/secure_storage_provider/secure_storage_provider.c b/components/service/secure_storage/frontend/secure_storage_provider/secure_storage_provider.c
index 11d61e8..c18e435 100644
--- a/components/service/secure_storage/frontend/secure_storage_provider/secure_storage_provider.c
+++ b/components/service/secure_storage/frontend/secure_storage_provider/secure_storage_provider.c
@@ -128,12 +128,90 @@
 	return TS_RPC_CALL_ACCEPTED;
 }
 
+static rpc_status_t create_handler(void *context, struct call_req *req)
+{
+	struct secure_storage_provider *this_context = (struct secure_storage_provider*)context;
+	struct secure_storage_request_create *request_desc;
+	psa_status_t psa_status;
+
+	/* Checking if the descriptor fits into the request buffer */
+	if (req->req_buf.data_len < sizeof(struct secure_storage_request_create))
+		return TS_RPC_ERROR_INVALID_REQ_BODY;
+
+	request_desc = (struct secure_storage_request_create *)(req->req_buf.data);
+
+	psa_status = this_context->backend->interface->create(this_context->backend->context,
+				req->caller_id,
+				request_desc->uid,
+				request_desc->capacity,
+				request_desc->create_flags);
+	call_req_set_opstatus(req, psa_status);
+
+	return TS_RPC_CALL_ACCEPTED;
+}
+
+static rpc_status_t set_extended_handler(void *context, struct call_req *req)
+{
+	struct secure_storage_provider *this_context = (struct secure_storage_provider*)context;
+	struct secure_storage_request_set_extended *request_desc;
+	psa_status_t psa_status;
+
+	/* Checking if the descriptor fits into the request buffer */
+	if (req->req_buf.data_len < sizeof(struct secure_storage_request_set_extended))
+		return TS_RPC_ERROR_INVALID_REQ_BODY;
+
+	request_desc = (struct secure_storage_request_set_extended *)(req->req_buf.data);
+
+	/* Checking for overflow */
+	if (sizeof(struct secure_storage_request_set_extended) + request_desc->data_length < request_desc->data_length)
+		return TS_RPC_ERROR_INVALID_REQ_BODY;
+
+	/* Checking if descriptor and data fits into the request buffer */
+	if (req->req_buf.data_len < sizeof(struct secure_storage_request_set_extended) + request_desc->data_length)
+		return TS_RPC_ERROR_INVALID_REQ_BODY;
+
+	psa_status = this_context->backend->interface->set_extended(this_context->backend->context,
+				req->caller_id,
+				request_desc->uid,
+				request_desc->data_offset,
+				request_desc->data_length,
+				request_desc->p_data);
+	call_req_set_opstatus(req, psa_status);
+
+	return TS_RPC_CALL_ACCEPTED;
+}
+
+static rpc_status_t get_support_handler(void *context, struct call_req *req)
+{
+	struct secure_storage_provider *this_context = (struct secure_storage_provider*)context;
+	struct secure_storage_response_get_support *response_desc;
+	uint32_t feature_map;
+
+	/* Checking if the response structure would fit the response buffer */
+	if (req->resp_buf.size < sizeof(struct secure_storage_response_get_support))
+		return TS_RPC_ERROR_INVALID_RESP_BODY;
+
+	response_desc = (struct secure_storage_response_get_support *)(req->resp_buf.data);
+
+	feature_map = this_context->backend->interface->get_support(this_context->backend->context,
+				req->caller_id);
+	call_req_set_opstatus(req, PSA_SUCCESS);
+
+	response_desc->support = feature_map;
+	req->resp_buf.data_len = sizeof(struct secure_storage_response_get_support);
+
+	return TS_RPC_CALL_ACCEPTED;
+}
+
 /* Handler mapping table for service */
 static const struct service_handler handler_table[] = {
 	{TS_SECURE_STORAGE_OPCODE_SET,	set_handler},
 	{TS_SECURE_STORAGE_OPCODE_GET,	get_handler},
 	{TS_SECURE_STORAGE_OPCODE_GET_INFO,	get_info_handler},
-	{TS_SECURE_STORAGE_OPCODE_REMOVE,	remove_handler}
+	{TS_SECURE_STORAGE_OPCODE_REMOVE,	remove_handler},
+	{TS_SECURE_STORAGE_OPCODE_CREATE,	create_handler},
+	{TS_SECURE_STORAGE_OPCODE_SET_EXTENDED,	set_extended_handler},
+	{TS_SECURE_STORAGE_OPCODE_GET_SUPPORT,	get_support_handler}
 };
 
 struct rpc_interface *secure_storage_provider_init(struct secure_storage_provider *context,
diff --git a/components/service/secure_storage/test/its_tests.cpp b/components/service/secure_storage/test/its_tests.cpp
deleted file mode 100644
index 12b057f..0000000
--- a/components/service/secure_storage/test/its_tests.cpp
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * Copyright (c) 2020-2021, Arm Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#include <cstring>
-#include <cstdint>
-#include <CppUTest/TestHarness.h>
-#include <rpc/direct/direct_caller.h>
-#include <service/secure_storage/frontend/psa/its/its_frontend.h>
-#include <service/secure_storage/backend/secure_storage_client/secure_storage_client.h>
-#include <service/secure_storage/frontend/secure_storage_provider/secure_storage_provider.h>
-#include <service/secure_storage/backend/secure_flash_store/secure_flash_store.h>
-#include <psa/internal_trusted_storage.h>
-#include <psa/error.h>
-
-TEST_GROUP(InternalTrustedStorageTests)
-{
-    void setup()
-    {
-        struct storage_backend *storage_provider_backend = sfs_init();
-        struct rpc_interface *storage_ep = secure_storage_provider_init(&m_storage_provider, storage_provider_backend);
-        struct rpc_caller *storage_caller = direct_caller_init_default(&m_storage_caller, storage_ep);
-
-        struct storage_backend *storage_client_backend = secure_storage_client_init(&m_storage_client, storage_caller);
-        psa_its_frontend_init(storage_client_backend);
-    }
-
-    void teardown()
-    {
-        secure_storage_provider_deinit(&m_storage_provider);
-        secure_storage_client_deinit(&m_storage_client);
-        direct_caller_deinit(&m_storage_caller);
-    }
-
-    struct secure_storage_provider m_storage_provider;
-    struct secure_storage_client m_storage_client;
-    struct direct_caller m_storage_caller;
-};
-
-TEST(InternalTrustedStorageTests, storeNewItem)
-{
-    psa_status_t status;
-    psa_storage_uid_t uid = 10;
-    struct psa_storage_info_t storage_info;
-    static const size_t ITEM_SIZE = 68;
-    uint8_t item[ITEM_SIZE];
-    uint8_t read_item[ITEM_SIZE];
-
-    memset(item, 0x55, sizeof(item));
-
-    /* Probe to check item does not exist */
-    status = psa_its_get_info(uid, &storage_info);
-    CHECK_EQUAL(PSA_ERROR_DOES_NOT_EXIST, status);
-
-    /* Store the item */
-    status = psa_its_set(uid, sizeof(item), item, PSA_STORAGE_FLAG_NONE);
-    CHECK_EQUAL(PSA_SUCCESS, status);
-
-    /* Probe to check item now exists */
-    status = psa_its_get_info(uid, &storage_info);
-    CHECK_EQUAL(PSA_SUCCESS, status);
-    CHECK_EQUAL(sizeof(item), storage_info.size);
-
-    /* Get the item */
-    size_t read_len = 0;
-    status = psa_its_get(uid, 0, sizeof(read_item), read_item, &read_len);
-    CHECK_EQUAL(PSA_SUCCESS, status);
-    CHECK_EQUAL(sizeof(item), read_len);
-    CHECK(memcmp(item, read_item, sizeof(item)) == 0);
-
-    /* Remove the item */
-    status = psa_its_remove(uid);
-    CHECK_EQUAL(PSA_SUCCESS, status);
-
-    /* Expect it to have gone */
-    status = psa_its_get_info(uid, &storage_info);
-    CHECK_EQUAL(PSA_ERROR_DOES_NOT_EXIST, status);
-}
-
-TEST(InternalTrustedStorageTests, storageLimitTest)
-{
-    psa_status_t status;
-    psa_storage_uid_t uid = 10;
-    struct psa_storage_info_t storage_info;
-    static const size_t MAX_ITEM_SIZE = 10000;
-    uint8_t item[MAX_ITEM_SIZE];
-    uint8_t read_item[MAX_ITEM_SIZE];
-
-    memset(item, 0x55, sizeof(item));
-
-    /* Probe to check item does not exist */
-    status = psa_its_get_info(uid, &storage_info);
-    CHECK_EQUAL(PSA_ERROR_DOES_NOT_EXIST, status);
-
-    /* Attempt to store a reasonably big item */
-    status = psa_its_set(uid, 5000, item, PSA_STORAGE_FLAG_NONE);
-    CHECK(PSA_SUCCESS != status);
-
-    /* Attempt to store a stupidly big item */
-    status = psa_its_set(uid, static_cast<size_t>(-1), item, PSA_STORAGE_FLAG_NONE);
-    CHECK(PSA_SUCCESS != status);
-
-    /* Attempt to store a zero length item */
-    status = psa_its_set(uid, 0, item, PSA_STORAGE_FLAG_NONE);
-    CHECK_EQUAL(PSA_SUCCESS, status);
-
-    /* Remove the item */
-    status = psa_its_remove(uid);
-    CHECK_EQUAL(PSA_SUCCESS, status);
-}
\ No newline at end of file
diff --git a/deployments/component-test/component-test.cmake b/deployments/component-test/component-test.cmake
index f2f972a..130d82b 100644
--- a/deployments/component-test/component-test.cmake
+++ b/deployments/component-test/component-test.cmake
@@ -51,13 +51,18 @@
 		"components/service/crypto/test/service/packed-c"
 		"components/service/crypto/test/protocol"
 		"components/service/secure_storage/frontend/psa/its"
+		"components/service/secure_storage/frontend/psa/its/test"
+		"components/service/secure_storage/frontend/psa/ps"
+		"components/service/secure_storage/frontend/psa/ps/test"
 		"components/service/secure_storage/frontend/secure_storage_provider"
 		"components/service/secure_storage/backend/secure_storage_client"
+		"components/service/secure_storage/backend/secure_storage_client/test"
 		"components/service/secure_storage/backend/mock_store"
+		"components/service/secure_storage/backend/mock_store/test"
 		"components/service/secure_storage/backend/secure_flash_store"
+		"components/service/secure_storage/backend/secure_flash_store/test"
 		"components/service/secure_storage/backend/secure_flash_store/flash_fs"
 		"components/service/secure_storage/backend/secure_flash_store/flash"
-		"components/service/secure_storage/test"
 		"components/service/test_runner/provider"
 		"components/service/test_runner/provider/serializer/packed-c"
 		"components/service/test_runner/provider/backend/null"
diff --git a/protocols/service/secure_storage/packed-c/secure_storage_proto.h b/protocols/service/secure_storage/packed-c/secure_storage_proto.h
index 1a9b8c8..6b2c04a 100644
--- a/protocols/service/secure_storage/packed-c/secure_storage_proto.h
+++ b/protocols/service/secure_storage/packed-c/secure_storage_proto.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2020-2021, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -9,6 +9,7 @@
 
 #include <stdint.h>
 
+/* Operation SET request parameters */
 struct __attribute__ ((__packed__)) secure_storage_request_set {
 	uint64_t uid;
 	uint64_t data_length;
@@ -16,12 +17,14 @@
 	uint8_t p_data[];
 };
 
+/* Operation GET request parameters */
 struct __attribute__ ((__packed__)) secure_storage_request_get {
 	uint64_t uid;
 	uint64_t data_offset;
 	uint64_t data_size;
 };
 
+/* Operation GET_INFO request and response parameters */
 struct __attribute__ ((__packed__)) secure_storage_request_get_info {
 	uint64_t uid;
 };
@@ -32,14 +35,38 @@
 	uint32_t flags;
 };
 
+/* Operation REMOVE request parameters */
 struct __attribute__ ((__packed__)) secure_storage_request_remove {
 	uint64_t uid;
 };
 
+/* Operation CREATE request parameters */
+struct __attribute__ ((__packed__)) secure_storage_request_create {
+	uint64_t uid;
+	uint64_t capacity;
+	uint32_t create_flags;
+};
+
+/* Operation SET_EXTENDED request parameters */
+struct __attribute__ ((__packed__)) secure_storage_request_set_extended {
+	uint64_t uid;
+	uint64_t data_offset;
+	uint64_t data_length;
+	uint8_t p_data[];
+};
+
+/* Operation GET_SUPPORT response parameters */
+struct __attribute__ ((__packed__)) secure_storage_response_get_support {
+	uint32_t support;
+};
+
 #define TS_SECURE_STORAGE_OPCODE_SET			(0u)
 #define TS_SECURE_STORAGE_OPCODE_GET			(1u)
 #define TS_SECURE_STORAGE_OPCODE_GET_INFO		(2u)
 #define TS_SECURE_STORAGE_OPCODE_REMOVE			(3u)
+#define TS_SECURE_STORAGE_OPCODE_CREATE			(4u)
+#define TS_SECURE_STORAGE_OPCODE_SET_EXTENDED	(5u)
+#define TS_SECURE_STORAGE_OPCODE_GET_SUPPORT	(6u)
 
 #define TS_SECURE_STORAGE_FLAG_NONE			(0u)
 #define TS_SECURE_STORAGE_FLAG_WRITE_ONCE		(1u << 0)