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 "cadaemon_stub.h"
14 #include <malloc.h>
15 #include <memory>
16 #include <securec.h>
17 #include "ipc_skeleton.h"
18 #include "ipc_types.h"
19 #include "string_ex.h"
20 #include "tee_client_api.h"
21 #include "tee_client_inner.h"
22 #include "tee_log.h"
23
24 using namespace std;
25
26 namespace OHOS {
27 namespace CaDaemon {
28 const std::u16string INTERFACE_TOKEN = u"ohos.tee_client.accessToken";
CaDaemonStub()29 CaDaemonStub::CaDaemonStub()
30 {
31 }
32
~CaDaemonStub()33 CaDaemonStub::~CaDaemonStub()
34 {
35 memberFuncMap_.clear();
36 }
37
OnRemoteRequest(uint32_t code,MessageParcel & data,MessageParcel & reply,MessageOption & option)38 int32_t CaDaemonStub::OnRemoteRequest(uint32_t code,
39 MessageParcel& data, MessageParcel &reply, MessageOption &option)
40 {
41 tlogi("CaDaemonStub::OnReceived, code = %{public}u, flags= %{public}d.", code, option.GetFlags());
42 int32_t result;
43 (void)mallopt(M_SET_THREAD_CACHE, M_THREAD_CACHE_DISABLE);
44 (void)mallopt(M_DELAYED_FREE, M_DELAYED_FREE_DISABLE);
45 switch (code) {
46 case static_cast<uint32_t>(CadaemonOperationInterfaceCode::INIT_CONTEXT):
47 result = InitContextRecvProc(data, reply);
48 break;
49 case static_cast<uint32_t>(CadaemonOperationInterfaceCode::FINAL_CONTEXT):
50 result = FinalContextRecvProc(data, reply);
51 break;
52 case static_cast<uint32_t>(CadaemonOperationInterfaceCode::OPEN_SESSION):
53 result = OpenSessionRecvProc(data, reply);
54 break;
55 case static_cast<uint32_t>(CadaemonOperationInterfaceCode::CLOSE_SESSION):
56 result = CloseSessionRecvProc(data, reply);
57 break;
58 case static_cast<uint32_t>(CadaemonOperationInterfaceCode::INVOKE_COMMND):
59 result = InvokeCommandRecvProc(data, reply);
60 break;
61 case static_cast<uint32_t>(CadaemonOperationInterfaceCode::REGISTER_MEM):
62 result = RegisterMemRecvProc(data, reply);
63 break;
64 case static_cast<uint32_t>(CadaemonOperationInterfaceCode::ALLOC_MEM):
65 result = AllocMemRecvProc(data, reply);
66 break;
67 case static_cast<uint32_t>(CadaemonOperationInterfaceCode::RELEASE_MEM):
68 result = ReleaseMemRecvProc(data, reply);
69 break;
70 case static_cast<uint32_t>(CadaemonOperationInterfaceCode::SET_CALL_BACK):
71 result = SetCallBackRecvProc(data, reply);
72 break;
73 case static_cast<uint32_t>(CadaemonOperationInterfaceCode::SEND_SECFILE):
74 result = SendSecFileRecvProc(data, reply);
75 break;
76 case static_cast<uint32_t>(CadaemonOperationInterfaceCode::GET_TEE_VERSION):
77 result = GetTeeVersionRecvProc(data, reply);
78 break;
79 default:
80 tlogi("CaDaemonStub: default case, need check");
81 (void)mallopt(M_FLUSH_THREAD_CACHE, 0);
82 return IPCObjectStub::OnRemoteRequest(code, data, reply, option);
83 }
84
85 (void)mallopt(M_FLUSH_THREAD_CACHE, 0);
86 return result;
87 }
88
GetChar(MessageParcel & data,char tempChar[],const char ** str)89 static bool GetChar(MessageParcel &data, char tempChar[], const char **str)
90 {
91 uint32_t strLen;
92 string tempStr;
93 int32_t ret;
94
95 ret = data.ReadUint32(strLen);
96 CHECK_ERR_RETURN(ret, true, ret);
97
98 if (strLen > 0) {
99 ret = data.ReadString(tempStr);
100 CHECK_ERR_RETURN(ret, true, ret);
101 if (strnlen(tempStr.c_str(), PATH_MAX) == PATH_MAX || strLen != strnlen(tempStr.c_str(), PATH_MAX)) {
102 tloge("recv str length check fail\n");
103 return false;
104 }
105
106 if (strcpy_s(tempChar, PATH_MAX + 1, tempStr.c_str()) != EOK) {
107 tloge("copy str fail, errno = %{public}d\n", errno);
108 return false;
109 }
110 *str = tempChar;
111 }
112
113 return true;
114 }
115
InitContextRecvProc(MessageParcel & data,MessageParcel & reply)116 int32_t CaDaemonStub::InitContextRecvProc(MessageParcel &data, MessageParcel &reply)
117 {
118 tlogi("CaDaemonStub: InitContextRecvProc start");
119 if (!EnforceInterceToken(data)) {
120 tloge("CaDaemonStub: InitContextRecvProc interface token check failed!");
121 return ERR_UNKNOWN_REASON;
122 }
123
124 const char *name = nullptr;
125 char tempChar[PATH_MAX + 1] = { 0 };
126 if (!GetChar(data, tempChar, &name)) {
127 tloge("InitContextRecvProc: get name failed\n");
128 return ERR_UNKNOWN_OBJECT;
129 }
130
131 if (InitializeContext(name, reply) != TEEC_SUCCESS) {
132 tloge("initialize context failed\n");
133 return ERR_UNKNOWN_REASON;
134 }
135
136 return ERR_NONE;
137 }
138
FinalContextRecvProc(MessageParcel & data,MessageParcel & reply)139 int32_t CaDaemonStub::FinalContextRecvProc(MessageParcel &data, MessageParcel &reply)
140 {
141 (void)reply;
142 tlogi("CaDaemonStub: FinalContextRecvProc start");
143 if (!EnforceInterceToken(data)) {
144 tloge("CaDaemonStub: FinalContextRecvProc interface token check failed!");
145 return -1;
146 }
147
148 TEEC_Context *context = nullptr;
149 size_t len = sizeof(*context);
150 context = (TEEC_Context *)(data.ReadBuffer(len));
151 if (context == nullptr) {
152 return ERR_UNKNOWN_OBJECT;
153 }
154
155 if (FinalizeContext(context) != TEEC_SUCCESS) {
156 return ERR_UNKNOWN_REASON;
157 }
158
159 return ERR_NONE;
160 }
161
GetContextFromData(MessageParcel & data,TEEC_Context * context)162 static bool GetContextFromData(MessageParcel &data, TEEC_Context *context)
163 {
164 size_t len = sizeof(*context);
165 TEEC_Context *tempContext = (TEEC_Context *)(data.ReadBuffer(len));
166 if (tempContext == nullptr) {
167 return false;
168 }
169
170 if (memcpy_s(context, len, tempContext, len) != EOK) {
171 tloge("getContext: operation memcpy failed\n");
172 return false;
173 }
174 return true;
175 }
176
GetSessionFromData(MessageParcel & data,TEEC_Session * session)177 static bool GetSessionFromData(MessageParcel &data, TEEC_Session *session)
178 {
179 TEEC_Session *tempSession = nullptr;
180 size_t len = sizeof(*tempSession);
181 tempSession = (TEEC_Session *)(data.ReadBuffer(len));
182 if (tempSession == nullptr) {
183 return ERR_UNKNOWN_OBJECT;
184 }
185
186 if (memcpy_s(session, len, tempSession, len) != EOK) {
187 tloge("getSession: operation memcpy failed\n");
188 return false;
189 }
190 return true;
191 }
192
GetSharedMemFromData(MessageParcel & data,TEEC_SharedMemory * shm)193 static bool GetSharedMemFromData(MessageParcel &data, TEEC_SharedMemory *shm)
194 {
195 tlogi("start to recieve sharedmem\n");
196 TEEC_SharedMemory *tempShm = nullptr;
197 size_t len = sizeof(*tempShm);
198 tempShm = (TEEC_SharedMemory *)(data.ReadBuffer(len));
199 if (tempShm == nullptr) {
200 return ERR_UNKNOWN_OBJECT;
201 }
202
203 if (memcpy_s(shm, len, tempShm, len) != EOK) {
204 tloge("getShamem: operation memcpy failed\n");
205 return false;
206 }
207 return true;
208 }
209
GetOperationFromData(MessageParcel & data,TEEC_Operation * operation,bool & opFlag)210 static bool GetOperationFromData(MessageParcel &data, TEEC_Operation *operation, bool &opFlag)
211 {
212 bool retTmp = data.ReadBool(opFlag);
213 uint32_t paramType[TEEC_PARAM_NUM] = { 0 };
214 CHECK_ERR_RETURN(retTmp, true, retTmp);
215
216 if (!opFlag) {
217 tloge("operation is nullptr\n");
218 return true;
219 }
220
221 size_t len = sizeof(*operation);
222 TEEC_Operation *tempOp = (TEEC_Operation *)(data.ReadBuffer(len));
223 if (tempOp == nullptr) {
224 return false;
225 }
226
227 if (memcpy_s(operation, len, tempOp, len) != EOK) {
228 tloge("getOperation: operation memcpy failed\n");
229 return false;
230 }
231
232 /* clear the pointer from ca to avoid access to invalid address */
233 operation->session = nullptr;
234 for (uint32_t paramCnt = 0; paramCnt < TEEC_PARAM_NUM; paramCnt++) {
235 paramType[paramCnt] = TEEC_PARAM_TYPE_GET(operation->paramTypes, paramCnt);
236 if (IS_TEMP_MEM(paramType[paramCnt])) {
237 operation->params[paramCnt].tmpref.buffer = nullptr;
238 } else if (IS_PARTIAL_MEM(paramType[paramCnt])) {
239 operation->params[paramCnt].memref.parent = nullptr;
240 }
241 }
242 return true;
243 }
244
245
ReadFd(MessageParcel & data,int32_t & fd)246 static bool ReadFd(MessageParcel &data, int32_t &fd)
247 {
248 bool fdFlag = false;
249
250 bool retTmp = data.ReadBool(fdFlag);
251 CHECK_ERR_RETURN(retTmp, true, retTmp);
252
253 if (fdFlag) {
254 fd = data.ReadFileDescriptor();
255 if (fd < 0) {
256 tloge("read fd failed\n");
257 return false;
258 }
259 tloge("read fd success = %{public}d\n", fd);
260 }
261 return true;
262 }
263
ClearAsmMem(sptr<Ashmem> & optMem)264 static void ClearAsmMem(sptr<Ashmem> &optMem)
265 {
266 if (optMem != nullptr) {
267 optMem->UnmapAshmem();
268 optMem->CloseAshmem();
269 }
270 }
271
GetOptMemFromData(MessageParcel & data,sptr<Ashmem> & optMem,uint32_t & optMemSize)272 static bool GetOptMemFromData(MessageParcel &data, sptr<Ashmem> &optMem, uint32_t &optMemSize)
273 {
274 tlogi("get optMem start\n");
275 bool retTmp = data.ReadUint32(optMemSize);
276 CHECK_ERR_RETURN(retTmp, true, retTmp);
277
278 if (optMemSize > 0) {
279 optMem = data.ReadAshmem();
280 if (optMem == nullptr) {
281 tloge("get optMem failed\n");
282 return false;
283 }
284
285 bool ret = optMem->MapReadAndWriteAshmem();
286 if (!ret) {
287 tloge("map ashmem failed\n");
288 return false;
289 }
290 tloge("get optMem success\n");
291 }
292
293 return true;
294 }
295
ReadOpenData(MessageParcel & data,int32_t & fd,TEEC_UUID ** uuid,uint32_t & connMethod)296 static int32_t ReadOpenData(MessageParcel &data, int32_t &fd, TEEC_UUID **uuid, uint32_t &connMethod)
297 {
298 size_t len = sizeof(**uuid);
299
300 bool retTmp = ReadFd(data, fd);
301 if (!retTmp) {
302 tloge("read ta fd failed\n");
303 goto ERROR;
304 }
305
306 *uuid = (TEEC_UUID *)(data.ReadBuffer(len));
307 if (*uuid == nullptr) {
308 tloge("read uuid failed\n");
309 goto ERROR;
310 }
311
312 retTmp = data.ReadUint32(connMethod);
313 if (!retTmp) {
314 tloge("read connection method failed\n");
315 goto ERROR;
316 }
317
318 return ERR_NONE;
319
320 ERROR:
321 if (fd >= 0) {
322 close(fd);
323 }
324
325 return ERR_UNKNOWN_OBJECT;
326 }
327
OpenSessionRecvProc(MessageParcel & data,MessageParcel & reply)328 int32_t CaDaemonStub::OpenSessionRecvProc(MessageParcel &data, MessageParcel &reply)
329 {
330 int32_t result = ERR_NONE;
331 tlogi("CaDaemonStub: OpenSessionRecvProc start");
332 if (!EnforceInterceToken(data)) {
333 tloge("CaDaemonStub: OpenSessionRecvProc interface token check failed!");
334 return -1;
335 }
336
337 TEEC_Context context;
338 bool retTmp = GetContextFromData(data, &context);
339 CHECK_ERR_RETURN(retTmp, true, ERR_UNKNOWN_OBJECT);
340
341 const char *taPath = nullptr;
342 char tempChar[PATH_MAX + 1] = { 0 };
343 retTmp = GetChar(data, tempChar, &taPath);
344 CHECK_ERR_RETURN(retTmp, true, ERR_UNKNOWN_OBJECT);
345 if (taPath != nullptr) {
346 tloge("recieve taPath is not nullptr\n");
347 context.ta_path = reinterpret_cast<uint8_t *>(const_cast<char *>(taPath));
348 }
349
350 int32_t fd = -1;
351 TEEC_UUID *uuid = nullptr;
352 uint32_t connMethod;
353 result = ReadOpenData(data, fd, &uuid, connMethod);
354 CHECK_ERR_RETURN(result, ERR_NONE, ERR_UNKNOWN_OBJECT);
355
356 TEEC_Operation operation;
357 bool opFlag = false;
358 retTmp = GetOperationFromData(data, &operation, opFlag);
359 CHECK_ERR_RETURN(retTmp, true, ERR_UNKNOWN_OBJECT);
360
361 uint32_t optMemSize;
362 sptr<Ashmem> optMem;
363 retTmp = GetOptMemFromData(data, optMem, optMemSize);
364 if (!retTmp) {
365 result = ERR_UNKNOWN_OBJECT;
366 goto END;
367 }
368
369 if (opFlag) {
370 result = OpenSession(&context, taPath, fd, uuid, connMethod, &operation, optMemSize, optMem, reply);
371 } else {
372 result = OpenSession(&context, taPath, fd, uuid, connMethod, nullptr, optMemSize, optMem, reply);
373 }
374
375 END:
376 ClearAsmMem(optMem);
377
378 if (fd >= 0) {
379 close(fd);
380 }
381
382 return result;
383 }
384
CloseSessionRecvProc(MessageParcel & data,MessageParcel & reply)385 int32_t CaDaemonStub::CloseSessionRecvProc(MessageParcel &data, MessageParcel &reply)
386 {
387 (void)reply;
388 tlogi("CaDaemonStub: CloseSessionRecvProc start");
389 if (!EnforceInterceToken(data)) {
390 tloge("CaDaemonStub: CloseSessionRecvProc interface token check failed!");
391 return -1;
392 }
393
394 TEEC_Context context;
395 bool retTmp = GetContextFromData(data, &context);
396 CHECK_ERR_RETURN(retTmp, true, ERR_UNKNOWN_OBJECT);
397
398 TEEC_Session session;
399 retTmp = GetSessionFromData(data, &session);
400 CHECK_ERR_RETURN(retTmp, true, ERR_UNKNOWN_OBJECT);
401
402 if (CloseSession(&session, &context) != TEEC_SUCCESS) {
403 return ERR_UNKNOWN_REASON;
404 }
405
406 return ERR_NONE;
407 }
InvokeCommandRecvProc(MessageParcel & data,MessageParcel & reply)408 int32_t CaDaemonStub::InvokeCommandRecvProc(MessageParcel &data, MessageParcel &reply)
409 {
410 int32_t result = ERR_NONE;
411 tlogi("CaDaemonStub: InvokeCommandRecvProc start");
412 if (!EnforceInterceToken(data)) {
413 tloge("CaDaemonStub: InvokeCommandRecvProc interface token check failed!");
414 return -1;
415 }
416
417 TEEC_Context context;
418 bool retTmp = GetContextFromData(data, &context);
419 CHECK_ERR_RETURN(retTmp, true, ERR_UNKNOWN_OBJECT);
420
421 TEEC_Session session;
422 retTmp = GetSessionFromData(data, &session);
423 CHECK_ERR_RETURN(retTmp, true, ERR_UNKNOWN_OBJECT);
424
425 uint32_t commandID;
426 retTmp = data.ReadUint32(commandID);
427 CHECK_ERR_RETURN(retTmp, true, ERR_UNKNOWN_OBJECT);
428
429 TEEC_Operation operation;
430 bool opFlag = false;
431 retTmp = GetOperationFromData(data, &operation, opFlag);
432 CHECK_ERR_RETURN(retTmp, true, ERR_UNKNOWN_OBJECT);
433
434 uint32_t optMemSize;
435 sptr<Ashmem> optMem;
436 retTmp = GetOptMemFromData(data, optMem, optMemSize);
437 if (!retTmp) {
438 result = ERR_UNKNOWN_OBJECT;
439 goto END;
440 }
441
442 if (opFlag) {
443 result = InvokeCommand(&context, &session, commandID, &operation, optMemSize, optMem, reply);
444 } else {
445 result = InvokeCommand(&context, &session, commandID, nullptr, optMemSize, optMem, reply);
446 }
447
448 END:
449 ClearAsmMem(optMem);
450 return result;
451 }
452
RegisterMemRecvProc(MessageParcel & data,MessageParcel & reply)453 int32_t CaDaemonStub::RegisterMemRecvProc(MessageParcel &data, MessageParcel &reply)
454 {
455 tlogi("CaDaemonStub: RegisterMemRecvProc start");
456 if (!EnforceInterceToken(data)) {
457 tloge("CaDaemonStub: RegisterMemRecvProc interface token check failed!");
458 return -1;
459 }
460
461 TEEC_Context context;
462 bool retTmp = GetContextFromData(data, &context);
463 CHECK_ERR_RETURN(retTmp, true, ERR_UNKNOWN_OBJECT);
464
465 TEEC_SharedMemory sharedMem;
466 retTmp = GetSharedMemFromData(data, &sharedMem);
467 CHECK_ERR_RETURN(retTmp, true, ERR_UNKNOWN_OBJECT);
468
469 if (RegisterSharedMemory(&context, &sharedMem, reply) != TEEC_SUCCESS) {
470 return ERR_UNKNOWN_REASON;
471 }
472
473 return ERR_NONE;
474 }
475
AllocMemRecvProc(MessageParcel & data,MessageParcel & reply)476 int32_t CaDaemonStub::AllocMemRecvProc(MessageParcel &data, MessageParcel &reply)
477 {
478 tlogi("CaDaemonStub: AllocMemRecvProc start");
479 if (!EnforceInterceToken(data)) {
480 tloge("CaDaemonStub: AllocMemRecvProc interface token check failed!");
481 return -1;
482 }
483
484 TEEC_Context context;
485 bool retTmp = GetContextFromData(data, &context);
486 CHECK_ERR_RETURN(retTmp, true, ERR_UNKNOWN_OBJECT);
487
488 TEEC_SharedMemory sharedMem;
489 retTmp = GetSharedMemFromData(data, &sharedMem);
490 CHECK_ERR_RETURN(retTmp, true, ERR_UNKNOWN_OBJECT);
491
492 if (AllocateSharedMemory(&context, &sharedMem, reply) != TEEC_SUCCESS) {
493 return ERR_UNKNOWN_REASON;
494 }
495
496 return ERR_NONE;
497 }
498
ReleaseMemRecvProc(MessageParcel & data,MessageParcel & reply)499 int32_t CaDaemonStub::ReleaseMemRecvProc(MessageParcel &data, MessageParcel &reply)
500 {
501 tlogi("CaDaemonStub: ReleaseMemRecvProc start");
502 if (!EnforceInterceToken(data)) {
503 tloge("CaDaemonStub: ReleaseMemRecvProc interface token check failed!");
504 return -1;
505 }
506
507 TEEC_Context context;
508 bool retTmp = GetContextFromData(data, &context);
509 CHECK_ERR_RETURN(retTmp, true, ERR_UNKNOWN_OBJECT);
510
511 TEEC_SharedMemory sharedMem;
512 retTmp = GetSharedMemFromData(data, &sharedMem);
513 CHECK_ERR_RETURN(retTmp, true, ERR_UNKNOWN_OBJECT);
514
515 uint32_t shmOffset;
516 retTmp = data.ReadUint32(shmOffset);
517 CHECK_ERR_RETURN(retTmp, true, ERR_UNKNOWN_OBJECT);
518
519 ReleaseSharedMemory(&context, &sharedMem, shmOffset, reply);
520
521 return ERR_NONE;
522 }
523
SetCallBackRecvProc(MessageParcel & data,MessageParcel & reply)524 int32_t CaDaemonStub::SetCallBackRecvProc(MessageParcel &data, MessageParcel &reply)
525 {
526 tlogi("CaDaemonStub: SetCallBackRecvProc start");
527 if (!EnforceInterceToken(data)) {
528 tloge("CaDaemonStub: SetCallBackRecvProc interface token check failed!");
529 return -1;
530 }
531
532 sptr<IRemoteObject> notify = nullptr;
533 notify = data.ReadRemoteObject();
534 if (notify == nullptr) {
535 tloge("CaDaemonStub: recieve notify is nullptr\n");
536 return ERR_NONE;
537 }
538
539 return SetCallBack(notify);
540 }
541
EnforceInterceToken(MessageParcel & data)542 bool CaDaemonStub::EnforceInterceToken(MessageParcel& data)
543 {
544 u16string interfaceToken = data.ReadInterfaceToken();
545 return interfaceToken == INTERFACE_TOKEN;
546 }
547
SendSecFileRecvProc(MessageParcel & data,MessageParcel & reply)548 int32_t CaDaemonStub::SendSecFileRecvProc(MessageParcel& data, MessageParcel &reply)
549 {
550 tlogi("CaDaemonStub: SendSecFileRecvProc start");
551 if (!EnforceInterceToken(data)) {
552 tloge("CaDaemonStub: SendSecFileRecvProc interface token check failed!");
553 return -1;
554 }
555 const char *path = nullptr;
556 char tempChar[PATH_MAX + 1] = {0};
557 if (!GetChar(data, tempChar, &path)) {
558 tloge("SendSecFileRecvProc: get path failed\n");
559 return ERR_UNKNOWN_OBJECT;
560 }
561
562 int fd;
563 FILE *fp = nullptr;
564 bool retTmp = ReadFd(data, fd);
565 CHECK_ERR_RETURN(retTmp, true, ERR_UNKNOWN_OBJECT);
566 fp = fdopen(fd, "r");
567
568 TEEC_Context context;
569 retTmp = GetContextFromData(data, &context);
570 CHECK_ERR_RETURN(retTmp, true, ERR_UNKNOWN_OBJECT);
571
572 TEEC_Session session;
573 retTmp = GetSessionFromData(data, &session);
574 CHECK_ERR_RETURN(retTmp, true, ERR_UNKNOWN_OBJECT);
575
576 (void)SendSecfile(path, context.fd, fp, reply);
577
578 return ERR_NONE;
579 }
580
GetTeeVersionRecvProc(MessageParcel & data,MessageParcel & reply)581 int32_t CaDaemonStub::GetTeeVersionRecvProc(MessageParcel& data, MessageParcel &reply)
582 {
583 (void)GetTeeVersion(reply);
584 return ERR_NONE;
585 }
586 } // namespace CaDaemon
587 } // namespace OHOS
588