1 /*
2 * Copyright (C) 2022 Huawei Technologies Co., Ltd.
3 * Licensed under the Mulan PSL v2.
4 * You can use this software according to the terms and conditions of the Mulan PSL v2.
5 * You may obtain a copy of Mulan PSL v2 at:
6 * http://license.coscl.org.cn/MulanPSL2
7 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
8 * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
9 * PURPOSE.
10 * See the Mulan PSL v2 for more details.
11 */
12
13 #include "tee_client_api.h"
14 #include <errno.h> /* for errno */
15 #include <fcntl.h>
16 #include <limits.h>
17 #include <pthread.h>
18 #include <securec.h>
19 #include <stdint.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <sys/ioctl.h> /* for ioctl */
24 #include <sys/mman.h> /* for mmap */
25 #include <sys/stat.h>
26 #include <sys/types.h> /* for open close */
27 #include "tc_ns_client.h"
28 #include "tee_client_app_load.h"
29 #include "tee_client_inner_api.h"
30 #include "tee_client_list.h"
31 #include "tee_get_native_cert.h"
32 #include "tee_log.h"
33 #include "tee_client_socket.h"
34 #include "tee_auth_system.h"
35
36 #define TEE_ERROR_CA_AUTH_FAIL 0xFFFFCFE5
37
38 #define AGENT_BUFF_SIZE 0x1000
39 #define CA_AUTH_RETRY_TIMES 30
40 #define H_OFFSET 32
41
42 #ifdef LOG_TAG
43 #undef LOG_TAG
44 #endif
45 #define LOG_TAG "libteec_vendor"
46
47 #define SHIFT 3
48 #define MASK 0x7
49 #define BYTE_BIT 8
50
SetBit(uint32_t i,uint32_t byteMax,uint8_t * bitMap)51 void SetBit(uint32_t i, uint32_t byteMax, uint8_t *bitMap)
52 {
53 if ((i >> SHIFT) >= byteMax) {
54 return;
55 }
56 if (bitMap == NULL) {
57 return;
58 }
59 bitMap[i >> SHIFT] |= (1U << (i & MASK));
60 }
61
ClearBit(uint32_t i,uint32_t byteMax,uint8_t * bitMap)62 void ClearBit(uint32_t i, uint32_t byteMax, uint8_t *bitMap)
63 {
64 if ((i >> SHIFT) >= byteMax) {
65 return;
66 }
67 if (bitMap == NULL) {
68 return;
69 }
70 bitMap[i >> SHIFT] &= ~(1U << (i & MASK));
71 }
72
ClearBitWithLock(pthread_mutex_t * mutex,uint32_t i,uint32_t byteMax,uint8_t * bitMap)73 static void ClearBitWithLock(pthread_mutex_t *mutex, uint32_t i, uint32_t byteMax, uint8_t *bitMap)
74 {
75 if (pthread_mutex_lock(mutex) != 0) {
76 tloge("get share mem bit lock failed\n");
77 return;
78 }
79 ClearBit(i, byteMax, bitMap);
80 (void)pthread_mutex_unlock(mutex);
81 }
82
83 enum BitmapOps {
84 SET,
85 CLEAR
86 };
87
IterateBitmap(uint8_t * bitMap,uint32_t byteMax,enum BitmapOps ops)88 static int32_t IterateBitmap(uint8_t *bitMap, uint32_t byteMax, enum BitmapOps ops)
89 {
90 uint32_t i, j;
91 int32_t validBit = -1;
92 uint8_t refByte = ((ops == SET) ? 0xff : 0);
93 bool refBit = ((ops == SET) ? true : false);
94
95 for (i = 0; i < byteMax; i++) {
96 if (bitMap[i] == refByte) {
97 continue;
98 }
99 for (j = 0; j < BYTE_BIT; j++) {
100 bool bitZero = (bitMap[i] & (0x1 << j)) == 0;
101 if (bitZero == refBit) {
102 validBit = (int32_t)i * BYTE_BIT + (int32_t)j;
103 break;
104 }
105 }
106
107 if (validBit != -1) {
108 break;
109 }
110 }
111
112 if (validBit == -1) {
113 return validBit;
114 }
115
116 if (ops == SET) {
117 SetBit(validBit, byteMax, bitMap);
118 } else {
119 ClearBit(validBit, byteMax, bitMap);
120 }
121 return validBit;
122 }
123
GetAndSetBit(uint8_t * bitMap,uint32_t byteMax)124 int32_t GetAndSetBit(uint8_t *bitMap, uint32_t byteMax)
125 {
126 if (bitMap == NULL) {
127 return -1;
128 }
129 return IterateBitmap(bitMap, byteMax, SET);
130 }
131
GetAndSetBitWithLock(pthread_mutex_t * mutex,uint8_t * bitMap,uint32_t byteMax)132 static int32_t GetAndSetBitWithLock(pthread_mutex_t *mutex, uint8_t *bitMap, uint32_t byteMax)
133 {
134 if (pthread_mutex_lock(mutex) != 0) {
135 tloge("get share mem bit lock failed\n");
136 return -1;
137 }
138 int32_t validBit = GetAndSetBit(bitMap, byteMax);
139 (void)pthread_mutex_unlock(mutex);
140 return validBit;
141 }
142
GetAndCleartBit(uint8_t * bitMap,uint32_t byteMax)143 int32_t GetAndCleartBit(uint8_t *bitMap, uint32_t byteMax)
144 {
145 if (bitMap == NULL) {
146 return -1;
147 }
148 return IterateBitmap(bitMap, byteMax, CLEAR);
149 }
150
151 static pthread_mutex_t g_mutexAtom = PTHREAD_MUTEX_INITIALIZER;
AtomInc(volatile uint32_t * cnt)152 static void AtomInc(volatile uint32_t *cnt)
153 {
154 /*
155 * The use of g_mutexAtom has been rigorously checked
156 * and there is no risk of failure, we do not care the return value
157 * of pthread_mutex_lock here
158 */
159 (void)pthread_mutex_lock(&g_mutexAtom);
160 (*cnt)++;
161 (void)pthread_mutex_unlock(&g_mutexAtom);
162 }
163
AtomDecAndCompareWithZero(volatile uint32_t * cnt)164 static bool AtomDecAndCompareWithZero(volatile uint32_t *cnt)
165 {
166 bool result = false;
167
168 /*
169 * The use of g_mutexAtom has been rigorously checked
170 * and there is no risk of failure, we do not care the return value
171 * of pthread_mutex_lock here
172 */
173 (void)pthread_mutex_lock(&g_mutexAtom);
174 (*cnt)--;
175 if ((*cnt) == 0) {
176 result = true;
177 }
178 (void)pthread_mutex_unlock(&g_mutexAtom);
179 return result;
180 }
181
182 static LIST_DECLARE(g_teecContextList);
183 static pthread_mutex_t g_mutexTeecContext = PTHREAD_MUTEX_INITIALIZER;
184 TEEC_Result TEEC_CheckOperation(TEEC_ContextInner *context, const TEEC_Operation *operation);
185
MutexLockContext(void)186 static int32_t MutexLockContext(void)
187 {
188 int lockRet = pthread_mutex_lock(&g_mutexTeecContext);
189 return lockRet;
190 }
191
MutexUnlockContext(int lockRet)192 static void MutexUnlockContext(int lockRet)
193 {
194 if (lockRet) {
195 tloge("unlock mutex: not exe, mutex not in lock state. lockRet = %d\n", lockRet);
196 return;
197 }
198 (void)pthread_mutex_unlock(&g_mutexTeecContext);
199 }
200
AddSessionList(uint32_t sessionId,const TEEC_UUID * destination,TEEC_ContextInner * context,TEEC_Session * session)201 static TEEC_Result AddSessionList(uint32_t sessionId, const TEEC_UUID *destination, TEEC_ContextInner *context,
202 TEEC_Session *session)
203 {
204 struct ListNode *node = NULL;
205 struct ListNode *n = NULL;
206 TEEC_Session *sessionEntry = NULL;
207
208 session->session_id = sessionId;
209 session->service_id = *destination;
210 session->ops_cnt = 1; /* only for libteec, not for vendor ca */
211
212 int lockRet = pthread_mutex_lock(&context->sessionLock);
213 if (lockRet != 0) {
214 tloge("get session lock failed.\n");
215 return TEEC_ERROR_GENERIC;
216 }
217 /* if session is still in list, remove it */
218 LIST_FOR_EACH_SAFE(node, n, &context->session_list)
219 {
220 sessionEntry = CONTAINER_OF(node, TEEC_Session, head);
221 if (sessionEntry == session) {
222 ListRemoveEntry(node);
223 }
224 }
225 ListInit(&session->head);
226 ListInsertTail(&context->session_list, &session->head);
227 AtomInc(&session->ops_cnt); /* only for libteec, not for vendor ca */
228 (void)pthread_mutex_unlock(&context->sessionLock);
229 return TEEC_SUCCESS;
230 }
231
FindBnContext(const TEEC_Context * context)232 static TEEC_ContextInner *FindBnContext(const TEEC_Context *context)
233 {
234 TEEC_ContextInner *sContext = NULL;
235
236 if (context == NULL) {
237 tloge("find context: context is NULL!\n");
238 return NULL;
239 }
240
241 struct ListNode *ptr = NULL;
242 if (!LIST_EMPTY(&g_teecContextList)) {
243 LIST_FOR_EACH(ptr, &g_teecContextList)
244 {
245 TEEC_ContextInner *tmp = CONTAINER_OF(ptr, TEEC_ContextInner, c_node);
246 if (tmp->fd == context->fd) {
247 sContext = tmp;
248 break;
249 }
250 }
251 }
252 return sContext;
253 }
254
GetBnContext(const TEEC_Context * context)255 TEEC_ContextInner *GetBnContext(const TEEC_Context *context)
256 {
257 TEEC_ContextInner *sContext = NULL;
258
259 int retMutexLock = MutexLockContext();
260 if (retMutexLock != 0) {
261 tloge("get context lock failed.\n");
262 return NULL;
263 }
264 sContext = FindBnContext(context);
265 if (sContext != NULL) {
266 AtomInc(&sContext->ops_cnt);
267 }
268 MutexUnlockContext(retMutexLock);
269 return sContext;
270 }
271
PutBnContext(TEEC_ContextInner * context)272 bool PutBnContext(TEEC_ContextInner *context)
273 {
274 if (context == NULL) {
275 tloge("put context: context is NULL!\n");
276 return false;
277 }
278
279 if (AtomDecAndCompareWithZero(&context->ops_cnt)) {
280 TEEC_FinalizeContextInner(context);
281 return true;
282 }
283
284 return false;
285 }
286
FindAndRemoveBnContext(const TEEC_Context * context)287 TEEC_ContextInner *FindAndRemoveBnContext(const TEEC_Context *context)
288 {
289 TEEC_ContextInner *sContext = NULL;
290
291 int retMutexLock = MutexLockContext();
292 if (retMutexLock != 0) {
293 tloge("get context lock failed.\n");
294 return NULL;
295 }
296 sContext = FindBnContext(context);
297 if (sContext != NULL) {
298 ListRemoveEntry(&sContext->c_node);
299 }
300 MutexUnlockContext(retMutexLock);
301 return sContext;
302 }
303
FindBnSession(const TEEC_Session * session,const TEEC_ContextInner * context)304 static TEEC_Session *FindBnSession(const TEEC_Session *session, const TEEC_ContextInner *context)
305 {
306 TEEC_Session *sSession = NULL;
307
308 struct ListNode *ptr = NULL;
309 if (!LIST_EMPTY(&context->session_list)) {
310 LIST_FOR_EACH(ptr, &context->session_list)
311 {
312 TEEC_Session *tmp = CONTAINER_OF(ptr, TEEC_Session, head);
313 if (tmp->session_id == session->session_id) {
314 sSession = tmp;
315 break;
316 }
317 }
318 }
319 return sSession;
320 }
321
322 /* only for libteec, not for vendor ca */
GetBnSession(const TEEC_Session * session,TEEC_ContextInner * context)323 TEEC_Session *GetBnSession(const TEEC_Session *session, TEEC_ContextInner *context)
324 {
325 TEEC_Session *sSession = NULL;
326
327 if (session == NULL || context == NULL) {
328 tloge("get session: context or session is NULL!\n");
329 return NULL;
330 }
331
332 int lockRet = pthread_mutex_lock(&context->sessionLock);
333 if (lockRet != 0) {
334 tloge("get session lock failed.\n");
335 return NULL;
336 }
337 sSession = FindBnSession(session, context);
338 if (sSession != NULL) {
339 AtomInc(&sSession->ops_cnt);
340 }
341 (void)pthread_mutex_unlock(&context->sessionLock);
342 return sSession;
343 }
344
345 /* only for libteec, not for vendor ca */
PutBnSession(TEEC_Session * session)346 void PutBnSession(TEEC_Session *session)
347 {
348 if (session == NULL) {
349 tloge("put session: session is NULL!\n");
350 return;
351 }
352
353 if (AtomDecAndCompareWithZero(&session->ops_cnt)) {
354 free(session);
355 }
356 return;
357 }
358
FindAndRemoveSession(const TEEC_Session * session,TEEC_ContextInner * context)359 TEEC_Session *FindAndRemoveSession(const TEEC_Session *session, TEEC_ContextInner *context)
360 {
361 TEEC_Session *sSession = NULL;
362
363 if (session == NULL || context == NULL) {
364 tloge("find and remove session: context or session is NULL!\n");
365 return NULL;
366 }
367
368 int lockRet = pthread_mutex_lock(&context->sessionLock);
369 if (lockRet != 0) {
370 tloge("get session lock failed.\n");
371 return NULL;
372 }
373 sSession = FindBnSession(session, context);
374 if (sSession != NULL) {
375 ListRemoveEntry(&sSession->head);
376 }
377 (void)pthread_mutex_unlock(&context->sessionLock);
378 return sSession;
379 }
380
ReleaseSharedMemory(TEEC_SharedMemoryInner * sharedMem)381 static void ReleaseSharedMemory(TEEC_SharedMemoryInner *sharedMem)
382 {
383 bool condition = (sharedMem->is_allocated) && (sharedMem->buffer != NULL) && (sharedMem->buffer != ZERO_SIZE_PTR) &&
384 (sharedMem->size != 0);
385 if (condition) {
386 int32_t ret = ioctl(sharedMem->context->fd, (int)TC_NS_CLIENT_IOCTL_UNMAP_SHARED_MEM, sharedMem->buffer);
387 if (ret) {
388 tlogd("Release SharedMemory ioctl failed, maybe linux not support\n");
389 }
390
391 ret = munmap(sharedMem->buffer, sharedMem->size);
392 if (ret) {
393 tloge("Release SharedMemory failed, munmap error\n");
394 }
395 ClearBitWithLock(&sharedMem->context->shrMemBitMapLock, sharedMem->offset,
396 sizeof(sharedMem->context->shm_bitmap), sharedMem->context->shm_bitmap);
397 }
398
399 sharedMem->buffer = NULL;
400 sharedMem->size = 0;
401 sharedMem->flags = 0;
402 sharedMem->ops_cnt = 0;
403 sharedMem->context = NULL;
404 free(sharedMem);
405 }
406
PutBnShrMem(TEEC_SharedMemoryInner * shrMem)407 void PutBnShrMem(TEEC_SharedMemoryInner *shrMem)
408 {
409 if (shrMem == NULL) {
410 return;
411 }
412
413 if (AtomDecAndCompareWithZero(&shrMem->ops_cnt)) {
414 ReleaseSharedMemory(shrMem);
415 }
416 return;
417 }
418
GetBnShmByOffset(uint32_t shmOffset,TEEC_ContextInner * context)419 TEEC_SharedMemoryInner *GetBnShmByOffset(uint32_t shmOffset, TEEC_ContextInner *context)
420 {
421 TEEC_SharedMemoryInner *tempShardMem = NULL;
422
423 if (context == NULL) {
424 tloge("get shrmem offset: context is NULL!\n");
425 return NULL;
426 }
427
428 int lockRet = pthread_mutex_lock(&context->shrMemLock);
429 if (lockRet != 0) {
430 tloge("get shrmem lock failed.\n");
431 return NULL;
432 }
433
434 /* found server shardmem */
435 struct ListNode *ptr = NULL;
436 if (!LIST_EMPTY(&context->shrd_mem_list)) {
437 LIST_FOR_EACH(ptr, &context->shrd_mem_list)
438 {
439 tempShardMem = CONTAINER_OF(ptr, TEEC_SharedMemoryInner, head);
440 if (tempShardMem->offset == shmOffset) {
441 AtomInc(&tempShardMem->ops_cnt);
442 (void)pthread_mutex_unlock(&context->shrMemLock);
443 return tempShardMem;
444 }
445 }
446 }
447 (void)pthread_mutex_unlock(&context->shrMemLock);
448 return NULL;
449 }
450
MallocShrMemInner(TEEC_SharedMemoryInner ** shareMemInner)451 static TEEC_Result MallocShrMemInner(TEEC_SharedMemoryInner **shareMemInner)
452 {
453 errno_t nRet;
454
455 TEEC_SharedMemoryInner *shmInner = (TEEC_SharedMemoryInner *)malloc(sizeof(*shmInner));
456 if (shmInner == NULL) {
457 tloge("malloc shrmem: shmInner malloc failed\n");
458 return TEEC_FAIL;
459 }
460 nRet = memset_s(shmInner, sizeof(*shmInner), 0x00, sizeof(*shmInner));
461 if (nRet != EOK) {
462 tloge("malloc shrmem: shmInner memset failed : %d\n", (int)nRet);
463 free(shmInner);
464 return TEEC_FAIL;
465 }
466 *shareMemInner = shmInner;
467 return TEEC_SUCCESS;
468 }
469
TranslateRetValue(int32_t ret)470 static TEEC_Result TranslateRetValue(int32_t ret)
471 {
472 TEEC_Result teeRet;
473
474 switch (ret) {
475 case -EFAULT:
476 teeRet = TEEC_ERROR_ACCESS_DENIED;
477 break;
478 case -ENOMEM:
479 teeRet = TEEC_ERROR_OUT_OF_MEMORY;
480 break;
481 case -EINVAL:
482 teeRet = TEEC_ERROR_BAD_PARAMETERS;
483 break;
484 default:
485 teeRet = TEEC_ERROR_GENERIC;
486 break;
487 }
488 return teeRet;
489 }
490
TranslateParamType(uint32_t flag)491 static uint32_t TranslateParamType(uint32_t flag)
492 {
493 uint32_t paramType;
494
495 switch (flag) {
496 case TEEC_MEM_INPUT:
497 paramType = TEEC_MEMREF_PARTIAL_INPUT;
498 break;
499 case TEEC_MEM_OUTPUT:
500 paramType = TEEC_MEMREF_PARTIAL_OUTPUT;
501 break;
502 case TEEC_MEM_INOUT:
503 paramType = TEEC_MEMREF_PARTIAL_INOUT;
504 break;
505 default:
506 paramType = TEEC_MEMREF_PARTIAL_INOUT;
507 break;
508 }
509
510 return paramType;
511 }
512
TEEC_EncodeTempParam(const TEEC_TempMemoryReference * tempRef,TC_NS_ClientParam * param)513 static void TEEC_EncodeTempParam(const TEEC_TempMemoryReference *tempRef, TC_NS_ClientParam *param)
514 {
515 param->memref.buffer = (unsigned int)(uintptr_t)tempRef->buffer;
516 param->memref.buffer_h_addr = ((unsigned long long)(uintptr_t)tempRef->buffer) >> H_OFFSET;
517 param->memref.size_addr = (unsigned int)(uintptr_t)&tempRef->size;
518 param->memref.size_h_addr = ((unsigned long long)(uintptr_t)&tempRef->size) >> H_OFFSET;
519 }
520
TEEC_EncodePartialParam(uint32_t paramType,const TEEC_RegisteredMemoryReference * memRef,TC_NS_ClientParam * param)521 static void TEEC_EncodePartialParam(uint32_t paramType, const TEEC_RegisteredMemoryReference *memRef,
522 TC_NS_ClientParam *param)
523 {
524 /* buffer offset len */
525 if (paramType == TEEC_MEMREF_WHOLE) {
526 param->memref.offset = 0;
527 param->memref.size_addr = (unsigned int)(uintptr_t)&memRef->parent->size;
528 param->memref.size_h_addr = ((unsigned long long)(uintptr_t)&memRef->parent->size) >> H_OFFSET;
529 } else {
530 param->memref.offset = memRef->offset;
531 param->memref.size_addr = (unsigned int)(uintptr_t)&memRef->size;
532 param->memref.size_h_addr = ((unsigned long long)(uintptr_t)&memRef->size) >> H_OFFSET;
533 }
534
535 if (memRef->parent->is_allocated) {
536 param->memref.buffer = (unsigned int)(uintptr_t)memRef->parent->buffer;
537 param->memref.buffer_h_addr = ((unsigned long long)(uintptr_t)memRef->parent->buffer) >> H_OFFSET;
538 } else {
539 param->memref.buffer = (unsigned int)(uintptr_t)((unsigned char *)memRef->parent->buffer + memRef->offset);
540 param->memref.buffer_h_addr =
541 (unsigned long long)(uintptr_t)((unsigned char *)memRef->parent->buffer + memRef->offset) >> H_OFFSET;
542 param->memref.offset = 0;
543 }
544 }
545
TEEC_EncodeValueParam(const TEEC_Value * val,TC_NS_ClientParam * param)546 static void TEEC_EncodeValueParam(const TEEC_Value *val, TC_NS_ClientParam *param)
547 {
548 param->value.a_addr = (unsigned int)(uintptr_t)&val->a;
549 param->value.a_h_addr = ((unsigned long long)(uintptr_t)&val->a) >> H_OFFSET;
550 param->value.b_addr = (unsigned int)(uintptr_t)&val->b;
551 param->value.b_h_addr = ((unsigned long long)(uintptr_t)&val->b) >> H_OFFSET;
552 }
553
TEEC_EncodeIonParam(const TEEC_IonReference * ionRef,TC_NS_ClientParam * param)554 static void TEEC_EncodeIonParam(const TEEC_IonReference *ionRef, TC_NS_ClientParam *param)
555 {
556 param->value.a_addr = (unsigned int)(uintptr_t)&ionRef->ionShareFd;
557 param->value.a_h_addr = (unsigned int)(((unsigned long long)(uintptr_t)&ionRef->ionShareFd) >> H_OFFSET);
558 param->value.b_addr = (unsigned int)(uintptr_t)&ionRef->ionSize;
559 param->value.b_h_addr = (unsigned int)(((unsigned long long)(uintptr_t)&ionRef->ionSize) >> H_OFFSET);
560 }
561
TEEC_EncodeParam(TC_NS_ClientContext * cliContext,const TEEC_Operation * operation)562 static void TEEC_EncodeParam(TC_NS_ClientContext *cliContext, const TEEC_Operation *operation)
563 {
564 uint32_t paramType[TEEC_PARAM_NUM];
565 uint32_t paramCnt;
566 uint32_t diff;
567
568 diff = (uint32_t)TEEC_MEMREF_PARTIAL_INPUT - (uint32_t)TEEC_MEMREF_TEMP_INPUT;
569
570 for (paramCnt = 0; paramCnt < TEEC_PARAM_NUM; paramCnt++) {
571 paramType[paramCnt] = TEEC_PARAM_TYPE_GET(operation->paramTypes, paramCnt);
572 bool checkValue = (paramType[paramCnt] == TEEC_ION_INPUT || paramType[paramCnt] == TEEC_ION_SGLIST_INPUT);
573 if (IS_TEMP_MEM(paramType[paramCnt])) {
574 TEEC_EncodeTempParam(&operation->params[paramCnt].tmpref, &cliContext->params[paramCnt]);
575 } else if (IS_PARTIAL_MEM(paramType[paramCnt])) {
576 const TEEC_RegisteredMemoryReference *memref = &operation->params[paramCnt].memref;
577
578 TEEC_EncodePartialParam(paramType[paramCnt], memref, &cliContext->params[paramCnt]);
579
580 /* translate the paramType to know the driver */
581 if (paramType[paramCnt] == TEEC_MEMREF_WHOLE) {
582 paramType[paramCnt] = TranslateParamType(memref->parent->flags);
583 }
584
585 /* if is not allocated,
586 * translate TEEC_MEMREF_PARTIAL_XXX to TEEC_MEMREF_TEMP_XXX */
587 if (!memref->parent->is_allocated) {
588 paramType[paramCnt] = paramType[paramCnt] - diff;
589 }
590 } else if (IS_VALUE_MEM(paramType[paramCnt])) {
591 TEEC_EncodeValueParam(&operation->params[paramCnt].value, &cliContext->params[paramCnt]);
592 } else if (checkValue == true) {
593 TEEC_EncodeIonParam(&operation->params[paramCnt].ionref, &cliContext->params[paramCnt]);
594 }
595 }
596
597 cliContext->paramTypes = TEEC_PARAM_TYPES(paramType[0], paramType[1], paramType[2], paramType[3]);
598 tlogd("cli param type %x\n", cliContext->paramTypes);
599 return;
600 }
601
TEEC_Encode(TC_NS_ClientContext * cliContext,const TEEC_Session * session,uint32_t cmdId,const TC_NS_ClientLogin * cliLogin,const TEEC_Operation * operation)602 static TEEC_Result TEEC_Encode(TC_NS_ClientContext *cliContext, const TEEC_Session *session,
603 uint32_t cmdId, const TC_NS_ClientLogin *cliLogin, const TEEC_Operation *operation)
604 {
605 errno_t rc;
606
607 rc = memset_s(cliContext, sizeof(TC_NS_ClientContext), 0x00, sizeof(TC_NS_ClientContext));
608 if (rc != EOK) {
609 return (TEEC_Result)TEEC_ERROR_BAD_PARAMETERS;
610 }
611
612 cliContext->session_id = session->session_id;
613 cliContext->cmd_id = cmdId;
614 cliContext->returns.code = 0;
615 cliContext->returns.origin = TEEC_ORIGIN_API;
616
617 cliContext->login.method = cliLogin->method;
618 cliContext->login.mdata = cliLogin->mdata;
619
620 rc = memcpy_s(cliContext->uuid, sizeof(cliContext->uuid), (uint8_t *)(&session->service_id), sizeof(TEEC_UUID));
621 if (rc != EOK) {
622 return (TEEC_Result)TEEC_ERROR_BAD_PARAMETERS;
623 }
624
625 if ((operation == NULL) || (!operation->paramTypes)) {
626 return TEEC_SUCCESS;
627 }
628 cliContext->started = operation->cancel_flag;
629
630 TEEC_EncodeParam(cliContext, operation);
631
632 return TEEC_SUCCESS;
633 }
634
635 #ifdef LIB_TEEC_VENDOR
CaDaemonConnectWithoutCaInfo(void)636 static int CaDaemonConnectWithoutCaInfo(void)
637 {
638 int ret;
639 errno_t rc;
640 CaAuthInfo caInfo;
641
642 rc = memset_s(&caInfo, sizeof(caInfo), 0, sizeof(caInfo));
643 if (rc != EOK) {
644 return -1;
645 }
646
647 ret = CaDaemonConnectWithCaInfo(&caInfo, GET_FD);
648 return ret;
649 }
650 #else
ObtainTzdriveFd(void)651 static int32_t ObtainTzdriveFd(void)
652 {
653 int32_t fd = open(TC_NS_CLIENT_DEV_NAME, O_RDWR);
654 if (fd < 0) {
655 tloge("open tzdriver fd failed\n");
656 return -1;
657 }
658 return fd;
659 }
660
SetLoginInfo(const CaAuthInfo * caInfo,int32_t fd)661 static int32_t SetLoginInfo(const CaAuthInfo *caInfo, int32_t fd)
662 {
663 int32_t ret;
664 int32_t rc = 0;
665 uint32_t bufLen = BUF_MAX_SIZE;
666 uint8_t *buf = (uint8_t *)malloc(bufLen);
667 if (buf == NULL) {
668 tloge("malloc failed\n");
669 return -1;
670 }
671 ret = memset_s(buf, bufLen, 0, bufLen);
672 if (ret != EOK) {
673 tloge("memset buf failed\n");
674 goto END;
675 }
676
677 switch (caInfo->type) {
678 case SYSTEM_CA:
679 tlogd("system ca type\n");
680 rc = TeeGetNativeCert(caInfo->pid, caInfo->uid, &bufLen, buf);
681 break;
682 case SA_CA:
683 tlogd("sa ca type\n");
684 rc = TEEGetNativeSACaInfo(caInfo, buf, bufLen);
685 break;
686 case APP_CA:
687 tlogd("hap ca type\n");
688 if (memcpy_s(buf, bufLen, caInfo->certs, sizeof(caInfo->certs)) != EOK) {
689 tloge("memcpy hap cainfo failed\n");
690 rc = -1;
691 }
692 break;
693 default:
694 tloge("invaild ca type %d\n", caInfo->type);
695 rc = -1;
696 break;
697 }
698
699 if (rc != 0) {
700 /* Inform the driver the cert could not be set */
701 ret = ioctl(fd, TC_NS_CLIENT_IOCTL_LOGIN, NULL);
702 } else {
703 ret = ioctl(fd, TC_NS_CLIENT_IOCTL_LOGIN, buf);
704 }
705
706 if (ret != 0) {
707 tloge("Failed to set login information for client err = %d, %d\n", ret, caInfo->type);
708 } else {
709 ret = rc;
710 }
711
712 END:
713 free(buf);
714 buf = NULL;
715 return ret;
716 }
717 #endif
718
TEEC_InitializeContextInner(TEEC_ContextInner * context,const CaAuthInfo * caInfo)719 TEEC_Result TEEC_InitializeContextInner(TEEC_ContextInner *context, const CaAuthInfo *caInfo)
720 {
721 if (context == NULL) {
722 tloge("Initial context: context is NULL\n");
723 return TEEC_ERROR_BAD_PARAMETERS;
724 }
725 #ifdef LIB_TEEC_VENDOR
726 int32_t fd = CaDaemonConnectWithoutCaInfo();
727 if (fd < 0) {
728 tloge("connect() failed, fd %d", fd);
729 return TEEC_ERROR_GENERIC;
730 }
731 #else
732 if (caInfo == NULL) {
733 return TEEC_ERROR_BAD_PARAMETERS;
734 }
735
736 int32_t fd = ObtainTzdriveFd();
737 if (fd < 0) {
738 tloge("obtain fd failed\n");
739 return TEEC_ERROR_BAD_PARAMETERS;
740 }
741
742 if (SetLoginInfo(caInfo, fd) != TEEC_SUCCESS) {
743 tloge("set login failed\n");
744 close(fd);
745 return TEEC_ERROR_GENERIC;
746 }
747 #endif
748 context->fd = (uint32_t)fd;
749 context->ops_cnt = 1;
750
751 ListInit(&context->session_list);
752 ListInit(&context->shrd_mem_list);
753
754 errno_t nRet = memset_s(context->shm_bitmap, sizeof(context->shm_bitmap), 0x00, sizeof(context->shm_bitmap));
755 if (nRet != EOK) {
756 tloge("Initial context: context->shm_bitmap memset failed : %d\n", (int)nRet);
757 close((int)context->fd);
758 return TEEC_FAIL;
759 }
760
761 int retMutexLock = MutexLockContext();
762 if (retMutexLock != 0) {
763 tloge("get context lock failed.\n");
764 close((int)context->fd);
765 return TEEC_FAIL;
766 }
767 (void)pthread_mutex_init(&context->sessionLock, NULL);
768 (void)pthread_mutex_init(&context->shrMemLock, NULL);
769 (void)pthread_mutex_init(&context->shrMemBitMapLock, NULL);
770 ListInsertTail(&g_teecContextList, &context->c_node);
771 AtomInc(&context->ops_cnt);
772 MutexUnlockContext(retMutexLock);
773
774 return TEEC_SUCCESS;
775 }
776
777 /*
778 * Function: TEEC_InitializeContext
779 * Description: This function initializes a new TEE Context, forming a connection between
780 * this Client Application and the TEE identified by the string identifier name.
781 * Parameters: name: a zero-terminated string that describes the TEE to connect to.
782 * If this parameter is set to NULL, the Implementation MUST select a default TEE.
783 * context: a TEEC_Context structure that be initialized by the Implementation.
784 * Return: TEEC_SUCCESS: the initialization was successful.
785 * other: initialization was not successful.
786 */
TEEC_InitializeContext(const char * name,TEEC_Context * context)787 TEEC_Result TEEC_InitializeContext(const char *name, TEEC_Context *context)
788 {
789 TEEC_Result ret;
790 errno_t nRet;
791 uint32_t conCxt = 0;
792 struct ListNode *ptr = NULL;
793
794 (void)name;
795
796 if (context == NULL) {
797 tloge("initialize context: context is NULL\n");
798 return TEEC_ERROR_BAD_PARAMETERS;
799 }
800
801 if (!LIST_EMPTY(&g_teecContextList)) {
802 LIST_FOR_EACH(ptr, &g_teecContextList) {
803 conCxt++;
804 }
805 }
806
807 if (conCxt >= MAX_CXTCNT_ONECA) {
808 tloge("the contexts is already full, please finalize some of them\n");
809 return TEEC_FAIL;
810 }
811
812 TEEC_ContextInner *contextInner = (TEEC_ContextInner *)malloc(sizeof(*contextInner));
813 if (contextInner == NULL) {
814 tloge("initialize context: Failed to malloc teec contextInner\n");
815 return TEEC_ERROR_GENERIC;
816 }
817 nRet = memset_s(contextInner, sizeof(*contextInner), 0, sizeof(*contextInner));
818 if (nRet != EOK) {
819 tloge("initialize context: contextInner memset failed : %d\n", (int)nRet);
820 free(contextInner);
821 return TEEC_FAIL;
822 }
823
824 ret = TEEC_InitializeContextInner(contextInner, NULL);
825 if (ret == TEEC_SUCCESS) {
826 context->fd = contextInner->fd;
827 context->ta_path = NULL;
828
829 ListInit(&context->session_list);
830 ListInit(&context->shrd_mem_list);
831 (void)PutBnContext(contextInner); /* pair with ops_cnt++ when add to list */
832 return TEEC_SUCCESS;
833 }
834
835 tloge("initialize context: failed:0x%x\n", ret);
836 free(contextInner);
837 return ret;
838 }
839
840 /*
841 * Function: TEEC_FinalizeContext
842 * Description: This function finalizes an initialized TEE Context.
843 * Parameters: context: an initialized TEEC_Context structure which is to be finalized.
844 * Return: NULL
845 */
TEEC_FinalizeContextInner(TEEC_ContextInner * context)846 void TEEC_FinalizeContextInner(TEEC_ContextInner *context)
847 {
848 struct ListNode *ptr = NULL;
849 struct ListNode *n = NULL;
850 TEEC_Session *session = NULL;
851 TEEC_SharedMemoryInner *shrdMem = NULL;
852
853 /* First, check parameters is valid or not */
854 if (context == NULL) {
855 tloge("finalize context: context is NULL\n");
856 return;
857 }
858
859 int lockRet = pthread_mutex_lock(&context->sessionLock);
860 if (lockRet != 0) {
861 tloge("get session lock failed.\n");
862 return;
863 }
864 if (!LIST_EMPTY(&context->session_list)) {
865 tlogd("context still has sessions opened, close it\n");
866
867 LIST_FOR_EACH_SAFE(ptr, n, &context->session_list)
868 {
869 session = CONTAINER_OF(ptr, TEEC_Session, head);
870 ListRemoveEntry(&session->head);
871 TEEC_CloseSessionInner(session, context);
872 /* for service */
873 if (context->callFromService) {
874 PutBnSession(session); /* pair with open session */
875 session = NULL;
876 }
877 }
878 }
879 (void)pthread_mutex_unlock(&context->sessionLock);
880
881 lockRet = pthread_mutex_lock(&context->shrMemLock);
882 if (lockRet != 0) {
883 tloge("get shrmem lock failed.\n");
884 return;
885 }
886
887 if (!LIST_EMPTY(&context->shrd_mem_list)) {
888 tlogd("context contains unreleased Shared Memory blocks, release it\n");
889
890 LIST_FOR_EACH_SAFE(ptr, n, &context->shrd_mem_list)
891 {
892 shrdMem = CONTAINER_OF(ptr, TEEC_SharedMemoryInner, head);
893 ListRemoveEntry(&shrdMem->head);
894 PutBnShrMem(shrdMem); /* pair with Initial value 1 */
895 }
896 }
897 (void)pthread_mutex_unlock(&context->shrMemLock);
898
899 close((int)context->fd);
900 context->fd = -1;
901 (void)pthread_mutex_destroy(&context->sessionLock);
902 (void)pthread_mutex_destroy(&context->shrMemLock);
903 free(context);
904 }
905
TEEC_FinalizeContext(TEEC_Context * context)906 void TEEC_FinalizeContext(TEEC_Context *context)
907 {
908 if (context == NULL) {
909 tloge("finalize context: context is NULL\n");
910 return;
911 }
912
913 TEEC_ContextInner *contextInner = FindAndRemoveBnContext(context);
914 (void)PutBnContext(contextInner); /* pair with initialize context */
915 context->fd = -1;
916 }
917
TEEC_DoOpenSession(int fd,TC_NS_ClientContext * cliContext,const TEEC_UUID * destination,TEEC_ContextInner * context,TEEC_Session * session)918 static TEEC_Result TEEC_DoOpenSession(int fd, TC_NS_ClientContext *cliContext, const TEEC_UUID *destination,
919 TEEC_ContextInner *context, TEEC_Session *session)
920 {
921 int32_t ret;
922 TEEC_Result teecRet;
923 int i = CA_AUTH_RETRY_TIMES;
924 do {
925 cliContext->returns.code = 0;
926 cliContext->returns.origin = TEEC_ORIGIN_API;
927 ret = ioctl(fd, (int)TC_NS_CLIENT_IOCTL_SES_OPEN_REQ, cliContext);
928 } while (((TEEC_Result)cliContext->returns.code == TEE_ERROR_CA_AUTH_FAIL) && i--);
929
930 if (ret < 0) {
931 tloge("open session failed, ioctl errno = %d\n", ret);
932 teecRet = TranslateRetValue(ret);
933 cliContext->returns.origin = TEEC_ORIGIN_COMMS;
934 return teecRet;
935 } else if (ret > 0) {
936 tloge("open session failed(%d), code=0x%x, origin=%u\n", ret, cliContext->returns.code,
937 cliContext->returns.origin);
938 if (cliContext->returns.code) {
939 teecRet = (TEEC_Result)cliContext->returns.code;
940 } else {
941 teecRet = (TEEC_Result)TEEC_ERROR_GENERIC;
942 }
943 return teecRet;
944 }
945
946 return AddSessionList(cliContext->session_id, destination, context, session);
947 }
948
TEEC_OpenSessionInner(int callingPid,const TaFileInfo * taFile,TEEC_ContextInner * context,TEEC_Session * session,const TEEC_UUID * destination,uint32_t connectionMethod,const void * connectionData,TEEC_Operation * operation,uint32_t * returnOrigin)949 TEEC_Result TEEC_OpenSessionInner(int callingPid, const TaFileInfo *taFile, TEEC_ContextInner *context,
950 TEEC_Session *session, const TEEC_UUID *destination, uint32_t connectionMethod,
951 const void *connectionData, TEEC_Operation *operation, uint32_t *returnOrigin)
952 {
953 TEEC_Result teecRet = (TEEC_Result)TEEC_ERROR_BAD_PARAMETERS;
954 TC_NS_ClientContext cliContext;
955 TC_NS_ClientLogin cliLogin = { 0, 0 };
956
957 /* prefirst, we set origin be zero */
958 cliContext.returns.origin = TEEC_ORIGIN_API;
959 cliContext.file_buffer = NULL;
960
961 bool condition = (context == NULL) || (taFile == NULL) || (session == NULL) || (destination == NULL);
962 if (condition) {
963 tloge("context or session or destination is NULL\n");
964 goto ERROR;
965 }
966 /* now only support TEEC_LOGIN_IDENTIFY */
967 condition = (connectionMethod != TEEC_LOGIN_IDENTIFY) || (connectionData != NULL);
968 if (condition) {
969 tloge("Login method is not supported or connection data is not null\n");
970 goto ERROR;
971 }
972
973 cliLogin.method = connectionMethod;
974
975 if (operation != NULL) {
976 /* Params 2 and 3 are used for ident by teecd hence ->TEEC_NONE */
977 operation->paramTypes = TEEC_PARAM_TYPES(TEEC_PARAM_TYPE_GET(operation->paramTypes, 0),
978 TEEC_PARAM_TYPE_GET(operation->paramTypes, 1), TEEC_NONE, TEEC_NONE);
979 }
980 teecRet = TEEC_CheckOperation(context, operation);
981 if (teecRet != TEEC_SUCCESS) {
982 tloge("operation is invalid\n");
983 goto ERROR;
984 }
985
986 /* Paramters right, start execution */
987 /*
988 * note:before open session success, we should send session=0 as initial state.
989 */
990 teecRet = TEEC_Encode(&cliContext, session, GLOBAL_CMD_ID_OPEN_SESSION, &cliLogin, operation);
991 if (teecRet != TEEC_SUCCESS) {
992 tloge("OpenSession: teec encode failed(0x%x)!\n", teecRet);
993 goto ERROR;
994 }
995
996 cliContext.callingPid = (unsigned int)callingPid;
997
998 int32_t ret = TEEC_GetApp(taFile, destination, &cliContext);
999 if (ret < 0) {
1000 tloge("get app error\n");
1001 teecRet = (TEEC_Result)TEEC_ERROR_TRUSTED_APP_LOAD_ERROR;
1002 goto ERROR;
1003 }
1004
1005 teecRet = TEEC_DoOpenSession(context->fd, &cliContext, destination, context, session);
1006
1007 ERROR:
1008 /* ONLY when ioctl returnCode!=0 and returnOrigin not NULL,
1009 * set *returnOrigin
1010 */
1011 if (returnOrigin != NULL) {
1012 *returnOrigin = cliContext.returns.origin;
1013 }
1014
1015 if (cliContext.file_buffer != NULL) {
1016 free(cliContext.file_buffer);
1017 }
1018 return teecRet;
1019 }
1020
1021 /*
1022 * Function: TEEC_OpenSession
1023 * Description: This function opens a new Session
1024 * Parameters: context: a pointer to an initialized TEE Context.
1025 * session: a pointer to a Session structure to open.
1026 * destination: a pointer to a UUID structure.
1027 * connectionMethod: the method of connection to use.
1028 * connectionData: any necessary data required to support the connection method chosen.
1029 * operation: a pointer to an Operation containing a set of Parameters.
1030 * returnOrigin: a pointer to a variable which will contain the return origin.
1031 * Return: TEEC_SUCCESS: success
1032 * other: failure
1033 */
TEEC_OpenSession(TEEC_Context * context,TEEC_Session * session,const TEEC_UUID * destination,uint32_t connectionMethod,const void * connectionData,TEEC_Operation * operation,uint32_t * returnOrigin)1034 TEEC_Result TEEC_OpenSession(TEEC_Context *context, TEEC_Session *session, const TEEC_UUID *destination,
1035 uint32_t connectionMethod, const void *connectionData, TEEC_Operation *operation,
1036 uint32_t *returnOrigin)
1037 {
1038 TEEC_Result ret = TEEC_ERROR_BAD_PARAMETERS;
1039 uint32_t retOrigin = TEEC_ORIGIN_API;
1040
1041 if ((context == NULL) || (session == NULL) || (destination == NULL)) {
1042 tloge("param is null!\n");
1043 goto END;
1044 }
1045
1046 /*
1047 * ca may call closesession even if opensession failed,
1048 * we set session->context here to avoid receive a illegal ptr
1049 */
1050 session->context = context;
1051 session->service_id = *destination;
1052 session->session_id = 0;
1053
1054 TaFileInfo taFile;
1055 taFile.taFp = NULL;
1056 taFile.taPath = context->ta_path;
1057
1058 TEEC_ContextInner *contextInner = GetBnContext(context);
1059 if (contextInner == NULL) {
1060 tloge("no context found!\n");
1061 goto END;
1062 }
1063
1064 ret = TEEC_OpenSessionInner(0, &taFile, contextInner, session, destination,
1065 connectionMethod, connectionData, operation, &retOrigin);
1066 (void)PutBnContext(contextInner);
1067
1068 END:
1069 if (returnOrigin != NULL) {
1070 *returnOrigin = retOrigin;
1071 }
1072 return ret;
1073 }
1074
TEEC_CloseSessionInner(TEEC_Session * session,const TEEC_ContextInner * context)1075 void TEEC_CloseSessionInner(TEEC_Session *session, const TEEC_ContextInner *context)
1076 {
1077 int32_t ret;
1078 TC_NS_ClientContext cliContext;
1079 TC_NS_ClientLogin cliLogin = { 0, 0 };
1080 TEEC_Result teecRet;
1081
1082 /* First, check parameters is valid or not */
1083 if ((session == NULL) || (context == NULL)) {
1084 tloge("close session: session or context is NULL\n");
1085 return;
1086 }
1087
1088 teecRet = TEEC_Encode(&cliContext, session, GLOBAL_CMD_ID_CLOSE_SESSION, &cliLogin, NULL);
1089 if (teecRet != TEEC_SUCCESS) {
1090 tloge("close session: teec encode failed(0x%x)!\n", teecRet);
1091 return;
1092 }
1093
1094 ret = ioctl((int)context->fd, (int)TC_NS_CLIENT_IOCTL_SES_CLOSE_REQ, &cliContext);
1095 if (ret != 0) {
1096 tloge("close session failed, ret=0x%x\n", ret);
1097 }
1098 session->session_id = 0;
1099 session->context = NULL;
1100 errno_t rc =
1101 memset_s((uint8_t *)&session->service_id, sizeof(session->service_id), 0x00, sizeof(session->service_id));
1102 if (rc != EOK) {
1103 tloge("memset service id fail\n");
1104 }
1105 return;
1106 }
1107
1108 /*
1109 * Function: TEEC_CloseSession
1110 * Description: This function closes an opened Session.
1111 * Parameters: session: the session to close.
1112 * Return: NULL
1113 */
TEEC_CloseSession(TEEC_Session * session)1114 void TEEC_CloseSession(TEEC_Session *session)
1115 {
1116 if ((session == NULL) || (session->context == NULL)) {
1117 tloge("close session: session or session->context is NULL\n");
1118 return;
1119 }
1120
1121 TEEC_ContextInner *contextInner = GetBnContext(session->context);
1122 if (contextInner == NULL) {
1123 tloge("context is NULL\n");
1124 return;
1125 }
1126 TEEC_Session *sessionInList = FindAndRemoveSession(session, contextInner);
1127 if (sessionInList == NULL) {
1128 tloge("session is not in the context list\n");
1129 (void)PutBnContext(contextInner);
1130 return;
1131 }
1132
1133 TEEC_CloseSessionInner(session, contextInner);
1134 (void)PutBnContext(contextInner);
1135 }
1136
ProcessInvokeCommand(const TEEC_ContextInner * context,TC_NS_ClientContext * cliContext)1137 static TEEC_Result ProcessInvokeCommand(const TEEC_ContextInner *context, TC_NS_ClientContext *cliContext)
1138 {
1139 TEEC_Result teecRet;
1140
1141 int32_t ret = ioctl((int)context->fd, (int)TC_NS_CLIENT_IOCTL_SEND_CMD_REQ, cliContext);
1142 if (ret == 0) {
1143 tlogd("invoke cmd success\n");
1144 teecRet = TEEC_SUCCESS;
1145 } else if (ret < 0) {
1146 teecRet = TranslateRetValue(-errno);
1147 tloge("invoke cmd failed, ioctl errno = %d\n", errno);
1148 cliContext->returns.origin = TEEC_ORIGIN_COMMS;
1149 } else {
1150 tloge("invoke cmd failed(%d), code=0x%x, origin=%u\n", ret,
1151 cliContext->returns.code, cliContext->returns.origin);
1152 if (cliContext->returns.code) {
1153 teecRet = (TEEC_Result)cliContext->returns.code;
1154 } else {
1155 teecRet = (TEEC_Result)TEEC_ERROR_GENERIC;
1156 }
1157 }
1158
1159 return teecRet;
1160 }
1161
TEEC_InvokeCommandInner(TEEC_ContextInner * context,const TEEC_Session * session,uint32_t commandID,const TEEC_Operation * operation,uint32_t * returnOrigin)1162 TEEC_Result TEEC_InvokeCommandInner(TEEC_ContextInner *context, const TEEC_Session *session,
1163 uint32_t commandID, const TEEC_Operation *operation, uint32_t *returnOrigin)
1164 {
1165 TEEC_Result teecRet = (TEEC_Result)TEEC_ERROR_BAD_PARAMETERS;
1166 TC_NS_ClientContext cliContext;
1167 TC_NS_ClientLogin cliLogin = { 0, 0 };
1168 /* prefirst, we set origin be zero */
1169 cliContext.returns.origin = TEEC_ORIGIN_API;
1170 /* First, check parameters is valid or not */
1171 if ((session == NULL) || (context == NULL)) {
1172 goto ERROR;
1173 }
1174 teecRet = TEEC_CheckOperation(context, operation);
1175 if (teecRet != TEEC_SUCCESS) {
1176 tloge("operation is invalid\n");
1177 goto ERROR;
1178 }
1179
1180 /* Paramters all right, start execution */
1181 teecRet = TEEC_Encode(&cliContext, session, commandID, &cliLogin, operation);
1182 if (teecRet != TEEC_SUCCESS) {
1183 tloge("InvokeCommand: teec encode failed(0x%x)!\n", teecRet);
1184 goto ERROR;
1185 }
1186
1187 teecRet = ProcessInvokeCommand(context, &cliContext);
1188 if (teecRet != TEEC_SUCCESS) {
1189 tloge("InvokeCommand failed\n");
1190 }
1191
1192 ERROR:
1193 /* ONLY when ioctl returnCode!=0 and returnOrigin not NULL,
1194 * set *returnOrigin
1195 */
1196 if (returnOrigin != NULL) {
1197 *returnOrigin = cliContext.returns.origin;
1198 }
1199 return teecRet;
1200 }
1201
1202 /*
1203 * Function: TEEC_InvokeCommand
1204 * Description: This function invokes a Command within the specified Session.
1205 * Parameters: session: the open Session in which the command will be invoked.
1206 * commandID: the identifier of the Command.
1207 * operation: a pointer to an Operation containing a set of Parameters.
1208 * returnOrigin: a pointer to a variable which will contain the return origin.
1209 * Return: TEEC_SUCCESS: success
1210 * other: failure
1211 */
TEEC_InvokeCommand(TEEC_Session * session,uint32_t commandID,TEEC_Operation * operation,uint32_t * returnOrigin)1212 TEEC_Result TEEC_InvokeCommand(TEEC_Session *session, uint32_t commandID, TEEC_Operation *operation,
1213 uint32_t *returnOrigin)
1214 {
1215 TEEC_Result ret = TEEC_ERROR_BAD_PARAMETERS;
1216 uint32_t retOrigin = TEEC_ORIGIN_API;
1217
1218 if ((session == NULL) || (session->context == NULL)) {
1219 tloge("invoke failed, session or session context is null\n");
1220 goto END;
1221 }
1222 TEEC_Context *contextTemp = session->context;
1223 TEEC_ContextInner *contextInner = GetBnContext(session->context);
1224
1225 ret = TEEC_InvokeCommandInner(contextInner, session, commandID, operation, &retOrigin);
1226 if (ret == TEEC_SUCCESS) {
1227 session->context = contextTemp;
1228 }
1229 (void)PutBnContext(contextInner);
1230
1231 END:
1232 if (returnOrigin != NULL) {
1233 *returnOrigin = retOrigin;
1234 }
1235 return ret;
1236 }
1237
TEEC_RegisterSharedMemoryInner(TEEC_ContextInner * context,TEEC_SharedMemoryInner * sharedMem)1238 TEEC_Result TEEC_RegisterSharedMemoryInner(TEEC_ContextInner *context, TEEC_SharedMemoryInner *sharedMem)
1239 {
1240 /* First, check parameters is valid or not */
1241 if ((context == NULL) || (sharedMem == NULL)) {
1242 tloge("register shardmem: context or sharedMem is NULL\n");
1243 return (TEEC_Result)TEEC_ERROR_BAD_PARAMETERS;
1244 }
1245
1246 bool condition =
1247 (sharedMem->buffer == NULL) || ((sharedMem->flags != TEEC_MEM_INPUT) && (sharedMem->flags != TEEC_MEM_OUTPUT) &&
1248 (sharedMem->flags != TEEC_MEM_INOUT));
1249 if (condition) {
1250 tloge("register shardmem: sharedMem->flags wrong\n");
1251 return (TEEC_Result)TEEC_ERROR_BAD_PARAMETERS;
1252 }
1253
1254 /* Paramters all right, start execution */
1255 sharedMem->ops_cnt = 1;
1256 sharedMem->is_allocated = false;
1257 sharedMem->offset = (uint32_t)(-1);
1258 sharedMem->context = context;
1259 ListInit(&sharedMem->head);
1260 int lockRet = pthread_mutex_lock(&context->shrMemLock);
1261 if (lockRet != 0) {
1262 tloge("get share mem lock failed.\n");
1263 return TEEC_ERROR_GENERIC;
1264 }
1265 ListInsertTail(&context->shrd_mem_list, &sharedMem->head);
1266 AtomInc(&sharedMem->ops_cnt);
1267 (void)pthread_mutex_unlock(&context->shrMemLock);
1268
1269 return TEEC_SUCCESS;
1270 }
1271
1272 /*
1273 * Function: TEEC_RegisterSharedMemory
1274 * Description: This function registers a block of existing Client Application memory
1275 * as a block of Shared Memory within the scope of the specified TEE Context.
1276 * Parameters: context: a pointer to an initialized TEE Context.
1277 * sharedMem: a pointer to a Shared Memory structure to register.
1278 * Return: TEEC_SUCCESS: success
1279 * other: failure
1280 */
TEEC_RegisterSharedMemory(TEEC_Context * context,TEEC_SharedMemory * sharedMem)1281 TEEC_Result TEEC_RegisterSharedMemory(TEEC_Context *context, TEEC_SharedMemory *sharedMem)
1282 {
1283 TEEC_Result ret;
1284 TEEC_ContextInner *contextInner = NULL;
1285 TEEC_SharedMemoryInner *shmInner = NULL;
1286
1287 bool condition = (context == NULL) || (sharedMem == NULL);
1288 if (condition) {
1289 tloge("register shardmem: context or sharedMem is NULL\n");
1290 return (TEEC_Result)TEEC_ERROR_BAD_PARAMETERS;
1291 }
1292
1293 /*
1294 * ca may call ReleaseShareMemory even if RegisterShareMem failed,
1295 * we set sharedMem->context here to avoid receive a illegal ptr
1296 */
1297 sharedMem->context = context;
1298
1299 ret = MallocShrMemInner(&shmInner);
1300 if (ret != TEEC_SUCCESS) {
1301 return ret;
1302 }
1303 shmInner->buffer = sharedMem->buffer;
1304 shmInner->size = sharedMem->size;
1305 shmInner->flags = sharedMem->flags;
1306
1307 contextInner = GetBnContext(context);
1308 ret = TEEC_RegisterSharedMemoryInner(contextInner, shmInner);
1309 if (ret == TEEC_SUCCESS) {
1310 sharedMem->ops_cnt = shmInner->ops_cnt;
1311 sharedMem->is_allocated = shmInner->is_allocated;
1312 ListInit(&sharedMem->head);
1313 PutBnShrMem(shmInner); /* pair with ops_cnt++ when add to list */
1314 (void)PutBnContext(contextInner);
1315 return ret;
1316 }
1317 tloge("register shardmem: failed:0x%x\n", ret);
1318 (void)PutBnContext(contextInner);
1319 free(shmInner);
1320 return ret;
1321 }
1322
RelaseBufferAndClearBit(TEEC_ContextInner * context,TEEC_SharedMemoryInner * sharedMem)1323 static void RelaseBufferAndClearBit(TEEC_ContextInner *context, TEEC_SharedMemoryInner *sharedMem)
1324 {
1325 if (sharedMem->buffer != MAP_FAILED && sharedMem->size != 0) {
1326 (void)munmap(sharedMem->buffer, sharedMem->size);
1327 }
1328 ClearBitWithLock(&context->shrMemBitMapLock, sharedMem->offset,
1329 sizeof(context->shm_bitmap), context->shm_bitmap);
1330 sharedMem->buffer = NULL;
1331 sharedMem->offset = 0;
1332 }
1333
TEEC_AllocateSharedMemoryInner(TEEC_ContextInner * context,TEEC_SharedMemoryInner * sharedMem)1334 TEEC_Result TEEC_AllocateSharedMemoryInner(TEEC_ContextInner *context, TEEC_SharedMemoryInner *sharedMem)
1335 {
1336 TEEC_Result ret;
1337
1338 /* First, check parameters is valid or not */
1339 if ((context == NULL) || (sharedMem == NULL)) {
1340 tloge("allocate shardmem: context or sharedMem is NULL\n");
1341 return (TEEC_Result)TEEC_ERROR_BAD_PARAMETERS;
1342 }
1343
1344 bool condition = (sharedMem->flags != TEEC_MEM_INPUT) && (sharedMem->flags != TEEC_MEM_OUTPUT) &&
1345 (sharedMem->flags != TEEC_MEM_INOUT);
1346 if (condition) {
1347 tloge("allocate shardmem: sharedMem->flags wrong\n");
1348 return (TEEC_Result)TEEC_ERROR_BAD_PARAMETERS;
1349 }
1350
1351 /* Paramters all right, start execution */
1352 sharedMem->buffer = NULL;
1353
1354 int32_t validBit = GetAndSetBitWithLock(&context->shrMemBitMapLock, context->shm_bitmap,
1355 sizeof(context->shm_bitmap));
1356 if (validBit < 0) {
1357 tloge("get valid bit for shm failed\n");
1358 return (TEEC_Result)TEEC_ERROR_BAD_PARAMETERS;
1359 }
1360
1361 sharedMem->offset = (uint32_t)validBit;
1362 if (sharedMem->size != 0) {
1363 sharedMem->buffer = mmap(0, (unsigned long)sharedMem->size, (PROT_READ | PROT_WRITE), MAP_SHARED,
1364 (int)context->fd, (long)(sharedMem->offset * PAGE_SIZE));
1365 } else {
1366 sharedMem->buffer = ZERO_SIZE_PTR;
1367 }
1368
1369 if (sharedMem->buffer == MAP_FAILED) {
1370 tloge("mmap failed\n");
1371 ret = TEEC_ERROR_OUT_OF_MEMORY;
1372 goto ERROR;
1373 }
1374 sharedMem->ops_cnt = 1;
1375 sharedMem->is_allocated = true;
1376 sharedMem->context = context;
1377 ListInit(&sharedMem->head);
1378 if (pthread_mutex_lock(&context->shrMemLock) != 0) {
1379 tloge("get share mem lock failed\n");
1380 ret = TEEC_ERROR_GENERIC;
1381 goto ERROR;
1382 }
1383 ListInsertTail(&context->shrd_mem_list, &sharedMem->head);
1384 AtomInc(&sharedMem->ops_cnt);
1385 (void)pthread_mutex_unlock(&context->shrMemLock);
1386 return TEEC_SUCCESS;
1387
1388 ERROR:
1389 RelaseBufferAndClearBit(context, sharedMem);
1390 return ret;
1391 }
1392
1393 /*
1394 * Function: TEEC_AllocateSharedMemory
1395 * Description: This function allocates a new block of memory as a block of
1396 * Shared Memory within the scope of the specified TEE Context.
1397 * Parameters: context: a pointer to an initialized TEE Context.
1398 * sharedMem: a pointer to a Shared Memory structure to allocate.
1399 * Return: TEEC_SUCCESS: success
1400 * other: failure
1401 */
TEEC_AllocateSharedMemory(TEEC_Context * context,TEEC_SharedMemory * sharedMem)1402 TEEC_Result TEEC_AllocateSharedMemory(TEEC_Context *context, TEEC_SharedMemory *sharedMem)
1403 {
1404 TEEC_Result ret;
1405 TEEC_ContextInner *contextInner = NULL;
1406 TEEC_SharedMemoryInner *shmInner = NULL;
1407
1408 bool condition = (context == NULL) || (sharedMem == NULL);
1409 if (condition) {
1410 tloge("allocate shardmem: context or sharedMem is NULL\n");
1411 return (TEEC_Result)TEEC_ERROR_BAD_PARAMETERS;
1412 }
1413
1414 /*
1415 * ca may call ReleaseShareMemory even if AllocateSharedMemory failed,
1416 * we set sharedMem->context here to avoid receive a illegal ptr
1417 */
1418 sharedMem->context = context;
1419
1420 ret = MallocShrMemInner(&shmInner);
1421 if (ret != TEEC_SUCCESS) {
1422 return ret;
1423 }
1424 shmInner->size = sharedMem->size;
1425 shmInner->flags = sharedMem->flags;
1426
1427 contextInner = GetBnContext(context);
1428 ret = TEEC_AllocateSharedMemoryInner(contextInner, shmInner);
1429 if (ret == TEEC_SUCCESS) {
1430 sharedMem->buffer = shmInner->buffer;
1431 sharedMem->ops_cnt = shmInner->ops_cnt;
1432 sharedMem->is_allocated = shmInner->is_allocated;
1433 ListInit(&sharedMem->head);
1434 PutBnShrMem(shmInner); /* pair with ops_cnt++ when add to list */
1435 (void)PutBnContext(contextInner);
1436 return TEEC_SUCCESS;
1437 }
1438
1439 tloge("allocate shardmem: failed:0x%x\n", ret);
1440 (void)PutBnContext(contextInner);
1441 free(shmInner);
1442 return ret;
1443 }
1444
TEEC_FindAndRemoveShrMemInner(TEEC_SharedMemoryInner ** sharedMem,TEEC_ContextInner * contextInner)1445 static bool TEEC_FindAndRemoveShrMemInner(TEEC_SharedMemoryInner **sharedMem, TEEC_ContextInner *contextInner)
1446 {
1447 bool found = false;
1448 struct ListNode *ptr = NULL;
1449 TEEC_SharedMemoryInner *tempSharedMem = NULL;
1450 TEEC_SharedMemoryInner *shm = *sharedMem;
1451
1452 int lockRet = pthread_mutex_lock(&contextInner->shrMemLock);
1453 if (lockRet != 0) {
1454 tloge("get share mem lock failed.\n");
1455 return false;
1456 }
1457
1458 LIST_FOR_EACH(ptr, &contextInner->shrd_mem_list)
1459 {
1460 tempSharedMem = CONTAINER_OF(ptr, TEEC_SharedMemoryInner, head);
1461 if (tempSharedMem->offset == shm->offset && tempSharedMem->context == shm->context) {
1462 found = true;
1463 ListRemoveEntry(&tempSharedMem->head);
1464 *sharedMem = tempSharedMem;
1465 break;
1466 }
1467 }
1468
1469 (void)pthread_mutex_unlock(&contextInner->shrMemLock);
1470 return found;
1471 }
1472
TEEC_ReleaseSharedMemoryInner(TEEC_SharedMemoryInner * sharedMem)1473 void TEEC_ReleaseSharedMemoryInner(TEEC_SharedMemoryInner *sharedMem)
1474 {
1475 TEEC_SharedMemoryInner *shm = sharedMem;
1476
1477 /* First, check parameters is valid or not */
1478 if ((shm == NULL) || (shm->context == NULL)) {
1479 tloge("Shared Memory is NULL\n");
1480 return;
1481 }
1482
1483 bool found = TEEC_FindAndRemoveShrMemInner(&shm, shm->context);
1484 if (!found) {
1485 tloge("Shared Memory is not in the list\n");
1486 return;
1487 }
1488
1489 tloge("Shared Memory found\n");
1490
1491 PutBnShrMem(shm); /* pair with Initial value 1 */
1492 }
1493
1494 /*
1495 * Function: TEEC_ReleaseSharedMemory
1496 * Description: This function deregisters or deallocates a previously initialized
1497 * block of Shared Memory..
1498 * Parameters: sharedMem: a pointer to a valid Shared Memory structure.
1499 * Return: NULL
1500 */
TEEC_ReleaseSharedMemory(TEEC_SharedMemory * sharedMem)1501 void TEEC_ReleaseSharedMemory(TEEC_SharedMemory *sharedMem)
1502 {
1503 if ((sharedMem == NULL) || (sharedMem->context == NULL)) {
1504 tloge("release shardmem: sharedMem or sharedMem->context is NULL\n");
1505 return;
1506 }
1507
1508 TEEC_SharedMemoryInner shmInner = { 0 };
1509 shmInner.buffer = sharedMem->buffer;
1510 shmInner.size = sharedMem->size;
1511 shmInner.flags = sharedMem->flags;
1512 shmInner.ops_cnt = sharedMem->ops_cnt;
1513 shmInner.is_allocated = sharedMem->is_allocated;
1514
1515 TEEC_ContextInner *contextInner = GetBnContext(sharedMem->context);
1516 shmInner.context = contextInner;
1517
1518 TEEC_ReleaseSharedMemoryInner(&shmInner);
1519 (void)PutBnContext(contextInner);
1520 sharedMem->buffer = NULL;
1521 sharedMem->size = 0;
1522 sharedMem->flags = 0;
1523 sharedMem->ops_cnt = 0;
1524 sharedMem->context = NULL;
1525 }
1526
TEEC_CheckTmpRef(TEEC_TempMemoryReference tmpref)1527 static TEEC_Result TEEC_CheckTmpRef(TEEC_TempMemoryReference tmpref)
1528 {
1529 if ((tmpref.buffer == NULL) || (tmpref.size == 0)) {
1530 tloge("tmpref buffer is null, or size is zero\n");
1531 return (TEEC_Result)TEEC_ERROR_BAD_PARAMETERS;
1532 }
1533 return (TEEC_Result)TEEC_SUCCESS;
1534 }
1535
CheckSharedBufferExist(TEEC_ContextInner * context,const TEEC_RegisteredMemoryReference * sharedMem)1536 static bool CheckSharedBufferExist(TEEC_ContextInner *context, const TEEC_RegisteredMemoryReference *sharedMem)
1537 {
1538 if (context == NULL) {
1539 return false;
1540 }
1541
1542 struct ListNode *ptr = NULL;
1543 TEEC_SharedMemoryInner *tempSharedMem = NULL;
1544 TEEC_SharedMemory *shm = sharedMem->parent;
1545
1546 int lockRet = pthread_mutex_lock(&context->shrMemLock);
1547 if (lockRet != 0) {
1548 tloge("get share mem lock failed\n");
1549 return false;
1550 }
1551
1552 LIST_FOR_EACH(ptr, &context->shrd_mem_list)
1553 {
1554 tempSharedMem = CONTAINER_OF(ptr, TEEC_SharedMemoryInner, head);
1555 if (tempSharedMem->buffer == shm->buffer) {
1556 (void)pthread_mutex_unlock(&context->shrMemLock);
1557 return true;
1558 }
1559 }
1560
1561 (void)pthread_mutex_unlock(&context->shrMemLock);
1562 return false;
1563 }
1564
TEEC_CheckMemRef(TEEC_ContextInner * context,TEEC_RegisteredMemoryReference memref,uint32_t paramType)1565 static TEEC_Result TEEC_CheckMemRef(TEEC_ContextInner *context, TEEC_RegisteredMemoryReference memref,
1566 uint32_t paramType)
1567 {
1568 bool condition = (memref.parent == NULL) || (memref.parent->buffer == NULL);
1569 if (condition) {
1570 tloge("parent of memref is null, or the buffer is zero\n");
1571 return (TEEC_Result)TEEC_ERROR_BAD_PARAMETERS;
1572 }
1573
1574 if (paramType == TEEC_MEMREF_PARTIAL_INPUT) {
1575 if (!(memref.parent->flags & TEEC_MEM_INPUT)) {
1576 goto PARAM_ERROR;
1577 }
1578 } else if (paramType == TEEC_MEMREF_PARTIAL_OUTPUT) {
1579 if (!(memref.parent->flags & TEEC_MEM_OUTPUT)) {
1580 goto PARAM_ERROR;
1581 }
1582 } else if (paramType == TEEC_MEMREF_PARTIAL_INOUT) {
1583 if (!(memref.parent->flags & TEEC_MEM_INPUT)) {
1584 goto PARAM_ERROR;
1585 }
1586 if (!(memref.parent->flags & TEEC_MEM_OUTPUT)) {
1587 goto PARAM_ERROR;
1588 }
1589 } else {
1590 /* if type is TEEC_MEMREF_WHOLE, ignore it */
1591 }
1592
1593 condition = (paramType == TEEC_MEMREF_PARTIAL_INPUT) || (paramType == TEEC_MEMREF_PARTIAL_OUTPUT) ||
1594 (paramType == TEEC_MEMREF_PARTIAL_INOUT);
1595 if (condition) {
1596 if ((memref.offset + memref.size) > memref.parent->size) {
1597 tloge("offset + size exceed the parent size\n");
1598 return (TEEC_Result)TEEC_ERROR_BAD_PARAMETERS;
1599 }
1600 }
1601
1602 if (memref.parent->is_allocated) {
1603 if (!CheckSharedBufferExist(context, &memref)) {
1604 return (TEEC_Result)TEEC_ERROR_BAD_PARAMETERS;
1605 }
1606 }
1607
1608 return (TEEC_Result)TEEC_SUCCESS;
1609 PARAM_ERROR:
1610 tloge("type of memref not belong to the parent flags\n");
1611 return (TEEC_Result)TEEC_ERROR_BAD_PARAMETERS;
1612 }
1613
1614 /*
1615 * Function: TEEC_CheckOperation
1616 * Description: This function checks an operation is valid or not.
1617 * Parameters: operation: a pointer to an Operation to be checked.
1618 * Return: TEEC_SUCCESS: success
1619 * other: failure
1620 */
TEEC_CheckOperation(TEEC_ContextInner * context,const TEEC_Operation * operation)1621 TEEC_Result TEEC_CheckOperation(TEEC_ContextInner *context, const TEEC_Operation *operation)
1622 {
1623 uint32_t paramType[TEEC_PARAM_NUM];
1624 uint32_t paramCnt;
1625 TEEC_Result ret = TEEC_SUCCESS;
1626 /* GP Support operation is NULL
1627 * operation: a pointer to a Client Application initialized TEEC_Operation structure,
1628 * or NULL if there is no payload to send or if the Command does not need to support
1629 * cancellation.
1630 */
1631 if (operation == NULL) {
1632 return ret;
1633 }
1634 if (!operation->started) {
1635 tloge("sorry, cancellation not support\n");
1636 return (TEEC_Result)TEEC_ERROR_NOT_IMPLEMENTED;
1637 }
1638
1639 for (paramCnt = 0; paramCnt < TEEC_PARAM_NUM; paramCnt++) {
1640 paramType[paramCnt] = TEEC_PARAM_TYPE_GET(operation->paramTypes, paramCnt);
1641 bool checkValue = (paramType[paramCnt] == TEEC_ION_INPUT || paramType[paramCnt] == TEEC_ION_SGLIST_INPUT);
1642 if (IS_TEMP_MEM(paramType[paramCnt])) {
1643 ret = TEEC_CheckTmpRef(operation->params[paramCnt].tmpref);
1644 } else if (IS_PARTIAL_MEM(paramType[paramCnt])) {
1645 ret = TEEC_CheckMemRef(context, operation->params[paramCnt].memref, paramType[paramCnt]);
1646 } else if (IS_VALUE_MEM(paramType[paramCnt])) {
1647 /* if type is value, ignore it */
1648 } else if (checkValue == true) {
1649 if (operation->params[paramCnt].ionref.ionShareFd < 0 ||
1650 operation->params[paramCnt].ionref.ionSize == 0) {
1651 tloge("check failed: ion_share_fd and ion_size\n");
1652 ret = (TEEC_Result)TEEC_ERROR_BAD_PARAMETERS;
1653 break;
1654 }
1655 } else if (paramType[paramCnt] == TEEC_NONE) {
1656 /* if type is none, ignore it */
1657 } else {
1658 tloge("paramType is not support\n");
1659 ret = (TEEC_Result)TEEC_ERROR_BAD_PARAMETERS;
1660 break;
1661 }
1662
1663 if (ret != TEEC_SUCCESS) {
1664 tloge("paramCnt is %u\n", paramCnt);
1665 break;
1666 }
1667 }
1668 return ret;
1669 }
1670
1671 /*
1672 * Function: TEEC_RequestCancellation
1673 * Description: This function requests the cancellation of a pending open Session operation or
1674 a Command invocation operation.
1675 * Parameters: operation:a pointer to a Client Application instantiated Operation structure
1676 * Return: void
1677 */
TEEC_RequestCancellation(TEEC_Operation * operation)1678 void TEEC_RequestCancellation(TEEC_Operation *operation)
1679 {
1680 int32_t ret;
1681 TEEC_Result teecRet;
1682 TC_NS_ClientContext cliContext;
1683 TC_NS_ClientLogin cliLogin = { 0, 0 };
1684
1685 /* First, check parameters is valid or not */
1686 if (operation == NULL) {
1687 return;
1688 }
1689
1690 TEEC_Session *session = operation->session;
1691 if ((session == NULL) || (session->context == NULL)) {
1692 tloge("session is invalid\n");
1693 return;
1694 }
1695 TEEC_ContextInner *contextInner = GetBnContext(session->context);
1696 teecRet = TEEC_CheckOperation(contextInner, operation);
1697 (void)PutBnContext(contextInner);
1698 if (teecRet != TEEC_SUCCESS) {
1699 tloge("operation is invalid\n");
1700 return;
1701 }
1702
1703 /* Paramters all right, start execution */
1704 teecRet = TEEC_Encode(&cliContext, session, TC_NS_CLIENT_IOCTL_CANCEL_CMD_REQ, &cliLogin, operation);
1705 if (teecRet != TEEC_SUCCESS) {
1706 tloge("RequestCancellation: teec encode failed(0x%x)!\n", teecRet);
1707 return;
1708 }
1709
1710 ret = ioctl((int)session->context->fd, (int)TC_NS_CLIENT_IOCTL_CANCEL_CMD_REQ, &cliContext);
1711 if (ret == 0) {
1712 tlogd("invoke cmd success\n");
1713 } else if (ret < 0) {
1714 tloge("invoke cmd failed, ioctl errno = %d\n", ret);
1715 } else {
1716 tloge("invoke cmd failed, code=0x%x, origin=%u\n", cliContext.returns.code, cliContext.returns.origin);
1717 }
1718
1719 return;
1720 }
1721
1722 #ifdef LIB_TEEC_VENDOR
TEEC_EXT_RegisterAgent(uint32_t agentId,int * devFd,void ** buffer)1723 TEEC_Result TEEC_EXT_RegisterAgent(uint32_t agentId, int *devFd, void **buffer)
1724 {
1725 int ret;
1726 struct AgentIoctlArgs args = { 0 };
1727
1728 if ((devFd == NULL) || (buffer == NULL)) {
1729 tloge("Failed to open tee client dev!\n");
1730 return (TEEC_Result)TEEC_ERROR_GENERIC;
1731 }
1732
1733 int fd = CaDaemonConnectWithoutCaInfo();
1734 if (fd < 0) {
1735 tloge("Failed to open tee client dev!\n");
1736 return (TEEC_Result)TEEC_ERROR_GENERIC;
1737 }
1738
1739 args.id = agentId;
1740 args.bufferSize = AGENT_BUFF_SIZE;
1741 ret = ioctl(fd, TC_NS_CLIENT_IOCTL_REGISTER_AGENT, &args);
1742 if (ret != 0) {
1743 (void)close(fd);
1744 tloge("ioctl failed, failed to register agent!\n");
1745 return (TEEC_Result)TEEC_ERROR_GENERIC;
1746 }
1747
1748 *devFd = fd;
1749 *buffer = args.buffer;
1750 return TEEC_SUCCESS;
1751 }
1752
TEEC_EXT_WaitEvent(uint32_t agentId,int devFd)1753 TEEC_Result TEEC_EXT_WaitEvent(uint32_t agentId, int devFd)
1754 {
1755 int ret;
1756
1757 ret = ioctl(devFd, TC_NS_CLIENT_IOCTL_WAIT_EVENT, agentId);
1758 if (ret != 0) {
1759 tloge("Agent 0x%x wait failed, errno=%d\n", agentId, ret);
1760 return TEEC_ERROR_GENERIC;
1761 }
1762
1763 return TEEC_SUCCESS;
1764 }
1765
TEEC_EXT_SendEventResponse(uint32_t agentId,int devFd)1766 TEEC_Result TEEC_EXT_SendEventResponse(uint32_t agentId, int devFd)
1767 {
1768 int ret;
1769 ret = ioctl(devFd, TC_NS_CLIENT_IOCTL_SEND_EVENT_RESPONSE, agentId);
1770 if (ret != 0) {
1771 tloge("Agent %u failed to send response, ret is %d!\n", agentId, ret);
1772 return (TEEC_Result)TEEC_ERROR_GENERIC;
1773 }
1774
1775 return TEEC_SUCCESS;
1776 }
1777
TEEC_EXT_UnregisterAgent(uint32_t agentId,int devFd,void ** buffer)1778 TEEC_Result TEEC_EXT_UnregisterAgent(uint32_t agentId, int devFd, void **buffer)
1779 {
1780 int ret;
1781 TEEC_Result result = TEEC_SUCCESS;
1782
1783 if (buffer == NULL || *buffer == NULL) {
1784 tloge("buffer is invalid!\n");
1785 return TEEC_ERROR_BAD_PARAMETERS;
1786 }
1787 if (devFd < 0) {
1788 tloge("fd is invalid!\n");
1789 return TEEC_ERROR_BAD_PARAMETERS;
1790 }
1791 ret = ioctl(devFd, TC_NS_CLIENT_IOCTL_UNREGISTER_AGENT, agentId);
1792 if (ret != 0) {
1793 tloge("Failed to unregister agent %u, ret is %d\n", agentId, ret);
1794 result = TEEC_ERROR_GENERIC;
1795 }
1796
1797 (void)close(devFd);
1798 *buffer = NULL;
1799 return result;
1800 }
1801
TEEC_SendSecfile(const char * path,TEEC_Session * session)1802 TEEC_Result TEEC_SendSecfile(const char *path, TEEC_Session *session)
1803 {
1804 TEEC_Result ret = (TEEC_Result)TEEC_SUCCESS;
1805 TEEC_ContextInner *contextInner = NULL;
1806
1807 if (path == NULL || session == NULL || session->context == NULL) {
1808 tloge("params error!\n");
1809 return TEEC_ERROR_BAD_PARAMETERS;
1810 }
1811 contextInner = GetBnContext(session->context);
1812 if (contextInner == NULL) {
1813 tloge("find context failed!\n");
1814 return TEEC_ERROR_BAD_PARAMETERS;
1815 }
1816
1817 ret = TEEC_SendSecfileInner(path, contextInner->fd, NULL);
1818 (void)PutBnContext(contextInner);
1819 return ret;
1820 }
1821 #endif
1822
TEEC_SendSecfileInner(const char * path,int tzFd,FILE * fp)1823 TEEC_Result TEEC_SendSecfileInner(const char *path, int tzFd, FILE *fp)
1824 {
1825 int32_t ret;
1826 TEEC_Result teecRet = (TEEC_Result)TEEC_SUCCESS;
1827
1828 if (path == NULL) {
1829 return TEEC_ERROR_BAD_PARAMETERS;
1830 }
1831 ret = TEEC_LoadSecfile(path, tzFd, fp);
1832 if (ret < 0) {
1833 tloge("Send secfile error\n");
1834 teecRet = (TEEC_Result)TEEC_ERROR_TRUSTED_APP_LOAD_ERROR;
1835 }
1836 return teecRet;
1837 }
1838