TF-M Reference Manual  1.2.0
TrustedFirmware-M
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
tfm_internal_trusted_storage.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  *
6  */
7 
9 
10 #include "flash/its_flash.h"
11 #include "flash_fs/its_flash_fs.h"
12 #include "psa_manifest/pid.h"
13 #include "tfm_memory_utils.h"
14 #include "tfm_its_defs.h"
15 #include "tfm_its_req_mngr.h"
16 #include "its_utils.h"
17 
18 #ifndef ITS_BUF_SIZE
19 /* By default, set the ITS buffer size to the max asset size so that all
20  * requests can be handled in one iteration.
21  */
22 #define ITS_BUF_SIZE ITS_MAX_ASSET_SIZE
23 #endif
24 
25 /* Buffer to store asset data from the caller.
26  * Note: size must be aligned to the max flash program unit to meet the
27  * alignment requirement of the filesystem.
28  */
29 static uint8_t asset_data[ITS_UTILS_ALIGN(ITS_BUF_SIZE,
31 
32 static uint8_t g_fid[ITS_FILE_ID_SIZE];
33 static struct its_file_info_t g_file_info;
34 
35 static its_flash_fs_ctx_t fs_ctx_its;
36 static its_flash_fs_ctx_t fs_ctx_ps;
37 
38 static its_flash_fs_ctx_t *get_fs_ctx(int32_t client_id)
39 {
40  return (client_id == TFM_SP_PS) ? &fs_ctx_ps : &fs_ctx_its;
41 }
42 
50 static void tfm_its_get_fid(int32_t client_id,
52  uint8_t *fid)
53 {
54  tfm_memcpy(fid, (const void *)&client_id, sizeof(client_id));
55  tfm_memcpy(fid + sizeof(client_id), (const void *)&uid, sizeof(uid));
56 }
57 
59 {
60  psa_status_t status;
61 
62  /* Initialise the ITS context */
63  status = its_flash_fs_prepare(&fs_ctx_its,
65 #ifdef ITS_CREATE_FLASH_LAYOUT
66  /* If ITS_CREATE_FLASH_LAYOUT is set, it indicates that it is required to
67  * create a ITS flash layout. ITS service will generate an empty and valid
68  * ITS flash layout to store assets. It will erase all data located in the
69  * assigned ITS memory area before generating the ITS layout.
70  * This flag is required to be set if the ITS memory area is located in
71  * non-persistent memory.
72  * This flag can be set if the ITS memory area is located in persistent
73  * memory without a previous valid ITS flash layout in it. That is the case
74  * when it is the first time in the device life that the ITS service is
75  * executed.
76  */
77  if (status != PSA_SUCCESS) {
78  /* Remove all data in the ITS memory area and create a valid ITS flash
79  * layout in that area.
80  */
81  status = its_flash_fs_wipe_all(&fs_ctx_its);
82  if (status != PSA_SUCCESS) {
83  return status;
84  }
85 
86  /* Attempt to initialise again */
87  status = its_flash_fs_prepare(&fs_ctx_its,
89  }
90 #endif /* ITS_CREATE_FLASH_LAYOUT */
91 
92 #ifdef TFM_PARTITION_PROTECTED_STORAGE
93  /* Initialise the PS context */
94  status = its_flash_fs_prepare(&fs_ctx_ps,
96 #ifdef PS_CREATE_FLASH_LAYOUT
97  /* If PS_CREATE_FLASH_LAYOUT is set, it indicates that it is required to
98  * create a PS flash layout. PS service will generate an empty and valid
99  * PS flash layout to store assets. It will erase all data located in the
100  * assigned PS memory area before generating the PS layout.
101  * This flag is required to be set if the PS memory area is located in
102  * non-persistent memory.
103  * This flag can be set if the PS memory area is located in persistent
104  * memory without a previous valid PS flash layout in it. That is the case
105  * when it is the first time in the device life that the PS service is
106  * executed.
107  */
108  if (status != PSA_SUCCESS) {
109  /* Remove all data in the PS memory area and create a valid PS flash
110  * layout in that area.
111  */
112  status = its_flash_fs_wipe_all(&fs_ctx_ps);
113  if (status != PSA_SUCCESS) {
114  return status;
115  }
116 
117  /* Attempt to initialise again */
118  status = its_flash_fs_prepare(&fs_ctx_ps,
120  }
121 #endif /* PS_CREATE_FLASH_LAYOUT */
122 
123 #endif /* TFM_PARTITION_PROTECTED_STORAGE */
124 
125  return status;
126 }
127 
128 psa_status_t tfm_its_set(int32_t client_id,
129  psa_storage_uid_t uid,
130  size_t data_length,
131  psa_storage_create_flags_t create_flags)
132 {
133  psa_status_t status;
134  size_t write_size;
135  size_t offset;
136  uint32_t flags;
137 
138  /* Check that the UID is valid */
139  if (uid == TFM_ITS_INVALID_UID) {
141  }
142 
143  /* Check that the create_flags does not contain any unsupported flags */
144  if (create_flags & ~(PSA_STORAGE_FLAG_WRITE_ONCE |
148  }
149 
150  /* Set file id */
151  tfm_its_get_fid(client_id, uid, g_fid);
152 
153  /* Read file info */
154  status = its_flash_fs_file_get_info(get_fs_ctx(client_id), g_fid,
155  &g_file_info);
156  if (status == PSA_SUCCESS) {
157  /* If the object exists and has the write once flag set, then it
158  * cannot be modified.
159  */
160  if (g_file_info.flags & PSA_STORAGE_FLAG_WRITE_ONCE) {
162  }
163  } else if (status != PSA_ERROR_DOES_NOT_EXIST) {
164  /* If the file does not exist, then do nothing.
165  * If other error occurred, return it
166  */
167  return status;
168  }
169 
170  offset = 0;
171  flags = (uint32_t)create_flags |
173 
174  /* Iteratively read data from the caller and write it to the filesystem, in
175  * chunks no larger than the size of the asset_data buffer.
176  */
177  do {
178  /* Write as much of the data as will fit in the asset_data buffer */
179  write_size = ITS_UTILS_MIN(data_length, sizeof(asset_data));
180 
181  /* Read asset data from the caller */
182  (void)its_req_mngr_read(asset_data, write_size);
183 
184  /* Write to the file in the file system */
185  status = its_flash_fs_file_write(get_fs_ctx(client_id), g_fid, flags,
186  data_length, write_size, offset,
187  asset_data);
188  if (status != PSA_SUCCESS) {
189  return status;
190  }
191 
192  /* Do not create or truncate after the first iteration */
194 
195  offset += write_size;
196  data_length -= write_size;
197  } while (data_length > 0);
198 
199  return PSA_SUCCESS;
200 }
201 
202 psa_status_t tfm_its_get(int32_t client_id,
203  psa_storage_uid_t uid,
204  size_t data_offset,
205  size_t data_size,
206  size_t *p_data_length)
207 {
208  psa_status_t status;
209  size_t read_size;
210 
211 #ifdef TFM_PARTITION_TEST_PS
212  /* The PS test partition can call tfm_its_get() through PS code. Treat it
213  * as if it were PS.
214  */
215  if (client_id == TFM_SP_PS_TEST) {
216  client_id = TFM_SP_PS;
217  }
218 #endif
219 
220  /* Check that the UID is valid */
221  if (uid == TFM_ITS_INVALID_UID) {
223  }
224 
225  /* Set file id */
226  tfm_its_get_fid(client_id, uid, g_fid);
227 
228  /* Read file info */
229  status = its_flash_fs_file_get_info(get_fs_ctx(client_id), g_fid,
230  &g_file_info);
231  if (status != PSA_SUCCESS) {
232  return status;
233  }
234 
235  /* Boundary check the incoming request */
236  if (data_offset > g_file_info.size_current) {
238  }
239 
240  /* Copy the object data only from within the file boundary */
241  data_size = ITS_UTILS_MIN(data_size,
242  g_file_info.size_current - data_offset);
243 
244  /* Update the size of the output data */
245  *p_data_length = data_size;
246 
247  /* Iteratively read data from the filesystem and write it to the caller, in
248  * chunks no larger than the size of the asset_data buffer.
249  */
250  do {
251  /* Read as much of the data as will fit in the asset_data buffer */
252  read_size = ITS_UTILS_MIN(data_size, sizeof(asset_data));
253 
254  /* Read file data from the filesystem */
255  status = its_flash_fs_file_read(get_fs_ctx(client_id), g_fid, read_size,
256  data_offset, asset_data);
257  if (status != PSA_SUCCESS) {
258  *p_data_length = 0;
259  return status;
260  }
261 
262  /* Write asset data to the caller */
263  its_req_mngr_write(asset_data, read_size);
264 
265  data_offset += read_size;
266  data_size -= read_size;
267  } while (data_size > 0);
268 
269  return PSA_SUCCESS;
270 }
271 
273  struct psa_storage_info_t *p_info)
274 {
275  psa_status_t status;
276 
277  /* Check that the UID is valid */
278  if (uid == TFM_ITS_INVALID_UID) {
280  }
281 
282  /* Set file id */
283  tfm_its_get_fid(client_id, uid, g_fid);
284 
285  /* Read file info */
286  status = its_flash_fs_file_get_info(get_fs_ctx(client_id), g_fid,
287  &g_file_info);
288  if (status != PSA_SUCCESS) {
289  return status;
290  }
291 
292  /* Copy file info to the PSA info struct */
293  p_info->capacity = g_file_info.size_current;
294  p_info->size = g_file_info.size_current;
295  p_info->flags = g_file_info.flags;
296 
297  return PSA_SUCCESS;
298 }
299 
301 {
302  psa_status_t status;
303 
304 #ifdef TFM_PARTITION_TEST_PS
305  /* The PS test partition can call tfm_its_remove() through PS code. Treat
306  * it as if it were PS.
307  */
308  if (client_id == TFM_SP_PS_TEST) {
309  client_id = TFM_SP_PS;
310  }
311 #endif
312 
313  /* Check that the UID is valid */
314  if (uid == TFM_ITS_INVALID_UID) {
316  }
317 
318  /* Set file id */
319  tfm_its_get_fid(client_id, uid, g_fid);
320 
321  status = its_flash_fs_file_get_info(get_fs_ctx(client_id), g_fid,
322  &g_file_info);
323  if (status != PSA_SUCCESS) {
324  return status;
325  }
326 
327  /* If the object exists and has the write once flag set, then it
328  * cannot be deleted.
329  */
330  if (g_file_info.flags & PSA_STORAGE_FLAG_WRITE_ONCE) {
332  }
333 
334  /* Delete old file from the persistent area */
335  return its_flash_fs_file_delete(get_fs_ctx(client_id), g_fid);
336 }
uint32_t flags
Definition: its_flash_fs.h:64
#define PSA_STORAGE_FLAG_NO_CONFIDENTIALITY
psa_status_t its_flash_fs_file_get_info(struct its_flash_fs_ctx_t *fs_ctx, const uint8_t *fid, struct its_file_info_t *info)
Gets the file information referenced by the file ID.
Definition: its_flash_fs.c:112
psa_status_t its_flash_fs_prepare(struct its_flash_fs_ctx_t *fs_ctx, const struct its_flash_info_t *flash_info)
Prepares the filesystem to accept operations on the files.
Definition: its_flash_fs.c:58
#define PSA_SUCCESS
Definition: crypto_values.h:35
Internal Trusted Storage service filesystem abstraction APIs. The purpose of this abstraction is to h...
psa_status_t tfm_its_get_info(int32_t client_id, psa_storage_uid_t uid, struct psa_storage_info_t *p_info)
Retrieve the metadata about the provided uid.
size_t size_current
Definition: its_flash_fs.h:60
#define ITS_BUF_SIZE
#define PSA_STORAGE_FLAG_WRITE_ONCE
psa_status_t its_flash_fs_file_write(struct its_flash_fs_ctx_t *fs_ctx, const uint8_t *fid, uint32_t flags, size_t max_size, size_t data_size, size_t offset, const uint8_t *data)
Writes data to a file.
Definition: its_flash_fs.c:144
#define TFM_SP_PS
Definition: pid.h:17
#define PSA_ERROR_INVALID_ARGUMENT
psa_status_t its_flash_fs_file_read(struct its_flash_fs_ctx_t *fs_ctx, const uint8_t *fid, size_t size, size_t offset, uint8_t *data)
Reads data from an existing file.
Definition: its_flash_fs.c:469
#define PSA_ERROR_NOT_PERMITTED
Definition: crypto_values.h:65
#define ITS_FILE_ID_SIZE
Definition: its_utils.h:20
#define TFM_SP_PS_TEST
Definition: pid.h:29
#define ITS_FLASH_MAX_ALIGNMENT
Provides a compile-time constant for the maximum program unit required by any flash device that can b...
Definition: its_flash.h:43
psa_status_t its_flash_fs_file_delete(struct its_flash_fs_ctx_t *fs_ctx, const uint8_t *fid)
Deletes file referenced by the file ID.
Definition: its_flash_fs.c:454
const struct its_flash_info_t * its_flash_get_info(enum its_flash_id_t id)
Gets the flash info structure for the provided flash device.
Definition: its_flash.c:27
psa_status_t tfm_its_remove(int32_t client_id, psa_storage_uid_t uid)
Remove the provided uid and its associated data from the storage.
#define PSA_STORAGE_FLAG_NO_REPLAY_PROTECTION
#define PSA_ERROR_NOT_SUPPORTED
Definition: crypto_values.h:52
psa_status_t tfm_its_get(int32_t client_id, psa_storage_uid_t uid, size_t data_offset, size_t data_size, size_t *p_data_length)
Retrieve data associated with a provided UID.
psa_status_t tfm_its_set(int32_t client_id, psa_storage_uid_t uid, size_t data_length, psa_storage_create_flags_t create_flags)
Create a new, or modify an existing, uid/value pair.
__STATIC_INLINE void * tfm_memcpy(void *dest, const void *src, size_t num)
void its_req_mngr_write(const uint8_t *buf, size_t num_bytes)
Writes asset data to the caller.
uint64_t psa_storage_uid_t
psa_status_t tfm_its_init(void)
Initializes the internal trusted storage system.
#define ITS_FLASH_FS_FLAG_CREATE
Definition: its_flash_fs.h:39
#define TFM_ITS_INVALID_UID
Definition: tfm_its_defs.h:16
psa_status_t its_flash_fs_wipe_all(struct its_flash_fs_ctx_t *fs_ctx)
Wipes all files from the filesystem.
Definition: its_flash_fs.c:92
Structure to store the file information.
Definition: its_flash_fs.h:59
psa_storage_create_flags_t flags
Structure to store the ITS flash file system context.
#define PSA_ERROR_DOES_NOT_EXIST
Definition: crypto_values.h:89
uint32_t psa_storage_create_flags_t
int32_t psa_status_t
Function return status.
Definition: crypto_types.h:43
#define ITS_UTILS_ALIGN(x, a)
Aligns a value up to the provided alignment.
Definition: its_utils.h:56
#define ITS_UTILS_MIN(x, y)
Evaluates to the minimum of the two parameters.
Definition: its_utils.h:41
#define ITS_FLASH_FS_FLAG_TRUNCATE
Definition: its_flash_fs.h:41
size_t its_req_mngr_read(uint8_t *buf, size_t num_bytes)
Reads asset data from the caller.