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