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