PSA_proxy: Create first version of PSA proxy partition
This implementation has some limitations, please check
docs/reference/services/tfm_psa_proxy_integration_guide.rst for details.
Change-Id: Ic1ce7aecfd8bb60b8fb87d5e64ffd186991b560b
Signed-off-by: Mark Horvath <mark.horvath@arm.com>
diff --git a/docs/reference/services/tfm_psa_proxy_integration_guide.rst b/docs/reference/services/tfm_psa_proxy_integration_guide.rst
new file mode 100644
index 0000000..2c5a389
--- /dev/null
+++ b/docs/reference/services/tfm_psa_proxy_integration_guide.rst
@@ -0,0 +1,83 @@
+#####################################
+PSA Proxy Partition Integration Guide
+#####################################
+
+************
+Introduction
+************
+TF-M PSA Proxy partition is responsible for forwarding all the PSA RoT messages
+to a Secure Enclave, this way virtually providing all the PSA RoT services.
+Proxy can only be used in IPC model, for context and design details please
+check the
+:doc:`Secure Enclave design document <docs/design_documents/secure_enclave_solution.rst>`.
+
+Currently to forward the PSA Client call parameters Proxy must read them with
+``psa_read`` into a memory area shared with the Secure Enclave. (Similarily
+``psa_write`` is used to give back the results to the caller.) By default this
+memory is allocated from BSS, but if that is not accessible to the Secure
+Enclave other memory area can be used. To communicate with the Secure Enclave
+the mailbox solution is used, and Proxy uses the Non-secure side of mailbox.
+(The secure side of the mailbox is handled by the Secure Enclave.)
+
+***************************************
+Current PSA Proxy partition limitations
+***************************************
+- Client IDs are not forwarded to Secure Enclave. For Non-secure clients this
+ is straightforward, but for calls coming from other secure partitions the IDs
+ must be translated to a negative value. The reason is all clients on Host
+ are treated as non-secure from Secure Enclave's point of view. (This is the
+ cause why Protected Storage messages also forwarded. Protected Storage uses
+ Internal Trusted Storage partition to manage the PS flash area. But as client
+ IDs are not forwarded the ITS partition running on Secure Enclave can not
+ know whether should work on ITS or PS flash.)
+- Sending of the mailbox messages is a blocking call in Proxy, so control is
+ not given back to Host's SPM while waiting for Secure Enclave's answer.
+- Only one message can be put into the mailbox at a time.
+- Current platform partition provides Non Volatile (NV) counter, System Reset,
+ and IOCTL services. But while NV counters and System Reset shall be provided
+ by the Secure Enclave, IOCTL probably shall be provided by Host, as the
+ underlaying HW probably placed in Host subsystem. So the current platform
+ partition should be split into two halves by conditional compilation, and
+ Proxy should forward only the calls provided by Secure Enclave.
+- PSA Proxy can only get the IPC parameters by PSA read, so the parameters need
+ to be copied to a shared memory, because the partition cannot forward the
+ original pointers. This copy might be omitted on platforms where Secure
+ Enclave has access to all Host memory areas, if all security risks are
+ addressed. Note that IOVECs shall be verified by Host's SPM and sent to SE
+ with the mailbox message.
+
+**************
+Code Structure
+**************
+PSA Proxy partition code is located in ``secure_fw/partitions/psa_proxy/``.
+As Proxy can be treated as an alternative implementation of all the PSA RoT
+services, the Secure and Non-secure interface implementations of the forwarded
+services are reused without modification.
+
+Files
+=====
+- ``psa_proxy.c`` - Handles IPC messages and manages communication with the
+ Secure Enclave.
+
+- ``psa_proxy_shared_mem_mngr.c`` - Responsible to manage the shared memory
+ area used to share the input and output parameters with Secure Enclave.
+
+*****************
+Integration Guide
+*****************
+- Non-secure mailbox interface must be provided.
+- Shared memory must be configured:
+ - If Secure Enclave can access TF-M's BSS section it is enough to set the
+ area's size by the ``SHARED_BUFFER_SIZE`` macro.
+ - If a special memory region must be used as the shared memory the
+ ``PSA_PROXY_SHARED_MEMORY_BASE`` and ``PSA_PROXY_SHARED_MEMORY_SIZE``
+ macros must be set. (Not just for compilation but for linking as well,
+ becuase these macros used in the linker script/scatter file too.)
+- If memories are mapped to different addresses for Host and Secure Enclave
+ address translation can be turned on by setting
+ ``PSA_PROXY_ADDR_TRANSLATION`` macro and implementing the interface defined
+ by ``platform/include/tfm_plat_psa_proxy_addr_trans.h`` header.
+
+--------------
+
+*Copyright (c) 2020, Arm Limited. All rights reserved.*
diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt
index 086cc87..93c45de 100644
--- a/interface/CMakeLists.txt
+++ b/interface/CMakeLists.txt
@@ -72,11 +72,11 @@
if (${TFM_PSA_API})
target_sources(psa_api_ns PRIVATE
- $<$<BOOL:${TFM_PARTITION_PLATFORM}>:${CMAKE_CURRENT_SOURCE_DIR}/src/tfm_platform_ipc_api.c>
- $<$<BOOL:${TFM_PARTITION_PROTECTED_STORAGE}>:${CMAKE_CURRENT_SOURCE_DIR}/src/tfm_ps_ipc_api.c>
- $<$<BOOL:${TFM_PARTITION_INTERNAL_TRUSTED_STORAGE}>:${CMAKE_CURRENT_SOURCE_DIR}/src/tfm_its_ipc_api.c>
- $<$<BOOL:${TFM_PARTITION_CRYPTO}>:${CMAKE_CURRENT_SOURCE_DIR}/src/tfm_crypto_ipc_api.c>
- $<$<BOOL:${TFM_PARTITION_INITIAL_ATTESTATION}>:${CMAKE_CURRENT_SOURCE_DIR}/src/tfm_initial_attestation_ipc_api.c>
+ $<$<OR:$<BOOL:{$FORWARD_PROT_MSG}>,$<BOOL:${TFM_PARTITION_PLATFORM}>>:${CMAKE_CURRENT_SOURCE_DIR}/src/tfm_platform_ipc_api.c>
+ $<$<OR:$<BOOL:{$FORWARD_PROT_MSG}>,$<BOOL:${TFM_PARTITION_PROTECTED_STORAGE}>>:${CMAKE_CURRENT_SOURCE_DIR}/src/tfm_ps_ipc_api.c>
+ $<$<OR:$<BOOL:{$FORWARD_PROT_MSG}>,$<BOOL:${TFM_PARTITION_INTERNAL_TRUSTED_STORAGE}>>:${CMAKE_CURRENT_SOURCE_DIR}/src/tfm_its_ipc_api.c>
+ $<$<OR:$<BOOL:{$FORWARD_PROT_MSG}>,$<BOOL:${TFM_PARTITION_CRYPTO}>>:${CMAKE_CURRENT_SOURCE_DIR}/src/tfm_crypto_ipc_api.c>
+ $<$<OR:$<BOOL:{$FORWARD_PROT_MSG}>,$<BOOL:${TFM_PARTITION_INITIAL_ATTESTATION}>>:${CMAKE_CURRENT_SOURCE_DIR}/src/tfm_initial_attestation_ipc_api.c>
)
if (TFM_MULTI_CORE_TOPOLOGY)
diff --git a/platform/ext/common/armclang/tfm_common_s.sct.template b/platform/ext/common/armclang/tfm_common_s.sct.template
index 1e50363..627ca06 100644
--- a/platform/ext/common/armclang/tfm_common_s.sct.template
+++ b/platform/ext/common/armclang/tfm_common_s.sct.template
@@ -312,6 +312,12 @@
}
#endif
+#if defined(PSA_PROXY_SHARED_MEMORY_BASE)
+ PSA_PROXY_SHARED_MEMORY PSA_PROXY_SHARED_MEMORY_BASE PSA_PROXY_SHARED_MEMORY_SIZE {
+ *(PSA_PROXY_SHARED_MEMORY_SECTION)
+ }
+#endif
+
#if defined (S_RAM_CODE_START)
/* Executable code allocated in RAM */
TFM_RAM_CODE S_RAM_CODE_START {
diff --git a/platform/ext/common/gcc/tfm_common_s.ld.template b/platform/ext/common/gcc/tfm_common_s.ld.template
index a2bf516..d596cea 100644
--- a/platform/ext/common/gcc/tfm_common_s.ld.template
+++ b/platform/ext/common/gcc/tfm_common_s.ld.template
@@ -34,6 +34,11 @@
#ifndef TFM_MULTI_CORE_TOPOLOGY
VENEERS (rx) : ORIGIN = CMSE_VENEER_REGION_START, LENGTH = CMSE_VENEER_REGION_SIZE
#endif
+
+#if defined(PSA_PROXY_SHARED_MEMORY_BASE)
+ PSA_PROXY_SHARED_MEMORY_RAM (rw) : ORIGIN = PSA_PROXY_SHARED_MEMORY_BASE, LENGTH = PSA_PROXY_SHARED_MEMORY_SIZE
+#endif
+
}
__heap_size__ = S_HEAP_SIZE;
@@ -122,6 +127,10 @@
#endif /* {{manifest.attr.conditional}} */
{% endif %}
{% endfor %}
+#if defined(PSA_PROXY_SHARED_MEMORY_BASE)
+ LONG (PSA_PROXY_SHARED_MEMORY_BASE)
+ LONG (PSA_PROXY_SHARED_MEMORY_SIZE)
+#endif
__zero_table_end__ = .;
} > FLASH
@@ -651,6 +660,17 @@
Image$$ER_TFM_DATA$$Base = ADDR(.TFM_DATA);
Image$$ER_TFM_DATA$$Limit = ADDR(.TFM_DATA) + SIZEOF(.TFM_DATA) + SIZEOF(.TFM_BSS);
+#if defined(PSA_PROXY_SHARED_MEMORY_BASE)
+ /* If a variable defined with __attribute__((section())) keyword the
+ * variable is treated like an initialized variable. To not waste memory
+ * NOLOAD attribute used here. The whole section is zero initialized by
+ * adding section information to .zero.table */
+ .PSA_PROXY_SHARED_MEMORY (NOLOAD) :
+ {
+ KEEP(*(PSA_PROXY_SHARED_MEMORY_SECTION))
+ } > PSA_PROXY_SHARED_MEMORY_RAM
+#endif
+
#if defined (S_RAM_CODE_START)
/* Code executed from RAM */
.TFM_RAM_CODE S_RAM_CODE_START :
diff --git a/platform/include/tfm_plat_psa_proxy_addr_trans.h b/platform/include/tfm_plat_psa_proxy_addr_trans.h
new file mode 100644
index 0000000..05f8e1f
--- /dev/null
+++ b/platform/include/tfm_plat_psa_proxy_addr_trans.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef __TFM_PLAT_PSA_PROXY_H__
+#define __TFM_PLAT_PSA_PROXY_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief Translates an address from Host to Secure Enclave
+ *
+ * \param[in] addr The address to be translated
+ *
+ * \return Returns the translated pointer
+ */
+void* translate_addr_from_host_to_se(void *addr);
+
+/**
+ * \brief Translates an address from Secure Enclave to Host
+ *
+ * \param[in] addr The address to be translated
+ *
+ * \return Returns the translated pointer
+ */
+void* translate_addr_from_se_to_host(void *addr);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __TFM_PLAT_PSA_PROXY_H__ */
diff --git a/secure_fw/CMakeLists.txt b/secure_fw/CMakeLists.txt
index 49f5dff..f1a6a6b 100644
--- a/secure_fw/CMakeLists.txt
+++ b/secure_fw/CMakeLists.txt
@@ -25,6 +25,7 @@
add_subdirectory(partitions/protected_storage)
add_subdirectory(partitions/internal_trusted_storage)
add_subdirectory(partitions/platform)
+add_subdirectory(partitions/psa_proxy)
add_subdirectory(spm)
target_include_directories(secure_fw
diff --git a/secure_fw/partitions/initial_attestation/CMakeLists.txt b/secure_fw/partitions/initial_attestation/CMakeLists.txt
index e066326..a087e93 100644
--- a/secure_fw/partitions/initial_attestation/CMakeLists.txt
+++ b/secure_fw/partitions/initial_attestation/CMakeLists.txt
@@ -6,6 +6,14 @@
#-------------------------------------------------------------------------------
if (NOT TFM_PARTITION_INITIAL_ATTESTATION)
+ if(TFM_PARTITION_PSA_PROXY)
+ add_library(tfm_attestation_defs INTERFACE)
+
+ target_include_directories(tfm_attestation_defs
+ INTERFACE
+ .
+ )
+ endif()
return()
endif()
diff --git a/secure_fw/partitions/protected_storage/CMakeLists.txt b/secure_fw/partitions/protected_storage/CMakeLists.txt
index a8bd061..b1cb12f 100644
--- a/secure_fw/partitions/protected_storage/CMakeLists.txt
+++ b/secure_fw/partitions/protected_storage/CMakeLists.txt
@@ -6,6 +6,14 @@
#-------------------------------------------------------------------------------
if (NOT TFM_PARTITION_PROTECTED_STORAGE)
+ if(TFM_PARTITION_PSA_PROXY)
+ add_library(tfm_partition_ps INTERFACE)
+
+ target_include_directories(tfm_partition_ps
+ INTERFACE
+ $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
+ )
+ endif()
return()
endif()
diff --git a/secure_fw/partitions/psa_proxy/CMakeLists.txt b/secure_fw/partitions/psa_proxy/CMakeLists.txt
new file mode 100644
index 0000000..ffbc778
--- /dev/null
+++ b/secure_fw/partitions/psa_proxy/CMakeLists.txt
@@ -0,0 +1,69 @@
+#-------------------------------------------------------------------------------
+# Copyright (c) 2020, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#-------------------------------------------------------------------------------
+
+if(NOT TFM_PARTITION_PSA_PROXY)
+ return()
+endif()
+
+cmake_minimum_required(VERSION 3.15)
+cmake_policy(SET CMP0079 NEW)
+
+add_library(tfm_partition_psa_proxy STATIC)
+
+target_include_directories(tfm_partition_psa_proxy
+ INTERFACE
+ $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
+ ${CMAKE_BINARY_DIR}/generated/secure_fw/partitions/psa_proxy
+ PUBLIC
+ # Required for spm_ipc.h
+ $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>/../../spm/cmsis_psa
+)
+
+target_sources(tfm_partition_psa_proxy
+ PRIVATE
+ psa_proxy.c
+ psa_proxy_shared_mem_mngr.c
+ ../../../interface/src/tfm_ns_mailbox.c
+)
+
+target_link_libraries(tfm_partition_psa_proxy
+ PRIVATE
+ tfm_secure_api
+ psa_interface
+ secure_fw
+ platform_s
+)
+
+############################ Secure API ########################################
+
+target_sources(tfm_secure_api
+ PRIVATE
+ ../crypto/tfm_crypto_secure_api.c
+ ../initial_attestation/tfm_attest_secure_api.c
+ ../internal_trusted_storage/tfm_its_secure_api.c
+ ../platform/tfm_platform_secure_api.c
+ ../protected_storage/tfm_ps_secure_api.c
+)
+
+# The veneers give warnings about not being properly declared so they get hidden
+# to not overshadow _real_ warnings.
+set_source_files_properties(tfm_ps_secure_api.c
+ PROPERTIES
+ COMPILE_FLAGS -Wno-implicit-function-declaration
+)
+
+############################ Partition Defs ####################################
+
+target_link_libraries(tfm_partitions
+ INTERFACE
+ tfm_partition_psa_proxy
+)
+
+target_compile_definitions(tfm_partition_defs
+ INTERFACE
+ TFM_PARTITION_PSA_PROXY
+)
diff --git a/secure_fw/partitions/psa_proxy/dir_psa_proxy.dox b/secure_fw/partitions/psa_proxy/dir_psa_proxy.dox
new file mode 100644
index 0000000..5ef7661
--- /dev/null
+++ b/secure_fw/partitions/psa_proxy/dir_psa_proxy.dox
@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+//This file holds description for the current directory. This documentation
+//will be included in the Doxygen output.
+
+/*!
+\dir
+\brief Source code for the PSA Proxy service.
+\details The PSA Proxy service can forward IPC messages to a Secure Enclave.
+
+*/
\ No newline at end of file
diff --git a/secure_fw/partitions/psa_proxy/psa_proxy.c b/secure_fw/partitions/psa_proxy/psa_proxy.c
new file mode 100644
index 0000000..5475d26
--- /dev/null
+++ b/secure_fw/partitions/psa_proxy/psa_proxy.c
@@ -0,0 +1,284 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <stdint.h>
+
+#include "psa/service.h"
+#include "psa_manifest/tfm_psa_proxy.h"
+#include "tfm_pools.h"
+#include "psa_manifest/sid.h"
+#include "tfm_multi_core_api.h"
+#include "tfm_ns_mailbox.h"
+#include "platform_multicore.h"
+#include "psa_proxy_shared_mem_mngr.h"
+
+#define NON_SECURE_CLIENT_ID (-1)
+
+/* Maximum number of connections supported, should be platform/configuration
+ * specific */
+#define SE_CONN_MAX_NUM (16)
+
+TFM_POOL_DECLARE(forward_handle_pool, sizeof(psa_handle_t),
+ SE_CONN_MAX_NUM);
+
+static inline void init_forward_handle_pool(void)
+{
+ tfm_pool_init(forward_handle_pool,
+ POOL_BUFFER_SIZE(forward_handle_pool),
+ sizeof(psa_handle_t),
+ SE_CONN_MAX_NUM);
+}
+
+static inline psa_handle_t * allocate_forward_handle(void)
+{
+ return (psa_handle_t *) tfm_pool_alloc(forward_handle_pool);
+}
+
+static inline void deallocate_forward_handle(psa_handle_t *h)
+{
+ tfm_pool_free(h);
+}
+
+static psa_status_t forward_psa_call_to_secure_enclave(const psa_msg_t *msg)
+{
+ psa_status_t status;
+ psa_handle_t *forward_handle_ptr = (psa_handle_t *)msg->rhandle;
+ struct psa_client_params_t params;
+ mailbox_msg_handle_t mailbox_handle;
+ int32_t ret;
+
+ params.psa_call_params.handle = *forward_handle_ptr;
+ params.psa_call_params.type = PSA_IPC_CALL;
+
+ status = psa_proxy_put_msg_into_shared_mem(msg, ¶ms);
+
+ if (status != PSA_SUCCESS) {
+ return status;
+ }
+
+ mailbox_handle = tfm_ns_mailbox_tx_client_req(MAILBOX_PSA_CALL, ¶ms,
+ NON_SECURE_CLIENT_ID);
+
+ /* Waiting for mailbox answer */
+ while(!tfm_ns_mailbox_is_msg_replied(mailbox_handle)) {
+ ;
+ }
+
+ ret = tfm_ns_mailbox_rx_client_reply(mailbox_handle, (int32_t *)&status);
+
+ if (ret != MAILBOX_SUCCESS) {
+ status = PSA_ERROR_COMMUNICATION_FAILURE;
+ }
+
+ if (status == PSA_SUCCESS) {
+ psa_proxy_write_back_results_from_shared_mem(msg);
+ }
+
+ return status;
+}
+
+static void psa_disconnect_from_secure_enclave(psa_msg_t *msg)
+{
+ psa_handle_t *forward_handle_ptr = (psa_handle_t *)msg->rhandle;
+ struct psa_client_params_t params;
+ mailbox_msg_handle_t mailbox_handle;
+ int32_t reply;
+
+ params.psa_close_params.handle = *forward_handle_ptr;
+
+ mailbox_handle = tfm_ns_mailbox_tx_client_req(MAILBOX_PSA_CLOSE, ¶ms,
+ NON_SECURE_CLIENT_ID);
+
+ /* Waiting for mailbox answer */
+ while(!tfm_ns_mailbox_is_msg_replied(mailbox_handle)) {
+ ;
+ }
+
+ tfm_ns_mailbox_rx_client_reply(mailbox_handle, (int32_t *)&reply);
+
+ deallocate_forward_handle(forward_handle_ptr);
+}
+
+static void get_sid_and_version_for_signal(psa_signal_t signal, uint32_t *sid,
+ uint32_t *version)
+{
+ switch (signal) {
+ case TFM_CRYPTO_SIGNAL:
+ *sid = TFM_CRYPTO_SID;
+ *version = TFM_CRYPTO_VERSION;
+ break;
+ case TFM_ATTEST_GET_TOKEN_SIGNAL:
+ *sid = TFM_ATTEST_GET_TOKEN_SID;
+ *version = TFM_ATTEST_GET_TOKEN_VERSION;
+ break;
+ case TFM_ATTEST_GET_TOKEN_SIZE_SIGNAL:
+ *sid = TFM_ATTEST_GET_TOKEN_SIZE_SID;
+ *version = TFM_ATTEST_GET_TOKEN_SIZE_VERSION;
+ break;
+ case TFM_ATTEST_GET_PUBLIC_KEY_SIGNAL:
+ *sid = TFM_ATTEST_GET_PUBLIC_KEY_SID;
+ *version = TFM_ATTEST_GET_PUBLIC_KEY_VERSION;
+ break;
+ case TFM_ITS_SET_SIGNAL:
+ *sid = TFM_ITS_SET_SID;
+ *version = TFM_ITS_SET_VERSION;
+ break;
+ case TFM_ITS_GET_SIGNAL:
+ *sid = TFM_ITS_GET_SID;
+ *version = TFM_ITS_GET_VERSION;
+ break;
+ case TFM_ITS_GET_INFO_SIGNAL:
+ *sid = TFM_ITS_GET_INFO_SID;
+ *version = TFM_ITS_GET_INFO_VERSION;
+ break;
+ case TFM_ITS_REMOVE_SIGNAL:
+ *sid = TFM_ITS_REMOVE_SID;
+ *version = TFM_ITS_REMOVE_VERSION;
+ break;
+ case TFM_SP_PLATFORM_SYSTEM_RESET_SIGNAL:
+ *sid = TFM_SP_PLATFORM_SYSTEM_RESET_SID;
+ *version = TFM_SP_PLATFORM_SYSTEM_RESET_VERSION;
+ break;
+ case TFM_SP_PLATFORM_IOCTL_SIGNAL:
+ *sid = TFM_SP_PLATFORM_IOCTL_SID;
+ *version = TFM_SP_PLATFORM_IOCTL_VERSION;
+ break;
+ case TFM_SP_PLATFORM_NV_COUNTER_SIGNAL:
+ *sid = TFM_SP_PLATFORM_NV_COUNTER_SID;
+ *version = TFM_SP_PLATFORM_NV_COUNTER_VERSION;
+ break;
+ case TFM_PS_SET_SIGNAL:
+ *sid = TFM_PS_SET_SID;
+ *version = TFM_PS_SET_VERSION;
+ break;
+ case TFM_PS_GET_SIGNAL:
+ *sid = TFM_PS_GET_SID;
+ *version = TFM_PS_GET_VERSION;
+ break;
+ case TFM_PS_GET_INFO_SIGNAL:
+ *sid = TFM_PS_GET_INFO_SID;
+ *version = TFM_PS_GET_INFO_VERSION;
+ break;
+ case TFM_PS_REMOVE_SIGNAL:
+ *sid = TFM_PS_REMOVE_SID;
+ *version = TFM_PS_REMOVE_VERSION;
+ break;
+ case TFM_PS_GET_SUPPORT_SIGNAL:
+ *sid = TFM_PS_GET_SUPPORT_SID;
+ *version = TFM_PS_GET_SUPPORT_VERSION;
+ break;
+ default:
+ psa_panic();
+ break;
+ }
+}
+
+static psa_status_t psa_connect_to_secure_enclave(psa_signal_t signal,
+ psa_msg_t *msg)
+{
+ psa_handle_t *forward_handle_ptr;
+ struct psa_client_params_t params;
+ mailbox_msg_handle_t mailbox_handle;
+ int32_t ret;
+
+ forward_handle_ptr = allocate_forward_handle();
+
+ if (forward_handle_ptr != NULL) {
+
+ get_sid_and_version_for_signal(signal, ¶ms.psa_connect_params.sid,
+ ¶ms.psa_connect_params.version);
+
+ /* Fixme: All messages sent with the same client id */
+ mailbox_handle = tfm_ns_mailbox_tx_client_req(MAILBOX_PSA_CONNECT,
+ ¶ms,
+ NON_SECURE_CLIENT_ID);
+
+ /* Waiting for mailbox answer */
+ while (!tfm_ns_mailbox_is_msg_replied(mailbox_handle)) {
+ ;
+ }
+
+ ret = tfm_ns_mailbox_rx_client_reply(mailbox_handle,
+ (int32_t *)forward_handle_ptr);
+
+ if (ret != MAILBOX_SUCCESS) {
+ *forward_handle_ptr = PSA_NULL_HANDLE;
+ }
+
+ if ( *forward_handle_ptr > 0) {
+ psa_set_rhandle(msg->handle, (void *)forward_handle_ptr);
+ return PSA_SUCCESS;
+ } else {
+ deallocate_forward_handle(forward_handle_ptr);
+ return *forward_handle_ptr;
+ }
+ } else {
+ return PSA_ERROR_INSUFFICIENT_MEMORY;
+ }
+}
+
+static void handle_signal(psa_signal_t signal)
+{
+ psa_msg_t msg;
+ psa_status_t status;
+
+ status = psa_get(signal, &msg);
+ switch (msg.type) {
+ case PSA_IPC_CONNECT:
+ status = psa_connect_to_secure_enclave(signal, &msg);
+ psa_reply(msg.handle, status);
+ break;
+ case PSA_IPC_CALL:
+ status = forward_psa_call_to_secure_enclave(&msg);
+ psa_reply(msg.handle, status);
+ break;
+ case PSA_IPC_DISCONNECT:
+ psa_disconnect_from_secure_enclave(&msg);
+ psa_reply(msg.handle, PSA_SUCCESS);
+ break;
+ default:
+ psa_panic();
+ break;
+ }
+}
+
+static psa_status_t psa_proxy_init(void)
+{
+ int32_t ret;
+
+ if (tfm_platform_ns_wait_for_s_cpu_ready()) {
+ return PSA_ERROR_HARDWARE_FAILURE;
+ }
+
+ ret = tfm_ns_mailbox_init(psa_proxy_get_ns_mailbox_queue());
+ if (ret != MAILBOX_SUCCESS) {
+ return PSA_ERROR_GENERIC_ERROR;
+ }
+
+ init_forward_handle_pool();
+
+ return PSA_SUCCESS;
+}
+
+psa_status_t psa_proxy_sp_init(void)
+{
+ psa_signal_t signal;
+ psa_status_t err;
+
+ err = psa_proxy_init();
+ if ( err != PSA_SUCCESS ) {
+ psa_panic();
+ }
+
+ while (1) {
+ /* Control is given back to SPM */
+ signal = psa_wait(PSA_WAIT_ANY, PSA_BLOCK);
+ handle_signal(signal);
+ }
+
+ return PSA_SUCCESS;
+}
diff --git a/secure_fw/partitions/psa_proxy/psa_proxy_shared_mem_mngr.c b/secure_fw/partitions/psa_proxy/psa_proxy_shared_mem_mngr.c
new file mode 100644
index 0000000..dc5614e
--- /dev/null
+++ b/secure_fw/partitions/psa_proxy/psa_proxy_shared_mem_mngr.c
@@ -0,0 +1,204 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include "psa_proxy_shared_mem_mngr.h"
+#include "platform_multicore.h"
+#include "region_defs.h"
+#include "psa/service.h"
+#ifdef PSA_PROXY_ADDR_TRANSLATION
+#include "tfm_plat_psa_proxy_addr_trans.h"
+#endif
+
+/* If a dedicated region used for memory sharing maximum buffer size calculated
+ * here. Otherwise the buffer size must be defined.
+ */
+#ifdef PSA_PROXY_SHARED_MEMORY_SIZE
+#define SHARED_BUFFER_SIZE (PSA_PROXY_SHARED_MEMORY_SIZE - \
+ sizeof(struct ns_mailbox_queue_t) - \
+ (sizeof(psa_invec) * PSA_MAX_IOVEC)- \
+ (sizeof(psa_outvec) * PSA_MAX_IOVEC))
+#else
+#ifndef SHARED_BUFFER_SIZE
+#error "PSA_PROXY_SHARED_MEMORY_SIZE or SHARED_BUFFER_SIZE should be defined"
+#endif
+#endif
+
+struct shared_mem_t {
+ struct ns_mailbox_queue_t ns_mailbox_queue;
+ psa_invec in_vec[PSA_MAX_IOVEC];
+ psa_outvec out_vec[PSA_MAX_IOVEC];
+ uint8_t buffer[SHARED_BUFFER_SIZE];
+};
+
+#ifdef PSA_PROXY_SHARED_MEMORY_BASE
+/* If a dedicated region used for memory sharing the shared_mem variable must
+ * be allocated into it.
+ * If compiled with gcc the whole section zero initialized, even if the
+ * variable initialized here with some other value.
+ */
+__attribute__((section("PSA_PROXY_SHARED_MEMORY_SECTION")))
+#endif
+struct shared_mem_t shared_mem;
+
+uint32_t shared_mem_buffer_actual_size = 0;
+
+static psa_status_t write_input_param_into_shared_mem(uint32_t param_num,
+ const psa_msg_t *msg)
+{
+ const void *buff_input_ptr;
+
+ if (shared_mem_buffer_actual_size + msg->in_size[param_num] <=
+ SHARED_BUFFER_SIZE) {
+ buff_input_ptr = &(shared_mem.buffer[shared_mem_buffer_actual_size]);
+
+ psa_read(msg->handle,
+ param_num,
+ (void *) buff_input_ptr,
+ msg->in_size[param_num]);
+ shared_mem_buffer_actual_size += msg->in_size[param_num];
+
+ shared_mem.in_vec[param_num].base = buff_input_ptr;
+ shared_mem.in_vec[param_num].len = msg->in_size[param_num];
+
+ return PSA_SUCCESS;
+ } else {
+ return PSA_ERROR_INSUFFICIENT_MEMORY;
+ }
+}
+
+static psa_status_t allocate_output_param_in_shared_mem(uint32_t param_num,
+ const psa_msg_t *msg)
+{
+ void * buff_output_ptr;
+
+ if (shared_mem_buffer_actual_size + msg->out_size[param_num] <=
+ SHARED_BUFFER_SIZE) {
+ buff_output_ptr = &(shared_mem.buffer[shared_mem_buffer_actual_size]);
+
+ shared_mem_buffer_actual_size += msg->out_size[param_num];
+
+ shared_mem.out_vec[param_num].base = buff_output_ptr;
+ shared_mem.out_vec[param_num].len = msg->out_size[param_num];
+
+ return PSA_SUCCESS;
+ } else {
+ return PSA_ERROR_INSUFFICIENT_MEMORY;
+ }
+}
+
+static void clear_shared_mem_buffer(void)
+{
+ int32_t i;
+
+ shared_mem_buffer_actual_size = 0;
+
+ for (i = 0; i < PSA_MAX_IOVEC; i++) {
+ shared_mem.in_vec[i].base = NULL;
+ shared_mem.in_vec[i].len = 0;
+ shared_mem.out_vec[i].base = NULL;
+ shared_mem.out_vec[i].len = 0;
+ }
+}
+
+#ifdef PSA_PROXY_ADDR_TRANSLATION
+static void translate_shared_mem_addrs_to_send_msg(
+ struct psa_client_params_t* forward_params)
+{
+ int32_t i;
+
+ for (i = 0; i < PSA_MAX_IOVEC; i++) {
+ shared_mem.in_vec[i].base = translate_addr_from_host_to_se(
+ (void*)shared_mem.in_vec[i].base);
+ shared_mem.out_vec[i].base = translate_addr_from_host_to_se(
+ shared_mem.out_vec[i].base);
+ }
+
+ forward_params->psa_call_params.in_vec = translate_addr_from_host_to_se(
+ shared_mem.in_vec);
+ forward_params->psa_call_params.out_vec = translate_addr_from_host_to_se(
+ shared_mem.out_vec);
+}
+
+static void translate_shared_mem_addrs_to_write_back_results(void)
+{
+ int32_t i;
+
+ for (i = 0; i < PSA_MAX_IOVEC; i++) {
+ shared_mem.in_vec[i].base = translate_addr_from_se_to_host(
+ (void*)shared_mem.in_vec[i].base);
+ shared_mem.out_vec[i].base = translate_addr_from_se_to_host(
+ shared_mem.out_vec[i].base);
+ }
+
+}
+#endif
+
+struct ns_mailbox_queue_t * psa_proxy_get_ns_mailbox_queue(void)
+{
+ return &(shared_mem.ns_mailbox_queue);
+}
+
+psa_status_t psa_proxy_put_msg_into_shared_mem(
+ const psa_msg_t* msg,
+ struct psa_client_params_t* forward_params)
+{
+ psa_status_t status;
+ uint32_t i;
+ size_t in_vec_len = 0;
+ size_t out_vec_len = 0;
+
+ clear_shared_mem_buffer();
+
+ for (i = 0; i < PSA_MAX_IOVEC; i++) {
+ if (msg->in_size[i] > 0) {
+ status = write_input_param_into_shared_mem(i, msg);
+ if ( status != PSA_SUCCESS ) {
+ return status;
+ }
+ in_vec_len = i + 1;
+ }
+ }
+
+ for (i = 0; i < PSA_MAX_IOVEC; i++) {
+ if (msg->out_size[i] > 0) {
+ status = allocate_output_param_in_shared_mem(i, msg);
+ if ( status != PSA_SUCCESS ) {
+ return status;
+ }
+ out_vec_len = i + 1;
+ }
+ }
+
+ forward_params->psa_call_params.in_vec = shared_mem.in_vec;
+ forward_params->psa_call_params.in_len = in_vec_len;
+ forward_params->psa_call_params.out_vec = shared_mem.out_vec;
+ forward_params->psa_call_params.out_len = out_vec_len;
+
+#ifdef PSA_PROXY_ADDR_TRANSLATION
+ translate_shared_mem_addrs_to_send_msg(forward_params);
+#endif
+
+ return PSA_SUCCESS;
+}
+
+void psa_proxy_write_back_results_from_shared_mem(const psa_msg_t* msg)
+{
+ uint32_t i;
+
+#ifdef PSA_PROXY_ADDR_TRANSLATION
+ translate_shared_mem_addrs_to_write_back_results();
+#endif
+
+ for (i = 0; i < PSA_MAX_IOVEC; i++) {
+ if (shared_mem.out_vec[i].len > 0) {
+ psa_write(msg->handle,
+ i,
+ shared_mem.out_vec[i].base,
+ shared_mem.out_vec[i].len);
+ }
+ }
+}
diff --git a/secure_fw/partitions/psa_proxy/psa_proxy_shared_mem_mngr.h b/secure_fw/partitions/psa_proxy/psa_proxy_shared_mem_mngr.h
new file mode 100644
index 0000000..62254bf
--- /dev/null
+++ b/secure_fw/partitions/psa_proxy/psa_proxy_shared_mem_mngr.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef __PSA_PROXY_SHARED_MEM_MNGR_H__
+#define __PSA_PROXY_SHARED_MEM_MNGR_H__
+
+#include "tfm_mailbox.h"
+#include "psa/error.h"
+#include "psa/service.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief Returns the NS mailbox
+ *
+ * \return Returns a pointer to the NS mailbox
+ */
+struct ns_mailbox_queue_t * psa_proxy_get_ns_mailbox_queue(void);
+
+/*!
+ * \brief Puts message into the shared memory
+ *
+ * \param[in] msg PSA message to be forwarded
+ * \param[out] forward_params PSA client parameters to be forwarded (pointers
+ * of the shared input and output vectors shall be
+ * written back to this structure.
+ *
+ * \return Returns values as specified by the \ref psa_status_t
+ */
+psa_status_t psa_proxy_put_msg_into_shared_mem(
+ const psa_msg_t *msg,
+ struct psa_client_params_t *forward_params);
+
+/*!
+ * \brief Writes back the results of the forwarded PSA message
+ *
+ * \param[in] msg Original PSA message was already forwarded
+ */
+void psa_proxy_write_back_results_from_shared_mem(const psa_msg_t *msg);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __PSA_PROXY_SHARED_MEM_MNGR_H__ */
diff --git a/secure_fw/partitions/psa_proxy/tfm_psa_proxy.yaml b/secure_fw/partitions/psa_proxy/tfm_psa_proxy.yaml
new file mode 100644
index 0000000..31bdf18
--- /dev/null
+++ b/secure_fw/partitions/psa_proxy/tfm_psa_proxy.yaml
@@ -0,0 +1,132 @@
+#-------------------------------------------------------------------------------
+# Copyright (c) 2020, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#-------------------------------------------------------------------------------
+
+{
+ "psa_framework_version": 1.0,
+ "name": "TFM_SP_PSA_PROXY",
+ "type": "PSA-ROT",
+ "priority": "HIGH",
+ "entry_point": "psa_proxy_sp_init",
+ "stack_size": "0x0A00",
+ "services": [
+ {
+ "name": "TFM_CRYPTO",
+ "sid": "0x00000080",
+ "non_secure_clients": true,
+ "version": 1,
+ "version_policy": "STRICT"
+ },
+ {
+ "name": "TFM_ATTEST_GET_TOKEN",
+ "sid": "0x00000020",
+ "non_secure_clients": true,
+ "version": 1,
+ "version_policy": "STRICT"
+ },
+ {
+ "name": "TFM_ATTEST_GET_TOKEN_SIZE",
+ "sid": "0x00000021",
+ "non_secure_clients": true,
+ "version": 1,
+ "version_policy": "STRICT"
+ },
+ {
+ "name": "TFM_ATTEST_GET_PUBLIC_KEY",
+ "sid": "0x00000022",
+ "non_secure_clients": true,
+ "version": 1,
+ "version_policy": "STRICT"
+ },
+ {
+ "name": "TFM_ITS_SET",
+ "sid": "0x00000070",
+ "non_secure_clients": true,
+ "version": 1,
+ "version_policy": "STRICT"
+ },
+ {
+ "name": "TFM_ITS_GET",
+ "sid": "0x00000071",
+ "non_secure_clients": true,
+ "version": 1,
+ "version_policy": "STRICT"
+ },
+ {
+ "name": "TFM_ITS_GET_INFO",
+ "sid": "0x00000072",
+ "non_secure_clients": true,
+ "version": 1,
+ "version_policy": "STRICT"
+ },
+ {
+ "name": "TFM_ITS_REMOVE",
+ "sid": "0x00000073",
+ "non_secure_clients": true,
+ "version": 1,
+ "version_policy": "STRICT"
+ },
+ {
+ "name": "TFM_SP_PLATFORM_SYSTEM_RESET",
+ "signal": "PLATFORM_SP_SYSTEM_RESET_SIG",
+ "sid": "0x00000040",
+ "non_secure_clients": true,
+ "minor_version": 1,
+ "minor_policy": "STRICT"
+ },
+ {
+ "name": "TFM_SP_PLATFORM_IOCTL",
+ "signal": "PLATFORM_SP_IOCTL_SIG",
+ "sid": "0x00000041",
+ "non_secure_clients": true,
+ "minor_version": 1,
+ "minor_policy": "STRICT"
+ },
+ {
+ "name": "TFM_SP_PLATFORM_NV_COUNTER",
+ "signal": "PLATFORM_SP_NV_COUNTER_SIG",
+ "sid": "0x00000042",
+ "non_secure_clients": false,
+ "version": 1,
+ "version_policy": "STRICT"
+ },
+ {
+ "name": "TFM_PS_SET",
+ "sid": "0x00000060",
+ "non_secure_clients": true,
+ "version": 1,
+ "version_policy": "STRICT"
+ },
+ {
+ "name": "TFM_PS_GET",
+ "sid": "0x00000061",
+ "non_secure_clients": true,
+ "version": 1,
+ "version_policy": "STRICT"
+ },
+ {
+ "name": "TFM_PS_GET_INFO",
+ "sid": "0x00000062",
+ "non_secure_clients": true,
+ "version": 1,
+ "version_policy": "STRICT"
+ },
+ {
+ "name": "TFM_PS_REMOVE",
+ "sid": "0x00000063",
+ "non_secure_clients": true,
+ "version": 1,
+ "version_policy": "STRICT"
+ },
+ {
+ "name": "TFM_PS_GET_SUPPORT",
+ "sid": "0x00000064",
+ "non_secure_clients": true,
+ "version": 1,
+ "version_policy": "STRICT"
+ }
+ ]
+}
diff --git a/secure_fw/spm/CMakeLists.txt b/secure_fw/spm/CMakeLists.txt
index e243f05..5512e57 100755
--- a/secure_fw/spm/CMakeLists.txt
+++ b/secure_fw/spm/CMakeLists.txt
@@ -31,7 +31,7 @@
target_sources(tfm_spm
PRIVATE
- $<$<BOOL:${TFM_PARTITION_INITIAL_ATTESTATION}>:common/tfm_boot_data.c>
+ common/tfm_boot_data.c
common/tfm_core_utils.c
common/utilities.c
common/spm_log.c
diff --git a/tools/tfm_manifest_list.yaml b/tools/tfm_manifest_list.yaml
index 82dcdd7..bad309c 100644
--- a/tools/tfm_manifest_list.yaml
+++ b/tools/tfm_manifest_list.yaml
@@ -240,6 +240,22 @@
"*tfm_secure_client_2.*"
]
}
+ },
+ {
+ "name": "TF-M PSA Proxy Service",
+ "short_name": "TFM_SP_PSA_PROXY",
+ "manifest": "secure_fw/partitions/psa_proxy/tfm_psa_proxy.yaml",
+ "tfm_extensions": true,
+ "tfm_partition_ipc": true,
+ "conditional": "TFM_PARTITION_PSA_PROXY",
+ "version_major": 0,
+ "version_minor": 1,
+ "pid": 270,
+ "linker_pattern": {
+ "library_list": [
+ "*tfm_psa_proxy*"
+ ]
+ }
}
]
}