xref: /optee_os/core/pta/tests/invoke.c (revision 5b25c76ac40f830867e3d60800120ffd7874e8dc)
1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3  * Copyright (c) 2014, STMicroelectronics International N.V.
4  */
5 
6 #include <compiler.h>
7 #include <kernel/pseudo_ta.h>
8 #include <kernel/panic.h>
9 #include <mm/core_memprot.h>
10 #include <pta_invoke_tests.h>
11 #include <string.h>
12 #include <tee/cache.h>
13 #include <tee_api_defines.h>
14 #include <tee_api_types.h>
15 #include <trace.h>
16 #include <types_ext.h>
17 
18 #include "misc.h"
19 
20 #define TA_NAME		"invoke_tests.pta"
21 
22 static TEE_Result test_trace(uint32_t param_types __unused,
23 			TEE_Param params[TEE_NUM_PARAMS] __unused)
24 {
25 	IMSG("pseudo TA \"%s\" says \"Hello world !\"", TA_NAME);
26 
27 	return TEE_SUCCESS;
28 }
29 
30 static int test_v2p2v(void *va)
31 {
32 	struct tee_ta_session *session;
33 	paddr_t p;
34 	void *v;
35 
36 	if  (!va)
37 		return 0;
38 
39 	if (tee_ta_get_current_session(&session))
40 		panic();
41 
42 	p = virt_to_phys(va);
43 
44 	/* 0 is not a valid physical address */
45 	if (!p)
46 		return 1;
47 
48 	if (session->clnt_id.login == TEE_LOGIN_TRUSTED_APP) {
49 		v = phys_to_virt(p, MEM_AREA_TA_VASPACE);
50 	} else {
51 		v = phys_to_virt(p, MEM_AREA_NSEC_SHM);
52 		if (!v)
53 			v = phys_to_virt(p, MEM_AREA_SDP_MEM);
54 		if (!v)
55 			v = phys_to_virt(p, MEM_AREA_SHM_VASPACE);
56 	}
57 
58 	/*
59 	 * Return an error only the vaddr found mismatches input address.
60 	 * Finding a virtual address from a physical address cannot be painful
61 	 * in some case (i.e pager). Moreover this operation is more debug
62 	 * related. Thus do not report error if phys_to_virt failed
63 	 */
64 	if (v && va != v) {
65 		EMSG("Failed to p2v/v2p on caller TA memref arguments");
66 		EMSG("va %p -> pa 0x%" PRIxPA " -> va %p", va, p, v);
67 		return 1;
68 	}
69 
70 	return 0;
71 }
72 
73 /*
74  * Supported tests on parameters
75  * (I, J, K, L refer to param index)
76  *
77  * Case 1: command parameters type are: 1 in/out value, 3 empty.
78  *         => process outI.a = inI.a + inI.b
79  * Case 2: command parameters type are: 3 input value, 1 output value
80  *         => process = outI.a = inJ.a + inK.a + inL.a
81  * Case 3: command parameters type are: 1 in/out memref, 3 empty.
82  *         => process = outI[0] = sum(inI[0..len-1])
83  */
84 static TEE_Result test_entry_params(uint32_t type, TEE_Param p[TEE_NUM_PARAMS])
85 {
86 	size_t i;
87 	uint8_t d8, *in;
88 
89 	/* case 1a: 1 input/output value argument */
90 	if ((TEE_PARAM_TYPE_GET(type, 0) == TEE_PARAM_TYPE_VALUE_INOUT) &&
91 		(TEE_PARAM_TYPE_GET(type, 1) == TEE_PARAM_TYPE_NONE) &&
92 		(TEE_PARAM_TYPE_GET(type, 2) == TEE_PARAM_TYPE_NONE) &&
93 		(TEE_PARAM_TYPE_GET(type, 3) == TEE_PARAM_TYPE_NONE)) {
94 		p[0].value.a = p[0].value.a + p[0].value.b;
95 		return TEE_SUCCESS;
96 	}
97 	/* case 1b: 1 input/output value argument */
98 	if ((TEE_PARAM_TYPE_GET(type, 0) == TEE_PARAM_TYPE_NONE) &&
99 		(TEE_PARAM_TYPE_GET(type, 1) == TEE_PARAM_TYPE_VALUE_INOUT) &&
100 		(TEE_PARAM_TYPE_GET(type, 2) == TEE_PARAM_TYPE_NONE) &&
101 		(TEE_PARAM_TYPE_GET(type, 3) == TEE_PARAM_TYPE_NONE)) {
102 		p[1].value.a = p[1].value.a + p[1].value.b;
103 		return TEE_SUCCESS;
104 	}
105 	/* case 1c: 1 input/output value argument */
106 	if ((TEE_PARAM_TYPE_GET(type, 0) == TEE_PARAM_TYPE_NONE) &&
107 		(TEE_PARAM_TYPE_GET(type, 1) == TEE_PARAM_TYPE_NONE) &&
108 		(TEE_PARAM_TYPE_GET(type, 2) == TEE_PARAM_TYPE_VALUE_INOUT) &&
109 		(TEE_PARAM_TYPE_GET(type, 3) == TEE_PARAM_TYPE_NONE)) {
110 		p[2].value.a = p[2].value.a + p[2].value.b;
111 		return TEE_SUCCESS;
112 	}
113 	/* case 1d: 1 input/output value argument */
114 	if ((TEE_PARAM_TYPE_GET(type, 0) == TEE_PARAM_TYPE_NONE) &&
115 		(TEE_PARAM_TYPE_GET(type, 1) == TEE_PARAM_TYPE_NONE) &&
116 		(TEE_PARAM_TYPE_GET(type, 2) == TEE_PARAM_TYPE_NONE) &&
117 		(TEE_PARAM_TYPE_GET(type, 3) == TEE_PARAM_TYPE_VALUE_INOUT)) {
118 		p[3].value.a = p[3].value.a + p[3].value.b;
119 		return TEE_SUCCESS;
120 	}
121 
122 	/* case 2a: 3 input value arguments, 1 output value argument */
123 	if ((TEE_PARAM_TYPE_GET(type, 0) == TEE_PARAM_TYPE_VALUE_OUTPUT) &&
124 		(TEE_PARAM_TYPE_GET(type, 1) == TEE_PARAM_TYPE_VALUE_INPUT) &&
125 		(TEE_PARAM_TYPE_GET(type, 2) == TEE_PARAM_TYPE_VALUE_INPUT) &&
126 		(TEE_PARAM_TYPE_GET(type, 3) == TEE_PARAM_TYPE_VALUE_INPUT)) {
127 		p[0].value.a = p[1].value.a + p[2].value.a + p[3].value.a;
128 		p[0].value.b = p[1].value.b + p[2].value.b + p[3].value.b;
129 		return TEE_SUCCESS;
130 	}
131 	/* case 2a: 3 input value arguments, 1 output value argument */
132 	if ((TEE_PARAM_TYPE_GET(type, 0) == TEE_PARAM_TYPE_VALUE_INPUT) &&
133 		(TEE_PARAM_TYPE_GET(type, 1) == TEE_PARAM_TYPE_VALUE_OUTPUT) &&
134 		(TEE_PARAM_TYPE_GET(type, 2) == TEE_PARAM_TYPE_VALUE_INPUT) &&
135 		(TEE_PARAM_TYPE_GET(type, 3) == TEE_PARAM_TYPE_VALUE_INPUT)) {
136 		p[1].value.a = p[0].value.a + p[2].value.a + p[3].value.a;
137 		p[1].value.b = p[0].value.b + p[2].value.b + p[3].value.b;
138 		return TEE_SUCCESS;
139 	}
140 	/* case 2a: 3 input value arguments, 1 output value argument */
141 	if ((TEE_PARAM_TYPE_GET(type, 0) == TEE_PARAM_TYPE_VALUE_INPUT) &&
142 		(TEE_PARAM_TYPE_GET(type, 1) == TEE_PARAM_TYPE_VALUE_INPUT) &&
143 		(TEE_PARAM_TYPE_GET(type, 2) == TEE_PARAM_TYPE_VALUE_OUTPUT) &&
144 		(TEE_PARAM_TYPE_GET(type, 3) == TEE_PARAM_TYPE_VALUE_INPUT)) {
145 		p[2].value.a = p[0].value.a + p[1].value.a + p[3].value.a;
146 		p[2].value.b = p[0].value.b + p[1].value.b + p[3].value.b;
147 		return TEE_SUCCESS;
148 	}
149 	/* case 2a: 3 input value arguments, 1 output value argument */
150 	if ((TEE_PARAM_TYPE_GET(type, 0) == TEE_PARAM_TYPE_VALUE_INPUT) &&
151 		(TEE_PARAM_TYPE_GET(type, 1) == TEE_PARAM_TYPE_VALUE_INPUT) &&
152 		(TEE_PARAM_TYPE_GET(type, 2) == TEE_PARAM_TYPE_VALUE_INPUT) &&
153 		(TEE_PARAM_TYPE_GET(type, 3) == TEE_PARAM_TYPE_VALUE_OUTPUT)) {
154 		p[3].value.a = p[0].value.a + p[1].value.a + p[2].value.a;
155 		p[3].value.b = p[0].value.b + p[1].value.b + p[2].value.b;
156 		return TEE_SUCCESS;
157 	}
158 
159 	DMSG("expect memref params: %p/%" PRIu32 " - %p/%" PRIu32 "zu - %p/%" PRIu32 "zu - %p/%" PRIu32 "zu",
160 			p[0].memref.buffer, p[0].memref.size,
161 			p[1].memref.buffer, p[1].memref.size,
162 			p[2].memref.buffer, p[2].memref.size,
163 			p[3].memref.buffer, p[3].memref.size);
164 
165 	/* case 3a: 1 in/out memref argument */
166 	if ((TEE_PARAM_TYPE_GET(type, 0) == TEE_PARAM_TYPE_MEMREF_INOUT) &&
167 		(TEE_PARAM_TYPE_GET(type, 1) == TEE_PARAM_TYPE_NONE) &&
168 		(TEE_PARAM_TYPE_GET(type, 2) == TEE_PARAM_TYPE_NONE) &&
169 		(TEE_PARAM_TYPE_GET(type, 3) == TEE_PARAM_TYPE_NONE)) {
170 		in = (uint8_t *)p[0].memref.buffer;
171 		if (test_v2p2v(in))
172 			return TEE_ERROR_SECURITY;
173 		d8 = 0;
174 		for (i = 0; i < p[0].memref.size; i++)
175 			d8 += in[i];
176 		*(uint8_t *)p[0].memref.buffer = d8;
177 		return TEE_SUCCESS;
178 	}
179 	/* case 3b: 1 in/out memref argument */
180 	if ((TEE_PARAM_TYPE_GET(type, 0) == TEE_PARAM_TYPE_NONE) &&
181 		(TEE_PARAM_TYPE_GET(type, 1) == TEE_PARAM_TYPE_MEMREF_INOUT) &&
182 		(TEE_PARAM_TYPE_GET(type, 2) == TEE_PARAM_TYPE_NONE) &&
183 		(TEE_PARAM_TYPE_GET(type, 3) == TEE_PARAM_TYPE_NONE)) {
184 		in = (uint8_t *)p[1].memref.buffer;
185 		if (test_v2p2v(in))
186 			return TEE_ERROR_SECURITY;
187 		d8 = 0;
188 		for (i = 0; i < p[1].memref.size; i++)
189 			d8 += in[i];
190 		*(uint8_t *)p[1].memref.buffer = d8;
191 		return TEE_SUCCESS;
192 	}
193 	/* case 3c: 1 in/out memref argument */
194 	if ((TEE_PARAM_TYPE_GET(type, 0) == TEE_PARAM_TYPE_NONE) &&
195 		(TEE_PARAM_TYPE_GET(type, 1) == TEE_PARAM_TYPE_NONE) &&
196 		(TEE_PARAM_TYPE_GET(type, 2) == TEE_PARAM_TYPE_MEMREF_INOUT) &&
197 		(TEE_PARAM_TYPE_GET(type, 3) == TEE_PARAM_TYPE_NONE)) {
198 		in = (uint8_t *)p[2].memref.buffer;
199 		if (test_v2p2v(in))
200 			return TEE_ERROR_SECURITY;
201 		d8 = 0;
202 		for (i = 0; i < p[2].memref.size; i++)
203 			d8 += in[i];
204 		*(uint8_t *)p[2].memref.buffer = d8;
205 		return TEE_SUCCESS;
206 	}
207 	/* case 3d: 1 in/out memref argument */
208 	if ((TEE_PARAM_TYPE_GET(type, 0) == TEE_PARAM_TYPE_NONE) &&
209 		(TEE_PARAM_TYPE_GET(type, 1) == TEE_PARAM_TYPE_NONE) &&
210 		(TEE_PARAM_TYPE_GET(type, 2) == TEE_PARAM_TYPE_NONE) &&
211 		(TEE_PARAM_TYPE_GET(type, 3) == TEE_PARAM_TYPE_MEMREF_INOUT)) {
212 		in = (uint8_t *)p[3].memref.buffer;
213 		if (test_v2p2v(in))
214 			return TEE_ERROR_SECURITY;
215 		d8 = 0;
216 		for (i = 0; i < p[3].memref.size; i++)
217 			d8 += in[i];
218 		*(uint8_t *)p[3].memref.buffer = d8;
219 		return TEE_SUCCESS;
220 	}
221 
222 	EMSG("unexpected parameters");
223 	return TEE_ERROR_BAD_PARAMETERS;
224 }
225 
226 /*
227  * Test access to Secure Data Path memory from pseudo TAs
228  */
229 
230 static TEE_Result test_inject_sdp(uint32_t type, TEE_Param p[TEE_NUM_PARAMS])
231 {
232 	char *src = p[0].memref.buffer;
233 	char *dst = p[1].memref.buffer;
234 	size_t sz = p[0].memref.size;
235 	uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT,
236 					  TEE_PARAM_TYPE_MEMREF_OUTPUT,
237 					  TEE_PARAM_TYPE_NONE,
238 					  TEE_PARAM_TYPE_NONE);
239 
240 	if (exp_pt != type) {
241 		DMSG("bad parameter types");
242 		return TEE_ERROR_BAD_PARAMETERS;
243 	}
244 
245 	if (p[1].memref.size < sz) {
246 		p[1].memref.size = sz;
247 		return TEE_ERROR_SHORT_BUFFER;
248 	}
249 
250 	if (!core_vbuf_is(CORE_MEM_NON_SEC, src, sz) ||
251 	    !core_vbuf_is(CORE_MEM_SDP_MEM, dst, sz)) {
252 		DMSG("bad memref secure attribute");
253 		return TEE_ERROR_BAD_PARAMETERS;
254 	}
255 
256 	if (!sz)
257 		return TEE_SUCCESS;
258 
259 	/* Check that core can p2v and v2p over memory reference arguments */
260 	if (test_v2p2v(src) || test_v2p2v(src + sz - 1) ||
261 	    test_v2p2v(dst) || test_v2p2v(dst + sz - 1))
262 		return TEE_ERROR_SECURITY;
263 
264 	if (cache_operation(TEE_CACHEFLUSH, dst, sz) != TEE_SUCCESS)
265 		return TEE_ERROR_GENERIC;
266 
267 	memcpy(dst, src, sz);
268 
269 	if (cache_operation(TEE_CACHEFLUSH, dst, sz) != TEE_SUCCESS)
270 		return TEE_ERROR_GENERIC;
271 
272 	return TEE_SUCCESS;
273 }
274 
275 static TEE_Result test_transform_sdp(uint32_t type, TEE_Param p[TEE_NUM_PARAMS])
276 {
277 	char *buf = p[0].memref.buffer;
278 	size_t sz = p[0].memref.size;
279 	uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
280 					  TEE_PARAM_TYPE_NONE,
281 					  TEE_PARAM_TYPE_NONE,
282 					  TEE_PARAM_TYPE_NONE);
283 
284 	if (exp_pt != type) {
285 		DMSG("bad parameter types");
286 		return TEE_ERROR_BAD_PARAMETERS;
287 	}
288 
289 	if (!core_vbuf_is(CORE_MEM_SDP_MEM, buf, sz)) {
290 		DMSG("bad memref secure attribute");
291 		return TEE_ERROR_BAD_PARAMETERS;
292 	}
293 
294 	if (!sz)
295 		return TEE_SUCCESS;
296 
297 	/* Check that core can p2v and v2p over memory reference arguments */
298 	if (test_v2p2v(buf) || test_v2p2v(buf + sz - 1))
299 		return TEE_ERROR_SECURITY;
300 
301 	if (cache_operation(TEE_CACHEFLUSH, buf, sz) != TEE_SUCCESS)
302 		return TEE_ERROR_GENERIC;
303 
304 	for (; sz; sz--, buf++)
305 		*buf = ~(*buf) + 1;
306 
307 	if (cache_operation(TEE_CACHEFLUSH, buf, sz) != TEE_SUCCESS)
308 		return TEE_ERROR_GENERIC;
309 
310 	return TEE_SUCCESS;
311 }
312 
313 static TEE_Result test_dump_sdp(uint32_t type, TEE_Param p[TEE_NUM_PARAMS])
314 {
315 	char *src = p[0].memref.buffer;
316 	char *dst = p[1].memref.buffer;
317 	size_t sz = p[0].memref.size;
318 	uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT,
319 					  TEE_PARAM_TYPE_MEMREF_OUTPUT,
320 					  TEE_PARAM_TYPE_NONE,
321 					  TEE_PARAM_TYPE_NONE);
322 
323 	if (exp_pt != type) {
324 		DMSG("bad parameter types");
325 		return TEE_ERROR_BAD_PARAMETERS;
326 	}
327 
328 	if (p[1].memref.size < sz) {
329 		p[1].memref.size = sz;
330 		return TEE_ERROR_SHORT_BUFFER;
331 	}
332 
333 	if (!core_vbuf_is(CORE_MEM_SDP_MEM, src, sz) ||
334 	    !core_vbuf_is(CORE_MEM_NON_SEC, dst, sz)) {
335 		DMSG("bad memref secure attribute");
336 		return TEE_ERROR_BAD_PARAMETERS;
337 	}
338 
339 	if (!sz)
340 		return TEE_SUCCESS;
341 
342 	/* Check that core can p2v and v2p over memory reference arguments */
343 	if (test_v2p2v(src) || test_v2p2v(src + sz - 1) ||
344 	    test_v2p2v(dst) || test_v2p2v(dst + sz - 1))
345 		return TEE_ERROR_SECURITY;
346 
347 	if (cache_operation(TEE_CACHEFLUSH, dst, sz) != TEE_SUCCESS)
348 		return TEE_ERROR_GENERIC;
349 
350 	memcpy(dst, src, sz);
351 
352 	if (cache_operation(TEE_CACHEFLUSH, dst, sz) != TEE_SUCCESS)
353 		return TEE_ERROR_GENERIC;
354 
355 	return TEE_SUCCESS;
356 }
357 
358 /*
359  * Trusted Application Entry Points
360  */
361 
362 static TEE_Result create_ta(void)
363 {
364 	DMSG("create entry point for pseudo TA \"%s\"", TA_NAME);
365 	return TEE_SUCCESS;
366 }
367 
368 static void destroy_ta(void)
369 {
370 	DMSG("destroy entry point for pseudo ta \"%s\"", TA_NAME);
371 }
372 
373 static TEE_Result open_session(uint32_t nParamTypes __unused,
374 		TEE_Param pParams[TEE_NUM_PARAMS] __unused,
375 		void **ppSessionContext __unused)
376 {
377 	DMSG("open entry point for pseudo ta \"%s\"", TA_NAME);
378 	return TEE_SUCCESS;
379 }
380 
381 static void close_session(void *pSessionContext __unused)
382 {
383 	DMSG("close entry point for pseudo ta \"%s\"", TA_NAME);
384 }
385 
386 static TEE_Result invoke_command(void *pSessionContext __unused,
387 		uint32_t nCommandID, uint32_t nParamTypes,
388 		TEE_Param pParams[TEE_NUM_PARAMS])
389 {
390 	FMSG("command entry point for pseudo ta \"%s\"", TA_NAME);
391 
392 	switch (nCommandID) {
393 	case PTA_INVOKE_TESTS_CMD_TRACE:
394 		return test_trace(nParamTypes, pParams);
395 	case PTA_INVOKE_TESTS_CMD_PARAMS:
396 		return test_entry_params(nParamTypes, pParams);
397 	case PTA_INVOKE_TESTS_CMD_COPY_NSEC_TO_SEC:
398 		return test_inject_sdp(nParamTypes, pParams);
399 	case PTA_INVOKE_TESTS_CMD_READ_MODIFY_SEC:
400 		return test_transform_sdp(nParamTypes, pParams);
401 	case PTA_INVOKE_TESTS_CMD_COPY_SEC_TO_NSEC:
402 		return test_dump_sdp(nParamTypes, pParams);
403 	case PTA_INVOKE_TESTS_CMD_SELF_TESTS:
404 		return core_self_tests(nParamTypes, pParams);
405 #if defined(CFG_WITH_USER_TA)
406 	case PTA_INVOKE_TESTS_CMD_FS_HTREE:
407 		return core_fs_htree_tests(nParamTypes, pParams);
408 #endif
409 	case PTA_INVOKE_TESTS_CMD_MUTEX:
410 		return core_mutex_tests(nParamTypes, pParams);
411 	case PTA_INVOKE_TESTS_CMD_LOCKDEP:
412 		return core_lockdep_tests(nParamTypes, pParams);
413 	case PTA_INVOKE_TEST_CMD_AES_PERF:
414 		return core_aes_perf_tests(nParamTypes, pParams);
415 	default:
416 		break;
417 	}
418 	return TEE_ERROR_BAD_PARAMETERS;
419 }
420 
421 pseudo_ta_register(.uuid = PTA_INVOKE_TESTS_UUID, .name = TA_NAME,
422 		   .flags = PTA_DEFAULT_FLAGS | TA_FLAG_SECURE_DATA_PATH |
423 			    TA_FLAG_CONCURRENT | TA_FLAG_DEVICE_ENUM,
424 		   .create_entry_point = create_ta,
425 		   .destroy_entry_point = destroy_ta,
426 		   .open_session_entry_point = open_session,
427 		   .close_session_entry_point = close_session,
428 		   .invoke_command_entry_point = invoke_command);
429