• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 Huawei Technologies Co., Ltd.
3  * Licensed under the Mulan PSL v2.
4  * You can use this software according to the terms and conditions of the Mulan PSL v2.
5  * You may obtain a copy of Mulan PSL v2 at:
6  *     http://license.coscl.org.cn/MulanPSL2
7  * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
8  * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
9  * PURPOSE.
10  * See the Mulan PSL v2 for more details.
11  */
12 
13 #include "tee_client.h"
14 #include <fcntl.h>
15 #include <securec.h>
16 #include <sys/mman.h>
17 #include <unistd.h>
18 #include "ashmem.h"
19 #include "if_system_ability_manager.h"
20 #include "ipc_skeleton.h"
21 #include "ipc_types.h"
22 #include "iremote_proxy.h"
23 #include "iremote_stub.h"
24 #include "iservice_registry.h"
25 #include "system_ability_definition.h"
26 #include "tee_client_api.h"
27 #include "tee_client_ext_api.h"
28 #include "tee_client_inner.h"
29 #include "tee_log.h"
30 using namespace std;
31 namespace OHOS {
32 bool TeeClient::mServiceValid = false;
33 
SetCallBack()34 bool TeeClient::SetCallBack()
35 {
36     MessageParcel data;
37     MessageParcel reply;
38     MessageOption option;
39 
40     if (mNotify == nullptr || mTeecService == nullptr) {
41         tloge("get call back handle failed\n");
42         return false;
43     }
44 
45     (void)data.WriteInterfaceToken(INTERFACE_TOKEN);
46     bool result = data.WriteRemoteObject(mNotify);
47     if (!result) {
48         tloge("write notify failed\n");
49         return false;
50     }
51 
52     int ret = mTeecService->SendRequest(SET_CALL_BACK, data, reply, option);
53     if (ret != ERR_NONE) {
54         tloge("send notify failed\n");
55         return false;
56     }
57 
58     return true;
59 }
60 
InitTeecService()61 bool TeeClient::InitTeecService()
62 {
63     lock_guard<mutex> autoLock(mServiceLock);
64 
65     if (mServiceValid) {
66         return true;
67     }
68 
69     if (mNotify == nullptr) {
70         mNotify = new IPCObjectStub(u"TeecClientDeathRecipient");
71         if (mNotify == nullptr) {
72             tloge("new mNotify failed\n");
73             return false;
74         }
75     }
76 
77     sptr<ISystemAbilityManager> sm = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
78     if (sm == nullptr) {
79         tloge("get system ability failed\n");
80         return false;
81     }
82 
83     mTeecService = sm->GetSystemAbility(CA_DAEMON_ID);
84     if (mTeecService == nullptr) {
85         tloge("get teec service failed\n");
86         return false;
87     }
88 
89     mDeathNotifier = new DeathNotifier(mTeecService);
90     if (mDeathNotifier == nullptr) {
91         tloge("new death notify failed\n");
92         mTeecService = nullptr;
93         return false;
94     }
95 
96     /* death notify, TeecService-->CA */
97     bool result = mTeecService->AddDeathRecipient(mDeathNotifier);
98     if (!result) {
99         tloge("set service to ca failed\n");
100         mTeecService = nullptr;
101         return false;
102     }
103 
104     /* death notify, CA-->TeecService */
105     result = SetCallBack();
106     if (!result) {
107         tloge("set ca to service failed\n");
108         mTeecService = nullptr;
109         return false;
110     }
111 
112     mServiceValid = true;
113     return true;
114 }
115 
TEEC_CheckTmpRef(TEEC_TempMemoryReference tmpref)116 static TEEC_Result TEEC_CheckTmpRef(TEEC_TempMemoryReference tmpref)
117 {
118     if ((tmpref.buffer == nullptr) && (tmpref.size != 0)) {
119         tloge("tmpref buffer is null, but size is not zero\n");
120         return (TEEC_Result)TEEC_ERROR_BAD_PARAMETERS;
121     }
122     if ((tmpref.buffer != nullptr) && (tmpref.size == 0)) {
123         tloge("tmpref buffer is not null, but size is zero\n");
124         return (TEEC_Result)TEEC_ERROR_BAD_PARAMETERS;
125     }
126     return (TEEC_Result)TEEC_SUCCESS;
127 }
128 
TEEC_CheckMemRef(TEEC_RegisteredMemoryReference memref,uint32_t paramType)129 static TEEC_Result TEEC_CheckMemRef(TEEC_RegisteredMemoryReference memref, uint32_t paramType)
130 {
131     if ((memref.parent == nullptr) || (memref.parent->buffer == nullptr)) {
132         tloge("parent of memref is null, or the buffer is zero\n");
133         return TEEC_ERROR_BAD_PARAMETERS;
134     }
135 
136     if (paramType == TEEC_MEMREF_PARTIAL_INPUT) {
137         if (!(memref.parent->flags & TEEC_MEM_INPUT)) {
138             goto PARAM_ERROR;
139         }
140     } else if (paramType == TEEC_MEMREF_PARTIAL_OUTPUT) {
141         if (!(memref.parent->flags & TEEC_MEM_OUTPUT)) {
142             goto PARAM_ERROR;
143         }
144     } else if (paramType == TEEC_MEMREF_PARTIAL_INOUT) {
145         if (!(memref.parent->flags & TEEC_MEM_INPUT)) {
146             goto PARAM_ERROR;
147         }
148         if (!(memref.parent->flags & TEEC_MEM_OUTPUT)) {
149             goto PARAM_ERROR;
150         }
151     } else {
152         /*  if type is TEEC_MEMREF_WHOLE, ignore it */
153     }
154 
155     if ((paramType == TEEC_MEMREF_PARTIAL_INPUT) ||
156         (paramType == TEEC_MEMREF_PARTIAL_OUTPUT) ||
157         (paramType == TEEC_MEMREF_PARTIAL_INOUT)) {
158         if ((UINT32_MAX - memref.offset < memref.size) ||
159             ((memref.offset + memref.size) > memref.parent->size)) {
160             tloge("partial mem check failed, offset %" PUBLIC "u size %" PUBLIC "u\n", memref.offset, memref.size);
161             return TEEC_ERROR_BAD_PARAMETERS;
162         }
163     }
164 
165     return TEEC_SUCCESS;
166 PARAM_ERROR:
167     tloge("type of memref not belong to the parent flags\n");
168     return TEEC_ERROR_BAD_PARAMETERS;
169 }
170 
TEEC_CheckOperation(const TEEC_Operation * operation)171 TEEC_Result TeeClient::TEEC_CheckOperation(const TEEC_Operation *operation)
172 {
173     TEEC_Result ret = TEEC_SUCCESS;
174 
175     if (operation == nullptr) {
176         return ret;
177     }
178     if (!operation->started) {
179         tloge("sorry, cancellation not support\n");
180         return TEEC_ERROR_NOT_IMPLEMENTED;
181     }
182 
183     for (uint32_t i = 0; i < TEEC_PARAM_NUM; i++) {
184         uint32_t paramType = TEEC_PARAM_TYPE_GET(operation->paramTypes, i);
185         if (IS_TEMP_MEM(paramType)) {
186             ret = TEEC_CheckTmpRef(operation->params[i].tmpref);
187         } else if (IS_PARTIAL_MEM(paramType)) {
188             ret = TEEC_CheckMemRef(operation->params[i].memref, paramType);
189         } else if (IS_VALUE_MEM(paramType)) {
190             /*  if type is value, ignore it */
191         } else if (paramType == TEEC_NONE) {
192             /*  if type is none, ignore it */
193         } else if (paramType == TEEC_ION_INPUT) {
194           /* Secure Camera */
195         } else {
196             tloge("param %" PUBLIC "u has invalid type %" PUBLIC "u\n", i, paramType);
197             ret = TEEC_ERROR_BAD_PARAMETERS;
198             break;
199         }
200 
201         if (ret != TEEC_SUCCESS) {
202             tloge("param %" PUBLIC "u check failed\n", i);
203             break;
204         }
205     }
206     return ret;
207 }
208 
IsOverFlow(uint32_t num1,uint32_t num2)209 static inline bool IsOverFlow(uint32_t num1, uint32_t num2)
210 {
211     if (UINT32_MAX - num1 < num2) {
212         return true;
213     }
214     return false;
215 }
216 
WriteChar(const char * srcStr,MessageParcel & data)217 static bool WriteChar(const char *srcStr, MessageParcel &data)
218 {
219     if (srcStr == nullptr) {
220         if (data.WriteUint32(0) != true) {
221             return false;
222         }
223     } else {
224         if (strnlen(srcStr, PATH_MAX) == PATH_MAX) {
225             tloge("param srcStr is too long\n");
226             return false;
227         }
228         string tempStr = srcStr;
229         if (data.WriteUint32(strlen(srcStr)) != true) {
230             return false;
231         }
232         if (data.WriteString(tempStr) != true) {
233             return false;
234         }
235     }
236     return true;
237 }
238 
WriteContext(MessageParcel & data,TEEC_Context * context)239 static bool WriteContext(MessageParcel &data, TEEC_Context *context)
240 {
241     return data.WriteBuffer(context, sizeof(*context));
242 }
243 
WriteSession(MessageParcel & data,TEEC_Session * session)244 static bool WriteSession(MessageParcel &data, TEEC_Session *session)
245 {
246     return data.WriteBuffer(session, sizeof(*session));
247 }
248 
WriteSharedMem(MessageParcel & data,TEEC_SharedMemory * shm)249 static bool WriteSharedMem(MessageParcel &data, TEEC_SharedMemory *shm)
250 {
251     return data.WriteBuffer(shm, sizeof(*shm));
252 }
253 
CheckSharedMemoryFLag(uint32_t flag)254 static bool CheckSharedMemoryFLag(uint32_t flag)
255 {
256     return (flag == TEEC_MEM_INPUT || flag == TEEC_MEM_OUTPUT || flag == TEEC_MEM_INOUT);
257 }
258 
FindShareMemOffset(const void * buffer)259 uint32_t TeeClient::FindShareMemOffset(const void *buffer)
260 {
261     lock_guard<mutex> autoLock(mSharMemLock);
262     size_t count = mShareMem.size();
263     for (size_t index = 0; index < count; index++) {
264         if (mShareMem[index].buffer == buffer) {
265             return mShareMem[index].offset;
266         }
267     }
268 
269     return UINT32_MAX;
270 }
271 
UnmapSharedMem(void * buff,uint32_t size)272 static void UnmapSharedMem(void *buff, uint32_t size)
273 {
274     int ret = munmap(buff, size);
275     if (ret != 0) {
276         tloge("munmap share mem failed, ret=0x%" PUBLIC "x\n", ret);
277     }
278 }
279 
FreeAllShareMem()280 void TeeClient::FreeAllShareMem()
281 {
282     size_t index;
283 
284     lock_guard<mutex> autoLock(mSharMemLock);
285     size_t count = mShareMem.size();
286     for (index = 0; index < count; index++) {
287         if ((mShareMem[index].buffer != nullptr) && (mShareMem[index].buffer != ZERO_SIZE_PTR) &&
288             (mShareMem[index].size != 0)) {
289             UnmapSharedMem(mShareMem[index].buffer, mShareMem[index].size);
290         }
291     }
292     mShareMem.clear();
293     return;
294 }
295 
FreeAllShareMemoryInContext(const TEEC_Context * context)296 void TeeClient::FreeAllShareMemoryInContext(const TEEC_Context *context)
297 {
298     std::vector<TC_NS_ShareMem>::iterator vec;
299 
300     lock_guard<mutex> autoLock(mSharMemLock);
301     for (vec = mShareMem.begin(); vec != mShareMem.end();) {
302         if ((vec->fd == context->fd) && (vec->buffer != nullptr) && (vec->buffer != ZERO_SIZE_PTR) &&
303             (vec->size != 0)) {
304             UnmapSharedMem(vec->buffer, vec->size);
305             vec = mShareMem.erase(vec);
306         } else {
307             ++vec;
308         }
309     }
310     return;
311 }
312 
SleepNs(long num)313 static void SleepNs(long num)
314 {
315     struct timespec ts;
316     ts.tv_sec  = 0;
317     ts.tv_nsec = num;
318 
319     (void)nanosleep(&ts, nullptr);
320 }
321 
322 #define SLEEP_TIME (200 * 1000 * 1000)
323 #define CONNECT_MAX_NUM 10
324 
InitializeContextSendCmd(const char * name,MessageParcel & reply)325 TEEC_Result TeeClient::InitializeContextSendCmd(const char *name, MessageParcel &reply)
326 {
327     MessageParcel data;
328     MessageOption option;
329     uint32_t connectTime = 0;
330     /* add retry to avoid app start before daemon */
331     while (connectTime++ < CONNECT_MAX_NUM) {
332         if (InitTeecService()) {
333             break;
334         }
335         tlogd("get cadaemon handle retry\n");
336         SleepNs(SLEEP_TIME);
337     }
338     if (connectTime > CONNECT_MAX_NUM) {
339         tloge("get cadaemon handle failed\n");
340         return TEEC_FAIL;
341     }
342 
343     (void)data.WriteInterfaceToken(INTERFACE_TOKEN);
344 
345     if (WriteChar(name, data) != true) {
346         return TEEC_FAIL;
347     }
348 
349     if (mTeecService->SendRequest(INIT_CONTEXT, data, reply, option) != ERR_NONE)
350         return TEEC_FAIL;
351 
352     return TEEC_SUCCESS;
353 }
354 
InitializeContext(const char * name,TEEC_Context * context)355 TEEC_Result TeeClient::InitializeContext(const char *name, TEEC_Context *context)
356 {
357     if (context == nullptr) {
358         tloge("context is nullptr\n");
359         return TEEC_ERROR_BAD_PARAMETERS;
360     }
361 
362     MessageParcel reply;
363     int32_t ret = InitializeContextSendCmd(name, reply);
364     if ((TEEC_Result)ret != TEEC_SUCCESS) {
365         tloge("initialize context send cmd failed\n");
366         return TEEC_FAIL;
367     }
368 
369     if (!reply.ReadInt32(ret)) {
370         return TEEC_FAIL;
371     }
372 
373     if ((TEEC_Result)ret != TEEC_SUCCESS) {
374         tloge("init context failed:0x%" PUBLIC "x\n", ret);
375         return (TEEC_Result)ret;
376     }
377 
378     context->ta_path = nullptr;
379     if (!reply.ReadInt32(context->fd)) {
380         return TEEC_FAIL;
381     }
382 
383     if (context->fd < 0) {
384         return TEEC_FAIL;
385     }
386     return TEEC_SUCCESS;
387 }
388 
FinalizeContext(TEEC_Context * context)389 void TeeClient::FinalizeContext(TEEC_Context *context)
390 {
391     MessageParcel data;
392     MessageOption option;
393     MessageParcel reply;
394     bool parRet = false;
395 
396     if (context == nullptr) {
397         tloge("invalid context\n");
398         return;
399     }
400 
401     if (!InitTeecService()) {
402         return;
403     }
404 
405     (void)data.WriteInterfaceToken(INTERFACE_TOKEN);
406     parRet = WriteContext(data, context);
407     if (!parRet) {
408         return;
409     }
410 
411     if (mTeecService->SendRequest(FINAL_CONTEXT, data, reply, option) != ERR_NONE) {
412         tloge("close session failed\n");
413     }
414 
415     FreeAllShareMemoryInContext(context);
416     context->fd = -1;
417 }
418 
OpenSession(TEEC_Context * context,TEEC_Session * session,const TEEC_UUID * destination,uint32_t connectionMethod,const void * connectionData,TEEC_Operation * operation,uint32_t * returnOrigin)419 TEEC_Result TeeClient::OpenSession(TEEC_Context *context, TEEC_Session *session, const TEEC_UUID *destination,
420     uint32_t connectionMethod, const void *connectionData, TEEC_Operation *operation,
421     uint32_t *returnOrigin)
422 {
423     uint32_t retOrigin  = TEEC_ORIGIN_API;
424     TEEC_Result teecRet = TEEC_ERROR_BAD_PARAMETERS;
425     int fd              = -1;
426 
427     bool condition = (context == nullptr) || (session == nullptr) || (destination == nullptr);
428     if (condition) {
429         tloge("open Session: OpenSession in params error!\n");
430         goto END;
431     }
432 
433     /*
434      * ca may call closesession even if opensession failed,
435      * we set session->context here to avoid receive a illegal ptr
436      */
437     session->context = context;
438 
439     teecRet = TEEC_CheckOperation(operation);
440     if (teecRet != TEEC_SUCCESS) {
441         tloge("invoke command:check operation failed!\n");
442         goto END;
443     }
444 
445     condition = (connectionMethod != TEEC_LOGIN_IDENTIFY) || (connectionData != nullptr);
446     if (condition) {
447         tloge("Login method is not supported or connection data is not nullptr\n");
448         teecRet = TEEC_ERROR_BAD_PARAMETERS;
449         goto END;
450     }
451 
452     if (operation != nullptr) {
453         /* Params 2 and 3 are used for ident by teecd hence ->TEEC_NONE */
454         operation->paramTypes = TEEC_PARAM_TYPES(TEEC_PARAM_TYPE_GET(operation->paramTypes, 0),
455             TEEC_PARAM_TYPE_GET(operation->paramTypes, 1), TEEC_NONE, TEEC_NONE);
456     }
457 
458     fd = GetFileFd((const char *)context->ta_path);
459     teecRet = OpenSessionSendCmd(context, session, destination, connectionMethod, fd, operation, &retOrigin);
460 
461     if (fd >= 0) {
462         close(fd);
463     }
464 
465 END:
466     if (returnOrigin != nullptr) {
467         *returnOrigin = retOrigin;
468     }
469     return teecRet;
470 }
471 
WriteOpenData(MessageParcel & data,TEEC_Context * context,int32_t fd,const TEEC_UUID * destination,uint32_t connectionMethod)472 static bool WriteOpenData(MessageParcel &data, TEEC_Context *context, int32_t fd,
473     const TEEC_UUID *destination, uint32_t connectionMethod)
474 {
475     (void)data.WriteInterfaceToken(INTERFACE_TOKEN);
476 
477     if (!WriteContext(data, context)) {
478         return false;
479     }
480 
481     if (!WriteChar((const char *)context->ta_path, data)) {
482         return false;
483     }
484 
485     if (fd < 0) {
486         if (!data.WriteBool(false)) {
487             return false;
488         }
489     } else {
490         if (!data.WriteBool(true)) {
491             return false;
492         }
493         if (!data.WriteFileDescriptor(fd)) {
494             return false;
495         }
496     }
497 
498     if (!data.WriteBuffer(destination, sizeof(*destination))) {
499         return false;
500     }
501     if (!data.WriteUint32(connectionMethod)) {
502         return false;
503     }
504 
505     return true;
506 }
507 
WriteOperation(MessageParcel & data,TEEC_Operation * operation)508 static bool WriteOperation(MessageParcel &data, TEEC_Operation *operation)
509 {
510     if (operation == nullptr) {
511         return data.WriteBool(false);
512     }
513 
514     if (!data.WriteBool(true)) {
515         return false;
516     }
517 
518     return data.WriteBuffer(operation, sizeof(*operation));
519 }
520 
WriteIonFd(MessageParcel & data,TEEC_Operation * operation)521 static bool WriteIonFd(MessageParcel &data, TEEC_Operation *operation)
522 {
523     if (operation == nullptr) {
524         return true;
525     }
526 
527     uint32_t paramCnt;
528     bool teeRet = true;
529     for (paramCnt = 0; paramCnt < TEEC_PARAM_NUM; paramCnt++) {
530         if (TEEC_PARAM_TYPE_GET(operation->paramTypes, paramCnt) == TEEC_ION_INPUT) {
531             teeRet = data.WriteFileDescriptor(operation->params[paramCnt].ionref.ion_share_fd);
532         }
533         if (teeRet != true) {
534             tloge("write ion fd failed. paramCnt: %" PUBLIC "u\n", paramCnt);
535             return teeRet;
536         }
537     }
538     return teeRet;
539 }
540 
FormatSession(TEEC_Session * session,MessageParcel & reply)541 bool TeeClient::FormatSession(TEEC_Session *session, MessageParcel &reply)
542 {
543     bool sessFlag = false;
544     if (!reply.ReadBool(sessFlag)) {
545         return false;
546     }
547 
548     if (!sessFlag) {
549         tloge("session is nullptr\n");
550         return false;
551     }
552 
553     TEEC_Session *sessRet = nullptr;
554     size_t len = sizeof(*sessRet);
555     sessRet = (TEEC_Session *)(reply.ReadBuffer(len));
556     if (sessRet == nullptr) {
557         tloge("read session failed\n");
558         return false;
559     }
560     tlogi("reieve sessRet_id = %" PUBLIC "d\n", sessRet->session_id);
561 
562     session->session_id = sessRet->session_id;
563     session->service_id = sessRet->service_id;
564     session->ops_cnt    = sessRet->ops_cnt;
565     ListInit(&session->head);
566     return true;
567 }
568 
GetTeecOptMem(TEEC_Operation * operation,size_t optMemSize,sptr<Ashmem> & optMem,MessageParcel & reply)569 TEEC_Result TeeClient::GetTeecOptMem(TEEC_Operation *operation,
570     size_t optMemSize, sptr<Ashmem> &optMem, MessageParcel &reply)
571 {
572     if (operation == nullptr) {
573         return TEEC_SUCCESS;
574     }
575 
576     bool opFlag = false;
577     if (!reply.ReadBool(opFlag)) {
578         return TEEC_FAIL;
579     }
580 
581     if (!opFlag) {
582         tloge("operation is nullptr\n");
583         return TEEC_FAIL;
584     }
585 
586     TEEC_Operation *optRet = nullptr;
587     size_t len = sizeof(*optRet);
588     optRet = (TEEC_Operation *)(reply.ReadBuffer(len));
589     if (optRet == nullptr) {
590         tloge("the buffer is nullptr\n");
591         return TEEC_FAIL;
592     }
593 
594     const void *data = nullptr;
595     if (optMemSize != 0) {
596         data = optMem->ReadFromAshmem(optMemSize, 0);
597     }
598     return TeecOptDecode(operation, optRet, reinterpret_cast<const uint8_t *>(data), optMemSize);
599 }
600 
TeecOptDecodePartialMem(TEEC_Parameter * param,uint32_t paramType,TEEC_Parameter * inParam,const uint8_t ** data,size_t * dataSize)601 TEEC_Result TeeClient::TeecOptDecodePartialMem(TEEC_Parameter *param,
602     uint32_t paramType, TEEC_Parameter *inParam, const uint8_t **data, size_t *dataSize)
603 {
604     TEEC_SharedMemory *shm = param->memref.parent;
605     /* we put 4 uint32 and 1 bool in sharemem */
606     uint32_t shmSize       = 4 * (sizeof(uint32_t)) + 1 * (sizeof(bool));
607     uint32_t cSize         = param->memref.size;
608     uint32_t tSize         = inParam->memref.size; /* size return from ta */
609     uint8_t *p = nullptr;
610 
611     if (paramType == TEEC_MEMREF_WHOLE) {
612         cSize = shm->size;
613         /*
614          * Actually, we should usr tSize return from ta,
615          * but our process is temporarily not supported,
616          * so we usr cSize instead. There will be a problem,
617          * if ta write a larger buff size, we can not transfer it to ca
618          */
619         tSize = cSize;
620     }
621 
622     if (IsOverFlow(cSize, shmSize) || (*dataSize < (cSize + shmSize))) {
623         tloge("cSize:%" PUBLIC "u, shmSize:%" PUBLIC "u, dataSize:%" PUBLIC "zu\n", cSize, shmSize, *dataSize);
624         return TEEC_FAIL;
625     }
626 
627     *data += shmSize;
628     *dataSize -= shmSize;
629     if (paramType == TEEC_MEMREF_PARTIAL_INPUT) {
630         goto END;
631     }
632 
633     p = reinterpret_cast<uint8_t *>(param->memref.parent->buffer);
634     if (p == nullptr) {
635         goto COPY_TA_SIZE_TO_CA;
636     }
637     p += param->memref.offset;
638 
639     if (cSize == 0 && tSize == 0) {
640         tlogd("cSize=0 && inOpt->memref.size=0\n");
641         goto COPY_TA_SIZE_TO_CA;
642     }
643     if (!shm->is_allocated) {
644         /* if ta buff size > ca buff size, copy ta size to ca */
645         if (cSize < tSize) {
646             tloge("size from ca is:%" PUBLIC "u, size from ta is:%" PUBLIC "u\n", cSize, tSize);
647             goto COPY_TA_SIZE_TO_CA;
648         }
649 
650         if (memcpy_s(p, cSize, *data, tSize) != EOK) {
651             tloge("operation memcpy failed\n");
652             return TEEC_FAIL;
653         }
654     }
655 
656 COPY_TA_SIZE_TO_CA:
657     param->memref.size = inParam->memref.size;
658 
659 END:
660     *data += cSize;
661     *dataSize -= cSize;
662     return TEEC_SUCCESS;
663 }
664 
TeecOptDecode(TEEC_Operation * operation,TEEC_Operation * inOpt,const uint8_t * data,size_t dataSize)665 TEEC_Result TeeClient::TeecOptDecode(TEEC_Operation *operation,
666     TEEC_Operation *inOpt, const uint8_t *data, size_t dataSize)
667 {
668     uint32_t paramType[TEEC_PARAM_NUM] = { 0 };
669     uint32_t paramCnt;
670     const uint8_t *ptr = data;
671     size_t sizeLeft = dataSize;
672     TEEC_Result teeRet = TEEC_SUCCESS;
673 
674     for (paramCnt = 0; paramCnt < TEEC_PARAM_NUM; paramCnt++) {
675         paramType[paramCnt] = TEEC_PARAM_TYPE_GET(operation->paramTypes, paramCnt);
676         if (IS_TEMP_MEM(paramType[paramCnt])) {
677             if (ptr == nullptr) {
678                 continue;
679             }
680             teeRet = TeecOptDecodeTempMem(&(operation->params[paramCnt]), paramType[paramCnt],
681                 &(inOpt->params[paramCnt]), &ptr, &sizeLeft);
682         } else if (IS_PARTIAL_MEM(paramType[paramCnt])) {
683             if (ptr == nullptr) {
684                 return TEEC_ERROR_BAD_PARAMETERS;
685             }
686             teeRet = TeecOptDecodePartialMem(&(operation->params[paramCnt]), paramType[paramCnt],
687                 &(inOpt->params[paramCnt]), &ptr, &sizeLeft);
688         } else if (IS_VALUE_MEM(paramType[paramCnt])) {
689             operation->params[paramCnt].value.a = inOpt->params[paramCnt].value.a;
690             operation->params[paramCnt].value.b = inOpt->params[paramCnt].value.b;
691         }
692         if (teeRet != TEEC_SUCCESS) {
693             tloge("opt decode param fail. paramCnt: %" PUBLIC "u, ret: 0x%" PUBLIC "x\n", paramCnt, teeRet);
694             return teeRet;
695         }
696     }
697     return TEEC_SUCCESS;
698 }
699 
TeecOptDecodeTempMem(TEEC_Parameter * param,uint32_t paramType,const TEEC_Parameter * inParam,const uint8_t ** data,size_t * dataSize)700 TEEC_Result TeeClient::TeecOptDecodeTempMem(TEEC_Parameter *param, uint32_t paramType,
701     const TEEC_Parameter *inParam, const uint8_t **data, size_t *dataSize)
702 {
703     size_t sizeLeft = *dataSize;
704     const uint8_t *ptr    = *data;
705     uint8_t *p = nullptr;
706     if (sizeLeft < param->tmpref.size) {
707         tloge("size is error:%" PUBLIC "zu:%" PUBLIC "u\n", sizeLeft, param->tmpref.size);
708         return TEEC_FAIL;
709     }
710 
711     if (paramType == TEEC_MEMREF_TEMP_INPUT) {
712         ptr += param->tmpref.size;
713         sizeLeft -= param->tmpref.size;
714         goto END;
715     }
716 
717     p = reinterpret_cast<uint8_t *>(param->tmpref.buffer);
718     if (p != nullptr) {
719         /* if ta buff size > ca buff size, copy ta size to ca */
720         if (param->tmpref.size < inParam->tmpref.size) {
721             tlogw("size from ca is:%" PUBLIC "u, size from ta is:%" PUBLIC "u\n",
722                 param->tmpref.size, inParam->tmpref.size);
723             goto COPY_TA_SIZE_TO_CA;
724         }
725         if (sizeLeft < inParam->tmpref.size) {
726             tloge("size is not enough:%" PUBLIC "zu:%" PUBLIC "u\n", sizeLeft, inParam->tmpref.size);
727             return TEEC_FAIL;
728         }
729 
730         if (memcpy_s(p, param->tmpref.size, ptr, inParam->tmpref.size) != EOK) {
731             tloge("peration decode memcpy_s failed\n");
732             return TEEC_FAIL;
733         }
734     }
735 
736 COPY_TA_SIZE_TO_CA:
737     ptr += param->tmpref.size;
738     sizeLeft -= param->tmpref.size;
739     param->tmpref.size = inParam->tmpref.size;
740 
741 END:
742     *data     = ptr;
743     *dataSize = sizeLeft;
744     return TEEC_SUCCESS;
745 }
746 
ClearAsmMem(sptr<Ashmem> & optMem)747 static inline void ClearAsmMem(sptr<Ashmem> &optMem)
748 {
749     if (optMem != nullptr) {
750         optMem->UnmapAshmem();
751         optMem->CloseAshmem();
752     }
753 }
754 
OpenSessionSendCmd(TEEC_Context * context,TEEC_Session * session,const TEEC_UUID * destination,uint32_t connectionMethod,int32_t fd,TEEC_Operation * operation,uint32_t * retOrigin)755 TEEC_Result TeeClient::OpenSessionSendCmd(TEEC_Context *context, TEEC_Session *session, const TEEC_UUID *destination,
756     uint32_t connectionMethod, int32_t fd, TEEC_Operation *operation, uint32_t *retOrigin)
757 {
758     MessageParcel data, reply;
759     MessageOption option;
760     int32_t ret = (int32_t)TEEC_FAIL;
761 
762     CHECK_ERR_RETURN(InitTeecService(), true, TEEC_FAIL);
763 
764     size_t optMemSize;
765     sptr<Ashmem> optMem;
766     if (GetOptMemSize(operation, &optMemSize) != TEEC_SUCCESS) {
767         return TEEC_ERROR_BAD_PARAMETERS;
768     }
769 
770     TEEC_Result nRet = CopyTeecOptMem(operation, optMemSize, optMem);
771     if (nRet != TEEC_SUCCESS) {
772         tloge("copy teec opt mem failed\n");
773         return nRet;
774     }
775 
776     CHECK_ERR_GOTO(WriteOpenData(data, context, fd, destination, connectionMethod), true, END);
777 
778     if (WriteOperation(data, operation) != true) {
779         goto END;
780     }
781 
782     CHECK_ERR_GOTO(WriteIonFd(data, operation), true, END);
783 
784     if (data.WriteUint32(optMemSize) != true) {
785         goto END;
786     }
787 
788     if (optMemSize > 0) {
789         if (data.WriteAshmem(optMem) != true) {
790             goto END;
791         }
792     }
793 
794     if (mTeecService->SendRequest(OPEN_SESSION, data, reply, option) != ERR_NONE) {
795         goto END;
796     }
797 
798     if (reply.ReadUint32(*retOrigin) != true) {
799         goto END;
800     }
801 
802     if (reply.ReadInt32(ret) != true) {
803         ret = (int32_t)TEEC_FAIL;
804         goto END;
805     }
806 
807     if (!FormatSession(session, reply)) {
808         ret = (ret == (int32_t)TEEC_SUCCESS) ? (int32_t)TEEC_FAIL : ret;
809         goto END;
810     }
811 
812     nRet = GetTeecOptMem(operation, optMemSize, optMem, reply);
813     if (nRet != TEEC_SUCCESS && ret == (int32_t)TEEC_SUCCESS) {
814         ret = (int32_t)nRet;
815     }
816 
817 END:
818     ClearAsmMem(optMem);
819     return (TEEC_Result)ret;
820 }
821 
TeecOptEncodeTempMem(const TEEC_Parameter * param,sptr<Ashmem> & optMem,size_t * dataSize)822 TEEC_Result TeeClient::TeecOptEncodeTempMem(const TEEC_Parameter *param, sptr<Ashmem> &optMem, size_t *dataSize)
823 {
824     if (*dataSize < param->tmpref.size) {
825         tloge("size is error:%" PUBLIC "zu:%" PUBLIC "u\n", *dataSize, param->tmpref.size);
826         return TEEC_FAIL;
827     }
828 
829     uint8_t *p = reinterpret_cast<uint8_t *>(param->tmpref.buffer);
830     if (p == nullptr) {
831         return TEEC_SUCCESS;
832     }
833 
834     bool nRet = optMem->WriteToAshmem(p, (int32_t)(param->tmpref.size),
835         optMem->GetAshmemSize() - (int32_t)(*dataSize));
836     if (!nRet) {
837         tloge("temp mem to hal memcpy failed : %" PUBLIC "d\n", nRet);
838         return TEEC_FAIL;
839     }
840 
841     *dataSize -= param->tmpref.size;
842 
843     return TEEC_SUCCESS;
844 }
845 
CovertEncodePtr(sptr<Ashmem> & optMem,size_t * sizeLeft,TEEC_SharedMemory * shm)846 bool TeeClient::CovertEncodePtr(sptr<Ashmem> &optMem, size_t *sizeLeft, TEEC_SharedMemory *shm)
847 {
848     if (optMem->WriteToAshmem(&(shm->is_allocated), (int32_t)(sizeof(bool)),
849         optMem->GetAshmemSize() - (int32_t)(*sizeLeft)) != true) {
850             return false;
851         }
852 
853     *sizeLeft -= sizeof(bool);
854 
855     if (optMem->WriteToAshmem(&(shm->flags), (int32_t)(sizeof(uint32_t)),
856         optMem->GetAshmemSize() - (int32_t)(*sizeLeft)) != true) {
857             return false;
858         }
859 
860     *sizeLeft -= sizeof(uint32_t);
861 
862     if (optMem->WriteToAshmem(&(shm->ops_cnt), (int32_t)(sizeof(uint32_t)),
863         optMem->GetAshmemSize() - (int32_t)(*sizeLeft)) != true) {
864             return false;
865         }
866 
867     *sizeLeft -= sizeof(uint32_t);
868 
869     uint32_t shmOffset = FindShareMemOffset(shm->buffer);
870     if (optMem->WriteToAshmem(&shmOffset, (int32_t)(sizeof(uint32_t)),
871         optMem->GetAshmemSize() - (int32_t)(*sizeLeft)) != true) {
872             return false;
873         }
874 
875     *sizeLeft -= sizeof(uint32_t);
876 
877     if (optMem->WriteToAshmem(&(shm->size), (int32_t)(sizeof(uint32_t)),
878         optMem->GetAshmemSize() - (int32_t)(*sizeLeft)) != true) {
879             return false;
880         }
881 
882     *sizeLeft -= sizeof(uint32_t);
883 
884     return true;
885 }
886 
TeecOptEncodePartialMem(const TEEC_Parameter * param,uint32_t paramType,sptr<Ashmem> & optMem,size_t * dataSize)887 TEEC_Result TeeClient::TeecOptEncodePartialMem(const TEEC_Parameter *param,
888     uint32_t paramType, sptr<Ashmem> &optMem, size_t *dataSize)
889 {
890     size_t sizeLeft = *dataSize;
891 
892     TEEC_SharedMemory *shm = param->memref.parent;
893 
894     if ((shm == nullptr) || (shm->buffer == nullptr)) {
895         tloge("parent of memref is nullptr, or the buffer is zero\n");
896         return (TEEC_Result)TEEC_ERROR_BAD_PARAMETERS;
897     }
898     /* we put 4 uint32 and 1 bool in sharemem */
899     uint32_t shmSize = 4 * (sizeof(uint32_t)) + 1 * (sizeof(bool));
900     if (sizeLeft < shmSize) {
901         tloge("size is error:%" PUBLIC "zu:%" PUBLIC "u\n", sizeLeft, shmSize);
902         return TEEC_FAIL;
903     }
904 
905     if (CovertEncodePtr(optMem, &sizeLeft, shm) != true) {
906         return TEEC_FAIL;
907     }
908 
909     uint32_t cSize = param->memref.size;
910     if (paramType == TEEC_MEMREF_WHOLE) {
911         cSize = shm->size;
912     }
913     if (sizeLeft < cSize) {
914         tloge("size is error:%" PUBLIC "zu:%" PUBLIC "u\n", sizeLeft, cSize);
915         return TEEC_FAIL;
916     }
917 
918     if (!shm->is_allocated) {
919         uint8_t *p = reinterpret_cast<uint8_t *>(param->memref.parent->buffer);
920         if (p != nullptr) {
921             if (paramType != TEEC_MEMREF_WHOLE) {
922                 p += param->memref.offset;
923             }
924             if ((sizeLeft == 0) || (cSize == 0)) {
925                 tlogd("size left=%" PUBLIC "zu, ca size=%" PUBLIC "u\n", sizeLeft, cSize);
926             } else {
927                 bool nRet = optMem->WriteToAshmem(p, (int32_t)cSize, optMem->GetAshmemSize() - (int32_t)sizeLeft);
928                 CHECK_ERR_RETURN(nRet, true, TEEC_FAIL);
929             }
930         }
931     }
932 
933     sizeLeft -= cSize;
934     *dataSize = sizeLeft;
935     return TEEC_SUCCESS;
936 }
937 
TeecOptEncode(TEEC_Operation * operation,sptr<Ashmem> & optMem,size_t dataSize)938 TEEC_Result TeeClient::TeecOptEncode(TEEC_Operation *operation, sptr<Ashmem> &optMem, size_t dataSize)
939 {
940     uint32_t paramType[TEEC_PARAM_NUM] = { 0 };
941     uint32_t paramCnt;
942     size_t sizeLeft    = dataSize;
943     TEEC_Result teeRet = TEEC_SUCCESS;
944     for (paramCnt = 0; paramCnt < TEEC_PARAM_NUM; paramCnt++) {
945         paramType[paramCnt] = TEEC_PARAM_TYPE_GET(operation->paramTypes, paramCnt);
946         if (IS_TEMP_MEM(paramType[paramCnt])) {
947             teeRet = TeecOptEncodeTempMem(&(operation->params[paramCnt]), optMem, &sizeLeft);
948         } else if (IS_PARTIAL_MEM(paramType[paramCnt])) {
949             teeRet = TeecOptEncodePartialMem(&(operation->params[paramCnt]), paramType[paramCnt], optMem, &sizeLeft);
950         }
951         if (teeRet != TEEC_SUCCESS) {
952             tloge("opt encode param fail. paramCnt: %" PUBLIC "u, ret: 0x%" PUBLIC "x\n", paramCnt, teeRet);
953             return teeRet;
954         }
955     }
956     return TEEC_SUCCESS;
957 }
958 
CopyTeecOptMem(TEEC_Operation * operation,size_t optMemSize,sptr<Ashmem> & optMem)959 TEEC_Result TeeClient::CopyTeecOptMem(TEEC_Operation *operation, size_t optMemSize, sptr<Ashmem> &optMem)
960 {
961     TEEC_Result ret;
962     bool mapRet = false;
963     if (optMemSize == 0 || operation == nullptr) {
964         return TEEC_SUCCESS;
965     }
966 
967     optMem = Ashmem::CreateAshmem("TeeClient", static_cast<int32_t>(optMemSize));
968     if (optMem == nullptr) {
969         tloge("not enough memory for opt size=%" PUBLIC "u", static_cast<uint32_t>(optMemSize));
970         goto ERROR;
971     }
972 
973     mapRet = optMem->MapReadAndWriteAshmem();
974     if (!mapRet) {
975         tloge("map ashmem failed\n");
976         goto ERROR;
977     }
978 
979     ret = TeecOptEncode(operation, optMem, optMemSize);
980     if (ret != TEEC_SUCCESS) {
981         tloge("copy ashmem failed\n");
982         goto ERROR;
983     }
984 
985     return TEEC_SUCCESS;
986 
987 ERROR:
988     ClearAsmMem(optMem);
989     return TEEC_FAIL;
990 }
991 
992 
GetPartialMemSize(TEEC_Operation * operation,size_t optMemSize,uint32_t paramCnt,uint32_t * cSize)993 TEEC_Result TeeClient::GetPartialMemSize(TEEC_Operation *operation, size_t optMemSize,
994                                          uint32_t paramCnt, uint32_t *cSize)
995 {
996     uint32_t shmSize;
997     uint32_t paramType[TEEC_PARAM_NUM] = { 0 };
998     TEEC_Parameter *param = &(operation->params[paramCnt]);
999 
1000     paramType[paramCnt] = TEEC_PARAM_TYPE_GET(operation->paramTypes, paramCnt);
1001     /* we put 4 uint32 and 1 bool in sharemem */
1002     shmSize = 4 * (sizeof(uint32_t)) + 1 * (sizeof(bool));
1003     *cSize            = param->memref.size;
1004     if (paramType[paramCnt] == TEEC_MEMREF_WHOLE) {
1005         *cSize = param->memref.parent->size;
1006     }
1007     if (IsOverFlow(*cSize, shmSize)) {
1008         tloge("cSize:%" PUBLIC "u, shmSize:%" PUBLIC "u\n", *cSize, shmSize);
1009         return TEEC_ERROR_BAD_PARAMETERS;
1010     }
1011     *cSize += shmSize;
1012     if (IsOverFlow(optMemSize, *cSize)) {
1013         tloge("cSize:%" PUBLIC "u, optMemSize:%" PUBLIC "zu\n", *cSize, optMemSize);
1014         return TEEC_ERROR_BAD_PARAMETERS;
1015     }
1016     return TEEC_SUCCESS;
1017 }
1018 
GetOptMemSize(TEEC_Operation * operation,size_t * memSize)1019 TEEC_Result TeeClient::GetOptMemSize(TEEC_Operation *operation, size_t *memSize)
1020 {
1021     uint32_t paramType[TEEC_PARAM_NUM] = { 0 };
1022     uint32_t paramCnt;
1023     size_t optMemSize = 0;
1024     uint32_t cSize;
1025     TEEC_Result ret;
1026 
1027     if (operation == nullptr) {
1028         *memSize = optMemSize;
1029         return TEEC_SUCCESS;
1030     }
1031 
1032     for (paramCnt = 0; paramCnt < TEEC_PARAM_NUM; paramCnt++) {
1033         paramType[paramCnt] = TEEC_PARAM_TYPE_GET(operation->paramTypes, paramCnt);
1034         if (IS_TEMP_MEM(paramType[paramCnt])) {
1035             cSize = operation->params[paramCnt].tmpref.size;
1036             if (IsOverFlow(optMemSize, cSize)) {
1037                 tloge("cSize:%" PUBLIC "u, optMemSize:%" PUBLIC "zu\n", cSize, optMemSize);
1038                 return TEEC_ERROR_BAD_PARAMETERS;
1039             }
1040             optMemSize += cSize;
1041         } else if (IS_PARTIAL_MEM(paramType[paramCnt])) {
1042             ret = GetPartialMemSize(operation, optMemSize, paramCnt, &cSize);
1043             if (ret == TEEC_ERROR_BAD_PARAMETERS) {
1044                 return TEEC_ERROR_BAD_PARAMETERS;
1045             }
1046             optMemSize += cSize;
1047         }
1048     }
1049 
1050     if (optMemSize > PARAM_SIZE_LIMIT) {
1051         tloge("opt mem size over limit:%" PUBLIC "zu\n", optMemSize);
1052         return TEEC_ERROR_BAD_PARAMETERS;
1053     }
1054     *memSize = optMemSize;
1055     return TEEC_SUCCESS;
1056 }
1057 
InvokeCommand(TEEC_Session * session,uint32_t commandID,TEEC_Operation * operation,uint32_t * returnOrigin)1058 TEEC_Result TeeClient::InvokeCommand(TEEC_Session *session, uint32_t commandID,
1059     TEEC_Operation *operation, uint32_t *returnOrigin)
1060 {
1061     uint32_t retOrigin  = TEEC_ORIGIN_API;
1062     TEEC_Result ret = TEEC_ERROR_BAD_PARAMETERS;
1063 
1064     if (session == nullptr || session->context == nullptr) {
1065         tloge("InvokeCommand in params error!\n");
1066         goto END;
1067     }
1068 
1069     ret = TEEC_CheckOperation(operation);
1070     if (ret != TEEC_SUCCESS) {
1071         tloge("invoke command:check operation failed!\n");
1072         goto END;
1073     }
1074 
1075     ret = InvokeCommandSendCmd(session->context, session, commandID, operation, &retOrigin);
1076     if (ret != TEEC_SUCCESS) {
1077         tloge("invokeCommand: send cmd failed, ret=0x%" PUBLIC "x\n", ret);
1078     }
1079 
1080 END:
1081         if (returnOrigin != nullptr) {
1082             *returnOrigin = retOrigin;
1083         }
1084         return ret;
1085 }
1086 
WriteInvokeData(MessageParcel & data,TEEC_Context * context,TEEC_Session * session,uint32_t commandID,TEEC_Operation * operation)1087 static bool WriteInvokeData(MessageParcel &data, TEEC_Context *context,
1088     TEEC_Session *session, uint32_t commandID, TEEC_Operation *operation)
1089 {
1090     (void)data.WriteInterfaceToken(INTERFACE_TOKEN);
1091 
1092     if (WriteContext(data, context) != true) {
1093         return false;
1094     }
1095 
1096     if (WriteSession(data, session) != true) {
1097         return false;
1098     }
1099 
1100     if (data.WriteUint32(commandID) != true) {
1101         return false;
1102     }
1103 
1104     if (WriteOperation(data, operation) != true) {
1105         return false;
1106     }
1107 
1108     if (WriteIonFd(data, operation) != true) {
1109         return false;
1110     }
1111     return true;
1112 }
1113 
RecReply(MessageParcel & reply,int32_t & ret,uint32_t * returnOrigin)1114 static inline bool RecReply(MessageParcel &reply, int32_t &ret, uint32_t *returnOrigin)
1115 {
1116     if (reply.ReadUint32(*returnOrigin) != true) {
1117         return false;
1118     }
1119 
1120     if (reply.ReadInt32(ret) != true) {
1121         return false;
1122     }
1123 
1124     return true;
1125 }
1126 
InvokeCommandSendCmd(TEEC_Context * context,TEEC_Session * session,uint32_t commandID,TEEC_Operation * operation,uint32_t * returnOrigin)1127 TEEC_Result TeeClient::InvokeCommandSendCmd(TEEC_Context *context, TEEC_Session *session,
1128     uint32_t commandID, TEEC_Operation *operation, uint32_t *returnOrigin)
1129 {
1130     MessageParcel data;
1131     MessageOption option;
1132     MessageParcel reply;
1133     int32_t ret = (int32_t)TEEC_FAIL;
1134 
1135     CHECK_ERR_RETURN(InitTeecService(), true, TEEC_FAIL);
1136 
1137     size_t optMemSize;
1138     sptr<Ashmem> optMem;
1139     if (GetOptMemSize(operation, &optMemSize) != TEEC_SUCCESS) {
1140         return TEEC_ERROR_BAD_PARAMETERS;
1141     }
1142     CHECK_ERR_RETURN(WriteInvokeData(data, context, session, commandID, operation), true, TEEC_ERROR_BAD_PARAMETERS);
1143 
1144     if (data.WriteUint32(optMemSize) != true) {
1145         return TEEC_FAIL;
1146     }
1147 
1148     TEEC_Result nRet = CopyTeecOptMem(operation, optMemSize, optMem);
1149     if (nRet != TEEC_SUCCESS) {
1150         tloge("copy teec opt mem failed\n");
1151         return nRet;
1152     }
1153 
1154     if (optMemSize > 0) {
1155         if (!data.WriteAshmem(optMem)) {
1156             tloge("write ash mem to parcel failed\n");
1157             goto CLEAR_MEM;
1158         }
1159     }
1160 
1161     if (mTeecService->SendRequest(INVOKE_COMMND, data, reply, option) != ERR_NONE) {
1162         tloge("invoke command failed\n");
1163         ret = TEEC_FAIL;
1164         goto CLEAR_MEM;
1165     }
1166 
1167     if (!RecReply(reply, ret, returnOrigin)) {
1168         ret = TEEC_FAIL;
1169         goto CLEAR_MEM;
1170     }
1171 
1172     nRet = GetTeecOptMem(operation, optMemSize, optMem, reply);
1173     if (nRet != TEEC_SUCCESS && ret == TEEC_SUCCESS) {
1174         ret = nRet;
1175     }
1176 
1177 CLEAR_MEM:
1178     ClearAsmMem(optMem);
1179     return (TEEC_Result)ret;
1180 }
1181 
CloseSession(TEEC_Session * session)1182 void TeeClient::CloseSession(TEEC_Session *session)
1183 {
1184     MessageParcel data;
1185     MessageOption option;
1186     MessageParcel reply;
1187     bool parRet = false;
1188 
1189     if ((session == nullptr) || (session->context == nullptr)) {
1190         tloge("closeSession: invalid params\n");
1191         return;
1192     }
1193 
1194     if (!InitTeecService()) {
1195         return;
1196     }
1197 
1198     (void)data.WriteInterfaceToken(INTERFACE_TOKEN);
1199     parRet = WriteContext(data, session->context);
1200     if (!parRet) {
1201         return;
1202     }
1203 
1204     parRet = WriteSession(data, session);
1205     if (!parRet) {
1206         return;
1207     }
1208 
1209     if (mTeecService->SendRequest(CLOSE_SESSION, data, reply, option) != ERR_NONE) {
1210         tloge("close session failed\n");
1211     }
1212 
1213     session->session_id = 0;
1214     session->ops_cnt    = 0;
1215     session->context    = nullptr;
1216 }
1217 
GetFileFd(const char * filePath)1218 int32_t TeeClient::GetFileFd(const char *filePath)
1219 {
1220     if (filePath == nullptr) {
1221         return -1;
1222     }
1223 
1224     if (!((strnlen(filePath, MAX_TA_PATH_LEN) < MAX_TA_PATH_LEN) && strstr(filePath, ".sec"))) {
1225         tloge("ta_path format is wrong\n");
1226         return -1;
1227     }
1228 
1229     char realLoadFile[PATH_MAX + 1] = { 0 };
1230     if (realpath(filePath, realLoadFile) == nullptr) {
1231         tloge("real path failed err=%" PUBLIC "d\n", errno);
1232         return -1;
1233     }
1234 
1235     if (strncmp(realLoadFile, "/data/", sizeof("/data/") - 1) == 0 ||
1236         strncmp(realLoadFile, "/chip_prod/", sizeof("/chip_prod/") - 1) == 0 ||
1237         strncmp(realLoadFile, "/system/", sizeof("/system/") - 1) == 0) {
1238         int fd = open(realLoadFile, O_RDONLY);
1239         if (fd == -1) {
1240             tloge("open ta failed\n");
1241         }
1242         return fd;
1243     }
1244     return -1;
1245 }
1246 
FormatSharedMemory(MessageParcel & reply,TEEC_SharedMemory * sharedMem,uint32_t * offset)1247 TEEC_Result TeeClient::FormatSharedMemory(MessageParcel &reply, TEEC_SharedMemory *sharedMem, uint32_t *offset)
1248 {
1249     TEEC_SharedMemory *shmRet = nullptr;
1250     size_t len = sizeof(*shmRet);
1251     shmRet = (TEEC_SharedMemory *)(reply.ReadBuffer(len));
1252     if (shmRet == nullptr) {
1253         tloge("read session failed\n");
1254         return TEEC_FAIL;
1255     }
1256     tloge("reieve shmRet_is_allocated = %" PUBLIC "d\n", shmRet->is_allocated);
1257 
1258     sharedMem->ops_cnt      = shmRet->ops_cnt;
1259     sharedMem->is_allocated = shmRet->is_allocated;
1260     ListInit(&sharedMem->head);
1261 
1262     if (offset != nullptr) {
1263         if (reply.ReadUint32(*offset) != true) {
1264             return TEEC_FAIL;
1265         }
1266     }
1267     return TEEC_SUCCESS;
1268 }
1269 
RegisterSharedMemory(TEEC_Context * context,TEEC_SharedMemory * sharedMem)1270 TEEC_Result TeeClient::RegisterSharedMemory(TEEC_Context *context, TEEC_SharedMemory *sharedMem)
1271 {
1272     MessageParcel data;
1273     MessageParcel reply;
1274     MessageOption option;
1275 
1276     if ((context == nullptr) || (sharedMem == nullptr)) {
1277         tloge("context or sharedMem is nullptr\n");
1278         return TEEC_ERROR_BAD_PARAMETERS;
1279     }
1280 
1281     /*
1282      * ca may call ReleaseShareMemory even if RegisterShareMem failed,
1283      * we set sharedMem->context here to avoid receive a illegal ptr
1284      */
1285     sharedMem->context = context;
1286 
1287     if (sharedMem->buffer == nullptr || !CheckSharedMemoryFLag(sharedMem->flags)) {
1288         tloge("register shr mem failed: flag %" PUBLIC "d is invalid\n", sharedMem->flags);
1289         return TEEC_ERROR_BAD_PARAMETERS;
1290     }
1291 
1292     if (!InitTeecService()) {
1293         tloge("teec service not valid\n");
1294         return TEEC_FAIL;
1295     }
1296 
1297     (void)data.WriteInterfaceToken(INTERFACE_TOKEN);
1298 
1299     if (WriteContext(data, context) != true) {
1300         return TEEC_FAIL;
1301     }
1302 
1303     if (WriteSharedMem(data, sharedMem) != true) {
1304         return TEEC_FAIL;
1305     }
1306 
1307     int32_t ret = mTeecService->SendRequest(REGISTER_MEM, data, reply, option);
1308     if (ret != ERR_NONE) {
1309         return TEEC_FAIL;
1310     }
1311 
1312     if (reply.ReadInt32(ret) != true) {
1313         return TEEC_FAIL;
1314     }
1315 
1316     if ((TEEC_Result)ret != TEEC_SUCCESS) {
1317         tloge("return failed from tee\n");
1318         return (TEEC_Result)ret;
1319     }
1320     return FormatSharedMemory(reply, sharedMem, nullptr);
1321 }
1322 
MapSharedMemory(int fd,uint32_t offset,TEEC_SharedMemory * sharedMem)1323 TEEC_Result TeeClient::MapSharedMemory(int fd, uint32_t offset, TEEC_SharedMemory *sharedMem)
1324 {
1325     if (sharedMem->size != 0) {
1326         sharedMem->buffer = mmap(0, sharedMem->size,
1327             (PROT_READ | PROT_WRITE), MAP_SHARED, fd, (off_t)(offset * PAGE_SIZE));
1328     } else {
1329         sharedMem->buffer = ZERO_SIZE_PTR;
1330     }
1331 
1332     if (sharedMem->buffer == MAP_FAILED) {
1333         tloge("mmap failed\n");
1334         sharedMem->buffer = nullptr;
1335         return TEEC_ERROR_OUT_OF_MEMORY;
1336     }
1337 
1338     return TEEC_SUCCESS;
1339 }
1340 
AddShareMem(void * buffer,uint32_t offset,uint32_t size,int32_t fd)1341 void TeeClient::AddShareMem(void *buffer, uint32_t offset, uint32_t size, int32_t fd)
1342 {
1343     TC_NS_ShareMem shareMem;
1344 
1345     shareMem.offset = offset;
1346     shareMem.buffer = buffer;
1347     shareMem.size   = size;
1348     shareMem.fd     = fd;
1349     lock_guard<mutex> autoLock(mSharMemLock);
1350     mShareMem.push_back(shareMem);
1351     return;
1352 }
1353 
ProcAllocateSharedMemory(MessageParcel & reply,TEEC_SharedMemory * sharedMem)1354 TEEC_Result TeeClient::ProcAllocateSharedMemory(MessageParcel &reply, TEEC_SharedMemory *sharedMem)
1355 {
1356     int32_t ret;
1357 
1358     if (reply.ReadInt32(ret) != true) {
1359         return TEEC_FAIL;
1360     }
1361 
1362     if ((TEEC_Result)ret != TEEC_SUCCESS) {
1363         tloge("alloca share mem return failed\n");
1364         return (TEEC_Result)ret;
1365     }
1366 
1367     uint32_t offset;
1368     TEEC_Result rRet = FormatSharedMemory(reply, sharedMem, &offset);
1369     if (rRet != TEEC_SUCCESS) {
1370         return rRet;
1371     }
1372 
1373     int fd = reply.ReadFileDescriptor();
1374     if (fd < 0) {
1375         tloge("alloca share mem read fd failed\n");
1376         return TEEC_FAIL;
1377     }
1378 
1379     rRet = MapSharedMemory(fd, offset, sharedMem);
1380     if (rRet != TEEC_SUCCESS) {
1381         tloge("map shared mem failed\n");
1382         goto END;
1383     }
1384 
1385     AddShareMem(sharedMem->buffer, offset, sharedMem->size, sharedMem->context->fd);
1386 
1387 END:
1388     if (fd >= 0) {
1389         close(fd);
1390     }
1391     return TEEC_SUCCESS;
1392 }
1393 
AllocateSharedMemory(TEEC_Context * context,TEEC_SharedMemory * sharedMem)1394 TEEC_Result TeeClient::AllocateSharedMemory(TEEC_Context *context, TEEC_SharedMemory *sharedMem)
1395 {
1396     MessageParcel data;
1397     MessageParcel reply;
1398     MessageOption option;
1399 
1400     if ((context == nullptr) || (sharedMem == nullptr)) {
1401         tloge("alloca share mem: context or sharedMem is nullptr\n");
1402         return TEEC_ERROR_BAD_PARAMETERS;
1403     }
1404 
1405     /*
1406      * ca may call ReleaseShareMemory even if AllocateSharedMemory failed,
1407      * we set sharedMem->context here to avoid receive a illegal ptr
1408      */
1409     sharedMem->context = context;
1410 
1411     if (!CheckSharedMemoryFLag(sharedMem->flags)) {
1412         tloge("alloc shr mem: failed: flag %" PUBLIC "d is invalid\n", sharedMem->flags);
1413         return TEEC_ERROR_BAD_PARAMETERS;
1414     }
1415 
1416     if (!InitTeecService()) {
1417         tloge("alloca share mem: teec service not valid\n");
1418         return TEEC_FAIL;
1419     }
1420 
1421     (void)data.WriteInterfaceToken(INTERFACE_TOKEN);
1422     if (WriteContext(data, context) != true) {
1423         return TEEC_FAIL;
1424     }
1425 
1426     if (WriteSharedMem(data, sharedMem) != true) {
1427         return TEEC_FAIL;
1428     }
1429 
1430     if (mTeecService->SendRequest(ALLOC_MEM, data, reply, option) != ERR_NONE) {
1431         return TEEC_FAIL;
1432     }
1433 
1434     return ProcAllocateSharedMemory(reply, sharedMem);
1435 }
1436 
FreeShareMem(TEEC_SharedMemory * sharedMem)1437 TEEC_Result TeeClient::FreeShareMem(TEEC_SharedMemory *sharedMem)
1438 {
1439     size_t index;
1440     bool findFlag = false;
1441 
1442     lock_guard<mutex> autoLock(mSharMemLock);
1443     size_t count = mShareMem.size();
1444     for (index = 0; index < count; index++) {
1445         if (mShareMem[index].buffer == sharedMem->buffer) {
1446             findFlag = true;
1447             break;
1448         }
1449     }
1450 
1451     if (findFlag) {
1452         if ((sharedMem->buffer != nullptr) && (sharedMem->buffer != ZERO_SIZE_PTR) && (sharedMem->size != 0)) {
1453             int32_t ret = munmap(sharedMem->buffer, sharedMem->size);
1454             if (ret != 0) {
1455                 tloge("munmap share mem failed, ret=0x%" PUBLIC "x\n", ret);
1456             }
1457             sharedMem->buffer = nullptr;
1458             sharedMem->size   = 0;
1459         }
1460         mShareMem.erase(mShareMem.begin() + index);
1461     } else {
1462         tloge("failed to find share mem in vector\n");
1463         return TEEC_FAIL;
1464     }
1465 
1466     return TEEC_SUCCESS;
1467 }
1468 
ReleaseSharedMemory(TEEC_SharedMemory * sharedMem)1469 void TeeClient::ReleaseSharedMemory(TEEC_SharedMemory *sharedMem)
1470 {
1471     MessageParcel data;
1472     MessageParcel reply;
1473     MessageOption option;
1474 
1475     if (sharedMem == nullptr || sharedMem->context == nullptr) {
1476         tloge("releaseSharemem: wrong params");
1477         return;
1478     }
1479 
1480     uint32_t shmOffset = UINT32_MAX;
1481     if (sharedMem->buffer != nullptr) {
1482         shmOffset = FindShareMemOffset(sharedMem->buffer);
1483         if (sharedMem->is_allocated) {
1484             if (FreeShareMem(sharedMem)) {
1485                 tloge("releaseSharemem: free share mem failed\n");
1486             }
1487         }
1488     }
1489 
1490     if (!InitTeecService()) {
1491         return;
1492     }
1493 
1494     (void)data.WriteInterfaceToken(INTERFACE_TOKEN);
1495     if (!WriteContext(data, sharedMem->context)) {
1496         return;
1497     }
1498 
1499     if (!WriteSharedMem(data, sharedMem)) {
1500         return;
1501     }
1502 
1503     if (!data.WriteUint32(shmOffset)) {
1504         return;
1505     }
1506 
1507     if (mTeecService->SendRequest(RELEASE_MEM, data, reply, option) != ERR_NONE) {
1508         tloge("releaseSharemem: send request failed\n");
1509         return;
1510     }
1511 
1512     sharedMem->buffer  = nullptr;
1513     sharedMem->size    = 0;
1514     sharedMem->flags   = 0;
1515     sharedMem->ops_cnt = 0;
1516     sharedMem->context = nullptr;
1517 }
1518 
RequestCancellation(const TEEC_Operation * operation)1519 void TeeClient::RequestCancellation(const TEEC_Operation *operation)
1520 {
1521     tloge("requestCancellation not support!\n");
1522     (void)operation;
1523     return;
1524 }
1525 
SendSecfile(const char * path,TEEC_Session * session)1526 TEEC_Result TeeClient::SendSecfile(const char *path, TEEC_Session *session)
1527 {
1528     MessageParcel data;
1529     MessageParcel reply;
1530     MessageOption option;
1531     uint32_t result = TEEC_FAIL;
1532     if (path == nullptr || session == nullptr || session->context == nullptr) {
1533         tloge("the params is error\n");
1534         return TEEC_ERROR_BAD_PARAMETERS;
1535     }
1536 
1537     if (!InitTeecService()) {
1538         return TEEC_FAIL;
1539     }
1540 
1541     (void)data.WriteInterfaceToken(INTERFACE_TOKEN);
1542     int fd = GetFileFd(path);
1543     if (fd < 0) {
1544         tloge("open the path error\n");
1545         return TEEC_FAIL;
1546     }
1547 
1548     if (WriteChar(path, data) != true) {
1549         goto teec_error;
1550     }
1551 
1552     if (data.WriteBool(true) != true) {
1553         goto teec_error;
1554     }
1555     if (data.WriteFileDescriptor(fd) != true) {
1556         goto teec_error;
1557     }
1558 
1559     if (WriteContext(data, session->context) != true) {
1560         goto teec_error;
1561     }
1562 
1563     if (WriteSession(data, session)!= true) {
1564         goto teec_error;
1565     }
1566 
1567     if (mTeecService->SendRequest(SEND_SECFILE, data, reply, option) != ERR_NONE) {
1568         goto teec_error;
1569     }
1570 
1571     if (reply.ReadUint32(result) != true) {
1572         goto teec_error;
1573     }
1574 
1575 teec_error:
1576     close(fd);
1577     return (TEEC_Result)result;
1578 }
1579 
GetTeeVersion(uint32_t & teeVersion)1580 TEEC_Result TeeClient::GetTeeVersion(uint32_t &teeVersion)
1581 {
1582     MessageParcel data;
1583     MessageParcel reply;
1584     MessageOption option;
1585 
1586     if (!InitTeecService()) {
1587         return TEEC_FAIL;
1588     }
1589 
1590     if (mTeecService->SendRequest(GET_TEE_VERSION, data, reply, option) != ERR_NONE) {
1591         return TEEC_FAIL;
1592     }
1593 
1594     if (reply.ReadUint32(teeVersion) != true) {
1595         return TEEC_FAIL;
1596     }
1597     return TEEC_SUCCESS;
1598 }
1599 
1600 } // namespace OHOS
1601 
1602 
TEEC_InitializeContext(const char * name,TEEC_Context * context)1603 TEEC_Result TEEC_InitializeContext(const char *name, TEEC_Context *context)
1604 {
1605     return OHOS::TeeClient::GetInstance().InitializeContext(name, context);
1606 }
1607 
TEEC_FinalizeContext(TEEC_Context * context)1608 void TEEC_FinalizeContext(TEEC_Context *context)
1609 {
1610     OHOS::TeeClient::GetInstance().FinalizeContext(context);
1611 }
1612 
TEEC_OpenSession(TEEC_Context * context,TEEC_Session * session,const TEEC_UUID * destination,uint32_t connectionMethod,const void * connectionData,TEEC_Operation * operation,uint32_t * returnOrigin)1613 TEEC_Result TEEC_OpenSession(TEEC_Context *context, TEEC_Session *session, const TEEC_UUID *destination,
1614     uint32_t connectionMethod, const void *connectionData, TEEC_Operation *operation,
1615     uint32_t *returnOrigin)
1616 {
1617     return OHOS::TeeClient::GetInstance().OpenSession(context, session, destination,
1618         connectionMethod, connectionData, operation, returnOrigin);
1619 }
1620 
TEEC_CloseSession(TEEC_Session * session)1621 void TEEC_CloseSession(TEEC_Session *session)
1622 {
1623     OHOS::TeeClient::GetInstance().CloseSession(session);
1624 }
1625 
TEEC_InvokeCommand(TEEC_Session * session,uint32_t commandID,TEEC_Operation * operation,uint32_t * returnOrigin)1626 TEEC_Result TEEC_InvokeCommand(TEEC_Session *session, uint32_t commandID, TEEC_Operation *operation,
1627     uint32_t *returnOrigin)
1628 {
1629     return OHOS::TeeClient::GetInstance().InvokeCommand(session, commandID, operation, returnOrigin);
1630 }
1631 
TEEC_RegisterSharedMemory(TEEC_Context * context,TEEC_SharedMemory * sharedMem)1632 TEEC_Result TEEC_RegisterSharedMemory(TEEC_Context *context, TEEC_SharedMemory *sharedMem)
1633 {
1634     return OHOS::TeeClient::GetInstance().RegisterSharedMemory(context, sharedMem);
1635 }
1636 
TEEC_AllocateSharedMemory(TEEC_Context * context,TEEC_SharedMemory * sharedMem)1637 TEEC_Result TEEC_AllocateSharedMemory(TEEC_Context *context, TEEC_SharedMemory *sharedMem)
1638 {
1639     return OHOS::TeeClient::GetInstance().AllocateSharedMemory(context, sharedMem);
1640 }
1641 
TEEC_ReleaseSharedMemory(TEEC_SharedMemory * sharedMem)1642 void TEEC_ReleaseSharedMemory(TEEC_SharedMemory *sharedMem)
1643 {
1644     return OHOS::TeeClient::GetInstance().ReleaseSharedMemory(sharedMem);
1645 }
1646 
TEEC_RequestCancellation(TEEC_Operation * operation)1647 void TEEC_RequestCancellation(TEEC_Operation *operation)
1648 {
1649     OHOS::TeeClient::GetInstance().RequestCancellation(operation);
1650 }
1651 
TEEC_SendSecfile(const char * path,TEEC_Session * session)1652 TEEC_Result TEEC_SendSecfile(const char *path, TEEC_Session *session)
1653 {
1654     return OHOS::TeeClient::GetInstance().SendSecfile(path, session);
1655 }
1656 
TEEC_GetTEEVersion(void)1657 uint32_t TEEC_GetTEEVersion(void)
1658 {
1659     uint32_t teeVersion = 0;
1660     TEEC_Result result = OHOS::TeeClient::GetInstance().GetTeeVersion(teeVersion);
1661     if (result != TEEC_SUCCESS || teeVersion == 0) {
1662         tloge("get the tee version failed, result:0x%" PUBLIC "x, the version:0x%" PUBLIC "x", result, teeVersion);
1663     }
1664     return teeVersion;
1665 }
1666