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 31using namespace std; 32namespace OHOS { 33bool TeeClient::mServiceValid = false; 34 35bool 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 67void 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 121static 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 130static 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; 167PARAM_ERROR: 168 tloge("type of memref not belong to the parent flags\n"); 169 return TEEC_ERROR_BAD_PARAMETERS; 170} 171 172TEEC_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 208static inline bool IsOverFlow(uint32_t num1, uint32_t num2) 209{ 210 if (num1 + num2 < num1) { 211 return true; 212 } 213 return false; 214} 215 216static 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 236static bool WriteContext(MessageParcel &data, TEEC_Context *context) 237{ 238 return data.WriteBuffer(context, sizeof(*context)); 239} 240 241static bool WriteSession(MessageParcel &data, TEEC_Session *session) 242{ 243 return data.WriteBuffer(session, sizeof(*session)); 244} 245 246static bool WriteSharedMem(MessageParcel &data, TEEC_SharedMemory *shm) 247{ 248 return data.WriteBuffer(shm, sizeof(*shm)); 249} 250 251static bool CheckSharedMemoryFLag(uint32_t flag) 252{ 253 return (flag == TEEC_MEM_INPUT || flag == TEEC_MEM_OUTPUT || flag == TEEC_MEM_INOUT); 254} 255 256uint32_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 269void 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 288void 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 308static void SleepNs(long num) 309{ 310 struct timespec ts; 311 ts.tv_sec = 0; 312 ts.tv_nsec = num; 313 314 if (nanosleep(&ts, NULL) != 0) { 315 tlogd("nanosleep ms error\n"); 316 } 317} 318 319#define SLEEP_TIME (200*1000*1000) 320#define CONNECT_MAX_NUM 50 321 322TEEC_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 353TEEC_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 384void 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 420TEEC_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 466END: 467 if (returnOrigin != nullptr) { 468 *returnOrigin = retOrigin; 469 } 470 return teecRet; 471} 472 473static 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 503static 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 515bool 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 541TEEC_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 572TEEC_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 627COPY_TA_SIZE_TO_CA: 628 param->memref.size = inParam->memref.size; 629 630END: 631 *data += cSize; 632 *dataSize -= cSize; 633 return TEEC_SUCCESS; 634} 635 636TEEC_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 671TEEC_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 706COPY_TA_SIZE_TO_CA: 707 ptr += param->tmpref.size; 708 sizeLeft -= param->tmpref.size; 709 param->tmpref.size = inParam->tmpref.size; 710 711END: 712 *data = ptr; 713 *dataSize = sizeLeft; 714 return TEEC_SUCCESS; 715} 716 717static inline void ClearAsmMem(sptr<Ashmem> &optMem) 718{ 719 if (optMem != nullptr) { 720 optMem->UnmapAshmem(); 721 optMem->CloseAshmem(); 722 } 723} 724 725TEEC_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 780END: 781 ClearAsmMem(optMem); 782 return (TEEC_Result)ret; 783 784ERROR: 785 ClearAsmMem(optMem); 786 return TEEC_FAIL; 787} 788 789TEEC_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 814bool 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 850TEEC_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 900TEEC_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 921TEEC_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 949ERROR: 950 ClearAsmMem(optMem); 951 return TEEC_FAIL; 952} 953 954 955TEEC_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 990TEEC_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 1032TEEC_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 1054END: 1055 if (returnOrigin != nullptr) { 1056 *returnOrigin = retOrigin; 1057 } 1058 return ret; 1059} 1060 1061static 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 1082static 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 1093TEEC_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 1147CLEAR_MEM: 1148 ClearAsmMem(optMem); 1149 return (TEEC_Result)ret; 1150} 1151 1152void 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 1194int32_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 1221TEEC_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 1243TEEC_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 1293TEEC_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 1311void 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 1324TEEC_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 1354END: 1355 if (fd >= 0) { 1356 close(fd); 1357 } 1358 return TEEC_SUCCESS; 1359} 1360 1361TEEC_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 1404TEEC_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 1436void 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 1485void TeeClient::RequestCancellation(const TEEC_Operation *operation) 1486{ 1487 tloge("requestCancellation not support!\n"); 1488 (void)operation; 1489 return; 1490} 1491 1492TEEC_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 1540TEEC_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 1561TEEC_Result TEEC_InitializeContext(const char *name, TEEC_Context *context) 1562{ 1563 return OHOS::TeeClient::GetInstance().InitializeContext(name, context); 1564} 1565 1566void TEEC_FinalizeContext(TEEC_Context *context) 1567{ 1568 OHOS::TeeClient::GetInstance().FinalizeContext(context); 1569} 1570 1571TEEC_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 1579void TEEC_CloseSession(TEEC_Session *session) 1580{ 1581 OHOS::TeeClient::GetInstance().CloseSession(session); 1582} 1583 1584TEEC_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 1590TEEC_Result TEEC_RegisterSharedMemory(TEEC_Context *context, TEEC_SharedMemory *sharedMem) 1591{ 1592 return OHOS::TeeClient::GetInstance().RegisterSharedMemory(context, sharedMem); 1593} 1594 1595TEEC_Result TEEC_AllocateSharedMemory(TEEC_Context *context, TEEC_SharedMemory *sharedMem) 1596{ 1597 return OHOS::TeeClient::GetInstance().AllocateSharedMemory(context, sharedMem); 1598} 1599 1600void TEEC_ReleaseSharedMemory(TEEC_SharedMemory *sharedMem) 1601{ 1602 return OHOS::TeeClient::GetInstance().ReleaseSharedMemory(sharedMem); 1603} 1604 1605void TEEC_RequestCancellation(TEEC_Operation *operation) 1606{ 1607 OHOS::TeeClient::GetInstance().RequestCancellation(operation); 1608} 1609 1610TEEC_Result TEEC_SendSecfile(const char *path, TEEC_Session *session) 1611{ 1612 return OHOS::TeeClient::GetInstance().SendSecfile(path, session); 1613} 1614 1615uint32_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