1. Introduction
In the context of the Secure Manager, an RTOS can be used. This article will explore how an RTOS can be used with the Secure Manager, with a focus on the mechanism provided to ensure secure, thread-safe calls To do this, we will take the example of a non-secure application as SMAK_Appli that uses the Secure Manager service. It will explore the differences in implementation required for a non-secure application to use the Secure Manager in a multi-threaded environment.
The different steps and prerequisites to integrate a non-secure application with the Secure Manager can be find here Security:How_to_start_with_Secure_Manager_customized_config_on_STM32H5 which details: Secure Manager installation, non-secure application development, firmware update, etc.
2. Implementation example
2.1. Thread-safe secure calls
We will need to protect the API calls. There is a mechanism in the middleware secure_manager_api that allows interfacing with the secure manager. This mechanism, based on functions defined as __weak, will need to be re-implemented by integrating our protection based on mutexes, refer to Figure 1. The use of mutex as a mechanism to synchronize access to the PSA API is essential when using multithreading.
The functions ns_ipc_seq_begin and ns_ipc_seq_end, which are declared by default in the secure manager library in the file tfm_ns_interface.c, will need to be re-implemented in the FreeRTOS project due to multithreaded use.
Firmware
└───Middlewares
└─── ST
└─── ''' secure_manager_api '''
└───ipc
└───nonsecure
└───src
└───tfm_ns_interface.c
2.2. Step by step implementation
In your project in the file where you decide to reimplement ipc function see above:
1. Declare a mutex and initialize it to 0 :
static SemaphoreHandle_t nsIpcMutex = { 0 };
2. Create a function that creates the mutex and assigns it to the nsIpcMutex variable. If the mutex creation fails, log an error:
void tfm_ns_interface_init( void )
{
nsIpcMutex = xSemaphoreCreateMutex();
if(nsIpcMutex == NULL)
{
// Logging Error
}
}
3. Implement the acquisition and release of the mutex with functions defines in semphr.c from library FreeRTOS , in the ns_ipc_seq_begin and ns_ipc_seq_end functions, respectively. This ensuring that shared resources are not accessed simultaneously:
void ns_ipc_seq_begin(const ns_ipc_seq_info_t* info)
{
/* Lock mutex */
if(nsIpcMutex != NULL)
{
xSemaphoreTake(nsIpcMutex, portMAX_DELAY );
}
….
}
void ns_ipc_seq_end(const ns_ipc_seq_info_t* info)
{
/* Unlock mutex */
if(nsIpcMutex != NULL)
{
xSemaphoreGive(nsIpcMutex);
}
….
}
For more concrete examples, an actual implementations can be found in X-Cube-AWS & X-Cube-Azure using the Secure Manager with a real-time operating system.
2.3. Memory Management
SRAM 3 can be configured with heap RTOS configuration. The heap_5 implementation of FreeRTOS dynamic memory allocator is selected to use non-contiguous memory regions in SRAM1 and SRAM3. During initialization, prvInitializeHeap() needs to be set up.