Initial commit with upstream sources
[platform/core/security/tef-optee_os.git] / core / arch / arm / pta / pta_self_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 #include <compiler.h>
28 #include <types_ext.h>
29 #include <kernel/pseudo_ta.h>
30 #include <trace.h>
31 #include <tee_api_types.h>
32 #include <tee_api_defines.h>
33 #include "core_self_tests.h"
34
35 #define TA_NAME         "sta_self_tests.ta"
36
37 #define STA_SELF_TEST_UUID \
38                 { 0xd96a5b40, 0xc3e5, 0x21e3, \
39                         { 0x87, 0x94, 0x10, 0x02, 0xa5, 0xd5, 0xc6, 0x1b } }
40
41 #define CMD_TRACE       0
42 #define CMD_PARAMS      1
43 #define CMD_SELF_TESTS  2
44
45 static TEE_Result test_trace(uint32_t param_types __unused,
46                         TEE_Param params[TEE_NUM_PARAMS] __unused)
47 {
48         IMSG("pseudo TA \"%s\" says \"Hello world !\"", TA_NAME);
49
50         return TEE_SUCCESS;
51 }
52
53 /*
54  * Supported tests on parameters
55  * (I, J, K, L refer to param index)
56  *
57  * Case 1: command parameters type are: 1 in/out value, 3 empty.
58  *         => process outI.a = inI.a + inI.b
59  * Case 2: command parameters type are: 3 input value, 1 output value
60  *         => process = outI.a = inJ.a + inK.a + inL.a
61  * Case 3: command parameters type are: 1 in/out memref, 3 empty.
62  *         => process = outI[0] = sum(inI[0..len-1])
63  */
64 static TEE_Result test_entry_params(uint32_t type, TEE_Param p[TEE_NUM_PARAMS])
65 {
66         size_t i;
67         uint8_t d8, *in;
68
69         /* case 1a: 1 input/output value argument */
70         if ((TEE_PARAM_TYPE_GET(type, 0) == TEE_PARAM_TYPE_VALUE_INOUT) &&
71                 (TEE_PARAM_TYPE_GET(type, 1) == TEE_PARAM_TYPE_NONE) &&
72                 (TEE_PARAM_TYPE_GET(type, 2) == TEE_PARAM_TYPE_NONE) &&
73                 (TEE_PARAM_TYPE_GET(type, 3) == TEE_PARAM_TYPE_NONE)) {
74                 p[0].value.a = p[0].value.a + p[0].value.b;
75                 return TEE_SUCCESS;
76         }
77         /* case 1b: 1 input/output value argument */
78         if ((TEE_PARAM_TYPE_GET(type, 0) == TEE_PARAM_TYPE_NONE) &&
79                 (TEE_PARAM_TYPE_GET(type, 1) == TEE_PARAM_TYPE_VALUE_INOUT) &&
80                 (TEE_PARAM_TYPE_GET(type, 2) == TEE_PARAM_TYPE_NONE) &&
81                 (TEE_PARAM_TYPE_GET(type, 3) == TEE_PARAM_TYPE_NONE)) {
82                 p[1].value.a = p[1].value.a + p[1].value.b;
83                 return TEE_SUCCESS;
84         }
85         /* case 1c: 1 input/output value argument */
86         if ((TEE_PARAM_TYPE_GET(type, 0) == TEE_PARAM_TYPE_NONE) &&
87                 (TEE_PARAM_TYPE_GET(type, 1) == TEE_PARAM_TYPE_NONE) &&
88                 (TEE_PARAM_TYPE_GET(type, 2) == TEE_PARAM_TYPE_VALUE_INOUT) &&
89                 (TEE_PARAM_TYPE_GET(type, 3) == TEE_PARAM_TYPE_NONE)) {
90                 p[2].value.a = p[2].value.a + p[2].value.b;
91                 return TEE_SUCCESS;
92         }
93         /* case 1d: 1 input/output value argument */
94         if ((TEE_PARAM_TYPE_GET(type, 0) == TEE_PARAM_TYPE_NONE) &&
95                 (TEE_PARAM_TYPE_GET(type, 1) == TEE_PARAM_TYPE_NONE) &&
96                 (TEE_PARAM_TYPE_GET(type, 2) == TEE_PARAM_TYPE_NONE) &&
97                 (TEE_PARAM_TYPE_GET(type, 3) == TEE_PARAM_TYPE_VALUE_INOUT)) {
98                 p[3].value.a = p[3].value.a + p[3].value.b;
99                 return TEE_SUCCESS;
100         }
101
102         /* case 2a: 3 input value arguments, 1 output value argument */
103         if ((TEE_PARAM_TYPE_GET(type, 0) == TEE_PARAM_TYPE_VALUE_OUTPUT) &&
104                 (TEE_PARAM_TYPE_GET(type, 1) == TEE_PARAM_TYPE_VALUE_INPUT) &&
105                 (TEE_PARAM_TYPE_GET(type, 2) == TEE_PARAM_TYPE_VALUE_INPUT) &&
106                 (TEE_PARAM_TYPE_GET(type, 3) == TEE_PARAM_TYPE_VALUE_INPUT)) {
107                 p[0].value.a = p[1].value.a + p[2].value.a + p[3].value.a;
108                 p[0].value.b = p[1].value.b + p[2].value.b + p[3].value.b;
109                 return TEE_SUCCESS;
110         }
111         /* case 2a: 3 input value arguments, 1 output value argument */
112         if ((TEE_PARAM_TYPE_GET(type, 0) == TEE_PARAM_TYPE_VALUE_INPUT) &&
113                 (TEE_PARAM_TYPE_GET(type, 1) == TEE_PARAM_TYPE_VALUE_OUTPUT) &&
114                 (TEE_PARAM_TYPE_GET(type, 2) == TEE_PARAM_TYPE_VALUE_INPUT) &&
115                 (TEE_PARAM_TYPE_GET(type, 3) == TEE_PARAM_TYPE_VALUE_INPUT)) {
116                 p[1].value.a = p[0].value.a + p[2].value.a + p[3].value.a;
117                 p[1].value.b = p[0].value.b + p[2].value.b + p[3].value.b;
118                 return TEE_SUCCESS;
119         }
120         /* case 2a: 3 input value arguments, 1 output value argument */
121         if ((TEE_PARAM_TYPE_GET(type, 0) == TEE_PARAM_TYPE_VALUE_INPUT) &&
122                 (TEE_PARAM_TYPE_GET(type, 1) == TEE_PARAM_TYPE_VALUE_INPUT) &&
123                 (TEE_PARAM_TYPE_GET(type, 2) == TEE_PARAM_TYPE_VALUE_OUTPUT) &&
124                 (TEE_PARAM_TYPE_GET(type, 3) == TEE_PARAM_TYPE_VALUE_INPUT)) {
125                 p[2].value.a = p[0].value.a + p[1].value.a + p[3].value.a;
126                 p[2].value.b = p[0].value.b + p[1].value.b + p[3].value.b;
127                 return TEE_SUCCESS;
128         }
129         /* case 2a: 3 input value arguments, 1 output value argument */
130         if ((TEE_PARAM_TYPE_GET(type, 0) == TEE_PARAM_TYPE_VALUE_INPUT) &&
131                 (TEE_PARAM_TYPE_GET(type, 1) == TEE_PARAM_TYPE_VALUE_INPUT) &&
132                 (TEE_PARAM_TYPE_GET(type, 2) == TEE_PARAM_TYPE_VALUE_INPUT) &&
133                 (TEE_PARAM_TYPE_GET(type, 3) == TEE_PARAM_TYPE_VALUE_OUTPUT)) {
134                 p[3].value.a = p[0].value.a + p[1].value.a + p[2].value.a;
135                 p[3].value.b = p[0].value.b + p[1].value.b + p[2].value.b;
136                 return TEE_SUCCESS;
137         }
138
139         DMSG("expect memref params: %p/%" PRIu32 " - %p/%" PRIu32 "zu - %p/%" PRIu32 "zu - %p/%" PRIu32 "zu",
140                         p[0].memref.buffer, p[0].memref.size,
141                         p[1].memref.buffer, p[1].memref.size,
142                         p[2].memref.buffer, p[2].memref.size,
143                         p[3].memref.buffer, p[3].memref.size);
144
145         /* case 3a: 1 in/out memref argument */
146         if ((TEE_PARAM_TYPE_GET(type, 0) == TEE_PARAM_TYPE_MEMREF_INOUT) &&
147                 (TEE_PARAM_TYPE_GET(type, 1) == TEE_PARAM_TYPE_NONE) &&
148                 (TEE_PARAM_TYPE_GET(type, 2) == TEE_PARAM_TYPE_NONE) &&
149                 (TEE_PARAM_TYPE_GET(type, 3) == TEE_PARAM_TYPE_NONE)) {
150                 in = (uint8_t *)p[0].memref.buffer;
151                 d8 = 0;
152                 for (i = 0; i < p[0].memref.size; i++)
153                         d8 += in[i];
154                 *(uint8_t *)p[0].memref.buffer = d8;
155                 return TEE_SUCCESS;
156         }
157         /* case 3b: 1 in/out memref argument */
158         if ((TEE_PARAM_TYPE_GET(type, 0) == TEE_PARAM_TYPE_NONE) &&
159                 (TEE_PARAM_TYPE_GET(type, 1) == TEE_PARAM_TYPE_MEMREF_INOUT) &&
160                 (TEE_PARAM_TYPE_GET(type, 2) == TEE_PARAM_TYPE_NONE) &&
161                 (TEE_PARAM_TYPE_GET(type, 3) == TEE_PARAM_TYPE_NONE)) {
162                 in = (uint8_t *)p[1].memref.buffer;
163                 d8 = 0;
164                 for (i = 0; i < p[1].memref.size; i++)
165                         d8 += in[i];
166                 *(uint8_t *)p[1].memref.buffer = d8;
167                 return TEE_SUCCESS;
168         }
169         /* case 3c: 1 in/out memref argument */
170         if ((TEE_PARAM_TYPE_GET(type, 0) == TEE_PARAM_TYPE_NONE) &&
171                 (TEE_PARAM_TYPE_GET(type, 1) == TEE_PARAM_TYPE_NONE) &&
172                 (TEE_PARAM_TYPE_GET(type, 2) == TEE_PARAM_TYPE_MEMREF_INOUT) &&
173                 (TEE_PARAM_TYPE_GET(type, 3) == TEE_PARAM_TYPE_NONE)) {
174                 in = (uint8_t *)p[2].memref.buffer;
175                 d8 = 0;
176                 for (i = 0; i < p[2].memref.size; i++)
177                         d8 += in[i];
178                 *(uint8_t *)p[2].memref.buffer = d8;
179                 return TEE_SUCCESS;
180         }
181         /* case 3d: 1 in/out memref argument */
182         if ((TEE_PARAM_TYPE_GET(type, 0) == TEE_PARAM_TYPE_NONE) &&
183                 (TEE_PARAM_TYPE_GET(type, 1) == TEE_PARAM_TYPE_NONE) &&
184                 (TEE_PARAM_TYPE_GET(type, 2) == TEE_PARAM_TYPE_NONE) &&
185                 (TEE_PARAM_TYPE_GET(type, 3) == TEE_PARAM_TYPE_MEMREF_INOUT)) {
186                 in = (uint8_t *)p[3].memref.buffer;
187                 d8 = 0;
188                 for (i = 0; i < p[3].memref.size; i++)
189                         d8 += in[i];
190                 *(uint8_t *)p[3].memref.buffer = d8;
191                 return TEE_SUCCESS;
192         }
193
194         EMSG("unexpected parameters");
195         return TEE_ERROR_BAD_PARAMETERS;
196 }
197
198 /*
199  * Trusted Application Entry Points
200  */
201
202 static TEE_Result create_ta(void)
203 {
204         DMSG("create entry point for pseudo TA \"%s\"", TA_NAME);
205         return TEE_SUCCESS;
206 }
207
208 static void destroy_ta(void)
209 {
210         DMSG("destroy entry point for pseudo ta \"%s\"", TA_NAME);
211 }
212
213 static TEE_Result open_session(uint32_t nParamTypes __unused,
214                 TEE_Param pParams[TEE_NUM_PARAMS] __unused,
215                 void **ppSessionContext __unused)
216 {
217         DMSG("open entry point for pseudo ta \"%s\"", TA_NAME);
218         return TEE_SUCCESS;
219 }
220
221 static void close_session(void *pSessionContext __unused)
222 {
223         DMSG("close entry point for pseudo ta \"%s\"", TA_NAME);
224 }
225
226 static TEE_Result invoke_command(void *pSessionContext __unused,
227                 uint32_t nCommandID, uint32_t nParamTypes,
228                 TEE_Param pParams[TEE_NUM_PARAMS])
229 {
230         DMSG("command entry point for pseudo ta \"%s\"", TA_NAME);
231
232         switch (nCommandID) {
233         case CMD_TRACE:
234                 return test_trace(nParamTypes, pParams);
235         case CMD_PARAMS:
236                 return test_entry_params(nParamTypes, pParams);
237         case CMD_SELF_TESTS:
238                 return core_self_tests(nParamTypes, pParams);
239         default:
240                 break;
241         }
242         return TEE_ERROR_BAD_PARAMETERS;
243 }
244
245 pseudo_ta_register(.uuid = STA_SELF_TEST_UUID, .name = TA_NAME,
246                    .flags = PTA_DEFAULT_FLAGS,
247                    .create_entry_point = create_ta,
248                    .destroy_entry_point = destroy_ta,
249                    .open_session_entry_point = open_session,
250                    .close_session_entry_point = close_session,
251                    .invoke_command_entry_point = invoke_command);