1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3 * Copyright (c) 2016, Linaro Limited
4 * All rights reserved.
5 */
6
7 #include <pta_invoke_tests.h>
8 #include <string.h>
9 #include <ta_sdp_basic.h>
10 #include <tee_api.h>
11 #include <tee_internal_api_extensions.h>
12 #include <tee_internal_api.h>
13 #include <tee_ta_api.h>
14 #include <trace.h>
15
16
17 /*
18 * Basic Secure Data Path access test commands:
19 * - command INJECT: copy from non secure input into secure output.
20 * - command TRANSFROM: read, transform and write from/to secure in/out.
21 * - command DUMP: copy from secure input into non secure output.
22 */
23
cmd_inject(uint32_t types,TEE_Param params[TEE_NUM_PARAMS])24 static TEE_Result cmd_inject(uint32_t types,
25 TEE_Param params[TEE_NUM_PARAMS])
26 {
27 TEE_Result rc = TEE_ERROR_GENERIC;
28 const int sec_idx = 1; /* highlight secure buffer index */
29 const int ns_idx = 0; /* highlight nonsecure buffer index */
30
31 if (types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT,
32 TEE_PARAM_TYPE_MEMREF_OUTPUT,
33 TEE_PARAM_TYPE_NONE,
34 TEE_PARAM_TYPE_NONE)) {
35 EMSG("bad parameters %x", (unsigned)types);
36 return TEE_ERROR_BAD_PARAMETERS;
37 }
38
39 if (params[sec_idx].memref.size < params[ns_idx].memref.size)
40 return TEE_ERROR_SHORT_BUFFER;
41
42 /*
43 * We could rely on the TEE to provide consistent buffer/size values
44 * to reference a buffer with a unique and consistent secure attribute
45 * value. Hence it is safe enough (and more optimal) to test only the
46 * secure attribute of a single byte of it. Yet, since the current
47 * test does not deal with performance, let check the secure attribute
48 * of each byte of the buffer.
49 */
50 rc = TEE_CheckMemoryAccessRights(TEE_MEMORY_ACCESS_ANY_OWNER |
51 TEE_MEMORY_ACCESS_READ |
52 TEE_MEMORY_ACCESS_NONSECURE,
53 params[ns_idx].memref.buffer,
54 params[ns_idx].memref.size);
55 if (rc != TEE_SUCCESS) {
56 EMSG("TEE_CheckMemoryAccessRights(nsec) failed %x", rc);
57 return rc;
58 }
59
60 rc = TEE_CheckMemoryAccessRights(TEE_MEMORY_ACCESS_ANY_OWNER |
61 TEE_MEMORY_ACCESS_WRITE |
62 TEE_MEMORY_ACCESS_SECURE,
63 params[sec_idx].memref.buffer,
64 params[sec_idx].memref.size);
65 if (rc != TEE_SUCCESS) {
66 EMSG("TEE_CheckMemoryAccessRights(secure) failed %x", rc);
67 return rc;
68 }
69
70
71 #ifdef CFG_CACHE_API
72 /*
73 * we should invalidate cache (here we assume buffer were not
74 * filled through cpu core caches. We flush buffers so that
75 * cache is not corrupted in cache target buffer not aligned
76 * on cache line size.
77 */
78 rc = TEE_CacheFlush(params[sec_idx].memref.buffer,
79 params[sec_idx].memref.size);
80 if (rc != TEE_SUCCESS) {
81 EMSG("TEE_CacheFlush(%p, %x) failed: 0x%x",
82 params[sec_idx].memref.buffer,
83 params[sec_idx].memref.size, rc);
84 return rc;
85 }
86 #endif /* CFG_CACHE_API */
87
88 /* inject data */
89 TEE_MemMove(params[sec_idx].memref.buffer,
90 params[ns_idx].memref.buffer,
91 params[sec_idx].memref.size);
92
93 #ifdef CFG_CACHE_API
94 rc = TEE_CacheFlush(params[sec_idx].memref.buffer,
95 params[sec_idx].memref.size);
96 if (rc != TEE_SUCCESS) {
97 EMSG("TEE_CacheFlush(%p, %x) failed: 0x%x",
98 params[sec_idx].memref.buffer,
99 params[sec_idx].memref.size, rc);
100 return rc;
101 }
102 #endif /* CFG_CACHE_API */
103
104 return rc;
105 }
106
cmd_transform(uint32_t types,TEE_Param params[TEE_NUM_PARAMS])107 static TEE_Result cmd_transform(uint32_t types,
108 TEE_Param params[TEE_NUM_PARAMS])
109 {
110 TEE_Result rc = TEE_ERROR_GENERIC;
111 unsigned char *p = NULL;
112 size_t sz = 0;
113
114 if (types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
115 TEE_PARAM_TYPE_NONE,
116 TEE_PARAM_TYPE_NONE,
117 TEE_PARAM_TYPE_NONE))
118 return TEE_ERROR_BAD_PARAMETERS;
119
120 /*
121 * We could rely on the TEE to provide consistent buffer/size values
122 * to reference a buffer with a unique and consistent secure attribute
123 * value. Hence it is safe enough (and more optimal) to test only the
124 * secure attribute of a single byte of it. Yet, since the current
125 * test does not deal with performance, let check the secure attribute
126 * of each byte of the buffer.
127 */
128 rc = TEE_CheckMemoryAccessRights(TEE_MEMORY_ACCESS_ANY_OWNER |
129 TEE_MEMORY_ACCESS_READ |
130 TEE_MEMORY_ACCESS_WRITE |
131 TEE_MEMORY_ACCESS_SECURE,
132 params[0].memref.buffer,
133 params[0].memref.size);
134 if (rc != TEE_SUCCESS) {
135 EMSG("TEE_CheckMemoryAccessRights(secure) failed %x", rc);
136 return rc;
137 }
138
139
140 #ifdef CFG_CACHE_API
141 /*
142 * we should invalidate cache (here we assume buffer were not
143 * filled through cpu core caches. We flush buffers so that
144 * cache is not corrupted in cache target buffer not aligned
145 * on cache line size.
146 */
147 rc = TEE_CacheFlush(params[0].memref.buffer,
148 params[0].memref.size);
149 if (rc != TEE_SUCCESS) {
150 EMSG("TEE_CacheFlush(%p, %x) failed: 0x%x",
151 params[0].memref.buffer,
152 params[0].memref.size, rc);
153 return rc;
154 }
155 #endif /* CFG_CACHE_API */
156
157 /* transform the data */
158 p = (unsigned char *)params[0].memref.buffer;
159 sz = params[0].memref.size;
160 for (; sz; sz--, p++)
161 *p = ~(*p) + 1;
162
163 #ifdef CFG_CACHE_API
164 rc = TEE_CacheFlush(params[0].memref.buffer,
165 params[0].memref.size);
166 if (rc != TEE_SUCCESS) {
167 EMSG("TEE_CacheFlush(%p, %x) failed: 0x%x",
168 params[0].memref.buffer,
169 params[0].memref.size, rc);
170 return rc;
171 }
172 #endif /* CFG_CACHE_API */
173
174 return rc;
175 }
176
cmd_dump(uint32_t types,TEE_Param params[TEE_NUM_PARAMS])177 static TEE_Result cmd_dump(uint32_t types,
178 TEE_Param params[TEE_NUM_PARAMS])
179 {
180 TEE_Result rc = TEE_ERROR_GENERIC;
181 const int sec_idx = 0; /* highlight secure buffer index */
182 const int ns_idx = 1; /* highlight nonsecure buffer index */
183
184 if (types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT,
185 TEE_PARAM_TYPE_MEMREF_OUTPUT,
186 TEE_PARAM_TYPE_NONE,
187 TEE_PARAM_TYPE_NONE))
188 return TEE_ERROR_BAD_PARAMETERS;
189
190 if (params[ns_idx].memref.size < params[sec_idx].memref.size)
191 return TEE_ERROR_SHORT_BUFFER;
192
193 /*
194 * We could rely on the TEE to provide consistent buffer/size values
195 * to reference a buffer with a unique and consistent secure attribute
196 * value. Hence it is safe enough (and more optimal) to test only the
197 * secure attribute of a single byte of it. Yet, since the current
198 * test does not deal with performance, let check the secure attribute
199 * of each byte of the buffer.
200 */
201 rc = TEE_CheckMemoryAccessRights(TEE_MEMORY_ACCESS_ANY_OWNER |
202 TEE_MEMORY_ACCESS_WRITE |
203 TEE_MEMORY_ACCESS_NONSECURE,
204 params[ns_idx].memref.buffer,
205 params[ns_idx].memref.size);
206 if (rc != TEE_SUCCESS) {
207 EMSG("TEE_CheckMemoryAccessRights(nsec) failed %x", rc);
208 return rc;
209 }
210
211 rc = TEE_CheckMemoryAccessRights(TEE_MEMORY_ACCESS_ANY_OWNER |
212 TEE_MEMORY_ACCESS_READ |
213 TEE_MEMORY_ACCESS_SECURE,
214 params[sec_idx].memref.buffer,
215 params[sec_idx].memref.size);
216 if (rc != TEE_SUCCESS) {
217 EMSG("TEE_CheckMemoryAccessRights(secure) failed %x", rc);
218 return rc;
219 }
220
221 #ifdef CFG_CACHE_API
222 /*
223 * we should invalidate cache (here we assume buffer were not
224 * filled through cpu core caches. We flush buffers so that
225 * cache is not corrupted in cache target buffer not aligned
226 * on cache line size.
227 */
228 rc = TEE_CacheFlush(params[sec_idx].memref.buffer,
229 params[sec_idx].memref.size);
230 if (rc != TEE_SUCCESS) {
231 EMSG("TEE_CacheFlush(%p, %x) failed: 0x%x",
232 params[sec_idx].memref.buffer,
233 params[sec_idx].memref.size, rc);
234 return rc;
235 }
236 #endif /* CFG_CACHE_API */
237
238 /* dump the data */
239 TEE_MemMove(params[ns_idx].memref.buffer,
240 params[sec_idx].memref.buffer,
241 params[sec_idx].memref.size);
242
243 return rc;
244 }
245
cmd_invoke(uint32_t nParamTypes,TEE_Param pParams[TEE_NUM_PARAMS],uint32_t nCommandID)246 static TEE_Result cmd_invoke(uint32_t nParamTypes,
247 TEE_Param pParams[TEE_NUM_PARAMS],
248 uint32_t nCommandID)
249 {
250 const TEE_UUID uuid = TA_SDP_BASIC_UUID;
251 static TEE_TASessionHandle sess = TEE_HANDLE_NULL;
252 uint32_t ret_orig = 0;
253 TEE_Result res = TEE_ERROR_GENERIC;
254
255 if (sess == TEE_HANDLE_NULL) {
256 res = TEE_OpenTASession(&uuid, TEE_TIMEOUT_INFINITE, 0, NULL,
257 &sess, &ret_orig);
258 if (res != TEE_SUCCESS) {
259 EMSG("SDP basic test TA: TEE_OpenTASession() FAILED \n");
260 goto cleanup_return;
261 }
262
263 }
264
265 res = TEE_InvokeTACommand(sess, TEE_TIMEOUT_INFINITE,
266 nCommandID, nParamTypes, pParams, &ret_orig);
267 if (res != TEE_SUCCESS) {
268 EMSG("SDP basic test TA: TEE_OpenTASession() FAILED %x/%d\n",
269 res, ret_orig);
270 }
271
272 cleanup_return:
273 if (res != TEE_SUCCESS) {
274 TEE_CloseTASession(sess);
275 sess = TEE_HANDLE_NULL;
276 }
277 return res;
278 }
279
cmd_invoke_pta(uint32_t nParamTypes,TEE_Param pParams[TEE_NUM_PARAMS],uint32_t nCommandID)280 static TEE_Result cmd_invoke_pta(uint32_t nParamTypes,
281 TEE_Param pParams[TEE_NUM_PARAMS],
282 uint32_t nCommandID)
283 {
284 const TEE_UUID uuid = PTA_INVOKE_TESTS_UUID;
285 static TEE_TASessionHandle sess = TEE_HANDLE_NULL;
286 uint32_t ret_orig = 0;
287 TEE_Result res = TEE_ERROR_GENERIC;
288
289 if (sess == TEE_HANDLE_NULL) {
290 res = TEE_OpenTASession(&uuid, TEE_TIMEOUT_INFINITE, 0, NULL,
291 &sess, &ret_orig);
292 if (res != TEE_SUCCESS) {
293 EMSG("SDP basic test TA: TEE_OpenTASession() FAILED \n");
294 goto cleanup_return;
295 }
296
297 }
298
299 res = TEE_InvokeTACommand(sess, TEE_TIMEOUT_INFINITE,
300 nCommandID, nParamTypes, pParams, &ret_orig);
301 if (res != TEE_SUCCESS) {
302 EMSG("SDP basic test TA: TEE_OpenTASession() FAILED %x/%d\n",
303 res, ret_orig);
304 }
305
306 cleanup_return:
307 if (res != TEE_SUCCESS) {
308 TEE_CloseTASession(sess);
309 sess = TEE_HANDLE_NULL;
310 }
311 return res;
312 }
313
TA_CreateEntryPoint(void)314 TEE_Result TA_CreateEntryPoint(void)
315 {
316 return TEE_SUCCESS;
317 }
318
TA_DestroyEntryPoint(void)319 void TA_DestroyEntryPoint(void)
320 {
321 }
322
TA_OpenSessionEntryPoint(uint32_t nParamTypes,TEE_Param pParams[TEE_NUM_PARAMS],void ** ppSessionContext)323 TEE_Result TA_OpenSessionEntryPoint(uint32_t nParamTypes,
324 TEE_Param pParams[TEE_NUM_PARAMS],
325 void **ppSessionContext)
326 {
327 (void)nParamTypes;
328 (void)pParams;
329 (void)ppSessionContext;
330 return TEE_SUCCESS;
331 }
332
TA_CloseSessionEntryPoint(void * pSessionContext)333 void TA_CloseSessionEntryPoint(void *pSessionContext)
334 {
335 (void)pSessionContext;
336 }
337
TA_InvokeCommandEntryPoint(void * pSessionContext,uint32_t nCommandID,uint32_t nParamTypes,TEE_Param pParams[TEE_NUM_PARAMS])338 TEE_Result TA_InvokeCommandEntryPoint(void *pSessionContext,
339 uint32_t nCommandID, uint32_t nParamTypes,
340 TEE_Param pParams[TEE_NUM_PARAMS])
341 {
342 (void)pSessionContext;
343
344 switch (nCommandID) {
345 case TA_SDP_BASIC_CMD_INJECT:
346 return cmd_inject(nParamTypes, pParams);
347 case TA_SDP_BASIC_CMD_TRANSFORM:
348 return cmd_transform(nParamTypes, pParams);
349 case TA_SDP_BASIC_CMD_DUMP:
350 return cmd_dump(nParamTypes, pParams);
351
352 case TA_SDP_BASIC_CMD_INVOKE_INJECT:
353 return cmd_invoke(nParamTypes, pParams, TA_SDP_BASIC_CMD_INJECT);
354 case TA_SDP_BASIC_CMD_INVOKE_TRANSFORM:
355 return cmd_invoke(nParamTypes, pParams, TA_SDP_BASIC_CMD_TRANSFORM);
356 case TA_SDP_BASIC_CMD_INVOKE_DUMP:
357 return cmd_invoke(nParamTypes, pParams, TA_SDP_BASIC_CMD_DUMP);
358
359 case TA_SDP_BASIC_CMD_PTA_INJECT:
360 return cmd_invoke_pta(nParamTypes, pParams, PTA_INVOKE_TESTS_CMD_COPY_NSEC_TO_SEC);
361 case TA_SDP_BASIC_CMD_PTA_TRANSFORM:
362 return cmd_invoke_pta(nParamTypes, pParams, PTA_INVOKE_TESTS_CMD_READ_MODIFY_SEC);
363 case TA_SDP_BASIC_CMD_PTA_DUMP:
364 return cmd_invoke_pta(nParamTypes, pParams, PTA_INVOKE_TESTS_CMD_COPY_SEC_TO_NSEC);
365
366 default:
367 return TEE_ERROR_BAD_PARAMETERS;
368 }
369 }
370