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