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