1 /*
2 * Copyright (c) 2019-2022, Arm Limited. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 */
7
8 #include <stdint.h>
9 #include <string.h>
10 #include <stdbool.h>
11
12 #include "cmsis_compiler.h"
13 #include "config_its.h"
14 #include "psa/storage_common.h"
15 #include "tfm_internal_trusted_storage.h"
16 #include "its_utils.h"
17
18 #include "psa/framework_feature.h"
19 #include "psa/service.h"
20 #include "psa_manifest/tfm_internal_trusted_storage.h"
21 #include "tfm_its_defs.h"
22 #if PSA_FRAMEWORK_HAS_MM_IOVEC != 1
23 #include "flash/its_flash.h"
24 #endif /* PSA_FRAMEWORK_HAS_MM_IOVEC != 1 */
25
26 #if PSA_FRAMEWORK_HAS_MM_IOVEC != 1
27 /* Buffer to store asset data from the caller.
28 * Note: size must be aligned to the max flash program unit to meet the
29 * alignment requirement of the filesystem.
30 */
31 static uint8_t __ALIGNED(4) asset_data[ITS_UTILS_ALIGN(ITS_BUF_SIZE,
32 ITS_FLASH_MAX_ALIGNMENT)];
33 #endif
34
tfm_its_set_req(const psa_msg_t * msg)35 static psa_status_t tfm_its_set_req(const psa_msg_t *msg)
36 {
37 psa_status_t status;
38 psa_storage_uid_t uid;
39 uint8_t *data_buf;
40 size_t size_remaining;
41 size_t offset;
42 psa_storage_create_flags_t create_flags;
43 struct its_asset_info asset_info;
44 size_t num;
45
46 if (msg->in_size[0] != sizeof(uid) ||
47 msg->in_size[2] != sizeof(create_flags)) {
48 /* The size of one of the arguments is incorrect */
49 return PSA_ERROR_PROGRAMMER_ERROR;
50 }
51
52 num = psa_read(msg->handle, 0, &uid, sizeof(uid));
53 if (num != sizeof(uid)) {
54 return PSA_ERROR_PROGRAMMER_ERROR;
55 }
56
57 num = psa_read(msg->handle, 2, &create_flags, sizeof(create_flags));
58 if (num != sizeof(create_flags)) {
59 return PSA_ERROR_PROGRAMMER_ERROR;
60 }
61
62 asset_info.uid = uid;
63 asset_info.client_id = msg->client_id;
64 asset_info.create_flags = create_flags;
65
66 size_remaining = msg->in_size[1];
67 offset = 0;
68
69 #if PSA_FRAMEWORK_HAS_MM_IOVEC == 1
70 if (size_remaining != 0) {
71 data_buf = (uint8_t *)psa_map_invec(msg->handle, 1);
72 } else {
73 /* zero-size asset is supported */
74 data_buf = NULL;
75 }
76
77 status = tfm_its_set(&asset_info, data_buf, size_remaining,
78 size_remaining, offset);
79 #else
80 data_buf = asset_data;
81 do {
82 num = psa_read(msg->handle, 1, asset_data,
83 ITS_UTILS_MIN(size_remaining, sizeof(asset_data)));
84
85 status = tfm_its_set(&asset_info, data_buf, size_remaining,
86 num, offset);
87 if (status != PSA_SUCCESS) {
88 return status;
89 }
90
91 size_remaining -= num;
92 offset += num;
93 } while (size_remaining);
94 #endif
95
96 return status;
97 }
98
tfm_its_get_req(const psa_msg_t * msg)99 static psa_status_t tfm_its_get_req(const psa_msg_t *msg)
100 {
101 psa_status_t status;
102 psa_storage_uid_t uid;
103 uint8_t *data_buf;
104 size_t size_to_read;
105 size_t data_offset;
106 size_t out_size;
107 size_t size_read;
108 size_t num;
109 struct its_asset_info asset_info;
110 bool first_get;
111
112 if (msg->in_size[0] != sizeof(uid) ||
113 msg->in_size[1] != sizeof(data_offset)) {
114 /* The size of one of the arguments is incorrect */
115 return PSA_ERROR_PROGRAMMER_ERROR;
116 }
117
118 num = psa_read(msg->handle, 0, &uid, sizeof(uid));
119 if (num != sizeof(uid)) {
120 return PSA_ERROR_PROGRAMMER_ERROR;
121 }
122
123 num = psa_read(msg->handle, 1, &data_offset, sizeof(data_offset));
124 if (num != sizeof(data_offset)) {
125 return PSA_ERROR_PROGRAMMER_ERROR;
126 }
127
128 asset_info.uid = uid;
129 asset_info.client_id = msg->client_id;
130 out_size = msg->out_size[0];
131 first_get = true;
132
133 #if PSA_FRAMEWORK_HAS_MM_IOVEC == 1
134 size_to_read = msg->out_size[0];
135 if (size_to_read != 0) {
136 data_buf = (uint8_t *)psa_map_outvec(msg->handle, 0);
137 } else {
138 data_buf = NULL;
139 }
140
141 status = tfm_its_get(&asset_info, data_buf, size_to_read,
142 data_offset, &size_read, first_get);
143 if (status == PSA_SUCCESS && size_to_read != 0) {
144 /* Unmap to update caller’s outvec with the number of bytes written */
145 psa_unmap_outvec(msg->handle, 0, size_read);
146 }
147 #else
148 /* Fill in the outvec unless no data left */
149 data_buf = asset_data;
150 do {
151 size_to_read = ITS_UTILS_MIN(out_size, sizeof(asset_data));
152 status = tfm_its_get(&asset_info, data_buf, size_to_read,
153 data_offset, &size_read, first_get);
154 if (status != PSA_SUCCESS) {
155 return status;
156 }
157 if (size_read == 0) {
158 /* No more data */
159 return PSA_SUCCESS;
160 }
161
162 psa_write(msg->handle, 0, data_buf, size_read);
163
164 first_get = false;
165 out_size -= size_read;
166 data_offset += size_read;
167 } while (out_size > 0);
168 #endif
169
170 return status;
171 }
172
tfm_its_get_info_req(const psa_msg_t * msg)173 static psa_status_t tfm_its_get_info_req(const psa_msg_t *msg)
174 {
175 psa_status_t status;
176 psa_storage_uid_t uid;
177 struct psa_storage_info_t info;
178 size_t num;
179
180 if (msg->in_size[0] != sizeof(uid) ||
181 msg->out_size[0] != sizeof(info)) {
182 /* The size of one of the arguments is incorrect */
183 return PSA_ERROR_PROGRAMMER_ERROR;
184 }
185
186 num = psa_read(msg->handle, 0, &uid, sizeof(uid));
187 if (num != sizeof(uid)) {
188 return PSA_ERROR_PROGRAMMER_ERROR;
189 }
190
191 status = tfm_its_get_info(msg->client_id, uid, &info);
192 if (status == PSA_SUCCESS) {
193 psa_write(msg->handle, 0, &info, sizeof(info));
194 }
195
196 return status;
197 }
198
tfm_its_remove_req(const psa_msg_t * msg)199 static psa_status_t tfm_its_remove_req(const psa_msg_t *msg)
200 {
201 psa_storage_uid_t uid;
202 size_t num;
203
204 if (msg->in_size[0] != sizeof(uid)) {
205 /* The input argument size is incorrect */
206 return PSA_ERROR_PROGRAMMER_ERROR;
207 }
208
209 num = psa_read(msg->handle, 0, &uid, sizeof(uid));
210 if (num != sizeof(uid)) {
211 return PSA_ERROR_PROGRAMMER_ERROR;
212 }
213
214 return tfm_its_remove(msg->client_id, uid);
215 }
216
tfm_its_entry(void)217 psa_status_t tfm_its_entry(void)
218 {
219 return tfm_its_init();
220 }
221
tfm_internal_trusted_storage_service_sfn(const psa_msg_t * msg)222 psa_status_t tfm_internal_trusted_storage_service_sfn(const psa_msg_t *msg)
223 {
224 switch (msg->type) {
225 case TFM_ITS_SET:
226 return tfm_its_set_req(msg);
227 case TFM_ITS_GET:
228 return tfm_its_get_req(msg);
229 case TFM_ITS_GET_INFO:
230 return tfm_its_get_info_req(msg);
231 case TFM_ITS_REMOVE:
232 return tfm_its_remove_req(msg);
233 default:
234 return PSA_ERROR_NOT_SUPPORTED;
235 }
236
237 return PSA_ERROR_GENERIC_ERROR;
238 }
239