1 /* Copyright (c) 2024 Nordic Semiconductor
2  * SPDX-License-Identifier: Apache-2.0
3  */
4 #include <zephyr/ztest.h>
5 #include <psa/internal_trusted_storage.h>
6 
7 /* The flash must be erased after this test suite is run for the write-once entry test to pass. */
8 ZTEST_SUITE(secure_storage_psa_its, NULL, NULL, NULL, NULL, NULL);
9 
10 #ifdef CONFIG_SECURE_STORAGE
11 #define MAX_DATA_SIZE CONFIG_SECURE_STORAGE_ITS_MAX_DATA_SIZE
12 #else
13 #define MAX_DATA_SIZE CONFIG_TFM_ITS_MAX_ASSET_SIZE
14 #endif
15 
16 #define UID (psa_storage_uid_t)1
17 
fill_data_buffer(uint8_t data[static MAX_DATA_SIZE])18 static void fill_data_buffer(uint8_t data[static MAX_DATA_SIZE])
19 {
20 	for (unsigned int i = 0; i != MAX_DATA_SIZE; ++i) {
21 		data[i] = i;
22 	}
23 }
24 
ZTEST(secure_storage_psa_its,test_all_sizes)25 ZTEST(secure_storage_psa_its, test_all_sizes)
26 {
27 	psa_status_t ret;
28 	uint8_t written_data[MAX_DATA_SIZE];
29 	struct psa_storage_info_t info;
30 	uint8_t read_data[MAX_DATA_SIZE];
31 	size_t data_length;
32 
33 	fill_data_buffer(written_data);
34 
35 	for (unsigned int i = 0; i <= sizeof(written_data); ++i) {
36 
37 		ret = psa_its_set(UID, i, written_data, PSA_STORAGE_FLAG_NONE);
38 		zassert_equal(ret, PSA_SUCCESS);
39 
40 		ret = psa_its_get_info(UID, &info);
41 		zassert_equal(ret, PSA_SUCCESS);
42 		zassert_equal(info.flags, PSA_STORAGE_FLAG_NONE);
43 		zassert_equal(info.size, i);
44 		zassert_equal(info.capacity, i);
45 
46 		ret = psa_its_get(UID, 0, sizeof(read_data), read_data, &data_length);
47 		zassert_equal(ret, PSA_SUCCESS);
48 		zassert_equal(data_length, i);
49 		zassert_mem_equal(read_data, written_data, data_length);
50 
51 		ret = psa_its_remove(UID);
52 		zassert_equal(ret, PSA_SUCCESS);
53 		ret = psa_its_get_info(UID, &info);
54 		zassert_equal(ret, PSA_ERROR_DOES_NOT_EXIST);
55 	}
56 }
57 
ZTEST(secure_storage_psa_its,test_all_offsets)58 ZTEST(secure_storage_psa_its, test_all_offsets)
59 {
60 	psa_status_t ret;
61 	uint8_t written_data[MAX_DATA_SIZE];
62 	uint8_t read_data[MAX_DATA_SIZE];
63 	size_t data_length;
64 
65 	fill_data_buffer(written_data);
66 	ret = psa_its_set(UID, sizeof(written_data), written_data, PSA_STORAGE_FLAG_NONE);
67 	zassert_equal(ret, PSA_SUCCESS);
68 
69 	for (unsigned int i = 0; i <= sizeof(read_data); ++i) {
70 
71 		ret = psa_its_get(UID, i, sizeof(read_data) - i, read_data, &data_length);
72 		zassert_equal(ret, PSA_SUCCESS);
73 		zassert_equal(data_length, sizeof(read_data) - i);
74 
75 		zassert_mem_equal(read_data, written_data + i, data_length);
76 	}
77 }
78 
ZTEST(secure_storage_psa_its,test_max_num_entries)79 ZTEST(secure_storage_psa_its, test_max_num_entries)
80 {
81 	psa_status_t ret = PSA_SUCCESS;
82 	unsigned int i;
83 	struct psa_storage_info_t info;
84 
85 	for (i = 0; ret == PSA_SUCCESS; ++i) {
86 		ret = psa_its_set(UID + i, sizeof(i), &i, PSA_STORAGE_FLAG_NONE);
87 	}
88 	const unsigned int max_num_entries = i - 1;
89 
90 	zassert_true(max_num_entries > 1);
91 	printk("Successfully wrote %u entries.\n", max_num_entries);
92 	zassert_equal(ret, PSA_ERROR_INSUFFICIENT_STORAGE);
93 
94 	for (i = 0; i != max_num_entries; ++i) {
95 		unsigned int data;
96 		size_t data_length;
97 
98 		ret = psa_its_get(UID + i, 0, sizeof(data), &data, &data_length);
99 		zassert_equal(ret, PSA_SUCCESS);
100 		zassert_equal(data, i);
101 	}
102 	for (i = 0; i != max_num_entries; ++i) {
103 		ret = psa_its_remove(UID + i);
104 		zassert_equal(ret, PSA_SUCCESS);
105 	}
106 	for (i = 0; i != max_num_entries; ++i) {
107 		ret = psa_its_get_info(UID + i, &info);
108 		zassert_equal(ret, PSA_ERROR_DOES_NOT_EXIST);
109 	}
110 }
111 
112 /* The flash must be erased between runs of this test for it to pass. */
ZTEST(secure_storage_psa_its,test_write_once_flag)113 ZTEST(secure_storage_psa_its, test_write_once_flag)
114 {
115 	psa_status_t ret;
116 	/* Use a UID that isn't used in the other tests for the write-once entry. */
117 	const psa_storage_uid_t uid = 1 << 16;
118 	const uint8_t data[MAX_DATA_SIZE] = {};
119 	struct psa_storage_info_t info;
120 
121 	ret = psa_its_set(uid, sizeof(data), data, PSA_STORAGE_FLAG_WRITE_ONCE);
122 	zassert_equal(ret, PSA_SUCCESS, "%s%d", (ret == PSA_ERROR_NOT_PERMITTED) ?
123 		      "Has the flash been erased since this test ran? " : "", ret);
124 
125 	ret = psa_its_get_info(uid, &info);
126 	zassert_equal(ret, PSA_SUCCESS);
127 	zassert_equal(info.flags, PSA_STORAGE_FLAG_WRITE_ONCE);
128 
129 	ret = psa_its_set(uid, sizeof(data), data, PSA_STORAGE_FLAG_NONE);
130 	zassert_equal(ret, PSA_ERROR_NOT_PERMITTED);
131 
132 	ret = psa_its_remove(uid);
133 	zassert_equal(ret, PSA_ERROR_NOT_PERMITTED);
134 }
135