1 /* Copyright (c) 2024 Nordic Semiconductor
2  * SPDX-License-Identifier: Apache-2.0
3  */
4 #ifndef PSA_PROTECTED_STORAGE_H
5 #define PSA_PROTECTED_STORAGE_H
6 
7 /** @file psa/protected_storage.h The PSA Protected Storage (PS) API.
8  * @ingroup psa_secure_storage
9  * For more information on the PS, see [The Protected Storage API](https://arm-software.github.io/psa-api/storage/1.0/overview/architecture.html#the-protected-storage-api).
10  */
11 
12 /** @cond INTERNAL_HIDDEN */
13 #ifdef CONFIG_SECURE_STORAGE_PS_IMPLEMENTATION_ITS
14 #include "../internal/zephyr/secure_storage/its.h"
15 #define ITS_UID (secure_storage_its_uid_t){.uid = uid, \
16 					   .caller_id = SECURE_STORAGE_ITS_CALLER_PSA_PS}
17 #else
18 #include "../internal/zephyr/secure_storage/ps.h"
19 #endif
20 /** @endcond */
21 
22 #include <psa/storage_common.h>
23 
24 #define PSA_PS_API_VERSION_MAJOR 1
25 #define PSA_PS_API_VERSION_MINOR 0
26 
27 /**
28  * @brief Creates a new or modifies an existing entry.
29  *
30  * @param uid          The identifier of the data. Must be nonzero.
31  * @param data_length  The size in bytes of the data in `p_data` to store.
32  * @param p_data       A buffer containing the data to store.
33  * @param create_flags Flags indicating the properties of the entry.
34  *
35  * @retval PSA_SUCCESS                    The operation completed successfully.
36  * @retval PSA_ERROR_GENERIC_ERROR        An unspecified internal failure happened.
37  * @retval PSA_ERROR_NOT_PERMITTED        An entry associated with the provided `uid` already
38  *                                        exists and was created with `PSA_STORAGE_FLAG_WRITE_ONCE`.
39  * @retval PSA_ERROR_NOT_SUPPORTED        One or more of the flags provided in `create_flags`
40  *                                        are not supported or invalid.
41  * @retval PSA_ERROR_INVALID_ARGUMENT     One or more arguments other than `create_flags` are
42  *                                        invalid.
43  * @retval PSA_ERROR_INSUFFICIENT_STORAGE There is insufficient space on the storage medium.
44  * @retval PSA_ERROR_STORAGE_FAILURE      The physical storage has failed (fatal error).
45  */
46 /** @cond INTERNAL_HIDDEN */
47 static ALWAYS_INLINE
48 /** @endcond  */
psa_ps_set(psa_storage_uid_t uid,size_t data_length,const void * p_data,psa_storage_create_flags_t create_flags)49 psa_status_t psa_ps_set(psa_storage_uid_t uid, size_t data_length,
50 			const void *p_data, psa_storage_create_flags_t create_flags)
51 {
52 #ifdef CONFIG_SECURE_STORAGE_PS_IMPLEMENTATION_ITS
53 	return secure_storage_its_set(ITS_UID, data_length, p_data, create_flags);
54 #else
55 	return secure_storage_ps_set(uid, data_length, p_data, create_flags);
56 #endif
57 }
58 
59 /**
60  * @brief Retrieves data associated with the provided `uid`.
61  *
62  * @param[in]  uid           The identifier of the data.
63  * @param[in]  data_offset   The offset, in bytes, from which to start reading the data.
64  * @param[in]  data_size     The number of bytes to read.
65  * @param[out] p_data        The buffer where the data will be placed on success.
66  *                           Must be at least `data_size` bytes long.
67  * @param[out] p_data_length On success, the number of bytes placed in `p_data`.
68  *
69  * @retval PSA_SUCCESS                 The operation completed successfully.
70  * @retval PSA_ERROR_GENERIC_ERROR     An unspecified internal failure happened.
71  * @retval PSA_ERROR_INVALID_ARGUMENT  One or more of the arguments are invalid. This can also
72  *                                     happen if `data_offset` is larger than the size of the data
73  *                                     associated with `uid`.
74  * @retval PSA_ERROR_DOES_NOT_EXIST    The provided `uid` was not found in the storage.
75  * @retval PSA_ERROR_STORAGE_FAILURE   The physical storage has failed (fatal error).
76  * @retval PSA_ERROR_INVALID_SIGNATURE The data associated with `uid` failed authentication.
77  * @retval PSA_ERROR_DATA_CORRUPT      The data associated with `uid` is corrupt.
78  */
79 /** @cond INTERNAL_HIDDEN */
80 static ALWAYS_INLINE
81 /** @endcond  */
psa_ps_get(psa_storage_uid_t uid,size_t data_offset,size_t data_size,void * p_data,size_t * p_data_length)82 psa_status_t psa_ps_get(psa_storage_uid_t uid, size_t data_offset,
83 			size_t data_size, void *p_data, size_t *p_data_length)
84 {
85 #ifdef CONFIG_SECURE_STORAGE_PS_IMPLEMENTATION_ITS
86 	return secure_storage_its_get(ITS_UID, data_offset, data_size, p_data, p_data_length);
87 #else
88 	return secure_storage_ps_get(uid, data_offset, data_size, p_data, p_data_length);
89 #endif
90 }
91 
92 /**
93  * @brief Retrieves the metadata of a given entry.
94  *
95  * @param[in]  uid    The identifier of the entry.
96  * @param[out] p_info A pointer to a `psa_storage_info_t` struct that will
97  *                    be populated with the metadata on success.
98  *
99  * @retval PSA_SUCCESS                 The operation completed successfully.
100  * @retval PSA_ERROR_GENERIC_ERROR     An unspecified internal failure happened.
101  * @retval PSA_ERROR_INVALID_ARGUMENT  One or more of the arguments are invalid.
102  * @retval PSA_ERROR_DOES_NOT_EXIST    The provided `uid` was not found in the storage.
103  * @retval PSA_ERROR_STORAGE_FAILURE   The physical storage has failed (fatal error).
104  * @retval PSA_ERROR_INVALID_SIGNATURE The data associated with `uid` failed authentication.
105  * @retval PSA_ERROR_DATA_CORRUPT      The data associated with `uid` is corrupt.
106  */
107 /** @cond INTERNAL_HIDDEN */
108 static ALWAYS_INLINE
109 /** @endcond  */
psa_ps_get_info(psa_storage_uid_t uid,struct psa_storage_info_t * p_info)110 psa_status_t psa_ps_get_info(psa_storage_uid_t uid, struct psa_storage_info_t *p_info)
111 {
112 #ifdef CONFIG_SECURE_STORAGE_PS_IMPLEMENTATION_ITS
113 	return secure_storage_its_get_info(ITS_UID, p_info);
114 #else
115 	return secure_storage_ps_get_info(uid, p_info);
116 #endif
117 }
118 
119 /**
120  * @brief Removes the provided `uid` and its associated data.
121  *
122  * Deletes previously stored data and any associated metadata, including rollback protection data.
123  *
124  * @param uid The identifier of the entry to remove.
125  *
126  * @return A status indicating the success/failure of the operation
127  *
128  * @retval PSA_SUCCESS                The operation completed successfully.
129  * @retval PSA_ERROR_GENERIC_ERROR    An unspecified internal failure happened.
130  * @retval PSA_ERROR_NOT_PERMITTED    The entry was created with `PSA_STORAGE_FLAG_WRITE_ONCE`.
131  * @retval PSA_ERROR_INVALID_ARGUMENT `uid` is invalid.
132  * @retval PSA_ERROR_DOES_NOT_EXIST   The provided `uid` was not found in the storage.
133  * @retval PSA_ERROR_STORAGE_FAILURE  The physical storage has failed (fatal error).
134  */
135 /** @cond INTERNAL_HIDDEN */
136 static ALWAYS_INLINE
137 /** @endcond  */
psa_ps_remove(psa_storage_uid_t uid)138 psa_status_t psa_ps_remove(psa_storage_uid_t uid)
139 {
140 #ifdef CONFIG_SECURE_STORAGE_PS_IMPLEMENTATION_ITS
141 	return secure_storage_its_remove(ITS_UID);
142 #else
143 	return secure_storage_ps_remove(uid);
144 #endif
145 }
146 
147 /**
148  * @brief Reserves storage for the provided `uid`.
149  *
150  * Upon success, the capacity of the storage for `uid` will be `capacity`, and the size will be 0.
151  * It is only necessary to call this function for data that will be written with the
152  * @ref psa_ps_set_extended() function. If only the @ref psa_ps_set() function is used, calls to
153  * this function are redundant. This function cannot be used to replace or resize an existing entry.
154  *
155  * @param uid          The identifier of the entry to reserve storage for.
156  * @param capacity     The capacity, in bytes, to allocate.
157  * @param create_flags Flags indicating the properties of the entry.
158  *
159  * @retval PSA_SUCCESS                    The operation completed successfully.
160  * @retval PSA_ERROR_GENERIC_ERROR        An unspecified internal failure happened.
161  * @retval PSA_ERROR_NOT_SUPPORTED        The implementation doesn't support this function or one
162  *                                        or more of the flags provided in `create_flags` are not
163  *                                        supported or invalid.
164  * @retval PSA_ERROR_INVALID_ARGUMENT     `uid` is invalid.
165  * @retval PSA_ERROR_ALREADY_EXISTS       An entry with the provided `uid` already exists.
166  * @retval PSA_ERROR_INSUFFICIENT_STORAGE There is insufficient space on the storage medium.
167  * @retval PSA_ERROR_STORAGE_FAILURE      The physical storage has failed (fatal error).
168  */
169 /** @cond INTERNAL_HIDDEN */
170 static ALWAYS_INLINE
171 /** @endcond  */
psa_ps_create(psa_storage_uid_t uid,size_t capacity,psa_storage_create_flags_t create_flags)172 psa_status_t psa_ps_create(psa_storage_uid_t uid, size_t capacity,
173 			   psa_storage_create_flags_t create_flags)
174 {
175 #ifdef CONFIG_SECURE_STORAGE_PS_SUPPORTS_SET_EXTENDED
176 	return secure_storage_ps_create(uid, capacity, create_flags);
177 #else
178 	return PSA_ERROR_NOT_SUPPORTED;
179 #endif
180 }
181 
182 /**
183  * @brief Writes part of the data associated with the provided `uid`.
184  *
185  * Before calling this function, storage must have been reserved with a call to
186  * @ref psa_ps_create(). This function can also be used to overwrite data that was
187  * written with @ref psa_ps_set(). This function can overwrite existing data and/or extend
188  * it up to the capacity of the entry specified in @ref psa_ps_create(), but cannot create gaps.
189  *
190  * @param uid         The identifier of the entry to write.
191  * @param data_offset The offset, in bytes, from which to start writing the data.
192  *                    Can be at most the current size of the data.
193  * @param data_length The size in bytes of the data in `p_data` to write. `data_offset`
194  *                    + `data_length` can be at most the capacity of the entry.
195  * @param p_data      A buffer containing the data to write.
196  *
197  * @retval PSA_SUCCESS                 The operation completed successfully.
198  * @retval PSA_ERROR_GENERIC_ERROR     An unspecified internal failure happened.
199  * @retval PSA_ERROR_NOT_PERMITTED     The entry was created with `PSA_STORAGE_FLAG_WRITE_ONCE`.
200  * @retval PSA_ERROR_NOT_SUPPORTED     The implementation doesn't support this function.
201  * @retval PSA_ERROR_INVALID_ARGUMENT  One or more of the arguments are invalid.
202  * @retval PSA_ERROR_DOES_NOT_EXIST    The provided `uid` was not found in the storage.
203  * @retval PSA_ERROR_STORAGE_FAILURE   The physical storage has failed (fatal error).
204  * @retval PSA_ERROR_INVALID_SIGNATURE The data associated with `uid` failed authentication.
205  * @retval PSA_ERROR_DATA_CORRUPT      The data associated with `uid` is corrupt.
206  */
207 /** @cond INTERNAL_HIDDEN */
208 static ALWAYS_INLINE
209 /** @endcond  */
psa_ps_set_extended(psa_storage_uid_t uid,size_t data_offset,size_t data_length,const void * p_data)210 psa_status_t psa_ps_set_extended(psa_storage_uid_t uid, size_t data_offset,
211 				 size_t data_length, const void *p_data)
212 {
213 #ifdef CONFIG_SECURE_STORAGE_PS_SUPPORTS_SET_EXTENDED
214 	return secure_storage_ps_set_extended(uid, data_offset, data_length, p_data);
215 #else
216 	return PSA_ERROR_NOT_SUPPORTED;
217 #endif
218 }
219 
220 /**
221  * @brief Lists optional features.
222  *
223  * @return A bitmask with flags set for the optional features supported by the implementation.
224  *         Currently defined flags are limited to `PSA_STORAGE_SUPPORT_SET_EXTENDED`.
225  */
226 /** @cond INTERNAL_HIDDEN */
227 static ALWAYS_INLINE
228 /** @endcond  */
psa_ps_get_support(void)229 uint32_t psa_ps_get_support(void)
230 {
231 	uint32_t flags = 0;
232 
233 #ifdef CONFIG_SECURE_STORAGE_PS_SUPPORTS_SET_EXTENDED
234 	flags |= PSA_STORAGE_SUPPORT_SET_EXTENDED;
235 #endif
236 	return flags;
237 }
238 
239 #undef ITS_UID
240 
241 #endif
242