1 /*
2 * Copyright (c) 2021-2023, Arm Limited and Contributors. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7 #include <ctype.h>
8 #include <rpc_caller.h>
9 #include <stdbool.h>
10 #include <stdint.h>
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <string.h>
14
15 #include "psa_api_test_common.h"
16 #include "trace.h"
17
18 #define TEST_ID_OFFSET (5)
19 #define TEST_POSTFIX_OFFSET (8)
20 #define TEST_ENTRY_LENGTH (9)
21
22 int32_t val_entry(void);
23 size_t val_get_test_list(uint32_t *test_id_list, size_t size);
24 void pal_set_custom_test_list(char *custom_test_list);
25
26 /* Returns whether option_switch is in the argv list and provide its index in the array */
option_selected(const char * option_switch,int argc,char * argv[],int * index)27 static bool option_selected(const char *option_switch, int argc, char *argv[], int *index)
28 {
29 bool selected = false;
30 *index = 0;
31
32 for (int i = 1; (i < argc) && !selected; ++i) {
33 selected = (strcmp(argv[i], option_switch) == 0);
34 *index = i;
35 }
36
37 return selected;
38 }
39
40 /* Print the supported command line arguments */
print_help(void)41 static void print_help(void)
42 {
43 EMSG("Supported command line arguments:\n");
44 EMSG("\t -l: Print list of tests.");
45 EMSG("\t -t <test_list>: Run only the listed tests (e.g: test_201;test_202;). test_list = ^(test_[0-9]{3};)+");
46 EMSG("\t -c: <service name>: Crypto service name");
47 EMSG("\t -a: <service name>: Initial attestation service name");
48 EMSG("\t -p: <service name>: Protected Storage service name");
49 EMSG("\t -i: <service name>: Internal Trusted Storage service name");
50 EMSG("\t -v: Verbose mode.");
51 EMSG("\t -h: Print this help message.\n");
52 }
53
54 /* Prints the list of selectable psa-api tests */
print_psa_api_tests(void)55 static void print_psa_api_tests(void)
56 {
57 /*
58 * Request the number of tests to find out the size
59 * of the area needed to store the test ID-s.
60 */
61 size_t n_test = val_get_test_list(NULL, 0);
62
63 uint32_t *test_id_list = (uint32_t *)calloc(n_test, sizeof(uint32_t));
64
65 if (test_id_list) {
66 n_test = val_get_test_list(test_id_list, n_test);
67
68 EMSG("Available psa-api tests:");
69 for (int i = 0; i < n_test; i++)
70 EMSG("\t test_%d;", test_id_list[i]);
71
72 free(test_id_list);
73 } else {
74 EMSG("Could not allocate enough memory to store the list of tests");
75 }
76 }
77
78 /* Check if the received test list string is formatted as expected */
is_test_list_wrong(char * test_list)79 static bool is_test_list_wrong(char *test_list)
80 {
81 size_t len = strlen(test_list);
82
83 for (unsigned int i = 0; i < len; i += TEST_ENTRY_LENGTH) {
84 /* Report error when the test entry is not properly finished */
85 if (i + TEST_ENTRY_LENGTH > len) {
86 EMSG("Expecting \"test_xxx;\" test entry at the %dth character, got \"%s\" instead.",
87 i, &test_list[i]);
88 return true;
89 }
90
91 /* Report error at incorrect test entry prefix */
92 if (memcmp(&test_list[i], "test_", TEST_ID_OFFSET)) {
93 EMSG("Expecting \"test_\" at the %dth character, got \"%.5s\" instead.", i,
94 &test_list[i]);
95 return true;
96 }
97
98 /* Report error if the test ID is incorrect */
99 if (!(isdigit(test_list[i + TEST_ID_OFFSET]) &&
100 isdigit(test_list[i + TEST_ID_OFFSET + 1]) &&
101 isdigit(test_list[i + TEST_ID_OFFSET + 2]))) {
102 EMSG("Expecting three digits at %dth character, got \"%.3s\" instead.",
103 i + TEST_ID_OFFSET, &test_list[i + TEST_ID_OFFSET]);
104 return true;
105 }
106
107 /* Report error at incorrect test entry postfix */
108 if (test_list[i + TEST_POSTFIX_OFFSET] != ';') {
109 EMSG("Expecting ; at the %dth character, got \"%.1s\" instead.",
110 i + TEST_POSTFIX_OFFSET, &test_list[i + TEST_POSTFIX_OFFSET]);
111 return true;
112 }
113 }
114
115 return false;
116 }
117
118 /* Entry point */
main(int argc,char * argv[])119 int main(int argc, char *argv[])
120 {
121 int rval = -1;
122 int option_index = 0;
123 char *service_name_crypto = NULL;
124 char *service_name_iat = NULL;
125 char *service_name_ps = NULL;
126 char *service_name_its = NULL;
127
128 /* Print available tests */
129 if (option_selected("-l", argc, argv, &option_index)) {
130 print_psa_api_tests();
131 return 0;
132 }
133
134 /* Create custom test list */
135 if (option_selected("-t", argc, argv, &option_index)) {
136 /*
137 * Avoid overindexing of argv and detect if the
138 * option is followed by another option
139 */
140 char *test_list_values = argv[option_index + 1];
141
142 if ((option_index >= argc) || (test_list_values[0] == '-')) {
143 EMSG("Testlist string is expected after -t argument!");
144 return -1;
145 }
146
147 if (is_test_list_wrong(test_list_values)) {
148 EMSG("Testlist string is not valid!");
149 print_psa_api_tests();
150 return -1;
151 }
152
153 /* Filter tests */
154 pal_set_custom_test_list(test_list_values);
155 }
156
157 /* Print help */
158 if (option_selected("-h", argc, argv, &option_index)) {
159 print_help();
160 return 0;
161 }
162
163 /* Process optional service names */
164 if (option_selected("-c", argc, argv, &option_index))
165 service_name_crypto = argv[option_index + 1];
166
167 if (option_selected("-a", argc, argv, &option_index))
168 service_name_iat = argv[option_index + 1];
169
170 if (option_selected("-p", argc, argv, &option_index))
171 service_name_ps = argv[option_index + 1];
172
173 if (option_selected("-i", argc, argv, &option_index))
174 service_name_its = argv[option_index + 1];
175
176 rval = test_setup(service_name_crypto, service_name_iat, service_name_ps, service_name_its);
177
178 if (!rval)
179 rval = val_entry();
180
181 test_teardown();
182
183 return rval;
184 }
185