Skip to content

Commit c9a59dd

Browse files
tomi-fontcarlescufi
authored andcommitted
samples: psa: persistent_key: add the persistent_key sample
Add a sample to demonstrate use of persistent keys in the PSA Crypto API. The implementation of the PSA ITS API that allows storage of persistent keys is provided either by the just-introduced secure storage subsystem or by TF-M. Signed-off-by: Tomi Fontanilles <[email protected]>
1 parent d6bee54 commit c9a59dd

File tree

8 files changed

+258
-0
lines changed

8 files changed

+258
-0
lines changed
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# SPDX-License-Identifier: Apache-2.0
2+
cmake_minimum_required(VERSION 3.20.0)
3+
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
4+
5+
project(persistent_key)
6+
7+
target_sources(app PRIVATE src/main.c)

samples/psa/persistent_key/README.rst

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
.. zephyr:code-sample:: persistent_key
2+
:name: PSA Crypto persistent key
3+
4+
Manage and use persistent keys via the PSA Crypto API.
5+
6+
Overview
7+
********
8+
9+
This sample demonstrates usage of persistent keys in the :ref:`PSA Crypto API <psa_crypto>`.
10+
11+
Requirements
12+
************
13+
14+
In addition to the PSA Crypto API, an implementation of the
15+
`PSA Internal Trusted Storage (ITS) API <https://arm-software.github.io/psa-api/storage/1.0/overview/architecture.html#the-internal-trusted-storage-api>`_
16+
(for storage of the persistent keys) must be present for this sample to work.
17+
It can be provided by:
18+
19+
* :ref:`tfm`, for ``*/ns`` :term:`board targets<board target>`.
20+
* The :ref:`secure storage subsystem <secure_storage>`, for the other board targets.
21+
22+
Building
23+
********
24+
25+
This sample is located in :zephyr_file:`samples/psa/persistent_key`.
26+
27+
Different configurations are defined in the :file:`sample.yaml` file.
28+
You can use them to build the sample, depending on the PSA ITS provider, as follows:
29+
30+
.. tabs::
31+
32+
.. tab:: TF-M
33+
34+
For board targets with TF-M:
35+
36+
.. zephyr-app-commands::
37+
:zephyr-app: samples/psa/persistent_key
38+
:tool: west
39+
:goals: build
40+
:board: <ns_board_target>
41+
:west-args: -T sample.psa.persistent_key.tfm
42+
43+
.. tab:: secure storage subsystem
44+
45+
For board targets without TF-M.
46+
47+
If the board target to compile for has an entropy driver (preferable):
48+
49+
.. zephyr-app-commands::
50+
:zephyr-app: samples/psa/persistent_key
51+
:tool: west
52+
:goals: build
53+
:board: <board_target>
54+
:west-args: -T sample.psa.persistent_key.secure_storage.entropy_driver
55+
56+
Or, to use an insecure entropy source (only for testing):
57+
58+
.. zephyr-app-commands::
59+
:zephyr-app: samples/psa/persistent_key
60+
:tool: west
61+
:goals: build
62+
:board: <board_target>
63+
:west-args: -T sample.psa.persistent_key.secure_storage.entropy_not_secure
64+
65+
To flash it, see :ref:`west-flashing`.
66+
67+
API reference
68+
*************
69+
70+
`PSA Crypto key management API reference <https://arm-software.github.io/psa-api/crypto/1.2/api/keys/index.html>`_
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# SPDX-License-Identifier: Apache-2.0
2+
3+
CONFIG_ENTROPY_GENERATOR=y
4+
CONFIG_MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG=y
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# SPDX-License-Identifier: Apache-2.0
2+
3+
CONFIG_TEST_RANDOM_GENERATOR=y
4+
CONFIG_TIMER_RANDOM_GENERATOR=y
5+
CONFIG_MBEDTLS_ENTROPY_POLL_ZEPHYR=y
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# SPDX-License-Identifier: Apache-2.0
2+
3+
CONFIG_MBEDTLS=y
4+
CONFIG_MBEDTLS_PSA_CRYPTO_C=y
5+
6+
# The default stack size (1024) is not enough for the PSA Crypto core.
7+
# On top of that, the ITS implementation uses the stack for buffers.
8+
CONFIG_MAIN_STACK_SIZE=3072
9+
10+
CONFIG_SECURE_STORAGE=y

samples/psa/persistent_key/prj.conf

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# SPDX-License-Identifier: Apache-2.0
2+
3+
CONFIG_LOG=y
4+
CONFIG_LOG_DEFAULT_LEVEL=3
5+
CONFIG_ASSERT=y
6+
7+
CONFIG_PSA_WANT_KEY_TYPE_AES=y
8+
CONFIG_PSA_WANT_ALG_CTR=y
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
sample:
2+
name: PSA Crypto persistent key sample
3+
description: Demonstration of persistent key usage in the PSA Crypto API.
4+
common:
5+
tags:
6+
- psa.secure_storage
7+
timeout: 10
8+
harness: console
9+
harness_config:
10+
type: one_line
11+
regex:
12+
- "Sample finished successfully."
13+
tests:
14+
sample.psa.persistent_key.tfm:
15+
filter: CONFIG_BUILD_WITH_TFM
16+
tags:
17+
- trusted-firmware-m
18+
sample.psa.persistent_key.secure_storage.entropy_driver:
19+
filter: CONFIG_SECURE_STORAGE and not CONFIG_SECURE_STORAGE_ITS_STORE_IMPLEMENTATION_NONE
20+
and CONFIG_ENTROPY_HAS_DRIVER
21+
extra_args: EXTRA_CONF_FILE=overlay-secure_storage.conf;overlay-entropy_driver.conf
22+
tags:
23+
- drivers.entropy
24+
- settings
25+
sample.psa.persistent_key.secure_storage.entropy_not_secure:
26+
filter: CONFIG_SECURE_STORAGE and not CONFIG_SECURE_STORAGE_ITS_STORE_IMPLEMENTATION_NONE
27+
and not CONFIG_ENTROPY_HAS_DRIVER
28+
extra_args: EXTRA_CONF_FILE="overlay-secure_storage.conf;overlay-entropy_not_secure.conf"
29+
tags:
30+
- random
31+
- settings

samples/psa/persistent_key/src/main.c

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
/* Copyright (c) 2024 Nordic Semiconductor
2+
* SPDX-License-Identifier: Apache-2.0
3+
*/
4+
#include <psa/crypto.h>
5+
#include <zephyr/logging/log.h>
6+
7+
LOG_MODULE_REGISTER(persistent_key);
8+
9+
#define SAMPLE_KEY_ID PSA_KEY_ID_USER_MIN
10+
#define SAMPLE_KEY_TYPE PSA_KEY_TYPE_AES
11+
#define SAMPLE_ALG PSA_ALG_CTR
12+
#define SAMPLE_KEY_BITS 256
13+
14+
int generate_persistent_key(void)
15+
{
16+
LOG_INF("Generating a persistent key...");
17+
psa_status_t ret;
18+
psa_key_id_t key_id;
19+
psa_key_attributes_t key_attributes = PSA_KEY_ATTRIBUTES_INIT;
20+
21+
psa_set_key_lifetime(&key_attributes, PSA_KEY_LIFETIME_PERSISTENT);
22+
psa_set_key_usage_flags(&key_attributes, PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT);
23+
psa_set_key_id(&key_attributes, SAMPLE_KEY_ID);
24+
psa_set_key_type(&key_attributes, SAMPLE_KEY_TYPE);
25+
psa_set_key_algorithm(&key_attributes, SAMPLE_ALG);
26+
psa_set_key_bits(&key_attributes, SAMPLE_KEY_BITS);
27+
28+
ret = psa_generate_key(&key_attributes, &key_id);
29+
if (ret != PSA_SUCCESS) {
30+
LOG_ERR("Failed to generate the key. (%d)", ret);
31+
return -1;
32+
}
33+
__ASSERT_NO_MSG(key_id == SAMPLE_KEY_ID);
34+
35+
/* Purge the key from volatile memory. Has the same affect than resetting the device. */
36+
ret = psa_purge_key(SAMPLE_KEY_ID);
37+
if (ret != PSA_SUCCESS) {
38+
LOG_ERR("Failed to purge the generated key from volatile memory. (%d).", ret);
39+
return -1;
40+
}
41+
42+
LOG_INF("Persistent key generated.");
43+
return 0;
44+
}
45+
46+
int use_persistent_key(void)
47+
{
48+
LOG_INF("Using the persistent key to encrypt and decrypt some plaintext...");
49+
psa_status_t ret;
50+
size_t ciphertext_len;
51+
size_t decrypted_text_len;
52+
53+
static uint8_t plaintext[] =
54+
"Example plaintext to demonstrate basic usage of a persistent key.";
55+
static uint8_t ciphertext[PSA_CIPHER_ENCRYPT_OUTPUT_SIZE(SAMPLE_KEY_TYPE, SAMPLE_ALG,
56+
sizeof(plaintext))];
57+
static uint8_t decrypted_text[sizeof(plaintext)];
58+
59+
ret = psa_cipher_encrypt(SAMPLE_KEY_ID, SAMPLE_ALG, plaintext, sizeof(plaintext),
60+
ciphertext, sizeof(ciphertext), &ciphertext_len);
61+
if (ret != PSA_SUCCESS) {
62+
LOG_ERR("Failed to encrypt the plaintext. (%d)", ret);
63+
return -1;
64+
}
65+
66+
ret = psa_cipher_decrypt(SAMPLE_KEY_ID, SAMPLE_ALG, ciphertext, ciphertext_len,
67+
decrypted_text, sizeof(decrypted_text), &decrypted_text_len);
68+
if (ret != PSA_SUCCESS) {
69+
LOG_ERR("Failed to decrypt the ciphertext. (%d)", ret);
70+
return -1;
71+
}
72+
__ASSERT_NO_MSG(decrypted_text_len == sizeof(plaintext));
73+
74+
/* Make sure the decryption gives us the original plaintext back. */
75+
if (memcmp(plaintext, decrypted_text, sizeof(plaintext))) {
76+
LOG_HEXDUMP_INF(plaintext, sizeof(plaintext), "Plaintext:");
77+
LOG_HEXDUMP_INF(ciphertext, ciphertext_len, "Ciphertext:");
78+
LOG_HEXDUMP_INF(decrypted_text, sizeof(decrypted_text), "Decrypted text:");
79+
LOG_ERR("The decrypted text doesn't match the plaintext.");
80+
return -1;
81+
}
82+
83+
LOG_INF("Persistent key usage successful.");
84+
return 0;
85+
}
86+
87+
static int destroy_persistent_key(void)
88+
{
89+
LOG_INF("Destroying the persistent key...");
90+
psa_status_t ret;
91+
92+
ret = psa_destroy_key(SAMPLE_KEY_ID);
93+
if (ret != PSA_SUCCESS) {
94+
LOG_ERR("Failed to destroy the key. (%d)", ret);
95+
return -1;
96+
}
97+
98+
LOG_INF("Persistent key destroyed.");
99+
return 0;
100+
}
101+
102+
int main(void)
103+
{
104+
LOG_INF("Persistent key sample started.");
105+
106+
/* Ensure there is not already a key with this ID. */
107+
psa_destroy_key(SAMPLE_KEY_ID);
108+
109+
if (generate_persistent_key()) {
110+
return -1;
111+
}
112+
113+
if (use_persistent_key()) {
114+
return -1;
115+
}
116+
117+
if (destroy_persistent_key()) {
118+
return -1;
119+
}
120+
121+
LOG_INF("Sample finished successfully.");
122+
return 0;
123+
}

0 commit comments

Comments
 (0)