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