Merge pull request #8873 from kfnta/psa_spm_docs

PSA-SPM documentation follow-up
pull/8993/head
Martin Kojtal 2018-12-04 15:38:45 +01:00 committed by GitHub
commit 6edc81ddae
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 61 additions and 206 deletions

View File

@ -26,24 +26,22 @@
/* -------------------------------- Handle Manager Module ---------------------------- */
/* The Handle Manager Module manages handles.
*
* It basically generates and exposes a unique handle identifier [handle] per
* handle memory [handle_mem] it receives from the user.
* Then users can use the exposed handle identifier to relate to the "registered"
/*
* The Handle Manager module generates and exposes a unique
* identifier (handle) per handle memory (handle_mem) it receives.
* You can use the exposed handle identifier to relate to the "registered"
* handle memory.
*
* Users can:
* - Ask for a unique handle identifier for a given handle memory [handle_create]
* You can:
* - Ask for a unique handle identifier for a given handle memory [`handle_create`].
* - Ask for a pointer to the handle memory corresponding to a
* handle identifier [handle_get_mem]
* - Remove a handle from the handle manager module [handle_destroy]
* handle identifier [`handle_get_mem`].
* - Remove a handle from the handle manager module [`handle_destroy`].
*
* Note:
* Handles generation is done exclusively.
* Once we got a handle, removing a handle or getting its memory can be
* done non-exclusive.
* The assumption is that only one context is dealing with a handle after it was
* Handle generation is done exclusively.
* Once you have a handle, you can remove or get its memory non-exclusively.
* The assumption is that only one context is dealing with a handle after it is
* generated.
*/
@ -61,9 +59,9 @@ extern "C" {
#define PSA_HANDLE_MGR_INVALID_FRIEND_OWNER 0 // Denoting invalid friend or invalid owner
// Handles manager pool indexes must be in range 0 - 0x7FFF.
// The reason for this limitation is that the index is stored in the upper 16 bits of a handle,
// and the most significant bit must be zero to keep handles non negative.
// Handle manager pool indexes must be in range 0 - 0x7FFF.
// This is because the index is stored in the upper 16 bits of a handle,
// and the most significant bit must be zero to keep handles non-negative.
#define PSA_HANDLE_MGR_MAX_HANDLES_NUM 0x8000
@ -72,19 +70,19 @@ extern "C" {
typedef struct psa_handle_item_t {
psa_handle_t handle; /* The user exposed handle [unique identifier] */
int32_t handle_owner; /* The partition id of the handle creator - allowed to get_mem() / destroy() */
int32_t handle_friend; /* The partition id of a "friend" partition - allowed to get_mem() */
void *handle_mem; /* Points to memory allocated by the user */
psa_handle_t handle; /* The user-exposed handle [unique identifier]. */
int32_t handle_owner; /* The partition ID of the handle creator. Allowed to get_mem() / destroy(). */
int32_t handle_friend; /* The partition ID of a "friend" partition. Allowed to get_mem(). */
void *handle_mem; /* Points to memory allocated by the use.r */
} psa_handle_item_t;
typedef struct psa_handle_manager_t {
uint32_t handle_generator; /* A counter supplying handle numbers */
uint32_t pool_size; /* The maximum number of handles that pool can contain */
psa_handle_item_t *handles_pool; /* Holding couples of handles and their memory "blocks" */
uint32_t handle_generator; /* A counter supplying handle numbers. */
uint32_t pool_size; /* The maximum number of handles that pool can contain. */
psa_handle_item_t *handles_pool; /* Holds couples of handles and their memory "blocks". */
} psa_handle_manager_t;
@ -111,43 +109,43 @@ handles_pool
/*
* @brief create unique handle identifier
* @brief Create unique handle identifier
*
* This function generates a unique handle identifier, and "couples" it with the received handle memory.
* This function generates a unique handle identifier, and **couples** it with the received handle memory.
* If there is no vacant space for the new handle, the function fails.
*
* @note This function is expected to pass since it is always coupled with memory pool allocation of the same size.
* In case memory pool allocation fails, this function should not be called.
* This function will panic on non vacant space use case.
* This function will panic in the case of non-vacant space use.
*
* @param[in] handle_mgr A pointer to the handle manager object
* @param[in] handle_mem A pointer to a pre-allocated handle memory to get a handle identifier for
* @param[in] friend_pid The partition id which is allowed to get_mem() and destroy() in addition to the handle owner.
* Use PSA_HANDLE_MGR_INVALID_FRIEND_OWNER to denote there is no friend partition.
* @return The created handle identifier
* @param[in] handle_mgr A pointer to the handle manager object.
* @param[in] handle_mem A pointer to a pre-allocated handle memory for which to get a handle identifier.
* @param[in] friend_pid The partition ID allowed to `get_mem()` and `destroy()` in addition to the handle owner.
* Use `PSA_HANDLE_MGR_INVALID_FRIEND_OWNER` to denote that there is no friend partition.
* @return The created handle identifier
*/
psa_handle_t psa_hndl_mgr_handle_create(psa_handle_manager_t *handle_mgr, void *handle_mem, int32_t friend_pid);
/*
* @brief remove a handle from the handle manager.
* @brief Remove a handle from the handle manager.
*
* @param handle_mgr A pointer to the handle manager object
* @param handle The handle to be removed
* @param handle_mgr A pointer to the handle manager object.
* @param handle The handle to be removed.
*/
void psa_hndl_mgr_handle_destroy(psa_handle_manager_t *handle_mgr, psa_handle_t handle);
/*
* @brief dereference handle
* @brief De-reference handle
*
* This function retrieves the pointer associated with the input <handle>.
*
* @note This function will panic in case caller not allowed to dereference the memory
* or handler does not correspond to a valid existing handle
* @note This function will panic if caller is not allowed to de-reference the memory,
* or handler does not correspond to a valid existing handle.
*
* @param handle_mgr A pointer to the handle manager object.
* @param handle The handle for which we request the corresponding memory handle.
* @param handle The handle for which you request the corresponding memory handle.
* @return void* A pointer to the memory corresponding to the handle.
*/
void *psa_hndl_mgr_handle_get_mem(psa_handle_manager_t *handle_mgr, psa_handle_t handle);

View File

@ -110,11 +110,11 @@ typedef struct spm_ipc_channel {
struct spm_partition *src_partition; /* Pointer to the Partition which connects to the Root of Trust Service.*/
spm_rot_service_t *dst_rot_service; /* Pointer to the connected Root of Trust Service.*/
void *rhandle; /* Reverse handle to be used for this channel.*/
void *msg_ptr; /* message data sent from user */
struct spm_ipc_channel *next; /* Next channel in the chain */
void *msg_ptr; /* Message data sent from user. */
struct spm_ipc_channel *next; /* Next channel in the chain.*/
uint8_t msg_type; /* The message type.*/
uint8_t state; /* The current processing state of the channel.*/
uint8_t is_dropped;
uint8_t is_dropped; /* Indicates whether the channel has been dropped by the partition.*/
} spm_ipc_channel_t;
/*
@ -127,7 +127,7 @@ typedef struct spm_active_msg {
} spm_active_msg_t;
/*
* Structure containing resources and attributes of a Secure Partition.
* Structure containing resources and attributes of a secure partition.
*/
typedef struct spm_partition {
const int32_t partition_id; /* The Partition ID.*/
@ -136,7 +136,7 @@ typedef struct spm_partition {
const uint32_t flags_interrupts; /* Mask of all the IRQs & doorbell which the partition supports.*/
spm_rot_service_t *rot_services; /* Array of the Partition's Root of Trust Services.*/
const uint32_t rot_services_count; /* Number of the Partition's Root of Trust Services.*/
const uint32_t *extern_sids; /* Array of Root of Trust Service IDs which the partition can connect to.*/
const uint32_t *extern_sids; /* Array of Root of Trust Service IDs that the partition can connect to.*/
const uint32_t extern_sids_count; /* Number of Root of Trust Services which the partition can connect to.*/
osMutexId_t mutex; /* Mutex for all rot_service's queues operations. */
spm_signal_to_irq_mapper_t irq_mapper; /* a function which maps signal to irq number*/
@ -171,19 +171,19 @@ const mem_region_t *get_mem_regions(int32_t partition_id, uint32_t *region_count
// Platform dependent APIs
/*
* Validates a memory block is accessable from a specific partition
* Validates that a memory block accessible from a specific partition
*
* @param[in] ptr pointer to the beggining of the memory block.
* @param[in] size size of the memory block in bytes.
* @param[in] accessing_partition which partition is trying to access the memory.
* @return true if the entire memory block is accessable from given partition.
* @param[in] ptr - Pointer to the beggining of the memory block.
* @param[in] size - Size of the memory block in bytes.
* @param[in] accessing_partition - Which partition is trying to access the memory.
* @return `true` if the entire memory block is accessable from given partition.
*/
bool is_buffer_accessible(const void *ptr, size_t size, spm_partition_t *accessing_partition);
/**
* Alerts NSPE that a proccess (connect or call) has ended.
*
* @param[in] completion_sem_id semaphore id in NSPE.
* @param[in] completion_sem_id - semaphore id in NSPE.
*/
void nspe_done(osSemaphoreId_t completion_sem_id);

View File

@ -35,7 +35,7 @@ extern "C" {
#endif
/** @addtogroup RoT-Service-API
* The C interface for a Root of Trust Service in a partition.
* The C interface for a root of trust (RoT) Service in a partition.
* @{
*/
@ -75,8 +75,8 @@ int32_t psa_identity(psa_handle_t msg_handle);
/**
* Get the message that corresponds to a given signal.
*
* @param[in] signum an asserted signal returned from psa_wait().
* @param[out] msg pointer to a psa_msg structure.
* @param[in] signum An asserted signal returned from psa_wait().
* @param[out] msg Pointer to a psa_msg structure.
*/
void psa_get(psa_signal_t signum, psa_msg_t *msg);

View File

@ -1,117 +0,0 @@
## The Secure Partition Manager
The **Secure Partition Manager (SPM)** is a Platform Security Architecture (PSA) compliant software hypervisor that creates and manages independent Secure Partitions on Arm Cortex&reg;-M microcontrollers. It increases resilience against malware and protects secrets from leaking between different modules in the same application. The SPM complements other important security features, such as safe firmware updates and secure crypto libraries.
The SPM provides hardware-enforced partitions for individual code blocks by limiting access to memories and peripherals using the existing hardware security features of the Cortex&reg;-M microcontrollers. It isolates software in partitions, managing the execution of software within those partitions and providing Inter Process Communication (IPC) between the partitions. Correct use of SPM prevents malware from becoming resident on the device and enables protection of device secrets, such as cryptographic keys.
### Isolating partitions in the Secure Processing Environment
The SPM and the secure partitions are located in the Secure Processing Environment (SPE), isolating them from the Non-Secure Processing Environment (NSPE), which contains the application firmware, OS kernel and libraries, and other nonsecure hardware resources.
A secure partition is a container for one or more root of trust services, and a platform may have multiple secure partitions. Secure partitions provide the execution environment for security functionality.
Platform hardware, such as the Security Attribution Unit (SAU) and Memory Protection Unit (MPU) in the new ARMv8-M platforms, enforces the separation of partitions. Other platforms may use different mechanisms to provide equivalent isolation for the partitions.
#### PSA levels of isolation
If you are prototyping software or using platforms without SAU or MPU, you can choose to have no isolation between the SPE and NSPE (sometimes referred to as Level 0), though the PSA does not specify this. However, for production software, consider implementing one of the following levels of isolation:
* **Level 1 - SPE isolation** In this level, the SPE is fully isolated from the nonsecure application firmware and hardware.
* **Level 2 - Root of Trust isolation** In this level, the SPE is fully isolated from the nonsecure application firmware and hardware and the trusted partitions (secure partitions that implement Root of Trust services) are isolated from other secure partitions.
* **Level 3 - Maximum firmware isolation** In this level, the SPE is fully isolated from the nonsecure application firmware and hardware, and all secure and trusted partitions are individually sandboxed from one another and from the SPM.
### Using secure partitions
Secure partitions are located within the SPE, and must contain at least one set of related security operations (known as a root of trust service) or at least one Interrupt Request (IRQ). You can have multiple root of trust services in a single secure partition.
For a secure partition, you need:
* The **secure partition code**, which must:
* Be single threaded.
* Be structured as a loop that waits for inputs.
* Never exit its loop (considered as a programming error).
* Be written in C or 'extern "C"' to avoid C++ name mangling.
* Follow PSA IPC rules. Secure partitions communicate with one another using the IPC API defined in [IPC API](https://github.com/ARMmbed/PSA-IPC-doc/blob/master/IPC_revision.md). All IPC messages must eventually be completed [`call psa_end()`]. Note that the SPM does not schedule IPC messages fairly.
* A **manifest file** in JSON format, that describes the Secure Partition characteristics. The specifications in the manifest file are validated during the build process and at run time.
### Manifest file example
The secure partition manifest file describes the properties of the secure partitions. In this file:
* **entry_point** is the function name of the partition's thread.
* **source_files** is the list of source files containing the partition's code.
* **heap_size** sets the heap size for platforms that have an isolation level of 2 and higher.
* **services** is the list of the partition's root of trust services with their properties.
* **extern_sids** defines a dependency to other Root of Trust Service (referenced by SID). If the manifest does not specify the access between a partition (acting as client) and a root of trust service (acting as server), then the client is not able to send any messages to the root of trust service.
For example:
```json
{
"name": "BOX_MAIN",
"type": "APPLICATION-ROT",
"priority": "NORMAL",
"id": "0x7BADD00D",
"entry_point": "main",
"stack_size": 10,
"heap_size": "0x0400",
"mmio_regions": [
{
"name": "CMU",
"permission": "READ-WRITE"
},
{
"name": "MSC",
"permission": "READ-WRITE"
},
{
"name": "GPIO",
"permission": "READ-WRITE"
},
{
"name": "TIMER0",
"permission": "READ-WRITE"
},
{
"name": "UART0",
"permission": "READ-WRITE"
},
{
"base": "0x10000000",
"size": "0x1000",
"permission": "READ-ONLY"
},
{
"base": "0x42000000",
"size": "0x02000000",
"permission": "READ-ONLY"
}
],
"services": [
{
"sid": "PSA_TRUSTED_UPDATE",
"signal": "PSA_TRUSTED_UPDATE",
"non_secure_clients": true,
"minor_version": 1,
"minor_policy": "STRICT"
}
],
"extern_sids": [
"PSA_CRYPTO_RSA",
"PSA_CRYPTO_AES"
],
"source_files": [
"../source/main.cpp"
],
"irqs": [
{
"signal": "MY_IRQ",
"line_num": 4
}
]
}
```
#### Code example
[Mbed SPM example on GitHub](https://github.com/ARMmbed/mbed-os-example-spm)

View File

@ -1,23 +0,0 @@
# Mbed Secure Partition Manager (SPM)
The Platform Security Architecture (PSA) firmware framework specifications contain a logic component called the Secure Partition Manager (SPM). PSA defines a Secure Processing Environment (SPE) for:
* Sensitive data, such as keys, credentials and firmware.
* The code that manages it.
* Its trusted hardware resources.
The PSA SPM interfaces decouple components, allowing reuse of components in other device platform and helps to reduce an integration effort.
Mbed SPM is an implementation of PSA SPM, which:
* Secures low cost IoT devices, where a full Trusted Execution Environment (TEE) would not be appropriate.
* Protects sensitive assets (keys, credentials and firmware) by separating these from the application firmware and hardware.
* Is architecture agnostic and can be implemented on different Arm Cortex&reg;-M architectures, offering variable level of protection, based on platform resources.
![diagram](png/PSA-standardized-Interfaces-diagram.png)
## Further reading
* The [introduction to PSA SPM](INTRO.md) provides more details about PSA SPM.
* Visit the official Arm Platform Security Architecture web page https://pages.arm.com/psa-resources
* Trusted firmware presentation during the Linaro Connect event by James King on IOT http://connect.linaro.org/resource/hkg18/hkg18-212/

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

View File

@ -2099,6 +2099,8 @@ PREDEFINED = DOXYGEN_ONLY \
DEVICE_SPISLAVE \
DEVICE_QSPI \
DEVICE_STORAGE \
COMPONENT_SPE \
COMPONENT_SPM_MAILBOX \
"MBED_DEPRECATED_SINCE(d, m)=" \
"MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, M)=" \
"MBED_DEPRECATED(s)="

View File

@ -6,7 +6,7 @@
"SEARCH_INCLUDES": "YES",
"INCLUDE_PATH": "",
"INCLUDE_FILE_PATTERNS": "",
"PREDEFINED": "DOXYGEN_ONLY DEVICE_ANALOGIN DEVICE_ANALOGOUT DEVICE_CAN DEVICE_CRC DEVICE_ETHERNET DEVICE_EMAC DEVICE_FLASH DEVICE_I2C DEVICE_I2CSLAVE DEVICE_I2C_ASYNCH DEVICE_INTERRUPTIN DEVICE_ITM DEVICE_LPTICKER DEVICE_MPU DEVICE_PORTIN DEVICE_PORTINOUT DEVICE_PORTOUT DEVICE_PWMOUT DEVICE_RTC DEVICE_TRNG DEVICE_SERIAL DEVICE_SERIAL_ASYNCH DEVICE_SERIAL_FC DEVICE_SLEEP DEVICE_SPI DEVICE_SPI_ASYNCH DEVICE_SPISLAVE DEVICE_QSPI DEVICE_STORAGE \"MBED_DEPRECATED_SINCE(f, g)=\" \"MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, M)=\" \"MBED_DEPRECATED(s)=\"",
"PREDEFINED": "DOXYGEN_ONLY DEVICE_ANALOGIN DEVICE_ANALOGOUT DEVICE_CAN DEVICE_CRC DEVICE_ETHERNET DEVICE_EMAC DEVICE_FLASH DEVICE_I2C DEVICE_I2CSLAVE DEVICE_I2C_ASYNCH DEVICE_INTERRUPTIN DEVICE_ITM DEVICE_LPTICKER DEVICE_MPU DEVICE_PORTIN DEVICE_PORTINOUT DEVICE_PORTOUT DEVICE_PWMOUT DEVICE_RTC DEVICE_TRNG DEVICE_SERIAL DEVICE_SERIAL_ASYNCH DEVICE_SERIAL_FC DEVICE_SLEEP DEVICE_SPI DEVICE_SPI_ASYNCH DEVICE_SPISLAVE DEVICE_QSPI DEVICE_STORAGE COMPONENT_SPE COMPONENT_SPM_MAILBOX \"MBED_DEPRECATED_SINCE(f, g)=\" \"MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, M)=\" \"MBED_DEPRECATED(s)=\"",
"EXPAND_AS_DEFINED": "",
"SKIP_FUNCTION_MACROS": "NO",
"STRIP_CODE_COMMENTS": "NO",

View File

@ -1,3 +1,6 @@
/** \addtogroup hal */
/** @{*/
/* Copyright (c) 2017-2018 ARM Limited
*
* SPDX-License-Identifier: Apache-2.0
@ -18,14 +21,6 @@
#ifndef __SPM_API_H__
#define __SPM_API_H__
/** @addtogroup SPM
* The Secure Partition Manager (SPM) is responsible for isolating software in
* partitions, managing the execution of software within partitions and
* providing IPC between partitions.
* @{
*/
#include <stdint.h>
#include <stddef.h>
@ -34,8 +29,8 @@ extern "C" {
#endif
/** @addtogroup HAL-SPE
* The HAL functions for SPE.
/** @defgroup SPM-HAL SPM HAL API
* The HAL functions for PSA SPM
* @{
*/
@ -92,12 +87,12 @@ void spm_hal_mailbox_notify(void);
#endif // defined(COMPONENT_SPM_MAILBOX)
/** @}*/ // end of HAL-SPE group
/** @}*/
#ifdef __cplusplus
}
#endif
/** @}*/ // end of SPM group
#endif // __SPM_API_H__
/** @}*/