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",