From d6bee54986a2ee908d4699d91c5f71e6f635011e Mon Sep 17 00:00:00 2001 From: Tomi Fontanilles Date: Fri, 13 Sep 2024 09:29:01 +0300 Subject: [PATCH] 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 --- MAINTAINERS.yml | 1 + samples/psa/index.rst | 6 + samples/psa/its/CMakeLists.txt | 7 + samples/psa/its/README.rst | 67 +++++++++ samples/psa/its/overlay-entropy_driver.conf | 4 + .../psa/its/overlay-entropy_not_secure.conf | 5 + samples/psa/its/overlay-secure_storage.conf | 10 ++ samples/psa/its/prj.conf | 4 + samples/psa/its/sample.yaml | 31 +++++ samples/psa/its/src/main.c | 128 ++++++++++++++++++ 10 files changed, 263 insertions(+) create mode 100644 samples/psa/index.rst create mode 100644 samples/psa/its/CMakeLists.txt create mode 100644 samples/psa/its/README.rst create mode 100644 samples/psa/its/overlay-entropy_driver.conf create mode 100644 samples/psa/its/overlay-entropy_not_secure.conf create mode 100644 samples/psa/its/overlay-secure_storage.conf create mode 100644 samples/psa/its/prj.conf create mode 100644 samples/psa/its/sample.yaml create mode 100644 samples/psa/its/src/main.c diff --git a/MAINTAINERS.yml b/MAINTAINERS.yml index 41b34476174..422d849ea79 100644 --- a/MAINTAINERS.yml +++ b/MAINTAINERS.yml @@ -4113,6 +4113,7 @@ Secure storage: - tomi-font files: - subsys/secure_storage/ + - samples/psa/ - tests/subsys/secure_storage/ labels: - "area: Secure storage" diff --git a/samples/psa/index.rst b/samples/psa/index.rst new file mode 100644 index 00000000000..fd5f3386eb3 --- /dev/null +++ b/samples/psa/index.rst @@ -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 `_. diff --git a/samples/psa/its/CMakeLists.txt b/samples/psa/its/CMakeLists.txt new file mode 100644 index 00000000000..fbac539c4f0 --- /dev/null +++ b/samples/psa/its/CMakeLists.txt @@ -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) diff --git a/samples/psa/its/README.rst b/samples/psa/its/README.rst new file mode 100644 index 00000000000..94bff4f47d9 --- /dev/null +++ b/samples/psa/its/README.rst @@ -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 `_, +which is part of the `PSA Secure Storage API `_, +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`. +* The :ref:`secure storage subsystem `, 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: + :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: + :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: + :west-args: -T sample.psa.its.secure_storage.entropy_not_secure + +To flash it, see :ref:`west-flashing`. diff --git a/samples/psa/its/overlay-entropy_driver.conf b/samples/psa/its/overlay-entropy_driver.conf new file mode 100644 index 00000000000..b2fea61e044 --- /dev/null +++ b/samples/psa/its/overlay-entropy_driver.conf @@ -0,0 +1,4 @@ +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_ENTROPY_GENERATOR=y +CONFIG_MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG=y diff --git a/samples/psa/its/overlay-entropy_not_secure.conf b/samples/psa/its/overlay-entropy_not_secure.conf new file mode 100644 index 00000000000..2aba3a2c7e2 --- /dev/null +++ b/samples/psa/its/overlay-entropy_not_secure.conf @@ -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 diff --git a/samples/psa/its/overlay-secure_storage.conf b/samples/psa/its/overlay-secure_storage.conf new file mode 100644 index 00000000000..3473ae38910 --- /dev/null +++ b/samples/psa/its/overlay-secure_storage.conf @@ -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 diff --git a/samples/psa/its/prj.conf b/samples/psa/its/prj.conf new file mode 100644 index 00000000000..4c214a79a52 --- /dev/null +++ b/samples/psa/its/prj.conf @@ -0,0 +1,4 @@ +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_LOG=y +CONFIG_LOG_DEFAULT_LEVEL=3 diff --git a/samples/psa/its/sample.yaml b/samples/psa/its/sample.yaml new file mode 100644 index 00000000000..c4ee3543696 --- /dev/null +++ b/samples/psa/its/sample.yaml @@ -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 diff --git a/samples/psa/its/src/main.c b/samples/psa/its/src/main.c new file mode 100644 index 00000000000..47752f05658 --- /dev/null +++ b/samples/psa/its/src/main.c @@ -0,0 +1,128 @@ +/* Copyright (c) 2024 Nordic Semiconductor + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include + +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; +}