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