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, &params);
+
+    if (status != PSA_SUCCESS) {
+        return status;
+    }
+
+    mailbox_handle = tfm_ns_mailbox_tx_client_req(MAILBOX_PSA_CALL, &params,
+                                                  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, &params,
+                                                  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, &params.psa_connect_params.sid,
+                                       &params.psa_connect_params.version);
+
+        /* Fixme: All messages sent with the same client id */
+        mailbox_handle = tfm_ns_mailbox_tx_client_req(MAILBOX_PSA_CONNECT,
+                                                      &params,
+                                                      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*"
+         ]
+      }
     }
   ]
 }