1 /*
2  * Copyright (c) 2019-2022, Arm Limited. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  *
6  */
7 
8 #include "config_ps.h"
9 #include "tfm_protected_storage.h"
10 #include "ps_object_system.h"
11 #include "tfm_ps_defs.h"
12 
tfm_ps_init(void)13 psa_status_t tfm_ps_init(void)
14 {
15     psa_status_t err;
16 
17     err = ps_system_prepare();
18 #if PS_CREATE_FLASH_LAYOUT
19     /* If PS_CREATE_FLASH_LAYOUT is set to 1, it indicates that it is required to
20      * create a PS flash layout. PS service will generate an empty and valid
21      * PS flash layout to store assets. It will erase all data located in the
22      * assigned PS memory area before generating the PS layout.
23      * This flag is required to be set if the PS memory area is located in
24      * non-persistent memory.
25      * This flag can be set if the PS memory area is located in persistent
26      * memory without a previous valid PS flash layout in it. That is the case
27      * when it is the first time in the device life that the PS service is
28      * executed.
29      */
30     if (err != PSA_SUCCESS) {
31         /* Remove all data in the PS memory area and create a valid PS flash
32          * layout in that area.
33          */
34         err = ps_system_wipe_all();
35         if (err != PSA_SUCCESS) {
36             return err;
37         }
38 
39         /* Attempt to initialise again */
40         err = ps_system_prepare();
41     }
42 #endif /* PS_CREATE_FLASH_LAYOUT */
43 
44     return err;
45 }
46 
tfm_ps_set(int32_t client_id,psa_storage_uid_t uid,uint32_t data_length,psa_storage_create_flags_t create_flags)47 psa_status_t tfm_ps_set(int32_t client_id,
48                         psa_storage_uid_t uid,
49                         uint32_t data_length,
50                         psa_storage_create_flags_t create_flags)
51 {
52     /* Check that the UID is valid */
53     if (uid == TFM_PS_INVALID_UID) {
54         return PSA_ERROR_INVALID_ARGUMENT;
55     }
56 
57     /* Check that the create_flags does not contain any unsupported flags */
58     if (create_flags & ~(PSA_STORAGE_FLAG_WRITE_ONCE |
59                          PSA_STORAGE_FLAG_NO_CONFIDENTIALITY |
60                          PSA_STORAGE_FLAG_NO_REPLAY_PROTECTION)) {
61         return PSA_ERROR_NOT_SUPPORTED;
62     }
63 
64     /* Create the object in the object system */
65     return ps_object_create(uid, client_id, create_flags, data_length);
66 }
67 
tfm_ps_get(int32_t client_id,psa_storage_uid_t uid,uint32_t data_offset,uint32_t data_size,size_t * p_data_length)68 psa_status_t tfm_ps_get(int32_t client_id,
69                         psa_storage_uid_t uid,
70                         uint32_t data_offset,
71                         uint32_t data_size,
72                         size_t *p_data_length)
73 {
74     /* Check that the UID is valid */
75     if (uid == TFM_PS_INVALID_UID) {
76         return PSA_ERROR_INVALID_ARGUMENT;
77     }
78 
79     /* Read the object data from the object system */
80     return ps_object_read(uid, client_id, data_offset, data_size,
81                           p_data_length);
82 }
83 
tfm_ps_get_info(int32_t client_id,psa_storage_uid_t uid,struct psa_storage_info_t * p_info)84 psa_status_t tfm_ps_get_info(int32_t client_id, psa_storage_uid_t uid,
85                              struct psa_storage_info_t *p_info)
86 {
87     /* Check that the UID is valid */
88     if (uid == TFM_PS_INVALID_UID) {
89         return PSA_ERROR_INVALID_ARGUMENT;
90     }
91 
92     /* Get the info struct data from the object system */
93     return ps_object_get_info(uid, client_id, p_info);
94 }
95 
tfm_ps_remove(int32_t client_id,psa_storage_uid_t uid)96 psa_status_t tfm_ps_remove(int32_t client_id, psa_storage_uid_t uid)
97 {
98     psa_status_t err;
99 
100     /* Check that the UID is valid */
101     if (uid == TFM_PS_INVALID_UID) {
102         return PSA_ERROR_INVALID_ARGUMENT;
103     }
104 
105     /* Delete the object from the object system */
106     err = ps_object_delete(uid, client_id);
107 
108     /* PSA_ERROR_INVALID_SIGNATURE is not supported by psa_ps_remove
109      * specification. So, this function returns TFM_PS_ERR_OPERATION_FAILED
110      * instead.
111      */
112     if (err == PSA_ERROR_INVALID_SIGNATURE) {
113         return PSA_ERROR_GENERIC_ERROR;
114     }
115 
116     return err;
117 }
118 
tfm_ps_get_support(void)119 uint32_t tfm_ps_get_support(void)
120 {
121     /*
122      * This function returns a bitmask with flags set for all of the optional
123      * features supported by the PS service implementation.
124      *
125      * PS service does not support the optional extended PSA PS API yet.
126      */
127 
128     return 0;
129 }
130