samples: tfm: Add PSA Protected Storage sample
Add sample showing PSA Protected Storage API usage Signed-off-by: Andreas Vibeto <andreas.vibeto@nordicsemi.no>
This commit is contained in:
parent
9143f4fd8c
commit
75dccbbbc7
|
@ -0,0 +1,18 @@
|
|||
#
|
||||
# Copyright (c) 2021 Nordic Semiconductor ASA
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
# Building TFM requires Cmake 3.15.
|
||||
cmake_minimum_required(VERSION 3.15)
|
||||
|
||||
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
|
||||
|
||||
project(protected_storage)
|
||||
|
||||
target_sources(app PRIVATE src/main.c)
|
||||
|
||||
target_include_directories(app PRIVATE
|
||||
${ZEPHYR_TRUSTED_FIRMWARE_M_MODULE_DIR}/trusted-firmware-m/interface/include
|
||||
)
|
|
@ -0,0 +1,71 @@
|
|||
.. psa_protected_storage:
|
||||
|
||||
PSA Protected Storage
|
||||
#####################
|
||||
|
||||
Overview
|
||||
********
|
||||
|
||||
This sample demonstrates how the Protected Storage (PS) API can be used for storing data.
|
||||
|
||||
Protected storage provides a key/value storage interface where data is (by default) encrypted, with
|
||||
optional authentication and rollback protection. The default crypto algorithm is ``AES-128-GCM``.
|
||||
The encryption key is derived from the Hardware Unique Key (HUK), which is often set via device
|
||||
fuses, etc.
|
||||
|
||||
Using the PS API, this sample stores data to non-volatile storage. The sample shows how data can
|
||||
be stored to and read from UIDs, and how overwrite protection can be enabled using flags.
|
||||
|
||||
TF-M includes a maximum number of PS records, set via ``PS_NUM_ASSETS`` (default 10 as of
|
||||
TF-M 1.3), and a maximum record size, set via ``PS_MAX_ASSET_SIZE`` (default of 2048 as of
|
||||
TF-M 1.3.0). These defaults may be different depending on the platform being used, the current
|
||||
value will be printed by the build system during the TF-M compilation step.
|
||||
|
||||
More information about Protected Storage can be found in the Platform Security Architecture (PSA)
|
||||
Secure Storage API: https://developer.arm.com/architectures/architecture-security-features/platform-security
|
||||
|
||||
This sample is available for platforms that are supported in the trusted-firmware-m repo:
|
||||
https://git.trustedfirmware.org/TF-M/trusted-firmware-m.git/
|
||||
See sample.yaml for a list of supported platforms.
|
||||
|
||||
Building and Running
|
||||
********************
|
||||
|
||||
On Target
|
||||
=========
|
||||
|
||||
Refer to :ref:`tfm_psa_level_1` for detailed instructions.
|
||||
|
||||
Note that the board needs to be completely erased before programming the sample, as the flash area
|
||||
used might contain data from before. The board must also be erased between each time the sample is
|
||||
run as the overwrite protection will not be removed with a power reset.
|
||||
|
||||
On QEMU
|
||||
========
|
||||
|
||||
Refer to :ref:`tfm_ipc` for detailed instructions.
|
||||
Following is an example based on ``west build``
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ west build samples/tfm_integration/psa_protected_storage/ -p -b mps2_an521_nonsecure -t run
|
||||
|
||||
Sample Output
|
||||
=============
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
*** Booting Zephyr OS build zephyr-v2.5.0-2791-g5585355dde0c ***
|
||||
TF-M Protected Storage sample started. PSA Protected Storage API Version 1.0
|
||||
Writing data to UID1: The quick brown fox jumps over the lazy dog
|
||||
Info on data stored in UID1:
|
||||
- Size: 16
|
||||
- Capacity: 0x42
|
||||
- Flags: 0x 0
|
||||
Read and compare data stored in UID1
|
||||
Data stored in UID1: The quick brown fox jumps over the lazy dog
|
||||
Overwriting data stored in UID1 with: Lorem ipsum dolor sit amet
|
||||
Writing data to UID2 with overwrite protection: The quick brown fox jumps over the lazy dog
|
||||
Attempting to write 'The quick brown fox jumps over the lazy dog' to UID2
|
||||
Got expected error (PSA_ERROR_NOT_PERMITTED) when writing to protected UID
|
||||
Removing UID1
|
|
@ -0,0 +1,7 @@
|
|||
#
|
||||
# Copyright (c) 2021 Nordic Semiconductor ASA
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
CONFIG_BUILD_WITH_TFM=y
|
|
@ -0,0 +1,25 @@
|
|||
sample:
|
||||
description: Protected Storage API sample
|
||||
name: PSA Protected Storage
|
||||
common:
|
||||
tags: psa
|
||||
platform_allow: mps2_an521_nonsecure v2m_musca_s1_nonsecure
|
||||
nrf5340dk_nrf5340_cpuappns nrf9160dk_nrf9160ns bl5340_dvk_cpuappns
|
||||
harness: console
|
||||
harness_config:
|
||||
type: multi_line
|
||||
regex:
|
||||
- "Protected Storage sample started"
|
||||
- "PSA Protected Storage API Version [0-9]*.[0-9]*"
|
||||
- "Writing data to UID1: .*"
|
||||
- "Info on data stored in UID1:"
|
||||
- "- Size: [0-9]*"
|
||||
- "- Capacity: 0x[0-9a-f]*"
|
||||
- "- Flags: 0x[0-9-a-f]*"
|
||||
- "Got expected error \\(PSA_ERROR_NOT_PERMITTED\\) when writing to protected UID"
|
||||
- "Removing UID1"
|
||||
|
||||
tests:
|
||||
sample.tfm.protected_storage:
|
||||
extra_args: "CONFIG_TEST=y"
|
||||
tags: tfm ci_build
|
|
@ -0,0 +1,89 @@
|
|||
/*
|
||||
* Copyright (c) 2021 Nordic Semiconductor ASA.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <zephyr.h>
|
||||
#include <string.h>
|
||||
#include <sys/printk.h>
|
||||
#include <psa/storage_common.h>
|
||||
#include <psa/protected_storage.h>
|
||||
|
||||
#define TEST_STRING_1 "The quick brown fox jumps over the lazy dog"
|
||||
#define TEST_STRING_2 "Lorem ipsum dolor sit amet"
|
||||
|
||||
void main(void)
|
||||
{
|
||||
psa_status_t status = 0;
|
||||
|
||||
printk("Protected Storage sample started.\n");
|
||||
printk("PSA Protected Storage API Version %d.%d\n",
|
||||
PSA_PS_API_VERSION_MAJOR, PSA_PS_API_VERSION_MINOR);
|
||||
|
||||
printk("Writing data to UID1: %s\n", TEST_STRING_1);
|
||||
psa_storage_uid_t uid1 = 1;
|
||||
psa_storage_create_flags_t uid1_flag = PSA_STORAGE_FLAG_NONE;
|
||||
|
||||
status = psa_ps_set(uid1, sizeof(TEST_STRING_1), TEST_STRING_1, uid1_flag);
|
||||
if (status != PSA_SUCCESS) {
|
||||
printk("Failed to store data! (%d)\n", status);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Get info on UID1 */
|
||||
struct psa_storage_info_t uid1_info;
|
||||
|
||||
status = psa_ps_get_info(uid1, &uid1_info);
|
||||
if (status != PSA_SUCCESS) {
|
||||
printk("Failed to get info! (%d)\n", status);
|
||||
return;
|
||||
}
|
||||
printk("Info on data stored in UID1:\n");
|
||||
printk("- Size: %d\n", uid1_info.size);
|
||||
printk("- Capacity: 0x%2x\n", uid1_info.capacity);
|
||||
printk("- Flags: 0x%2x\n", uid1_info.flags);
|
||||
|
||||
printk("Read and compare data stored in UID1\n");
|
||||
size_t bytes_read;
|
||||
char stored_data[sizeof(TEST_STRING_1)];
|
||||
|
||||
status = psa_ps_get(uid1, 0, sizeof(TEST_STRING_1), &stored_data, &bytes_read);
|
||||
if (status != PSA_SUCCESS) {
|
||||
printk("Failed to get data stored in UID1! (%d)\n", status);
|
||||
return;
|
||||
}
|
||||
printk("Data stored in UID1: %s\n", stored_data);
|
||||
|
||||
printk("Overwriting data stored in UID1: %s\n", TEST_STRING_2);
|
||||
status = psa_ps_set(uid1, sizeof(TEST_STRING_2), TEST_STRING_2, uid1_flag);
|
||||
if (status != PSA_SUCCESS) {
|
||||
printk("Failed to overwrite UID1! (%d)\n", status);
|
||||
return;
|
||||
}
|
||||
|
||||
printk("Writing data to UID2 with overwrite protection: %s\n", TEST_STRING_1);
|
||||
psa_storage_uid_t uid2 = 2;
|
||||
psa_storage_create_flags_t uid2_flag = PSA_STORAGE_FLAG_WRITE_ONCE;
|
||||
|
||||
status = psa_ps_set(uid2, sizeof(TEST_STRING_1), TEST_STRING_1, uid2_flag);
|
||||
if (status != PSA_SUCCESS) {
|
||||
printk("Failed to set write once flag! (%d)\n", status);
|
||||
return;
|
||||
}
|
||||
|
||||
printk("Attempting to write '%s' to UID2\n", TEST_STRING_2);
|
||||
status = psa_ps_set(uid2, sizeof(TEST_STRING_2), TEST_STRING_2, uid2_flag);
|
||||
if (status != PSA_ERROR_NOT_PERMITTED) {
|
||||
printk("Got unexpected status when overwriting! (%d)\n", status);
|
||||
return;
|
||||
}
|
||||
printk("Got expected error (PSA_ERROR_NOT_PERMITTED) when writing to protected UID\n");
|
||||
|
||||
printk("Removing UID1\n");
|
||||
status = psa_ps_remove(uid1);
|
||||
if (status != PSA_SUCCESS) {
|
||||
printk("Failed to remove UID1! (%d)\n", status);
|
||||
return;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue