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