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