29c3b7474227a89dee66dd588c8f63e5e5abc351
[platform/core/security/tef-optee_os.git] / core / arch / arm / tee / entry_std.c
1 /*
2  * Copyright (c) 2015-2016, Linaro Limited
3  * All rights reserved.
4  * Copyright (c) 2014, STMicroelectronics International N.V.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright notice,
11  * this list of conditions and the following disclaimer.
12  *
13  * 2. Redistributions in binary form must reproduce the above copyright notice,
14  * this list of conditions and the following disclaimer in the documentation
15  * and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
21  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27  * POSSIBILITY OF SUCH DAMAGE.
28  */
29
30 #include <assert.h>
31 #include <compiler.h>
32 #include <initcall.h>
33 #include <kernel/panic.h>
34 #include <kernel/tee_misc.h>
35 #include <mm/core_memprot.h>
36 #include <mm/core_mmu.h>
37 #include <mm/mobj.h>
38 #include <optee_msg.h>
39 #include <sm/optee_smc.h>
40 #include <string.h>
41 #include <tee/entry_std.h>
42 #include <tee/tee_cryp_utl.h>
43 #include <tee/uuid.h>
44 #include <util.h>
45
46 #define SHM_CACHE_ATTRS \
47         (uint32_t)(core_mmu_is_shm_cached() ?  OPTEE_SMC_SHM_CACHED : 0)
48
49 /* Sessions opened from normal world */
50 static struct tee_ta_session_head tee_open_sessions =
51 TAILQ_HEAD_INITIALIZER(tee_open_sessions);
52
53 static struct mobj *shm_mobj;
54
55 static TEE_Result set_mem_param(const struct optee_msg_param *param,
56                                 struct param_mem *mem)
57 {
58         paddr_t b;
59         size_t sz;
60         size_t tsz;
61
62         if (mobj_get_pa(shm_mobj, 0, 0, &b) != TEE_SUCCESS)
63                 panic("Failed to be PA of shared memory MOBJ");
64
65         sz = shm_mobj->size;
66         tsz = param->u.tmem.size;
67         if (param->u.tmem.buf_ptr && !tsz)
68                 tsz++;
69         if (!core_is_buffer_inside(param->u.tmem.buf_ptr, tsz, b, sz))
70                 return TEE_ERROR_BAD_PARAMETERS;
71
72         mem->mobj = shm_mobj;
73         mem->offs = param->u.tmem.buf_ptr - b;
74         mem->size = param->u.tmem.size;
75         return TEE_SUCCESS;
76 }
77
78 static TEE_Result copy_in_params(const struct optee_msg_param *params,
79                 uint32_t num_params, struct tee_ta_param *ta_param)
80 {
81         TEE_Result res;
82         size_t n;
83         uint8_t pt[TEE_NUM_PARAMS];
84
85         if (num_params > TEE_NUM_PARAMS)
86                 return TEE_ERROR_BAD_PARAMETERS;
87
88         memset(ta_param, 0, sizeof(*ta_param));
89
90         for (n = 0; n < num_params; n++) {
91                 uint32_t attr;
92
93                 if (params[n].attr & OPTEE_MSG_ATTR_META)
94                         return TEE_ERROR_BAD_PARAMETERS;
95                 if (params[n].attr & OPTEE_MSG_ATTR_FRAGMENT)
96                         return TEE_ERROR_BAD_PARAMETERS;
97
98                 attr = params[n].attr & OPTEE_MSG_ATTR_TYPE_MASK;
99
100                 switch (attr) {
101                 case OPTEE_MSG_ATTR_TYPE_NONE:
102                         pt[n] = TEE_PARAM_TYPE_NONE;
103                         memset(&ta_param->u[n], 0, sizeof(ta_param->u[n]));
104                         break;
105                 case OPTEE_MSG_ATTR_TYPE_VALUE_INPUT:
106                 case OPTEE_MSG_ATTR_TYPE_VALUE_OUTPUT:
107                 case OPTEE_MSG_ATTR_TYPE_VALUE_INOUT:
108                         pt[n] = TEE_PARAM_TYPE_VALUE_INPUT + attr -
109                                 OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
110                         ta_param->u[n].val.a = params[n].u.value.a;
111                         ta_param->u[n].val.b = params[n].u.value.b;
112                         break;
113                 case OPTEE_MSG_ATTR_TYPE_TMEM_INPUT:
114                 case OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT:
115                 case OPTEE_MSG_ATTR_TYPE_TMEM_INOUT:
116                         pt[n] = TEE_PARAM_TYPE_MEMREF_INPUT + attr -
117                                 OPTEE_MSG_ATTR_TYPE_TMEM_INPUT;
118                         res = set_mem_param(params + n, &ta_param->u[n].mem);
119                         if (res != TEE_SUCCESS)
120                                 return res;
121                         break;
122                 default:
123                         return TEE_ERROR_BAD_PARAMETERS;
124                 }
125         }
126
127         ta_param->types = TEE_PARAM_TYPES(pt[0], pt[1], pt[2], pt[3]);
128
129         return TEE_SUCCESS;
130 }
131
132 static void copy_out_param(struct tee_ta_param *ta_param, uint32_t num_params,
133                            struct optee_msg_param *params)
134 {
135         size_t n;
136
137         for (n = 0; n < num_params; n++) {
138                 switch (TEE_PARAM_TYPE_GET(ta_param->types, n)) {
139                 case TEE_PARAM_TYPE_MEMREF_OUTPUT:
140                 case TEE_PARAM_TYPE_MEMREF_INOUT:
141                         params[n].u.tmem.size = ta_param->u[n].mem.size;
142                         break;
143                 case TEE_PARAM_TYPE_VALUE_OUTPUT:
144                 case TEE_PARAM_TYPE_VALUE_INOUT:
145                         params[n].u.value.a = ta_param->u[n].val.a;
146                         params[n].u.value.b = ta_param->u[n].val.b;
147                         break;
148                 default:
149                         break;
150                 }
151         }
152 }
153
154 /*
155  * Extracts mandatory parameter for open session.
156  *
157  * Returns
158  * false : mandatory parameter wasn't found or malformatted
159  * true  : paramater found and OK
160  */
161 static TEE_Result get_open_session_meta(size_t num_params,
162                                         struct optee_msg_param *params,
163                                         size_t *num_meta, TEE_UUID *uuid,
164                                         TEE_Identity *clnt_id)
165 {
166         const uint32_t req_attr = OPTEE_MSG_ATTR_META |
167                                   OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
168
169         if (num_params < 2)
170                 return TEE_ERROR_BAD_PARAMETERS;
171
172         if (params[0].attr != req_attr || params[1].attr != req_attr)
173                 return TEE_ERROR_BAD_PARAMETERS;
174
175         tee_uuid_from_octets(uuid, (void *)&params[0].u.value);
176         clnt_id->login = params[1].u.value.c;
177         switch (clnt_id->login) {
178         case TEE_LOGIN_PUBLIC:
179                 memset(&clnt_id->uuid, 0, sizeof(clnt_id->uuid));
180                 break;
181         case TEE_LOGIN_USER:
182         case TEE_LOGIN_GROUP:
183         case TEE_LOGIN_APPLICATION:
184         case TEE_LOGIN_APPLICATION_USER:
185         case TEE_LOGIN_APPLICATION_GROUP:
186                 tee_uuid_from_octets(&clnt_id->uuid,
187                                      (void *)&params[1].u.value);
188                 break;
189         default:
190                 return TEE_ERROR_BAD_PARAMETERS;
191         }
192
193         *num_meta = 2;
194         return TEE_SUCCESS;
195 }
196
197 static void entry_open_session(struct thread_smc_args *smc_args,
198                                struct optee_msg_arg *arg, uint32_t num_params)
199 {
200         TEE_Result res;
201         struct optee_msg_param *params = OPTEE_MSG_GET_PARAMS(arg);
202         TEE_ErrorOrigin err_orig = TEE_ORIGIN_TEE;
203         struct tee_ta_session *s = NULL;
204         TEE_Identity clnt_id;
205         TEE_UUID uuid;
206         struct tee_ta_param param;
207         size_t num_meta;
208
209         res = get_open_session_meta(num_params, params, &num_meta, &uuid,
210                                     &clnt_id);
211         if (res != TEE_SUCCESS)
212                 goto out;
213
214         res = copy_in_params(params + num_meta, num_params - num_meta, &param);
215         if (res != TEE_SUCCESS)
216                 goto out;
217
218         res = tee_ta_open_session(&err_orig, &s, &tee_open_sessions, &uuid,
219                                   &clnt_id, TEE_TIMEOUT_INFINITE, &param);
220         if (res != TEE_SUCCESS)
221                 s = NULL;
222         copy_out_param(&param, num_params - num_meta, params + num_meta);
223
224         /*
225          * The occurrence of open/close session command is usually
226          * un-predictable, using this property to increase randomness
227          * of prng
228          */
229         plat_prng_add_jitter_entropy();
230
231 out:
232         if (s)
233                 arg->session = (vaddr_t)s;
234         else
235                 arg->session = 0;
236         arg->ret = res;
237         arg->ret_origin = err_orig;
238         smc_args->a0 = OPTEE_SMC_RETURN_OK;
239 }
240
241 static void entry_close_session(struct thread_smc_args *smc_args,
242                         struct optee_msg_arg *arg, uint32_t num_params)
243 {
244         TEE_Result res;
245         struct tee_ta_session *s;
246
247         if (num_params) {
248                 res = TEE_ERROR_BAD_PARAMETERS;
249                 goto out;
250         }
251
252         plat_prng_add_jitter_entropy();
253
254         s = (struct tee_ta_session *)(vaddr_t)arg->session;
255         res = tee_ta_close_session(s, &tee_open_sessions, NSAPP_IDENTITY);
256 out:
257         arg->ret = res;
258         arg->ret_origin = TEE_ORIGIN_TEE;
259         smc_args->a0 = OPTEE_SMC_RETURN_OK;
260 }
261
262 static void entry_invoke_command(struct thread_smc_args *smc_args,
263                                  struct optee_msg_arg *arg, uint32_t num_params)
264 {
265         TEE_Result res;
266         struct optee_msg_param *params = OPTEE_MSG_GET_PARAMS(arg);
267         TEE_ErrorOrigin err_orig = TEE_ORIGIN_TEE;
268         struct tee_ta_session *s;
269         struct tee_ta_param param;
270
271         res = copy_in_params(params, num_params, &param);
272         if (res != TEE_SUCCESS)
273                 goto out;
274
275         s = tee_ta_get_session(arg->session, true, &tee_open_sessions);
276         if (!s) {
277                 res = TEE_ERROR_BAD_PARAMETERS;
278                 goto out;
279         }
280
281         res = tee_ta_invoke_command(&err_orig, s, NSAPP_IDENTITY,
282                                     TEE_TIMEOUT_INFINITE, arg->func, &param);
283
284         tee_ta_put_session(s);
285
286         copy_out_param(&param, num_params, params);
287
288 out:
289         arg->ret = res;
290         arg->ret_origin = err_orig;
291         smc_args->a0 = OPTEE_SMC_RETURN_OK;
292 }
293
294 static void entry_cancel(struct thread_smc_args *smc_args,
295                         struct optee_msg_arg *arg, uint32_t num_params)
296 {
297         TEE_Result res;
298         TEE_ErrorOrigin err_orig = TEE_ORIGIN_TEE;
299         struct tee_ta_session *s;
300
301         if (num_params) {
302                 res = TEE_ERROR_BAD_PARAMETERS;
303                 goto out;
304         }
305
306         s = tee_ta_get_session(arg->session, false, &tee_open_sessions);
307         if (!s) {
308                 res = TEE_ERROR_BAD_PARAMETERS;
309                 goto out;
310         }
311
312         res = tee_ta_cancel_command(&err_orig, s, NSAPP_IDENTITY);
313         tee_ta_put_session(s);
314
315 out:
316         arg->ret = res;
317         arg->ret_origin = err_orig;
318         smc_args->a0 = OPTEE_SMC_RETURN_OK;
319 }
320
321 void tee_entry_std(struct thread_smc_args *smc_args)
322 {
323         paddr_t parg;
324         struct optee_msg_arg *arg = NULL;       /* fix gcc warning */
325         uint32_t num_params;
326
327         if (smc_args->a0 != OPTEE_SMC_CALL_WITH_ARG) {
328                 EMSG("Unknown SMC 0x%" PRIx64, (uint64_t)smc_args->a0);
329                 DMSG("Expected 0x%x\n", OPTEE_SMC_CALL_WITH_ARG);
330                 smc_args->a0 = OPTEE_SMC_RETURN_EBADCMD;
331                 return;
332         }
333         parg = (uint64_t)smc_args->a1 << 32 | smc_args->a2;
334         if (!tee_pbuf_is_non_sec(parg, sizeof(struct optee_msg_arg)) ||
335             !ALIGNMENT_IS_OK(parg, struct optee_msg_arg) ||
336             !(arg = phys_to_virt(parg, MEM_AREA_NSEC_SHM))) {
337                 EMSG("Bad arg address 0x%" PRIxPA, parg);
338                 smc_args->a0 = OPTEE_SMC_RETURN_EBADADDR;
339                 return;
340         }
341
342         num_params = arg->num_params;
343         if (!tee_pbuf_is_non_sec(parg, OPTEE_MSG_GET_ARG_SIZE(num_params))) {
344                 EMSG("Bad arg address 0x%" PRIxPA, parg);
345                 smc_args->a0 = OPTEE_SMC_RETURN_EBADADDR;
346                 return;
347         }
348
349         thread_set_irq(true);   /* Enable IRQ for STD calls */
350         switch (arg->cmd) {
351         case OPTEE_MSG_CMD_OPEN_SESSION:
352                 entry_open_session(smc_args, arg, num_params);
353                 break;
354         case OPTEE_MSG_CMD_CLOSE_SESSION:
355                 entry_close_session(smc_args, arg, num_params);
356                 break;
357         case OPTEE_MSG_CMD_INVOKE_COMMAND:
358                 entry_invoke_command(smc_args, arg, num_params);
359                 break;
360         case OPTEE_MSG_CMD_CANCEL:
361                 entry_cancel(smc_args, arg, num_params);
362                 break;
363         default:
364                 EMSG("Unknown cmd 0x%x\n", arg->cmd);
365                 smc_args->a0 = OPTEE_SMC_RETURN_EBADCMD;
366         }
367 }
368
369 static TEE_Result default_mobj_init(void)
370 {
371         shm_mobj = mobj_phys_alloc(default_nsec_shm_paddr,
372                                    default_nsec_shm_size, SHM_CACHE_ATTRS,
373                                    CORE_MEM_NSEC_SHM);
374         if (!shm_mobj)
375                 panic("Failed to register shared memory");
376
377         mobj_sec_ddr = mobj_phys_alloc(tee_mm_sec_ddr.lo,
378                                        tee_mm_sec_ddr.hi - tee_mm_sec_ddr.lo,
379                                        SHM_CACHE_ATTRS, CORE_MEM_TA_RAM);
380         if (!mobj_sec_ddr)
381                 panic("Failed to register secure ta ram");
382
383         return TEE_SUCCESS;
384 }
385
386 driver_init_late(default_mobj_init);