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 %#"PRIx32, 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 %#"PRIx32, 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 %#"PRIx32, 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, %zu) failed: %#"PRIx32,
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, %zu) failed: %#"PRIx32,
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 %#"PRIx32, 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, %zu) failed: %#"PRIx32,
151 params[0].memref.buffer, params[0].memref.size, rc);
152 return rc;
153 }
154 #endif /* CFG_CACHE_API */
155
156 /* transform the data */
157 p = (unsigned char *)params[0].memref.buffer;
158 sz = params[0].memref.size;
159 for (; sz; sz--, p++)
160 *p = ~(*p) + 1;
161
162 #ifdef CFG_CACHE_API
163 rc = TEE_CacheFlush(params[0].memref.buffer,
164 params[0].memref.size);
165 if (rc != TEE_SUCCESS) {
166 EMSG("TEE_CacheFlush(%p, %zu) failed: %#"PRIx32,
167 params[0].memref.buffer, params[0].memref.size, rc);
168 return rc;
169 }
170 #endif /* CFG_CACHE_API */
171
172 return rc;
173 }
174
cmd_dump(uint32_t types,TEE_Param params[TEE_NUM_PARAMS])175 static TEE_Result cmd_dump(uint32_t types,
176 TEE_Param params[TEE_NUM_PARAMS])
177 {
178 TEE_Result rc = TEE_ERROR_GENERIC;
179 const int sec_idx = 0; /* highlight secure buffer index */
180 const int ns_idx = 1; /* highlight nonsecure buffer index */
181
182 if (types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT,
183 TEE_PARAM_TYPE_MEMREF_OUTPUT,
184 TEE_PARAM_TYPE_NONE,
185 TEE_PARAM_TYPE_NONE))
186 return TEE_ERROR_BAD_PARAMETERS;
187
188 if (params[ns_idx].memref.size < params[sec_idx].memref.size)
189 return TEE_ERROR_SHORT_BUFFER;
190
191 /*
192 * We could rely on the TEE to provide consistent buffer/size values
193 * to reference a buffer with a unique and consistent secure attribute
194 * value. Hence it is safe enough (and more optimal) to test only the
195 * secure attribute of a single byte of it. Yet, since the current
196 * test does not deal with performance, let check the secure attribute
197 * of each byte of the buffer.
198 */
199 rc = TEE_CheckMemoryAccessRights(TEE_MEMORY_ACCESS_ANY_OWNER |
200 TEE_MEMORY_ACCESS_WRITE |
201 TEE_MEMORY_ACCESS_NONSECURE,
202 params[ns_idx].memref.buffer,
203 params[ns_idx].memref.size);
204 if (rc != TEE_SUCCESS) {
205 EMSG("TEE_CheckMemoryAccessRights(nsec) failed %#"PRIx32, rc);
206 return rc;
207 }
208
209 rc = TEE_CheckMemoryAccessRights(TEE_MEMORY_ACCESS_ANY_OWNER |
210 TEE_MEMORY_ACCESS_READ |
211 TEE_MEMORY_ACCESS_SECURE,
212 params[sec_idx].memref.buffer,
213 params[sec_idx].memref.size);
214 if (rc != TEE_SUCCESS) {
215 EMSG("TEE_CheckMemoryAccessRights(secure) failed %#"PRIx32, rc);
216 return rc;
217 }
218
219 #ifdef CFG_CACHE_API
220 /*
221 * we should invalidate cache (here we assume buffer were not
222 * filled through cpu core caches. We flush buffers so that
223 * cache is not corrupted in cache target buffer not aligned
224 * on cache line size.
225 */
226 rc = TEE_CacheFlush(params[sec_idx].memref.buffer,
227 params[sec_idx].memref.size);
228 if (rc != TEE_SUCCESS) {
229 EMSG("TEE_CacheFlush(%p, %zu) failed: %#"PRIx32,
230 params[sec_idx].memref.buffer,
231 params[sec_idx].memref.size, rc);
232 return rc;
233 }
234 #endif /* CFG_CACHE_API */
235
236 /* dump the data */
237 TEE_MemMove(params[ns_idx].memref.buffer,
238 params[sec_idx].memref.buffer,
239 params[sec_idx].memref.size);
240
241 return rc;
242 }
243
cmd_invoke(uint32_t nParamTypes,TEE_Param pParams[TEE_NUM_PARAMS],uint32_t nCommandID)244 static TEE_Result cmd_invoke(uint32_t nParamTypes,
245 TEE_Param pParams[TEE_NUM_PARAMS],
246 uint32_t nCommandID)
247 {
248 const TEE_UUID uuid = TA_SDP_BASIC_UUID;
249 static TEE_TASessionHandle sess = TEE_HANDLE_NULL;
250 uint32_t ret_orig = 0;
251 TEE_Result res = TEE_ERROR_GENERIC;
252
253 if (sess == TEE_HANDLE_NULL) {
254 res = TEE_OpenTASession(&uuid, TEE_TIMEOUT_INFINITE, 0, NULL,
255 &sess, &ret_orig);
256 if (res != TEE_SUCCESS) {
257 EMSG("SDP basic test TA: TEE_OpenTASession() FAILED");
258 goto cleanup_return;
259 }
260
261 }
262
263 res = TEE_InvokeTACommand(sess, TEE_TIMEOUT_INFINITE,
264 nCommandID, nParamTypes, pParams, &ret_orig);
265 if (res != TEE_SUCCESS) {
266 EMSG("SDP basic test TA: TEE_OpenTASession() FAILED %#"PRIx32"/%"PRIu32,
267 res, ret_orig);
268 }
269
270 cleanup_return:
271 if (res != TEE_SUCCESS) {
272 TEE_CloseTASession(sess);
273 sess = TEE_HANDLE_NULL;
274 }
275 return res;
276 }
277
cmd_invoke_pta(uint32_t nParamTypes,TEE_Param pParams[TEE_NUM_PARAMS],uint32_t nCommandID)278 static TEE_Result cmd_invoke_pta(uint32_t nParamTypes,
279 TEE_Param pParams[TEE_NUM_PARAMS],
280 uint32_t nCommandID)
281 {
282 const TEE_UUID uuid = PTA_INVOKE_TESTS_UUID;
283 static TEE_TASessionHandle sess = TEE_HANDLE_NULL;
284 uint32_t ret_orig = 0;
285 TEE_Result res = TEE_ERROR_GENERIC;
286
287 if (sess == TEE_HANDLE_NULL) {
288 res = TEE_OpenTASession(&uuid, TEE_TIMEOUT_INFINITE, 0, NULL,
289 &sess, &ret_orig);
290 if (res != TEE_SUCCESS) {
291 EMSG("SDP basic test TA: TEE_OpenTASession() FAILED");
292 goto cleanup_return;
293 }
294
295 }
296
297 res = TEE_InvokeTACommand(sess, TEE_TIMEOUT_INFINITE,
298 nCommandID, nParamTypes, pParams, &ret_orig);
299 if (res != TEE_SUCCESS) {
300 EMSG("SDP basic test TA: TEE_OpenTASession() FAILED %#"PRIx32"/%"PRIu32,
301 res, ret_orig);
302 }
303
304 cleanup_return:
305 if (res != TEE_SUCCESS) {
306 TEE_CloseTASession(sess);
307 sess = TEE_HANDLE_NULL;
308 }
309 return res;
310 }
311
TA_CreateEntryPoint(void)312 TEE_Result TA_CreateEntryPoint(void)
313 {
314 return TEE_SUCCESS;
315 }
316
TA_DestroyEntryPoint(void)317 void TA_DestroyEntryPoint(void)
318 {
319 }
320
TA_OpenSessionEntryPoint(uint32_t nParamTypes,TEE_Param pParams[TEE_NUM_PARAMS],void ** ppSessionContext)321 TEE_Result TA_OpenSessionEntryPoint(uint32_t nParamTypes,
322 TEE_Param pParams[TEE_NUM_PARAMS],
323 void **ppSessionContext)
324 {
325 (void)nParamTypes;
326 (void)pParams;
327 (void)ppSessionContext;
328 return TEE_SUCCESS;
329 }
330
TA_CloseSessionEntryPoint(void * pSessionContext)331 void TA_CloseSessionEntryPoint(void *pSessionContext)
332 {
333 (void)pSessionContext;
334 }
335
TA_InvokeCommandEntryPoint(void * pSessionContext,uint32_t nCommandID,uint32_t nParamTypes,TEE_Param pParams[TEE_NUM_PARAMS])336 TEE_Result TA_InvokeCommandEntryPoint(void *pSessionContext,
337 uint32_t nCommandID, uint32_t nParamTypes,
338 TEE_Param pParams[TEE_NUM_PARAMS])
339 {
340 (void)pSessionContext;
341
342 switch (nCommandID) {
343 case TA_SDP_BASIC_CMD_INJECT:
344 return cmd_inject(nParamTypes, pParams);
345 case TA_SDP_BASIC_CMD_TRANSFORM:
346 return cmd_transform(nParamTypes, pParams);
347 case TA_SDP_BASIC_CMD_DUMP:
348 return cmd_dump(nParamTypes, pParams);
349
350 case TA_SDP_BASIC_CMD_INVOKE_INJECT:
351 return cmd_invoke(nParamTypes, pParams, TA_SDP_BASIC_CMD_INJECT);
352 case TA_SDP_BASIC_CMD_INVOKE_TRANSFORM:
353 return cmd_invoke(nParamTypes, pParams, TA_SDP_BASIC_CMD_TRANSFORM);
354 case TA_SDP_BASIC_CMD_INVOKE_DUMP:
355 return cmd_invoke(nParamTypes, pParams, TA_SDP_BASIC_CMD_DUMP);
356
357 case TA_SDP_BASIC_CMD_PTA_INJECT:
358 return cmd_invoke_pta(nParamTypes, pParams, PTA_INVOKE_TESTS_CMD_COPY_NSEC_TO_SEC);
359 case TA_SDP_BASIC_CMD_PTA_TRANSFORM:
360 return cmd_invoke_pta(nParamTypes, pParams, PTA_INVOKE_TESTS_CMD_READ_MODIFY_SEC);
361 case TA_SDP_BASIC_CMD_PTA_DUMP:
362 return cmd_invoke_pta(nParamTypes, pParams, PTA_INVOKE_TESTS_CMD_COPY_SEC_TO_NSEC);
363
364 default:
365 return TEE_ERROR_BAD_PARAMETERS;
366 }
367 }
368