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