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 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 32 static int test_v2p2v(void *va) 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_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 * Check PTA can be invoked with a memory reference on a NULL buffer 75 */ 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 */ 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)) 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)) 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)) 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)) 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 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) || test_v2p2v(src + sz - 1) || 281 test_v2p2v(dst) || test_v2p2v(dst + sz - 1)) 282 return TEE_ERROR_SECURITY; 283 284 if (cache_operation(TEE_CACHEFLUSH, dst, sz) != TEE_SUCCESS) 285 return TEE_ERROR_GENERIC; 286 287 memcpy(dst, src, sz); 288 289 if (cache_operation(TEE_CACHEFLUSH, dst, sz) != TEE_SUCCESS) 290 return TEE_ERROR_GENERIC; 291 292 return TEE_SUCCESS; 293 } 294 295 static TEE_Result test_transform_sdp(uint32_t type, TEE_Param p[TEE_NUM_PARAMS]) 296 { 297 char *buf = p[0].memref.buffer; 298 size_t sz = p[0].memref.size; 299 uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, 300 TEE_PARAM_TYPE_NONE, 301 TEE_PARAM_TYPE_NONE, 302 TEE_PARAM_TYPE_NONE); 303 304 if (exp_pt != type) { 305 DMSG("bad parameter types"); 306 return TEE_ERROR_BAD_PARAMETERS; 307 } 308 309 if (!core_vbuf_is(CORE_MEM_SDP_MEM, buf, sz)) { 310 DMSG("bad memref secure attribute"); 311 return TEE_ERROR_BAD_PARAMETERS; 312 } 313 314 if (!sz) 315 return TEE_SUCCESS; 316 317 /* Check that core can p2v and v2p over memory reference arguments */ 318 if (test_v2p2v(buf) || test_v2p2v(buf + sz - 1)) 319 return TEE_ERROR_SECURITY; 320 321 if (cache_operation(TEE_CACHEFLUSH, buf, sz) != TEE_SUCCESS) 322 return TEE_ERROR_GENERIC; 323 324 for (; sz; sz--, buf++) 325 *buf = ~(*buf) + 1; 326 327 if (cache_operation(TEE_CACHEFLUSH, buf, sz) != TEE_SUCCESS) 328 return TEE_ERROR_GENERIC; 329 330 return TEE_SUCCESS; 331 } 332 333 static TEE_Result test_dump_sdp(uint32_t type, TEE_Param p[TEE_NUM_PARAMS]) 334 { 335 char *src = p[0].memref.buffer; 336 char *dst = p[1].memref.buffer; 337 size_t sz = p[0].memref.size; 338 uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, 339 TEE_PARAM_TYPE_MEMREF_OUTPUT, 340 TEE_PARAM_TYPE_NONE, 341 TEE_PARAM_TYPE_NONE); 342 343 if (exp_pt != type) { 344 DMSG("bad parameter types"); 345 return TEE_ERROR_BAD_PARAMETERS; 346 } 347 348 if (p[1].memref.size < sz) { 349 p[1].memref.size = sz; 350 return TEE_ERROR_SHORT_BUFFER; 351 } 352 353 if (!core_vbuf_is(CORE_MEM_SDP_MEM, src, sz) || 354 !core_vbuf_is(CORE_MEM_NON_SEC, dst, sz)) { 355 DMSG("bad memref secure attribute"); 356 return TEE_ERROR_BAD_PARAMETERS; 357 } 358 359 if (!sz) 360 return TEE_SUCCESS; 361 362 /* Check that core can p2v and v2p over memory reference arguments */ 363 if (test_v2p2v(src) || test_v2p2v(src + sz - 1) || 364 test_v2p2v(dst) || test_v2p2v(dst + sz - 1)) 365 return TEE_ERROR_SECURITY; 366 367 if (cache_operation(TEE_CACHEFLUSH, dst, sz) != TEE_SUCCESS) 368 return TEE_ERROR_GENERIC; 369 370 memcpy(dst, src, sz); 371 372 if (cache_operation(TEE_CACHEFLUSH, dst, sz) != TEE_SUCCESS) 373 return TEE_ERROR_GENERIC; 374 375 return TEE_SUCCESS; 376 } 377 378 /* 379 * Trusted Application Entry Points 380 */ 381 382 static TEE_Result create_ta(void) 383 { 384 DMSG("create entry point for pseudo TA \"%s\"", TA_NAME); 385 return TEE_SUCCESS; 386 } 387 388 static void destroy_ta(void) 389 { 390 DMSG("destroy entry point for pseudo ta \"%s\"", TA_NAME); 391 } 392 393 static TEE_Result open_session(uint32_t nParamTypes __unused, 394 TEE_Param pParams[TEE_NUM_PARAMS] __unused, 395 void **ppSessionContext __unused) 396 { 397 DMSG("open entry point for pseudo ta \"%s\"", TA_NAME); 398 return TEE_SUCCESS; 399 } 400 401 static void close_session(void *pSessionContext __unused) 402 { 403 DMSG("close entry point for pseudo ta \"%s\"", TA_NAME); 404 } 405 406 static TEE_Result invoke_command(void *pSessionContext __unused, 407 uint32_t nCommandID, uint32_t nParamTypes, 408 TEE_Param pParams[TEE_NUM_PARAMS]) 409 { 410 FMSG("command entry point for pseudo ta \"%s\"", TA_NAME); 411 412 switch (nCommandID) { 413 case PTA_INVOKE_TESTS_CMD_TRACE: 414 return test_trace(nParamTypes, pParams); 415 case PTA_INVOKE_TESTS_CMD_PARAMS: 416 return test_entry_params(nParamTypes, pParams); 417 case PTA_INVOKE_TESTS_CMD_MEMREF_NULL: 418 return test_entry_memref_null(nParamTypes, pParams); 419 case PTA_INVOKE_TESTS_CMD_COPY_NSEC_TO_SEC: 420 return test_inject_sdp(nParamTypes, pParams); 421 case PTA_INVOKE_TESTS_CMD_READ_MODIFY_SEC: 422 return test_transform_sdp(nParamTypes, pParams); 423 case PTA_INVOKE_TESTS_CMD_COPY_SEC_TO_NSEC: 424 return test_dump_sdp(nParamTypes, pParams); 425 case PTA_INVOKE_TESTS_CMD_SELF_TESTS: 426 return core_self_tests(nParamTypes, pParams); 427 #if defined(CFG_WITH_USER_TA) 428 case PTA_INVOKE_TESTS_CMD_FS_HTREE: 429 return core_fs_htree_tests(nParamTypes, pParams); 430 #endif 431 case PTA_INVOKE_TESTS_CMD_MUTEX: 432 return core_mutex_tests(nParamTypes, pParams); 433 case PTA_INVOKE_TESTS_CMD_LOCKDEP: 434 return core_lockdep_tests(nParamTypes, pParams); 435 case PTA_INVOKE_TEST_CMD_AES_PERF: 436 return core_aes_perf_tests(nParamTypes, pParams); 437 default: 438 break; 439 } 440 return TEE_ERROR_BAD_PARAMETERS; 441 } 442 443 pseudo_ta_register(.uuid = PTA_INVOKE_TESTS_UUID, .name = TA_NAME, 444 .flags = PTA_DEFAULT_FLAGS | TA_FLAG_SECURE_DATA_PATH | 445 TA_FLAG_CONCURRENT | TA_FLAG_DEVICE_ENUM, 446 .create_entry_point = create_ta, 447 .destroy_entry_point = destroy_ta, 448 .open_session_entry_point = open_session, 449 .close_session_entry_point = close_session, 450 .invoke_command_entry_point = invoke_command); 451