1 /*
2 * Copyright (C) 2022 Huawei Technologies Co., Ltd.
3 * Decription: function definition for libteec interface for kernel CA.
4 *
5 * This software is licensed under the terms of the GNU General Public
6 * License version 2, as published by the Free Software Foundation, and
7 * may be copied, distributed, and modified under those terms.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 */
14 #include "teek_client_api.h"
15 #include <linux/slab.h>
16 #include <linux/fs.h>
17 #include <linux/platform_device.h>
18 #include <linux/cdev.h>
19 #include <linux/uaccess.h>
20 #include <linux/sched.h>
21 #include <linux/list.h>
22 #include <linux/mutex.h>
23 #include <asm/cacheflush.h>
24 #include <linux/kthread.h>
25 #include <linux/freezer.h>
26 #include <linux/kernel.h>
27 #include <securec.h>
28 #include "tc_ns_log.h"
29 #include "tc_ns_client.h"
30 #include "gp_ops.h"
31 #include "internal_functions.h"
32 #include "session_manager.h"
33 #include "tc_client_driver.h"
34 #include "teek_app_load.h"
35 #include "dynamic_ion_mem.h"
36
encode_for_part_mem(struct tc_ns_client_context * context,const struct teec_operation * oper,uint32_t idex,uint32_t * param_type)37 static void encode_for_part_mem(struct tc_ns_client_context *context,
38 const struct teec_operation *oper, uint32_t idex, uint32_t *param_type)
39 {
40 uint32_t diff = (uint32_t)TEEC_MEMREF_PARTIAL_INPUT -
41 (uint32_t)TEEC_MEMREF_TEMP_INPUT;
42 uint64_t size_addr, buffer_addr;
43
44 if (idex >= TEE_PARAM_NUM)
45 return;
46
47 if (param_type[idex] == TEEC_MEMREF_WHOLE) {
48 context->params[idex].memref.offset = 0;
49 size_addr = (__u64)(uintptr_t)(&(oper->params[idex].memref.parent->size));
50 } else {
51 context->params[idex].memref.offset = oper->params[idex].memref.offset;
52 size_addr = (__u64)(uintptr_t)(&(oper->params[idex].memref.size));
53 }
54 context->params[idex].memref.size_addr = (__u32)size_addr;
55 context->params[idex].memref.size_h_addr = (__u32)(size_addr >> ADDR_TRANS_NUM);
56
57 if (oper->params[idex].memref.parent->is_allocated) {
58 buffer_addr = (__u64)(uintptr_t)oper->params[idex].memref.parent->buffer;
59 } else {
60 buffer_addr = (__u64)(uintptr_t)
61 oper->params[idex].memref.parent->buffer +
62 oper->params[idex].memref.offset;
63 context->params[idex].memref.offset = 0;
64 }
65 context->params[idex].memref.buffer = (__u32)buffer_addr;
66 context->params[idex].memref.buffer_h_addr = (__u32)(buffer_addr >> ADDR_TRANS_NUM);
67
68 /* translate the paramType to know the driver */
69 if (param_type[idex] == TEEC_MEMREF_WHOLE) {
70 switch (oper->params[idex].memref.parent->flags) {
71 case TEEC_MEM_INPUT:
72 param_type[idex] = TEEC_MEMREF_PARTIAL_INPUT;
73 break;
74 case TEEC_MEM_OUTPUT:
75 param_type[idex] = TEEC_MEMREF_PARTIAL_OUTPUT;
76 break;
77 case TEEC_MEM_INOUT:
78 param_type[idex] = TEEC_MEMREF_PARTIAL_INOUT;
79 break;
80 default:
81 param_type[idex] = TEEC_MEMREF_PARTIAL_INOUT;
82 break;
83 }
84 }
85
86 /* if not allocated, trans PARTIAL_XXX to MEMREF_TEMP_XXX */
87 if (!oper->params[idex].memref.parent->is_allocated)
88 param_type[idex] = param_type[idex] - diff;
89 }
90
proc_teek_encode(struct tc_ns_client_context * cli_context,const struct teec_operation * operation)91 static uint32_t proc_teek_encode(struct tc_ns_client_context *cli_context,
92 const struct teec_operation *operation)
93 {
94 uint32_t param_type[TEE_PARAM_NUM];
95 uint32_t idex;
96 uint64_t buffer_addr, size_addr, a_addr, b_addr;
97
98 param_type[0] =
99 teec_param_type_get(operation->paramtypes, 0);
100 param_type[1] =
101 teec_param_type_get(operation->paramtypes, 1);
102 param_type[2] =
103 teec_param_type_get(operation->paramtypes, 2);
104 param_type[3] =
105 teec_param_type_get(operation->paramtypes, 3);
106 for (idex = 0; idex < TEE_PARAM_NUM; idex++) {
107 if (is_tmp_mem(param_type[idex])) {
108 buffer_addr = (__u64)(uintptr_t)(operation->params[idex].tmpref.buffer);
109 size_addr = (__u64)(uintptr_t)(&operation->params[idex].tmpref.size);
110 cli_context->params[idex].memref.buffer = (__u32)buffer_addr;
111 cli_context->params[idex].memref.buffer_h_addr = (__u32)(buffer_addr >> ADDR_TRANS_NUM);
112 cli_context->params[idex].memref.size_addr = (__u32)size_addr;
113 cli_context->params[idex].memref.size_h_addr = (__u32)(size_addr >> ADDR_TRANS_NUM);
114 } else if (is_ref_mem(param_type[idex])) {
115 encode_for_part_mem(cli_context, operation,
116 idex, param_type);
117 } else if (is_val_param(param_type[idex])) {
118 a_addr = (__u64)(uintptr_t)(&(operation->params[idex].value.a));
119 b_addr = (__u64)(uintptr_t)(&(operation->params[idex].value.b));
120 cli_context->params[idex].value.a_addr = (__u32)a_addr;
121 cli_context->params[idex].value.a_h_addr = (__u32)(a_addr >> ADDR_TRANS_NUM);
122 cli_context->params[idex].value.b_addr = (__u32)b_addr;
123 cli_context->params[idex].value.b_h_addr = (__u32)(b_addr >> ADDR_TRANS_NUM);
124 } else if (is_ion_param(param_type[idex])) {
125 a_addr = (__u64)(uintptr_t)(&(operation->params[idex].ionref.ion_share_fd));
126 b_addr = (__u64)(uintptr_t)(&(operation->params[idex].ionref.ion_size));
127 cli_context->params[idex].value.a_addr = (__u32)a_addr;
128 cli_context->params[idex].value.a_h_addr = (__u32)(a_addr >> ADDR_TRANS_NUM);
129 cli_context->params[idex].value.b_addr = (__u32)b_addr;
130 cli_context->params[idex].value.b_h_addr = (__u32)(b_addr >> ADDR_TRANS_NUM);
131 } else if (param_type[idex] == TEEC_NONE) {
132 /* do nothing */
133 } else {
134 tloge("param_type[%u]=%u not correct\n", idex,
135 param_type[idex]);
136 return TEEC_ERROR_BAD_PARAMETERS;
137 }
138 }
139 cli_context->param_types = teec_param_types(param_type[0],
140 param_type[1], param_type[2], param_type[3]);
141
142 tlogv("cli param type %u\n", cli_context->param_types);
143 return TEEC_SUCCESS;
144 }
145
teek_init_context(struct tc_ns_client_context * cli_context,struct teec_uuid service_id,uint32_t session_id,uint32_t cmd_id,const struct tc_ns_client_login * cli_login)146 static uint32_t teek_init_context(struct tc_ns_client_context *cli_context,
147 struct teec_uuid service_id, uint32_t session_id, uint32_t cmd_id,
148 const struct tc_ns_client_login *cli_login)
149 {
150 uint32_t diff;
151
152 diff = (uint32_t)TEEC_MEMREF_PARTIAL_INPUT -
153 (uint32_t)TEEC_MEMREF_TEMP_INPUT;
154
155 if (memset_s(cli_context, sizeof(*cli_context),
156 0x00, sizeof(*cli_context)) != 0) {
157 tloge("memset error, init cli context failed\n");
158 return TEEC_ERROR_BAD_PARAMETERS;
159 }
160
161 cli_context->returns.origin = TEEC_ORIGIN_COMMS;
162
163 if (memcpy_s(cli_context->uuid, sizeof(cli_context->uuid),
164 (uint8_t *)&service_id, sizeof(service_id)) != 0) {
165 tloge("memcpy error, init cli context failed\n");
166 return TEEC_ERROR_BAD_PARAMETERS;
167 }
168 cli_context->session_id = session_id;
169 cli_context->cmd_id = cmd_id;
170 cli_context->returns.code = 0;
171 cli_context->login.method = cli_login->method;
172 cli_context->login.mdata = cli_login->mdata;
173
174 return TEEC_SUCCESS;
175 }
176
teek_check_tmp_mem(const struct teec_tempmemory_reference * tmpref)177 static uint32_t teek_check_tmp_mem(
178 const struct teec_tempmemory_reference *tmpref)
179 {
180 if (!tmpref->buffer || (tmpref->size == 0)) {
181 tloge("tmpref buffer is null, or size is zero\n");
182 return TEEC_ERROR_BAD_PARAMETERS;
183 }
184
185 return TEEC_SUCCESS;
186 }
187
is_partical_mem(uint32_t param_type)188 static bool is_partical_mem(uint32_t param_type)
189 {
190 if (param_type == TEEC_MEMREF_PARTIAL_INPUT ||
191 param_type == TEEC_MEMREF_PARTIAL_OUTPUT ||
192 param_type == TEEC_MEMREF_PARTIAL_INOUT)
193 return true;
194
195 return false;
196 }
197
is_offset_invalid(const struct teec_registeredmemory_reference * memref)198 static bool is_offset_invalid(
199 const struct teec_registeredmemory_reference *memref)
200 {
201 if ((memref->offset + memref->size > memref->parent->size) ||
202 (memref->offset + memref->size < memref->offset) ||
203 (memref->offset + memref->size < memref->size))
204 return true;
205
206 return false;
207 }
208
teek_check_ref_mem(const struct teec_registeredmemory_reference * memref,uint32_t param_type)209 static uint32_t teek_check_ref_mem(
210 const struct teec_registeredmemory_reference *memref,
211 uint32_t param_type)
212 {
213 if (!memref->parent || !memref->parent->buffer) {
214 tloge("parent of memref is null, or the buffer is zero\n");
215 return TEEC_ERROR_BAD_PARAMETERS;
216 }
217 if (param_type == TEEC_MEMREF_PARTIAL_INPUT) {
218 if ((memref->parent->flags & TEEC_MEM_INPUT) == 0)
219 return TEEC_ERROR_BAD_PARAMETERS;
220 } else if (param_type == TEEC_MEMREF_PARTIAL_OUTPUT) {
221 if ((memref->parent->flags & TEEC_MEM_OUTPUT) == 0)
222 return TEEC_ERROR_BAD_PARAMETERS;
223 } else if (param_type == TEEC_MEMREF_PARTIAL_INOUT) {
224 if ((memref->parent->flags & TEEC_MEM_INPUT) == 0)
225 return TEEC_ERROR_BAD_PARAMETERS;
226 if ((memref->parent->flags & TEEC_MEM_OUTPUT) == 0)
227 return TEEC_ERROR_BAD_PARAMETERS;
228 } else if (param_type == TEEC_MEMREF_WHOLE) {
229 /* if type is TEEC_MEMREF_WHOLE, ignore it */
230 } else {
231 return TEEC_ERROR_BAD_PARAMETERS;
232 }
233
234 if (is_partical_mem(param_type)) {
235 if (is_offset_invalid(memref)) {
236 tloge("offset + size exceed the parent size\n");
237 return TEEC_ERROR_BAD_PARAMETERS;
238 }
239 }
240 return TEEC_SUCCESS;
241 }
242
243 /*
244 * This function checks a operation is valid or not.
245 */
teek_check_operation(const struct teec_operation * operation)246 uint32_t teek_check_operation(const struct teec_operation *operation)
247 {
248 uint32_t param_type[TEE_PARAM_NUM] = {0};
249 uint32_t idex;
250 uint32_t ret = TEEC_SUCCESS;
251
252 /*
253 * GP Support operation is NULL
254 * operation: a pointer to a Client Application initialized struct,
255 * or NULL if there is no payload to send or
256 * if the Command does not need to support cancellation.
257 */
258 if (!operation)
259 return TEEC_SUCCESS;
260
261 if (operation->started == 0) {
262 tloge("sorry, cancellation not support\n");
263 return TEEC_ERROR_NOT_IMPLEMENTED;
264 }
265
266 param_type[0] =
267 teec_param_type_get(operation->paramtypes, 0);
268 param_type[1] =
269 teec_param_type_get(operation->paramtypes, 1);
270 param_type[2] =
271 teec_param_type_get(operation->paramtypes, 2);
272 param_type[3] =
273 teec_param_type_get(operation->paramtypes, 3);
274 for (idex = 0; idex < TEE_PARAM_NUM; idex++) {
275 if (is_tmp_mem(param_type[idex])) {
276 ret = teek_check_tmp_mem(
277 &(operation->params[idex].tmpref));
278 if (ret != TEEC_SUCCESS)
279 break;
280 } else if (is_ref_mem(param_type[idex])) {
281 ret = teek_check_ref_mem(
282 &(operation->params[idex].memref),
283 param_type[idex]);
284 if (ret != TEEC_SUCCESS)
285 break;
286 } else if (is_val_param(param_type[idex])) {
287 /* do nothing */
288 } else if (is_ion_param(param_type[idex])) {
289 if (operation->params[idex].ionref.ion_share_fd < 0) {
290 tloge("ion_handle is invalid!\n");
291 ret = TEEC_ERROR_BAD_PARAMETERS;
292 break;
293 }
294 } else if (param_type[idex] == TEEC_NONE) {
295 /* do nothing */
296 } else {
297 tloge("paramType[%u]=%x is not support\n", idex,
298 param_type[idex]);
299 ret = TEEC_ERROR_BAD_PARAMETERS;
300 break;
301 }
302 }
303
304 return ret;
305 }
306
307 /*
308 * This function check if the special agent is launched.Used For HDCP key.
309 * e.g. If sfs agent is not alive, you can not do HDCP key write to SRAM.
310 */
teek_is_agent_alive(unsigned int agent_id)311 int teek_is_agent_alive(unsigned int agent_id)
312 {
313 return is_agent_alive(agent_id);
314 }
315
316 /*
317 * This function initializes a new TEE Context,
318 * forming a connection between this Client Application
319 * and the TEE identified by the string identifier name.
320 */
teek_initialize_context(const char * name,struct teec_context * context)321 uint32_t teek_initialize_context(const char *name,
322 struct teec_context *context)
323 {
324 int32_t ret;
325 /* name current not used */
326 (void)(name);
327 if (!get_tz_init_flag()) return (uint32_t)TEEC_ERROR_BUSY;
328 tlogd("teek_initialize_context Started:\n");
329 /* First, check parameters is valid or not */
330 if (!context) {
331 tloge("context is null, not correct\n");
332 return TEEC_ERROR_BAD_PARAMETERS;
333 }
334 context->dev = NULL;
335 context->ta_path = NULL;
336 /* Paramters right, start execution */
337 ret = tc_ns_client_open((struct tc_ns_dev_file **)&context->dev,
338 TEE_REQ_FROM_KERNEL_MODE);
339 if (ret != TEEC_SUCCESS) {
340 tloge("open device failed\n");
341 return TEEC_ERROR_GENERIC;
342 }
343 tlogd("open device success\n");
344 return TEEC_SUCCESS;
345 }
346 EXPORT_SYMBOL(teek_initialize_context);
347
348 /*
349 * This function finalizes an initialized TEE Context.
350 */
teek_finalize_context(struct teec_context * context)351 void teek_finalize_context(struct teec_context *context)
352 {
353 if (!get_tz_init_flag()) return;
354 tlogd("teek_finalize_context started\n");
355 if (!context || !context->dev) {
356 tloge("context or dev is null, not correct\n");
357 return;
358 }
359
360 tlogd("close device\n");
361 tc_ns_client_close(context->dev);
362 context->dev = NULL;
363 }
364 EXPORT_SYMBOL(teek_finalize_context);
365
is_oper_param_valid(const struct teec_operation * operation)366 static bool is_oper_param_valid(const struct teec_operation *operation)
367 {
368 uint32_t param_type[TEE_PARAM_NUM] = {0};
369
370 param_type[3] =
371 teec_param_type_get(operation->paramtypes, 3);
372 param_type[2] =
373 teec_param_type_get(operation->paramtypes, 2);
374
375 if (param_type[3] != TEEC_MEMREF_TEMP_INPUT ||
376 param_type[2] != TEEC_MEMREF_TEMP_INPUT) {
377 tloge("invalid param type 0x%x\n", operation->paramtypes);
378 return false;
379 }
380
381 if (!operation->params[3].tmpref.buffer ||
382 !operation->params[2].tmpref.buffer ||
383 operation->params[3].tmpref.size == 0 ||
384 operation->params[2].tmpref.size == 0) {
385 tloge("invalid operation params(NULL)\n");
386 return false;
387 }
388 return true;
389 }
390
check_open_sess_params(struct teec_context * context,const struct teec_operation * operation,const struct teec_uuid * destination,uint32_t connection_method)391 static uint32_t check_open_sess_params(struct teec_context *context,
392 const struct teec_operation *operation, const struct teec_uuid *destination,
393 uint32_t connection_method)
394 {
395 struct tc_ns_dev_file *dev_file = NULL;
396 uint32_t teec_ret;
397
398 if (!context || !operation || !destination ||
399 connection_method != TEEC_LOGIN_IDENTIFY) {
400 tloge("invalid input params\n");
401 return TEEC_ERROR_BAD_PARAMETERS;
402 }
403
404 if (!is_oper_param_valid(operation))
405 return TEEC_ERROR_BAD_PARAMETERS;
406
407 dev_file = (struct tc_ns_dev_file *)(context->dev);
408 if (!dev_file) {
409 tloge("invalid context->dev (NULL)\n");
410 return TEEC_ERROR_BAD_PARAMETERS;
411 }
412
413 dev_file->pkg_name_len = operation->params[3].tmpref.size;
414 if (operation->params[3].tmpref.size > MAX_PACKAGE_NAME_LEN - 1) {
415 return TEEC_ERROR_BAD_PARAMETERS;
416 } else {
417 if (memset_s(dev_file->pkg_name, sizeof(dev_file->pkg_name),
418 0, MAX_PACKAGE_NAME_LEN) != 0) {
419 tloge("memset error\n");
420 return TEEC_ERROR_BAD_PARAMETERS;
421 }
422 if (memcpy_s(dev_file->pkg_name, sizeof(dev_file->pkg_name),
423 operation->params[3].tmpref.buffer,
424 operation->params[3].tmpref.size) != 0) {
425 tloge("memcpy error\n");
426 return TEEC_ERROR_BAD_PARAMETERS;
427 }
428 }
429
430 dev_file->pub_key_len = 0;
431 dev_file->login_setup = 1;
432 teec_ret = teek_check_operation(operation);
433 if (teec_ret != TEEC_SUCCESS) {
434 tloge("operation is invalid\n");
435 return TEEC_ERROR_BAD_PARAMETERS;
436 }
437
438 return teec_ret;
439 }
440
open_session_and_switch_ret(struct teec_session * session,struct teec_context * context,const struct teec_uuid * destination,struct tc_ns_client_context * cli_context,uint32_t * origin)441 static uint32_t open_session_and_switch_ret(struct teec_session *session,
442 struct teec_context *context, const struct teec_uuid *destination,
443 struct tc_ns_client_context *cli_context, uint32_t *origin)
444 {
445 int32_t ret;
446 uint32_t teec_ret;
447
448 ret = tc_ns_open_session(context->dev, cli_context);
449 if (ret == 0) {
450 tlogd("open session success\n");
451 session->session_id = cli_context->session_id;
452 session->service_id = *destination;
453 session->ops_cnt = 0;
454 session->context = context;
455 return TEEC_SUCCESS;
456 } else if (ret < 0) {
457 tloge("open session failed, ioctl errno = %d\n", ret);
458 if (ret == -EFAULT)
459 teec_ret = TEEC_ERROR_ACCESS_DENIED;
460 else if (ret == -ENOMEM)
461 teec_ret = TEEC_ERROR_OUT_OF_MEMORY;
462 else if (ret == -EINVAL)
463 teec_ret = TEEC_ERROR_BAD_PARAMETERS;
464 else if (ret == -ERESTARTSYS)
465 teec_ret = TEEC_CLIENT_INTR;
466 else
467 teec_ret = TEEC_ERROR_GENERIC;
468 *origin = TEEC_ORIGIN_COMMS;
469 return teec_ret;
470 } else {
471 tloge("open session failed, code=0x%x, origin=%u\n",
472 cli_context->returns.code,
473 cli_context->returns.origin);
474 teec_ret = (uint32_t)cli_context->returns.code;
475 *origin = cli_context->returns.origin;
476 }
477 return teec_ret;
478 }
479
proc_teek_open_session(struct teec_context * context,struct teec_session * session,const struct teec_uuid * destination,uint32_t connection_method,const void * connection_data,const struct teec_operation * operation,uint32_t * return_origin)480 static uint32_t proc_teek_open_session(struct teec_context *context,
481 struct teec_session *session, const struct teec_uuid *destination,
482 uint32_t connection_method, const void *connection_data,
483 const struct teec_operation *operation, uint32_t *return_origin)
484 {
485 uint32_t teec_ret;
486 uint32_t origin = TEEC_ORIGIN_API;
487 struct tc_ns_client_context cli_context;
488 struct tc_ns_client_login cli_login = {0};
489 bool load_app_flag = false;
490 char *file_buffer = NULL;
491
492 /* connectionData current not used */
493 (void)(connection_data);
494 if (return_origin)
495 *return_origin = origin;
496
497 /* First, check parameters is valid or not */
498 if (!session) {
499 tloge("invalid session\n");
500 teec_ret = TEEC_ERROR_BAD_PARAMETERS;
501 goto set_ori;
502 }
503
504 /*
505 * ca may call closesession even if opensession failed,
506 * we set session->context here to avoid receive a illegal ptr,
507 * same as libteec_vendor
508 */
509 session->context = context;
510
511 cli_login.method = TEEC_LOGIN_IDENTIFY;
512 teec_ret = check_open_sess_params(context, operation, destination, connection_method);
513 if (teec_ret != TEEC_SUCCESS)
514 goto set_ori;
515
516 teec_ret = teek_init_context(&cli_context, *destination, 0,
517 GLOBAL_CMD_ID_OPEN_SESSION, &cli_login);
518 if (teec_ret != TEEC_SUCCESS)
519 goto set_ori;
520
521 /* support when operation is null */
522 if (operation) {
523 cli_context.started = operation->cancel_flag;
524 teec_ret = proc_teek_encode(&cli_context, operation);
525 if (teec_ret != TEEC_SUCCESS)
526 goto set_ori;
527 }
528
529 teec_ret = (uint32_t)teek_get_app(context->ta_path, &file_buffer,
530 &cli_context.file_size);
531 if (teec_ret != TEEC_SUCCESS)
532 goto set_ori;
533 cli_context.memref.file_addr = (uint32_t)(uintptr_t)file_buffer;
534 cli_context.memref.file_h_addr = (uint32_t)(((uint64_t)(uintptr_t)file_buffer) >> ADDR_TRANS_NUM);
535 load_app_flag = true;
536
537 livepatch_down_read_sem();
538 teec_ret = open_session_and_switch_ret(session, context,
539 destination, &cli_context, &origin);
540 livepatch_up_read_sem();
541
542 set_ori:
543 if (teec_ret != TEEC_SUCCESS && return_origin != NULL)
544 *return_origin = origin;
545
546 teek_free_app(load_app_flag, &file_buffer);
547 return teec_ret;
548 }
549
550 #define RETRY_TIMES 5
teek_open_session(struct teec_context * context,struct teec_session * session,const struct teec_uuid * destination,uint32_t connection_method,const void * connection_data,const struct teec_operation * operation,uint32_t * return_origin)551 uint32_t teek_open_session(struct teec_context *context,
552 struct teec_session *session, const struct teec_uuid *destination,
553 uint32_t connection_method, const void *connection_data,
554 const struct teec_operation *operation, uint32_t *return_origin)
555 {
556 int i;
557 uint32_t ret;
558 if (!get_tz_init_flag()) return (uint32_t)TEEC_ERROR_BUSY;
559 for (i = 0; i < RETRY_TIMES; i++) {
560 ret = proc_teek_open_session(context, session,
561 destination, connection_method, connection_data,
562 operation, return_origin);
563 if (ret != (uint32_t)TEEC_CLIENT_INTR)
564 return ret;
565 }
566 return ret;
567 }
568 EXPORT_SYMBOL(teek_open_session);
569
570 /*
571 * This function closes an opened Session.
572 */
573
is_close_sess_param_valid(const struct teec_session * session)574 static bool is_close_sess_param_valid(const struct teec_session *session)
575 {
576 tlogd("teek_close_session started\n");
577
578 if (!session || !session->context || !session->context->dev) {
579 tloge("input invalid param\n");
580 return false;
581 }
582
583 return true;
584 }
585
teek_close_session(struct teec_session * session)586 void teek_close_session(struct teec_session *session)
587 {
588 int32_t ret;
589 struct tc_ns_client_context cli_context;
590 struct tc_ns_client_login cli_login = {0};
591
592 if (!get_tz_init_flag()) return;
593 if (!is_close_sess_param_valid(session))
594 return;
595
596 if (teek_init_context(&cli_context, session->service_id,
597 session->session_id, GLOBAL_CMD_ID_CLOSE_SESSION,
598 &cli_login) != TEEC_SUCCESS) {
599 tloge("init cli context failed just return\n");
600 return;
601 }
602 livepatch_down_read_sem();
603 ret = tc_ns_close_session(session->context->dev, &cli_context);
604 livepatch_up_read_sem();
605 if (ret == 0) {
606 session->session_id = 0;
607 if (memset_s((uint8_t *)(&session->service_id),
608 sizeof(session->service_id), 0x00, UUID_LEN) != 0)
609 tloge("memset error\n");
610 session->ops_cnt = 0;
611 session->context = NULL;
612 } else {
613 tloge("close session failed\n");
614 }
615 }
616 EXPORT_SYMBOL(teek_close_session);
617
proc_invoke_cmd(struct teec_session * session,struct tc_ns_client_context * cli_context,uint32_t * origin)618 static uint32_t proc_invoke_cmd(struct teec_session *session,
619 struct tc_ns_client_context *cli_context, uint32_t *origin)
620 {
621 int32_t ret;
622 uint32_t teec_ret;
623
624 livepatch_down_read_sem();
625 ret = tc_ns_send_cmd(session->context->dev, cli_context);
626 livepatch_up_read_sem();
627
628 if (ret == 0) {
629 tlogd("invoke cmd success\n");
630 teec_ret = TEEC_SUCCESS;
631 } else if (ret < 0) {
632 tloge("invoke cmd failed, ioctl errno = %d\n", ret);
633 if (ret == -EFAULT)
634 teec_ret = TEEC_ERROR_ACCESS_DENIED;
635 else if (ret == -ENOMEM)
636 teec_ret = TEEC_ERROR_OUT_OF_MEMORY;
637 else if (ret == -EINVAL)
638 teec_ret = TEEC_ERROR_BAD_PARAMETERS;
639 else
640 teec_ret = TEEC_ERROR_GENERIC;
641 *origin = TEEC_ORIGIN_COMMS;
642 } else {
643 tloge("invoke cmd failed, code=0x%x, origin=%d\n",
644 cli_context->returns.code,
645 cli_context->returns.origin);
646 teec_ret = (uint32_t)cli_context->returns.code;
647 *origin = cli_context->returns.origin;
648 }
649 return teec_ret;
650 }
651
652 /* This function invokes a Command within the specified Session. */
teek_invoke_command(struct teec_session * session,uint32_t cmd_id,struct teec_operation * operation,uint32_t * return_origin)653 uint32_t teek_invoke_command(struct teec_session *session, uint32_t cmd_id,
654 struct teec_operation *operation, uint32_t *return_origin)
655 {
656 uint32_t teec_ret = TEEC_ERROR_BAD_PARAMETERS;
657 uint32_t origin = TEEC_ORIGIN_API;
658 struct tc_ns_client_context cli_context;
659 struct tc_ns_client_login cli_login = { 0, 0 };
660
661 if (!get_tz_init_flag()) return (uint32_t)TEEC_ERROR_BUSY;
662 /* First, check parameters is valid or not */
663 if (!session || !session->context) {
664 tloge("input invalid session or session->context is null\n");
665 goto set_ori;
666 }
667
668 teec_ret = teek_check_operation(operation);
669 if (teec_ret != 0) {
670 tloge("operation is invalid\n");
671 goto set_ori;
672 }
673
674 /* Paramters all right, start execution */
675 teec_ret = teek_init_context(&cli_context, session->service_id,
676 session->session_id, cmd_id, &cli_login);
677 if (teec_ret != 0) {
678 tloge("init cli context failed\n");
679 goto set_ori;
680 }
681
682 /* support when operation is null */
683 if (operation) {
684 cli_context.started = operation->cancel_flag;
685 teec_ret = proc_teek_encode(&cli_context, operation);
686 if (teec_ret != 0) {
687 goto set_ori;
688 }
689 }
690
691 teec_ret = proc_invoke_cmd(session, &cli_context, &origin);
692
693 set_ori:
694 if ((teec_ret != 0) && return_origin)
695 *return_origin = origin;
696 return teec_ret;
697 }
698 EXPORT_SYMBOL(teek_invoke_command);
699
teek_send_secfile(struct teec_session * session,const char * file_buffer,unsigned int file_size)700 uint32_t teek_send_secfile(struct teec_session *session,
701 const char *file_buffer, unsigned int file_size)
702 {
703 uint32_t ret;
704
705 if (!get_tz_init_flag()) return (uint32_t)TEEC_ERROR_BUSY;
706 if (!file_buffer || (file_size == 0) || !session ||
707 !session->context || !session->context->dev) {
708 tloge("params error!\n");
709 return TEEC_ERROR_BAD_PARAMETERS;
710 }
711 livepatch_down_read_sem();
712 ret = (uint32_t)tc_ns_load_image_with_lock(session->context->dev,
713 file_buffer, file_size, LOAD_TA);
714 livepatch_up_read_sem();
715 return ret;
716 }
717 EXPORT_SYMBOL(teek_send_secfile);
718
TEEK_SendSecfile(TEEC_Session * session,const char * file_buffer,unsigned int file_size)719 TEEC_Result TEEK_SendSecfile(TEEC_Session *session,
720 const char *file_buffer, unsigned int file_size)
721 {
722 return (TEEC_Result)teek_send_secfile((struct teec_session *)session,
723 file_buffer, file_size);
724 }
725 EXPORT_SYMBOL(TEEK_SendSecfile);
726
727 /*
728 * This function registers a block of existing Client Application memory
729 * as a block of Shared Memory within the scope of the specified TEE Context.
730 */
teek_register_shared_memory(struct teec_context * context,struct teec_sharedmemory * sharedmem)731 uint32_t teek_register_shared_memory(struct teec_context *context,
732 struct teec_sharedmemory *sharedmem)
733 {
734 (void)context;
735 (void)sharedmem;
736 tloge("teek_register_shared_memory not supported\n");
737 return TEEC_ERROR_NOT_SUPPORTED;
738 }
739
740 /* begin: for KERNEL-HAL out interface */
TEEK_IsAgentAlive(unsigned int agent_id)741 int TEEK_IsAgentAlive(unsigned int agent_id)
742 {
743 return teek_is_agent_alive(agent_id);
744 }
745 EXPORT_SYMBOL(TEEK_IsAgentAlive);
746
TEEK_InitializeContext(const char * name,TEEC_Context * context)747 TEEC_Result TEEK_InitializeContext(const char *name, TEEC_Context *context)
748 {
749 return (TEEC_Result)teek_initialize_context(name,
750 (struct teec_context *)context);
751 }
752 EXPORT_SYMBOL(TEEK_InitializeContext);
753
TEEK_FinalizeContext(TEEC_Context * context)754 void TEEK_FinalizeContext(TEEC_Context *context)
755 {
756 teek_finalize_context((struct teec_context *)context);
757 }
758 EXPORT_SYMBOL(TEEK_FinalizeContext);
759
760 /*
761 * Function: TEEK_OpenSession
762 * Description: This function opens a new Session
763 * Parameters: context: a pointer to an initialized TEE Context.
764 * session: a pointer to a Session structure to open.
765 * destination: a pointer to a UUID structure.
766 * connectionMethod: the method of connection to use.
767 * connectionData: any necessary data required to support the connection method chosen.
768 * operation: a pointer to an Operation containing a set of Parameters.
769 * returnOrigin: a pointer to a variable which will contain the return origin.
770 * Return: TEEC_SUCCESS: success other: failure
771 */
772
TEEK_OpenSession(TEEC_Context * context,TEEC_Session * session,const TEEC_UUID * destination,uint32_t connectionMethod,const void * connectionData,TEEC_Operation * operation,uint32_t * returnOrigin)773 TEEC_Result TEEK_OpenSession(TEEC_Context *context, TEEC_Session *session,
774 const TEEC_UUID *destination, uint32_t connectionMethod,
775 const void *connectionData, TEEC_Operation *operation,
776 uint32_t *returnOrigin)
777 {
778 return (TEEC_Result)teek_open_session(
779 (struct teec_context *)context, (struct teec_session *)session,
780 (const struct teec_uuid *)destination, connectionMethod, connectionData,
781 (struct teec_operation *)operation, returnOrigin);
782 }
783 EXPORT_SYMBOL(TEEK_OpenSession);
784
TEEK_CloseSession(TEEC_Session * session)785 void TEEK_CloseSession(TEEC_Session *session)
786 {
787 teek_close_session((struct teec_session *)session);
788 }
789 EXPORT_SYMBOL(TEEK_CloseSession);
790
TEEK_InvokeCommand(TEEC_Session * session,uint32_t commandID,TEEC_Operation * operation,uint32_t * returnOrigin)791 TEEC_Result TEEK_InvokeCommand(TEEC_Session *session, uint32_t commandID,
792 TEEC_Operation *operation, uint32_t *returnOrigin)
793 {
794 return (TEEC_Result)teek_invoke_command(
795 (struct teec_session *)session, commandID,
796 (struct teec_operation *)operation, returnOrigin);
797 }
798 EXPORT_SYMBOL(TEEK_InvokeCommand);
799
800 /* end: for KERNEL-HAL out interface */
801