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, 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 */ 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/%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 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 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 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 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 385 static void destroy_ta(void) 386 { 387 DMSG("destroy entry point for pseudo ta \"%s\"", TA_NAME); 388 } 389 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 398 static void close_session(void *pSessionContext __unused) 399 { 400 DMSG("close entry point for pseudo ta \"%s\"", TA_NAME); 401 } 402 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