Skip to content

Commit

Permalink
tests: secure_storage: add tests for the secure storage subsystem
Browse files Browse the repository at this point in the history
Add one suite to test the PSA ITS API directly, and another to test it
through the PSA Crypto API.

The PSA ITS API test suite is run with different configurations to also
test customization possibilities that the secure storage subsystem offers.

Both test suites also have a test scenario with TF-M instead of the
secure storage subsystem.
This serves as compatibility testing to ensure that the PSA Secure
Storage API behaves the same from the user's point of view regardless
of the underlying implementation provider.

Signed-off-by: Tomi Fontanilles <tomi.fontanilles@nordicsemi.no>
  • Loading branch information
tomi-font authored and carlescufi committed Oct 7, 2024
1 parent 4b47901 commit 85a56b5
Show file tree
Hide file tree
Showing 18 changed files with 472 additions and 0 deletions.
6 changes: 6 additions & 0 deletions MAINTAINERS.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4113,8 +4113,12 @@ Secure storage:
- tomi-font
files:
- subsys/secure_storage/
- tests/subsys/secure_storage/
labels:
- "area: Secure storage"
tests:
- psa.secure_storage

Storage:
status: odd fixes
files:
Expand Down Expand Up @@ -4924,6 +4928,7 @@ West:
tests:
- benchmark.crypto.mbedtls
- crypto.mbedtls
- psa.secure_storage

"West project: mcuboot":
status: maintained
Expand Down Expand Up @@ -5096,6 +5101,7 @@ West:
- "area: TF-M"
tests:
- trusted-firmware-m
- psa.secure_storage

"West project: tf-m-tests":
status: maintained
Expand Down
5 changes: 5 additions & 0 deletions tests/subsys/secure_storage/psa/crypto/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
cmake_minimum_required(VERSION 3.20.0)
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
project(app)

target_sources(app PRIVATE src/main.c)
12 changes: 12 additions & 0 deletions tests/subsys/secure_storage/psa/crypto/overlay-secure_storage.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
CONFIG_ZTEST_STACK_SIZE=3072
CONFIG_MAIN_STACK_SIZE=2048

CONFIG_MBEDTLS=y
CONFIG_TEST_RANDOM_GENERATOR=y
CONFIG_TIMER_RANDOM_GENERATOR=y
CONFIG_MBEDTLS_ENTROPY_POLL_ZEPHYR=y
CONFIG_MBEDTLS_PSA_CRYPTO_C=y

CONFIG_SECURE_STORAGE=y
# For testing isolation between the different callers of the ITS.
CONFIG_SECURE_STORAGE_PS_IMPLEMENTATION_ITS=y
4 changes: 4 additions & 0 deletions tests/subsys/secure_storage/psa/crypto/prj.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
CONFIG_ZTEST=y

CONFIG_PSA_WANT_KEY_TYPE_AES=y
CONFIG_PSA_WANT_ALG_CBC_NO_PADDING=y
125 changes: 125 additions & 0 deletions tests/subsys/secure_storage/psa/crypto/src/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
/* Copyright (c) 2024 Nordic Semiconductor
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/ztest.h>
#include <psa/crypto.h>
#include <psa/internal_trusted_storage.h>
#include <psa/protected_storage.h>

ZTEST_SUITE(secure_storage_psa_crypto, NULL, NULL, NULL, NULL, NULL);

#define ID PSA_KEY_ID_USER_MIN
#define KEY_TYPE PSA_KEY_TYPE_AES
#define ALG PSA_ALG_CBC_NO_PADDING
#define KEY_BITS 256

static void fill_key_attributes(psa_key_attributes_t *key_attributes)
{
*key_attributes = psa_key_attributes_init();
psa_set_key_lifetime(key_attributes, PSA_KEY_LIFETIME_PERSISTENT);
psa_set_key_usage_flags(key_attributes, PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT);
psa_set_key_id(key_attributes, ID);
psa_set_key_type(key_attributes, KEY_TYPE);
psa_set_key_algorithm(key_attributes, ALG);
psa_set_key_bits(key_attributes, KEY_BITS);
}

static void fill_data(uint8_t *data, size_t size)
{
zassert_equal(psa_generate_random(data, size), PSA_SUCCESS);
}

ZTEST(secure_storage_psa_crypto, test_its_caller_isolation)
{
psa_status_t ret;
psa_key_attributes_t key_attributes;
psa_key_attributes_t retrieved_key_attributes;
psa_key_id_t key_id;
uint8_t data[32];
size_t data_length;
uint8_t its_data[sizeof(data)];
uint8_t ps_data[sizeof(data)];

fill_data(its_data, sizeof(its_data));
fill_data(ps_data, sizeof(ps_data));
zassert_true(memcmp(its_data, ps_data, sizeof(data)));
ret = psa_its_set(ID, sizeof(its_data), its_data, PSA_STORAGE_FLAG_NONE);
zassert_equal(ret, PSA_SUCCESS);
ret = psa_ps_set(ID, sizeof(ps_data), ps_data, PSA_STORAGE_FLAG_NONE);
zassert_equal(ret, PSA_SUCCESS);

fill_key_attributes(&key_attributes);
ret = psa_generate_key(&key_attributes, &key_id);
zassert_equal(ret, PSA_SUCCESS);
zassert_equal(key_id, ID);
ret = psa_purge_key(ID);
zassert_equal(ret, PSA_SUCCESS);

ret = psa_its_get(ID, 0, sizeof(data), data, &data_length);
zassert_equal(ret, PSA_SUCCESS);
zassert_equal(data_length, sizeof(data));
zassert_mem_equal(data, its_data, sizeof(data));
ret = psa_its_remove(ID);
zassert_equal(ret, PSA_SUCCESS);
ret = psa_its_remove(ID);
zassert_equal(ret, PSA_ERROR_DOES_NOT_EXIST);

ret = psa_ps_get(ID, 0, sizeof(data), data, &data_length);
zassert_equal(ret, PSA_SUCCESS);
zassert_equal(data_length, sizeof(data));
zassert_mem_equal(data, ps_data, sizeof(data));
ret = psa_ps_remove(ID);
zassert_equal(ret, PSA_SUCCESS);
ret = psa_ps_remove(ID);
zassert_equal(ret, PSA_ERROR_DOES_NOT_EXIST);

ret = psa_get_key_attributes(ID, &retrieved_key_attributes);
zassert_equal(ret, PSA_SUCCESS);
zassert_mem_equal(&retrieved_key_attributes, &key_attributes, sizeof(key_attributes));
ret = psa_destroy_key(ID);
zassert_equal(ret, PSA_SUCCESS);
ret = psa_get_key_attributes(ID, &retrieved_key_attributes);
zassert_equal(ret, PSA_ERROR_INVALID_HANDLE);
}

ZTEST(secure_storage_psa_crypto, test_persistent_key_usage)
{
psa_status_t ret;
psa_key_attributes_t key_attributes;
psa_key_id_t key_id;
uint8_t key_material[KEY_BITS / 8];

fill_key_attributes(&key_attributes);
fill_data(key_material, sizeof(key_material));
ret = psa_import_key(&key_attributes, key_material, sizeof(key_material), &key_id);
zassert_equal(ret, PSA_SUCCESS);
zassert_equal(key_id, ID);
ret = psa_purge_key(ID);
zassert_equal(ret, PSA_SUCCESS);

static uint8_t plaintext[1024];
static uint8_t ciphertext[PSA_CIPHER_ENCRYPT_OUTPUT_SIZE(KEY_TYPE, ALG, sizeof(plaintext))];
static uint8_t decrypted_text[sizeof(plaintext)];
size_t output_length;

fill_data(plaintext, sizeof(plaintext));
ret = psa_cipher_encrypt(ID, ALG, plaintext, sizeof(plaintext),
ciphertext, sizeof(ciphertext), &output_length);
zassert_equal(ret, PSA_SUCCESS);
zassert_equal(output_length, sizeof(ciphertext));
ret = psa_purge_key(ID);
zassert_equal(ret, PSA_SUCCESS);

ret = psa_cipher_decrypt(ID, ALG, ciphertext, output_length,
decrypted_text, sizeof(decrypted_text), &output_length);
zassert_equal(ret, PSA_SUCCESS);
zassert_equal(output_length, sizeof(plaintext));
zassert_mem_equal(plaintext, decrypted_text, sizeof(plaintext));
ret = psa_purge_key(ID);
zassert_equal(ret, PSA_SUCCESS);

ret = psa_destroy_key(ID);
zassert_equal(ret, PSA_SUCCESS);
ret = psa_destroy_key(ID);
zassert_equal(ret, PSA_ERROR_INVALID_HANDLE);
}
14 changes: 14 additions & 0 deletions tests/subsys/secure_storage/psa/crypto/testcase.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
common:
tags:
- psa.secure_storage
tests:
secure_storage.psa.crypto.secure_storage:
filter: CONFIG_SECURE_STORAGE and not CONFIG_SECURE_STORAGE_ITS_STORE_IMPLEMENTATION_NONE
extra_args: EXTRA_CONF_FILE=overlay-secure_storage.conf
integration_platforms:
- native_sim
- nrf9151dk/nrf9151
secure_storage.psa.crypto.tfm:
filter: CONFIG_BUILD_WITH_TFM
integration_platforms:
- nrf5340dk/nrf5340/cpuapp/ns
11 changes: 11 additions & 0 deletions tests/subsys/secure_storage/psa/its/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
cmake_minimum_required(VERSION 3.20.0)
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
project(app)

target_sources(app PRIVATE src/main.c)

zephyr_sources_ifdef(CONFIG_SECURE_STORAGE_ITS_TRANSFORM_IMPLEMENTATION_CUSTOM
src/custom_transform.c)

zephyr_sources_ifdef(CONFIG_SECURE_STORAGE_ITS_STORE_IMPLEMENTATION_CUSTOM
src/custom_store.c)
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
CONFIG_SECURE_STORAGE_ITS_STORE_IMPLEMENTATION_CUSTOM=y
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
CONFIG_SECURE_STORAGE_ITS_TRANSFORM_IMPLEMENTATION_CUSTOM=y
CONFIG_SECURE_STORAGE_ITS_TRANSFORM_OUTPUT_OVERHEAD=0

# SETTINGS_MAX_VAL_LEN (256) - flags (1)
CONFIG_SECURE_STORAGE_ITS_MAX_DATA_SIZE=255
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Limit the space available for the maximum entry test to not take too long.
CONFIG_SETTINGS_NVS_SECTOR_COUNT=2
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
CONFIG_MBEDTLS=y
CONFIG_TEST_RANDOM_GENERATOR=y
CONFIG_TIMER_RANDOM_GENERATOR=y
CONFIG_MBEDTLS_ENTROPY_POLL_ZEPHYR=y
CONFIG_MBEDTLS_PSA_CRYPTO_C=y

# SETTINGS_MAX_VAL_LEN (256) - flags (1) - CONFIG_SECURE_STORAGE_ITS_TRANSFORM_OUTPUT_OVERHEAD (28)
CONFIG_SECURE_STORAGE_ITS_MAX_DATA_SIZE=227
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
CONFIG_ZTEST_STACK_SIZE=3072
CONFIG_MAIN_STACK_SIZE=2048

CONFIG_SECURE_STORAGE=y
2 changes: 2 additions & 0 deletions tests/subsys/secure_storage/psa/its/overlay-tfm.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
CONFIG_TFM_ITS_MAX_ASSET_SIZE_OVERRIDE=y
CONFIG_TFM_ITS_MAX_ASSET_SIZE=256
1 change: 1 addition & 0 deletions tests/subsys/secure_storage/psa/its/prj.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
CONFIG_ZTEST=y
73 changes: 73 additions & 0 deletions tests/subsys/secure_storage/psa/its/src/custom_store.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/* Copyright (c) 2024 Nordic Semiconductor
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/secure_storage/its/store.h>
#include <zephyr/secure_storage/its/transform.h>
#include <zephyr/sys/util.h>
#include <string.h>

static struct {
secure_storage_its_uid_t uid;
size_t data_length;
uint8_t data[SECURE_STORAGE_ITS_TRANSFORM_MAX_STORED_DATA_SIZE];
} s_its_entries[100];

static int get_existing_entry_index(secure_storage_its_uid_t uid)
{
__ASSERT_NO_MSG(uid.uid != 0);

for (unsigned int i = 0; i != ARRAY_SIZE(s_its_entries); ++i) {
if (!memcmp(&uid, &s_its_entries[i].uid, sizeof(uid))) {
return i;
}
}
return -1;
}

psa_status_t secure_storage_its_store_set(secure_storage_its_uid_t uid,
size_t data_length, const void *data)
{
__ASSERT_NO_MSG(data_length <= sizeof(s_its_entries[0].data));
int index = get_existing_entry_index(uid);

if (index == -1) {
for (unsigned int i = 0; i != ARRAY_SIZE(s_its_entries); ++i) {
if (s_its_entries[i].uid.uid == 0) {
index = i;
break;
}
}
if (index == -1) {
return PSA_ERROR_INSUFFICIENT_STORAGE;
}
s_its_entries[index].uid = uid;
}

s_its_entries[index].data_length = data_length;
memcpy(s_its_entries[index].data, data, data_length);
return PSA_SUCCESS;
}

psa_status_t secure_storage_its_store_get(secure_storage_its_uid_t uid, size_t data_size,
void *data, size_t *data_length)
{
const int index = get_existing_entry_index(uid);

if (index == -1) {
return PSA_ERROR_DOES_NOT_EXIST;
}
*data_length = MIN(data_size, s_its_entries[index].data_length);
memcpy(data, s_its_entries[index].data, *data_length);
return PSA_SUCCESS;
}

psa_status_t secure_storage_its_store_remove(secure_storage_its_uid_t uid)
{
const int index = get_existing_entry_index(uid);

if (index == -1) {
return PSA_ERROR_DOES_NOT_EXIST;
}
s_its_entries[index].uid.uid = 0;
return PSA_SUCCESS;
}
33 changes: 33 additions & 0 deletions tests/subsys/secure_storage/psa/its/src/custom_transform.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/* Copyright (c) 2024 Nordic Semiconductor
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/secure_storage/its/transform.h>
#include <zephyr/sys/__assert.h>
#include <string.h>

psa_status_t secure_storage_its_transform_to_store(
secure_storage_its_uid_t uid, size_t data_len, const void *data,
secure_storage_packed_create_flags_t create_flags,
uint8_t stored_data[static SECURE_STORAGE_ITS_TRANSFORM_MAX_STORED_DATA_SIZE],
size_t *stored_data_len)
{
*stored_data_len = data_len + sizeof(secure_storage_packed_create_flags_t);
__ASSERT_NO_MSG(data_len <= CONFIG_SECURE_STORAGE_ITS_MAX_DATA_SIZE);
__ASSERT_NO_MSG(*stored_data_len <= SECURE_STORAGE_ITS_TRANSFORM_MAX_STORED_DATA_SIZE);
memcpy(stored_data, data, data_len);
*(secure_storage_packed_create_flags_t *)(&stored_data[data_len]) = create_flags;
return PSA_SUCCESS;
}

psa_status_t secure_storage_its_transform_from_store(
secure_storage_its_uid_t uid, size_t stored_data_len,
const uint8_t stored_data[static SECURE_STORAGE_ITS_TRANSFORM_MAX_STORED_DATA_SIZE],
size_t data_size, void *data, size_t *data_len,
psa_storage_create_flags_t *create_flags)
{
*data_len = stored_data_len - sizeof(secure_storage_packed_create_flags_t);
__ASSERT_NO_MSG(data_size >= *data_len);
memcpy(data, stored_data, *data_len);
*create_flags = *(secure_storage_packed_create_flags_t *)(&stored_data[*data_len]);
return PSA_SUCCESS;
}
Loading

0 comments on commit 85a56b5

Please sign in to comment.