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