• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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