= Table of contents =
- Scope
- Terms and abbreviations
- References
- Introduction
- Design content
- PSA Protected Storage APIs
- TF-M SST Interfaces
- TF-M SST non-secure APIs
- SST secure APIs
- SST veneers
- SST service components
- Protected Storage
- SST Manifest file
- Object System
- Object definition
- Object Table
- Platform-specific SST configuration
- SST tools
- Validation tests
= Scope =
The scope of this page is to describe the SST secure service re-design to align it with the mandatory set of PSA Protected Storage APIs version 1.0.
It is out of the design scope the use of [[ https://developer.trustedfirmware.org/w/tf_m/design/uniform_secure_service_signature | Uniform Secure Service Signatures ]] for all the secure functions. The support for the uniform secure service signatures will be added later and it will part of another design document.
= Terms and abbreviations =
This document uses the following terms and abbreviations.
| Term | Meaning
|-------- |----------
| AEAD | Authenticated Encryption with Associated Data
| ARoT | Application Root of Trust
| API | Application Program Interface
| MAC | Message Authentication Code
| PITS | PSA Internal Trusted Storage
| PPS | PSA Protected Storage
| PSA | Platform Security Architecture
| PS | Protected Storage
| PST | Protected Storage Service
| SST | Secure Storage Service
| SP | Secure Partition
| TF-M | Trusted Firmware for M-class devices
| UID | Unique Identifier
= References =
| Ref | Title | Doc No
|-----|------|---------
| [1] | PSA Trusted Storage documentation | TBD
| [2] | [[ https://github.com/ARM-software/psa-arch-tests/blob/master/api-specs/include/psa/protected_storage.h | Protected Storage Header ]] | PSA PS API version 1.0
| [3] | [[ https://git.trustedfirmware.org/trusted-firmware-m.git/tree/docs/user_guides/services/tfm_sst_integration_guide.md | TF-M Secure Storage Service Integration Guide ]] | SHA: b92c9e408b55616ec40d44d9380501da44b772cd
| [4] | [[ https://github.com/arm-software/psa-arch-tests | PSA Arch Tests ]] | PSA Arch tests version 0.7
= Introduction =
As described in [1], PSA Protected Storage is designed to protect larger data sets against physical attacks and switched-off devices. It aims to provide the ability for a firmware developer to store data into external flash, with a promise of data-at-rest protection, including device-bound encryption, integrity, and rollback protection. It should be possible to select the appropriate protection level, e.g. encryption only, or integrity only, or both.
The PSA Protected Storage API (PPS API) is the general-purpose API that most developers should use.
On platforms with external storage, implementations of this API should provide authenticated encryption of the data, as well as rollback protection values stored using the PSA Internal Trusted Storage API (PITS API).
PSA Protected Storage requirements are [1]:
# The technology and techniques used by the PSA Protected Storage Service MUST allow for frequent writes and data updates.
# If writing to external storage, the PSA Protected Storage Service MUST provide confidentiality.
# Confidentiality for a PSA Protected Storage service may be provided by cryptographic ciphers using device-bound keys, a tamper resistant enclosure, or an inaccessible deployment location, depending on the threat model of the deployed system.
# If writing to external storage, the PSA Protected Storage Service MUST provide integrity protection.
# Integrity protection for a PSA Protected Storage service may be provided by cryptographic Message Authentication Codes (MAC) or signatures generated using device-bound keys, a tamper resistant enclosure, or an inaccessible deployment location, depending on the threat model of the deployed system.
# If writing to external storage, the PSA Protected Storage Service MUST provide replay protection by writing replay protection values through the PSA Internal Trusted Storage API.
# If providing services to secure partitions, and the PSA Isolation level is 3, the PSA Protected Storage Service MUST provide protection from one PSA partition accessing the storage assets of a different partition.
# The PSA Protected Storage Service MUST use the partition ID information associated with each request for its access control mechanism.
# If the PSA Protected Storage Service is providing services to other ARoT services, it MUST be implemented inside the ARoT itself.
# If implemented inside the ARoT, the PSA Protected Storage Service MAY use helper services outside of the ARoT to perform actual read and write operations through the external interface or file system.
# In the event of power failures or unexpected flash write failures, the implementation must attempt to fall back to allow retention of old content.
# The creation of a UID with value 0 (zero) must be treated as an error.
The current TF-M SST service implementation addresses all the PSA Protected Storage requirements mentioned above [3]. However, the current SST implementation differs in terms of APIs. This document will cover the required modification to be applied in the current TF-M SST service implementation to align its APIs with the PPS APIs version 1.0 [2].
= Design content =
This design does not keep compatibility with the deprecated APIs to force the transition to the new PPS APIs. This decision simplifies the service, less code and memory usage, and removes the requirement to maintain the deprecated APIs until there are removed from the service.
== PSA Protected Storage APIs ==
The new SST service exposes the mandatory set of PSA Protected Storage APIs as they are described in [2]. A detailed description of these interfaces is outside of the scope of this document.
The list of mandatory PPS APIs exposed by the SST service are:
===== psa_ps_set() =====
This function creates a new or modify an existing key/value pair.
```
psa_ps_status_t psa_ps_set(psa_ps_uid_t uid, uint32_t data_length, const void *p_data, psa_ps_create_flags_t create_flags);
```
**Parameters**
| Direction | Type | Name | Description
|------------|-------|--------|---------------
| in | psa_ps_uid_t | uid | The identifier for the data.
| in | uint32_t | data_length | The size in bytes of the data in `p_data
| in | const void * | p_data | A buffer containing the data.
| in | psa_ps_create_flags_t | create_flags | The flags indicating the properties of the data
**Return**
A status indicating the success/failure of the operation based on psa_ps_status_t type.
| Type | Description
|-------|--------------
| PSA_PS_ERROR_SUCCESS | The operation completed successfully
| PSA_PS_ERROR_WRITE_ONCE | The operation failed because the provided uid value was already created with PSA_PS_WRITE_ONCE_FLAG
| PSA_PS_ERROR_INVALID_ARGUMENT | The operation failed because one or more of the given arguments were invalid (null pointer, wrong flags, etc.)
| PSA_PS_ERROR_FLAGS_NOT_SUPPORTED | The operation failed because one or more of the flags provided in `create_flags` is not supported or is not valid
| PSA_PS_ERROR_INSUFFICIENT_SPACE | The operation failed because there was insufficient space on the storage medium
| PSA_PS_ERROR_STORAGE_FAILURE | The operation failed because the physical storage has failed (Fatal error)
| PSA_PS_ERROR_OPERATION_FAILED | The operation failed because of an unspecified internal failure
---
===== psa_ps_get() =====
This function retrieves the value for a provided uid.
```
psa_ps_status_t psa_ps_get(psa_ps_uid_t uid, uint32_t data_offset, uint32_t data_length, void *p_data);
```
**Parameters**
|Direction | Type | Name | Description
|-----------|-------|--------|--------------
| in | psa_ps_uid_t | uid | The identifier for the data
| in | uint32_t | data_offset | The offset within the data associated with the `uid` to start retrieving data
| in | uint32_t | data_length | The amount of data to read (and the minimum allocated size of the `p_data` buffer)
| out | void * | p_data | A buffer containing the data
**Return**
A status indicating the success/failure of the operation based on psa_ps_status_t type.
| Type | Description
| ------|--------------
| PSA_PS_ERROR_SUCCESS | The operation completed successfully
| PSA_PS_ERROR_INVALID_ARGUMENT | The operation failed because one or more of the given arguments were invalid (null pointer, wrong flags, etc.)
| PSA_PS_ERROR_UID_NOT_FOUND | The operation failed because the provided uid value was not found in the storage
| PSA_PS_ERROR_INCORRECT_SIZE | The operation failed because the data associated with provided uid is not the same size as `data_size`
| PSA_PS_ERROR_STORAGE_FAILURE | The operation failed because the physical storage has failed (Fatal error)
| PSA_PS_ERROR_OPERATION_FAILED | The operation failed because of an unspecified internal failure
| PSA_PS_ERROR_DATA_CORRUPT | The operation failed because of an authentication failure when attempting to get the key
| PSA_PS_ERROR_AUTH_FAILED | The operation failed because the data associated with the UID failed authentication
---
===== psa_ps_get_info() =====
This function retrieves the metadata about the provided uid.
```
psa_ps_status_t psa_ps_get_info(psa_ps_uid_t uid, struct psa_ps_info_t *p_info);
```
**Parameters**
| Direction | Type | Name | Description
|------------|-------|-------|----------------
| in | psa_ps_uid_t | uid | The identifier for the data.
| out | struct psa_ps_info_t | p_info | A pointer to the `psa_ps_info_t` struct that will be populated with the metadata
**Return**
A status indicating the success/failure of the operation based on psa_ps_status_t type.
| Type | Description
|-------|--------------
| PSA_PS_ERROR_SUCCESS | The operation completed successfully
| PSA_PS_ERROR_INVALID_ARGUMENT | The operation failed because one or more of the given arguments were invalid (null pointer, wrong flags, etc.)
| PSA_PS_ERROR_UID_NOT_FOUND | The operation failed because the provided uid value was not found in the storage
| PSA_PS_ERROR_STORAGE_FAILURE | The operation failed because the physical storage has failed (Fatal error)
| PSA_PS_ERROR_OPERATION_FAILED | The operation failed because of an unspecified internal failure
| PSA_PS_ERROR_DATA_CORRUPT | The operation failed because of an authentication failure when attempting to get the key
| PSA_PS_ERROR_AUTH_FAILED | The operation failed because the data associated with the UID failed authentication
---
===== psa_ps_remove() =====
This function removes the provided uid and its associated data from the storage.
```
psa_ps_status_t psa_ps_remove(psa_ps_uid_t uid);
```
**Parameters**
| Direction | Type | Name | Description
|------------|-------|--------|---------------
| in | psa_ps_uid_t | uid | The identifier for the data.
**Return**
A status indicating the success/failure of the operation based on psa_ps_status_t type.
| Type | Description
|-------|--------------
| PSA_PS_ERROR_SUCCESS | The operation completed successfully
| PSA_PS_ERROR_INVALID_ARGUMENT | The operation failed because one or more of the given arguments were invalid (null pointer, wrong flags, etc.)
| PSA_PS_ERROR_UID_NOT_FOUND | The operation failed because the provided uid value was not found in the storage
| PSA_PS_ERROR_WRITE_ONCE | The operation failed because the provided uid value was created with PSA_PS_WRITE_ONCE_FLAG
| PSA_PS_ERROR_STORAGE_FAILURE | The operation failed because the physical storage has failed (Fatal error)
| PSA_PS_ERROR_OPERATION_FAILED | The operation failed because of an unspecified internal failure
----
===== psa_ps_get_support() =====
This function returns a bitmask with flags set for all the optional features supported by the implementation.
```
uint32_t psa_ps_get_support(void);
```
**Parameters**
| Direction | Type | Name | Description
| -----------|--------|--------|-------------
| | void | | None
**Return**
A bitmask with the flags set for all the optional features supported by the implementation.
| Value | Description
|--------|--------------
| 0 | Any optional feature is supported
| PSA_PS_SUPPORT_SET_EXTENDED | To indicate that psa_ps_create and psa_ps_set_extended are supported
---
The extended set of PPS APIs are not going to be implemented for the moment. However, an empty implementation is required, which returns PSA_PS_ERROR_NOT_SUPPORTED, for each extended function. The extended set of PPS APIs will be supported in the future.
The list of extended PPS APIs are:
===== psa_ps_create() =====
This function creates an asset based on the given identifier, the maximum size and creation flags. This create allocates the space in the secure storage area without setting any data in the asset.
It is only necessary to call this function for items that will be written with the psa_ps_set_extended function. If only the psa_ps_set function is needed, calls to this function are redundant.
This function is optional. Not all PSA Protected Storage implementations will implement this function.
```
psa_ps_status_t psa_ps_create(psa_ps_uid_t uid, uint32_t size, psa_ps_create_flags_t create_flags);
```
**Parameters**
| Direction | Type | Name | Description
|------------|-------|--------|--------------
| in | psa_ps_uid_t | uid | The identifier for the data.
| in | uint32_t | size | The maximum size in bytes of the asset.
| in | psa_ps_create_flags_t | create_flags | The flags indicating the properties of the data
**Return**
A status indicating the success/failure of the operation based on psa_ps_status_t type.
| Type | Description
|-------|---------------
| PSA_PS_ERROR_SUCCESS | The operation completed successfully
| PSA_PS_ERROR_INVALID_ARGUMENT | The operation failed because one or more of the given arguments were invalid (null pointer, wrong flags, etc.)
| PSA_PS_ERROR_FLAGS_NOT_SUPPORTED | The operation failed because one or more of the flags provided in `create_flags` is not supported or is not valid. If the PSA_PS_FLAG_WRITE_ONCE flag is passed.
| PSA_PS_ERROR_INSUFFICIENT_SPACE | The operation failed because there was insufficient space on the storage medium
| PSA_PS_ERROR_STORAGE_FAILURE | The operation failed because the physical storage has failed (Fatal error)
| PSA_PS_ERROR_OPERATION_FAILED | The operation failed because of an unspecified internal failure
| PSA_PS_ERROR_NOT_SUPPORTED | The implementation of the API does not support this function
---
===== psa_ps_set_extended() =====
This function sets partial data into an asset based on the given identifier, data_offset, data length and p_data.
Before calling this function, the asset must have been created with a call to psa_ps_create.
This function is optional. Not all PSA Protected Storage implementations will implement this function.
```
psa_ps_status_t psa_ps_set_extended(psa_ps_uid_t uid, uint32_t data_offset, uint32_t data_length, const void *p_data);
```
**Parameters**
| Direction| Type | Name | Description
|-----------|-------|--------|----------------
| in | psa_ps_uid_t | uid | The identifier for the data.
| in | uint32_t | data_offset | The offset within the data associated with the `uid` to start writing data
| in | uint32_t | data_length | The size in bytes of the data in `p_data
| in | const void * | p_data | A buffer containing the data.
**Return**
A status indicating the success/failure of the operation based on psa_ps_status_t type.
| Type | Description
| PSA_PS_ERROR_SUCCESS | The operation completed successfully
| PSA_PS_ERROR_INVALID_ARGUMENT | The operation failed because one or more of the given arguments were invalid (null pointer, wrong flags, etc.)
| PSA_PS_ERROR_OFFSET_INVALID | The operation failed because an offset was supplied that is invalid for the allocated size of the space reserved for the `uid` when psa_psa_create was called. For example, offset + size is too large
| PSA_PS_ERROR_UID_NOT_FOUND | The specified UID was not found
| PSA_PS_ERROR_STORAGE_FAILURE | The operation failed because the physical storage has failed (Fatal error)
| PSA_PS_ERROR_OPERATION_FAILED | The operation failed because of an unspecified internal failure
| PSA_PS_ERROR_DATA_CORRUPT | The operation failed because the existing data has been corrupted
| PSA_PS_ERROR_AUTH_FAILED | The operation failed because the existing data failed authentication (MAC check failed)
| PSA_PS_ERROR_NOT_SUPPORTED | The implementation of the API does not support this function
---
== TF-M SST Interfaces ==
The SST header files in “<TF-M REPO>/interface/include” must be updated or removed as follows:
- Remove psa_sst_assets_XX.h files as the content of those files are not part of the PPS API specification.
- Remove tfm_sst_defs.h as its content is not longer required.
- Rename psa_sst_api.h to psa_sst_defs.h and update its content.
The protected_storage.h with the PSA PS APIs definitions must be added in this location “<TF-M REPO>/interface/include” under the psa_protected_storage.h to be aligned with the other psa header files in the folder. The psa_protected_storage.h is included by the tfm_sst_defs.h file, which is the top header file of SST service.
The “psa_sst_defs.h” file must be updated to include protected_storage.h as it is the header file which specifies the new SST service interfaces. The SST error enumeration needs to be modified to incorporate the new errors defined by the psa_ps_status_t type, and remove the obsolete once.
The TF-M SST error codes have an offset to make sure those return values do not overlap with predefined TF-M status values used by TF-M Core. The definition name of each value starts with TFM_SST_ERR prefix.
The new TF-M SST errors are:
| New TF-M SST errors
|---------------------------
| TFM_SST_ERR_WRITE_ONCE
| TFM_SST_ERR_FLAGS_NOT_SUPPORTED
| TFM_SST_ERR_INSUFFICIENT_SPACE
| TFM_SST_ERR_STORAGE_FAILURE
| TFM_SST_ERR_UID_NOT_FOUND
| TFM_SST_ERR_INCORRECT_SIZE
| TFM_SST_ERR_OFFSET_INVALID
| TFM_SST_ERR_INVALID_ARGUMENT
| TFM_SST_ERR_DATA_CORRUPT
| TFM_SST_ERR_AUTH_FAILED
| TFM_SST_ERR_OPERATION_FAILED
| TFM_SST_ERR_NOT_SUPPORTED
The removed TF-M SST errors are:
| Removed TF-M SST errors
|-------------
| PSA_SST_ERR_STORAGE_SYSTEM_FULL
| PSA_SST_ERR_PARAM_ERROR
| PSA_SST_ERR_SYSTEM_ERROR
| PSA_SST_ERR_ASSET_NOT_FOUND
The “tfm_sst_defs.h” file defines a macro, or another mechanism, to translate the TF-M SST error types to PSA PS error type.
The translation table is as follows:
| TF-M SST ERROR | PSA PS ERROR
|---------------------|-------------------
| TFM_SST_ERR_SUCCESS | PSA_PS_ERROR_SUCCESS
| TFM_SST_ERR_ WRITE_ONCE | PSA_PS_ERROR_WRITE_ONCE
| TFM_SST_ERR_FLAGS_NOT_SUPPORTED | PSA_PS_ERROR_FLAGS_NOT_SUPPORTED
| TFM_SST_ERR_ INSUFFICIENT_SPACE | PSA_PS_ERROR_INSUFFICIENT_SPACE
| TFM_SST_ERR_STORAGE_FAILURE | PSA_PS_ERROR_STORAGE_FAILURE
| TFM_SST_ERR_UID_NOT_FOUND | PSA_PS_ERROR_UID_NOT_FOUND
| TFM_SST_ERR_INCORRECT_SIZE | PSA_PS_ERROR_INCORRECT_SIZE
| TFM_SST_ERR_OFFSET_INVALID | PSA_PS_ERROR_OFFSET_INVALID
| TFM_SST_ERR_INVALID_ARGUMENT | PSA_PS_ERROR_INVALID_ARGUMENT
| TFM_SST_ERR_DATA_CORRUPT | PSA_PS_ERROR_DATA_CORRUPT
| TFM_SST_ERR_AUTH_FAILED | PSA_PS_ERROR_AUTH_FAILED
| TFM_SST_ERR_OPERATION_FAILED | PSA_PS_ERROR_OPERATION_FAILED
| TFM_SST_ERR_NOT_SUPPORTED | PSA_PS_ERROR_NOT_SUPPORTED
== TF-M SST non-secure APIs ==
The SST source file tfm_sst_api.c, located in “<TF-M REPO>/interface/src”, must be updated in order to be aligned with PPS APIs. This file is the entry point for the non-secure applications to perform a request to the SST service. The implementation in this file is the one responsible to call the veneer function, via tfm_ns_lock_dispatch, and translate TF-M SST error codes to PSA PS error codes accordingly.
== SST secure APIs ==
The tfm_sst_secure_api.c file, located in “<TF-M REPO>/secure_fw/services/secure_storage”, must be updated in order to be aligned with PSA PS APIs. This file is the entry point for the secure partitions to perform a request to the SST service. The implementation in this file is the one responsible to call the veneer functions and translate TF-M SST error codes to PSA PS error codes accordingly.
The functions which implements the PSA PS APIs needs to have the `__attribute__(( section("SFN")))` attribute set, in order to make sure the code is located in the unprivilege memory partition when the TF-M Level 3 is required.
== SST veneers ==
The tfm_sst_veneers.c file, located in “<TF-M REPO>/secure_fw/ns_callable”, must be updated in order to be aligned with the PPS APIs, and perform the proper calls to the TFM_CORE_SFN_REQUEST. The error type to be used by the veneer interfaces is the TF-M SST error type.
The new Protected Storage component in SST service is the component which process the SST request. Detailed information about this Protected Storage layer and the SST manifest can be found in sections below.
== SST service components ==
The current SST service implements a set of components, each one dedicated to implementing a specific functionality in each layer of the SST service firmware stack [3].
The set of functionalities are:
- Asset Policy Management: This layer contains asset's access policy management code. It validates all the request received by the SST services based on the access policy database.
- Object System: This component contains the object system implementation to manage all objects store in the SST area.
- File System: It abstracts the flash filesystem operations for the secure storage service. The purpose of this abstraction is to have the ability to plug-in other filesystems or filesystem proxies (supplicant). Currently, it implements a custom filesystem based on a non-hierarchical storage model where all the files are managed by linearly indexed list of metadata.
The current SST firmware stack is:
{F20006, size=full}
The new design replaces the asset policy management layer by the Protected Storage layer, and it removes the policy database. This new layer exposes the new set of asset manipulation interfaces which are compliant with the PPS APIs specification.
A more detailed information about the interfaces exposed by this layer can be found in the section below.
The new SST firmware layers are:
{F20007, size=full}
== Protected Storage ==
Protected storage (PS) layer replaces the old asset management layer in order to implement the new PSA PS APIs. This layer interacts with the object system layer to create, read, write and delete assets in the secure storage area, as well as to get the asset information.
The list of TF-M SST PS APIs exposed by the protected storage layer are:
===== tfm_sst_set() =====
This function creates a new or modify an existing key/value pair.
```
enum tfm_sst_err_t tfm_sst_set(psa_ps_uid_t *uid, uint32_t data_length, const void *p_data, psa_ps_create_flags_t create_flags);
```
**Parameters**
| Direction | Type | Name | Description
|------------|-------|--------|--------------
| in | psa_ps_uid_t * | uid | Pointer to the identifier for the data.
| in | uint32_t | data_length | The size in bytes of the data in `p_data
| in | const void * | p_data | A buffer containing the data.
| in | psa_ps_create_flags_t | create_flags | The flags indicating the properties of the data.
**Return**
A status indicating the success/failure of the operation based on enum tfm_sst_err_t type.
| Type | Description
| TFM_SST_ERR_SUCCESS | The operation completed successfully.
| TFM_SST_ERR_WRITE_ONCE | The operation failed because the provided uid value was already created with PSA_PS_WRITE_ONCE_FLAG.
| TFM_SST_ERR_INVALID_ARGUMENT | The operation failed because one or more of the given arguments were invalid (null pointer, wrong flags, etc.)
| TFM_SST_ERR_FLAGS_NOT_SUPPORTED | The operation failed because one or more of the flags provided in `create_flags` is not supported or is not valid.
| TFM_SST_ERR_INSUFFICIENT_SPACE | The operation failed because there was insufficient space on the storage medium.
| TFM_SST_ERR_STORAGE_FAILURE | The operation failed because the physical storage has failed (Fatal error).
| TFM_SST_ERR_OPERATION_FAILED | The operation failed because of an unspecified internal failure.
---
===== tfm_sst_get() =====
This function gets the asset data for a provided uid.
```
enum tfm_sst_err_t tfm_sst_get(psa_ps_uid_t *uid, uint32_t data_offset, uint32_t data_length, void *p_data);
```
**Parameters**
| Direction| Type | Name | Description
|-----------|-------|--------|----------------
| in | psa_ps_uid_t * | uid | Pointer to the identifier for the data.
| in | uint32_t | data_offset | The offset within the data associated with the `uid` to start retrieving data
| in | uint32_t | data_length | The amount of data to read (and the minimum allocated size of the `p_data` buffer)
| out | void * | p_data | A buffer containing the data
**Return**
A status indicating the success/failure of the operation based on enum tfm_sst_err_t type.
| Type | Description
|-------|----------------
| TFM_SST_ERR_SUCCESS | The operation completed successfully
| TFM_SST_ERR_INVALID_ARGUMENT | The operation failed because one or more of the given arguments were invalid (null pointer, wrong flags, etc.)
| TFM_SST_ERR_UID_NOT_FOUND | The operation failed because the provided uid value was not found in the storage
| TFM_SST_ERR_STORAGE_FAILURE | The operation failed because the physical storage has failed (Fatal error)
| TFM_SST_ERR_OPERATION_FAILED | The operation failed because of an unspecified internal failure
| TFM_SST_ERR_DATA_CORRUPT | The operation failed because of the data is corrupted
| TFM_SST_ERR_AUTH_FAILED | The operation failed because of an authentication failure when attempting to get the key
---
===== tfm_sst_get_info() =====
This function gets the asset information about the provided uid.
```
enum tfm_sst_err_t tfm_sst_get_info(psa_ps_uid_t *uid, struct psa_ps_info_t *p_info);
```
**Parameters**
| Direction | Type | Name | Description
| in | psa_ps_uid_t * | uid | Pointer to the identifier for the data.
| out | struct psa_ps_info_t * | p_info | A pointer to the `psa_ps_info_t` struct that will be populated with the metadata
**Return**
A status indicating the success/failure of the operation based on enum tfm_sst_err_t type.
| Type | Description
| TFM_SST_ERR_SUCCESS | The operation completed successfully
| TFM_SST_ERR_INVALID_ARGUMENT | The operation failed because one or more of the given arguments were invalid (null pointer, wrong flags, etc.)
| TFM_SST_ERR_UID_NOT_FOUND | The operation failed because the provided uid value was not found in the storage
| TFM_SST_ERR_STORAGE_FAILURE | The operation failed because the physical storage has failed (Fatal error)
| TFM_SST_ERR_OPERATION_FAILED | The operation failed because of an unspecified internal failure
| TFM_SST_ERR_DATA_CORRUPT | The operation failed because of the data is corrupted
| TFM_SST_ERR_AUTH_FAILED | The operation failed because of an authentication failure when attempting to get the key
---
===== tfm_sst_remove() =====
This his function removes the asset from the storage.
```
enum tfm_sst_err_t tfm_sst_remove(psa_ps_uid_t *uid);
```
**Parameters**
| Direction | Type | Name | Description
| in | psa_ps_uid_t * | uid | Pointer to the identifier for the data.
**Return**
A status indicating the success/failure of the operation based on enum tfm_sst_err_t type.
| Type | Description
| TFM_SST_ERR_SUCCESS | The operation completed successfully
| TFM_SST_ERR_UID_NOT_FOUND | The operation failed because the provided uid value was not found in the storage
| TFM_SST_ERR_WRITE_ONCE | The operation failed because the provided uid value was created with PSA_PS_WRITE_ONCE_FLAG
| TFM_SST_ERR_STORAGE_FAILURE | The operation failed because the physical storage has failed (Fatal error)
| TFM_SST_ERR_OPERATION_FAILED | The operation failed because of an unspecified internal failure
---
===== tfm_sst_get_support() =====
This function returns a bitmask with flags set for all the optional features supported by the implementation.
```
enum tfm_sst_err_t tfm_sst_get_support(uint32_t *support_flags);
```
**Parameters**
| Direction | Type | Name | Description
|------------|-------|--------|--------------
| out | uint32_t* | support_flags | A pointer to a variable that will be populated with a uint32_t bitmask value which contains all the bits set for all the optional features supported by the implementation
**Return**
A status indicating the success/failure of the operation based on enum tfm_sst_err_t type.
| Type | Description
| TFM_SST_ERR_SUCCESS | The operation completed successfully
| TFM_SST_ERR_OPERATION_FAILED | The operation failed because of an unspecified internal failure
For the current implementation, this function must return 0 as the optional functions are not going to be implemented at this phase.
---
===== tfm_sst_init() =====
This function initializes the secure storage system.
```
enum tfm_sst_err_t tfm_sst_init(void);
```
**Parameters**
| Direction | Type | Name | Description
|------------|-------|--------|---------------
| | void | | None
**Return**
A status indicating the success/failure of the operation based on enum tfm_sst_err_t type.
| Type | Description
|-------|---------------
| TFM_SST_ERR_SUCCESS | The operation completed successfully
| TFM_SST_ERR_STORAGE_FAILURE | The operation failed because the physical storage has
failed (Fatal error)
| TFM_SST_ERR_OPERATION_FAILED | The operation failed because of an unspecified internal failure
== SST Manifest file ==
The SST manifest file must be updated to expose the Protected Storage layer functions instead of the old asset management functions. The “tfm_init_symbol” and “secure_functions” entries in the manifest file must be updated according to the new Protected Storage layer functions, as well as the “source_file” list.
== Object System ==
The SST object system layer must be updated to accommodate it to the PPS specification. According to the PPS requirements [1], the service must provide protection from one PSA partition accessing the storage assets of a different partition. In order to achieve this requirement, the object system must associate the asset UID with the secure partition (SP) or non-secure application which has created the asset (client ID). If another SP or non-secure application requests the access to an asset which does not belongs to it, the request must be rejected with the proper error type. Different clients can use the same UID to references different assets.
The object system interfaces must be updated to reflect the following changes:
- Rename uuid to uid
- Remove token structures
- Add client ID and create_flags
- Update create function to write in the file the data provided as an input
- Add check if the write once flag is set
- Update error codes in the code accordingly
The updated list of interfaces exposed by the object system layer are:
===== sst_object_create() =====
This function creates a new object about the provided UID.
```
enum tfm_sst_err_t sst_object_create(psa_ps_uid_t uid, int32_t client_id, psa_ps_create_flags_t create_flags, uint32_t size, const uint8_t *p_data);
```
**Parameters**
| Direction | Type | Name | Description
|------------|------|-------|----------------
| in | psa_ps_uid_t | uid | The identifier for the data.
| in | int32_t| client_id | The identifier of the asset’s owner (client)
| in | psa_ps_create_flags_t | create_flags | The flags indicating the properties of the data.
| in | uint32_t | size | The size in bytes of the data in `p_data`.
| in | const uint8_t * | p_data | A buffer containing the data.
**Return**
A status indicating the success/failure of the operation based on enum tfm_sst_err_t type.
| Type | Description
| TFM_SST_ERR_SUCCESS | The operation completed successfully
| TFM_SST_ERR_INVALID_ARGUMENT | The operation failed because one or more of the given arguments were invalid (null pointer, wrong flags, etc.)
| TFM_SST_ERR_INSUFFICIENT_SPACE | The operation failed because there was insufficient space on the storage medium
| TFM_SST_ERR_STORAGE_FAILURE | The operation failed because the physical storage has failed (Fatal error)
| TFM_SST_ERR_OPERATION_FAILED | The operation failed because of an unspecified internal failure
---
===== sst_object_read() =====
This function gets object's data about the provided UID.
```
enum tfm_sst_err_t sst_object_read(psa_ps_uid_t uid, int32_t client_id, uint32_t offset, uint32_t size, uint8_t *p_data);
```
**Parameters**
| Direction | Type | Name | Description
|------------|------|-------|----------------
| in | psa_ps_uid_t | uid | The identifier for the data
| in | int32_t | client_id | The identifier of the asset’s owner (client)
| in | uint32_t | offset | The offset within the data associated with the `uid` to start retrieving data
| in | uint32_t | size | The size in bytes of the data in `p_data`
| out | uint8_t * | p_data | A buffer containing the data
**Return**
A status indicating the success/failure of the operation based on enum tfm_sst_err_t type.
| Type | Description
|-------|---------------
| TFM_SST_ERR_SUCCESS | The operation completed successfully
| TFM_SST_ERR_INVALID_ARGUMENT | The operation failed because one or more of the given arguments were invalid (null pointer, wrong flags, etc.)
| TFM_SST_ERR_STORAGE_FAILURE | The operation failed because the physical storage has failed (Fatal error)
| TFM_SST_ERR_OPERATION_FAILED | The operation failed because of an unspecified internal failure
| TFM_SST_ERR_DATA_CORRUPT | The operation failed because of the data is corrupted
| TFM_SST_ERR_AUTH_FAILED | The operation failed because of an authentication failure
---
===== sst_object_write() =====
This function writes data into the object about the provided UID.
```
enum tfm_sst_err_t sst_object_write(psa_ps_uid_t uid, int32_t client_id, uint32_t offset, uint32_t size, const uint8_t *p_data);
```
**Parameters**
| Direction | Type | Name | Description
|------------|------|-------|----------------
| in | psa_ps_uid_t | uid | The identifier for the data
| in | int32_t | client_id | The identifier of the asset’s owner (client)
| in | uint32_t | offset | The offset within the data associated with the `uid` to start writing data
| in | uint32_t | size | The size in bytes of the data in `p_data`
| in | const uint8_t * | p_data | A buffer containing the data
**Return**
A status indicating the success/failure of the operation based on enum tfm_sst_err_t type.
| Type | Description
|-------|---------------
| TFM_SST_ERR_SUCCESS | The operation completed successfully
| TFM_SST_ERR_INVALID_ARGUMENT | The operation failed because one or more of the given arguments were invalid (null pointer, wrong flags, etc.)
| TFM_SST_ERR_UID_NOT_FOUND | If the object does not exist for this owner or authentication fails
| TFM_SST_ERR_INSUFFICIENT_SPACE | The operation failed because there was insufficient space on the storage medium
| TFM_SST_ERR_STORAGE_FAILURE | The operation failed because the physical storage has failed (Fatal error)
| TFM_SST_ERR_OPERATION_FAILED | The operation failed because of an unspecified internal failure
| TFM_SST_ERR_DATA_CORRUPT | The operation failed because of the data is corrupted
| TFM_SST_ERR_AUTH_FAILED | The operation failed because of an authentication failure when attempting to get the key
---
===== sst_object_delete() =====
This function deletes the object about the provided UID.
```
enum tfm_sst_err_t sst_object_delete(psa_ps_uid_t uid, int32_t client_id);
```
**Parameters**
| Direction | Type | Name | Description
|------------|------|-------|----------------
| in | psa_ps_uid_t | uid | The identifier for the data.
| in | int32_t | client_id | The identifier of the asset’s owner (client)
**Return**
A status indicating the success/failure of the operation based on enum tfm_sst_err_t type.
| Type | Description
|-------|---------------
| TFM_SST_ERR_SUCCESS | The operation completed successfully
| TFM_SST_ERR_UID_NOT_FOUND | If the object does not exist for this owner or authentication fails
| TFM_SST_ERR_STORAGE_FAILURE | The operation failed because the physical storage has failed (Fatal error)
| TFM_SST_ERR_OPERATION_FAILED | The operation failed because of an unspecified internal failure
---
===== sst_object_get_info() =====
This function gets the asset information about the provided UID.
```
enum tfm_sst_err_t sst_object_get_info(psa_ps_uid_t uid, int32_t client_id, psa_ps_info_t *info);
```
**Parameters**
| Direction | Type | Name | Description
|------------|------|-------|----------------
| in | psa_ps_uid_t | uid | The identifier for the data
| in | int32_t | client_id | The identifier of the asset’s owner (client)
| out | psa_ps_info_t * | p_info | A pointer to the `psa_ps_info_t` struct that will be populated with the metadata
**Return**
A status indicating the success/failure of the operation based on enum tfm_sst_err_t type.
| Type | Description
|-------|---------------
| TFM_SST_ERR_SUCCESS | The operation completed successfully
| TFM_SST_ERR_INVALID_ARGUMENT | The operation failed because one or more of the given arguments were invalid (null pointer, etc.)
| TFM_SST_ERR_UID_NOT_FOUND | If the object does not exist for this owner or authentication fails
| TFM_SST_ERR_STORAGE_FAILURE | The operation failed because the physical storage has failed (Fatal error)
| TFM_SST_ERR_OPERATION_FAILED | The operation failed because of an unspecified internal failure
| TFM_SST_ERR_DATA_CORRUPT | The operation failed because of the data is corrupted
| TFM_SST_ERR_AUTH_FAILED | The operation failed because of an authentication failure when attempting to get the key
---
The following interfaces are not available in the new design. So, they must be removed.
```
enum psa_sst_err_t sst_object_get_attributes(uint32_t uuid, const struct tfm_sst_token_t *s_token, struct psa_sst_asset_attrs_t *p_info);
enum psa_sst_err_t sst_object_set_attributes(uint32_t uuid, const struct tfm_sst_token_t *s_token, const struct psa_sst_asset_attrs_t *attrs);
```
===== Object definition =====
The object definition must be updated as follows:
- Remove struct psa_sst_asset_attrs_t attr
- Rename struct psa_sst_asset_info_t by struct sst_object_info_t
This is required to define sst_object_info_t structure as follows:
```
/*!
* \struct sst_object_info_t
*
* \brief Object information.
*/
struct sst_object_info_t {
uint32_t current_size; /*!< The current size of the object content */
uint32_t max_size; /*!< The maximum size of the object content in bytes */
psa_ps_create_flags_t create_flags; /*!< Object creation flags */
};
```
NOTE: The maximum size attribute will be used when the PPS extended API is supported.
The new object header version is as follows:
```
struct sst_obj_header_t {
#ifdef SST_ENCRYPTION
/* Metadata attached as a header to encrypted object data before storage */
union sst_crypto_t crypto; /*!< Crypto metadata */
#else
uint32_t version; /*!< Object version */
uint32_t fid; /*!< File ID */
#endif
struct sst_object_info_t info; /*!< Object information */
};
```
===== Object Table =====
The object table interfaces need to be updated to reflect the following changes:
- Rename uuid to uid
- Add client ID to be added in the object table
The object table contains the following information for each object stored in the system:
```
struct sst_obj_table_entry_t {
#ifdef SST_ENCRYPTION
uint8_t tag[SST_TAG_LEN_BYTES]; /*!< MAC value of AEAD object */
#else
uint32_t version; /*!< File version */
#endif
psa_ps_uid_t uid /*!< Object UID */
int32_t client_id; /*!< Client ID */
};
```
The list of interfaces to be modified in the object table layer are:
**sst_object_table_obj_exist()**
This function checks if there is an entry in the table about the provided UID and client ID pair.
```
enum tfm_sst_err_t sst_object_table_obj_exist(psa_ps_uid_t uid, int32_t client_id);
```
**Parameters**
| Direction | Type | Name | Description
|------------|------|-------|----------------
| in | psa_ps_uid_t | uid | The identifier for the data.
| in | int32_t | client_id | The identifier of the asset’s owner (client)
**Return**
A status indicating the success/failure of the operation based on enum tfm_sst_err_t type.
| Type | Description
|-------|---------------
| TFM_SST_ERR_SUCCESS| If the object exists
| TFM_SST_ERR_UID_NOT_FOUND| If an entry in the table does not exist
---
**sst_object_table_set_obj_tbl_info()**
This function sets object table information in the object table, stores it persistently, about the provided UID and client ID pair.
```
enum tfm_sst_err_t sst_object_table_set_obj_tbl_info(psa_ps_uid_t uid, int32_t client_id, const struct sst_obj_table_info_t *obj_tbl_info);
```
**Parameters**
| Direction | Type | Name | Description
|------------|-------|--------|----------------
| in | psa_ps_uid_t | uid | The identifier for the data.
| in | int32_t | client_id | The identifier of the asset’s owner (client)
| in | const struct sst_obj_table_info_t * | obj_tbl_info | A buffer containing the object table information data
**Return**
A status indicating the success/failure of the operation based on enum tfm_sst_err_t type.
| Type | Description
|-------|---------------
| TFM_SST_ERR_SUCCESS | The operation completed successfully
| TFM_SST_ERR_INVALID_ARGUMENT | The operation failed because one or more of the given arguments were invalid (null pointer, etc.)
| TFM_SST_ERR_INSUFFICIENT_SPACE | The operation failed because there was insufficient space on the storage medium
| TFM_SST_ERR_STORAGE_FAILURE | The operation failed because the physical storage has failed
| TFM_SST_ERR_OPERATION_FAILED | The operation failed because the storage system has failed
| TFM_SST_ERR_DATA_CORRUPT | The operation failed because of the data is corrupted
| TFM_SST_ERR_AUTH_FAILED | The operation failed because of an authentication failure
---
**sst_object_table_get_obj_tbl_info()**
This function gets the object table information from the object table about the provided UID and client ID pair.
```
enum tfm_sst_err_t sst_object_table_get_obj_tbl_info(psa_ps_uid_t uid, int32_t client_id, struct sst_obj_table_info_t *obj_tbl_info);
```
**Parameters**
| Direction | Type | Name | Description
|------------|------|-------|----------------
| in | psa_ps_uid_t | uid | The identifier for the data
| in | int32_t | client_id | The identifier of the asset’s owner (client)
| out | struct sst_obj_table_info_t * | obj_tbl_info | The buffer where the object table information data will be placed upon successful completion
**Return**
A status indicating the success/failure of the operation based on enum tfm_sst_err_t type.
| Type | Description
|-------|---------------
| TFM_SST_ERR_SUCCESS | The operation completed successfully
| TFM_SST_ERR_UID_NOT_FOUND | If an entry in the table does not exist
| TFM_SST_ERR_INVALID_ARGUMENT | The operation failed because one or more of the given arguments were invalid (null pointer, etc.)
| TFM_SST_ERR_OPERATION_FAILED | The operation failed because the storage system has failed
----
**sst_object_table_delete_object()**
This function deletes the object entry about the provided UID and client ID pair and stores this change persistently.
```
enum tfm_sst_err_t sst_object_table_delete_object(psa_ps_uid_t uid, int32_t client_id);
```
**Parameters**
| Direction | Type | Name | Description
|------------|------|-------|----------------
| in | psa_ps_uid_t | uid | The identifier for the data.
| in | int32_t | client_id | The identifier of the asset’s owner (client)
**Return**
A status indicating the success/failure of the operation based on enum tfm_sst_err_t type.
| Type | Description
|-------|---------------
| TFM_SST_ERR_SUCCESS | The operation completed successfully
| TFM_SST_ERR_UID_NOT_FOUND | If an entry in the table does not exist
| TFM_SST_ERR_STORAGE_FAILURE | If the object does not exist for this owner
| TFM_SST_ERR_OPERATION_FAILED | The operation failed because the storage system has failed
| TFM_SST_ERR_DATA_CORRUPT | The operation failed because of the data is corrupted
| TFM_SST_ERR_AUTH_FAILED | The operation failed because of an authentication failure
== Platform-specific SST configuration ==
The current SST service implementation does not allocate dynamic memory. So, all the memory needs be allocated at compile time. In the current design, there are 2 parameters that are defined based on the policy table and are used to dimension the amount of static memory required by the SST service. Those parameters are the maximum asset size and number of assets. As the policy table is not part of the new design, the maximum asset size and maximum number of assets, managed by the object system, need to be defined and exposed by the system integrator based on the board capabilities and/or system configuration. As a temporary solution, those parameters need to be exposed in the "flash_layout.h" located in “<TF-M PATH>/platform/ext/target/<target_name>/partition”. There is the place where other SST parameters are defined by the system integrators. It will be evaluated the fact of introduce a specific file for the SST configuration in the platforms folder.
As part of the re-design work, the following defines needs to be specified in the flash_layout.h:
- SST_MAX_ASSET_SIZE
Defines the maximum asset size to be stored in the SST area.
- SST_NUM_ASSETS
Defines the maximum number of assets to be stored in the SST area.
For the current platforms in the repository, the default values are 2048 for SST_MAX_ASSET_SIZE, and 10 for SST_NUM_ASSETS. Those are the values defined in sst_asset_defs.h.
== SST tools ==
As the policy table is not required in the new design, the SST folder must be removed from tools in order to delete the Python script tool which generates the table based on the YAML file.
== Validation tests ==
To validate the new SST service design and all changes in it, a set of new TF-M SST test suites will be implemented to validate the new interfaces.
The implementation of those test suites will be placed in “<TF-M REPO>/test/suites/sst/non_secure/” and “<TF-M REPO>/test/suites/sst/secure/”
To validate the modifications in the object system, it is required to update “sst_rollback_protection_testsuite” and “sst_reliability_testsuite” suites to use the new PSA PS APIs.
The following test suites are no longer required as tested functionalities have been removed from the service:
- SST referenced access test suite. The SST test service created to be used in combination with this test suite will be removed as well.
- SST policy test suite.
A more exhaustive validation of the new SST service must be performed with PSA Arch tests [4] in order to validate that SST service is compliant with PSA protected storage APIs.