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