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/%" PRIu32 " - %p/%" PRIu32 "zu - %p/%" PRIu32 "zu - %p/%" PRIu32 "zu",
180 p[0].memref.buffer, p[0].memref.size,
181 p[1].memref.buffer, p[1].memref.size,
182 p[2].memref.buffer, p[2].memref.size,
183 p[3].memref.buffer, p[3].memref.size);
184
185 /* case 3a: 1 in/out memref argument */
186 if ((TEE_PARAM_TYPE_GET(type, 0) == TEE_PARAM_TYPE_MEMREF_INOUT) &&
187 (TEE_PARAM_TYPE_GET(type, 1) == TEE_PARAM_TYPE_NONE) &&
188 (TEE_PARAM_TYPE_GET(type, 2) == TEE_PARAM_TYPE_NONE) &&
189 (TEE_PARAM_TYPE_GET(type, 3) == TEE_PARAM_TYPE_NONE)) {
190 in = (uint8_t *)p[0].memref.buffer;
191 if (test_v2p2v(in, p[0].memref.size))
192 return TEE_ERROR_SECURITY;
193 d8 = 0;
194 for (i = 0; i < p[0].memref.size; i++)
195 d8 += in[i];
196 *(uint8_t *)p[0].memref.buffer = d8;
197 return TEE_SUCCESS;
198 }
199 /* case 3b: 1 in/out memref argument */
200 if ((TEE_PARAM_TYPE_GET(type, 0) == TEE_PARAM_TYPE_NONE) &&
201 (TEE_PARAM_TYPE_GET(type, 1) == TEE_PARAM_TYPE_MEMREF_INOUT) &&
202 (TEE_PARAM_TYPE_GET(type, 2) == TEE_PARAM_TYPE_NONE) &&
203 (TEE_PARAM_TYPE_GET(type, 3) == TEE_PARAM_TYPE_NONE)) {
204 in = (uint8_t *)p[1].memref.buffer;
205 if (test_v2p2v(in, p[1].memref.size))
206 return TEE_ERROR_SECURITY;
207 d8 = 0;
208 for (i = 0; i < p[1].memref.size; i++)
209 d8 += in[i];
210 *(uint8_t *)p[1].memref.buffer = d8;
211 return TEE_SUCCESS;
212 }
213 /* case 3c: 1 in/out memref argument */
214 if ((TEE_PARAM_TYPE_GET(type, 0) == TEE_PARAM_TYPE_NONE) &&
215 (TEE_PARAM_TYPE_GET(type, 1) == TEE_PARAM_TYPE_NONE) &&
216 (TEE_PARAM_TYPE_GET(type, 2) == TEE_PARAM_TYPE_MEMREF_INOUT) &&
217 (TEE_PARAM_TYPE_GET(type, 3) == TEE_PARAM_TYPE_NONE)) {
218 in = (uint8_t *)p[2].memref.buffer;
219 if (test_v2p2v(in, p[2].memref.size))
220 return TEE_ERROR_SECURITY;
221 d8 = 0;
222 for (i = 0; i < p[2].memref.size; i++)
223 d8 += in[i];
224 *(uint8_t *)p[2].memref.buffer = d8;
225 return TEE_SUCCESS;
226 }
227 /* case 3d: 1 in/out memref argument */
228 if ((TEE_PARAM_TYPE_GET(type, 0) == TEE_PARAM_TYPE_NONE) &&
229 (TEE_PARAM_TYPE_GET(type, 1) == TEE_PARAM_TYPE_NONE) &&
230 (TEE_PARAM_TYPE_GET(type, 2) == TEE_PARAM_TYPE_NONE) &&
231 (TEE_PARAM_TYPE_GET(type, 3) == TEE_PARAM_TYPE_MEMREF_INOUT)) {
232 in = (uint8_t *)p[3].memref.buffer;
233 if (test_v2p2v(in, p[3].memref.size))
234 return TEE_ERROR_SECURITY;
235 d8 = 0;
236 for (i = 0; i < p[3].memref.size; i++)
237 d8 += in[i];
238 *(uint8_t *)p[3].memref.buffer = d8;
239 return TEE_SUCCESS;
240 }
241
242 EMSG("unexpected parameters");
243 return TEE_ERROR_BAD_PARAMETERS;
244 }
245
246 /*
247 * Test access to Secure Data Path memory from pseudo TAs
248 */
249
test_inject_sdp(uint32_t type,TEE_Param p[TEE_NUM_PARAMS])250 static TEE_Result test_inject_sdp(uint32_t type, TEE_Param p[TEE_NUM_PARAMS])
251 {
252 char *src = p[0].memref.buffer;
253 char *dst = p[1].memref.buffer;
254 size_t sz = p[0].memref.size;
255 uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT,
256 TEE_PARAM_TYPE_MEMREF_OUTPUT,
257 TEE_PARAM_TYPE_NONE,
258 TEE_PARAM_TYPE_NONE);
259
260 if (exp_pt != type) {
261 DMSG("bad parameter types");
262 return TEE_ERROR_BAD_PARAMETERS;
263 }
264
265 if (p[1].memref.size < sz) {
266 p[1].memref.size = sz;
267 return TEE_ERROR_SHORT_BUFFER;
268 }
269
270 if (!core_vbuf_is(CORE_MEM_NON_SEC, src, sz) ||
271 !core_vbuf_is(CORE_MEM_SDP_MEM, dst, sz)) {
272 DMSG("bad memref secure attribute");
273 return TEE_ERROR_BAD_PARAMETERS;
274 }
275
276 if (!sz)
277 return TEE_SUCCESS;
278
279 /* Check that core can p2v and v2p over memory reference arguments */
280 if (test_v2p2v(src, sz) || test_v2p2v(dst, sz))
281 return TEE_ERROR_SECURITY;
282
283 if (cache_operation(TEE_CACHEFLUSH, dst, sz) != TEE_SUCCESS)
284 return TEE_ERROR_GENERIC;
285
286 memcpy(dst, src, sz);
287
288 if (cache_operation(TEE_CACHEFLUSH, dst, sz) != TEE_SUCCESS)
289 return TEE_ERROR_GENERIC;
290
291 return TEE_SUCCESS;
292 }
293
test_transform_sdp(uint32_t type,TEE_Param p[TEE_NUM_PARAMS])294 static TEE_Result test_transform_sdp(uint32_t type, TEE_Param p[TEE_NUM_PARAMS])
295 {
296 char *buf = p[0].memref.buffer;
297 size_t sz = p[0].memref.size;
298 uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
299 TEE_PARAM_TYPE_NONE,
300 TEE_PARAM_TYPE_NONE,
301 TEE_PARAM_TYPE_NONE);
302
303 if (exp_pt != type) {
304 DMSG("bad parameter types");
305 return TEE_ERROR_BAD_PARAMETERS;
306 }
307
308 if (!core_vbuf_is(CORE_MEM_SDP_MEM, buf, sz)) {
309 DMSG("bad memref secure attribute");
310 return TEE_ERROR_BAD_PARAMETERS;
311 }
312
313 if (!sz)
314 return TEE_SUCCESS;
315
316 /* Check that core can p2v and v2p over memory reference arguments */
317 if (test_v2p2v(buf, sz))
318 return TEE_ERROR_SECURITY;
319
320 if (cache_operation(TEE_CACHEFLUSH, buf, sz) != TEE_SUCCESS)
321 return TEE_ERROR_GENERIC;
322
323 for (; sz; sz--, buf++)
324 *buf = ~(*buf) + 1;
325
326 if (cache_operation(TEE_CACHEFLUSH, buf, sz) != TEE_SUCCESS)
327 return TEE_ERROR_GENERIC;
328
329 return TEE_SUCCESS;
330 }
331
test_dump_sdp(uint32_t type,TEE_Param p[TEE_NUM_PARAMS])332 static TEE_Result test_dump_sdp(uint32_t type, TEE_Param p[TEE_NUM_PARAMS])
333 {
334 char *src = p[0].memref.buffer;
335 char *dst = p[1].memref.buffer;
336 size_t sz = p[0].memref.size;
337 uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT,
338 TEE_PARAM_TYPE_MEMREF_OUTPUT,
339 TEE_PARAM_TYPE_NONE,
340 TEE_PARAM_TYPE_NONE);
341
342 if (exp_pt != type) {
343 DMSG("bad parameter types");
344 return TEE_ERROR_BAD_PARAMETERS;
345 }
346
347 if (p[1].memref.size < sz) {
348 p[1].memref.size = sz;
349 return TEE_ERROR_SHORT_BUFFER;
350 }
351
352 if (!core_vbuf_is(CORE_MEM_SDP_MEM, src, sz) ||
353 !core_vbuf_is(CORE_MEM_NON_SEC, dst, sz)) {
354 DMSG("bad memref secure attribute");
355 return TEE_ERROR_BAD_PARAMETERS;
356 }
357
358 if (!sz)
359 return TEE_SUCCESS;
360
361 /* Check that core can p2v and v2p over memory reference arguments */
362 if (test_v2p2v(src, sz) || test_v2p2v(dst, sz))
363 return TEE_ERROR_SECURITY;
364
365 if (cache_operation(TEE_CACHEFLUSH, dst, sz) != TEE_SUCCESS)
366 return TEE_ERROR_GENERIC;
367
368 memcpy(dst, src, sz);
369
370 if (cache_operation(TEE_CACHEFLUSH, dst, sz) != TEE_SUCCESS)
371 return TEE_ERROR_GENERIC;
372
373 return TEE_SUCCESS;
374 }
375
376 /*
377 * Trusted Application Entry Points
378 */
379
create_ta(void)380 static TEE_Result create_ta(void)
381 {
382 DMSG("create entry point for pseudo TA \"%s\"", TA_NAME);
383 return TEE_SUCCESS;
384 }
385
destroy_ta(void)386 static void destroy_ta(void)
387 {
388 DMSG("destroy entry point for pseudo ta \"%s\"", TA_NAME);
389 }
390
open_session(uint32_t nParamTypes __unused,TEE_Param pParams[TEE_NUM_PARAMS]__unused,void ** ppSessionContext __unused)391 static TEE_Result open_session(uint32_t nParamTypes __unused,
392 TEE_Param pParams[TEE_NUM_PARAMS] __unused,
393 void **ppSessionContext __unused)
394 {
395 DMSG("open entry point for pseudo ta \"%s\"", TA_NAME);
396 return TEE_SUCCESS;
397 }
398
close_session(void * pSessionContext __unused)399 static void close_session(void *pSessionContext __unused)
400 {
401 DMSG("close entry point for pseudo ta \"%s\"", TA_NAME);
402 }
403
invoke_command(void * pSessionContext __unused,uint32_t nCommandID,uint32_t nParamTypes,TEE_Param pParams[TEE_NUM_PARAMS])404 static TEE_Result invoke_command(void *pSessionContext __unused,
405 uint32_t nCommandID, uint32_t nParamTypes,
406 TEE_Param pParams[TEE_NUM_PARAMS])
407 {
408 FMSG("command entry point for pseudo ta \"%s\"", TA_NAME);
409
410 switch (nCommandID) {
411 case PTA_INVOKE_TESTS_CMD_TRACE:
412 return test_trace(nParamTypes, pParams);
413 case PTA_INVOKE_TESTS_CMD_PARAMS:
414 return test_entry_params(nParamTypes, pParams);
415 case PTA_INVOKE_TESTS_CMD_MEMREF_NULL:
416 return test_entry_memref_null(nParamTypes, pParams);
417 case PTA_INVOKE_TESTS_CMD_COPY_NSEC_TO_SEC:
418 return test_inject_sdp(nParamTypes, pParams);
419 case PTA_INVOKE_TESTS_CMD_READ_MODIFY_SEC:
420 return test_transform_sdp(nParamTypes, pParams);
421 case PTA_INVOKE_TESTS_CMD_COPY_SEC_TO_NSEC:
422 return test_dump_sdp(nParamTypes, pParams);
423 case PTA_INVOKE_TESTS_CMD_SELF_TESTS:
424 return core_self_tests(nParamTypes, pParams);
425 #if defined(CFG_REE_FS) && defined(CFG_WITH_USER_TA)
426 case PTA_INVOKE_TESTS_CMD_FS_HTREE:
427 return core_fs_htree_tests(nParamTypes, pParams);
428 #endif
429 case PTA_INVOKE_TESTS_CMD_MUTEX:
430 return core_mutex_tests(nParamTypes, pParams);
431 case PTA_INVOKE_TESTS_CMD_LOCKDEP:
432 return core_lockdep_tests(nParamTypes, pParams);
433 case PTA_INVOKE_TEST_CMD_AES_PERF:
434 return core_aes_perf_tests(nParamTypes, pParams);
435 default:
436 break;
437 }
438 return TEE_ERROR_BAD_PARAMETERS;
439 }
440
441 pseudo_ta_register(.uuid = PTA_INVOKE_TESTS_UUID, .name = TA_NAME,
442 .flags = PTA_DEFAULT_FLAGS | TA_FLAG_SECURE_DATA_PATH |
443 TA_FLAG_CONCURRENT | TA_FLAG_DEVICE_ENUM,
444 .create_entry_point = create_ta,
445 .destroy_entry_point = destroy_ta,
446 .open_session_entry_point = open_session,
447 .close_session_entry_point = close_session,
448 .invoke_command_entry_point = invoke_command);
449