Initial commit with upstream sources
[platform/core/security/tef-optee_os.git] / core / arch / arm / pta / pta_invoke_tests.c
1 /*
2  * Copyright (c) 2014, STMicroelectronics International N.V.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright notice,
9  * this list of conditions and the following disclaimer.
10  *
11  * 2. Redistributions in binary form must reproduce the above copyright notice,
12  * this list of conditions and the following disclaimer in the documentation
13  * and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
19  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25  * POSSIBILITY OF SUCH DAMAGE.
26  */
27
28 #include <compiler.h>
29 #include <kernel/pseudo_ta.h>
30 #include <mm/core_memprot.h>
31 #include <pta_invoke_tests.h>
32 #include <string.h>
33 #include <tee/cache.h>
34 #include <tee_api_defines.h>
35 #include <tee_api_types.h>
36 #include <trace.h>
37 #include <types_ext.h>
38
39 #include "core_self_tests.h"
40
41 #define TA_NAME         "invoke_tests.pta"
42
43 static TEE_Result test_trace(uint32_t param_types __unused,
44                         TEE_Param params[TEE_NUM_PARAMS] __unused)
45 {
46         IMSG("pseudo TA \"%s\" says \"Hello world !\"", TA_NAME);
47
48         return TEE_SUCCESS;
49 }
50
51 /*
52  * Supported tests on parameters
53  * (I, J, K, L refer to param index)
54  *
55  * Case 1: command parameters type are: 1 in/out value, 3 empty.
56  *         => process outI.a = inI.a + inI.b
57  * Case 2: command parameters type are: 3 input value, 1 output value
58  *         => process = outI.a = inJ.a + inK.a + inL.a
59  * Case 3: command parameters type are: 1 in/out memref, 3 empty.
60  *         => process = outI[0] = sum(inI[0..len-1])
61  */
62 static TEE_Result test_entry_params(uint32_t type, TEE_Param p[TEE_NUM_PARAMS])
63 {
64         size_t i;
65         uint8_t d8, *in;
66
67         /* case 1a: 1 input/output value argument */
68         if ((TEE_PARAM_TYPE_GET(type, 0) == TEE_PARAM_TYPE_VALUE_INOUT) &&
69                 (TEE_PARAM_TYPE_GET(type, 1) == TEE_PARAM_TYPE_NONE) &&
70                 (TEE_PARAM_TYPE_GET(type, 2) == TEE_PARAM_TYPE_NONE) &&
71                 (TEE_PARAM_TYPE_GET(type, 3) == TEE_PARAM_TYPE_NONE)) {
72                 p[0].value.a = p[0].value.a + p[0].value.b;
73                 return TEE_SUCCESS;
74         }
75         /* case 1b: 1 input/output value argument */
76         if ((TEE_PARAM_TYPE_GET(type, 0) == TEE_PARAM_TYPE_NONE) &&
77                 (TEE_PARAM_TYPE_GET(type, 1) == TEE_PARAM_TYPE_VALUE_INOUT) &&
78                 (TEE_PARAM_TYPE_GET(type, 2) == TEE_PARAM_TYPE_NONE) &&
79                 (TEE_PARAM_TYPE_GET(type, 3) == TEE_PARAM_TYPE_NONE)) {
80                 p[1].value.a = p[1].value.a + p[1].value.b;
81                 return TEE_SUCCESS;
82         }
83         /* case 1c: 1 input/output value argument */
84         if ((TEE_PARAM_TYPE_GET(type, 0) == TEE_PARAM_TYPE_NONE) &&
85                 (TEE_PARAM_TYPE_GET(type, 1) == TEE_PARAM_TYPE_NONE) &&
86                 (TEE_PARAM_TYPE_GET(type, 2) == TEE_PARAM_TYPE_VALUE_INOUT) &&
87                 (TEE_PARAM_TYPE_GET(type, 3) == TEE_PARAM_TYPE_NONE)) {
88                 p[2].value.a = p[2].value.a + p[2].value.b;
89                 return TEE_SUCCESS;
90         }
91         /* case 1d: 1 input/output value argument */
92         if ((TEE_PARAM_TYPE_GET(type, 0) == TEE_PARAM_TYPE_NONE) &&
93                 (TEE_PARAM_TYPE_GET(type, 1) == TEE_PARAM_TYPE_NONE) &&
94                 (TEE_PARAM_TYPE_GET(type, 2) == TEE_PARAM_TYPE_NONE) &&
95                 (TEE_PARAM_TYPE_GET(type, 3) == TEE_PARAM_TYPE_VALUE_INOUT)) {
96                 p[3].value.a = p[3].value.a + p[3].value.b;
97                 return TEE_SUCCESS;
98         }
99
100         /* case 2a: 3 input value arguments, 1 output value argument */
101         if ((TEE_PARAM_TYPE_GET(type, 0) == TEE_PARAM_TYPE_VALUE_OUTPUT) &&
102                 (TEE_PARAM_TYPE_GET(type, 1) == TEE_PARAM_TYPE_VALUE_INPUT) &&
103                 (TEE_PARAM_TYPE_GET(type, 2) == TEE_PARAM_TYPE_VALUE_INPUT) &&
104                 (TEE_PARAM_TYPE_GET(type, 3) == TEE_PARAM_TYPE_VALUE_INPUT)) {
105                 p[0].value.a = p[1].value.a + p[2].value.a + p[3].value.a;
106                 p[0].value.b = p[1].value.b + p[2].value.b + p[3].value.b;
107                 return TEE_SUCCESS;
108         }
109         /* case 2a: 3 input value arguments, 1 output value argument */
110         if ((TEE_PARAM_TYPE_GET(type, 0) == TEE_PARAM_TYPE_VALUE_INPUT) &&
111                 (TEE_PARAM_TYPE_GET(type, 1) == TEE_PARAM_TYPE_VALUE_OUTPUT) &&
112                 (TEE_PARAM_TYPE_GET(type, 2) == TEE_PARAM_TYPE_VALUE_INPUT) &&
113                 (TEE_PARAM_TYPE_GET(type, 3) == TEE_PARAM_TYPE_VALUE_INPUT)) {
114                 p[1].value.a = p[0].value.a + p[2].value.a + p[3].value.a;
115                 p[1].value.b = p[0].value.b + p[2].value.b + p[3].value.b;
116                 return TEE_SUCCESS;
117         }
118         /* case 2a: 3 input value arguments, 1 output value argument */
119         if ((TEE_PARAM_TYPE_GET(type, 0) == TEE_PARAM_TYPE_VALUE_INPUT) &&
120                 (TEE_PARAM_TYPE_GET(type, 1) == TEE_PARAM_TYPE_VALUE_INPUT) &&
121                 (TEE_PARAM_TYPE_GET(type, 2) == TEE_PARAM_TYPE_VALUE_OUTPUT) &&
122                 (TEE_PARAM_TYPE_GET(type, 3) == TEE_PARAM_TYPE_VALUE_INPUT)) {
123                 p[2].value.a = p[0].value.a + p[1].value.a + p[3].value.a;
124                 p[2].value.b = p[0].value.b + p[1].value.b + p[3].value.b;
125                 return TEE_SUCCESS;
126         }
127         /* case 2a: 3 input value arguments, 1 output value argument */
128         if ((TEE_PARAM_TYPE_GET(type, 0) == TEE_PARAM_TYPE_VALUE_INPUT) &&
129                 (TEE_PARAM_TYPE_GET(type, 1) == TEE_PARAM_TYPE_VALUE_INPUT) &&
130                 (TEE_PARAM_TYPE_GET(type, 2) == TEE_PARAM_TYPE_VALUE_INPUT) &&
131                 (TEE_PARAM_TYPE_GET(type, 3) == TEE_PARAM_TYPE_VALUE_OUTPUT)) {
132                 p[3].value.a = p[0].value.a + p[1].value.a + p[2].value.a;
133                 p[3].value.b = p[0].value.b + p[1].value.b + p[2].value.b;
134                 return TEE_SUCCESS;
135         }
136
137         DMSG("expect memref params: %p/%" PRIu32 " - %p/%" PRIu32 "zu - %p/%" PRIu32 "zu - %p/%" PRIu32 "zu",
138                         p[0].memref.buffer, p[0].memref.size,
139                         p[1].memref.buffer, p[1].memref.size,
140                         p[2].memref.buffer, p[2].memref.size,
141                         p[3].memref.buffer, p[3].memref.size);
142
143         /* case 3a: 1 in/out memref argument */
144         if ((TEE_PARAM_TYPE_GET(type, 0) == TEE_PARAM_TYPE_MEMREF_INOUT) &&
145                 (TEE_PARAM_TYPE_GET(type, 1) == TEE_PARAM_TYPE_NONE) &&
146                 (TEE_PARAM_TYPE_GET(type, 2) == TEE_PARAM_TYPE_NONE) &&
147                 (TEE_PARAM_TYPE_GET(type, 3) == TEE_PARAM_TYPE_NONE)) {
148                 in = (uint8_t *)p[0].memref.buffer;
149                 d8 = 0;
150                 for (i = 0; i < p[0].memref.size; i++)
151                         d8 += in[i];
152                 *(uint8_t *)p[0].memref.buffer = d8;
153                 return TEE_SUCCESS;
154         }
155         /* case 3b: 1 in/out memref argument */
156         if ((TEE_PARAM_TYPE_GET(type, 0) == TEE_PARAM_TYPE_NONE) &&
157                 (TEE_PARAM_TYPE_GET(type, 1) == TEE_PARAM_TYPE_MEMREF_INOUT) &&
158                 (TEE_PARAM_TYPE_GET(type, 2) == TEE_PARAM_TYPE_NONE) &&
159                 (TEE_PARAM_TYPE_GET(type, 3) == TEE_PARAM_TYPE_NONE)) {
160                 in = (uint8_t *)p[1].memref.buffer;
161                 d8 = 0;
162                 for (i = 0; i < p[1].memref.size; i++)
163                         d8 += in[i];
164                 *(uint8_t *)p[1].memref.buffer = d8;
165                 return TEE_SUCCESS;
166         }
167         /* case 3c: 1 in/out memref argument */
168         if ((TEE_PARAM_TYPE_GET(type, 0) == TEE_PARAM_TYPE_NONE) &&
169                 (TEE_PARAM_TYPE_GET(type, 1) == TEE_PARAM_TYPE_NONE) &&
170                 (TEE_PARAM_TYPE_GET(type, 2) == TEE_PARAM_TYPE_MEMREF_INOUT) &&
171                 (TEE_PARAM_TYPE_GET(type, 3) == TEE_PARAM_TYPE_NONE)) {
172                 in = (uint8_t *)p[2].memref.buffer;
173                 d8 = 0;
174                 for (i = 0; i < p[2].memref.size; i++)
175                         d8 += in[i];
176                 *(uint8_t *)p[2].memref.buffer = d8;
177                 return TEE_SUCCESS;
178         }
179         /* case 3d: 1 in/out memref argument */
180         if ((TEE_PARAM_TYPE_GET(type, 0) == TEE_PARAM_TYPE_NONE) &&
181                 (TEE_PARAM_TYPE_GET(type, 1) == TEE_PARAM_TYPE_NONE) &&
182                 (TEE_PARAM_TYPE_GET(type, 2) == TEE_PARAM_TYPE_NONE) &&
183                 (TEE_PARAM_TYPE_GET(type, 3) == TEE_PARAM_TYPE_MEMREF_INOUT)) {
184                 in = (uint8_t *)p[3].memref.buffer;
185                 d8 = 0;
186                 for (i = 0; i < p[3].memref.size; i++)
187                         d8 += in[i];
188                 *(uint8_t *)p[3].memref.buffer = d8;
189                 return TEE_SUCCESS;
190         }
191
192         EMSG("unexpected parameters");
193         return TEE_ERROR_BAD_PARAMETERS;
194 }
195
196 /*
197  * Test access to Secure Data Path memory from pseudo TAs
198  */
199
200 static TEE_Result test_inject_sdp(uint32_t type, TEE_Param p[TEE_NUM_PARAMS])
201 {
202         char *src = p[0].memref.buffer;
203         char *dst = p[1].memref.buffer;
204         size_t sz = p[0].memref.size;
205         uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT,
206                                           TEE_PARAM_TYPE_MEMREF_OUTPUT,
207                                           TEE_PARAM_TYPE_NONE,
208                                           TEE_PARAM_TYPE_NONE);
209
210         if (exp_pt != type) {
211                 DMSG("bad parameter types");
212                 return TEE_ERROR_BAD_PARAMETERS;
213         }
214
215         if (p[1].memref.size < sz) {
216                 p[1].memref.size = sz;
217                 return TEE_ERROR_SHORT_BUFFER;
218         }
219
220
221         if (!core_vbuf_is(CORE_MEM_NSEC_SHM, src, sz) ||
222             !core_vbuf_is(CORE_MEM_SDP_MEM, dst, sz)) {
223                 DMSG("bad memref secure attribute");
224                 return TEE_ERROR_BAD_PARAMETERS;
225         }
226
227         if (cache_operation(TEE_CACHEFLUSH, dst, sz) != TEE_SUCCESS)
228                 return TEE_ERROR_GENERIC;
229
230         memcpy(dst, src, sz);
231
232         if (cache_operation(TEE_CACHEFLUSH, dst, sz) != TEE_SUCCESS)
233                 return TEE_ERROR_GENERIC;
234
235         return TEE_SUCCESS;
236 }
237
238 static TEE_Result test_transform_sdp(uint32_t type, TEE_Param p[TEE_NUM_PARAMS])
239 {
240         char *buf = p[0].memref.buffer;
241         size_t sz = p[0].memref.size;
242         uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
243                                           TEE_PARAM_TYPE_NONE,
244                                           TEE_PARAM_TYPE_NONE,
245                                           TEE_PARAM_TYPE_NONE);
246
247         if (exp_pt != type) {
248                 DMSG("bad parameter types");
249                 return TEE_ERROR_BAD_PARAMETERS;
250         }
251
252         if (!core_vbuf_is(CORE_MEM_SDP_MEM, buf, sz)) {
253                 DMSG("bad memref secure attribute");
254                 return TEE_ERROR_BAD_PARAMETERS;
255         }
256
257         if (cache_operation(TEE_CACHEFLUSH, buf, sz) != TEE_SUCCESS)
258                 return TEE_ERROR_GENERIC;
259
260         for (; sz; sz--, buf++)
261                 *buf = ~(*buf) + 1;
262
263         if (cache_operation(TEE_CACHEFLUSH, buf, sz) != TEE_SUCCESS)
264                 return TEE_ERROR_GENERIC;
265
266         return TEE_SUCCESS;
267 }
268
269 static TEE_Result test_dump_sdp(uint32_t type, TEE_Param p[TEE_NUM_PARAMS])
270 {
271         char *src = p[0].memref.buffer;
272         char *dst = p[1].memref.buffer;
273         size_t sz = p[0].memref.size;
274         uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT,
275                                           TEE_PARAM_TYPE_MEMREF_OUTPUT,
276                                           TEE_PARAM_TYPE_NONE,
277                                           TEE_PARAM_TYPE_NONE);
278
279         if (exp_pt != type) {
280                 DMSG("bad parameter types");
281                 return TEE_ERROR_BAD_PARAMETERS;
282         }
283
284         if (p[1].memref.size < sz) {
285                 p[1].memref.size = sz;
286                 return TEE_ERROR_SHORT_BUFFER;
287         }
288
289         if (!core_vbuf_is(CORE_MEM_SDP_MEM, src, sz) ||
290             !core_vbuf_is(CORE_MEM_NSEC_SHM, dst, sz)) {
291                 DMSG("bad memref secure attribute");
292                 return TEE_ERROR_BAD_PARAMETERS;
293         }
294
295         if (cache_operation(TEE_CACHEFLUSH, dst, sz) != TEE_SUCCESS)
296                 return TEE_ERROR_GENERIC;
297
298         memcpy(dst, src, sz);
299
300         if (cache_operation(TEE_CACHEFLUSH, dst, sz) != TEE_SUCCESS)
301                 return TEE_ERROR_GENERIC;
302
303         return TEE_SUCCESS;
304 }
305
306 /*
307  * Trusted Application Entry Points
308  */
309
310 static TEE_Result create_ta(void)
311 {
312         DMSG("create entry point for pseudo TA \"%s\"", TA_NAME);
313         return TEE_SUCCESS;
314 }
315
316 static void destroy_ta(void)
317 {
318         DMSG("destroy entry point for pseudo ta \"%s\"", TA_NAME);
319 }
320
321 static TEE_Result open_session(uint32_t nParamTypes __unused,
322                 TEE_Param pParams[TEE_NUM_PARAMS] __unused,
323                 void **ppSessionContext __unused)
324 {
325         DMSG("open entry point for pseudo ta \"%s\"", TA_NAME);
326         return TEE_SUCCESS;
327 }
328
329 static void close_session(void *pSessionContext __unused)
330 {
331         DMSG("close entry point for pseudo ta \"%s\"", TA_NAME);
332 }
333
334 static TEE_Result invoke_command(void *pSessionContext __unused,
335                 uint32_t nCommandID, uint32_t nParamTypes,
336                 TEE_Param pParams[TEE_NUM_PARAMS])
337 {
338         DMSG("command entry point for pseudo ta \"%s\"", TA_NAME);
339
340         switch (nCommandID) {
341         case PTA_INVOKE_TESTS_CMD_TRACE:
342                 return test_trace(nParamTypes, pParams);
343         case PTA_INVOKE_TESTS_CMD_PARAMS:
344                 return test_entry_params(nParamTypes, pParams);
345         case PTA_INVOKE_TESTS_CMD_COPY_NSEC_TO_SEC:
346                 return test_inject_sdp(nParamTypes, pParams);
347         case PTA_INVOKE_TESTS_CMD_READ_MODIFY_SEC:
348                 return test_transform_sdp(nParamTypes, pParams);
349         case PTA_INVOKE_TESTS_CMD_COPY_SEC_TO_NSEC:
350                 return test_dump_sdp(nParamTypes, pParams);
351         case PTA_INVOKE_TESTS_CMD_SELF_TESTS:
352                 return core_self_tests(nParamTypes, pParams);
353 #if defined(CFG_WITH_USER_TA)
354         case PTA_INVOKE_TESTS_CMD_FS_HTREE:
355                 return core_fs_htree_tests(nParamTypes, pParams);
356 #endif
357         default:
358                 break;
359         }
360         return TEE_ERROR_BAD_PARAMETERS;
361 }
362
363 pseudo_ta_register(.uuid = PTA_INVOKE_TESTS_UUID, .name = TA_NAME,
364                    .flags = PTA_DEFAULT_FLAGS | TA_FLAG_SECURE_DATA_PATH,
365                    .create_entry_point = create_ta,
366                    .destroy_entry_point = destroy_ta,
367                    .open_session_entry_point = open_session,
368                    .close_session_entry_point = close_session,
369                    .invoke_command_entry_point = invoke_command);