TF-M Reference Manual  1.2.0
TrustedFirmware-M
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
tfm_ps_req_mngr.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 
8 #include "tfm_ps_req_mngr.h"
9 
10 #include <stdbool.h>
11 #include <stdint.h>
12 
13 #include "psa/protected_storage.h"
14 #include "tfm_secure_api.h"
15 #include "tfm_api.h"
16 #include "tfm_protected_storage.h"
17 #ifdef TFM_PSA_API
18 #include "psa/service.h"
20 #include "flash_layout.h"
21 #endif
22 
23 #ifndef TFM_PSA_API
24 #include "tfm_memory_utils.h"
25 
26 static void *p_data;
27 
28 /*
29  * \brief Indicates whether PS has been initialised.
30  */
31 static bool ps_is_init = false;
32 
33 /*
34  * \brief Initialises PS, if not already initialised.
35  *
36  * \note In library mode, initialisation is delayed until the first secure
37  * function call, as calls to the Crypto service are required for
38  * initialisation.
39  *
40  * \return PSA_SUCCESS if PS is initialised, PSA_ERROR_GENERIC_ERROR
41  * otherwise.
42  */
43 static psa_status_t ps_check_init(void)
44 {
45  if (!ps_is_init) {
46  if (tfm_ps_init() != PSA_SUCCESS) {
48  }
49  ps_is_init = true;
50  }
51 
52  return PSA_SUCCESS;
53 }
54 
55 psa_status_t tfm_ps_set_req(psa_invec *in_vec, size_t in_len,
56  psa_outvec *out_vec, size_t out_len)
57 {
59  uint32_t data_length;
60  int32_t client_id;
61  int32_t status;
62  psa_storage_create_flags_t create_flags;
63 
64  if (ps_check_init() != PSA_SUCCESS) {
66  }
67 
68  if ((in_len != 3) || (out_len != 0)) {
69  /* The number of arguments are incorrect */
71  }
72 
73  if (in_vec[0].len != sizeof(psa_storage_uid_t)) {
74  /* The input argument size is incorrect */
76  }
77 
78  uid = *((psa_storage_uid_t *)in_vec[0].base);
79 
80  p_data = (void *)in_vec[1].base;
81  data_length = in_vec[1].len;
82 
83  if (in_vec[2].len != sizeof(psa_storage_create_flags_t)) {
84  /* The input argument size is incorrect */
86  }
87 
88  create_flags = *(psa_storage_create_flags_t *)in_vec[2].base;
89 
90  /* Get the caller's client ID */
91  status = tfm_core_get_caller_client_id(&client_id);
92  if (status != (int32_t)TFM_SUCCESS) {
94  }
95 
96  return tfm_ps_set(client_id, uid, data_length, create_flags);
97 }
98 
99 psa_status_t tfm_ps_get_req(psa_invec *in_vec, size_t in_len,
100  psa_outvec *out_vec, size_t out_len)
101 {
102  uint32_t data_offset;
103  uint32_t data_size;
104  int32_t client_id;
105  psa_storage_uid_t uid;
106  int32_t status;
107  size_t *p_data_length;
108 
109  if (ps_check_init() != PSA_SUCCESS) {
111  }
112 
113  if ((in_len != 2) || (out_len != 1)) {
114  /* The number of arguments are incorrect */
116  }
117 
118  if (in_vec[0].len != sizeof(psa_storage_uid_t)) {
119  /* The input argument size is incorrect */
121  }
122 
123  uid = *((psa_storage_uid_t *)in_vec[0].base);
124 
125  if (in_vec[1].len != sizeof(data_offset)) {
126  /* The input argument size is incorrect */
128  }
129 
130  data_offset = *(uint32_t *)in_vec[1].base;
131 
132  p_data = (void *)out_vec[0].base;
133  data_size = out_vec[0].len;
134  p_data_length = &out_vec[0].len;
135 
136  /* Get the caller's client ID */
137  status = tfm_core_get_caller_client_id(&client_id);
138  if (status != (int32_t)TFM_SUCCESS) {
140  }
141 
142  return tfm_ps_get(client_id, uid, data_offset, data_size, p_data_length);
143 
144 }
145 
147  psa_outvec *out_vec, size_t out_len)
148 {
149  int32_t client_id;
150  psa_storage_uid_t uid;
151  struct psa_storage_info_t *p_info;
152  int32_t tfm_status;
153 
154  if (ps_check_init() != PSA_SUCCESS) {
156  }
157 
158  if ((in_len != 1) || (out_len != 1)) {
159  /* The number of arguments are incorrect */
161  }
162 
163  if (in_vec[0].len != sizeof(psa_storage_uid_t)) {
164  /* The input argument size is incorrect */
166  }
167 
168  uid = *((psa_storage_uid_t *)in_vec[0].base);
169 
170  if (out_vec[0].len != sizeof(struct psa_storage_info_t)) {
171  /* The output argument size is incorrect */
173  }
174 
175  p_info = (struct psa_storage_info_t *)out_vec[0].base;
176 
177  /* Get the caller's client ID */
178  tfm_status = tfm_core_get_caller_client_id(&client_id);
179  if (tfm_status != (int32_t)TFM_SUCCESS) {
181  }
182 
183  return tfm_ps_get_info(client_id, uid, p_info);
184 }
185 
186 psa_status_t tfm_ps_remove_req(psa_invec *in_vec, size_t in_len,
187  psa_outvec *out_vec, size_t out_len)
188 {
189  int32_t client_id;
190  psa_storage_uid_t uid;
191  int32_t tfm_status;
192 
193  if (ps_check_init() != PSA_SUCCESS) {
195  }
196 
197  if ((in_len != 1) ||
198  (in_vec[0].len != sizeof(psa_storage_uid_t)) ||
199  (out_len != 0)) {
200  /* The number of arguments/output argument size are incorrect */
202  }
203 
204  uid = *((psa_storage_uid_t *)in_vec[0].base);
205 
206  /* Get the caller's client ID */
207  tfm_status = tfm_core_get_caller_client_id(&client_id);
208  if (tfm_status != (int32_t)TFM_SUCCESS) {
210  }
211 
212  return tfm_ps_remove(client_id, uid);
213 }
214 
216  psa_outvec *out_vec, size_t out_len)
217 {
218  uint32_t *support_flags;
219 
220  (void)in_vec;
221 
222  if (ps_check_init() != PSA_SUCCESS) {
224  }
225 
226  if ((in_len != 0) || (out_len != 1)) {
227  /* The number of arguments are incorrect */
229  }
230 
231  if (out_vec[0].len != sizeof(*support_flags)) {
232  /* The output argument size is incorrect */
234  }
235 
236  support_flags = (uint32_t *)out_vec[0].base;
237 
238  *support_flags = tfm_ps_get_support();
239 
240  return PSA_SUCCESS;
241 }
242 
243 #else /* !defined(TFM_PSA_API) */
244 typedef psa_status_t (*ps_func_t)(void);
245 static psa_msg_t msg;
246 
247 static psa_status_t tfm_ps_set_ipc(void)
248 {
249  psa_storage_uid_t uid;
250  int32_t client_id;
251  psa_storage_create_flags_t create_flags;
252  size_t num = 0;
253 
254  client_id = msg.client_id;
255 
256  if (msg.in_size[0] != sizeof(psa_storage_uid_t) ||
257  msg.in_size[2] != sizeof(psa_storage_create_flags_t)) {
258  /* The size of one of the arguments is incorrect */
260  }
261 
262  num = psa_read(msg.handle, 0, &uid, msg.in_size[0]);
263  if (num != msg.in_size[0]) {
265  }
266 
267  num = psa_read(msg.handle, 2, &create_flags, msg.in_size[2]);
268  if (num != msg.in_size[2]) {
270  }
271 
272  return tfm_ps_set(client_id, uid, msg.in_size[1], create_flags);
273 }
274 
275 static psa_status_t tfm_ps_get_ipc(void)
276 {
277  psa_storage_uid_t uid;
278  uint32_t data_offset;
279  size_t num = 0;
280  size_t p_data_length;
281 
282  if (msg.in_size[0] != sizeof(psa_storage_uid_t) ||
283  msg.in_size[1] != sizeof(uint32_t)) {
284  /* The size of one of the arguments is incorrect */
286  }
287 
288  num = psa_read(msg.handle, 0, &uid, msg.in_size[0]);
289  if (num != msg.in_size[0]) {
291  }
292 
293  num = psa_read(msg.handle, 1, &data_offset, msg.in_size[1]);
294  if (num != msg.in_size[1]) {
296  }
297 
298  return tfm_ps_get(msg.client_id, uid, data_offset, msg.out_size[0],
299  &p_data_length);
300 }
301 
302 static psa_status_t tfm_ps_get_info_ipc(void)
303 {
304  psa_storage_uid_t uid;
305 
306  struct psa_storage_info_t info;
307  size_t num = 0;
308  psa_status_t status;
309 
310  if (msg.in_size[0] != sizeof(psa_storage_uid_t) ||
311  msg.out_size[0] != sizeof(struct psa_storage_info_t)) {
312  /* The size of one of the arguments is incorrect */
314  }
315 
316  num = psa_read(msg.handle, 0, &uid, msg.in_size[0]);
317  if (num != msg.in_size[0]) {
319  }
320 
321  status = tfm_ps_get_info(msg.client_id, uid, &info);
322 
323  if (status == PSA_SUCCESS) {
324  psa_write(msg.handle, 0, &info, msg.out_size[0]);
325  }
326  return status;
327 }
328 
329 static psa_status_t tfm_ps_remove_ipc(void)
330 {
331  psa_storage_uid_t uid;
332  size_t num = 0;
333 
334  if (msg.in_size[0] != sizeof(psa_storage_uid_t)) {
335  /* The size of one of the arguments is incorrect */
337  }
338 
339  num = psa_read(msg.handle, 0, &uid, msg.in_size[0]);
340  if (num != msg.in_size[0]) {
342  }
343 
344  return tfm_ps_remove(msg.client_id, uid);
345 }
346 
347 static psa_status_t tfm_ps_get_support_ipc(void)
348 {
349  size_t out_size;
350  uint32_t support_flags;
351 
352  out_size = msg.out_size[0];
353  if (out_size != sizeof(support_flags)) {
354  /* The output argument size is incorrect */
356  }
357 
358  support_flags = tfm_ps_get_support();
359  psa_write(msg.handle, 0, &support_flags, out_size);
360  return PSA_SUCCESS;
361 }
362 
363 /*
364  * Fixme: Temporarily implement abort as infinite loop,
365  * will replace it later.
366  */
367 static void tfm_abort(void)
368 {
369  while (1)
370  ;
371 }
372 
373 static void ps_signal_handle(psa_signal_t signal, ps_func_t pfn)
374 {
375  psa_status_t status;
376 
377  status = psa_get(signal, &msg);
378  switch (msg.type) {
379  case PSA_IPC_CONNECT:
380  psa_reply(msg.handle, PSA_SUCCESS);
381  break;
382  case PSA_IPC_CALL:
383  status = pfn();
384  psa_reply(msg.handle, status);
385  break;
386  case PSA_IPC_DISCONNECT:
387  psa_reply(msg.handle, PSA_SUCCESS);
388  break;
389  default:
390  tfm_abort();
391  }
392 }
393 #endif /* !defined(TFM_PSA_API) */
394 
396 {
397 #ifdef TFM_PSA_API
398  psa_signal_t signals = 0;
399 
400  if (tfm_ps_init() != PSA_SUCCESS) {
401  tfm_abort();
402  }
403 
404  while (1) {
405  signals = psa_wait(PSA_WAIT_ANY, PSA_BLOCK);
406  if (signals & TFM_PS_SET_SIGNAL) {
407  ps_signal_handle(TFM_PS_SET_SIGNAL, tfm_ps_set_ipc);
408  } else if (signals & TFM_PS_GET_SIGNAL) {
409  ps_signal_handle(TFM_PS_GET_SIGNAL, tfm_ps_get_ipc);
410  } else if (signals & TFM_PS_GET_INFO_SIGNAL) {
411  ps_signal_handle(TFM_PS_GET_INFO_SIGNAL, tfm_ps_get_info_ipc);
412  } else if (signals & TFM_PS_REMOVE_SIGNAL) {
413  ps_signal_handle(TFM_PS_REMOVE_SIGNAL, tfm_ps_remove_ipc);
414  } else if (signals & TFM_PS_GET_SUPPORT_SIGNAL) {
415  ps_signal_handle(TFM_PS_GET_SUPPORT_SIGNAL,
416  tfm_ps_get_support_ipc);
417  } else {
418  tfm_abort();
419  }
420  }
421 #else
422  /* In library mode, initialisation is delayed until the first secure
423  * function call, as calls to the Crypto service are required for
424  * initialisation.
425  */
426  return PSA_SUCCESS;
427 #endif
428 }
429 
430 psa_status_t ps_req_mngr_read_asset_data(uint8_t *out_data, uint32_t size)
431 {
432 #ifdef TFM_PSA_API
433  size_t num = 0;
434 
435  num = psa_read(msg.handle, 1, out_data, size);
436  if (num != size) {
438  }
439 #else /* TFM_PSA_API */
440  (void)tfm_memcpy(out_data, p_data, size);
441 #endif
442  return PSA_SUCCESS;
443 }
444 
445 void ps_req_mngr_write_asset_data(const uint8_t *in_data,
446  uint32_t size)
447 {
448 #ifdef TFM_PSA_API
449  psa_write(msg.handle, 0, in_data, size);
450 #else /* TFM_PSA_API */
451  (void)tfm_memcpy(p_data, in_data, size);
452 #endif
453 }
psa_status_t tfm_ps_get_support_req(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len)
Handles the get support request.
uint32_t psa_signal_t
Definition: service.h:50
#define PSA_BLOCK
Definition: service.h:31
#define PSA_SUCCESS
Definition: crypto_values.h:35
psa_status_t tfm_ps_req_mngr_init(void)
#define TFM_PS_SET_SIGNAL
size_t len
Definition: client.h:68
psa_status_t tfm_ps_remove_req(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len)
Handles the remove request.
uint32_t tfm_ps_get_support(void)
Gets a bitmask with flags set for all of the optional features supported by the implementation.
int32_t client_id
Definition: service.h:64
#define TFM_PS_GET_INFO_SIGNAL
size_t psa_read(psa_handle_t msg_handle, uint32_t invec_idx, void *buffer, size_t num_bytes)
Read a message parameter or part of a message parameter from a client input vector.
Definition: psa_service.c:40
#define PSA_ERROR_GENERIC_ERROR
Definition: crypto_values.h:43
#define PSA_IPC_DISCONNECT
Definition: service.h:47
psa_status_t ps_req_mngr_read_asset_data(uint8_t *out_data, uint32_t size)
Writes the asset data of a client iovec onto an output buffer.
#define TFM_PS_GET_SUPPORT_SIGNAL
#define TFM_PS_GET_SIGNAL
#define PSA_ERROR_PROGRAMMER_ERROR
Definition: error.h:32
#define PSA_WAIT_ANY
Definition: service.h:36
psa_status_t 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)
Gets the asset data for the provided uid.
void ps_req_mngr_write_asset_data(const uint8_t *in_data, uint32_t size)
Takes an input buffer containing asset data and writes its contents to the client iovec...
psa_status_t tfm_ps_get_req(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len)
Handles the get request.
int32_t tfm_core_get_caller_client_id(int32_t *caller_client_id)
Definition: arch.c:28
void psa_write(psa_handle_t msg_handle, uint32_t outvec_idx, const void *buffer, size_t num_bytes)
Write a message response to a client output vector.
Definition: psa_service.c:58
psa_status_t tfm_ps_init(void)
Initializes the protected storage system.
void psa_reply(psa_handle_t msg_handle, psa_status_t status)
Complete handling of a specific message and unblock the client.
Definition: psa_service.c:67
psa_signal_t psa_wait(psa_signal_t signal_mask, uint32_t timeout)
Return the Secure Partition interrupt signals that have been asserted from a subset of signals provid...
Definition: psa_service.c:15
#define TFM_PS_REMOVE_SIGNAL
size_t len
Definition: client.h:76
__STATIC_INLINE void * tfm_memcpy(void *dest, const void *src, size_t num)
psa_status_t tfm_ps_set(int32_t client_id, psa_storage_uid_t uid, uint32_t data_length, psa_storage_create_flags_t create_flags)
Creates a new or modifies an existing asset.
psa_status_t tfm_ps_get_info(int32_t client_id, psa_storage_uid_t uid, struct psa_storage_info_t *p_info)
Gets the metadata for the provided uid.
uint64_t psa_storage_uid_t
#define PSA_IPC_CONNECT
Definition: service.h:45
psa_status_t tfm_ps_set_req(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len)
Handles the set request.
psa_status_t tfm_ps_get_info_req(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len)
Handles the get info request.
#define PSA_IPC_CALL
Definition: client.h:59
uint32_t psa_storage_create_flags_t
psa_status_t tfm_ps_remove(int32_t client_id, psa_storage_uid_t uid)
Removes the provided uid and its associated data from storage.
psa_status_t psa_get(psa_signal_t signal, psa_msg_t *msg)
Retrieve the message which corresponds to a given RoT Service signal and remove the message from the ...
Definition: psa_service.c:24
int32_t psa_status_t
Function return status.
Definition: crypto_types.h:43