1 /*
2 * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
3 * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without modification,
6 * are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice, this list of
9 * conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
12 * of conditions and the following disclaimer in the documentation and/or other materials
13 * provided with the distribution.
14 *
15 * 3. Neither the name of the copyright holder nor the names of its contributors may be used
16 * to endorse or promote products derived from this software without specific prior written
17 * permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
26 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
28 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
29 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 #include "teek_client_api.h"
33 #include <securec.h>
34 #include "tc_ns_log.h"
35 #include "tzdriver_compat.h"
36
EncdeForPartMem(TcNsClientContext * cliContext,const TeecOperation * operation,uint32_t paramCnt,uint32_t * paramType)37 static void EncdeForPartMem(TcNsClientContext *cliContext,
38 const TeecOperation *operation, uint32_t paramCnt, uint32_t *paramType)
39 {
40 uint32_t diff = (uint32_t)TEEC_MEMREF_PARTIAL_INPUT -
41 (uint32_t)TEEC_MEMREF_TEMP_INPUT;
42
43 if (paramCnt < TEE_PARAM_NUM) {
44 /* buffer offset len */
45 if (paramType[paramCnt] == TEEC_MEMREF_WHOLE) {
46 cliContext->params[paramCnt].memref.offset = 0;
47 cliContext->params[paramCnt].memref.sizeAddr =
48 (uint64_t)(uintptr_t)&operation->params[paramCnt].memref.parent->size;
49 } else {
50 cliContext->params[paramCnt].memref.offset =
51 operation->params[paramCnt].memref.offset;
52 cliContext->params[paramCnt].memref.sizeAddr =
53 (uint64_t)(uintptr_t)&operation->params[paramCnt].memref.size;
54 }
55 if (operation->params[paramCnt].memref.parent->isAllocated) {
56 cliContext->params[paramCnt].memref.buffer =
57 (uint64_t)(uintptr_t)
58 operation->params[paramCnt].memref.parent->buffer;
59 } else {
60 cliContext->params[paramCnt].memref.buffer =
61 (uint64_t)(uintptr_t)
62 operation->params[paramCnt].memref.parent->buffer +
63 operation->params[paramCnt].memref.offset;
64 cliContext->params[paramCnt].memref.offset = 0;
65 }
66 /* translate the paramType to know the driver */
67 if (paramType[paramCnt] == TEEC_MEMREF_WHOLE) {
68 switch (operation->params[paramCnt].memref.parent->flags) {
69 case TEEC_MEM_INPUT:
70 paramType[paramCnt] = TEEC_MEMREF_PARTIAL_INPUT;
71 break;
72 case TEEC_MEM_OUTPUT:
73 paramType[paramCnt] = TEEC_MEMREF_PARTIAL_OUTPUT;
74 break;
75 case TEEC_MEM_INOUT:
76 paramType[paramCnt] = TEEC_MEMREF_PARTIAL_INOUT;
77 break;
78 default:
79 paramType[paramCnt] = TEEC_MEMREF_PARTIAL_INOUT;
80 break;
81 }
82 }
83 /* if is not allocated, translate TEEC_MEMREF_PARTIAL_XXX to TEEC_MEMREF_TEMP_XXX */
84 if (!operation->params[paramCnt].memref.parent->isAllocated) {
85 paramType[paramCnt] = paramType[paramCnt] - diff;
86 }
87 }
88 return;
89 }
90
ProcTeekEncode(TcNsClientContext * cliContext,const TeecOperation * operation)91 static TeecResult ProcTeekEncode(TcNsClientContext *cliContext,
92 const TeecOperation *operation)
93 {
94 bool checkValue = false;
95 bool checkTempMem = false;
96 bool checkPartMem = false;
97 uint32_t paramType[TEE_PARAM_NUM];
98 uint32_t paramCnt;
99
100 paramType[TEE_PARAM_ONE] =
101 TEEC_PARAM_TYPE_GET(operation->paramTypes, TEE_PARAM_ONE);
102 paramType[TEE_PARAM_TWO] =
103 TEEC_PARAM_TYPE_GET(operation->paramTypes, TEE_PARAM_TWO);
104 paramType[TEE_PARAM_THREE] =
105 TEEC_PARAM_TYPE_GET(operation->paramTypes, TEE_PARAM_THREE);
106 paramType[TEE_PARAM_FOUR] =
107 TEEC_PARAM_TYPE_GET(operation->paramTypes, TEE_PARAM_FOUR);
108 for (paramCnt = 0; paramCnt < TEE_PARAM_NUM; paramCnt++) {
109 checkTempMem = paramType[paramCnt] == TEEC_MEMREF_TEMP_INPUT ||
110 paramType[paramCnt] == TEEC_MEMREF_TEMP_OUTPUT ||
111 paramType[paramCnt] == TEEC_MEMREF_TEMP_INOUT;
112 checkPartMem = paramType[paramCnt] == TEEC_MEMREF_WHOLE ||
113 paramType[paramCnt] == TEEC_MEMREF_PARTIAL_INPUT ||
114 paramType[paramCnt] == TEEC_MEMREF_PARTIAL_OUTPUT ||
115 paramType[paramCnt] == TEEC_MEMREF_PARTIAL_INOUT;
116 checkValue = paramType[paramCnt] == TEEC_VALUE_INPUT ||
117 paramType[paramCnt] == TEEC_VALUE_OUTPUT ||
118 paramType[paramCnt] == TEEC_VALUE_INOUT;
119 if (checkTempMem == true) {
120 cliContext->params[paramCnt].memref.buffer =
121 (uint64_t)(uintptr_t)(operation->params[paramCnt].tmpref.buffer);
122 cliContext->params[paramCnt].memref.sizeAddr =
123 (uint64_t)(uintptr_t)(&operation->params[paramCnt].tmpref.size);
124 } else if (checkPartMem == true) {
125 EncdeForPartMem(cliContext, operation,
126 paramCnt, paramType);
127 } else if (checkValue == true) {
128 cliContext->params[paramCnt].value.aAddr =
129 (uint64_t)(uintptr_t)(&operation->params[paramCnt].value.a);
130 cliContext->params[paramCnt].value.bAddr =
131 (uint64_t)(uintptr_t)(&operation->params[paramCnt].value.b);
132 } else if (paramType[paramCnt] == TEEC_NONE) {
133 /* do nothing */
134 } else {
135 tloge("paramType[%u]=%u not correct\n", paramCnt,
136 paramType[paramCnt]);
137 return (TeecResult)TEEC_ERROR_BAD_PARAMETERS;
138 }
139 }
140 cliContext->paramTypes = TEEC_PARAM_TYPES(paramType[TEE_PARAM_ONE],
141 paramType[TEE_PARAM_TWO], paramType[TEE_PARAM_THREE],
142 paramType[TEE_PARAM_FOUR]);
143 return TEEC_SUCCESS;
144 }
145
146 struct TeekEncodeMeg {
147 TeecUuid serviceId;
148 uint32_t sessionId;
149 uint32_t cmdId;
150 };
151
TeekEncode(TcNsClientContext * cliContext,struct TeekEncodeMeg * msg,const TcNsClientLogin * cliLogin,const TeecOperation * operation)152 static TeecResult TeekEncode(TcNsClientContext *cliContext,
153 struct TeekEncodeMeg *msg,
154 const TcNsClientLogin *cliLogin, const TeecOperation *operation)
155 {
156 TeecResult ret;
157 errno_t sret;
158
159 if (cliContext == NULL || cliLogin == NULL) {
160 tloge("cliContext or cliLogin is null.\n");
161 return (TeecResult)TEEC_ERROR_BAD_PARAMETERS;
162 }
163 sret = memset_s(cliContext, sizeof(*cliContext),
164 0x00, sizeof(*cliContext));
165 if (sret != EOK) {
166 tloge("memset error sret is %d.\n", sret);
167 return (TeecResult)TEEC_ERROR_BAD_PARAMETERS;
168 }
169 sret = memcpy_s(cliContext->uuid, sizeof(cliContext->uuid),
170 (uint8_t *)&msg->serviceId, sizeof(msg->serviceId));
171 if (sret != EOK) {
172 tloge("memcpy error sret is %d.\n", sret);
173 return (TeecResult)TEEC_ERROR_BAD_PARAMETERS;
174 }
175 cliContext->sessionId = msg->sessionId;
176 cliContext->cmdId = msg->cmdId;
177 cliContext->returns.code = 0;
178 cliContext->returns.origin = 0;
179 cliContext->login.method = cliLogin->method;
180 cliContext->login.mdata = cliLogin->mdata;
181 /* support when operation is null */
182 if (operation == NULL) {
183 return TEEC_SUCCESS;
184 }
185 cliContext->started = operation->cancelFlag;
186 ret = ProcTeekEncode(cliContext, operation);
187 tlogv("cli param type %u\n", cliContext->paramTypes);
188 return ret;
189 }
190
TeekCheckTmpRef(TeecTempmemoryReference tmpref)191 static TeecResult TeekCheckTmpRef(TeecTempmemoryReference tmpref)
192 {
193 TeecResult ret;
194 bool checkValue = (tmpref.buffer == NULL) || (tmpref.size == 0);
195
196 if (checkValue == true) {
197 tloge("tmpref buffer is null, or size is zero\n");
198 ret = (TeecResult) TEEC_ERROR_BAD_PARAMETERS;
199 } else {
200 ret = (TeecResult) TEEC_SUCCESS;
201 }
202 return ret;
203 }
204
TeekCheckMemRef(TeecRegisteredmemoryReference memref,uint32_t paramType)205 static TeecResult TeekCheckMemRef(TeecRegisteredmemoryReference memref,
206 uint32_t paramType)
207 {
208 bool checkValue = (memref.parent == NULL) || (memref.parent->buffer == NULL);
209 bool checkOffset = false;
210
211 if (checkValue == true) {
212 tloge("parent of memref is null, or the buffer is zero\n");
213 return (TeecResult) TEEC_ERROR_BAD_PARAMETERS;
214 }
215 if (paramType == TEEC_MEMREF_PARTIAL_INPUT) {
216 if (!(memref.parent->flags & TEEC_MEM_INPUT)) {
217 return (TeecResult) TEEC_ERROR_BAD_PARAMETERS;
218 }
219 } else if (paramType == TEEC_MEMREF_PARTIAL_OUTPUT) {
220 if (!(memref.parent->flags & TEEC_MEM_OUTPUT)) {
221 return (TeecResult) TEEC_ERROR_BAD_PARAMETERS;
222 }
223 } else if (paramType == TEEC_MEMREF_PARTIAL_INOUT) {
224 if (!(memref.parent->flags & TEEC_MEM_INPUT)) {
225 return (TeecResult) TEEC_ERROR_BAD_PARAMETERS;
226 }
227 if (!(memref.parent->flags & TEEC_MEM_OUTPUT)) {
228 return (TeecResult) TEEC_ERROR_BAD_PARAMETERS;
229 }
230 } else if (paramType == TEEC_MEMREF_WHOLE) {
231 /* if type is TEEC_MEMREF_WHOLE, ignore it */
232 } else {
233 return (TeecResult)TEEC_ERROR_BAD_PARAMETERS;
234 }
235
236 checkValue = (paramType == TEEC_MEMREF_PARTIAL_INPUT) ||
237 (paramType == TEEC_MEMREF_PARTIAL_OUTPUT) ||
238 (paramType == TEEC_MEMREF_PARTIAL_INOUT);
239 if (checkValue == true) {
240 checkOffset = (memref.offset + memref.size) > memref.parent->size ||
241 (memref.offset + memref.size) < memref.offset ||
242 (memref.offset + memref.size) < memref.size;
243 if (checkOffset == true) {
244 tloge("offset + size exceed the parent size\n");
245 return (TeecResult) TEEC_ERROR_BAD_PARAMETERS;
246 }
247 }
248 return (TeecResult) TEEC_SUCCESS;
249 }
250
251 /*
252 * This function checks an operation is valid or not.
253 */
TeekCheckOperation(const TeecOperation * operation)254 TeecResult TeekCheckOperation(const TeecOperation *operation)
255 {
256 uint32_t paramType[TEE_PARAM_NUM] = {0};
257 uint32_t paramCnt;
258 TeecResult ret = TEEC_SUCCESS;
259 bool checkValue = false;
260 bool checkTempMem = false;
261 bool checkPartMem = false;
262
263 /* GP Support operation is NULL
264 * operation: a pointer to a Client Application initialized TeecOperation structure,
265 * or NULL if there is no payload to send or if the Command does not need to support
266 * cancellation.
267 */
268 if (operation == NULL) {
269 return (TeecResult)TEEC_SUCCESS;
270 }
271 if (!operation->started) {
272 tloge("sorry, cancellation not support\n");
273 return (TeecResult) TEEC_ERROR_NOT_IMPLEMENTED;
274 }
275 paramType[TEE_PARAM_ONE] = TEEC_PARAM_TYPE_GET(operation->paramTypes, TEE_PARAM_ONE);
276 paramType[TEE_PARAM_TWO] = TEEC_PARAM_TYPE_GET(operation->paramTypes, TEE_PARAM_TWO);
277 paramType[TEE_PARAM_THREE] = TEEC_PARAM_TYPE_GET(operation->paramTypes, TEE_PARAM_THREE);
278 paramType[TEE_PARAM_FOUR] = TEEC_PARAM_TYPE_GET(operation->paramTypes, TEE_PARAM_FOUR);
279 for (paramCnt = 0; paramCnt < TEE_PARAM_NUM; paramCnt++) {
280 checkTempMem = paramType[paramCnt] == TEEC_MEMREF_TEMP_INPUT ||
281 paramType[paramCnt] == TEEC_MEMREF_TEMP_OUTPUT || paramType[paramCnt] == TEEC_MEMREF_TEMP_INOUT;
282 checkPartMem = paramType[paramCnt] == TEEC_MEMREF_WHOLE ||
283 paramType[paramCnt] == TEEC_MEMREF_PARTIAL_INPUT ||
284 paramType[paramCnt] == TEEC_MEMREF_PARTIAL_OUTPUT ||
285 paramType[paramCnt] == TEEC_MEMREF_PARTIAL_INOUT;
286 checkValue = paramType[paramCnt] == TEEC_VALUE_INPUT ||
287 paramType[paramCnt] == TEEC_VALUE_OUTPUT || paramType[paramCnt] == TEEC_VALUE_INOUT;
288 if (checkTempMem == true) {
289 ret = TeekCheckTmpRef(operation->params[paramCnt].tmpref);
290 if (ret != TEEC_SUCCESS) {
291 break;
292 }
293 } else if (checkPartMem == true) {
294 ret = TeekCheckMemRef(operation->params[paramCnt].memref, paramType[paramCnt]);
295 if (ret != TEEC_SUCCESS) {
296 break;
297 }
298 } else if (checkValue == true) {
299 /* if type is value, ignore it */
300 } else if (paramType[paramCnt] == TEEC_NONE) {
301 /* if type is none, ignore it */
302 } else {
303 tloge("paramType[%u]=%x is not support\n", paramCnt, paramType[paramCnt]);
304 ret = (TeecResult) TEEC_ERROR_BAD_PARAMETERS;
305 break;
306 }
307 }
308 return ret;
309 }
310
311 /*
312 * This function check if the special agent is launched.Used For HDCP key.
313 * e.g. If sfs agent is not alive, you can not do HDCP key write to SRAM.
314 */
TeekIsAgentAlive(unsigned int agentId)315 int TeekIsAgentAlive(unsigned int agentId)
316 {
317 return IsAgentAlive(agentId);
318 }
319
320 /*
321 * This function initializes a new TEE Context, forming a connection between this Client Application
322 * and the TEE identified by the string identifier name.
323 */
TeekInitializeContext(const char * name,TeecContext * context)324 TeecResult TeekInitializeContext(const char *name, TeecContext *context)
325 {
326 int32_t ret;
327
328 /* name current not used */
329 (void)(name);
330 tlogd("TeekInitializeContext Started:\n");
331 /* First, check parameters is valid or not */
332 if (context == NULL) {
333 tloge("context is null, not correct\n");
334 return (TeecResult) TEEC_ERROR_BAD_PARAMETERS;
335 }
336 context->dev = NULL;
337 /* Paramters right, start execution */
338 ret = TcNsClientOpen((TcNsDevFile **)&context->dev,
339 TEE_REQ_FROM_KERNEL_MODE);
340 if (ret != TEEC_SUCCESS) {
341 tloge("open device failed\n");
342 return (TeecResult) TEEC_ERROR_GENERIC;
343 }
344 tlogd("open device success\n");
345 TEEK_INIT_LIST_HEAD(&context->sessionList);
346 TEEK_INIT_LIST_HEAD(&context->shrdMemList);
347 return TEEC_SUCCESS;
348 }
349
350 /*
351 * This function finalizes an initialized TEE Context.
352 */
TeekFinalizeContext(TeecContext * context)353 void TeekFinalizeContext(TeecContext *context)
354 {
355 struct ListNode *ptr = NULL;
356 TeecSession *session = NULL;
357 /* TeecSharedMemory* shrdmem */
358 tlogd("TeekFinalizeContext started\n");
359 /* First, check parameters is valid or not */
360 if (context == NULL || context->dev == NULL) {
361 tloge("context or dev is null, not correct\n");
362 return;
363 }
364 /* Paramters right, start execution */
365 if (!LIST_EMPTY(&context->sessionList)) {
366 tlogi("context still has sessions opened, close it\n");
367 LIST_FOR_EACH(ptr, &context->sessionList) {
368 session = list_entry(ptr, TeecSession, head);
369 TeekCloseSession(session);
370 }
371 }
372 tlogd("close device\n");
373 TcNsClientClose(context->dev);
374 context->dev = NULL;
375 }
376
CheckParamsForOpenSession(TeecContext * context,const TeecOperation * operation,TcNsClientLogin * cliLogin)377 static TeecResult CheckParamsForOpenSession(TeecContext *context,
378 const TeecOperation *operation, TcNsClientLogin *cliLogin)
379 {
380 bool checkValue = false;
381 TcNsDevFile *devFile = NULL;
382 TeecResult teecRet;
383 errno_t sret;
384 uint32_t paramType[TEE_PARAM_NUM] = {0};
385
386 paramType[TEE_PARAM_FOUR] = TEEC_PARAM_TYPE_GET(operation->paramTypes, TEE_PARAM_FOUR);
387 paramType[TEE_PARAM_THREE] = TEEC_PARAM_TYPE_GET(operation->paramTypes, TEE_PARAM_THREE);
388 checkValue = paramType[TEE_PARAM_FOUR] != TEEC_MEMREF_TEMP_INPUT ||
389 paramType[TEE_PARAM_THREE] != TEEC_MEMREF_TEMP_INPUT;
390 if (checkValue == true) {
391 tloge("invalid param type 0x%x\n", operation->paramTypes);
392 return (TeecResult)TEEC_ERROR_BAD_PARAMETERS;
393 }
394 checkValue = operation->params[TEE_PARAM_FOUR].tmpref.buffer == NULL ||
395 operation->params[TEE_PARAM_THREE].tmpref.buffer == NULL ||
396 operation->params[TEE_PARAM_FOUR].tmpref.size == 0 || operation->params[TEE_PARAM_THREE].tmpref.size == 0;
397 if (checkValue == true) {
398 tloge("invalid operation params(NULL)\n");
399 return (TeecResult)TEEC_ERROR_BAD_PARAMETERS;
400 }
401 cliLogin->method = TEEC_LOGIN_IDENTIFY;
402 devFile = (TcNsDevFile *)(context->dev);
403 if (devFile == NULL) {
404 tloge("invalid context->dev (NULL)\n");
405 return (TeecResult)TEEC_ERROR_BAD_PARAMETERS;
406 }
407 devFile->pkgNameLen = operation->params[TEE_PARAM_FOUR].tmpref.size;
408 if (operation->params[TEE_PARAM_FOUR].tmpref.size > (MAX_PACKAGE_NAME_LEN - 1)) {
409 return (TeecResult)TEEC_ERROR_BAD_PARAMETERS;
410 } else {
411 sret = memset_s(devFile->PkgName, sizeof(devFile->PkgName), 0, MAX_PACKAGE_NAME_LEN);
412 if (sret != EOK) {
413 tloge("memset error sret is %d.\n", sret);
414 return (TeecResult)TEEC_ERROR_BAD_PARAMETERS;
415 }
416 sret = memcpy_s(devFile->PkgName, sizeof(devFile->PkgName), operation->params[TEE_PARAM_FOUR].tmpref.buffer,
417 operation->params[TEE_PARAM_FOUR].tmpref.size);
418 if (sret != EOK) {
419 tloge("memcpy error sret is %d.\n", sret);
420 return (TeecResult)TEEC_ERROR_BAD_PARAMETERS;
421 }
422 }
423 devFile->pubKeyLen = 0;
424 devFile->loginSetup = 1;
425 teecRet = TeekCheckOperation(operation);
426 if (teecRet != TEEC_SUCCESS) {
427 tloge("operation is invalid\n");
428 return (TeecResult)TEEC_ERROR_BAD_PARAMETERS;
429 }
430 return teecRet;
431 }
432
OpenSessionAndSwitchRet(TeecSession * session,TeecContext * context,const TeecUuid * destination,TcNsClientContext * cliContext,uint32_t * origin)433 static TeecResult OpenSessionAndSwitchRet(TeecSession *session,
434 TeecContext *context, const TeecUuid *destination,
435 TcNsClientContext *cliContext, uint32_t *origin)
436 {
437 int32_t ret;
438 TeecResult teecRet;
439
440 ret = TcNsOpenSession(context->dev, cliContext);
441 if (ret == 0) {
442 tlogd("open session success\n");
443 session->sessionId = cliContext->sessionId;
444 session->serviceId = *destination;
445 session->opsCnt = 0;
446 TEEK_INIT_LIST_HEAD(&session->head);
447 ListInsertTail(&context->sessionList, &session->head);
448 session->context = context;
449 return TEEC_SUCCESS;
450 } else if (ret < 0) {
451 tloge("open session failed, ioctl errno = %u\n", ret);
452 if (ret == -EFAULT) {
453 teecRet = (TeecResult) TEEC_ERROR_ACCESS_DENIED;
454 } else if (ret == -ENOMEM) {
455 teecRet = (TeecResult) TEEC_ERROR_OUT_OF_MEMORY;
456 } else if (ret == -EINVAL) {
457 teecRet = (TeecResult) TEEC_ERROR_BAD_PARAMETERS;
458 } else if (ret == -ERESTARTSYS) {
459 teecRet = (TeecResult) TEEC_CLIENT_INTR;
460 } else {
461 teecRet = (TeecResult) TEEC_ERROR_GENERIC;
462 }
463 *origin = TEEC_ORIGIN_COMMS;
464 return teecRet;
465 } else {
466 tloge("open session failed, code=0x%x, origin=%u\n", cliContext->returns.code,
467 cliContext->returns.origin);
468 teecRet = (TeecResult)cliContext->returns.code;
469 *origin = cliContext->returns.origin;
470 }
471 return teecRet;
472 }
473
474 /*
475 * Function: TEEC_OpenSession
476 * Description: This function opens a new Session
477 * Parameters: context: a pointer to an initialized TEE Context.
478 * session: a pointer to a Session structure to open.
479 * destination: a pointer to a UUID structure.
480 * connectionMethod: the method of connection to use.
481 * connectionData: any necessary data required to support the connection method chosen.
482 * operation: a pointer to an Operation containing a set of Parameters.
483 * returnOrigin: a pointer to a variable which will contain the return origin.
484 * Return: TEEC_SUCCESS: success other: failure
485 */
ProcTeekOpenSession(TeecContext * context,TeecSession * session,const TeecUuid * destination,uint32_t connectionMethod,const void * connectionData,const TeecOperation * operation,uint32_t * returnOrigin)486 static TeecResult ProcTeekOpenSession(TeecContext *context,
487 TeecSession *session, const TeecUuid *destination,
488 uint32_t connectionMethod, const void *connectionData,
489 const TeecOperation *operation, uint32_t *returnOrigin)
490 {
491 TeecResult teecRet;
492 uint32_t origin = TEEC_ORIGIN_API;
493 TcNsClientContext cliContext;
494 TcNsClientLogin cliLogin = { 0, 0 };
495 bool checkValue = false;
496
497 tlogd("TeekOpenSession Started:\n");
498 /* connectionData current not used */
499 (void)(connectionData);
500 /* returnOrigin maybe null, so only when it is valid, we set
501 * origin(error come from which module)
502 */
503 if (returnOrigin != NULL) {
504 *returnOrigin = origin;
505 }
506 /* First, check parameters is valid or not */
507 checkValue = (context == NULL || operation == NULL ||
508 connectionMethod != TEEC_LOGIN_IDENTIFY);
509 if (checkValue == true || destination == NULL || session == NULL) {
510 tloge("invalid input params\n");
511 return TEEC_ERROR_BAD_PARAMETERS;
512 }
513 teecRet = CheckParamsForOpenSession(context, operation, &cliLogin);
514 if (teecRet != TEEC_SUCCESS) {
515 goto RET_FAIL;
516 }
517 /* Paramters right, start execution
518 * note:before open session success,
519 * we should send session=0 as initial state.
520 */
521 struct TeekEncodeMeg msg = {
522 *destination, 0, GLOBAL_CMD_ID_OPEN_SESSION
523 };
524 teecRet = TeekEncode(&cliContext, &msg, &cliLogin, operation);
525 if (teecRet != TEEC_SUCCESS) {
526 tloge("encode failed\n");
527 goto RET_FAIL;
528 }
529 #ifdef SECURITY_AUTH_ENHANCE
530 cliContext.teecToken = session->teecToken;
531 cliContext.tokenLen = sizeof(session->teecToken);
532 #endif
533 teecRet = OpenSessionAndSwitchRet(session, context,
534 destination, &cliContext, &origin);
535 /* ONLY when ioctl returnCode!=0 and returnOrigin not NULL, set returnOrigin */
536 if (teecRet != TEEC_SUCCESS && returnOrigin != NULL) {
537 *returnOrigin = origin;
538 }
539 RET_FAIL:
540 return teecRet;
541 }
542
543 #define RETRY_TIMES 5
TeekOpenSession(TeecContext * context,TeecSession * session,const TeecUuid * destination,uint32_t connectionMethod,const void * connectionData,const TeecOperation * operation,uint32_t * returnOrigin)544 TeecResult TeekOpenSession(TeecContext *context,
545 TeecSession *session, const TeecUuid *destination,
546 uint32_t connectionMethod, const void *connectionData,
547 const TeecOperation *operation, uint32_t *returnOrigin)
548 {
549 int i;
550 TeecResult ret;
551
552 for (i = 0; i < RETRY_TIMES; i++) {
553 ret = ProcTeekOpenSession(context, session,
554 destination, connectionMethod, connectionData,
555 operation, returnOrigin);
556 if (ret != (TeecResult)TEEC_CLIENT_INTR) {
557 return ret;
558 }
559 }
560 return ret;
561 }
562
CheckCloseSessionParam(TeecSession * session)563 static int CheckCloseSessionParam(TeecSession *session)
564 {
565 bool checkValue = false;
566 bool found = false;
567 TeecSession *tempSess = NULL;
568 struct ListNode *ptr = NULL;
569
570 /* First, check parameters is valid or not */
571 checkValue = session == NULL || session->context == NULL;
572 if (checkValue || session->context->dev == NULL) {
573 tloge("input invalid session or session->context is null\n");
574 return -1;
575 }
576 LIST_FOR_EACH(ptr, &session->context->sessionList) {
577 tempSess = list_entry(ptr, TeecSession, head);
578 if (tempSess == session) {
579 found = true;
580 break;
581 }
582 }
583 if (!found) {
584 tloge("session is not in the context list\n");
585 return -1;
586 }
587 return 0;
588 }
589
590 /*
591 * This function closes an opened Session.
592 */
TeekCloseSession(TeecSession * session)593 void TeekCloseSession(TeecSession *session)
594 {
595 int32_t ret;
596 TcNsClientContext cliContext;
597 TcNsClientLogin cliLogin = { 0, 0 };
598 errno_t sret;
599
600 tlogd("TeekCloseSession started\n");
601 ret = CheckCloseSessionParam(session);
602 if (ret) {
603 return;
604 }
605 /* Paramters all right, start execution */
606 if (session->opsCnt) {
607 tloge("session still has commands running\n");
608 }
609 struct TeekEncodeMeg msg = {
610 session->serviceId, session->sessionId, GLOBAL_CMD_ID_CLOSE_SESSION
611 };
612 if (TeekEncode(&cliContext, &msg, &cliLogin, NULL) != TEEC_SUCCESS) {
613 tloge("encode failed, just return\n");
614 return;
615 }
616 #ifdef SECURITY_AUTH_ENHANCE
617 cliContext.teecToken = session->teecToken;
618 cliContext.tokenLen = sizeof(session->teecToken);
619 #endif
620 ret = TcNsCloseSession(session->context->dev, &cliContext);
621 if (ret == 0) {
622 tlogd("close session success\n");
623 session->sessionId = 0;
624 sret = memset_s((uint8_t *)(&session->serviceId), sizeof(session->serviceId), 0x00, UUID_LEN);
625 /* TeekCloseSession is void so go on execute */
626 if (sret != EOK) {
627 tloge("memset error sret is %d.\n", sret);
628 }
629 #ifdef SECURITY_AUTH_ENHANCE
630 sret = memset_s(session->teecToken, TOKEN_SAVE_LEN, 0x00, TOKEN_SAVE_LEN);
631 if (sret != EOK) {
632 tloge("memset session's member error ret value is %d.\n", sret);
633 }
634 #endif
635 session->opsCnt = 0;
636 ListRemove(&session->head);
637 session->context = NULL;
638 } else {
639 tloge("close session failed\n");
640 }
641 }
642
InvokeCmdAndSwitchRet(TeecSession * session,TcNsClientContext * cliContext,uint32_t * origin)643 static TeecResult InvokeCmdAndSwitchRet(TeecSession *session,
644 TcNsClientContext *cliContext, uint32_t *origin)
645 {
646 int32_t ret;
647 TeecResult teecRet;
648
649 ret = TcNsSendCmd(session->context->dev, cliContext);
650 if (ret == 0) {
651 tlogd("invoke cmd success\n");
652 teecRet = TEEC_SUCCESS;
653 } else if (ret < 0) {
654 tloge("invoke cmd failed, ioctl errno = %d\n", ret);
655 if (ret == -EFAULT) {
656 teecRet = (TeecResult)TEEC_ERROR_ACCESS_DENIED;
657 } else if (ret == -ENOMEM) {
658 teecRet = (TeecResult)TEEC_ERROR_OUT_OF_MEMORY;
659 } else if (ret == -EINVAL) {
660 teecRet = (TeecResult)TEEC_ERROR_BAD_PARAMETERS;
661 } else {
662 teecRet = (TeecResult)TEEC_ERROR_GENERIC;
663 }
664 *origin = TEEC_ORIGIN_COMMS;
665 } else {
666 tloge("invoke cmd failed, code=0x%x, origin=%d\n",
667 cliContext->returns.code, cliContext->returns.origin);
668 teecRet = (TeecResult)cliContext->returns.code;
669 *origin = cliContext->returns.origin;
670 }
671 return teecRet;
672 }
673
674 /* This function invokes a Command within the specified Session. */
TeekInvokeCommand(TeecSession * session,uint32_t commandID,TeecOperation * operation,uint32_t * returnOrigin)675 TeecResult TeekInvokeCommand(TeecSession *session, uint32_t commandID,
676 TeecOperation *operation, uint32_t *returnOrigin)
677 {
678 TeecResult teecRet = (TeecResult) TEEC_ERROR_BAD_PARAMETERS;
679 uint32_t origin = TEEC_ORIGIN_API;
680 TcNsClientContext cliContext;
681 TcNsClientLogin cliLogin = { 0, 0 };
682
683 tlogd("TeekInvokeCommand Started:\n");
684 /* First, check parameters is valid or not */
685 if (session == NULL || session->context == NULL) {
686 tloge("input invalid session or session->context is null\n");
687 if (returnOrigin != NULL) {
688 *returnOrigin = origin;
689 }
690 return teecRet;
691 }
692 teecRet = TeekCheckOperation(operation);
693 if (teecRet != TEEC_SUCCESS) {
694 tloge("operation is invalid\n");
695 if (returnOrigin != NULL) {
696 *returnOrigin = origin;
697 }
698 return teecRet;
699 }
700 /* Paramters all right, start execution */
701 session->opsCnt++;
702 struct TeekEncodeMeg msg = {
703 session->serviceId, session->sessionId, commandID
704 };
705 teecRet = TeekEncode(&cliContext, &msg, &cliLogin, operation);
706 if (teecRet != TEEC_SUCCESS) {
707 tloge("encode failed\n");
708 session->opsCnt--;
709 if (returnOrigin != NULL) {
710 *returnOrigin = origin;
711 }
712 return teecRet;
713 }
714 #ifdef SECURITY_AUTH_ENHANCE
715 cliContext.teecToken = session->teecToken;
716 cliContext.tokenLen = sizeof(session->teecToken);
717 #endif
718 teecRet = InvokeCmdAndSwitchRet(session, &cliContext, &origin);
719 session->opsCnt--;
720 /* ONLY when ioctl returnCode!=0 and returnOrigin not NULL, set *returnOrigin */
721 if ((teecRet != TEEC_SUCCESS) && (returnOrigin != NULL)) {
722 *returnOrigin = origin;
723 }
724 return teecRet;
725 }
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 */
TeekRegisterSharedMemory(TeecContext * context,TeecSharedMemory * sharedMem)731 TeecResult TeekRegisterSharedMemory(TeecContext *context,
732 TeecSharedMemory *sharedMem)
733 {
734 tloge("TeekRegisterSharedMemory not supported\n");
735 return (TeecResult)TEEC_ERROR_NOT_SUPPORTED;
736 }
737
738 /*
739 * This function allocates a new block of memory as a block of
740 * Shared Memory within the scope of the specified TEE Context.
741 */
TeekAllocateSharedMemory(TeecContext * context,TeecSharedMemory * sharedMem)742 TeecResult TeekAllocateSharedMemory(TeecContext *context,
743 TeecSharedMemory *sharedMem)
744 {
745 tloge("TeekAllocateSharedMemory not supported\n");
746 return (TeecResult)TEEC_ERROR_NOT_SUPPORTED;
747 }
748
749 /*
750 * This function deregisters or deallocates
751 * a previously initialized block of Shared Memory..
752 */
TeekReleaseSharedMemory(TeecSharedMemory * sharedMem)753 void TeekReleaseSharedMemory(TeecSharedMemory *sharedMem)
754 {
755 tloge("TeekReleaseSharedMemory not supported\n");
756 }
757
758 /*
759 * This function requests the cancellation of a pending open Session operation or
760 * a Command invocation operation.
761 */
TeekRequestCancellation(TeecOperation * operation)762 void TeekRequestCancellation(TeecOperation *operation)
763 {
764 tloge("TeekRequestCancellation not supported\n");
765 }
766