TF-M Reference Manual  1.2.0
TrustedFirmware-M
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
psa_ps_s_interface_testsuite.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 "ps_tests.h"
9 
10 #include <stdio.h>
11 
12 #include "s_test_helpers.h"
13 #include "tfm_memory_utils.h"
14 #include "psa/protected_storage.h"
15 #include "test_framework_helpers.h"
16 
17 /* Test UIDs */
18 #define WRITE_ONCE_UID 1U /* Cannot be modified or deleted once created */
19 #define TEST_UID_1 2U
20 #define TEST_UID_2 3U
21 #define TEST_UID_3 4U
22 
23 /* Invalid values */
24 #define INVALID_UID 0U
25 #define INVALID_DATA_LEN UINT32_MAX
26 #define INVALID_OFFSET UINT32_MAX
27 #define INVALID_FLAG (1U << 31)
28 #define INVALID_THREAD_NAME "Thread_INVALID"
29 
30 /* Write once data */
31 #define WRITE_ONCE_DATA "THE_FIVE_BOXING_WIZARDS_JUMP_QUICKLY"
32 #define WRITE_ONCE_DATA_SIZE (sizeof(WRITE_ONCE_DATA) - 1)
33 #define WRITE_ONCE_READ_DATA "############################################"
34 #define WRITE_ONCE_RESULT_DATA ("####" WRITE_ONCE_DATA "####")
35 
36 #define WRITE_DATA "THEQUICKBROWNFOXJUMPSOVERALAZYDOG"
37 #define WRITE_DATA_SIZE (sizeof(WRITE_DATA) - 1)
38 #define READ_DATA "_________________________________________"
39 #define RESULT_DATA ("____" WRITE_DATA "____")
40 #define OFFSET_READ_DATA "HEQUICKBROWNFOXJUMPSOVERALAZYDOG"
41 #define OFFSET_RESULT_DATA ("____" OFFSET_READ_DATA "_____")
42 
43 #define TEST_1022_CYCLES 3U
44 
45 static const uint8_t write_asset_data[PS_MAX_ASSET_SIZE] = {0xBF};
46 static uint8_t read_asset_data[PS_MAX_ASSET_SIZE] = {0};
47 static size_t read_asset_datal_len = 0;
48 
49 /* List of tests */
50 static void tfm_ps_test_2001(struct test_result_t *ret);
51 static void tfm_ps_test_2002(struct test_result_t *ret);
52 static void tfm_ps_test_2003(struct test_result_t *ret);
53 static void tfm_ps_test_2004(struct test_result_t *ret);
54 static void tfm_ps_test_2005(struct test_result_t *ret);
55 static void tfm_ps_test_2006(struct test_result_t *ret);
56 static void tfm_ps_test_2007(struct test_result_t *ret);
57 static void tfm_ps_test_2008(struct test_result_t *ret);
58 static void tfm_ps_test_2009(struct test_result_t *ret);
59 static void tfm_ps_test_2010(struct test_result_t *ret);
60 static void tfm_ps_test_2011(struct test_result_t *ret);
61 static void tfm_ps_test_2012(struct test_result_t *ret);
62 static void tfm_ps_test_2013(struct test_result_t *ret);
63 static void tfm_ps_test_2014(struct test_result_t *ret);
64 static void tfm_ps_test_2015(struct test_result_t *ret);
65 static void tfm_ps_test_2016(struct test_result_t *ret);
66 static void tfm_ps_test_2017(struct test_result_t *ret);
67 static void tfm_ps_test_2018(struct test_result_t *ret);
68 static void tfm_ps_test_2019(struct test_result_t *ret);
69 static void tfm_ps_test_2020(struct test_result_t *ret);
70 static void tfm_ps_test_2021(struct test_result_t *ret);
71 static void tfm_ps_test_2022(struct test_result_t *ret);
72 
73 static struct test_t psa_ps_s_tests[] = {
74  {&tfm_ps_test_2001, "TFM_PS_TEST_2001",
75  "Set interface"},
76  {&tfm_ps_test_2002, "TFM_PS_TEST_2002",
77  "Set interface with create flags"},
78  {&tfm_ps_test_2003, "TFM_PS_TEST_2003",
79  "Set interface with NULL data pointer"},
80  {&tfm_ps_test_2004, "TFM_PS_TEST_2004",
81  "Set interface with invalid data length"},
82  {&tfm_ps_test_2005, "TFM_PS_TEST_2005",
83  "Set interface with write once UID"},
84  {&tfm_ps_test_2006, "TFM_PS_TEST_2006",
85  "Get interface with valid data"},
86  {&tfm_ps_test_2007, "TFM_PS_TEST_2007",
87  "Get interface with zero data length"},
88  {&tfm_ps_test_2008, "TFM_PS_TEST_2008",
89  "Get interface with invalid UIDs"},
90  {&tfm_ps_test_2009, "TFM_PS_TEST_2009",
91  "Get interface with invalid data lengths and offsets"},
92  {&tfm_ps_test_2010, "TFM_PS_TEST_2010",
93  "Get interface with NULL data pointer"},
94  {&tfm_ps_test_2011, "TFM_PS_TEST_2011",
95  "Get info interface with write once UID"},
96  {&tfm_ps_test_2012, "TFM_PS_TEST_2012",
97  "Get info interface with valid UID"},
98  {&tfm_ps_test_2013, "TFM_PS_TEST_2013",
99  "Get info interface with invalid UIDs"},
100  {&tfm_ps_test_2014, "TFM_PS_TEST_2014",
101  "Get info interface with NULL info pointer"},
102  {&tfm_ps_test_2015, "TFM_PS_TEST_2015",
103  "Remove interface with valid UID"},
104  {&tfm_ps_test_2016, "TFM_PS_TEST_2016",
105  "Remove interface with write once UID"},
106  {&tfm_ps_test_2017, "TFM_PS_TEST_2017",
107  "Remove interface with invalid UID"},
108  {&tfm_ps_test_2018, "TFM_PS_TEST_2018",
109  "Block compaction after remove"},
110  {&tfm_ps_test_2019, "TFM_PS_TEST_2019",
111  "Multiple partial gets"},
112  {&tfm_ps_test_2020, "TFM_PS_TEST_2020",
113  "Multiple sets to same UID from same thread"},
114  {&tfm_ps_test_2021, "TFM_PS_TEST_2021",
115  "Get support interface"},
116  {&tfm_ps_test_2022, "TFM_PS_TEST_2022",
117  "Set, get and remove interface with different asset sizes"},
118 };
119 
121 {
122  uint32_t list_size;
123 
124  list_size = (sizeof(psa_ps_s_tests) / sizeof(psa_ps_s_tests[0]));
125 
126  set_testsuite("PSA protected storage S interface tests (TFM_PS_TEST_2XXX)",
127  psa_ps_s_tests, list_size, p_test_suite);
128 }
129 
135 static void tfm_ps_test_2001(struct test_result_t *ret)
136 {
137  psa_status_t status;
138  const psa_storage_uid_t uid = TEST_UID_1;
140  const uint32_t data_len = 0;
141  const uint8_t write_data[] = {0};
142 
143  /* Set with no data and no flags and a valid UID */
144  status = psa_ps_set(uid, data_len, write_data, flags);
145  if (status != PSA_SUCCESS) {
146  TEST_FAIL("Set should not fail with valid UID");
147  return;
148  }
149 
150  /* Attempt to set a second time */
151  status = psa_ps_set(uid, data_len, write_data, flags);
152  if (status != PSA_SUCCESS) {
153  TEST_FAIL("Set should not fail the second time with valid UID");
154  return;
155  }
156 
157  /* Set with an invalid UID */
158  status = psa_ps_set(INVALID_UID, data_len, write_data, flags);
159  if (status != PSA_ERROR_INVALID_ARGUMENT) {
160  TEST_FAIL("Set should not succeed with an invalid UID");
161  return;
162  }
163 
164  /* Call remove to clean up storage for the next test */
165  status = psa_ps_remove(uid);
166  if (status != PSA_SUCCESS) {
167  TEST_FAIL("Remove should not fail with valid UID");
168  return;
169  }
170 
171  ret->val = TEST_PASSED;
172 }
173 
180 static void tfm_ps_test_2002(struct test_result_t *ret)
181 {
182  psa_status_t status;
183  const psa_storage_uid_t uid = TEST_UID_2;
185  const uint32_t data_len = WRITE_DATA_SIZE;
186  const uint8_t write_data[] = WRITE_DATA;
187 
188  /* Set with no flags */
189  status = psa_ps_set(WRITE_ONCE_UID, data_len, write_data, flags);
190  if (status == PSA_SUCCESS) {
191  /* Set with valid flag: PSA_STORAGE_FLAG_WRITE_ONCE (with previously
192  * created UID)
193  * Note: Once created, WRITE_ONCE_UID cannot be deleted. It is reused
194  * across multiple tests.
195  */
198  if (status != PSA_SUCCESS) {
199  TEST_FAIL("Set should not fail with valid flags (existing UID)");
200  return;
201  }
202  } else if (status == PSA_ERROR_NOT_PERMITTED) {
203  /* The UID has already been created with the PSA_STORAGE_FLAG_WRITE_ONCE
204  * flag in a previous test run, so skip creating it again and emit a
205  * warning.
206  */
207  TEST_LOG("Note: The UID in this test has already been created with\r\n"
208  "the PSA_STORAGE_FLAG_WRITE_ONCE flag in a previous test\r\n"
209  "run. Wipe the storage area to run the full test.\r\n");
210  } else {
211  TEST_FAIL("Set should not fail with no flags");
212  return;
213  }
214 
215  /* Set with invalid flags */
216  status = psa_ps_set(uid, data_len, write_data, INVALID_FLAG);
217  if (status != PSA_ERROR_NOT_SUPPORTED) {
218  TEST_FAIL("Set should not succeed with invalid flags");
219  return;
220  }
221 
222  ret->val = TEST_PASSED;
223 }
224 
234 static void tfm_ps_test_2003(struct test_result_t *ret)
235 {
236  psa_status_t status;
237  const psa_storage_uid_t uid = TEST_UID_3;
239  const uint32_t data_len = 0;
240 
241  /* Set with NULL data pointer */
242  status = psa_ps_set(uid, data_len, NULL, flags);
243  if (status != PSA_SUCCESS) {
244  TEST_FAIL("Set should succeed with NULL data pointer and zero length");
245  return;
246  }
247 
248  ret->val = TEST_PASSED;
249 }
250 
255 static void tfm_ps_test_2004(struct test_result_t *ret)
256 {
257 #ifndef TFM_PSA_API
258  psa_status_t status;
259  const psa_storage_uid_t uid = TEST_UID_1;
261  const uint32_t data_len = INVALID_DATA_LEN;
262  const uint8_t write_data[] = WRITE_DATA;
263 
264  /* A parameter with a buffer pointer where its data length is longer than
265  * maximum permitted, it is treated as a secure violation.
266  * TF-M framework rejects the request with a proper error code.
267  * The PS secure PSA PS implementation returns
268  * PSA_ERROR_INVALID_ARGUMENT in that case.
269  */
270 
271  /* Set with data length longer than the maximum supported */
272  status = psa_ps_set(uid, data_len, write_data, flags);
273  if (status != PSA_ERROR_INVALID_ARGUMENT) {
274  TEST_FAIL("Set should not succeed with invalid data length");
275  return;
276  }
277 
278 #endif
279  ret->val = TEST_PASSED;
280 }
281 
286 static void tfm_ps_test_2005(struct test_result_t *ret)
287 {
288  psa_status_t status;
289  const psa_storage_uid_t uid = WRITE_ONCE_UID;
291  const uint32_t write_len = WRITE_DATA_SIZE;
292  const uint32_t read_len = WRITE_ONCE_DATA_SIZE;
293  const uint32_t offset = 0;
294  const uint8_t write_data[] = WRITE_DATA;
295  uint8_t read_data[] = WRITE_ONCE_READ_DATA;
296  size_t read_data_len = 0;
297 
298  /* Set a write once UID a second time */
299  status = psa_ps_set(uid, write_len, write_data, flags);
300  if (status != PSA_ERROR_NOT_PERMITTED) {
301  TEST_FAIL("Set should not rewrite a write once UID");
302  return;
303  }
304 
305  /* Get write once data */
306  status = psa_ps_get(uid, offset, read_len, read_data + HALF_PADDING_SIZE,
307  &read_data_len);
308  if (status != PSA_SUCCESS) {
309  TEST_FAIL("Get should not fail");
310  return;
311  }
312 
313  /* Check that write once data has not changed */
314  if (tfm_memcmp(read_data, WRITE_ONCE_RESULT_DATA, sizeof(read_data)) != 0) {
315  TEST_FAIL("Write once data should not have changed");
316  return;
317  }
318 
319  ret->val = TEST_PASSED;
320 }
321 
327 static void tfm_ps_test_2006(struct test_result_t *ret)
328 {
329  psa_status_t status;
330  const psa_storage_uid_t uid = TEST_UID_2;
332  uint32_t data_len = WRITE_DATA_SIZE;
333  uint32_t offset = 0;
334  const uint8_t write_data[] = WRITE_DATA;
335  uint8_t read_data[] = READ_DATA;
336  const uint8_t *p_read_data = read_data;
337  size_t read_data_len = 0;
338 
339  status = psa_ps_set(uid, data_len, write_data, flags);
340  if (status != PSA_SUCCESS) {
341  TEST_FAIL("Set should not fail");
342  return;
343  }
344 
345  /* Get the entire data */
346  status = psa_ps_get(uid, offset, data_len, read_data + HALF_PADDING_SIZE,
347  &read_data_len);
348  if (status != PSA_SUCCESS) {
349  TEST_FAIL("Get should not fail");
350  return;
351  }
352 
353  /* Check that the data is correct, including no illegal pre- or post-data */
354  if (tfm_memcmp(read_data, RESULT_DATA, sizeof(read_data)) != 0) {
355  TEST_FAIL("Read data should be equal to result data");
356  return;
357  }
358 
359  /* Reset read data */
360  tfm_memcpy(read_data, READ_DATA, sizeof(read_data));
361 
362  /* Read from offset 2 to 2 bytes before end of the data */
363  offset = 2;
364  data_len -= offset + 2;
365 
366  status = psa_ps_get(uid, offset, data_len, read_data + HALF_PADDING_SIZE,
367  &read_data_len);
368  if (status != PSA_SUCCESS) {
369  TEST_FAIL("Get should not fail");
370  return;
371  }
372 
373  /* Check that the correct data was read */
374  if (tfm_memcmp(p_read_data, "____", HALF_PADDING_SIZE) != 0) {
375  TEST_FAIL("Read data contains illegal pre-data");
376  return;
377  }
378 
379  p_read_data += HALF_PADDING_SIZE;
380 
381  if (tfm_memcmp(p_read_data, write_data + offset, data_len) != 0) {
382  TEST_FAIL("Read data incorrect");
383  return;
384  }
385 
386  p_read_data += data_len;
387 
388  if (tfm_memcmp(p_read_data, "____", HALF_PADDING_SIZE) != 0) {
389  TEST_FAIL("Read data contains illegal post-data");
390  return;
391  }
392 
393  /* Call remove to clean up storage for the next test */
394  status = psa_ps_remove(uid);
395  if (status != PSA_SUCCESS) {
396  TEST_FAIL("Remove should not fail with valid UID");
397  return;
398  }
399 
400  ret->val = TEST_PASSED;
401 }
402 
408 static void tfm_ps_test_2007(struct test_result_t *ret)
409 {
410  psa_status_t status;
411  const psa_storage_uid_t uid = TEST_UID_3;
413  const uint32_t write_len = WRITE_DATA_SIZE;
414  const uint32_t read_len = 0;
415  uint32_t offset = 0;
416  const uint8_t write_data[] = WRITE_DATA;
417  uint8_t read_data[] = READ_DATA;
418  size_t read_data_len = 0;
419 
420  status = psa_ps_set(uid, write_len, write_data, flags);
421  if (status != PSA_SUCCESS) {
422  TEST_FAIL("Set should not fail");
423  return;
424  }
425 
426  /* Get zero data from zero offset */
427  status = psa_ps_get(uid, offset, read_len, read_data + HALF_PADDING_SIZE,
428  &read_data_len);
429  if (status != PSA_SUCCESS) {
430  TEST_FAIL("Get should not fail with zero data len");
431  return;
432  }
433 
434  /* Check that the read data is unchanged */
435  if (tfm_memcmp(read_data, READ_DATA, sizeof(read_data)) != 0) {
436  TEST_FAIL("Read data should be equal to original read data");
437  return;
438  }
439 
440  offset = 5;
441 
442  /* Get zero data from non-zero offset */
443  status = psa_ps_get(uid, offset, read_len, read_data + HALF_PADDING_SIZE,
444  &read_data_len);
445  if (status != PSA_SUCCESS) {
446  TEST_FAIL("Get should not fail");
447  return;
448  }
449 
450  /* Check that the read data is unchanged */
451  if (tfm_memcmp(read_data, READ_DATA, sizeof(read_data)) != 0) {
452  TEST_FAIL("Read data should be equal to original read data");
453  return;
454  }
455 
456  /* Call remove to clean up storage for the next test */
457  status = psa_ps_remove(uid);
458  if (status != PSA_SUCCESS) {
459  TEST_FAIL("Remove should not fail with valid UID");
460  return;
461  }
462 
463  ret->val = TEST_PASSED;
464 }
465 
471 static void tfm_ps_test_2008(struct test_result_t *ret)
472 {
473  psa_status_t status;
474  const psa_storage_uid_t uid = TEST_UID_1;
475  const uint32_t data_len = 1;
476  const uint32_t offset = 0;
477  uint8_t read_data[] = READ_DATA;
478  size_t read_data_len = 0;
479 
480  /* Get with UID that has not yet been set */
481  status = psa_ps_get(uid, offset, data_len, read_data + HALF_PADDING_SIZE,
482  &read_data_len);
483  if (status != PSA_ERROR_DOES_NOT_EXIST) {
484  TEST_FAIL("Get succeeded with non-existant UID");
485  return;
486  }
487 
488  /* Check that the read data is unchanged */
489  if (tfm_memcmp(read_data, READ_DATA, sizeof(read_data)) != 0) {
490  TEST_FAIL("Read data not equal to original read data");
491  return;
492  }
493 
494  /* Get with invalid UID */
495  status = psa_ps_get(INVALID_UID, offset, data_len,
496  read_data + HALF_PADDING_SIZE, &read_data_len);
497  if (status != PSA_ERROR_INVALID_ARGUMENT) {
498  TEST_FAIL("Get succeeded with invalid UID");
499  return;
500  }
501 
502  /* Check that the read data is unchanged */
503  if (tfm_memcmp(read_data, READ_DATA, sizeof(read_data)) != 0) {
504  TEST_FAIL("Read data not equal to original read data");
505  return;
506  }
507 
508  ret->val = TEST_PASSED;
509 }
510 
518 static void tfm_ps_test_2009(struct test_result_t *ret)
519 {
520  psa_status_t status;
521  const psa_storage_uid_t uid = TEST_UID_2;
523  const uint32_t write_len = WRITE_DATA_SIZE;
524  uint32_t read_len;
525  uint32_t offset;
526  const uint8_t write_data[] = WRITE_DATA;
527  uint8_t read_data[] = READ_DATA;
528  size_t read_data_len = 0;
529 
530  status = psa_ps_set(uid, write_len, write_data, flags);
531  if (status != PSA_SUCCESS) {
532  TEST_FAIL("Set should not fail");
533  return;
534  }
535 
536  /* Get with offset greater than UID's length */
537  read_len = 1;
538  offset = write_len + 1;
539 
540  status = psa_ps_get(uid, offset, read_len, read_data + HALF_PADDING_SIZE,
541  &read_data_len);
542  if (status != PSA_ERROR_INVALID_ARGUMENT) {
543  TEST_FAIL("Get should not succeed with offset too large");
544  return;
545  }
546 
547  /* Check that the read data is unchanged */
548  if (tfm_memcmp(read_data, READ_DATA, sizeof(read_data)) != 0) {
549  TEST_FAIL("Read data should be equal to original read data");
550  return;
551  }
552 
553  /* Get with data length greater than UID's length */
554  read_len = write_len + 1;
555  offset = 0;
556 
557  status = psa_ps_get(uid, offset, read_len, read_data + HALF_PADDING_SIZE,
558  &read_data_len);
559  if (status != PSA_SUCCESS) {
560  TEST_FAIL("Get should succeed with data length larger than UID's "
561  "length");
562  return;
563  }
564 
565  if (read_data_len != write_len) {
566  TEST_FAIL("Read data length should be equal to UID's length");
567  return;
568  }
569 
570  /* Check that the read data is unchanged */
571  if (tfm_memcmp(read_data, RESULT_DATA, sizeof(read_data)) != 0) {
572  TEST_FAIL("Read data should be equal to original read data");
573  return;
574  }
575 
576  /* Get with offset + data length greater than UID's length, but individually
577  * valid
578  */
579  read_len = write_len;
580  offset = 1;
581 
582  /* Reset read_data to original READ_DATA */
583  tfm_memcpy(read_data, READ_DATA, sizeof(read_data));
584 
585  status = psa_ps_get(uid, offset, read_len, read_data + HALF_PADDING_SIZE,
586  &read_data_len);
587  if (status != PSA_SUCCESS) {
588  TEST_FAIL("Get should succeed with offset + data length too large, "
589  "but individually valid");
590  return;
591  }
592 
593  if (read_data_len != write_len - offset) {
594  TEST_FAIL("Read data length should be equal to the UID's remaining "
595  "size starting from offset");
596  return;
597  }
598 
599  /* Check that the read data is unchanged */
600  if (tfm_memcmp(read_data, OFFSET_RESULT_DATA, sizeof(read_data)) != 0) {
601  TEST_FAIL("Read data should be equal to original read data");
602  return;
603  }
604 
605 #ifndef TFM_PSA_API
606  /* Get with data length and offset set to invalid values */
607  read_len = INVALID_DATA_LEN;
608  offset = INVALID_OFFSET;
609 
610  /* Reset read_data to original READ_DATA */
611  tfm_memcpy(read_data, READ_DATA, sizeof(read_data));
612 
613  /* A parameter with a buffer pointer where its data length is longer than
614  * maximum permitted, it is treated as a secure violation.
615  * TF-M framework rejects the request with a proper error code.
616  * The PS secure PSA PS implementation returns
617  * PSA_ERROR_INVALID_ARGUMENT in that case.
618  */
619 
620  status = psa_ps_get(uid, offset, read_len, read_data + HALF_PADDING_SIZE,
621  &read_data_len);
622  if (status != PSA_ERROR_INVALID_ARGUMENT) {
623  TEST_FAIL("Get should not succeed with invalid arguments");
624  return;
625  }
626 
627  /* Check that the read data is unchanged */
628  if (tfm_memcmp(read_data, READ_DATA, sizeof(read_data)) != 0) {
629  TEST_FAIL("Read data should be equal to original read data");
630  return;
631  }
632 #endif
633 
634  /* Call remove to clean up storage for the next test */
635  status = psa_ps_remove(uid);
636  if (status != PSA_SUCCESS) {
637  TEST_FAIL("Remove should not fail with valid UID");
638  return;
639  }
640 
641  ret->val = TEST_PASSED;
642 }
643 
653 static void tfm_ps_test_2010(struct test_result_t *ret)
654 {
655  psa_status_t status;
656  const psa_storage_uid_t uid = TEST_UID_3;
658  const uint32_t data_len = WRITE_DATA_SIZE;
659  const uint32_t offset = 0;
660  const uint8_t write_data[] = WRITE_DATA;
661  size_t read_data_len = 0;
662 
663  status = psa_ps_set(uid, data_len, write_data, flags);
664  if (status != PSA_SUCCESS) {
665  TEST_FAIL("Set should not fail");
666  return;
667  }
668 
669  /* Get with NULL data pointer */
670  status = psa_ps_get(uid, offset, 0, NULL, &read_data_len);
671  if (status != PSA_SUCCESS) {
672  TEST_FAIL("Get should succeed with NULL data pointer and zero length");
673  return;
674  }
675 
676  /* Call remove to clean up storage for the next test */
677  status = psa_ps_remove(uid);
678  if (status != PSA_SUCCESS) {
679  TEST_FAIL("Remove should not fail with valid UID");
680  return;
681  }
682 
683  ret->val = TEST_PASSED;
684 }
685 
690 static void tfm_ps_test_2011(struct test_result_t *ret)
691 {
692  psa_status_t status;
693  const psa_storage_uid_t uid = WRITE_ONCE_UID;
694  struct psa_storage_info_t info = {0};
695 
696  /* Get info for write once UID */
697  status = psa_ps_get_info(uid, &info);
698  if (status != PSA_SUCCESS) {
699  TEST_FAIL("Get info should not fail for write once UID");
700  return;
701  }
702 
703  /* Check that the info struct contains the correct values */
704  if (info.size != WRITE_ONCE_DATA_SIZE) {
705  TEST_FAIL("Size incorrect for write once UID");
706  return;
707  }
708 
709  if (info.flags != PSA_STORAGE_FLAG_WRITE_ONCE) {
710  TEST_FAIL("Flags incorrect for write once UID");
711  return;
712  }
713 
714  ret->val = TEST_PASSED;
715 }
716 
721 static void tfm_ps_test_2012(struct test_result_t *ret)
722 {
723  psa_status_t status;
724  const psa_storage_uid_t uid = TEST_UID_1;
725  struct psa_storage_info_t info = {0};
727  const uint32_t data_len = WRITE_DATA_SIZE;
728  const uint8_t write_data[] = WRITE_DATA;
729 
730  status = psa_ps_set(uid, data_len, write_data, flags);
731  if (status != PSA_SUCCESS) {
732  TEST_FAIL("Set should not fail");
733  return;
734  }
735 
736  /* Get info for valid UID */
737  status = psa_ps_get_info(uid, &info);
738  if (status != PSA_SUCCESS) {
739  TEST_FAIL("Get info should not fail with valid UID");
740  return;
741  }
742 
743  /* Check that the info struct contains the correct values */
744  if (info.size != data_len) {
745  TEST_FAIL("Size incorrect for valid UID");
746  return;
747  }
748 
749  if (info.flags != flags) {
750  TEST_FAIL("Flags incorrect for valid UID");
751  return;
752  }
753 
754  /* Call remove to clean up storage for the next test */
755  status = psa_ps_remove(uid);
756  if (status != PSA_SUCCESS) {
757  TEST_FAIL("Remove should not fail with valid UID");
758  return;
759  }
760 
761  ret->val = TEST_PASSED;
762 }
763 
769 static void tfm_ps_test_2013(struct test_result_t *ret)
770 {
771  psa_status_t status;
772  const psa_storage_uid_t uid = TEST_UID_2;
773  struct psa_storage_info_t info = {0};
774 
775  /* Get info with UID that has not yet been set */
776  status = psa_ps_get_info(uid, &info);
777  if (status != PSA_ERROR_DOES_NOT_EXIST) {
778  TEST_FAIL("Get info should not succeed with unset UID");
779  return;
780  }
781 
782  /* Check that the info struct has not been modified */
783  if (info.size != 0) {
784  TEST_FAIL("Size should not have changed");
785  return;
786  }
787 
788  if (info.flags != 0) {
789  TEST_FAIL("Flags should not have changed");
790  return;
791  }
792 
793  /* Get info with invalid UID */
794  status = psa_ps_get_info(INVALID_UID, &info);
795  if (status != PSA_ERROR_INVALID_ARGUMENT) {
796  TEST_FAIL("Get info should not succeed with invalid UID");
797  return;
798  }
799 
800  /* Check that the info struct has not been modified */
801  if (info.size != 0) {
802  TEST_FAIL("Size should not have changed");
803  return;
804  }
805 
806  if (info.flags != 0) {
807  TEST_FAIL("Flags should not have changed");
808  return;
809  }
810 
811  ret->val = TEST_PASSED;
812 }
813 
818 static void tfm_ps_test_2014(struct test_result_t *ret)
819 {
820  psa_status_t status;
821  const psa_storage_uid_t uid = TEST_UID_3;
823  const uint32_t data_len = WRITE_DATA_SIZE;
824  const uint8_t write_data[] = WRITE_DATA;
825 
826  status = psa_ps_set(uid, data_len, write_data, flags);
827  if (status != PSA_SUCCESS) {
828  TEST_FAIL("Set should not fail");
829  return;
830  }
831 
832  /* A parameter with a null pointer is treated as a secure violation.
833  * TF-M framework rejects the request with a proper error code.
834  * The PS secure PSA PS implementation returns
835  * PSA_ERROR_GENERIC_ERROR in that case.
836  */
837 
838  /* Get info with NULL info pointer */
839 #ifndef TFM_PSA_API
840  status = psa_ps_get_info(uid, NULL);
841  if (status != PSA_ERROR_INVALID_ARGUMENT) {
842  TEST_FAIL("Get info should not succeed with NULL info pointer");
843  return;
844  }
845 #endif
846 
847  /* Call remove to clean up storage for the next test */
848  status = psa_ps_remove(uid);
849  if (status != PSA_SUCCESS) {
850  TEST_FAIL("Remove should not fail with valid UID");
851  return;
852  }
853 
854  ret->val = TEST_PASSED;
855 }
856 
861 static void tfm_ps_test_2015(struct test_result_t *ret)
862 {
863  psa_status_t status;
864  const psa_storage_uid_t uid = TEST_UID_1;
865  struct psa_storage_info_t info = {0};
867  const uint32_t data_len = WRITE_DATA_SIZE;
868  const uint32_t offset = 0;
869  const uint8_t write_data[] = WRITE_DATA;
870  uint8_t read_data[] = READ_DATA;
871  size_t read_data_len = 0;
872 
873  status = psa_ps_set(uid, data_len, write_data, flags);
874  if (status != PSA_SUCCESS) {
875  TEST_FAIL("Set should not fail");
876  return;
877  }
878 
879  /* Call remove with valid ID */
880  status = psa_ps_remove(uid);
881  if (status != PSA_SUCCESS) {
882  TEST_FAIL("Remove should not fail with valid UID");
883  return;
884  }
885 
886  /* Check that get info fails for removed UID */
887  status = psa_ps_get_info(uid, &info);
888  if (status != PSA_ERROR_DOES_NOT_EXIST) {
889  TEST_FAIL("Get info should not succeed with removed UID");
890  return;
891  }
892 
893  /* Check that get fails for removed UID */
894  status = psa_ps_get(uid, offset, data_len, read_data, &read_data_len);
895  if (status != PSA_ERROR_DOES_NOT_EXIST) {
896  TEST_FAIL("Get should not succeed with removed UID");
897  return;
898  }
899 
900  /* Check that remove fails for removed UID */
901  status = psa_ps_remove(uid);
902  if (status != PSA_ERROR_DOES_NOT_EXIST) {
903  TEST_FAIL("Remove should not succeed with removed UID");
904  return;
905  }
906 
907  ret->val = TEST_PASSED;
908 }
909 
914 static void tfm_ps_test_2016(struct test_result_t *ret)
915 {
916  psa_status_t status;
917  const psa_storage_uid_t uid = WRITE_ONCE_UID;
918 
919  /* Call remove with write once UID */
920  status = psa_ps_remove(uid);
921  if (status != PSA_ERROR_NOT_PERMITTED) {
922  TEST_FAIL("Remove should not succeed with write once UID");
923  return;
924  }
925 
926  ret->val = TEST_PASSED;
927 }
928 
933 static void tfm_ps_test_2017(struct test_result_t *ret)
934 {
935  psa_status_t status;
936  const psa_storage_uid_t uid = INVALID_UID;
937 
938  /* Call remove with an invalid UID */
939  status = psa_ps_remove(uid);
940  if (status != PSA_ERROR_INVALID_ARGUMENT) {
941  TEST_FAIL("Remove should not succeed with invalid UID");
942  return;
943  }
944 
945  ret->val = TEST_PASSED;
946 }
947 
955 static void tfm_ps_test_2018(struct test_result_t *ret)
956 {
957  psa_status_t status;
958  const psa_storage_uid_t uid_1 = TEST_UID_2;
959  const psa_storage_uid_t uid_2 = TEST_UID_3;
961  const uint32_t data_len_2 = WRITE_DATA_SIZE;
962  const uint32_t offset = 0;
963  const uint8_t write_data_1[] = "UID 1 DATA";
964  const uint8_t write_data_2[] = WRITE_DATA;
965  uint8_t read_data[] = READ_DATA;
966  size_t read_data_len = 0;
967 
968  /* Set UID 1 */
969  status = psa_ps_set(uid_1, sizeof(write_data_1), write_data_1, flags);
970  if (status != PSA_SUCCESS) {
971  TEST_FAIL("Set should not fail for UID 1");
972  return;
973  }
974 
975  /* Set UID 2 */
976  status = psa_ps_set(uid_2, data_len_2, write_data_2, flags);
977  if (status != PSA_SUCCESS) {
978  TEST_FAIL("Set should not fail for UID 2");
979  return;
980  }
981 
982  /* Remove UID 1. This should cause UID 2 to be compacted to the beginning of
983  * the block.
984  */
985  status = psa_ps_remove(uid_1);
986  if (status != PSA_SUCCESS) {
987  TEST_FAIL("Remove should not fail for UID 1");
988  return;
989  }
990 
991  /* If the compact worked as expected, the test should be able to read back
992  * the data from UID 2 correctly.
993  */
994  status = psa_ps_get(uid_2, offset, data_len_2,
995  read_data + HALF_PADDING_SIZE, &read_data_len);
996  if (status != PSA_SUCCESS) {
997  TEST_FAIL("Get should not fail for UID 2");
998  return;
999  }
1000 
1001  if (tfm_memcmp(read_data, RESULT_DATA, sizeof(read_data)) != 0) {
1002  TEST_FAIL("Read buffer has incorrect data");
1003  return;
1004  }
1005 
1006  /* Remove UID 2 to clean up storage for the next test */
1007  status = psa_ps_remove(uid_2);
1008  if (status != PSA_SUCCESS) {
1009  TEST_FAIL("Remove should not fail for UID 2");
1010  return;
1011  }
1012 
1013  ret->val = TEST_PASSED;
1014 }
1015 
1019 static void tfm_ps_test_2019(struct test_result_t *ret)
1020 {
1021  psa_status_t status;
1022  uint32_t i;
1023  const psa_storage_uid_t uid = TEST_UID_1;
1025  const uint32_t data_len = WRITE_DATA_SIZE;
1026  uint32_t offset = 0;
1027  const uint8_t write_data[] = WRITE_DATA;
1028  uint8_t read_data[] = READ_DATA;
1029  size_t read_data_len = 0;
1030 
1031  /* Set the entire data into UID */
1032  status = psa_ps_set(uid, data_len, write_data, flags);
1033  if (status != PSA_SUCCESS) {
1034  TEST_FAIL("Set should not fail");
1035  return;
1036  }
1037 
1038  /* Get the data from UID one byte at a time */
1039  for (i = 0; i < data_len; ++i) {
1040  status = psa_ps_get(uid, offset, 1,
1041  (read_data + HALF_PADDING_SIZE + i),
1042  &read_data_len);
1043  if (status != PSA_SUCCESS) {
1044  TEST_FAIL("Get should not fail for partial read");
1045  return;
1046  }
1047 
1048  ++offset;
1049  }
1050 
1051  if (tfm_memcmp(read_data, RESULT_DATA, sizeof(read_data)) != 0) {
1052  TEST_FAIL("Read buffer has incorrect data");
1053  return;
1054  }
1055 
1056  /* Remove UID to clean up storage for the next test */
1057  status = psa_ps_remove(uid);
1058  if (status != PSA_SUCCESS) {
1059  TEST_FAIL("Remove should not fail");
1060  return;
1061  }
1062 
1063  ret->val = TEST_PASSED;
1064 }
1065 
1069 static void tfm_ps_test_2020(struct test_result_t *ret)
1070 {
1071  psa_status_t status;
1072  const psa_storage_uid_t uid = TEST_UID_2;
1074  const uint32_t offset = 0;
1075  const uint8_t write_data_1[] = "ONE";
1076  const uint8_t write_data_2[] = "TWO";
1077  const uint8_t write_data_3[] = "THREE";
1078  uint8_t read_data[] = READ_DATA;
1079  size_t read_data_len = 0;
1080 
1081  /* Set write data 1 into UID */
1082  status = psa_ps_set(uid, sizeof(write_data_1), write_data_1, flags);
1083  if (status != PSA_SUCCESS) {
1084  TEST_FAIL("First set should not fail");
1085  return;
1086  }
1087 
1088  /* Set write data 2 into UID */
1089  status = psa_ps_set(uid, sizeof(write_data_2), write_data_2, flags);
1090  if (status != PSA_SUCCESS) {
1091  TEST_FAIL("Second set should not fail");
1092  return;
1093  }
1094 
1095  /* Set write data 3 into UID */
1096  status = psa_ps_set(uid, sizeof(write_data_3), write_data_3, flags);
1097  if (status != PSA_SUCCESS) {
1098  TEST_FAIL("Third set should not fail");
1099  return;
1100  }
1101 
1102  status = psa_ps_get(uid, offset, sizeof(write_data_3), read_data,
1103  &read_data_len);
1104  if (status != PSA_SUCCESS) {
1105  TEST_FAIL("Get should not fail");
1106  return;
1107  }
1108 
1109  /* Check that get returns the last data to be set */
1110  if (tfm_memcmp(read_data, write_data_3, sizeof(write_data_3)) != 0) {
1111  TEST_FAIL("Read buffer has incorrect data");
1112  return;
1113  }
1114 
1115  /* Remove UID to clean up storage for the next test */
1116  status = psa_ps_remove(uid);
1117  if (status != PSA_SUCCESS) {
1118  TEST_FAIL("Remove should not fail");
1119  return;
1120  }
1121 
1122  ret->val = TEST_PASSED;
1123 }
1124 
1128 static void tfm_ps_test_2021(struct test_result_t *ret)
1129 {
1130  uint32_t support_flags;
1131 
1132  support_flags = psa_ps_get_support();
1133  if (support_flags != 0) {
1134  TEST_FAIL("Support flags should be 0");
1135  return;
1136  }
1137 
1138  ret->val = TEST_PASSED;
1139 }
1140 
1147 static void tfm_ps_test_2022(struct test_result_t *ret)
1148 {
1149  uint8_t cycle;
1150  psa_status_t status;
1151  const psa_storage_uid_t test_uid[TEST_1022_CYCLES] = {
1152  TEST_UID_1,
1153  TEST_UID_2,
1154  TEST_UID_3};
1155  const uint32_t test_asset_sizes[TEST_1022_CYCLES] = {
1156  PS_MAX_ASSET_SIZE >> 2,
1157  PS_MAX_ASSET_SIZE >> 1,
1158  PS_MAX_ASSET_SIZE};
1159 
1160  /* Loop to test different asset sizes and UID's*/
1161  for (cycle = 0; cycle < TEST_1022_CYCLES; cycle++) {
1162  uint32_t data_size = test_asset_sizes[cycle];
1163  psa_storage_uid_t uid = test_uid[cycle];
1164  struct psa_storage_info_t info = {0};
1165 
1166  tfm_memset(read_asset_data, 0x00, sizeof(read_asset_data));
1167 
1168  /* Set with data and no flags and a valid UID */
1169  status = psa_ps_set(uid,
1170  data_size,
1171  write_asset_data,
1173  if (status != PSA_SUCCESS) {
1174  TEST_FAIL("Set should not fail with valid UID");
1175  return;
1176  }
1177 
1178  /* Get info for valid UID */
1179  status = psa_ps_get_info(uid, &info);
1180  if (status != PSA_SUCCESS) {
1181  TEST_FAIL("Get info should not fail with valid UID");
1182  return;
1183  }
1184 
1185  /* Check that the info struct contains the correct values */
1186  if (info.size != data_size) {
1187  TEST_FAIL("Size incorrect for valid UID");
1188  return;
1189  }
1190 
1191  if (info.flags != PSA_STORAGE_FLAG_NONE) {
1192  TEST_FAIL("Flags incorrect for valid UID");
1193  return;
1194  }
1195 
1196  /* Check that thread can still get UID */
1197  status = psa_ps_get(uid, 0, data_size, read_asset_data,
1198  &read_asset_datal_len);
1199  if (status != PSA_SUCCESS) {
1200  TEST_FAIL("Get should not fail with valid UID");
1201  return;
1202  }
1203 
1204  /* Check that thread's UID data has not been modified */
1205  if (tfm_memcmp(read_asset_data, write_asset_data, data_size) != 0) {
1206  TEST_FAIL("Read data should be equal to original write data");
1207  return;
1208  }
1209 
1210  /* Call remove to clean up storage for the next test */
1211  status = psa_ps_remove(uid);
1212  if (status != PSA_SUCCESS) {
1213  TEST_FAIL("Remove should not fail with valid UID");
1214  return;
1215  }
1216  }
1217 
1218  ret->val = TEST_PASSED;
1219 }
#define READ_DATA
void register_testsuite_s_psa_ps_interface(struct test_suite_t *p_test_suite)
Register testsuite for the PSA protected storage S interface tests.
#define WRITE_DATA
psa_status_t psa_ps_get(psa_storage_uid_t uid, size_t data_offset, size_t data_size, void *p_data, size_t *p_data_length)
Retrieve data associated with a provided uid.
__STATIC_INLINE void * tfm_memset(void *ptr, int value, size_t num)
#define PSA_SUCCESS
Definition: crypto_values.h:35
#define TEST_FAIL(info_msg)
enum test_suite_err_t set_testsuite(const char *name, struct test_t *test_list, uint32_t size, struct test_suite_t *p_ts)
Sets test suite parameters.
psa_status_t psa_ps_set(psa_storage_uid_t uid, size_t data_length, const void *p_data, psa_storage_create_flags_t create_flags)
Create a new, or modify an existing, uid/value pair.
#define TEST_UID_1
#define INVALID_FLAG
#define OFFSET_RESULT_DATA
#define PSA_STORAGE_FLAG_WRITE_ONCE
#define TEST_UID_2
#define INVALID_DATA_LEN
#define TEST_1022_CYCLES
#define TEST_UID_3
#define WRITE_ONCE_DATA_SIZE
#define PSA_ERROR_INVALID_ARGUMENT
psa_status_t psa_ps_get_info(psa_storage_uid_t uid, struct psa_storage_info_t *p_info)
Retrieve the metadata about the provided uid.
#define PSA_ERROR_NOT_PERMITTED
Definition: crypto_values.h:65
struct test_result_t ret
#define WRITE_ONCE_DATA
psa_status_t psa_ps_remove(psa_storage_uid_t uid)
Remove the provided uid and its associated data from the storage.
#define WRITE_ONCE_UID
#define PSA_ERROR_NOT_SUPPORTED
Definition: crypto_values.h:52
#define HALF_PADDING_SIZE
__STATIC_INLINE void * tfm_memcpy(void *dest, const void *src, size_t num)
#define WRITE_ONCE_RESULT_DATA
uint32_t psa_ps_get_support(void)
Lists optional features.
#define TEST_LOG(...)
uint64_t psa_storage_uid_t
enum test_status_t val
#define INVALID_UID
__STATIC_INLINE int tfm_memcmp(const void *ptr1, const void *ptr2, size_t num)
#define INVALID_OFFSET
psa_storage_create_flags_t flags
#define PSA_STORAGE_FLAG_NONE
#define RESULT_DATA
#define PSA_ERROR_DOES_NOT_EXIST
Definition: crypto_values.h:89
uint32_t psa_storage_create_flags_t
int32_t psa_status_t
Function return status.
Definition: crypto_types.h:43
#define WRITE_ONCE_READ_DATA
#define WRITE_DATA_SIZE