ITS: Implement the top layer of the ITS service

Implements the secure and non-secure top layer of the ITS service,
including a new manifest file, and generates the required veneers.
Updates the partition manifest with added SIDs. It also adds the
necessary CMake files to build the ITS service.

Change-Id: I6d66b01de56145d24a0bcbf0597ca158b6da3386
Signed-off-by: Tudor Cretu <tudor.cretu@arm.com>
diff --git a/CommonConfig.cmake b/CommonConfig.cmake
index 361e763..5b69392 100644
--- a/CommonConfig.cmake
+++ b/CommonConfig.cmake
@@ -334,6 +334,23 @@
 	endif()
 endif()
 
+#Default TF-M internal trusted storage flags.
+#These flags values can be overwritten by setting them in platform/ext/<TARGET_NAME>.cmake
+#Documentation about these flags can be found in the TF-M ITS integration guide
+option(ITS_CREATE_FLASH_LAYOUT "Create an empty ITS Flash Layout" OFF)
+
+if (NOT DEFINED ITS_VALIDATE_METADATA_FROM_FLASH)
+	set (ITS_VALIDATE_METADATA_FROM_FLASH ON)
+endif()
+
+if (NOT DEFINED ITS_RAM_FS)
+	if (REGRESSION)
+		set (ITS_RAM_FS ON)
+	else()
+		set (ITS_RAM_FS OFF)
+	endif()
+endif()
+
 if (NOT DEFINED MBEDTLS_DEBUG)
 	set(MBEDTLS_DEBUG OFF)
 endif()
diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt
index a2c9b5c..e93ff62 100644
--- a/app/CMakeLists.txt
+++ b/app/CMakeLists.txt
@@ -63,12 +63,14 @@
 if (TFM_PSA_API)
 	list(APPEND NS_APP_SRC
 		"${INTERFACE_DIR}/src/tfm_sst_ipc_api.c"
+		"${INTERFACE_DIR}/src/tfm_its_ipc_api.c"
 		"${INTERFACE_DIR}/src/tfm_crypto_ipc_api.c"
 		"${INTERFACE_DIR}/src/tfm_initial_attestation_ipc_api.c"
 	)
 else()
 	list(APPEND NS_APP_SRC
 		"${INTERFACE_DIR}/src/tfm_sst_func_api.c"
+		"${INTERFACE_DIR}/src/tfm_its_func_api.c"
 		"${INTERFACE_DIR}/src/tfm_crypto_func_api.c"
 		"${INTERFACE_DIR}/src/tfm_initial_attestation_func_api.c"
 	)
diff --git a/interface/include/psa_manifest/sid.h b/interface/include/psa_manifest/sid.h
index 49169ee..ac7ccf7 100644
--- a/interface/include/psa_manifest/sid.h
+++ b/interface/include/psa_manifest/sid.h
@@ -26,6 +26,16 @@
 #define TFM_SST_GET_SUPPORT_SID                                    (0x00000064U)
 #define TFM_SST_GET_SUPPORT_VERSION                                (1U)
 
+/******** TFM_SP_ITS ********/
+#define TFM_ITS_SET_SID                                            (0x00000070U)
+#define TFM_ITS_SET_VERSION                                        (1U)
+#define TFM_ITS_GET_SID                                            (0x00000071U)
+#define TFM_ITS_GET_VERSION                                        (1U)
+#define TFM_ITS_GET_INFO_SID                                       (0x00000072U)
+#define TFM_ITS_GET_INFO_VERSION                                   (1U)
+#define TFM_ITS_REMOVE_SID                                         (0x00000073U)
+#define TFM_ITS_REMOVE_VERSION                                     (1U)
+
 /******** TFM_SP_CRYPTO ********/
 #define TFM_CRYPTO_SID                                             (0x00000080U)
 #define TFM_CRYPTO_VERSION                                         (1U)
diff --git a/interface/include/tfm_its_defs.h b/interface/include/tfm_its_defs.h
new file mode 100644
index 0000000..852f8f4
--- /dev/null
+++ b/interface/include/tfm_its_defs.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2019, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef __TFM_ITS_DEFS_H__
+#define __TFM_ITS_DEFS_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Invalid UID */
+#define TFM_ITS_INVALID_UID 0
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __TFM_ITS_DEFS_H__ */
diff --git a/interface/include/tfm_veneers.h b/interface/include/tfm_veneers.h
index 0a24f47..23b4f8d 100644
--- a/interface/include/tfm_veneers.h
+++ b/interface/include/tfm_veneers.h
@@ -23,6 +23,12 @@
 psa_status_t tfm_tfm_sst_remove_req_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len);
 psa_status_t tfm_tfm_sst_get_support_req_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len);
 
+/******** TFM_SP_ITS ********/
+psa_status_t tfm_tfm_its_set_req_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len);
+psa_status_t tfm_tfm_its_get_req_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len);
+psa_status_t tfm_tfm_its_get_info_req_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len);
+psa_status_t tfm_tfm_its_remove_req_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len);
+
 #ifdef TFM_PARTITION_AUDIT_LOG
 /******** TFM_SP_AUDIT_LOG ********/
 psa_status_t tfm_audit_core_retrieve_record_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len);
diff --git a/interface/src/tfm_its_func_api.c b/interface/src/tfm_its_func_api.c
new file mode 100644
index 0000000..483cbee
--- /dev/null
+++ b/interface/src/tfm_its_func_api.c
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2019, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include "psa/internal_trusted_storage.h"
+#include "tfm_api.h"
+
+#include "tfm_ns_interface.h"
+#include "tfm_veneers.h"
+
+#define IOVEC_LEN(x) (sizeof(x)/sizeof(x[0]))
+
+psa_status_t psa_its_set(psa_storage_uid_t uid,
+                         size_t data_length,
+                         const void *p_data,
+                         psa_storage_create_flags_t create_flags)
+{
+    psa_status_t status;
+
+    psa_invec in_vec[] = {
+        { .base = &uid, .len = sizeof(uid) },
+        { .base = p_data, .len = data_length },
+        { .base = &create_flags, .len = sizeof(create_flags) }
+    };
+
+    status = tfm_ns_interface_dispatch((veneer_fn)tfm_tfm_its_set_req_veneer,
+                                       (uint32_t)in_vec, IOVEC_LEN(in_vec),
+                                       (uint32_t)NULL, 0);
+
+    if (status == (psa_status_t)TFM_ERROR_INVALID_PARAMETER) {
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    return status;
+}
+
+psa_status_t psa_its_get(psa_storage_uid_t uid,
+                         size_t data_offset,
+                         size_t data_size,
+                         void *p_data,
+                         size_t *p_data_length)
+{
+    psa_status_t status;
+
+    psa_invec in_vec[] = {
+        { .base = &uid, .len = sizeof(uid) },
+        { .base = &data_offset, .len = sizeof(data_offset) }
+    };
+
+    psa_outvec out_vec[] = {
+        { .base = p_data, .len = data_size }
+    };
+
+    if (p_data_length == NULL) {
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    status = tfm_ns_interface_dispatch((veneer_fn)tfm_tfm_its_get_req_veneer,
+                                       (uint32_t)in_vec, IOVEC_LEN(in_vec),
+                                       (uint32_t)out_vec, IOVEC_LEN(out_vec));
+
+    if (status == (psa_status_t)TFM_ERROR_INVALID_PARAMETER) {
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    *p_data_length = out_vec[0].len;
+
+    return status;
+}
+
+psa_status_t psa_its_get_info(psa_storage_uid_t uid,
+                              struct psa_storage_info_t *p_info)
+{
+    psa_status_t status;
+
+    psa_invec in_vec[] = {
+        { .base = &uid, .len = sizeof(uid) }
+    };
+
+    psa_outvec out_vec[] = {
+        { .base = p_info, .len = sizeof(*p_info) }
+    };
+
+    status = tfm_ns_interface_dispatch(
+                                     (veneer_fn)tfm_tfm_its_get_info_req_veneer,
+                                     (uint32_t)in_vec, IOVEC_LEN(in_vec),
+                                     (uint32_t)out_vec, IOVEC_LEN(out_vec));
+
+    if (status == (psa_status_t)TFM_ERROR_INVALID_PARAMETER) {
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    return status;
+}
+
+psa_status_t psa_its_remove(psa_storage_uid_t uid)
+{
+    psa_invec in_vec[] = {
+        { .base = &uid, .len = sizeof(uid) }
+    };
+
+    return tfm_ns_interface_dispatch((veneer_fn)tfm_tfm_its_remove_req_veneer,
+                                     (uint32_t)in_vec, IOVEC_LEN(in_vec),
+                                     (uint32_t)NULL, 0);
+}
diff --git a/interface/src/tfm_its_ipc_api.c b/interface/src/tfm_its_ipc_api.c
new file mode 100644
index 0000000..9326f7b
--- /dev/null
+++ b/interface/src/tfm_its_ipc_api.c
@@ -0,0 +1,137 @@
+/*
+ * Copyright (c) 2019, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include "psa/internal_trusted_storage.h"
+#include "tfm_api.h"
+
+#include "psa/client.h"
+#include "psa_manifest/sid.h"
+
+#define IOVEC_LEN(x) (sizeof(x)/sizeof(x[0]))
+
+psa_status_t psa_its_set(psa_storage_uid_t uid,
+                         size_t data_length,
+                         const void *p_data,
+                         psa_storage_create_flags_t create_flags)
+{
+    psa_status_t status;
+    psa_handle_t handle;
+
+    psa_invec in_vec[] = {
+        { .base = &uid, .len = sizeof(uid) },
+        { .base = p_data, .len = data_length },
+        { .base = &create_flags, .len = sizeof(create_flags) }
+    };
+
+    handle = psa_connect(TFM_ITS_SET_SID, TFM_ITS_SET_VERSION);
+    if (!PSA_HANDLE_IS_VALID(handle)) {
+        return PSA_ERROR_GENERIC_ERROR;
+    }
+
+    status = psa_call(handle, PSA_IPC_CALL, in_vec, IOVEC_LEN(in_vec), NULL, 0);
+
+    psa_close(handle);
+
+    if (status == (psa_status_t)TFM_ERROR_INVALID_PARAMETER) {
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    return status;
+}
+
+psa_status_t psa_its_get(psa_storage_uid_t uid,
+                         size_t data_offset,
+                         size_t data_size,
+                         void *p_data,
+                         size_t *p_data_length)
+{
+    psa_status_t status;
+    psa_handle_t handle;
+
+    psa_invec in_vec[] = {
+        { .base = &uid, .len = sizeof(uid) },
+        { .base = &data_offset, .len = sizeof(data_offset) }
+    };
+
+    psa_outvec out_vec[] = {
+        { .base = p_data, .len = data_size }
+    };
+
+    if (p_data_length == NULL) {
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    handle = psa_connect(TFM_ITS_GET_SID, TFM_ITS_GET_VERSION);
+    if (!PSA_HANDLE_IS_VALID(handle)) {
+        return PSA_ERROR_GENERIC_ERROR;
+    }
+
+    status = psa_call(handle, PSA_IPC_CALL, in_vec, IOVEC_LEN(in_vec), out_vec,
+                      IOVEC_LEN(out_vec));
+
+    psa_close(handle);
+
+    if (status == (psa_status_t)TFM_ERROR_INVALID_PARAMETER) {
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    *p_data_length = out_vec[0].len;
+
+    return status;
+}
+
+psa_status_t psa_its_get_info(psa_storage_uid_t uid,
+                              struct psa_storage_info_t *p_info)
+{
+    psa_status_t status;
+    psa_handle_t handle;
+
+    psa_invec in_vec[] = {
+        { .base = &uid, .len = sizeof(uid) }
+    };
+
+    psa_outvec out_vec[] = {
+        { .base = p_info, .len = sizeof(*p_info) }
+    };
+
+    handle = psa_connect(TFM_ITS_GET_INFO_SID, TFM_ITS_GET_INFO_VERSION);
+    if (!PSA_HANDLE_IS_VALID(handle)) {
+        return PSA_ERROR_GENERIC_ERROR;
+    }
+
+    status = psa_call(handle, PSA_IPC_CALL, in_vec, IOVEC_LEN(in_vec), out_vec,
+                      IOVEC_LEN(out_vec));
+
+    psa_close(handle);
+
+    if (status == (psa_status_t)TFM_ERROR_INVALID_PARAMETER) {
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    return status;
+}
+
+psa_status_t psa_its_remove(psa_storage_uid_t uid)
+{
+    psa_status_t status;
+    psa_handle_t handle;
+
+    psa_invec in_vec[] = {
+        { .base = &uid, .len = sizeof(uid) }
+    };
+
+    handle = psa_connect(TFM_ITS_REMOVE_SID, TFM_ITS_REMOVE_VERSION);
+    if (!PSA_HANDLE_IS_VALID(handle)) {
+        return PSA_ERROR_GENERIC_ERROR;
+    }
+
+    status = psa_call(handle, PSA_IPC_CALL, in_vec, IOVEC_LEN(in_vec), NULL, 0);
+
+    psa_close(handle);
+
+    return status;
+}
diff --git a/platform/ext/common/armclang/tfm_common_s.sct b/platform/ext/common/armclang/tfm_common_s.sct
index 9d8a4ca..62c7757 100644
--- a/platform/ext/common/armclang/tfm_common_s.sct
+++ b/platform/ext/common/armclang/tfm_common_s.sct
@@ -54,6 +54,11 @@
         *(TFM_SP_STORAGE_ATTR_FN)
     }
 
+    TFM_SP_ITS +0 ALIGN 32 {
+        *tfm_internal_trusted_storage* (+RO)
+        *(TFM_SP_ITS_ATTR_FN)
+    }
+
 #ifdef TFM_PARTITION_AUDIT_LOG
     TFM_SP_AUDIT_LOG +0 ALIGN 32 {
         *tfm_audit* (+RO)
@@ -204,6 +209,17 @@
     }
 #endif
 
+    TFM_SP_ITS_DATA +0 ALIGN 32 {
+        *tfm_internal_trusted_storage* (+RW +ZI)
+        *(TFM_SP_ITS_ATTR_RW)
+        *(TFM_SP_ITS_ATTR_ZI)
+    }
+
+#if defined (TFM_PSA_API)
+    TFM_SP_ITS_STACK +0 ALIGN 128 EMPTY 0x500 {
+    }
+#endif
+
 #ifdef TFM_PARTITION_AUDIT_LOG
     TFM_SP_AUDIT_LOG_DATA +0 ALIGN 32 {
         *tfm_audit* (+RW +ZI)
diff --git a/platform/ext/common/gcc/tfm_common_s.ld b/platform/ext/common/gcc/tfm_common_s.ld
index fb20a5d..fba27b9 100644
--- a/platform/ext/common/gcc/tfm_common_s.ld
+++ b/platform/ext/common/gcc/tfm_common_s.ld
@@ -67,6 +67,9 @@
         LONG (LOADADDR(.TFM_SP_STORAGE_DATA))
         LONG (ADDR(.TFM_SP_STORAGE_DATA))
         LONG (SIZEOF(.TFM_SP_STORAGE_DATA))
+        LONG (LOADADDR(.TFM_SP_ITS_DATA))
+        LONG (ADDR(.TFM_SP_ITS_DATA))
+        LONG (SIZEOF(.TFM_SP_ITS_DATA))
 #ifdef TFM_PARTITION_AUDIT_LOG
         LONG (LOADADDR(.TFM_SP_AUDIT_LOG_DATA))
         LONG (ADDR(.TFM_SP_AUDIT_LOG_DATA))
@@ -131,6 +134,12 @@
         LONG (ADDR(.TFM_SP_STORAGE_STACK))
         LONG (SIZEOF(.TFM_SP_STORAGE_STACK))
 #endif
+        LONG (ADDR(.TFM_SP_ITS_BSS))
+        LONG (SIZEOF(.TFM_SP_ITS_BSS))
+#if defined(TFM_PSA_API)
+        LONG (ADDR(.TFM_SP_ITS_STACK))
+        LONG (SIZEOF(.TFM_SP_ITS_STACK))
+#endif
 #ifdef TFM_PARTITION_AUDIT_LOG
         LONG (ADDR(.TFM_SP_AUDIT_LOG_BSS))
         LONG (SIZEOF(.TFM_SP_AUDIT_LOG_BSS))
@@ -251,6 +260,18 @@
     Image$$TFM_SP_STORAGE$$Base = ADDR(.TFM_SP_STORAGE);
     Image$$TFM_SP_STORAGE$$Limit = ADDR(.TFM_SP_STORAGE) + SIZEOF(.TFM_SP_STORAGE);
 
+    .TFM_SP_ITS : ALIGN(32)
+    {
+        *tfm_internal_trusted_storage*:*(.text*)
+        *tfm_internal_trusted_storage*:*(.rodata*)
+        *(TFM_SP_ITS_ATTR_FN)
+        . = ALIGN(32);
+    } > FLASH
+    Image$$TFM_SP_ITS$$RO$$Base = ADDR(.TFM_SP_ITS);
+    Image$$TFM_SP_ITS$$RO$$Limit = ADDR(.TFM_SP_ITS) + SIZEOF(.TFM_SP_ITS);
+    Image$$TFM_SP_ITS$$Base = ADDR(.TFM_SP_ITS);
+    Image$$TFM_SP_ITS$$Limit = ADDR(.TFM_SP_ITS) + SIZEOF(.TFM_SP_ITS);
+
 #ifdef TFM_PARTITION_AUDIT_LOG
     .TFM_SP_AUDIT_LOG : ALIGN(32)
     {
@@ -570,6 +591,37 @@
 #endif
 
 
+    .TFM_SP_ITS_DATA : ALIGN(32)
+    {
+        *tfm_internal_trusted_storage*:*(.data*)
+        *(TFM_SP_ITS_ATTR_RW)
+        . = ALIGN(32);
+    } > RAM AT> FLASH
+    Image$$TFM_SP_ITS_DATA$$RW$$Base = ADDR(.TFM_SP_ITS_DATA);
+    Image$$TFM_SP_ITS_DATA$$RW$$Limit = ADDR(.TFM_SP_ITS_DATA) + SIZEOF(.TFM_SP_ITS_DATA);
+
+    .TFM_SP_ITS_BSS : ALIGN(32)
+    {
+        start_of_TFM_SP_ITS = .;
+        *tfm_internal_trusted_storage*:*(.bss*)
+        *tfm_internal_trusted_storage*:*(COMMON)
+        *(TFM_SP_ITS_ATTR_ZI)
+        . += (. - start_of_TFM_SP_ITS) ? 0 : 4;
+        . = ALIGN(32);
+    } > RAM AT> RAM
+    Image$$TFM_SP_ITS_DATA$$ZI$$Base = ADDR(.TFM_SP_ITS_BSS);
+    Image$$TFM_SP_ITS_DATA$$ZI$$Limit = ADDR(.TFM_SP_ITS_BSS) + SIZEOF(.TFM_SP_ITS_BSS);
+
+#if defined (TFM_PSA_API)
+    .TFM_SP_ITS_STACK : ALIGN(128)
+    {
+        . += 0x500;
+    } > RAM
+    Image$$TFM_SP_ITS_STACK$$ZI$$Base = ADDR(.TFM_SP_ITS_STACK);
+    Image$$TFM_SP_ITS_STACK$$ZI$$Limit = ADDR(.TFM_SP_ITS_STACK) + SIZEOF(.TFM_SP_ITS_STACK);
+#endif
+
+
 #ifdef TFM_PARTITION_AUDIT_LOG
     .TFM_SP_AUDIT_LOG_DATA : ALIGN(32)
     {
diff --git a/secure_fw/CMakeLists.txt b/secure_fw/CMakeLists.txt
index 70999a4..6a56a05 100644
--- a/secure_fw/CMakeLists.txt
+++ b/secure_fw/CMakeLists.txt
@@ -162,6 +162,7 @@
 
 	add_dependencies(${EXE_NAME} tfm_crypto)
 	add_dependencies(${EXE_NAME} tfm_storage)
+	add_dependencies(${EXE_NAME} tfm_internal_trusted_storage)
 	add_dependencies(${EXE_NAME} tfm_secure_tests)
 	add_dependencies(${EXE_NAME} tfm_attest)
 	if (TFM_PARTITION_AUDIT_LOG)
@@ -177,12 +178,12 @@
 
 	if (REGRESSION OR CORE_TEST)
 		if (DEFINED TFM_PARTITION_TEST_SECURE_SERVICES AND TFM_PARTITION_TEST_SECURE_SERVICES)
-			target_link_libraries(${EXE_NAME} tfm_attest tfm_secure_tests tfm_attest tfm_crypto tfm_storage tfm_attest)
+			target_link_libraries(${EXE_NAME} tfm_attest tfm_secure_tests tfm_attest tfm_crypto tfm_storage tfm_internal_trusted_storage tfm_attest)
 		else()
-			target_link_libraries(${EXE_NAME} tfm_attest tfm_crypto tfm_storage tfm_secure_tests tfm_attest)
+			target_link_libraries(${EXE_NAME} tfm_attest tfm_crypto tfm_storage tfm_internal_trusted_storage tfm_secure_tests tfm_attest)
 		endif()
 	else()
-		target_link_libraries(${EXE_NAME} tfm_attest tfm_crypto tfm_storage tfm_attest)
+		target_link_libraries(${EXE_NAME} tfm_attest tfm_crypto tfm_storage tfm_internal_trusted_storage tfm_attest)
 	endif()
 
 	if (TFM_PARTITION_AUDIT_LOG)
@@ -316,11 +317,13 @@
 							${INTERFACE_SRC_DIR}/tfm_crypto_ipc_api.c
 							${INTERFACE_SRC_DIR}/tfm_initial_attestation_ipc_api.c
 							${INTERFACE_SRC_DIR}/tfm_sst_ipc_api.c
+							${INTERFACE_SRC_DIR}/tfm_its_ipc_api.c
 				DESTINATION ${EXPORT_SRC_DIR})
 	else()
 		install(FILES       ${INTERFACE_SRC_DIR}/tfm_crypto_func_api.c
 							${INTERFACE_SRC_DIR}/tfm_initial_attestation_func_api.c
 							${INTERFACE_SRC_DIR}/tfm_sst_func_api.c
+							${INTERFACE_SRC_DIR}/tfm_its_func_api.c
 				DESTINATION ${EXPORT_SRC_DIR})
 	endif()
 
@@ -366,6 +369,9 @@
 #Add the secure storage library target
 add_subdirectory(${SECURE_FW_DIR}/services/secure_storage)
 
+#Add the internal trusted storage library target
+add_subdirectory(${SECURE_FW_DIR}/services/internal_trusted_storage)
+
 #Add the platform service library target
 if (TFM_PARTITION_PLATFORM)
 	add_subdirectory(${SECURE_FW_DIR}/services/platform)
diff --git a/secure_fw/core/ipc/tfm_secure_irq_handlers_ipc.inc b/secure_fw/core/ipc/tfm_secure_irq_handlers_ipc.inc
index cc67b02..0bdf203 100644
--- a/secure_fw/core/ipc/tfm_secure_irq_handlers_ipc.inc
+++ b/secure_fw/core/ipc/tfm_secure_irq_handlers_ipc.inc
@@ -8,6 +8,7 @@
 /*********** WARNING: This is an auto-generated file. Do not edit! ***********/
 
 #include "secure_fw/services/secure_storage/psa_manifest/tfm_secure_storage.h"
+#include "secure_fw/services/internal_trusted_storage/psa_manifest/tfm_internal_trusted_storage.h"
 #include "secure_fw/services/audit_logging/psa_manifest/tfm_audit_logging.h"
 #include "secure_fw/services/crypto/psa_manifest/tfm_crypto.h"
 #include "secure_fw/services/platform/psa_manifest/tfm_platform.h"
diff --git a/secure_fw/core/tfm_secure_irq_handlers.inc b/secure_fw/core/tfm_secure_irq_handlers.inc
index 9c12be3..a48dcec 100644
--- a/secure_fw/core/tfm_secure_irq_handlers.inc
+++ b/secure_fw/core/tfm_secure_irq_handlers.inc
@@ -8,6 +8,7 @@
 /*********** WARNING: This is an auto-generated file. Do not edit! ***********/
 
 #include "secure_fw/services/secure_storage/psa_manifest/tfm_secure_storage.h"
+#include "secure_fw/services/internal_trusted_storage/psa_manifest/tfm_internal_trusted_storage.h"
 #include "secure_fw/services/audit_logging/psa_manifest/tfm_audit_logging.h"
 #include "secure_fw/services/crypto/psa_manifest/tfm_crypto.h"
 #include "secure_fw/services/platform/psa_manifest/tfm_platform.h"
diff --git a/secure_fw/ns_callable/tfm_veneers.c b/secure_fw/ns_callable/tfm_veneers.c
index fa8aacf..bfb01c3 100644
--- a/secure_fw/ns_callable/tfm_veneers.c
+++ b/secure_fw/ns_callable/tfm_veneers.c
@@ -17,6 +17,12 @@
 psa_status_t tfm_sst_remove_req(psa_invec *, size_t, psa_outvec *, size_t);
 psa_status_t tfm_sst_get_support_req(psa_invec *, size_t, psa_outvec *, size_t);
 
+/******** TFM_SP_ITS ********/
+psa_status_t tfm_its_set_req(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_its_get_req(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_its_get_info_req(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_its_remove_req(psa_invec *, size_t, psa_outvec *, size_t);
+
 #ifdef TFM_PARTITION_AUDIT_LOG
 /******** TFM_SP_AUDIT_LOG ********/
 psa_status_t audit_core_retrieve_record(psa_invec *, size_t, psa_outvec *, size_t);
@@ -137,6 +143,12 @@
 TFM_VENEER_FUNCTION(TFM_SP_STORAGE, tfm_sst_remove_req)
 TFM_VENEER_FUNCTION(TFM_SP_STORAGE, tfm_sst_get_support_req)
 
+/******** TFM_SP_ITS ********/
+TFM_VENEER_FUNCTION(TFM_SP_ITS, tfm_its_set_req)
+TFM_VENEER_FUNCTION(TFM_SP_ITS, tfm_its_get_req)
+TFM_VENEER_FUNCTION(TFM_SP_ITS, tfm_its_get_info_req)
+TFM_VENEER_FUNCTION(TFM_SP_ITS, tfm_its_remove_req)
+
 #ifdef TFM_PARTITION_AUDIT_LOG
 /******** TFM_SP_AUDIT_LOG ********/
 TFM_VENEER_FUNCTION(TFM_SP_AUDIT_LOG, audit_core_retrieve_record)
diff --git a/secure_fw/services/internal_trusted_storage/CMakeLists.inc b/secure_fw/services/internal_trusted_storage/CMakeLists.inc
new file mode 100644
index 0000000..a41e3af
--- /dev/null
+++ b/secure_fw/services/internal_trusted_storage/CMakeLists.inc
@@ -0,0 +1,96 @@
+#-------------------------------------------------------------------------------
+# Copyright (c) 2019, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#-------------------------------------------------------------------------------
+
+#Definitions to compile the "internal_trusted_storage" module.
+#This file assumes it will be included from a project specific cmakefile, and
+#will not create a library or executable.
+#Inputs:
+#    TFM_ROOT_DIR - root directory of the TF-M repository.
+#Outputs:
+#    Will modify include directories to make the source compile.
+#    ALL_SRC_C: C source files to be compiled will be added to this list. This shall be added to your add_executable or add_library command.
+#    ALL_SRC_CXX: C++ source files to be compiled will be added to this list. This shall be added to your add_executable or add_library command.
+#    ALL_SRC_ASM: assembly source files to be compiled will be added to this list. This shall be added to your add_executable or add_library command.
+#    Include directories will be modified by using the include_directories() commands as needed.
+
+#Get the current directory where this file is located.
+set(INTERNAL_TRUSTED_STORAGE_DIR ${CMAKE_CURRENT_LIST_DIR})
+
+#Check input variables
+if (NOT DEFINED TFM_ROOT_DIR)
+    message(FATAL_ERROR "Please set TFM_ROOT_DIR before including this file.")
+endif()
+
+if (NOT DEFINED ITS_CREATE_FLASH_LAYOUT)
+    message(FATAL_ERROR "Incomplete build configuration: ITS_CREATE_FLASH_LAYOUT is undefined. ")
+endif()
+
+if (NOT DEFINED ITS_VALIDATE_METADATA_FROM_FLASH)
+    message(FATAL_ERROR "Incomplete build configuration: ITS_VALIDATE_METADATA_FROM_FLASH is undefined. ")
+endif()
+
+if (NOT DEFINED ITS_RAM_FS)
+    message(FATAL_ERROR "Incomplete build configuration: ITS_RAM_FS is undefined. ")
+endif()
+
+set(INTERNAL_TRUSTED_STORAGE_C_SRC
+    "${INTERNAL_TRUSTED_STORAGE_DIR}/tfm_its_secure_api.c"
+    "${INTERNAL_TRUSTED_STORAGE_DIR}/tfm_its_req_mngr.c"
+    "${INTERNAL_TRUSTED_STORAGE_DIR}/tfm_internal_trusted_storage.c"
+    "${INTERNAL_TRUSTED_STORAGE_DIR}/its_utils.c"
+    "${INTERNAL_TRUSTED_STORAGE_DIR}/flash/its_flash.c"
+    "${INTERNAL_TRUSTED_STORAGE_DIR}/flash_fs/its_flash_fs.c"
+    "${INTERNAL_TRUSTED_STORAGE_DIR}/flash_fs/its_flash_fs_dblock.c"
+    "${INTERNAL_TRUSTED_STORAGE_DIR}/flash_fs/its_flash_fs_mblock.c"
+)
+
+if (ITS_VALIDATE_METADATA_FROM_FLASH)
+    set_property(SOURCE ${INTERNAL_TRUSTED_STORAGE_C_SRC} APPEND PROPERTY COMPILE_DEFINITIONS ITS_VALIDATE_METADATA_FROM_FLASH)
+endif()
+
+if (ITS_CREATE_FLASH_LAYOUT)
+    set_property(SOURCE ${INTERNAL_TRUSTED_STORAGE_C_SRC} APPEND PROPERTY COMPILE_DEFINITIONS ITS_CREATE_FLASH_LAYOUT)
+endif()
+
+if (ITS_RAM_FS)
+    set_property(SOURCE ${INTERNAL_TRUSTED_STORAGE_C_SRC} APPEND PROPERTY COMPILE_DEFINITIONS ITS_RAM_FS)
+endif()
+
+#Append all our source files to global lists.
+list(APPEND ALL_SRC_C ${INTERNAL_TRUSTED_STORAGE_C_SRC})
+unset(INTERNAL_TRUSTED_STORAGE_C_SRC)
+
+#Inform the user about ITS service features selected based on the ITS service CMake flags
+message("The ITS service compile configuration is as follows:")
+message("- ITS_VALIDATE_METADATA_FROM_FLASH: " ${ITS_VALIDATE_METADATA_FROM_FLASH})
+message("- ITS_CREATE_FLASH_LAYOUT: " ${ITS_CREATE_FLASH_LAYOUT})
+message("- ITS_RAM_FS: " ${ITS_RAM_FS})
+
+#Setting include directories
+embedded_include_directories(PATH ${TFM_ROOT_DIR} ABSOLUTE)
+embedded_include_directories(PATH ${TFM_ROOT_DIR}/interface/include ABSOLUTE)
+embedded_include_directories(PATH ${TFM_ROOT_DIR}/platform/ext/driver ABSOLUTE)
+set(BUILD_CMSIS_CORE Off)
+set(BUILD_RETARGET Off)
+set(BUILD_NATIVE_DRIVERS Off)
+set(BUILD_STARTUP Off)
+set(BUILD_TARGET_CFG Off)
+set(BUILD_TARGET_HARDWARE_KEYS Off)
+set(BUILD_TARGET_NV_COUNTERS Off)
+set(BUILD_CMSIS_DRIVERS Off)
+set(BUILD_TIME Off)
+set(BUILD_UART_STDOUT Off)
+set(BUILD_FLASH Off)
+set(BUILD_BOOT_SEED Off)
+set(BUILD_DEVICE_ID Off)
+if (NOT DEFINED PLATFORM_CMAKE_FILE)
+    message (FATAL_ERROR "Platform specific CMake is not defined. Please set PLATFORM_CMAKE_FILE.")
+elseif(NOT EXISTS ${PLATFORM_CMAKE_FILE})
+    message (FATAL_ERROR "Platform specific CMake \"${PLATFORM_CMAKE_FILE}\" file does not exist. Please fix value of PLATFORM_CMAKE_FILE.")
+else()
+    include(${PLATFORM_CMAKE_FILE})
+endif()
diff --git a/secure_fw/services/internal_trusted_storage/CMakeLists.txt b/secure_fw/services/internal_trusted_storage/CMakeLists.txt
new file mode 100644
index 0000000..765f556
--- /dev/null
+++ b/secure_fw/services/internal_trusted_storage/CMakeLists.txt
@@ -0,0 +1,41 @@
+#-------------------------------------------------------------------------------
+# Copyright (c) 2019, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#-------------------------------------------------------------------------------
+
+cmake_minimum_required(VERSION 3.7)
+
+# Tell cmake where our modules can be found
+list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}/../../../cmake)
+
+###Some project global settings
+set (INTERNAL_TRUSTED_STORAGE_DIR "${CMAKE_CURRENT_LIST_DIR}")
+get_filename_component(TFM_ROOT_DIR "${INTERNAL_TRUSTED_STORAGE_DIR}/../../.." ABSOLUTE)
+
+#Include common stuff to control cmake.
+include("Common/BuildSys")
+
+#Start an embedded project.
+embedded_project_start(CONFIG "${TFM_ROOT_DIR}/configs/ConfigDefault.cmake")
+project(tfm_internal_trusted_storage LANGUAGES ASM C)
+embedded_project_fixup()
+
+###Get the definition of what files we need to build
+include(CMakeLists.inc)
+
+if (NOT DEFINED TFM_LVL)
+    message(FATAL_ERROR "Incomplete build configuration: TFM_LVL is undefined. ")
+endif()
+
+# Specify what we build (for the internal trusted storage service, build as a static library)
+add_library(tfm_internal_trusted_storage STATIC ${ALL_SRC_ASM} ${ALL_SRC_C})
+
+#Set common compiler and linker flags
+config_setting_shared_compiler_flags(tfm_internal_trusted_storage)
+config_setting_shared_linker_flags(tfm_internal_trusted_storage)
+
+embedded_set_target_compile_defines(TARGET tfm_internal_trusted_storage LANGUAGE C DEFINES __ARM_FEATURE_CMSE=${ARM_FEATURE_CMSE} __thumb2__ TFM_LVL=${TFM_LVL})
+
+embedded_project_end(tfm_internal_trusted_storage)
diff --git a/secure_fw/services/internal_trusted_storage/psa_manifest/tfm_internal_trusted_storage.h b/secure_fw/services/internal_trusted_storage/psa_manifest/tfm_internal_trusted_storage.h
new file mode 100644
index 0000000..cd798c3
--- /dev/null
+++ b/secure_fw/services/internal_trusted_storage/psa_manifest/tfm_internal_trusted_storage.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2019, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+/*********** WARNING: This is an auto-generated file. Do not edit! ***********/
+
+#ifndef __PSA_MANIFEST_TFM_INTERNAL_TRUSTED_STORAGE_H__
+#define __PSA_MANIFEST_TFM_INTERNAL_TRUSTED_STORAGE_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define TFM_ITS_SET_SIG                                         (1U << ( 0 + 4))
+#define TFM_ITS_GET_SIG                                         (1U << ( 1 + 4))
+#define TFM_ITS_GET_INFO_SIG                                    (1U << ( 2 + 4))
+#define TFM_ITS_REMOVE_SIG                                      (1U << ( 3 + 4))
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __PSA_MANIFEST_TFM_INTERNAL_TRUSTED_STORAGE_H__ */
diff --git a/secure_fw/services/internal_trusted_storage/tfm_internal_trusted_storage.c b/secure_fw/services/internal_trusted_storage/tfm_internal_trusted_storage.c
new file mode 100644
index 0000000..c2814fe
--- /dev/null
+++ b/secure_fw/services/internal_trusted_storage/tfm_internal_trusted_storage.c
@@ -0,0 +1,215 @@
+/*
+ * Copyright (c) 2019, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include "tfm_internal_trusted_storage.h"
+#include "flash_fs/its_flash_fs.h"
+#include "tfm_memory_utils.h"
+#include "tfm_its_defs.h"
+#include "its_utils.h"
+
+static uint8_t g_fid[ITS_FILE_ID_SIZE];
+static struct its_file_info_t g_file_info;
+
+/**
+ * \brief Maps a pair of client id and uid to a file id.
+ *
+ * \param[in]  client_id  Identifier of the asset's owner (client)
+ * \param[in]  uid        Identifier for the data
+ * \param[out] fid        Identifier of the file
+ */
+static void tfm_its_get_fid(int32_t client_id,
+                            psa_storage_uid_t uid,
+                            uint8_t *fid)
+{
+    tfm_memcpy(fid, (const void *)&client_id, sizeof(client_id));
+    tfm_memcpy(fid + sizeof(client_id), (const void *)&uid, sizeof(uid));
+}
+
+psa_status_t tfm_its_init(void)
+{
+    psa_status_t status;
+
+    status = its_flash_fs_prepare();
+#ifdef ITS_CREATE_FLASH_LAYOUT
+    /* If ITS_CREATE_FLASH_LAYOUT is set, it indicates that it is required to
+     * create a ITS flash layout. ITS service will generate an empty and valid
+     * ITS flash layout to store assets. It will erase all data located in the
+     * assigned ITS memory area before generating the ITS layout.
+     * This flag is required to be set if the ITS memory area is located in
+     * non-persistent memory.
+     * This flag can be set if the ITS memory area is located in persistent
+     * memory without a previous valid ITS flash layout in it. That is the case
+     * when it is the first time in the device life that the ITS service is
+     * executed.
+     */
+     if (status != PSA_SUCCESS) {
+        /* Remove all data in the ITS memory area and create a valid ITS flash
+         * layout in that area.
+         */
+        status = its_flash_fs_wipe_all();
+        if (status != PSA_SUCCESS) {
+            return status;
+        }
+
+        /* Attempt to initialise again */
+        status = its_flash_fs_prepare();
+    }
+#endif /* ITS_CREATE_FLASH_LAYOUT */
+
+    return status;
+}
+
+psa_status_t tfm_its_set(int32_t client_id,
+                         psa_storage_uid_t uid,
+                         size_t data_length,
+                         const void *p_data,
+                         psa_storage_create_flags_t create_flags)
+{
+    psa_status_t status;
+
+    /* Check that the UID is valid */
+    if (uid == TFM_ITS_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 */
+    tfm_its_get_fid(client_id, uid, g_fid);
+
+    /* Read file info */
+    status = its_flash_fs_file_get_info(g_fid, &g_file_info);
+    if (status == PSA_SUCCESS) {
+        /* If the object exists and has the write once flag set, then it
+         * cannot be modified. Otherwise it needs to be removed.
+         */
+        if (g_file_info.flags & PSA_STORAGE_FLAG_WRITE_ONCE) {
+            return PSA_ERROR_NOT_PERMITTED;
+        } else {
+            status = its_flash_fs_file_delete(g_fid);
+            if (status != PSA_SUCCESS) {
+                return status;
+            }
+        }
+    } else if (status != PSA_ERROR_DOES_NOT_EXIST) {
+        /* If the file does not exist, then do nothing.
+         * If other error occurred, return it
+         */
+        return status;
+    }
+
+    /* Create the file in the file system */
+    return its_flash_fs_file_create(g_fid,
+                                    data_length,
+                                    data_length,
+                                    (uint32_t)create_flags,
+                                    (const uint8_t *)p_data);
+}
+
+psa_status_t tfm_its_get(int32_t client_id,
+                         psa_storage_uid_t uid,
+                         size_t data_offset,
+                         size_t data_size,
+                         void *p_data,
+                         size_t *p_data_length)
+{
+    psa_status_t status;
+
+    /* Check that the UID is valid */
+    if (uid == TFM_ITS_INVALID_UID) {
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    /* Set file id */
+    tfm_its_get_fid(client_id, uid, g_fid);
+
+    /* Read file info */
+    status = its_flash_fs_file_get_info(g_fid, &g_file_info);
+    if (status != PSA_SUCCESS) {
+        return status;
+    }
+
+    /* Boundary check the incoming request */
+    if (data_offset > g_file_info.size_current) {
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    /* Copy the object data only from within the file boundary */
+    data_size = ITS_UTILS_MIN(data_size,
+                              g_file_info.size_current - data_offset);
+
+    /* Read object data if any */
+    status = its_flash_fs_file_read(g_fid, data_size, data_offset, p_data);
+    if (status != PSA_SUCCESS) {
+        return status;
+    }
+
+    /* Update the size of the data placed in p_data */
+    *p_data_length = data_size;
+
+    return PSA_SUCCESS;
+}
+
+psa_status_t tfm_its_get_info(int32_t client_id, psa_storage_uid_t uid,
+                              struct psa_storage_info_t *p_info)
+{
+    psa_status_t status;
+
+    /* Check that the UID is valid */
+    if (uid == TFM_ITS_INVALID_UID) {
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    /* Set file id */
+    tfm_its_get_fid(client_id, uid, g_fid);
+
+    /* Read file info */
+    status = its_flash_fs_file_get_info(g_fid, &g_file_info);
+    if (status != PSA_SUCCESS) {
+        return status;
+    }
+
+    /* Copy file info to the PSA info struct */
+    p_info->capacity = g_file_info.size_current;
+    p_info->size = g_file_info.size_current;
+    p_info->flags = g_file_info.flags;
+
+    return PSA_SUCCESS;
+}
+
+psa_status_t tfm_its_remove(int32_t client_id, psa_storage_uid_t uid)
+{
+    psa_status_t status;
+
+    /* Check that the UID is valid */
+    if (uid == TFM_ITS_INVALID_UID) {
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    /* Set file id */
+    tfm_its_get_fid(client_id, uid, g_fid);
+
+    status = its_flash_fs_file_get_info(g_fid, &g_file_info);
+    if (status != PSA_SUCCESS) {
+        return status;
+    }
+
+    /* If the object exists and has the write once flag set, then it
+     * cannot be deleted.
+     */
+    if (g_file_info.flags & PSA_STORAGE_FLAG_WRITE_ONCE) {
+        return PSA_ERROR_NOT_PERMITTED;
+    }
+
+    /* Delete old file from the persistent area */
+    return its_flash_fs_file_delete(g_fid);
+}
diff --git a/secure_fw/services/internal_trusted_storage/tfm_internal_trusted_storage.h b/secure_fw/services/internal_trusted_storage/tfm_internal_trusted_storage.h
new file mode 100644
index 0000000..71c250d
--- /dev/null
+++ b/secure_fw/services/internal_trusted_storage/tfm_internal_trusted_storage.h
@@ -0,0 +1,175 @@
+/*
+ * Copyright (c) 2019, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef __TFM_INTERNAL_TRUSTED_STORAGE_H__
+#define __TFM_INTERNAL_TRUSTED_STORAGE_H__
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include "psa/error.h"
+#include "psa/storage_common.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief Initializes the internal trusted storage system.
+ *
+ * \return A status indicating the success/failure of the operation as specified
+ *         in \ref psa_status_t
+ *
+ * \retval PSA_SUCCESS                The operation completed successfully
+ * \retval PSA_ERROR_STORAGE_FAILURE  The operation failed because the storage
+ *                                    system initialization has failed (fatal
+ *                                    error)
+ * \retval PSA_ERROR_GENERIC_ERROR    The operation failed because of an
+ *                                    unspecified internal failure
+ */
+psa_status_t tfm_its_init(void);
+
+/**
+ * \brief Create a new, or modify an existing, uid/value pair
+ *
+ * Stores data in the internal storage.
+ *
+ * \param[in] client_id     Identifier of the asset's owner (client)
+ * \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_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
+ */
+psa_status_t tfm_its_set(int32_t client_id,
+                         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]  client_id      Identifier of the asset's owner (client)
+ * \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_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_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`.
+ */
+psa_status_t tfm_its_get(int32_t client_id,
+                         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` as a `psa_storage_info_t`
+ * structure.
+ *
+ * \param[in]  client_id  Identifier of the asset's owner (client)
+ * \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_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_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
+ */
+psa_status_t tfm_its_get_info(int32_t client_id, psa_storage_uid_t uid,
+                              struct psa_storage_info_t *p_info);
+
+/**
+ * \brief Remove the provided uid and its associated data from the storage
+ *
+ * Deletes the data from internal storage.
+ *
+ * \param[in] client_id  Identifier of the asset's owner (client)
+ * \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)
+ */
+psa_status_t tfm_its_remove(int32_t client_id, psa_storage_uid_t uid);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __TFM_INTERNAL_TRUSTED_STORAGE_H__ */
diff --git a/secure_fw/services/internal_trusted_storage/tfm_internal_trusted_storage.yaml b/secure_fw/services/internal_trusted_storage/tfm_internal_trusted_storage.yaml
new file mode 100644
index 0000000..06afa04
--- /dev/null
+++ b/secure_fw/services/internal_trusted_storage/tfm_internal_trusted_storage.yaml
@@ -0,0 +1,84 @@
+#-------------------------------------------------------------------------------
+# Copyright (c) 2019, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#-------------------------------------------------------------------------------
+
+{
+  "name": "TFM_SP_ITS",
+  "type": "PSA-ROT",
+  "priority": "NORMAL",
+  "id": "0x00000104",
+  "entry_point": "tfm_its_req_mngr_init",
+  "stack_size": "0x500",
+  "heap_size": "0",
+  "secure_functions": [
+    {
+      "sfid": "TFM_ITS_SET",
+      "signal": "TFM_ITS_SET_REQ",
+      "non_secure_clients": true,
+      "minor_version": 1,
+      "minor_policy": "STRICT"
+    },
+    {
+      "sfid": "TFM_ITS_GET",
+      "signal": "TFM_ITS_GET_REQ",
+      "non_secure_clients": true,
+      "minor_version": 1,
+      "minor_policy": "STRICT"
+    },
+    {
+      "sfid": "TFM_ITS_GET_INFO",
+      "signal": "TFM_ITS_GET_INFO_REQ",
+      "non_secure_clients": true,
+      "minor_version": 1,
+      "minor_policy": "STRICT"
+    },
+    {
+      "sfid": "TFM_ITS_REMOVE",
+      "signal": "TFM_ITS_REMOVE_REQ",
+      "non_secure_clients": true,
+      "minor_version": 1,
+      "minor_policy": "STRICT"
+    }
+  ],
+  "services" : [{
+    "name": "TFM_ITS_SET",
+    "sid": "0x00000070",
+    "signal": "TFM_ITS_SET_SIG",
+    "non_secure_clients": true,
+    "minor_version": 1,
+    "minor_policy": "STRICT"
+   },
+   {
+    "name": "TFM_ITS_GET",
+    "sid": "0x00000071",
+    "signal": "TFM_ITS_GET_SIG",
+    "non_secure_clients": true,
+    "minor_version": 1,
+    "minor_policy": "STRICT"
+   },
+   {
+    "name": "TFM_ITS_GET_INFO",
+    "sid": "0x00000072",
+    "signal": "TFM_ITS_GET_INFO_SIG",
+    "non_secure_clients": true,
+    "minor_version": 1,
+    "minor_policy": "STRICT"
+   },
+   {
+    "name": "TFM_ITS_REMOVE",
+    "sid": "0x00000073",
+    "signal": "TFM_ITS_REMOVE_SIG",
+    "non_secure_clients": true,
+    "minor_version": 1,
+    "minor_policy": "STRICT"
+   }
+  ],
+  "linker_pattern": {
+    "library_list": [
+      "*tfm_internal_trusted_storage*"
+    ]
+  }
+}
diff --git a/secure_fw/services/internal_trusted_storage/tfm_its_req_mngr.c b/secure_fw/services/internal_trusted_storage/tfm_its_req_mngr.c
new file mode 100644
index 0000000..bdd755c
--- /dev/null
+++ b/secure_fw/services/internal_trusted_storage/tfm_its_req_mngr.c
@@ -0,0 +1,384 @@
+/*
+ * Copyright (c) 2019, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include "tfm_its_req_mngr.h"
+
+#include <stdint.h>
+
+#include "psa/storage_common.h"
+#include "tfm_internal_trusted_storage.h"
+#include "its_utils.h"
+#include "flash_layout.h"
+
+#ifdef TFM_PSA_API
+#include "psa/service.h"
+#include "psa_manifest/tfm_internal_trusted_storage.h"
+#else
+#include <stdbool.h>
+#include "tfm_secure_api.h"
+#include "tfm_memory_utils.h"
+#include "tfm_api.h"
+#endif
+
+static uint8_t asset_data[GET_ALIGNED_FLASH_BYTES(ITS_MAX_ASSET_SIZE)] = {0};
+
+#ifndef TFM_PSA_API
+/**
+ * \brief Indicates whether ITS has been initialised.
+ */
+static bool its_is_init = false;
+
+psa_status_t tfm_its_set_req(psa_invec *in_vec, size_t in_len,
+                             psa_outvec *out_vec, size_t out_len)
+{
+    psa_storage_uid_t uid;
+    size_t data_length;
+    const void *p_data;
+    psa_storage_create_flags_t create_flags;
+    int32_t client_id;
+
+    (void)out_vec;
+
+    if (!its_is_init) {
+        return PSA_ERROR_GENERIC_ERROR;
+    }
+
+    if ((in_len != 3) || (out_len != 0)) {
+        /* The number of arguments is incorrect */
+        return PSA_ERROR_PROGRAMMER_ERROR;
+    }
+
+    if (in_vec[0].len != sizeof(uid) ||
+        in_vec[2].len != sizeof(create_flags)) {
+        /* The size of one of the arguments is incorrect */
+        return PSA_ERROR_PROGRAMMER_ERROR;
+    }
+
+    uid = *((psa_storage_uid_t *)in_vec[0].base);
+
+    p_data = in_vec[1].base;
+    data_length = in_vec[1].len;
+
+    /* Boundary check the incoming request */
+    if (data_length > sizeof(asset_data)) {
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+    tfm_memcpy(asset_data, p_data, data_length);
+
+    create_flags = *(psa_storage_create_flags_t *)in_vec[2].base;
+
+    /* Get the caller's client ID */
+    if (tfm_core_get_caller_client_id(&client_id) != (int32_t)TFM_SUCCESS) {
+        return PSA_ERROR_PROGRAMMER_ERROR;
+    }
+
+    return tfm_its_set(client_id, uid, data_length, asset_data, create_flags);
+}
+
+psa_status_t tfm_its_get_req(psa_invec *in_vec, size_t in_len,
+                             psa_outvec *out_vec, size_t out_len)
+{
+    psa_status_t status;
+    psa_storage_uid_t uid;
+    size_t data_offset;
+    size_t data_size;
+    void *p_data;
+    size_t *p_data_length;
+    int32_t client_id;
+
+    if (!its_is_init) {
+        return PSA_ERROR_GENERIC_ERROR;
+    }
+
+    if ((in_len != 2) || (out_len != 1)) {
+        /* The number of arguments is incorrect */
+        return PSA_ERROR_PROGRAMMER_ERROR;
+    }
+
+    if (in_vec[0].len != sizeof(uid) ||
+        in_vec[1].len != sizeof(data_offset)) {
+        /* The size of one of the arguments is incorrect */
+        return PSA_ERROR_PROGRAMMER_ERROR;
+    }
+
+    uid = *((psa_storage_uid_t *)in_vec[0].base);
+
+    data_offset = *(size_t *)in_vec[1].base;
+
+    p_data = out_vec[0].base;
+    data_size = out_vec[0].len;
+
+    p_data_length = &out_vec[0].len;
+
+    /* Get the caller's client ID */
+    if (tfm_core_get_caller_client_id(&client_id) != (int32_t)TFM_SUCCESS) {
+        return PSA_ERROR_PROGRAMMER_ERROR;
+    }
+
+    status =  tfm_its_get(client_id, uid, data_offset, data_size, asset_data,
+                          p_data_length);
+    if (status == PSA_SUCCESS) {
+        tfm_memcpy(p_data, asset_data, *p_data_length);
+    }
+
+    return status;
+}
+
+psa_status_t tfm_its_get_info_req(psa_invec *in_vec, size_t in_len,
+                                  psa_outvec *out_vec, size_t out_len)
+{
+    psa_storage_uid_t uid;
+    struct psa_storage_info_t *p_info;
+    int32_t client_id;
+
+    if (!its_is_init) {
+        return PSA_ERROR_GENERIC_ERROR;
+    }
+
+    if ((in_len != 1) || (out_len != 1)) {
+        /* The number of arguments is incorrect */
+        return PSA_ERROR_PROGRAMMER_ERROR;
+    }
+
+    if (in_vec[0].len != sizeof(uid) ||
+        out_vec[0].len != sizeof(*p_info)) {
+        /* The size of one of the arguments is incorrect */
+        return PSA_ERROR_PROGRAMMER_ERROR;
+    }
+
+    uid = *((psa_storage_uid_t *)in_vec[0].base);
+
+    p_info = (struct psa_storage_info_t *)out_vec[0].base;
+
+    /* Get the caller's client ID */
+    if (tfm_core_get_caller_client_id(&client_id) != (int32_t)TFM_SUCCESS) {
+        return PSA_ERROR_PROGRAMMER_ERROR;
+    }
+
+    return tfm_its_get_info(client_id, uid, p_info);
+}
+
+psa_status_t tfm_its_remove_req(psa_invec *in_vec, size_t in_len,
+                                psa_outvec *out_vec, size_t out_len)
+{
+    psa_storage_uid_t uid;
+    int32_t client_id;
+
+    (void)out_vec;
+
+    if (!its_is_init) {
+        return PSA_ERROR_GENERIC_ERROR;
+    }
+
+    if ((in_len != 1) || (out_len != 0)) {
+        /* The number of arguments is incorrect */
+        return PSA_ERROR_PROGRAMMER_ERROR;
+    }
+
+    if (in_vec[0].len != sizeof(uid)) {
+        /* The input argument size is incorrect */
+        return PSA_ERROR_PROGRAMMER_ERROR;
+    }
+
+    uid = *((psa_storage_uid_t *)in_vec[0].base);
+
+    /* Get the caller's client ID */
+    if (tfm_core_get_caller_client_id(&client_id) != (int32_t)TFM_SUCCESS) {
+        return PSA_ERROR_PROGRAMMER_ERROR;
+    }
+
+    return tfm_its_remove(client_id, uid);
+}
+
+#else /* !defined(TFM_PSA_API) */
+typedef psa_status_t (*its_func_t)(const psa_msg_t *msg);
+
+static psa_status_t tfm_its_set_ipc(const psa_msg_t *msg)
+{
+    psa_storage_uid_t uid;
+    size_t data_length;
+    psa_storage_create_flags_t create_flags;
+    size_t num;
+
+    if (msg->in_size[0] != sizeof(uid) ||
+        msg->in_size[2] != sizeof(create_flags)) {
+        /* The size of one of the arguments is incorrect */
+        return PSA_ERROR_PROGRAMMER_ERROR;
+    }
+
+    data_length = msg->in_size[1];
+    if (data_length > sizeof(asset_data)) {
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    num = psa_read(msg->handle, 0, &uid, sizeof(uid));
+    if (num != sizeof(uid)) {
+        return PSA_ERROR_PROGRAMMER_ERROR;
+    }
+
+    num = psa_read(msg->handle, 1, &asset_data, data_length);
+    if (num != data_length) {
+        return PSA_ERROR_PROGRAMMER_ERROR;
+    }
+
+    num = psa_read(msg->handle, 2, &create_flags, sizeof(create_flags));
+    if (num != sizeof(create_flags)) {
+        return PSA_ERROR_PROGRAMMER_ERROR;
+    }
+
+    return tfm_its_set(msg->client_id, uid, data_length, asset_data,
+                       create_flags);
+}
+
+static psa_status_t tfm_its_get_ipc(const psa_msg_t *msg)
+{
+    psa_status_t status;
+    psa_storage_uid_t uid;
+    size_t data_offset;
+    size_t data_size;
+    size_t data_length;
+    size_t num;
+
+    if (msg->in_size[0] != sizeof(uid) ||
+        msg->in_size[1] != sizeof(data_offset)) {
+        /* The size of one of the arguments is incorrect */
+        return PSA_ERROR_PROGRAMMER_ERROR;
+    }
+
+    num = psa_read(msg->handle, 0, &uid, sizeof(uid));
+    if (num != sizeof(uid)) {
+        return PSA_ERROR_PROGRAMMER_ERROR;
+    }
+
+    num = psa_read(msg->handle, 1, &data_offset, sizeof(data_offset));
+    if (num != sizeof(data_offset)) {
+        return PSA_ERROR_PROGRAMMER_ERROR;
+    }
+
+    data_size = msg->out_size[0];
+
+    status = tfm_its_get(msg->client_id, uid, data_offset, data_size,
+                         asset_data, &data_length);
+    if (status == PSA_SUCCESS) {
+        psa_write(msg->handle, 0, asset_data, data_length);
+    }
+
+    return status;
+}
+
+static psa_status_t tfm_its_get_info_ipc(const psa_msg_t *msg)
+{
+    psa_status_t status;
+    psa_storage_uid_t uid;
+    struct psa_storage_info_t info;
+    size_t num;
+
+    if (msg->in_size[0] != sizeof(uid) ||
+        msg->out_size[0] != sizeof(info)) {
+        /* The size of one of the arguments is incorrect */
+        return PSA_ERROR_PROGRAMMER_ERROR;
+    }
+
+    num = psa_read(msg->handle, 0, &uid, sizeof(uid));
+    if (num != sizeof(uid)) {
+        return PSA_ERROR_PROGRAMMER_ERROR;
+    }
+
+    status = tfm_its_get_info(msg->client_id, uid, &info);
+    if (status == PSA_SUCCESS) {
+        psa_write(msg->handle, 0, &info, sizeof(info));
+    }
+
+    return status;
+}
+
+static psa_status_t tfm_its_remove_ipc(const psa_msg_t *msg)
+{
+    psa_storage_uid_t uid;
+    size_t num;
+
+    if (msg->in_size[0] != sizeof(uid)) {
+        /* The input argument size is incorrect */
+        return PSA_ERROR_PROGRAMMER_ERROR;
+    }
+
+    num = psa_read(msg->handle, 0, &uid, sizeof(uid));
+    if (num != sizeof(uid)) {
+        return PSA_ERROR_PROGRAMMER_ERROR;
+    }
+
+    return tfm_its_remove(msg->client_id, uid);
+}
+
+/*
+ * Fixme: Temporarily implement abort as infinite loop,
+ * will replace it later.
+ */
+static void tfm_abort(void)
+{
+    while (1)
+        ;
+}
+
+static void its_signal_handle(psa_signal_t signal, its_func_t pfn)
+{
+    psa_msg_t msg;
+    psa_status_t status;
+
+    status = psa_get(signal, &msg);
+    if (status != PSA_SUCCESS) {
+        return;
+    }
+
+    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 /* !defined(TFM_PSA_API) */
+
+psa_status_t tfm_its_req_mngr_init(void)
+{
+#ifdef TFM_PSA_API
+    psa_signal_t signals = 0;
+
+    if (tfm_its_init() != PSA_SUCCESS) {
+        tfm_abort();
+    }
+
+    while (1) {
+        signals = psa_wait(PSA_WAIT_ANY, PSA_BLOCK);
+        if (signals & TFM_ITS_SET_SIG) {
+            its_signal_handle(TFM_ITS_SET_SIG, tfm_its_set_ipc);
+        } else if (signals & TFM_ITS_GET_SIG) {
+            its_signal_handle(TFM_ITS_GET_SIG, tfm_its_get_ipc);
+        } else if (signals & TFM_ITS_GET_INFO_SIG) {
+            its_signal_handle(TFM_ITS_GET_INFO_SIG, tfm_its_get_info_ipc);
+        } else if (signals & TFM_ITS_REMOVE_SIG) {
+            its_signal_handle(TFM_ITS_REMOVE_SIG, tfm_its_remove_ipc);
+        } else {
+            tfm_abort();
+        }
+    }
+#else
+    if (tfm_its_init() != PSA_SUCCESS) {
+        return PSA_ERROR_GENERIC_ERROR;
+    }
+    its_is_init = true;
+#endif
+    return PSA_SUCCESS;
+}
diff --git a/secure_fw/services/internal_trusted_storage/tfm_its_req_mngr.h b/secure_fw/services/internal_trusted_storage/tfm_its_req_mngr.h
new file mode 100644
index 0000000..6bebbc7
--- /dev/null
+++ b/secure_fw/services/internal_trusted_storage/tfm_its_req_mngr.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2019, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef __TFM_ITS_REQ_MNGR_H__
+#define __TFM_ITS_REQ_MNGR_H__
+
+#include <stddef.h>
+
+#include "psa/client.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief Handles the set request.
+ *
+ * \param[in]  in_vec  Pointer to the input vector which contains the input
+ *                     parameters.
+ * \param[in]  in_len  Number of input parameters in the input vector.
+ * \param[out] out_vec Pointer to the output vector which contains the output
+ *                     parameters.
+ * \param[in]  out_len Number of output parameters in the output vector.
+ *
+ * \return A status indicating the success/failure of the operation as specified
+ *         in \ref psa_status_t
+ */
+psa_status_t tfm_its_set_req(psa_invec *in_vec, size_t in_len,
+                             psa_outvec *out_vec, size_t out_len);
+
+/**
+ * \brief Handles the get request.
+ *
+ * \param[in]  in_vec  Pointer to the input vector which contains the input
+ *                     parameters.
+ * \param[in]  in_len  Number of input parameters in the input vector.
+ * \param[out] out_vec Pointer to the output vector which contains the output
+ *                     parameters.
+ * \param[in]  out_len Number of output parameters in the output vector.
+ *
+ * \return A status indicating the success/failure of the operation as specified
+ *         in \ref psa_status_t
+ */
+psa_status_t tfm_its_get_req(psa_invec *in_vec, size_t in_len,
+                             psa_outvec *out_vec, size_t out_len);
+
+/**
+ * \brief Handles the get info request.
+ *
+ * \param[in]  in_vec  Pointer to the input vector which contains the input
+ *                     parameters.
+ * \param[in]  in_len  Number of input parameters in the input vector.
+ * \param[out] out_vec Pointer to the output vector which contains the output
+ *                     parameters.
+ * \param[in]  out_len Number of output parameters in the output vector.
+ *
+ * \return A status indicating the success/failure of the operation as specified
+ *         in \ref psa_status_t
+ */
+psa_status_t tfm_its_get_info_req(psa_invec *in_vec, size_t in_len,
+                                  psa_outvec *out_vec, size_t out_len);
+
+/**
+ * \brief Handles the remove request.
+ *
+ * \param[in]  in_vec  Pointer to the input vector which contains the input
+ *                     parameters.
+ * \param[in]  in_len  Number of input parameters in the input vector.
+ * \param[out] out_vec Pointer to the output vector which contains the output
+ *                     parameters.
+ * \param[in]  out_len Number of output parameters in the output vector.
+ *
+ * \return A status indicating the success/failure of the operation as specified
+ *         in \ref psa_status_t
+ */
+psa_status_t tfm_its_remove_req(psa_invec *in_vec, size_t in_len,
+                                psa_outvec *out_vec, size_t out_len);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __TFM_ITS_REQ_MNGR_H__ */
diff --git a/secure_fw/services/internal_trusted_storage/tfm_its_secure_api.c b/secure_fw/services/internal_trusted_storage/tfm_its_secure_api.c
new file mode 100644
index 0000000..f06ed6b
--- /dev/null
+++ b/secure_fw/services/internal_trusted_storage/tfm_its_secure_api.c
@@ -0,0 +1,190 @@
+/*
+ * Copyright (c) 2019, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include "psa/internal_trusted_storage.h"
+#include "tfm_api.h"
+
+#ifdef TFM_PSA_API
+#include "psa/client.h"
+#include "psa_manifest/sid.h"
+#else
+#include "tfm_veneers.h"
+#endif
+
+#define IOVEC_LEN(x) (sizeof(x)/sizeof(x[0]))
+
+__attribute__((section("SFN")))
+psa_status_t psa_its_set(psa_storage_uid_t uid,
+                         size_t data_length,
+                         const void *p_data,
+                         psa_storage_create_flags_t create_flags)
+{
+    psa_status_t status;
+#ifdef TFM_PSA_API
+    psa_handle_t handle;
+#endif
+
+    psa_invec in_vec[] = {
+        { .base = &uid, .len = sizeof(uid) },
+        { .base = p_data, .len = data_length },
+        { .base = &create_flags, .len = sizeof(create_flags) }
+    };
+
+#ifdef TFM_PSA_API
+    handle = psa_connect(TFM_ITS_SET_SID, TFM_ITS_SET_VERSION);
+    if (!PSA_HANDLE_IS_VALID(handle)) {
+        return PSA_ERROR_GENERIC_ERROR;
+    }
+
+    status = psa_call(handle, PSA_IPC_CALL, in_vec, IOVEC_LEN(in_vec), NULL, 0);
+
+    psa_close(handle);
+#else
+    status = tfm_tfm_its_set_req_veneer(in_vec, IOVEC_LEN(in_vec), NULL, 0);
+#endif
+
+    /* A parameter with a buffer pointer where its data length is longer than
+     * maximum permitted, it is treated as a secure violation.
+     * TF-M framework rejects the request with TFM_ERROR_INVALID_PARAMETER.
+     * The ITS secure PSA implementation returns PSA_ERROR_INVALID_ARGUMENT in
+     * that case.
+     */
+    if (status == (psa_status_t)TFM_ERROR_INVALID_PARAMETER) {
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    return status;
+}
+
+__attribute__((section("SFN")))
+psa_status_t psa_its_get(psa_storage_uid_t uid,
+                         size_t data_offset,
+                         size_t data_size,
+                         void *p_data,
+                         size_t *p_data_length)
+{
+    psa_status_t status;
+#ifdef TFM_PSA_API
+    psa_handle_t handle;
+#endif
+
+    psa_invec in_vec[] = {
+        { .base = &uid, .len = sizeof(uid) },
+        { .base = &data_offset, .len = sizeof(data_offset) }
+    };
+
+    psa_outvec out_vec[] = {
+        { .base = p_data, .len = data_size }
+    };
+
+    if (p_data_length == NULL) {
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+#ifdef TFM_PSA_API
+    handle = psa_connect(TFM_ITS_GET_SID, TFM_ITS_GET_VERSION);
+    if (!PSA_HANDLE_IS_VALID(handle)) {
+        return PSA_ERROR_GENERIC_ERROR;
+    }
+
+    status = psa_call(handle, PSA_IPC_CALL, in_vec, IOVEC_LEN(in_vec), out_vec,
+                      IOVEC_LEN(out_vec));
+
+    psa_close(handle);
+#else
+    status = tfm_tfm_its_get_req_veneer(in_vec, IOVEC_LEN(in_vec),
+                                        out_vec, IOVEC_LEN(out_vec));
+#endif
+
+    /* A parameter with a buffer pointer where its data length is longer than
+     * maximum permitted or a parameter with a null pointer, it is treated as a
+     * secure violation.
+     * TF-M framework rejects the request with TFM_ERROR_INVALID_PARAMETER.
+     * The ITS secure PSA implementation returns PSA_ERROR_INVALID_ARGUMENT in
+     * that case.
+     */
+    if (status == (psa_status_t)TFM_ERROR_INVALID_PARAMETER) {
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    *p_data_length = out_vec[0].len;
+
+    return status;
+}
+
+__attribute__((section("SFN")))
+psa_status_t psa_its_get_info(psa_storage_uid_t uid,
+                              struct psa_storage_info_t *p_info)
+{
+    psa_status_t status;
+#ifdef TFM_PSA_API
+    psa_handle_t handle;
+#endif
+
+    psa_invec in_vec[] = {
+        { .base = &uid, .len = sizeof(uid) }
+    };
+
+    psa_outvec out_vec[] = {
+        { .base = p_info, .len = sizeof(*p_info) }
+    };
+
+#ifdef TFM_PSA_API
+    handle = psa_connect(TFM_ITS_GET_INFO_SID, TFM_ITS_GET_INFO_VERSION);
+    if (!PSA_HANDLE_IS_VALID(handle)) {
+        return PSA_ERROR_GENERIC_ERROR;
+    }
+
+    status = psa_call(handle, PSA_IPC_CALL, in_vec, IOVEC_LEN(in_vec), out_vec,
+                      IOVEC_LEN(out_vec));
+
+    psa_close(handle);
+#else
+    status = tfm_tfm_its_get_info_req_veneer(in_vec, IOVEC_LEN(in_vec),
+                                             out_vec, IOVEC_LEN(out_vec));
+#endif
+
+    /* A parameter with a null pointer is treated as a secure violation.
+     * TF-M framework rejects the request with TFM_ERROR_INVALID_PARAMETER.
+     * The secure PSA ITS implementation returns PSA_ERROR_INVALID_ARGUMENT
+     * in that case.
+     */
+    if (status == (psa_status_t)TFM_ERROR_INVALID_PARAMETER) {
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    return status;
+}
+
+__attribute__((section("SFN")))
+psa_status_t psa_its_remove(psa_storage_uid_t uid)
+{
+    psa_status_t status;
+#ifdef TFM_PSA_API
+    psa_handle_t handle;
+#endif
+
+    psa_invec in_vec[] = {
+        { .base = &uid, .len = sizeof(uid) }
+    };
+
+#ifdef TFM_PSA_API
+    handle = psa_connect(TFM_ITS_REMOVE_SID, TFM_ITS_REMOVE_VERSION);
+    if (!PSA_HANDLE_IS_VALID(handle)) {
+        return PSA_ERROR_GENERIC_ERROR;
+    }
+
+    status = psa_call(handle, PSA_IPC_CALL, in_vec, IOVEC_LEN(in_vec), NULL, 0);
+
+    psa_close(handle);
+
+#else
+    status = tfm_tfm_its_remove_req_veneer(in_vec, IOVEC_LEN(in_vec), NULL, 0);
+#endif
+
+    return status;
+}
diff --git a/secure_fw/services/tfm_partition_defs.inc b/secure_fw/services/tfm_partition_defs.inc
index b81f8c5..8bd8fa4 100644
--- a/secure_fw/services/tfm_partition_defs.inc
+++ b/secure_fw/services/tfm_partition_defs.inc
@@ -12,42 +12,44 @@
 
 #define TFM_SP_STORAGE_ID (TFM_SP_BASE + 0)
 
+#define TFM_SP_ITS_ID (TFM_SP_BASE + 1)
+
 #ifdef TFM_PARTITION_AUDIT_LOG
-#define TFM_SP_AUDIT_LOG_ID (TFM_SP_BASE + 1)
+#define TFM_SP_AUDIT_LOG_ID (TFM_SP_BASE + 2)
 #endif /* TFM_PARTITION_AUDIT_LOG */
 
-#define TFM_SP_CRYPTO_ID (TFM_SP_BASE + 2)
+#define TFM_SP_CRYPTO_ID (TFM_SP_BASE + 3)
 
 #ifdef TFM_PARTITION_PLATFORM
-#define TFM_SP_PLATFORM_ID (TFM_SP_BASE + 3)
+#define TFM_SP_PLATFORM_ID (TFM_SP_BASE + 4)
 #endif /* TFM_PARTITION_PLATFORM */
 
-#define TFM_SP_INITIAL_ATTESTATION_ID (TFM_SP_BASE + 4)
+#define TFM_SP_INITIAL_ATTESTATION_ID (TFM_SP_BASE + 5)
 
 #ifdef TFM_PARTITION_TEST_CORE
-#define TFM_SP_CORE_TEST_ID (TFM_SP_BASE + 5)
+#define TFM_SP_CORE_TEST_ID (TFM_SP_BASE + 6)
 #endif /* TFM_PARTITION_TEST_CORE */
 
 #ifdef TFM_PARTITION_TEST_CORE
-#define TFM_SP_CORE_TEST_2_ID (TFM_SP_BASE + 6)
+#define TFM_SP_CORE_TEST_2_ID (TFM_SP_BASE + 7)
 #endif /* TFM_PARTITION_TEST_CORE */
 
 #ifdef TFM_PARTITION_TEST_SECURE_SERVICES
-#define TFM_SP_SECURE_TEST_PARTITION_ID (TFM_SP_BASE + 7)
+#define TFM_SP_SECURE_TEST_PARTITION_ID (TFM_SP_BASE + 8)
 #endif /* TFM_PARTITION_TEST_SECURE_SERVICES */
 
 #ifdef TFM_PARTITION_TEST_CORE_IPC
-#define TFM_SP_IPC_SERVICE_TEST_ID (TFM_SP_BASE + 8)
+#define TFM_SP_IPC_SERVICE_TEST_ID (TFM_SP_BASE + 9)
 #endif /* TFM_PARTITION_TEST_CORE_IPC */
 
 #ifdef TFM_PARTITION_TEST_CORE_IPC
-#define TFM_SP_IPC_CLIENT_TEST_ID (TFM_SP_BASE + 9)
+#define TFM_SP_IPC_CLIENT_TEST_ID (TFM_SP_BASE + 10)
 #endif /* TFM_PARTITION_TEST_CORE_IPC */
 
 #ifdef TFM_ENABLE_IRQ_TEST
-#define TFM_IRQ_TEST_1_ID (TFM_SP_BASE + 10)
+#define TFM_IRQ_TEST_1_ID (TFM_SP_BASE + 11)
 #endif /* TFM_ENABLE_IRQ_TEST */
 
-#define TFM_MAX_USER_PARTITIONS (11)
+#define TFM_MAX_USER_PARTITIONS (12)
 
 #endif /* __TFM_PARTITION_DEFS_INC__ */
diff --git a/secure_fw/services/tfm_service_list.inc b/secure_fw/services/tfm_service_list.inc
index 1d41c77..19e968b 100644
--- a/secure_fw/services/tfm_service_list.inc
+++ b/secure_fw/services/tfm_service_list.inc
@@ -11,6 +11,7 @@
 #define __TFM_SERVICE_LIST_INC__
 
 #include "secure_fw/services/secure_storage/psa_manifest/tfm_secure_storage.h"
+#include "secure_fw/services/internal_trusted_storage/psa_manifest/tfm_internal_trusted_storage.h"
 #include "secure_fw/services/audit_logging/psa_manifest/tfm_audit_logging.h"
 #include "secure_fw/services/crypto/psa_manifest/tfm_crypto.h"
 #include "secure_fw/services/platform/psa_manifest/tfm_platform.h"
@@ -71,6 +72,44 @@
         .minor_policy = TFM_VERSION_POLICY_STRICT
     },
 
+    /******** TFM_SP_ITS ********/
+    {
+        .name = "TFM_ITS_SET",
+        .partition_id = TFM_SP_ITS_ID,
+        .signal = TFM_ITS_SET_SIG,
+        .sid = 0x00000070,
+        .non_secure_client = true,
+        .minor_version = 1,
+        .minor_policy = TFM_VERSION_POLICY_STRICT
+    },
+    {
+        .name = "TFM_ITS_GET",
+        .partition_id = TFM_SP_ITS_ID,
+        .signal = TFM_ITS_GET_SIG,
+        .sid = 0x00000071,
+        .non_secure_client = true,
+        .minor_version = 1,
+        .minor_policy = TFM_VERSION_POLICY_STRICT
+    },
+    {
+        .name = "TFM_ITS_GET_INFO",
+        .partition_id = TFM_SP_ITS_ID,
+        .signal = TFM_ITS_GET_INFO_SIG,
+        .sid = 0x00000072,
+        .non_secure_client = true,
+        .minor_version = 1,
+        .minor_policy = TFM_VERSION_POLICY_STRICT
+    },
+    {
+        .name = "TFM_ITS_REMOVE",
+        .partition_id = TFM_SP_ITS_ID,
+        .signal = TFM_ITS_REMOVE_SIG,
+        .sid = 0x00000073,
+        .non_secure_client = true,
+        .minor_version = 1,
+        .minor_policy = TFM_VERSION_POLICY_STRICT
+    },
+
     /******** TFM_SP_CRYPTO ********/
     {
         .name = "TFM_CRYPTO",
@@ -440,6 +479,36 @@
         .list = {0},
     },
 
+    /******** TFM_SP_ITS ********/
+    {
+        .service_db = NULL,
+        .partition = NULL,
+        .handle_list = {0},
+        .msg_queue = {0},
+        .list = {0},
+    },
+    {
+        .service_db = NULL,
+        .partition = NULL,
+        .handle_list = {0},
+        .msg_queue = {0},
+        .list = {0},
+    },
+    {
+        .service_db = NULL,
+        .partition = NULL,
+        .handle_list = {0},
+        .msg_queue = {0},
+        .list = {0},
+    },
+    {
+        .service_db = NULL,
+        .partition = NULL,
+        .handle_list = {0},
+        .msg_queue = {0},
+        .list = {0},
+    },
+
     /******** TFM_SP_CRYPTO ********/
     {
         .service_db = NULL,
diff --git a/secure_fw/services/tfm_spm_db.inc b/secure_fw/services/tfm_spm_db.inc
index 6d2bef6..d0dd9ae 100644
--- a/secure_fw/services/tfm_spm_db.inc
+++ b/secure_fw/services/tfm_spm_db.inc
@@ -17,6 +17,8 @@
 /**************************************************************************/
 #define TFM_PARTITION_TFM_SP_STORAGE_IRQ_COUNT 0
 
+#define TFM_PARTITION_TFM_SP_ITS_IRQ_COUNT 0
+
 #ifdef TFM_PARTITION_AUDIT_LOG
 #define TFM_PARTITION_TFM_SP_AUDIT_LOG_IRQ_COUNT 0
 #endif /* TFM_PARTITION_AUDIT_LOG */
@@ -62,6 +64,8 @@
 
 extern int32_t tfm_sst_req_mngr_init(void);
 
+extern int32_t tfm_its_req_mngr_init(void);
+
 #ifdef TFM_PARTITION_AUDIT_LOG
 extern int32_t audit_core_init(void);
 #endif /* TFM_PARTITION_AUDIT_LOG */
@@ -116,6 +120,17 @@
 REGION_DECLARE(Image$$, TFM_SP_STORAGE, _STACK$$ZI$$Base);
 REGION_DECLARE(Image$$, TFM_SP_STORAGE, _STACK$$ZI$$Limit);
 
+REGION_DECLARE(Image$$, TFM_SP_ITS, $$Base);
+REGION_DECLARE(Image$$, TFM_SP_ITS, $$Limit);
+REGION_DECLARE(Image$$, TFM_SP_ITS, $$RO$$Base);
+REGION_DECLARE(Image$$, TFM_SP_ITS, $$RO$$Limit);
+REGION_DECLARE(Image$$, TFM_SP_ITS, _DATA$$RW$$Base);
+REGION_DECLARE(Image$$, TFM_SP_ITS, _DATA$$RW$$Limit);
+REGION_DECLARE(Image$$, TFM_SP_ITS, _DATA$$ZI$$Base);
+REGION_DECLARE(Image$$, TFM_SP_ITS, _DATA$$ZI$$Limit);
+REGION_DECLARE(Image$$, TFM_SP_ITS, _STACK$$ZI$$Base);
+REGION_DECLARE(Image$$, TFM_SP_ITS, _STACK$$ZI$$Limit);
+
 #ifdef TFM_PARTITION_AUDIT_LOG
 REGION_DECLARE(Image$$, TFM_SP_AUDIT_LOG, $$Base);
 REGION_DECLARE(Image$$, TFM_SP_AUDIT_LOG, $$Limit);
@@ -270,6 +285,13 @@
                 sizeof(struct handler_ctx_stack_frame_t)
         )) / sizeof(uint32_t)];
 
+static uint32_t ctx_stack_TFM_SP_ITS[
+        (sizeof(struct interrupted_ctx_stack_frame_t) +
+            (TFM_PARTITION_TFM_SP_ITS_IRQ_COUNT) * (
+                sizeof(struct interrupted_ctx_stack_frame_t) +
+                sizeof(struct handler_ctx_stack_frame_t)
+        )) / sizeof(uint32_t)];
+
 #ifdef TFM_PARTITION_AUDIT_LOG
 static uint32_t ctx_stack_TFM_SP_AUDIT_LOG[
         (sizeof(struct interrupted_ctx_stack_frame_t) +
@@ -362,6 +384,7 @@
     ns_interrupt_ctx_stack,
     tfm_core_interrupt_ctx_stack,
     ctx_stack_TFM_SP_STORAGE,
+    ctx_stack_TFM_SP_ITS,
 #ifdef TFM_PARTITION_AUDIT_LOG
     ctx_stack_TFM_SP_AUDIT_LOG,
 #endif /* TFM_PARTITION_AUDIT_LOG */
@@ -423,6 +446,15 @@
         .partition_init       = tfm_sst_req_mngr_init,
     },
 
+    {
+        .partition_id         = TFM_SP_ITS_ID,
+        .partition_flags      = SPM_PART_FLAG_IPC
+                              | SPM_PART_FLAG_PSA_ROT | SPM_PART_FLAG_APP_ROT
+                              ,
+        .partition_priority   = TFM_PRIORITY(NORMAL),
+        .partition_init       = tfm_its_req_mngr_init,
+    },
+
 #ifdef TFM_PARTITION_AUDIT_LOG
     {
         .partition_id         = TFM_SP_AUDIT_LOG_ID,
@@ -544,6 +576,8 @@
 
     NULL,
 
+    NULL,
+
 #ifdef TFM_PARTITION_AUDIT_LOG
     /* FIXME: Only adding the first mmio region */
 #ifdef AUDIT_UART_REDIRECTION
@@ -614,6 +648,19 @@
         .stack_top            = PART_REGION_ADDR(TFM_SP_STORAGE, _STACK$$ZI$$Limit),
     },
 
+    {
+        .code_start           = PART_REGION_ADDR(TFM_SP_ITS, $$Base),
+        .code_limit           = PART_REGION_ADDR(TFM_SP_ITS, $$Limit),
+        .ro_start             = PART_REGION_ADDR(TFM_SP_ITS, $$RO$$Base),
+        .ro_limit             = PART_REGION_ADDR(TFM_SP_ITS, $$RO$$Limit),
+        .rw_start             = PART_REGION_ADDR(TFM_SP_ITS, _DATA$$RW$$Base),
+        .rw_limit             = PART_REGION_ADDR(TFM_SP_ITS, _DATA$$RW$$Limit),
+        .zi_start             = PART_REGION_ADDR(TFM_SP_ITS, _DATA$$ZI$$Base),
+        .zi_limit             = PART_REGION_ADDR(TFM_SP_ITS, _DATA$$ZI$$Limit),
+        .stack_bottom         = PART_REGION_ADDR(TFM_SP_ITS, _STACK$$ZI$$Base),
+        .stack_top            = PART_REGION_ADDR(TFM_SP_ITS, _STACK$$ZI$$Limit),
+    },
+
 #ifdef TFM_PARTITION_AUDIT_LOG
     {
         .code_start           = PART_REGION_ADDR(TFM_SP_AUDIT_LOG, $$Base),
@@ -785,6 +832,17 @@
     },
 
     /* -----------------------------------------------------------------------*/
+    /* - Partition DB record for TFM_SP_ITS */
+    /* -----------------------------------------------------------------------*/
+    {
+    /* Runtime data */
+        .runtime_data             = {},
+        .static_data              = NULL,
+        .platform_data            = NULL,
+
+    },
+
+    /* -----------------------------------------------------------------------*/
     /* - Partition DB record for TFM_SP_AUDIT_LOG */
     /* -----------------------------------------------------------------------*/
 #ifdef TFM_PARTITION_AUDIT_LOG
diff --git a/tools/tfm_manifest_list.yaml b/tools/tfm_manifest_list.yaml
index c0a65ce..833fef6 100644
--- a/tools/tfm_manifest_list.yaml
+++ b/tools/tfm_manifest_list.yaml
@@ -21,6 +21,15 @@
       "version_minor": 1
     },
     {
+      "name": "TF-M Internal Trusted Storage Service",
+      "short_name": "TFM_ITS",
+      "manifest": "secure_fw/services/internal_trusted_storage/tfm_internal_trusted_storage.yaml",
+      "tfm_extensions": true,
+      "tfm_partition_ipc": true,
+      "version_major": 0,
+      "version_minor": 1
+    },
+    {
       "name": "TFM Audit Log Service",
       "short_name": "TFM_Audit_Log",
       "manifest": "secure_fw/services/audit_logging/tfm_audit_logging.yaml",