= Table of contents =
- Table of contents
- Scope
- Terms and abbreviations
- References
- Introduction
- Design content
- SST service components
- SST request Manager
- SST Manifest file
- TF-M error codes
- PSA PS APIs non-secure and secure implementation
- Validation tests
= Scope =
The scope of this document is to describe the SST secure service design to align it with the [[https://developer.trustedfirmware.org/w/tf_m/design/uniform_secure_service_signature | uniform secure service signatures]].
= Terms and abbreviations =
This document uses the following terms and abbreviations.
| Term | Meaning
|------|---------
| API | Application Program Interface
| PS | Protected Storage
| PSA | Platform Security Architecture
| PPS | PSA Protected Storage
| SST | Secure Storage Service
| TF-M | Trusted Firmware for M-class devices
= References =
| Ref | Title | Doc No
|-----|-------|--------
| [1] | [[https://developer.trustedfirmware.org/w/tf_m/design/uniform_secure_service_signature | Uniform Secure Service Signatures]] |
| [2] | [[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]] |
| [3] | [[https://developer.trustedfirmware.org/w/tf_m/design/secure_storage_service/psa_protected_storage_apis_alignment | PSA Protected Storage APIs Alignment]] |
| [4] | [[https://github.com/ARM-software/psa-arch-tests/blob/master/api-specs/include/psa/protected_storage.h | Protected Storage header]] | PSA PS APIs version 1.0
| [5] | [[https://github.com/ARM-software/psa-arch-tests | PSA Arch tests]] | PSA Arch tests version 0.7
= Introduction =
Currently, a <service_name>_veneers.c file is created in the secure_fw/ns_callable directory, that specifies the signature for each veneer function, and calls the secure function from the veneers.
The respective interface/include/<service_name>_veneers.h file with the veneer declarations is created and maintained manually. In addition, the TF-M framework, aligned with that design, limits the range of valid return values a secure service can provide, reserving a range for framework error codes.
The uniform secure service signature design [ [[https://developer.trustedfirmware.org/w/tf_m/design/uniform_secure_service_signature | 1]] ] proposes to use a uniform signature for all the secure functions of the secure service. There are multiple advantages of this method:
- TF-M Core can do a sanity check on the access rights of the veneer parameters, and there is no need for the secure services to make these checks individually. Please note that in the present implementation sanity check is only fully supported for level 1 isolation.
- The veneer declarations and implementations for the secure functions can be generated automatically from a template (using the secure function list in the secure service's manifest)
The signature for such secure services would look like this:
```
psa_status_t secure_function_name(struct psa_invec *in_vec, size_t in_len,
struct psa_outvec *out_vec, size_t out_len);
```
A detailed information about the signature can be found in [ [[https://developer.trustedfirmware.org/w/tf_m/design/uniform_secure_service_signature | 1]] ].
= Design Content =
== 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 [ [[https://git.trustedfirmware.org/trusted-firmware-m.git/tree/docs/user_guides/services/tfm_sst_integration_guide.md | 2]] ][ [[https://developer.trustedfirmware.org/w/tf_m/design/uniform_secure_service_signature | 3]] ].
The set of functionalities are:
- Protected Storage layer: This layer exposes the PSA protected storage set of interfaces which are compliant with the PPS APIs specification.
- Object System: This component contains the object system implementation to manage all objects stored 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:
{F20007, size=full}
The new design adds the SST request manager layer as the entry point to the service. This layer manages all requests which arrive to the service, and performs the proper Protected Storage calls. Detailed information about this layer can be found in the section below.
The new SST firmware layers are:
{F20580, size=full}
== SST request Manager ==
The SST request manager handles all requests which arrive to the service. The interfaces of this layer are aligned with the [[https://developer.trustedfirmware.org/w/tf_m/design/uniform_secure_service_signature | unified secure service signatures]]. This layer extracts the arguments from the input and output vectors, and it calls the protected storage layer with the provided parameters. It also checks that the number of parameters and sizes are aligned with the protected storage interface to call.
The list of interfaces exposed by the SST request manager layer are:
=== tfm_sst_set_req() ===
This function handles the PSA PS set requests.
```
psa_status_t tfm_sst_set_req(struct psa_invec *in_vec, size_t in_len,
struct psa_outvec *out_vec, size_t out_len);
```
**Parameters**
| Direction | Type | Name | Description
|------------|-------|--------|--------------
| in | struct psa_invec * | in_vec | Pointer to the input vector which contains the input parameters.
| in | size_t | in_len | Number of input parameters in the input vector.
| out | struct psa_invec * | out_vec | Pointer to the output vector which contains the output parameters.
| in | size_t | out_len | Number of output parameters in the output vector.
**Return**
A status indicating the success/failure of the operation as specified in psa_status_t.
| Type | Description
|-------|--------------
| PSA_SUCCESS | The operation completed successfully.
| PSA_CONNECTION_REFUSED | The operation is refused because the number of input or output parameters in the vectors are incorrect or their types are incorrect.
The following table shows the input parameters mapping in the in_vec vector.
| PSA IN_VEC Element | SST PS Layer Set Function Input Parameter Names
|--------------------------|-----------------------------------------------------------
| in_vec[0].base = &uid; in_vec[0].len = sizeof(uid); | `psa_ps_uid_t uid`
| in_vec[1].base = p_data; in_vec[1].len = data_length; | `const void *p_data` and `uint32_t data_length`
| in_vec[2].base = &create_flags; in_vec[2].len = sizeof(create_flags); | `psa_ps_create_flags_t create_flags`
The following table shows the input parameters mapping in the out_vec vector.
| PSA OUT_VEC Element | SST PS Layer Set Function Output/Return Parameter Name
|-----------------------------|---------------------------------------------------------------------
| out_vec[0].base = &err; out_vec[0].len = sizeof(err); | `psa_ps_status_t err` defined in the caller space
=== tfm_sst_get_req() ===
This function handles the PSA PS get requests.
```
psa_status_t tfm_sst_get_req(struct psa_invec *in_vec, size_t in_len,
struct psa_outvec *out_vec, size_t out_len);
```
**Parameters**
| Direction | Type | Name | Description
|------------|-------|--------|--------------
| in | struct psa_invec * | in_vec | Pointer to the input vector which contains the input parameters.
| in | size_t | in_len | Number of input parameters in the input vector.
| out | struct psa_invec * | out_vec | Pointer to the output vector which contains the output parameters.
| in | size_t | out_len | Number of output parameters in the output vector.
**Return**
A status indicating the success/failure of the operation as specified in psa_status_t.
| Type | Description
|-------|--------------
| PSA_SUCCESS | The operation completed successfully.
| PSA_CONNECTION_REFUSED | The operation is refused because the number of input or output parameters in the vectors are incorrect or their types are incorrect.
The following table shows the input parameters mapping in the in_vec vector.
| PSA IN_VEC Element | SST PS Layer Get Function Input Parameter Names
|--------------------------|-----------------------------------------------------------
| in_vec[0].base = &uid; in_vec[0].len = sizeof(uid); | `psa_ps_uid_t uid`
| in_vec[1].base = &data_offset; in_vec[1].len = sizeof(data_offset); | `uint32_t data_offset`
The following table shows the input parameters mapping in the out_vec vector.
| PSA OUT_VEC Element | SST PS Layer Get Function Output/Return Parameter Names
|----------------------------|------------------------------------------------------------------------
| out_vec[0].base = &err; out_vec[0].len = sizeof(err); | `psa_ps_status_t err` defined in the caller space
| out_vec[1].base = p_data; out_vec[1].len = data_length; | `const void *p_data` and `uint32_t data_length`
=== tfm_sst_get_info_req() ===
This function handles the PSA PS get info requests.
```
psa_status_t tfm_sst_get_info_req(struct psa_invec *in_vec, size_t in_len,
struct psa_outvec *out_vec, size_t out_len);
```
**Parameters**
| Direction | Type | Name | Description
|------------|-------|--------|--------------
| in | struct psa_invec * | in_vec | Pointer to the input vector which contains the input parameters.
| in | size_t | in_len | Number of input parameters in the input vector.
| out | struct psa_invec * | out_vec | Pointer to the output vector which contains the output parameters.
| in | size_t | out_len | Number of output parameters in the output vector.
**Return**
A status indicating the success/failure of the operation as specified in psa_status_t.
| Type | Description
|-------|--------------
| PSA_SUCCESS | The operation completed successfully.
| PSA_CONNECTION_REFUSED | The operation is refused because the number of input or output parameters in the vectors are incorrect or their types are incorrect.
The following table shows the input parameters mapping in the in_vec vector.
| PSA IN_VEC Element | SST PS Layer Get Info Function Input Parameter Name
|--------------------------|-----------------------------------------------------------
| in_vec[0].base = &uid; in_vec[0].len = sizeof(uid); | `psa_ps_uid_t uid`
The following table shows the input parameters mapping in the out_vec vector.
| PSA OUT_VEC Element | SST PS Layer Get Info Function Output/Return Parameter Names
|-----------------------------|----------------------------------------------------------------------------
| out_vec[0].base = &err; out_vec[0].len = sizeof(err); | `psa_ps_status_t err` defined in the caller space
| out_vec[1].base = p_info; out_vec[1].len = sizeof(*p_info); | `struct psa_ps_info_t *p_info`
=== tfm_sst_remove_req() ===
This function handles the PSA PS remove requests.
```
psa_status_t tfm_sst_remove_req(struct psa_invec *in_vec, size_t in_len,
struct psa_outvec *out_vec, size_t out_len);
```
**Parameters**
| Direction | Type | Name | Description
|------------|-------|--------|--------------
| in | struct psa_invec * | in_vec | Pointer to the input vector which contains the input parameters.
| in | size_t | in_len | Number of input parameters in the input vector.
| out | struct psa_invec * | out_vec | Pointer to the output vector which contains the output parameters.
| in | size_t | out_len | Number of output parameters in the output vector.
**Return**
A status indicating the success/failure of the operation as specified in psa_status_t.
| Type | Description
|-------|--------------
| PSA_SUCCESS | The operation completed successfully.
| PSA_CONNECTION_REFUSED | The operation is refused because the number of input or output parameters in the vectors are incorrect or their types are incorrect.
The following table shows the input parameters mapping in the in_vec vector.
| PSA IN_VEC Element | SST PS Layer Remove Function Input Parameter Name
|--------------------------|----------------------------------------------------------------
| in_vec[0].base = &uid; in_vec[0].len = sizeof(uid); | `psa_ps_uid_t uid`
The following table shows the input parameters mapping in the out_vec vector.
| PSA OUT_VEC Element | SST PS Layer Remove Function Output/Return Parameter Name
|-----------------------------|---------------------------------------------------------------------------
| out_vec[0].base = &err; out_vec[0].len = sizeof(err); | `psa_ps_status_t err` defined in the caller space
=== tfm_sst_get_support_req() ===
This function handles the PSA PS get support requests.
```
psa_status_t tfm_sst_get_support_req(struct psa_invec *in_vec, size_t in_len,
struct psa_outvec *out_vec, size_t out_len);
```
**Parameters**
| Direction | Type | Name | Description
|------------|-------|--------|--------------
| in | struct psa_invec * | in_vec | Pointer to the input vector which contains the input parameters.
| in | size_t | in_len | Number of input parameters in the input vector.
| out | struct psa_invec * | out_vec | Pointer to the output vector which contains the output parameters.
| in | size_t | out_len | Number of output parameters in the output vector.
**Return**
A status indicating the success/failure of the operation as specified in psa_status_t.
| Type | Description
|-------|-------------
| PSA_SUCCESS | The operation completed successfully.
| PSA_CONNECTION_REFUSED | The operation is refused because the number of input or output parameters in the vectors are incorrect or their types are incorrect.
The following table shows the input parameters mapping in the in_vec vector.
| PSA IN_VEC Element | SST PS Layer Get Support Function Input Parameter Name
|--------------------------|--------------------------------------------------------------------
| NONE | NONE
The following table shows the input parameters mapping in the out_vec vector.
| PSA OUT_VEC Element | SST PS Layer Get Support Function Output/Return Parameter Name
|-----------------------------|-------------------------------------------------------------------------------
| out_vec[0].base = &support_flags; out_vec[0].len = sizeof(support_flags); | `uint32_t support_flags`
== SST Manifest file ==
The SST manifest file must be updated to expose the SST request manager functions rather than the Protected Storage layer. However, the “tfm_init_symbol” entry needs to be tfm_sst_init as this is the function which initializes the service.
The “source_file” list must be updated to add the new SST request manager files.
== TF-M error codes ==
The legacy TF-M framework, used by the current SST implementation, limits the range of valid return values that a secure service can provide, reserving a range for framework error codes. For that reason, the TF-M SST codes need to be different from the PSA PS ones. The uniform secure service feature in TF-M framework does not have this requirement anymore, so the current TF-M SST error codes must be replaced by the PSA PS ones [ [[https://github.com/ARM-software/psa-arch-tests/blob/master/api-specs/include/psa/protected_storage.h | 4]] ].
== PSA PS APIs non-secure and secure implementation ==
The current implementation must be updated to evaluate psa_status_t return codes from TF-M framework. In case, TF-M framework returns a value different from PSA_SUCCESS, the interface should return a PSA_PS_ERROR_OPERATION_FAILED as a PSA PS error code. Otherwise, it should return the error code returned via out_vec.
Each PSA PS API implementation must map the input, output and return vales as defined in section "SST request Manager" per each request interface.
== Validation Tests ==
To validate the new design of SST service, the new version must pass all the SST test suites defined in TF-M and
PSA Arch tests [ [[https://github.com/ARM-software/psa-arch-tests/blob/master/api-specs/include/psa/protected_storage.h | 5]] ].
However, the psa_ps_ns_interface and psa_ps_s_interface test suites must be updated to modify the tests which check the validity of the callers memory referenced by a pointer. All the null pointer checks must be with data length equal to 0. The new TF-M framework incorporates a mechanism to check the validity of the memory area referred by the pointers plus data length [ [[https://developer.trustedfirmware.org/w/tf_m/design/uniform_secure_service_signature | 1]] ]. If secure partition requests a service with an invalid pointer with a data length different from 0, in one or more parameters, the TF-M frameworks returns a specific error code to reject the request. In the other hand, if a non-secure application requests a service with a null pointer with a data length different from 0, in one or more parameters, the TF-M framework blocks the request and it does not return the control to the non-secure application.