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