1 /*
2  * Copyright (c) 2019-2024, Arm Limited. All rights reserved.
3  * Copyright (c) 2022 Cypress Semiconductor Corporation (an Infineon company)
4  * or an affiliate of Cypress Semiconductor Corporation. All rights reserved.
5  *
6  * SPDX-License-Identifier: BSD-3-Clause
7  *
8  */
9 #include <string.h>
10 #include "psa/framework_feature.h"
11 #if PSA_FRAMEWORK_HAS_MM_IOVEC != 1
12 #include "cmsis_compiler.h"
13 #endif
14 #include "config_tfm.h"
15 #include "tfm_internal_trusted_storage.h"
16 #include "tfm_its_req_mngr.h"
17 #include "tfm_hal_its.h"
18 #ifdef TFM_PARTITION_PROTECTED_STORAGE
19 #include "tfm_hal_ps.h"
20 #endif
21 #include "flash_fs/its_flash_fs.h"
22 #include "psa_manifest/pid.h"
23 #include "tfm_its_defs.h"
24 #include "its_utils.h"
25 #include "tfm_sp_log.h"
26 
27 #ifdef ITS_ENCRYPTION
28 #include "its_crypto_interface.h"
29 #endif
30 
31 #ifdef TFM_PARTITION_PROTECTED_STORAGE
32 #include "ps_object_defs.h"
33 #endif
34 
35 #ifndef TFM_PARTITION_INTERNAL_TRUSTED_STORAGE
36 extern uint8_t *p_psa_src_data;
37 extern uint8_t *p_psa_dest_data;
38 #endif /* !TFM_PARTITION_INTERNAL_TRUSTED_STORAGE */
39 
40 static uint8_t g_fid[ITS_FILE_ID_SIZE];
41 static struct its_flash_fs_file_info_t g_file_info;
42 
43 #if (PSA_FRAMEWORK_HAS_MM_IOVEC != 1) && defined(TFM_PARTITION_INTERNAL_TRUSTED_STORAGE)
44 /* Buffer to store asset data from the caller.
45  * Note: size must be aligned to the max flash program unit to meet the
46  * alignment requirement of the filesystem.
47  */
48 #ifndef ITS_ENCRYPTION
49 static uint8_t __ALIGNED(4) asset_data[ITS_UTILS_ALIGN(ITS_BUF_SIZE,
50                                           ITS_FLASH_MAX_ALIGNMENT)];
51 #else
52 static uint8_t __ALIGNED(4) asset_data[ITS_UTILS_ALIGN(ITS_MAX_ASSET_SIZE,
53                                               ITS_FLASH_MAX_ALIGNMENT)];
54 #endif
55 #endif
56 
57 #ifdef TFM_PARTITION_INTERNAL_TRUSTED_STORAGE
58 static its_flash_fs_ctx_t fs_ctx_its;
59 static struct its_flash_fs_config_t fs_cfg_its = {
60     .flash_dev = &ITS_FLASH_DEV,
61     .program_unit = ITS_FLASH_ALIGNMENT,
62     .max_file_size = ITS_UTILS_ALIGN(ITS_MAX_ASSET_SIZE, ITS_FLASH_ALIGNMENT),
63     .max_num_files = ITS_NUM_ASSETS + 1, /* Extra file for atomic replacement */
64 };
65 #endif /* TFM_PARTITION_INTERNAL_TRUSTED_STORAGE */
66 
67 #ifdef TFM_PARTITION_PROTECTED_STORAGE
68 static its_flash_fs_ctx_t fs_ctx_ps;
69 static struct its_flash_fs_config_t fs_cfg_ps = {
70     .flash_dev = &PS_FLASH_DEV,
71     .program_unit = PS_FLASH_ALIGNMENT,
72     .max_file_size = ITS_UTILS_ALIGN(PS_MAX_OBJECT_SIZE, PS_FLASH_ALIGNMENT),
73     .max_num_files = PS_MAX_NUM_OBJECTS,
74 };
75 #endif
76 
get_fs_ctx(int32_t client_id)77 static its_flash_fs_ctx_t *get_fs_ctx(int32_t client_id)
78 {
79 #ifdef TFM_PARTITION_PROTECTED_STORAGE
80 #ifndef TFM_PARTITION_INTERNAL_TRUSTED_STORAGE
81     (void)client_id;
82     return &fs_ctx_ps;
83 #else
84     return (client_id == TFM_SP_PS) ? &fs_ctx_ps : &fs_ctx_its;
85 #endif /* !TFM_PARTITION_INTERNAL_TRUSTED_STORAGE */
86 #else
87     (void)client_id;
88     return &fs_ctx_its;
89 #endif
90 }
91 
92 #ifdef ITS_ENCRYPTION
93 /* Buffer to store the encrypted asset data and the authentication tag before it
94  * is stored in the filesystem.
95  */
96 static uint8_t __ALIGNED(4) enc_asset_data[ITS_UTILS_ALIGN(ITS_MAX_ASSET_SIZE +
97                                            TFM_ITS_AUTH_TAG_LENGTH,
98                                            ITS_FLASH_MAX_ALIGNMENT)];
99 
buffer_size_check(int32_t client_id,size_t buffer_size)100 static psa_status_t buffer_size_check(int32_t client_id, size_t buffer_size)
101 {
102 /* With protected storage no encryption is used */
103 #ifdef TFM_PARTITION_PROTECTED_STORAGE
104     if (client_id != TFM_SP_PS) {
105 #else
106     {
107 #endif /* TFM_PARTITION_PROTECTED_STORAGE */
108         /* When encryption is enabled the whole file needs to fit in the
109          * global buffer.
110          */
111         if (buffer_size > ITS_MAX_ASSET_SIZE) {
112             return PSA_ERROR_INVALID_ARGUMENT;
113         }
114     }
115     return PSA_SUCCESS;
116 }
117 
118 static psa_status_t tfm_its_crypt_data(int32_t client_id,
119                                 uint8_t **input,
120                                 size_t input_size,
121                                 size_t offset)
122 {
123     psa_status_t status;
124 #ifdef TFM_PARTITION_PROTECTED_STORAGE
125     if (client_id != TFM_SP_PS) {
126 #else
127     {
128 #endif /* TFM_PARTITION_PROTECTED_STORAGE */
129         if (offset != 0) {
130             /* If the data will be encrypted the whole file needs to be written */
131             return PSA_ERROR_INVALID_ARGUMENT;
132         }
133 
134         status = tfm_its_crypt_file(&g_file_info,
135                                     g_fid,
136                                     sizeof(g_fid),
137                                     *input,
138                                     input_size,
139                                     enc_asset_data,
140                                     sizeof(enc_asset_data),
141                                     true);
142 
143         if (status != PSA_SUCCESS) {
144             return status;
145         }
146         *input = enc_asset_data;
147     }
148     return PSA_SUCCESS;
149 }
150 
151 static psa_status_t tfm_its_get_encrypted(int32_t client_id,
152                          size_t data_offset,
153                          size_t data_size,
154                          size_t *p_data_length)
155 {
156     psa_status_t status;
157 
158     if (g_file_info.size_max > sizeof(enc_asset_data)) {
159             return PSA_ERROR_BUFFER_TOO_SMALL;
160     }
161 
162     /* When encryption is enabled we need to read the whole file */
163     status = its_flash_fs_file_read(get_fs_ctx(client_id),
164                                     g_fid,
165                                     g_file_info.size_current,
166                                     0,
167                                     enc_asset_data);
168     if (status != PSA_SUCCESS) {
169         *p_data_length = 0;
170         return status;
171     }
172 
173     status = tfm_its_crypt_file(&g_file_info,
174                                 g_fid,
175                                 sizeof(g_fid),
176                                 enc_asset_data,
177                                 g_file_info.size_current,
178                                 asset_data,
179                                 sizeof(asset_data),
180                                 false);
181     if (status != PSA_SUCCESS) {
182         *p_data_length = 0;
183         return status;
184     }
185 
186     #if (PSA_FRAMEWORK_HAS_MM_IOVEC == 1) /* PSA_FRAMEWORK_HAS_MM_IOVEC */
187     memcpy(its_req_mngr_get_vec_base(), asset_data + data_offset, data_size);
188     #else
189     /* Write asset data to the caller in one go as due to buffer check before
190      * it is ensured that all data fit into asset_data
191      */
192     its_req_mngr_write(asset_data + data_offset, data_size);
193     #endif /* PSA_FRAMEWORK_HAS_MM_IOVEC */
194 
195     return PSA_SUCCESS;
196 }
197 #endif /* ITS_ENCRYPTION */
198 
199 /**
200  * \brief Maps a pair of client id and uid to a file id.
201  *
202  * \param[in]  client_id  Identifier of the asset's owner (client)
203  * \param[in]  uid        Identifier for the data
204  * \param[out] fid        Identifier of the file
205  */
206 static void tfm_its_get_fid(int32_t client_id,
207                             psa_storage_uid_t uid,
208                             uint8_t *fid)
209 {
210     memcpy(fid, (const void *)&client_id, sizeof(client_id));
211     memcpy(fid + sizeof(client_id), (const void *)&uid, sizeof(uid));
212 }
213 
214 #ifdef TFM_PARTITION_INTERNAL_TRUSTED_STORAGE
215 /**
216  * \brief Initialise the static ITS filesystem configurations.
217  *
218  * \return Returns PSA_ERROR_PROGRAMMER_ERROR if there is a configuration error,
219  *         and PSA_SUCCESS otherwise.
220  */
221 static psa_status_t init_its_fs_cfg(void)
222 {
223     struct tfm_hal_its_fs_info_t its_fs_info;
224 
225     /* Check the compile-time program unit matches the runtime value */
226     if (TFM_HAL_ITS_FLASH_DRIVER.GetInfo()->program_unit
227         != TFM_HAL_ITS_PROGRAM_UNIT) {
228         return PSA_ERROR_PROGRAMMER_ERROR;
229     }
230 
231     /* Retrieve flash properties from the ITS flash driver */
232     fs_cfg_its.sector_size = TFM_HAL_ITS_FLASH_DRIVER.GetInfo()->sector_size;
233     fs_cfg_its.erase_val = TFM_HAL_ITS_FLASH_DRIVER.GetInfo()->erased_value;
234 
235     /* Retrieve FS parameters from the ITS HAL */
236     if (tfm_hal_its_fs_info(&its_fs_info) != TFM_HAL_SUCCESS) {
237         return PSA_ERROR_PROGRAMMER_ERROR;
238     }
239 
240     /* Derive address, block_size and num_blocks from the HAL parameters */
241     fs_cfg_its.flash_area_addr = its_fs_info.flash_area_addr;
242     fs_cfg_its.block_size = fs_cfg_its.sector_size
243                             * its_fs_info.sectors_per_block;
244     fs_cfg_its.num_blocks = its_fs_info.flash_area_size / fs_cfg_its.block_size;
245 
246     return PSA_SUCCESS;
247 }
248 #endif /* TFM_PARTITION_INTERNAL_TRUSTED_STORAGE */
249 
250 #ifdef TFM_PARTITION_PROTECTED_STORAGE
251 /**
252  * \brief Initialise the static PS filesystem configurations.
253  *
254  * \return Returns PSA_ERROR_PROGRAMMER_ERROR if there is a configuration error,
255  *         and PSA_SUCCESS otherwise.
256  */
257 static psa_status_t init_ps_fs_cfg(void)
258 {
259     struct tfm_hal_ps_fs_info_t ps_fs_info;
260 
261     /* Check the compile-time program unit matches the runtime value */
262     if (TFM_HAL_PS_FLASH_DRIVER.GetInfo()->program_unit
263         != TFM_HAL_PS_PROGRAM_UNIT) {
264         return PSA_ERROR_PROGRAMMER_ERROR;
265     }
266 
267     /* Retrieve flash properties from the PS flash driver */
268     fs_cfg_ps.sector_size = TFM_HAL_PS_FLASH_DRIVER.GetInfo()->sector_size;
269     fs_cfg_ps.erase_val = TFM_HAL_PS_FLASH_DRIVER.GetInfo()->erased_value;
270 
271     /* Retrieve FS parameters from the PS HAL */
272     if (tfm_hal_ps_fs_info(&ps_fs_info) != TFM_HAL_SUCCESS) {
273         return PSA_ERROR_PROGRAMMER_ERROR;
274     }
275 
276     /* Derive address, block_size and num_blocks from the HAL parameters */
277     fs_cfg_ps.flash_area_addr = ps_fs_info.flash_area_addr;
278     fs_cfg_ps.block_size = fs_cfg_ps.sector_size * ps_fs_info.sectors_per_block;
279     fs_cfg_ps.num_blocks = ps_fs_info.flash_area_size / fs_cfg_ps.block_size;
280 
281     return PSA_SUCCESS;
282 }
283 #endif /* TFM_PARTITION_PROTECTED_STORAGE */
284 
285 psa_status_t tfm_its_init(void)
286 {
287     psa_status_t status = PSA_SUCCESS;
288 
289 #ifdef TFM_PARTITION_INTERNAL_TRUSTED_STORAGE
290     status = init_its_fs_cfg();
291     if (status != PSA_SUCCESS) {
292         return status;
293     }
294 
295     /* Initialise the ITS filesystem context */
296     status = its_flash_fs_init_ctx(&fs_ctx_its, &fs_cfg_its, &ITS_FLASH_OPS);
297     if (status != PSA_SUCCESS) {
298         return status;
299     }
300 
301     /* Prepare the ITS filesystem */
302     status = its_flash_fs_prepare(&fs_ctx_its);
303 #if ITS_CREATE_FLASH_LAYOUT
304     /* If ITS_CREATE_FLASH_LAYOUT is set to 1, it indicates that it is required to
305      * create a ITS flash layout. ITS service will generate an empty and valid
306      * ITS flash layout to store assets. It will erase all data located in the
307      * assigned ITS memory area before generating the ITS layout.
308      * This flag is required to be set if the ITS memory area is located in
309      * non-persistent memory.
310      * This flag can be set if the ITS memory area is located in persistent
311      * memory without a previous valid ITS flash layout in it. That is the case
312      * when it is the first time in the device life that the ITS service is
313      * executed.
314      */
315      if (status != PSA_SUCCESS) {
316         /* Remove all data in the ITS memory area and create a valid ITS flash
317          * layout in that area.
318          */
319         LOG_INFFMT("Creating an empty ITS flash layout.\r\n");
320         status = its_flash_fs_wipe_all(&fs_ctx_its);
321         if (status != PSA_SUCCESS) {
322             return status;
323         }
324 
325         /* Attempt to prepare again */
326         status = its_flash_fs_prepare(&fs_ctx_its);
327     }
328 #endif /* ITS_CREATE_FLASH_LAYOUT */
329 #endif /* TFM_PARTITION_INTERNAL_TRUSTED_STORAGE */
330 
331 #ifdef TFM_PARTITION_PROTECTED_STORAGE
332     /* Check status of ITS initialisation before continuing with PS */
333     if (status != PSA_SUCCESS) {
334         return status;
335     }
336 
337     status = init_ps_fs_cfg();
338     if (status != PSA_SUCCESS) {
339         return status;
340     }
341 
342     /* Initialise the PS filesystem context */
343     status = its_flash_fs_init_ctx(&fs_ctx_ps, &fs_cfg_ps, &PS_FLASH_OPS);
344     if (status != PSA_SUCCESS) {
345         return status;
346     }
347 
348     /* Prepare the PS filesystem */
349     status = its_flash_fs_prepare(&fs_ctx_ps);
350 #if PS_CREATE_FLASH_LAYOUT
351     /* If PS_CREATE_FLASH_LAYOUT is set to 1, it indicates that it is required to
352      * create a PS flash layout. PS service will generate an empty and valid
353      * PS flash layout to store assets. It will erase all data located in the
354      * assigned PS memory area before generating the PS layout.
355      * This flag is required to be set if the PS memory area is located in
356      * non-persistent memory.
357      * This flag can be set if the PS memory area is located in persistent
358      * memory without a previous valid PS flash layout in it. That is the case
359      * when it is the first time in the device life that the PS service is
360      * executed.
361      */
362      if (status != PSA_SUCCESS) {
363         /* Remove all data in the PS memory area and create a valid PS flash
364          * layout in that area.
365          */
366         LOG_INFFMT("Creating an empty PS flash layout.\r\n");
367         status = its_flash_fs_wipe_all(&fs_ctx_ps);
368         if (status != PSA_SUCCESS) {
369             return status;
370         }
371 
372         /* Attempt to prepare again */
373         status = its_flash_fs_prepare(&fs_ctx_ps);
374     }
375 #endif /* PS_CREATE_FLASH_LAYOUT */
376 #endif /* TFM_PARTITION_PROTECTED_STORAGE */
377 
378     return status;
379 }
380 
381 static psa_status_t get_file_info(psa_storage_uid_t uid, int32_t client_id)
382 {
383     /* Check that the UID is valid */
384     if (uid == TFM_ITS_INVALID_UID) {
385         return PSA_ERROR_INVALID_ARGUMENT;
386     }
387 
388     /* Set file id */
389     tfm_its_get_fid(client_id, uid, g_fid);
390 
391     /* Read file info */
392     return its_flash_fs_file_get_info(get_fs_ctx(client_id), g_fid,
393                                       &g_file_info);
394 }
395 
396 
397 static psa_status_t tfm_its_write_data_to_fs(const int32_t client_id,
398                                      const uint8_t *fid,
399                                      struct its_flash_fs_file_info_t *finfo,
400                                      const size_t data_size,
401                                      const size_t offset,
402                                      uint8_t *data)
403 {
404     psa_status_t status;
405     uint8_t *buffer_ptr = data;
406 #ifdef ITS_ENCRYPTION /* ITS_ENCRYPTION */
407     status = tfm_its_crypt_data(client_id, &buffer_ptr, data_size, offset);
408     if (status != PSA_SUCCESS) {
409         return status;
410     }
411 #endif /* ITS_ENCRYPTION */
412     status = its_flash_fs_file_write(get_fs_ctx(client_id),
413                                         fid,
414                                         &g_file_info,
415                                         data_size, offset, buffer_ptr);
416     if (status != PSA_SUCCESS) {
417         return status;
418     }
419 
420     return PSA_SUCCESS;
421 }
422 
423 psa_status_t tfm_its_set(int32_t client_id,
424                          psa_storage_uid_t uid,
425                          size_t data_length,
426                          psa_storage_create_flags_t create_flags)
427 {
428     psa_status_t status;
429 #if (PSA_FRAMEWORK_HAS_MM_IOVEC != 1) && defined(TFM_PARTITION_INTERNAL_TRUSTED_STORAGE)
430     size_t write_size;
431     size_t offset;
432 #endif
433 
434     /* Check that the UID is valid */
435     if (uid == TFM_ITS_INVALID_UID) {
436         return PSA_ERROR_INVALID_ARGUMENT;
437     }
438 
439     /* Check that the create_flags does not contain any unsupported flags */
440     if (create_flags & ~(PSA_STORAGE_FLAG_WRITE_ONCE |
441                          PSA_STORAGE_FLAG_NO_CONFIDENTIALITY |
442                          PSA_STORAGE_FLAG_NO_REPLAY_PROTECTION)) {
443         return PSA_ERROR_NOT_SUPPORTED;
444     }
445 
446 #if defined ITS_ENCRYPTION && defined TFM_PARTITION_INTERNAL_TRUSTED_STORAGE
447     status = buffer_size_check(client_id, data_length);
448     if (status != PSA_SUCCESS) {
449         return status;
450     }
451 #endif /* ITS_ENCRYPTION && TFM_PARTITION_INTERNAL_TRUSTED_STORAGE*/
452 
453     /* Read file info */
454     status = get_file_info(uid, client_id);
455     if (status == PSA_SUCCESS) {
456         /* If the object exists and has the write once flag set, then it
457          * cannot be modified.
458          */
459         if (g_file_info.flags & PSA_STORAGE_FLAG_WRITE_ONCE) {
460             return PSA_ERROR_NOT_PERMITTED;
461         }
462     } else if (status != PSA_ERROR_DOES_NOT_EXIST) {
463         /* If the file does not exist, then do nothing.
464          * If other error occurred, return it
465          */
466         return status;
467     }
468 
469     g_file_info.size_max = data_length;
470     g_file_info.flags = (uint32_t)create_flags |
471                         ITS_FLASH_FS_FLAG_CREATE | ITS_FLASH_FS_FLAG_TRUNCATE;
472 
473 
474 #ifndef TFM_PARTITION_INTERNAL_TRUSTED_STORAGE
475     /* Write to the file in the file system
476      * No encryption needed as this will be stored in the Protected Storage
477      * Partition if ITS partition is not enabled.
478      */
479     status = its_flash_fs_file_write(get_fs_ctx(client_id), g_fid, &g_file_info,
480                                      data_length, 0, p_psa_src_data);
481 #elif PSA_FRAMEWORK_HAS_MM_IOVEC == 1
482     status = tfm_its_write_data_to_fs(client_id,
483                                       g_fid,
484                                       &g_file_info,
485                                       data_length, 0,
486                                       its_req_mngr_get_vec_base());
487 #else
488     offset = 0;
489 
490     /* Iteratively read data from the caller and write it to the filesystem, in
491      * chunks no larger than the size of the asset_data buffer.
492      */
493     do {
494         /* Write as much of the data as will fit in the asset_data buffer */
495         write_size = ITS_UTILS_MIN(data_length, sizeof(asset_data));
496 
497         /* Read asset data from the caller */
498         (void)its_req_mngr_read(asset_data, write_size);
499 
500         status = tfm_its_write_data_to_fs(client_id, g_fid, &g_file_info,
501                                           write_size, offset, asset_data);
502 
503         if (status != PSA_SUCCESS) {
504                 return status;
505         }
506         /* Do not create or truncate after the first iteration */
507         g_file_info.flags &= ~(ITS_FLASH_FS_FLAG_CREATE | ITS_FLASH_FS_FLAG_TRUNCATE);
508 
509         offset += write_size;
510         data_length -= write_size;
511     } while (data_length > 0);
512 #endif
513 
514     return status;
515 }
516 
517 static psa_status_t tfm_its_get_plain(int32_t client_id,
518                          size_t data_offset,
519                          size_t data_size,
520                          size_t *p_data_length)
521 {
522     psa_status_t status;
523 
524 #if (PSA_FRAMEWORK_HAS_MM_IOVEC != 1) && defined(TFM_PARTITION_INTERNAL_TRUSTED_STORAGE)
525     size_t read_size;
526 #endif
527 
528 #ifndef TFM_PARTITION_INTERNAL_TRUSTED_STORAGE
529     /* Read file data from the filesystem */
530     status = its_flash_fs_file_read(get_fs_ctx(client_id), g_fid, data_size,
531                                     data_offset, p_psa_dest_data);
532     if (status != PSA_SUCCESS) {
533         *p_data_length = 0;
534         return status;
535     }
536 
537 #elif (PSA_FRAMEWORK_HAS_MM_IOVEC == 1)
538     /* Read file data from the filesystem */
539     status = its_flash_fs_file_read(get_fs_ctx(client_id), g_fid, data_size,
540                                     data_offset, its_req_mngr_get_vec_base());
541     if (status != PSA_SUCCESS) {
542         *p_data_length = 0;
543         return status;
544     }
545 
546 #else
547 
548     /* Iteratively read data from the filesystem and write it to the caller, in
549      * chunks no larger than the size of the asset_data buffer.
550      */
551     do {
552         /* Read as much of the data as will fit in the asset_data buffer */
553         read_size = ITS_UTILS_MIN(data_size, sizeof(asset_data));
554 
555         /* Read file data from the filesystem */
556         status = its_flash_fs_file_read(get_fs_ctx(client_id), g_fid, read_size,
557                                         data_offset, asset_data);
558         if (status != PSA_SUCCESS) {
559             *p_data_length = 0;
560             return status;
561         }
562 
563         /* Write asset data to the caller */
564         its_req_mngr_write(asset_data, read_size);
565 
566         data_offset += read_size;
567         data_size -= read_size;
568     } while (data_size > 0);
569 #endif /* TFM_PARTITION_INTERNAL_TRUSTED_STORAGE & PSA_FRAMEWORK_HAS_MM_IOVEC */
570 
571     return PSA_SUCCESS;
572 }
573 
574 psa_status_t tfm_its_get(int32_t client_id,
575                          psa_storage_uid_t uid,
576                          size_t data_offset,
577                          size_t data_size,
578                          size_t *p_data_length)
579 {
580     psa_status_t status;
581 
582 #ifdef TFM_PARTITION_TEST_PS
583     /* The PS test partition can call tfm_its_get() through PS code. Treat it
584      * as if it were PS.
585      */
586     if (client_id == TFM_SP_PS_TEST) {
587         client_id = TFM_SP_PS;
588     }
589 #endif
590 
591     /* Check that the UID is valid */
592     if (uid == TFM_ITS_INVALID_UID) {
593         return PSA_ERROR_INVALID_ARGUMENT;
594     }
595 
596 #if defined ITS_ENCRYPTION && defined TFM_PARTITION_INTERNAL_TRUSTED_STORAGE
597     status = buffer_size_check(client_id, data_offset + data_size);
598     if (status != PSA_SUCCESS) {
599         return status;
600     }
601 #endif /* ITS_ENCRYPTION && TFM_PARTITION_INTERNAL_TRUSTED_STORAGE */
602 
603     /* Read file info */
604     status = get_file_info(uid, client_id);
605     if (status != PSA_SUCCESS) {
606         return status;
607     }
608 
609     /* Boundary check the incoming request */
610     if (data_offset > g_file_info.size_current) {
611         return PSA_ERROR_INVALID_ARGUMENT;
612     }
613 
614     /* Copy the object data only from within the file boundary */
615     data_size = ITS_UTILS_MIN(data_size,
616                               g_file_info.size_current - data_offset);
617 
618     /* Update the size of the output data */
619     *p_data_length = data_size;
620 
621 #if defined ITS_ENCRYPTION && defined TFM_PARTITION_INTERNAL_TRUSTED_STORAGE
622 #if defined TFM_PARTITION_PROTECTED_STORAGE
623     /* With protected storage no encryption is used */
624     if (client_id == TFM_SP_PS) {
625         return tfm_its_get_plain(client_id, data_offset, data_size, p_data_length);
626     } else
627 #endif /* TFM_PARTITION_PROTECTED_STORAGE */
628     {
629         return tfm_its_get_encrypted(client_id, data_offset, data_size, p_data_length);
630     }
631 #else
632     {
633         return tfm_its_get_plain(client_id, data_offset, data_size, p_data_length);
634     }
635 #endif /* ITS_ENCRYPTION  && TFM_PARTITION_INTERNAL_TRUSTED_STORAGE */
636 }
637 
638 psa_status_t tfm_its_get_info(int32_t client_id, psa_storage_uid_t uid,
639                               struct psa_storage_info_t *p_info)
640 {
641     psa_status_t status;
642 
643     /* Validate and read file info */
644     status = get_file_info(uid, client_id);
645     if (status != PSA_SUCCESS) {
646         return status;
647     }
648 
649     /* Copy file info to the PSA info struct */
650     p_info->capacity = g_file_info.size_current;
651     p_info->size = g_file_info.size_current;
652     p_info->flags = g_file_info.flags;
653 
654     return PSA_SUCCESS;
655 }
656 
657 psa_status_t tfm_its_remove(int32_t client_id, psa_storage_uid_t uid)
658 {
659     psa_status_t status;
660 
661 #ifdef TFM_PARTITION_TEST_PS
662     /* The PS test partition can call tfm_its_remove() through PS code. Treat
663      * it as if it were PS.
664      */
665     if (client_id == TFM_SP_PS_TEST) {
666         client_id = TFM_SP_PS;
667     }
668 #endif
669 
670     /* Validate and read file info */
671     status = get_file_info(uid, client_id);
672     if (status != PSA_SUCCESS) {
673         return status;
674     }
675 
676     /* If the object exists and has the write once flag set, then it
677      * cannot be deleted.
678      */
679     if (g_file_info.flags & PSA_STORAGE_FLAG_WRITE_ONCE) {
680         return PSA_ERROR_NOT_PERMITTED;
681     }
682 
683     /* Delete old file from the persistent area */
684     return its_flash_fs_file_delete(get_fs_ctx(client_id), g_fid);
685 }
686