TF-M Reference Manual  1.2.0
TrustedFirmware-M
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
tfm_ss_core_test_2.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2017-2020, Arm Limited. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  *
6  */
7 
8 #include <stddef.h>
9 #include "core_test_defs.h"
10 #include "tfm_ss_core_test_2.h"
11 #include "tfm_api.h"
12 #include "tfm_secure_api.h"
13 #include "psa/service.h"
14 #include "psa_manifest/pid.h"
16 
17 #define INVALID_NS_CLIENT_ID 0x49abcdef
18 #define INVERT_BUFFER_SIZE (16*4)
19 
20 #ifndef TFM_PSA_API
21 /* Don't initialise caller_partition_id_zi and expect it to be linked in the
22  * zero-initialised data area
23  */
24 static int32_t caller_client_id_zi;
25 
26 /* Initialise caller_partition_id_rw and expect it to be linked in the
27  * read-write data area
28  */
29 static int32_t caller_client_id_rw = INVALID_NS_CLIENT_ID;
30 
31 static int32_t* invalid_addresses [] = {(int32_t*)0x0, (int32_t*)0xFFF12000};
32 #endif /* !defined(TFM_PSA_API) */
33 
34 /* structures for secure IRQ testing */
35 static struct irq_test_execution_data_t *current_execution_data;
36 
38  size_t in_len,
39  struct psa_outvec *out_vec,
40  size_t out_len)
41 {
42  /* This function doesn't do any sanity check on the input parameters, nor
43  * makes any expectation of them, always returns successfully, with a
44  * non-zero return value.
45  * This is to test the parameter sanitization mechanisms implemented in SPM,
46  * and the handling of non-zero success codes.
47  */
48 
50 }
51 
52 #ifndef TFM_PSA_API
54  size_t in_len,
55  struct psa_outvec *out_vec,
56  size_t out_len)
57 {
58  size_t i;
59  int32_t caller_client_id_stack = INVALID_NS_CLIENT_ID;
60  int32_t ret;
61 
62  caller_client_id_zi = INVALID_NS_CLIENT_ID;
63 
64  /* test with invalid output pointers */
65  for (i = 0; i < sizeof(invalid_addresses)/sizeof(invalid_addresses[0]); ++i)
66  {
67  ret = tfm_core_get_caller_client_id(invalid_addresses[i]);
68  if (ret != TFM_ERROR_INVALID_PARAMETER) {
70  }
71  }
72 
73  /* test with valid output pointers */
74  ret = tfm_core_get_caller_client_id(&caller_client_id_zi);
75  if (ret != TFM_SUCCESS || caller_client_id_zi != TFM_SP_CORE_TEST) {
77  }
78 
79  ret = tfm_core_get_caller_client_id(&caller_client_id_rw);
80  if (ret != TFM_SUCCESS || caller_client_id_rw != TFM_SP_CORE_TEST) {
82  }
83 
84  ret = tfm_core_get_caller_client_id(&caller_client_id_stack);
85  if (ret != TFM_SUCCESS ||
86  caller_client_id_stack != TFM_SP_CORE_TEST) {
88  }
89 
91 }
92 #endif /* !defined(TFM_PSA_API) */
93 
95  const uint8_t *inbuf,
96  uint8_t *outbuf,
97  size_t in_size,
98  size_t *out_size)
99 {
100  int j;
101 
102  if (in_size/2 > *out_size) {
104  }
105  for (j = 1; j < in_size; j += 2) {
106  outbuf[j/2] = inbuf[j];
107  }
108  *out_size = in_size/2;
109 
111 }
112 
114  struct psa_invec *in_vec, size_t in_len,
115  struct psa_outvec *out_vec, size_t out_len)
116 {
117  int i;
118  psa_status_t res;
119 
120  if (in_len != out_len) {
122  }
123  for (i = 0; i < in_len; ++i) {
125  in_vec[i].base, out_vec[i].base,
126  in_vec[i].len, &out_vec[i].len);
127  if (res < 0) {
128  return res;
129  }
130  }
132 }
133 
134 /* Invert function */
135 #define SFN_INVERT_MAX_LEN 128
136 static psa_status_t spm_core_test_2_sfn_invert_internal(uint32_t *in_ptr,
137  uint32_t *out_ptr,
138  int32_t *res_ptr,
139  int32_t len)
140 {
141  int32_t i;
142  static uint32_t invert_buffer[SFN_INVERT_MAX_LEN];
143 
144  *res_ptr = -1;
145 
146  if (len > SFN_INVERT_MAX_LEN) {
148  }
149 
150  for (i = 0; i < len; i++) {
151  invert_buffer[i] = in_ptr[i];
152  }
153  for (i = 0; i < len; i++) {
154  invert_buffer[i] = ~invert_buffer[i];
155  }
156  for (i = 0; i < len; i++) {
157  out_ptr[i] = invert_buffer[i];
158  }
159 
160  *res_ptr = 0;
162 }
163 
165  struct psa_invec *in_vec, size_t in_len,
166  struct psa_outvec *out_vec, size_t out_len)
167 {
168  int32_t len;
169  uint32_t *in_ptr;
170  uint32_t *out_ptr;
171  int32_t *res_ptr;
172 
173  if ((in_len != 1) || (out_len != 2)) {
175  }
176 
177  if ((out_vec[0].len < in_vec[0].len) || (in_vec[0].len%4 != 0) ||
178  (out_vec[1].len < sizeof(int32_t))) {
180  }
181 
182  len = in_vec[0].len / 4;
183 
184  in_ptr = (uint32_t *)in_vec[0].base;
185  out_ptr = (uint32_t *)out_vec[0].base;
186  res_ptr = (int32_t *)out_vec[1].base;
187 
188  return spm_core_test_2_sfn_invert_internal(in_ptr, out_ptr, res_ptr, len);
189 }
190 
191 static psa_status_t spm_core_test_2_prepare_test_scenario_internal(
192  enum irq_test_scenario_t irq_test_scenario,
193  struct irq_test_execution_data_t *execution_data)
194 {
195  current_execution_data = execution_data;
196 
197  switch (irq_test_scenario) {
200  case IRQ_TEST_SCENARIO_1:
201  case IRQ_TEST_SCENARIO_2:
202  case IRQ_TEST_SCENARIO_3:
203  case IRQ_TEST_SCENARIO_4:
204  case IRQ_TEST_SCENARIO_5:
205  /* No action is necessary*/
206  break;
207  default:
209  }
210 
212 }
213 
215  struct psa_invec *in_vec, size_t in_len,
216  struct psa_outvec *out_vec, size_t out_size)
217 {
218  if ((in_len != 2) ||
219  (in_vec[0].len != sizeof(uint32_t)) ||
220  (in_vec[1].len != sizeof(struct irq_test_execution_data_t *))) {
222  }
223 
224  enum irq_test_scenario_t irq_test_scenario =
225  (enum irq_test_scenario_t) *(uint32_t *)in_vec[0].base;
226 
227  struct irq_test_execution_data_t *execution_data =
228  *(struct irq_test_execution_data_t **)in_vec[1].base;
229 
230  return spm_core_test_2_prepare_test_scenario_internal(irq_test_scenario,
231  execution_data);
232 }
233 
234 static psa_status_t spm_core_test_2_execute_test_scenario_internal(
235  enum irq_test_scenario_t irq_test_scenario)
236 {
237  switch (irq_test_scenario) {
240  case IRQ_TEST_SCENARIO_1:
241  /* No action is necessary*/
242  break;
243  case IRQ_TEST_SCENARIO_2:
244  if (current_execution_data->timer0_triggered) {
246  }
247  while (!current_execution_data->timer0_triggered) {
248  ;
249  }
250  break;
251  case IRQ_TEST_SCENARIO_3:
252  case IRQ_TEST_SCENARIO_4:
253  /* No action is necessary*/
254  break;
255  case IRQ_TEST_SCENARIO_5:
256  if (current_execution_data->timer1_triggered) {
258  }
259  while (!current_execution_data->timer1_triggered) {
260  ;
261  }
262  break;
263  default:
265  }
266 
268 }
269 
271  struct psa_invec *in_vec, size_t in_len,
272  struct psa_outvec *out_vec, size_t out_size)
273 {
274  enum irq_test_scenario_t irq_test_scenario =
275  (enum irq_test_scenario_t) *(uint32_t *)in_vec[0].base;
276 
277  return spm_core_test_2_execute_test_scenario_internal(irq_test_scenario);
278 }
279 
280 
281 #ifdef TFM_PSA_API
282 
283 typedef psa_status_t (*core_test_2_func_t)(psa_msg_t *msg);
284 
285 static void core_test_2_signal_handle(psa_signal_t signal,
286  core_test_2_func_t pfn)
287 {
288  psa_msg_t msg;
289  psa_status_t status;
290 
291  status = psa_get(signal, &msg);
292  if (status) {
293  return;
294  }
295 
296  switch (msg.type) {
297  case PSA_IPC_CONNECT:
299  break;
300  case PSA_IPC_CALL:
301  status = pfn(&msg);
302  psa_reply(msg.handle, status);
303  break;
304  case PSA_IPC_DISCONNECT:
306  break;
307  default:
308  break;
309  }
310 }
311 
312 psa_status_t spm_core_test_2_wrap_slave_service(psa_msg_t *msg)
313 {
314  return spm_core_test_2_slave_service(NULL, 0, NULL, 0);
315 }
316 
317 psa_status_t spm_core_test_2_wrap_check_caller_client_id(psa_msg_t *msg)
318 {
320 }
321 
322 psa_status_t spm_core_test_2_wrap_get_every_second_byte(psa_msg_t *msg)
323 {
324  uint32_t inbuf[INVERT_BUFFER_SIZE/sizeof(uint32_t)] = {0};
325  uint32_t outbuf[INVERT_BUFFER_SIZE/sizeof(uint32_t)] = {0};
326 
327  int i;
328  size_t num;
329  size_t out_len;
330  psa_status_t res;
331 
332  for (i = 0; i < PSA_MAX_IOVEC; ++i) {
333  if (msg->in_size[i] > INVERT_BUFFER_SIZE) {
335  }
336 
337  if (msg->in_size[i] == 0) {
338  continue;
339  }
340 
341  num = psa_read(msg->handle, i, inbuf, msg->in_size[i]);
342  if (num != msg->in_size[i]) {
344  }
345 
346  out_len = msg->out_size[i];
347 
348  res = spm_core_test_2_get_every_second_byte_internal((uint8_t *)inbuf,
349  (uint8_t *)outbuf, msg->in_size[i], &out_len);
350  if (res < 0) {
351  return res;
352  }
353 
354  psa_write(msg->handle, i, outbuf, out_len);
355  }
357 }
358 
359 psa_status_t spm_core_test_2_wrap_sfn_invert(psa_msg_t *msg)
360 {
361  uint32_t inbuf[INVERT_BUFFER_SIZE/sizeof(uint32_t)] = {0};
362  uint32_t outbuf[INVERT_BUFFER_SIZE/sizeof(uint32_t)] = {0};
363  size_t num;
364  int32_t res_ptr;
365  psa_status_t ret;
366 
367  if ((msg->out_size[0] < msg->in_size[0]) ||
368  (msg->in_size[0] > INVERT_BUFFER_SIZE) ||
369  (msg->in_size[0]%4 != 0) ||
370  (msg->out_size[1] < sizeof(int32_t))) {
372  }
373 
374  num = psa_read(msg->handle, 0, inbuf, msg->in_size[0]);
375  if (num != msg->in_size[0]) {
377  }
378 
379  ret = spm_core_test_2_sfn_invert_internal(inbuf, outbuf,
380  &res_ptr, msg->in_size[0] / 4);
381  if (ret < 0) {
382  return ret;
383  }
384 
385  psa_write(msg->handle, 0, outbuf, msg->in_size[0]);
386  psa_write(msg->handle, 1, &res_ptr, sizeof(int32_t));
387 
388  return ret;
389 }
390 
391 psa_status_t spm_core_test_2_wrap_prepare_test_scenario(psa_msg_t *msg)
392 {
393  uint32_t irq_test_scenario;
394  struct irq_test_execution_data_t *execution_data;
395  size_t num;
396 
397  if ((msg->in_size[0] != sizeof(uint32_t)) ||
398  (msg->in_size[1] != sizeof(struct irq_test_execution_data_t*))) {
400  }
401 
402  num = psa_read(msg->handle, 0, &irq_test_scenario, sizeof(irq_test_scenario));
403  if (num != msg->in_size[0]) {
405  }
406 
407  num = psa_read(msg->handle, 1, &execution_data, sizeof(
408  struct irq_test_execution_data_t*));
409  if (num != msg->in_size[1]) {
411  }
412 
413  return spm_core_test_2_prepare_test_scenario_internal((enum irq_test_scenario_t)
414  irq_test_scenario,
415  execution_data);
416 }
417 
418 psa_status_t spm_core_test_2_wrap_execute_test_scenario(psa_msg_t *msg)
419 {
420  uint32_t irq_test_scenario;
421  size_t num;
422 
423  if (msg->in_size[0] != sizeof(uint32_t)) {
425  }
426 
427  num = psa_read(msg->handle, 0, &irq_test_scenario, sizeof(irq_test_scenario));
428  if (num != msg->in_size[0]) {
430  }
431 
432  return spm_core_test_2_execute_test_scenario_internal((enum irq_test_scenario_t)
433  irq_test_scenario);
434 }
435 
436 #endif /* defined(TFM_PSA_API) */
437 
438 /* FIXME: Add a testcase to test that a failed init makes the secure partition
439  * closed, and none of its functions can be called.
440  * A new test service for this purpose is to be added.
441  */
443 {
444 #ifdef TFM_PSA_API
445  psa_signal_t signals = 0;
446 
447  while (1) {
448  signals = psa_wait(PSA_WAIT_ANY, PSA_BLOCK);
449  if (signals & SPM_CORE_TEST_2_SLAVE_SERVICE_SIGNAL) {
450  core_test_2_signal_handle(SPM_CORE_TEST_2_SLAVE_SERVICE_SIGNAL,
451  spm_core_test_2_wrap_slave_service);
452  } else if (signals & SPM_CORE_TEST_2_CHECK_CALLER_CLIENT_ID_SIGNAL) {
453  core_test_2_signal_handle(
454  SPM_CORE_TEST_2_CHECK_CALLER_CLIENT_ID_SIGNAL,
455  spm_core_test_2_wrap_check_caller_client_id);
456  } else if (signals & SPM_CORE_TEST_2_GET_EVERY_SECOND_BYTE_SIGNAL) {
457  core_test_2_signal_handle(
458  SPM_CORE_TEST_2_GET_EVERY_SECOND_BYTE_SIGNAL,
459  spm_core_test_2_wrap_get_every_second_byte);
460  } else if (signals & SPM_CORE_TEST_2_INVERT_SIGNAL) {
461  core_test_2_signal_handle(SPM_CORE_TEST_2_INVERT_SIGNAL,
462  spm_core_test_2_wrap_sfn_invert);
463  } else if (signals & SPM_CORE_TEST_2_PREPARE_TEST_SCENARIO_SIGNAL) {
464  core_test_2_signal_handle(
465  SPM_CORE_TEST_2_PREPARE_TEST_SCENARIO_SIGNAL,
466  spm_core_test_2_wrap_prepare_test_scenario);
467  } else if (signals & SPM_CORE_TEST_2_EXECUTE_TEST_SCENARIO_SIGNAL) {
468  core_test_2_signal_handle(
469  SPM_CORE_TEST_2_EXECUTE_TEST_SCENARIO_SIGNAL,
470  spm_core_test_2_wrap_execute_test_scenario);
471  } else {
472  ; /* do nothing */
473  }
474  }
475 #else
477 #endif /* defined(TFM_PSA_API) */
478 }
#define INVALID_NS_CLIENT_ID
psa_status_t spm_core_test_2_execute_test_scenario(struct psa_invec *in_vec, size_t in_len, struct psa_outvec *out_vec, size_t out_size)
uint32_t psa_signal_t
Definition: service.h:50
psa_status_t spm_core_test_2_prepare_test_scenario(struct psa_invec *in_vec, size_t in_len, struct psa_outvec *out_vec, size_t out_size)
#define PSA_BLOCK
Definition: service.h:31
#define SPM_CORE_TEST_2_GET_EVERY_SECOND_BYTE_SIGNAL
int32_t type
Definition: service.h:56
#define PSA_SUCCESS
Definition: crypto_values.h:35
#define TFM_SP_CORE_TEST
Definition: pid.h:23
size_t len
Definition: client.h:68
volatile int32_t timer1_triggered
#define INVERT_BUFFER_SIZE
#define SPM_CORE_TEST_2_CHECK_CALLER_CLIENT_ID_SIGNAL
psa_status_t spm_core_test_2_get_every_second_byte(struct psa_invec *in_vec, size_t in_len, struct psa_outvec *out_vec, size_t out_len)
#define SPM_CORE_TEST_2_INVERT_SIGNAL
psa_status_t spm_core_test_2_sfn_invert(struct psa_invec *in_vec, size_t in_len, struct psa_outvec *out_vec, size_t out_len)
Bitwise inverts the buffer received as input.
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
psa_handle_t handle
Definition: service.h:61
#define PSA_MAX_IOVEC
Definition: client.h:54
irq_test_scenario_t
#define SFN_INVERT_MAX_LEN
#define PSA_IPC_DISCONNECT
Definition: service.h:47
psa_status_t spm_core_test_2_get_every_second_byte_internal(const uint8_t *inbuf, uint8_t *outbuf, size_t in_size, size_t *out_size)
#define PSA_WAIT_ANY
Definition: service.h:36
psa_status_t spm_core_test_2_check_caller_client_id(struct psa_invec *in_vec, size_t in_len, struct psa_outvec *out_vec, size_t out_len)
A minimal test secure function to be called from another partition.
size_t in_size[PSA_MAX_IOVEC]
Definition: service.h:70
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
#define SPM_CORE_TEST_2_EXECUTE_TEST_SCENARIO_SIGNAL
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 PSA_IPC_CONNECT
Definition: service.h:45
#define SPM_CORE_TEST_2_PREPARE_TEST_SCENARIO_SIGNAL
size_t out_size[PSA_MAX_IOVEC]
Definition: service.h:73
#define PSA_IPC_CALL
Definition: client.h:59
psa_status_t spm_core_test_2_slave_service(struct psa_invec *in_vec, size_t in_len, struct psa_outvec *out_vec, size_t out_len)
A minimal test service to be called from another service.
const void * base
Definition: client.h:67
psa_status_t core_test_2_init(void)
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
volatile int32_t timer0_triggered
#define SPM_CORE_TEST_2_SLAVE_SERVICE_SIGNAL