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