samples: psa: its: add the psa_its sample
Add a sample to demonstrate direct use of the PSA ITS API. The implementation of the API is provided either by the just-introduced secure storage subsystem or by TF-M. Signed-off-by: Tomi Fontanilles <tomi.fontanilles@nordicsemi.no>
This commit is contained in:
parent
85a56b5ee3
commit
d6bee54986
10 changed files with 263 additions and 0 deletions
|
|
@ -4113,6 +4113,7 @@ Secure storage:
|
|||
- tomi-font
|
||||
files:
|
||||
- subsys/secure_storage/
|
||||
- samples/psa/
|
||||
- tests/subsys/secure_storage/
|
||||
labels:
|
||||
- "area: Secure storage"
|
||||
|
|
|
|||
6
samples/psa/index.rst
Normal file
6
samples/psa/index.rst
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
.. zephyr:code-sample-category:: psa
|
||||
:name: PSA
|
||||
:show-listing:
|
||||
|
||||
The following samples demonstrate various uses of several of the
|
||||
`Platform Security Architecture (PSA) Certified APIs <https://arm-software.github.io/psa-api/>`_.
|
||||
7
samples/psa/its/CMakeLists.txt
Normal file
7
samples/psa/its/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
# SPDX-License-Identifier: Apache-2.0
|
||||
cmake_minimum_required(VERSION 3.20.0)
|
||||
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
|
||||
|
||||
project(psa_its)
|
||||
|
||||
target_sources(app PRIVATE src/main.c)
|
||||
67
samples/psa/its/README.rst
Normal file
67
samples/psa/its/README.rst
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
.. zephyr:code-sample:: psa_its
|
||||
:name: PSA Internal Trusted Storage API
|
||||
:relevant-api: psa_secure_storage
|
||||
|
||||
Use the PSA ITS API.
|
||||
|
||||
Overview
|
||||
********
|
||||
|
||||
This sample demonstrates usage of the
|
||||
`PSA Internal Trusted Storage (ITS) API <https://arm-software.github.io/psa-api/storage/1.0/overview/architecture.html#the-internal-trusted-storage-api>`_,
|
||||
which is part of the `PSA Secure Storage API <https://arm-software.github.io/psa-api/storage/>`_,
|
||||
for storing and retrieving persistent data.
|
||||
|
||||
Requirements
|
||||
************
|
||||
|
||||
An implementation of the PSA ITS API must be present for this sample to build.
|
||||
It can be provided by:
|
||||
|
||||
* :ref:`tfm`, for ``*/ns`` :term:`board targets<board target>`.
|
||||
* The :ref:`secure storage subsystem <secure_storage>`, for the other board targets.
|
||||
|
||||
Building
|
||||
********
|
||||
|
||||
This sample is located in :zephyr_file:`samples/psa/its`.
|
||||
|
||||
Different configurations are defined in the :file:`sample.yaml` file.
|
||||
You can use them to build the sample, depending on the PSA ITS provider, as follows:
|
||||
|
||||
.. tabs::
|
||||
|
||||
.. tab:: TF-M
|
||||
|
||||
For board targets with TF-M:
|
||||
|
||||
.. zephyr-app-commands::
|
||||
:zephyr-app: samples/psa/its
|
||||
:tool: west
|
||||
:goals: build
|
||||
:board: <ns_board_target>
|
||||
:west-args: -T sample.psa.its.tfm
|
||||
|
||||
.. tab:: secure storage subsystem
|
||||
|
||||
For board targets without TF-M.
|
||||
|
||||
If the board target to compile for has an entropy driver (preferable):
|
||||
|
||||
.. zephyr-app-commands::
|
||||
:zephyr-app: samples/psa/its
|
||||
:tool: west
|
||||
:goals: build
|
||||
:board: <board_target>
|
||||
:west-args: -T sample.psa.its.secure_storage.entropy_driver
|
||||
|
||||
Or, to use an insecure entropy source (only for testing):
|
||||
|
||||
.. zephyr-app-commands::
|
||||
:zephyr-app: samples/psa/its
|
||||
:tool: west
|
||||
:goals: build
|
||||
:board: <board_target>
|
||||
:west-args: -T sample.psa.its.secure_storage.entropy_not_secure
|
||||
|
||||
To flash it, see :ref:`west-flashing`.
|
||||
4
samples/psa/its/overlay-entropy_driver.conf
Normal file
4
samples/psa/its/overlay-entropy_driver.conf
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
CONFIG_ENTROPY_GENERATOR=y
|
||||
CONFIG_MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG=y
|
||||
5
samples/psa/its/overlay-entropy_not_secure.conf
Normal file
5
samples/psa/its/overlay-entropy_not_secure.conf
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
CONFIG_TEST_RANDOM_GENERATOR=y
|
||||
CONFIG_TIMER_RANDOM_GENERATOR=y
|
||||
CONFIG_MBEDTLS_ENTROPY_POLL_ZEPHYR=y
|
||||
10
samples/psa/its/overlay-secure_storage.conf
Normal file
10
samples/psa/its/overlay-secure_storage.conf
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
CONFIG_MBEDTLS=y
|
||||
CONFIG_MBEDTLS_PSA_CRYPTO_C=y
|
||||
|
||||
# The default stack size (1024) is not enough for the PSA Crypto core.
|
||||
# On top of that, the ITS implementation uses the stack for buffers.
|
||||
CONFIG_MAIN_STACK_SIZE=3072
|
||||
|
||||
CONFIG_SECURE_STORAGE=y
|
||||
4
samples/psa/its/prj.conf
Normal file
4
samples/psa/its/prj.conf
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
CONFIG_LOG=y
|
||||
CONFIG_LOG_DEFAULT_LEVEL=3
|
||||
31
samples/psa/its/sample.yaml
Normal file
31
samples/psa/its/sample.yaml
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
sample:
|
||||
name: PSA ITS API sample
|
||||
description: Demonstration of PSA Internal Trusted Storage (ITS) API usage.
|
||||
common:
|
||||
tags:
|
||||
- psa.secure_storage
|
||||
timeout: 10
|
||||
harness: console
|
||||
harness_config:
|
||||
type: one_line
|
||||
regex:
|
||||
- "Sample finished successfully."
|
||||
tests:
|
||||
sample.psa.its.tfm:
|
||||
filter: CONFIG_BUILD_WITH_TFM
|
||||
tags:
|
||||
- trusted-firmware-m
|
||||
sample.psa.its.secure_storage.entropy_driver:
|
||||
filter: CONFIG_SECURE_STORAGE and not CONFIG_SECURE_STORAGE_ITS_STORE_IMPLEMENTATION_NONE
|
||||
and CONFIG_ENTROPY_HAS_DRIVER
|
||||
extra_args: EXTRA_CONF_FILE=overlay-secure_storage.conf;overlay-entropy_driver.conf
|
||||
tags:
|
||||
- drivers.entropy
|
||||
- settings
|
||||
sample.psa.its.secure_storage.entropy_not_secure:
|
||||
filter: CONFIG_SECURE_STORAGE and not CONFIG_SECURE_STORAGE_ITS_STORE_IMPLEMENTATION_NONE
|
||||
and not CONFIG_ENTROPY_HAS_DRIVER
|
||||
extra_args: EXTRA_CONF_FILE="overlay-secure_storage.conf;overlay-entropy_not_secure.conf"
|
||||
tags:
|
||||
- random
|
||||
- settings
|
||||
128
samples/psa/its/src/main.c
Normal file
128
samples/psa/its/src/main.c
Normal file
|
|
@ -0,0 +1,128 @@
|
|||
/* Copyright (c) 2024 Nordic Semiconductor
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include <psa/internal_trusted_storage.h>
|
||||
#include <zephyr/logging/log.h>
|
||||
|
||||
LOG_MODULE_REGISTER(psa_its);
|
||||
|
||||
#define SAMPLE_DATA_UID (psa_storage_uid_t)1
|
||||
#define SAMPLE_DATA_FLAGS PSA_STORAGE_FLAG_NONE
|
||||
|
||||
#ifdef CONFIG_SECURE_STORAGE
|
||||
#define SAMPLE_DATA_SIZE CONFIG_SECURE_STORAGE_ITS_MAX_DATA_SIZE
|
||||
#else
|
||||
#define SAMPLE_DATA_SIZE 128
|
||||
#endif
|
||||
|
||||
static int write_and_read_data(void)
|
||||
{
|
||||
LOG_INF("Writing to and reading back from ITS...");
|
||||
psa_status_t ret;
|
||||
|
||||
/* Data to be written to ITS. */
|
||||
uint8_t p_data_write[SAMPLE_DATA_SIZE];
|
||||
|
||||
for (unsigned int i = 0; i != sizeof(p_data_write); ++i) {
|
||||
p_data_write[i] = i;
|
||||
}
|
||||
|
||||
ret = psa_its_set(SAMPLE_DATA_UID, sizeof(p_data_write), p_data_write, SAMPLE_DATA_FLAGS);
|
||||
if (ret != PSA_SUCCESS) {
|
||||
LOG_ERR("Writing the data to ITS failed. (%d)", ret);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Data to be read from ITS. */
|
||||
uint8_t p_data_read[SAMPLE_DATA_SIZE];
|
||||
|
||||
/* Read back the data starting from an offset. */
|
||||
const size_t data_offset = SAMPLE_DATA_SIZE / 2;
|
||||
|
||||
/* Number of bytes read. */
|
||||
size_t p_data_length = 0;
|
||||
|
||||
ret = psa_its_get(SAMPLE_DATA_UID, data_offset, sizeof(p_data_read), p_data_read,
|
||||
&p_data_length);
|
||||
if (ret != PSA_SUCCESS) {
|
||||
LOG_ERR("Reading back the data from ITS failed. (%d).", ret);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (p_data_length != SAMPLE_DATA_SIZE - data_offset) {
|
||||
LOG_ERR("Unexpected amount of bytes read back. (%zu != %zu)",
|
||||
p_data_length, SAMPLE_DATA_SIZE - data_offset);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (memcmp(p_data_write + data_offset, p_data_read, p_data_length)) {
|
||||
LOG_HEXDUMP_INF(p_data_write + data_offset, p_data_length, "Data written:");
|
||||
LOG_HEXDUMP_INF(p_data_read, p_data_length, "Data read back:");
|
||||
LOG_ERR("The data read back doesn't match the data written.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
LOG_INF("Successfully wrote to ITS and read back what was written.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int read_info(void)
|
||||
{
|
||||
LOG_INF("Reading the written entry's metadata...");
|
||||
psa_status_t ret;
|
||||
|
||||
/* The entry's metadata. */
|
||||
struct psa_storage_info_t p_info;
|
||||
|
||||
ret = psa_its_get_info(SAMPLE_DATA_UID, &p_info);
|
||||
if (ret != PSA_SUCCESS) {
|
||||
LOG_ERR("Failed to retrieve the entry's metadata. (%d)", ret);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (p_info.capacity != SAMPLE_DATA_SIZE
|
||||
|| p_info.size != SAMPLE_DATA_SIZE
|
||||
|| p_info.flags != SAMPLE_DATA_FLAGS) {
|
||||
LOG_ERR("Entry metadata unexpected. (capacity:%zu size:%zu flags:0x%x)",
|
||||
p_info.capacity, p_info.size, p_info.flags);
|
||||
return -1;
|
||||
}
|
||||
|
||||
LOG_INF("Successfully read the entry's metadata.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int remove_entry(void)
|
||||
{
|
||||
LOG_INF("Removing the entry from ITS...");
|
||||
psa_status_t ret;
|
||||
|
||||
ret = psa_its_remove(SAMPLE_DATA_UID);
|
||||
if (ret != PSA_SUCCESS) {
|
||||
LOG_ERR("Failed to remove the entry. (%d)", ret);
|
||||
return -1;
|
||||
}
|
||||
|
||||
LOG_INF("Entry removed from ITS.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
LOG_INF("PSA ITS sample started.");
|
||||
|
||||
if (write_and_read_data()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (read_info()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (remove_entry()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
LOG_INF("Sample finished successfully.");
|
||||
return 0;
|
||||
}
|
||||
Loading…
Reference in a new issue