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