1 /*
2 * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
3 * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without modification,
6 * are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice, this list of
9 * conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
12 * of conditions and the following disclaimer in the documentation and/or other materials
13 * provided with the distribution.
14 *
15 * 3. Neither the name of the copyright holder nor the names of its contributors may be used
16 * to endorse or promote products derived from this software without specific prior written
17 * permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
26 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
28 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
29 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 #include "tc_client_driver.h"
33 #include "agent.h"
34 #include "gp_ops.h"
35 #include "mailbox_mempool.h"
36 #include "mem.h"
37 #include "smc.h"
38 #include "tc_client_sub_driver.h"
39 #include "tc_ns_log.h"
40 #include "teek_client_constants.h"
41 #include "teek_client_type.h"
42 #include "tz_spi_notify.h"
43 #include "tzdebug.h"
44 #include "tzdriver_compat.h"
45
46 struct workqueue_struct *g_tzdriverWq = NULL;
47
48 #define TEEC_PARAM_TYPES(param0_type, param1_type, param2_type, param3_type) \
49 (((param3_type) << 12) | ((param2_type) << 8) | \
50 ((param1_type) << 4) | (param0_type))
51
52 #define TEEC_PARAM_TYPE_GET(paramTypes, index) \
53 (((paramTypes) >> ((index) << 2)) & 0x0F)
54
55 // record device_file count
56 static unsigned int g_deviceFileCnt = 1;
57 static DEFINE_MUTEX(g_deviceFileCntLock);
58
59 static LosTaskCB *g_teecdTask = NULL;
60 // dev node list and itself has mutex to avoid race
61 struct TcNsDevList g_tcNsDevList;
62
63 // record all service node and need mutex to avoid race
64 struct list_head g_serviceList;
65 DEFINE_MUTEX(g_serviceListLock);
66
67 #define TEECD_CERT_INDEX 0
68 // teecd must set 0 in g_arrayCertNativeVendor
69 static const unsigned char g_arrayCertNativeVendor[][SHA256_DIGEST_LENGTH] = {
70 /* /vendor/bin/teecd0 */
71 {0x99, 0xa2, 0xf1, 0xb3, 0xa3, 0x5f, 0x3f, 0x11, 0x8b, 0x33, 0xc1, 0x7e, 0xb9, 0xe8, 0x53, 0xbe,
72 0x88, 0xf0, 0xc4, 0x6a, 0xf2, 0x7e, 0x72, 0x6e, 0x91, 0xb7, 0x59, 0xf0, 0x73, 0x9c, 0x93, 0xa5},
73
74 /* /vendor/bin/teec_hello0 */
75 {0x9a, 0xab, 0xac, 0x19, 0xaa, 0xb2, 0xeb, 0xf4, 0x99, 0x11, 0x94, 0x15, 0xee, 0xb0, 0x03, 0x09,
76 0xd6, 0xe8, 0xfe, 0xe9, 0x32, 0x37, 0x48, 0xfd, 0x2b, 0xf2, 0x2c, 0x78, 0x74, 0xd6, 0xc3, 0x9c},
77
78 /* /vendor/bin/tee_test_mem0 */
79 {0x44, 0x7c, 0x8f, 0xc2, 0xa1, 0x1e, 0xfd, 0xab, 0x21, 0x63, 0x0e, 0xf8, 0x7d, 0x0b, 0xce, 0x06,
80 0x05, 0x7f, 0x4a, 0xa8, 0x14, 0x17, 0x0f, 0xef, 0xa6, 0xa5, 0x77, 0x6c, 0xfe, 0xca, 0x4a, 0x8e},
81
82 /* /vendor/bin/tee_test_sess0 */
83 {0xa0, 0xe4, 0x1b, 0x61, 0x8c, 0xd5, 0xf4, 0x4c, 0xec, 0x29, 0x03, 0xcd, 0x2f, 0xce, 0x28, 0xa7,
84 0x67, 0xba, 0x3a, 0x10, 0x20, 0xd7, 0x95, 0x2b, 0x41, 0xaf, 0x47, 0x7c, 0x3d, 0xed, 0xce, 0xa4},
85
86 /* /vendor/bin/tee_test_invoke0 */
87 {0xb5, 0x4e, 0x9d, 0x7b, 0x42, 0x10, 0x63, 0xcc, 0x4b, 0x7b, 0x16, 0x7d, 0xf6, 0xfe, 0xa8, 0x8e,
88 0x6f, 0xca, 0x1b, 0xf1, 0x6a, 0xff, 0xed, 0xfd, 0xee, 0x09, 0xed, 0xbb, 0x18, 0x13, 0x75, 0x02},
89
90 /* /vendor/bin/tee_test_ut0 */
91 {0x45, 0x71, 0xd9, 0x4b, 0x5b, 0xc7, 0xc1, 0x29, 0x2f, 0x9f, 0x46, 0xf2, 0x92, 0xef, 0xd5, 0x44,
92 0xda, 0xb4, 0x51, 0xfb, 0x75, 0xa4, 0xc7, 0x4f, 0x8d, 0x34, 0xca, 0x5e, 0x27, 0xa6, 0x08, 0x8c},
93
94 /* /vendor/bin/tee_test_ca0 */
95 {0xe9, 0x16, 0xde, 0x3f, 0x62, 0x27, 0x5b, 0x12, 0x04, 0x39, 0x9c, 0xc9, 0xf0, 0x34, 0x1f, 0xee,
96 0xf0, 0x1a, 0x66, 0x31, 0xa9, 0xbf, 0x7d, 0x14, 0x30, 0x3d, 0xae, 0xe1, 0xb3, 0x07, 0xb9, 0x54},
97
98 /* /vendor/bin/tee_test_agent0 */
99 {0x20, 0x6f, 0x1c, 0x54, 0xd5, 0x5f, 0xa8, 0xa8, 0x88, 0x56, 0xc4, 0x0c, 0xc3, 0xf9, 0x9c, 0x9a,
100 0xc3, 0x40, 0x86, 0x13, 0x61, 0xb0, 0xcf, 0x69, 0xdd, 0xb8, 0x6c, 0x1e, 0x53, 0xb4, 0x77, 0x55},
101
102 /* /vendor/bin/tee_test_client_api0 */
103 {0xae, 0xe9, 0x12, 0x90, 0x23, 0x9b, 0x99, 0x01, 0x99, 0x1d, 0xa5, 0x22, 0xe0, 0x26, 0x06, 0x12,
104 0x2b, 0xad, 0x5e, 0xaf, 0x34, 0xbf, 0x1a, 0x16, 0x3e, 0x75, 0x97, 0x65, 0xe6, 0x39, 0x9d, 0xf3},
105 };
106
107 typedef struct {
108 TcNsDevFile *devFile;
109 char *fileBuffer;
110 unsigned int fileSize;
111 } LoadImageParams;
112
GetServiceListLock(void)113 mutex_t *GetServiceListLock(void)
114 {
115 return &g_serviceListLock;
116 }
117
GetTcNsDevList(void)118 struct TcNsDevList *GetTcNsDevList(void)
119 {
120 return &g_tcNsDevList;
121 }
122
GetServiceList(void)123 struct list_head *GetServiceList(void)
124 {
125 return &g_serviceList;
126 }
127
GetMemSpace(char ** caCert,char ** tpath)128 static int GetMemSpace(char **caCert, char **tpath)
129 {
130 *tpath = malloc(MAX_PATH_SIZE);
131 if (ZERO_OR_NULL_PTR((unsigned long)(uintptr_t)(*tpath))) {
132 tloge("tpath malloc fail\n");
133 return -EPERM;
134 }
135 *caCert = malloc(BUF_MAX_SIZE);
136 if (ZERO_OR_NULL_PTR((unsigned long)(uintptr_t)(*caCert))) {
137 tloge("caCert malloc fail\n");
138 free(*tpath);
139 *tpath = NULL;
140 return -EPERM;
141 }
142 return 0;
143 }
144
CheckPathAndAccess(LosTaskCB * caTask,char * caCert,unsigned long messageSize,unsigned char * digest,unsigned int digLen)145 static int CheckPathAndAccess(LosTaskCB *caTask,
146 char *caCert, unsigned long messageSize,
147 unsigned char *digest, unsigned int digLen)
148 {
149 int ret;
150 unsigned long index;
151
152 if (digLen != SHA256_DIGEST_LENGTH) {
153 tlogd("check process path digest len error\n");
154 return CHECK_PATH_HASH_FAIL;
155 }
156
157 ret = CalcProcessPathHash((unsigned char *)caCert, messageSize, digest, digLen);
158 if (ret != 0) {
159 return ret;
160 }
161
162 for (index = 0; index < (sizeof(g_arrayCertNativeVendor) / SHA256_DIGEST_LENGTH); index++) {
163 ret = memcmp(digest, g_arrayCertNativeVendor[index], digLen);
164 if (ret == 0) {
165 if (g_teecdTask == NULL && index == TEECD_CERT_INDEX) {
166 g_teecdTask = GetProcessGroupLeader(caTask);
167 }
168 return 0;
169 }
170 }
171 return CHECK_PATH_HASH_FAIL;
172 }
173
CheckProcessAccess(LosTaskCB * caTask)174 static int CheckProcessAccess(LosTaskCB *caTask)
175 {
176 char *caCert = NULL;
177 char *path = NULL;
178 char *tpath = NULL;
179 unsigned char digest[SHA256_DIGEST_LENTH] = {0};
180 int messageSize;
181 int ret;
182
183 if (caTask == NULL) {
184 tloge("task_struct is NULL\n");
185 return -EPERM;
186 }
187
188 if (IsKernelThread(caTask)) {
189 tlogd("kernel thread need not check\n");
190 ret = ENTER_BYPASS_CHANNEL;
191 return ret;
192 }
193
194 ret = GetMemSpace(&caCert, &tpath);
195 if (ret != 0) {
196 return ret;
197 }
198
199 path = GetProcessPath(caTask, tpath, MAX_PATH_SIZE);
200 if (!IS_ERR_OR_NULL(path)) {
201 errno_t sret;
202
203 sret = memset_s(caCert, BUF_MAX_SIZE, 0x00, BUF_MAX_SIZE);
204 if (sret != EOK) {
205 tloge("memset error sret is %d\n", sret);
206 free(tpath);
207 free(caCert);
208 return -EPERM;
209 }
210
211 messageSize = PackCaCert(caCert, path, caTask, GetTaskUid(caTask));
212 if (messageSize > 0) {
213 ret = CheckPathAndAccess(caTask, caCert,
214 (unsigned long)messageSize, digest,
215 (unsigned int)SHA256_DIGEST_LENTH);
216 } else {
217 ret = -EPERM;
218 }
219 } else {
220 ret = -EPERM;
221 }
222 free(tpath);
223 free(caCert);
224 return ret;
225 }
226
227 /* Calculate the SHA256 file digest */
TeeCalcTaskHash(unsigned char * digest,uint32_t digLen,LosTaskCB * curStruct)228 static int TeeCalcTaskHash(unsigned char *digest,
229 uint32_t digLen, LosTaskCB *curStruct)
230 {
231 TeeSha256Context ctx;
232 LosVmSpace *space = OS_PCB_FROM_PID(curStruct->processID)->vmSpace;
233 if (space == NULL) {
234 return -EFAULT;
235 }
236
237 TeeSha256Init(&ctx);
238 /* search the region list */
239 if (space->codeStart != 0 && space->codeEnd > space->codeStart) {
240 TeeSha256Update(&ctx, (void *)space->codeStart, space->codeEnd - space->codeStart);
241 } else {
242 return -EFAULT;
243 }
244 TeeSha256Final(&ctx, digest);
245 return 0;
246 }
247
248 #define LIBTEEC_CODE_PAGE_SIZE 8
249 #define DEFAULT_TEXT_OFF 0
250 #define LIBTEEC_NAME_MAX_LEN 50
251
252 #define LIBTEEC_SO "/vendor/lib/libteec_vendor.so"
253
254 /* Calculate the SHA256 library digest */
TeeCalcTaskSoHash(unsigned char * digest,uint32_t digLen,LosTaskCB * curStruct,int soIndex)255 static int TeeCalcTaskSoHash(unsigned char *digest, uint32_t digLen,
256 LosTaskCB *curStruct, int soIndex)
257 {
258 TeeSha256Context ctx;
259 int findFlag = 0;
260 LosRbNode *pstRbNode = NULL;
261 LosRbNode *pstRbNodeNext = NULL;
262 LosVmSpace *space = OS_PCB_FROM_PID(curStruct->processID)->vmSpace;
263 if (space == NULL) {
264 return -EFAULT;
265 }
266
267 TeeSha256Init(&ctx);
268 /* search the region list */
269 (VOID)LOS_MuxAcquire(&space->regionMux);
270 RB_SCAN_SAFE(&space->regionRbTree, pstRbNode, pstRbNodeNext)
271 LosVmMapRegion *region = (LosVmMapRegion *)pstRbNode;
272 if (!LOS_IsRegionFileValid(region)) {
273 continue;
274 }
275 struct Vnode *vnode = region->unTypeData.rf.vnode;
276 if (vnode != NULL && !strncmp(vnode->filePath, LIBTEEC_SO, strlen(LIBTEEC_SO))) {
277 TeeSha256Update(&ctx, (void *)region->range.base, region->range.size);
278 findFlag = 1;
279 break;
280 }
281 RB_SCAN_SAFE_END(&space->regionRbTree, pstRbNode, pstRbNodeNext)
282 (VOID)LOS_MuxRelease(&space->regionMux);
283
284 if (findFlag == 0) {
285 return -EFAULT;
286 }
287 TeeSha256Final(&ctx, digest);
288 return 0;
289 }
290
291 /* Modify the client context so params id 2 and 3 contain temp pointers to the
292 * public key and package name for the open session. This is used for the
293 * TEEC_LOGIN_IDENTIFY open session method
294 */
SetLoginInformation(TcNsDevFile * devFile,TcNsClientContext * context)295 static int SetLoginInformation(TcNsDevFile *devFile,
296 TcNsClientContext *context)
297 {
298 /* The daemon has failed to get login information or not supplied */
299 if (devFile->pkgNameLen == 0) {
300 return -1;
301 }
302 /* The 3rd parameter buffer points to the pkg name buffer in the
303 * device file pointer
304 * get package name len and package name
305 */
306 context->params[TEE_PARAM_FOUR].memref.sizeAddr =
307 (uintptr_t)&devFile->pkgNameLen;
308 context->params[TEE_PARAM_FOUR].memref.buffer =
309 (uintptr_t)devFile->PkgName;
310 /* Set public key len and public key */
311 if (devFile->pubKeyLen != 0) {
312 context->params[TEE_PARAM_THREE].memref.sizeAddr =
313 (uintptr_t)&devFile->pubKeyLen;
314 context->params[TEE_PARAM_THREE].memref.buffer =
315 (uintptr_t)devFile->pubKey;
316 } else {
317 /* If get public key failed, then get uid in kernel */
318 uint32_t caUid = TcNsGetUid();
319 if (caUid == (uint32_t)(-1)) {
320 tloge("Failed to get uid of the task\n");
321 goto error;
322 }
323
324 devFile->pubKeyLen = sizeof(caUid);
325 context->params[TEE_PARAM_THREE].memref.sizeAddr =
326 (uintptr_t)&devFile->pubKeyLen;
327 if (memcpy_s(devFile->pubKey, MAX_PUBKEY_LEN, &caUid,
328 devFile->pubKeyLen)) {
329 tloge("Failed to copy pubkey, pubKeyLen=%u\n",
330 devFile->pubKeyLen);
331 goto error;
332 }
333 context->params[TEE_PARAM_THREE].memref.buffer =
334 (uint64_t)(uintptr_t)devFile->pubKey;
335 }
336 /* Now we mark the 2 parameters as input temp buffers */
337 context->paramTypes = TEEC_PARAM_TYPES(
338 TEEC_PARAM_TYPE_GET(context->paramTypes, TEE_PARAM_ONE),
339 TEEC_PARAM_TYPE_GET(context->paramTypes, TEE_PARAM_TWO),
340 TEEC_MEMREF_TEMP_INPUT, TEEC_MEMREF_TEMP_INPUT);
341 return 0;
342 error:
343 return -1;
344 }
345
CheckProcessAndAllocParams(TcNsDevFile * devFile,uint8_t ** certBuffer,unsigned int * certBufferSize)346 static int CheckProcessAndAllocParams(TcNsDevFile *devFile,
347 uint8_t **certBuffer, unsigned int *certBufferSize)
348 {
349 int ret;
350
351 #ifdef SECURITY_AUTH_ENHANCE
352 ret = CheckProcessAccess(OsCurrTaskGet());
353 if (ret) {
354 tloge(KERN_ERR "tc client login: teecd verification failed ret 0x%x!\n", ret);
355 return -EPERM;
356 }
357 #endif
358 mutex_lock(&devFile->LoginSetupLock);
359 if (devFile->loginSetup) {
360 tloge("Login information cannot be set twice!\n");
361 mutex_unlock(&devFile->LoginSetupLock);
362 return -EINVAL;
363 }
364 devFile->loginSetup = true;
365 mutex_unlock(&devFile->LoginSetupLock);
366
367 unsigned int bufSize = (unsigned int)(MAX_PACKAGE_NAME_LEN + MAX_PUBKEY_LEN +
368 sizeof(devFile->pkgNameLen) + sizeof(devFile->pubKeyLen));
369 *certBuffer = malloc(bufSize);
370 if (ZERO_OR_NULL_PTR((unsigned long)(uintptr_t)(*certBuffer))) {
371 tloge("Failed to allocate login buffer!");
372 return -EFAULT;
373 }
374 *certBufferSize = bufSize;
375
376 return 0;
377 }
378
TcNsGetTeeVersion(const TcNsDevFile * devFile,void * argp)379 static int TcNsGetTeeVersion(const TcNsDevFile *devFile, void *argp)
380 {
381 unsigned int version;
382 TcNsSmcCmd smcCmd = { {0}, 0 };
383 int smcRet;
384 struct MbCmdPack *mbPack = NULL;
385
386 if (argp == NULL || devFile == NULL) {
387 tloge("error input parameter\n");
388 return -1;
389 }
390 mbPack = MailboxAllocCmdPack();
391 if (mbPack == NULL) {
392 tloge("alloc mb pack failed\n");
393 return -ENOMEM;
394 }
395
396 mbPack->operation.paramTypes = TEEC_VALUE_OUTPUT;
397 smcCmd.globalCmd = true;
398 smcCmd.cmdId = GLOBAL_CMD_ID_GET_TEE_VERSION;
399 smcCmd.devFileId = devFile->devFileId;
400 smcCmd.operationPhys = LOS_PaddrQuery(&mbPack->operation);
401 smcCmd.operationHphys = 0;
402 smcRet = TcNsSmc(&smcCmd);
403 if (smcRet != 0) {
404 tloge("smc_call returns error ret 0x%x\n", smcRet);
405 }
406
407 version = mbPack->operation.params[0].value.a;
408 if (copy_to_user(argp, &version, sizeof(unsigned int))) {
409 if (smcRet != 0) {
410 smcRet = -EFAULT;
411 }
412 }
413 MailboxFree(mbPack);
414 return smcRet;
415 }
416
417 #define MAX_BUF_LEN 4096
418
TcNsClientLogWithoutCert(TcNsDevFile * devFile)419 static int TcNsClientLogWithoutCert(TcNsDevFile *devFile)
420 {
421 int ret;
422 uint8_t *certBuffer = NULL;
423 uint8_t *tempCertBuffer = NULL;
424 errno_t sret;
425 unsigned int certBufferSize = 0;
426 char *path = NULL;
427
428 ret = CheckProcessAndAllocParams(devFile, &certBuffer,
429 &certBufferSize);
430 if (ret != 0) {
431 return ret;
432 }
433 tempCertBuffer = certBuffer;
434
435 path = GetProcessPath(OsCurrTaskGet(), (char *)certBuffer, MAX_PACKAGE_NAME_LEN);
436 if (path == NULL) {
437 goto error;
438 }
439 devFile->pkgNameLen = strlen(path);
440
441 sret = strncpy_s((char *)devFile->PkgName, MAX_PACKAGE_NAME_LEN, (char *)certBuffer,
442 devFile->pkgNameLen);
443 if (sret != EOK) {
444 ret = -ENOMEM;
445 goto error;
446 }
447 int uid = GetTaskUid(OsCurrTaskGet());
448 devFile->pubKeyLen = sizeof(uid);
449 if (memcpy_s((char *)devFile->pubKey, MAX_PUBKEY_LEN, (char *)&uid,
450 devFile->pubKeyLen)) {
451 tloge("Failed to copy cert, pubKeyLen=%u\n",
452 devFile->pubKeyLen);
453 ret = -EINVAL;
454 goto error;
455 }
456 error:
457 free(tempCertBuffer);
458 return ret;
459 }
460
TcNsClientLogWithCert(TcNsDevFile * devFile,const void * buffer)461 static int TcNsClientLogWithCert(TcNsDevFile *devFile, const void *buffer)
462 {
463 int ret;
464 uint8_t *certBuffer = NULL;
465 uint8_t *tempCertBuffer = NULL;
466 errno_t sret;
467 unsigned int certBufferSize = 0;
468
469 // application ca login
470 ret = CheckProcessAndAllocParams(devFile, &certBuffer,
471 &certBufferSize);
472 if (ret != 0) {
473 return ret;
474 }
475
476 tempCertBuffer = certBuffer;
477 if (certBufferSize > MAX_BUF_LEN) {
478 tloge("cert buffer size is invalid!\n");
479 ret = -EINVAL;
480 goto error;
481 }
482
483 if (copy_from_user(certBuffer, buffer, certBufferSize)) {
484 tloge("Failed to get user login info!\n");
485 ret = -EINVAL;
486 goto error;
487 }
488 /* get package name len */
489 ret = GetPackNameLen(devFile, certBuffer, certBufferSize);
490 if (ret != 0) {
491 goto error;
492 }
493 certBuffer += sizeof(devFile->pkgNameLen);
494
495 /* get package name */
496 sret = strncpy_s((char *)devFile->PkgName, MAX_PACKAGE_NAME_LEN, (char *)certBuffer, devFile->pkgNameLen);
497 if (sret != EOK) {
498 ret = -ENOMEM;
499 goto error;
500 }
501 certBuffer += devFile->pkgNameLen;
502
503 /* get public key len */
504 ret = GetPublicKeyLen(devFile, certBuffer, certBufferSize);
505 if (ret != 0) {
506 goto error;
507 }
508
509 /* get public key */
510 if (devFile->pubKeyLen != 0) {
511 certBuffer += sizeof(devFile->pubKeyLen);
512 if (memcpy_s((char *)devFile->pubKey, MAX_PUBKEY_LEN, (char *)certBuffer, devFile->pubKeyLen)) {
513 tloge("Failed to copy cert, pubKeyLen=%u\n", devFile->pubKeyLen);
514 ret = -EINVAL;
515 goto error;
516 }
517 certBuffer += devFile->pubKeyLen;
518 }
519 ret = 0;
520 error:
521 free(tempCertBuffer);
522 return ret;
523 }
524
TcNsClientLoginFunc(TcNsDevFile * devFile,const void * buffer)525 static int TcNsClientLoginFunc(TcNsDevFile *devFile,
526 const void *buffer)
527 {
528 if (buffer == NULL) {
529 return TcNsClientLogWithoutCert(devFile);
530 } else {
531 return TcNsClientLogWithCert(devFile, buffer);
532 }
533 }
534
AllocForLoadImage(unsigned int * mbLoadSize,unsigned int fileSize,char ** mbLoadMem,struct MbCmdPack ** mbPack,TeecUuid ** uuidReturn)535 static int AllocForLoadImage(unsigned int *mbLoadSize,
536 unsigned int fileSize, char **mbLoadMem,
537 struct MbCmdPack **mbPack, TeecUuid **uuidReturn)
538 {
539 /* we will try any possible to alloc mailbox mem to load TA */
540 for (; *mbLoadSize > 0; *mbLoadSize >>= 1) {
541 *mbLoadMem = MailboxAlloc(*mbLoadSize, 0);
542 if (*mbLoadMem != NULL) {
543 break;
544 }
545 tlogw("alloc mem(size=%u) for TA load mem fail, will retry\n", *mbLoadSize);
546 }
547 if (*mbLoadMem == NULL) {
548 tloge("alloc TA load mem failed\n");
549 return -ENOMEM;
550 }
551 *mbPack = MailboxAllocCmdPack();
552 if (*mbPack == NULL) {
553 MailboxFree(*mbLoadMem);
554 *mbLoadMem = NULL;
555 tloge("alloc mb pack failed\n");
556 return -ENOMEM;
557 }
558 *uuidReturn = MailboxAlloc(sizeof(TeecUuid), 0);
559 if (*uuidReturn == NULL) {
560 MailboxFree(*mbLoadMem);
561 *mbLoadMem = NULL;
562 MailboxFree(*mbPack);
563 *mbPack = NULL;
564 tloge("alloc uuid failed\n");
565 return -ENOMEM;
566 }
567 return 0;
568 }
569
PackDataForSmcCmd(uint32_t loadSize,const char * mbLoadMem,struct MbCmdPack * mbPack,TeecUuid * uuidReturn,TcNsSmcCmd * smcCmd)570 static void PackDataForSmcCmd(uint32_t loadSize,
571 const char *mbLoadMem, struct MbCmdPack *mbPack,
572 TeecUuid *uuidReturn, TcNsSmcCmd *smcCmd)
573 {
574 mbPack->operation.params[TEE_PARAM_ONE].memref.buffer =
575 LOS_PaddrQuery((void *)mbLoadMem);
576 mbPack->operation.bufferHaddr[TEE_PARAM_ONE] = 0;
577 mbPack->operation.params[TEE_PARAM_ONE].memref.size = loadSize + sizeof(int);
578 mbPack->operation.params[TEE_PARAM_THREE].memref.buffer =
579 LOS_PaddrQuery((void *)uuidReturn);
580 mbPack->operation.bufferHaddr[TEE_PARAM_THREE] = 0;
581 mbPack->operation.params[TEE_PARAM_THREE].memref.size = sizeof(*uuidReturn);
582 mbPack->operation.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INOUT,
583 TEEC_VALUE_OUTPUT, TEEC_MEMREF_TEMP_OUTPUT, TEEC_VALUE_INPUT);
584 /* load image smc command */
585 smcCmd->globalCmd = true;
586 smcCmd->cmdId = GLOBAL_CMD_ID_LOAD_SECURE_APP;
587 smcCmd->contextId = 0;
588 smcCmd->operationPhys = LOS_PaddrQuery(&mbPack->operation);
589 smcCmd->operationHphys = 0;
590 }
591
592 struct MbLoad {
593 unsigned int mbLoadSize;
594 char *mbLoadMem;
595 };
596
LoadImageByFrame(const LoadImageParams * paramsIn,struct MbLoad * mb,struct MbCmdPack * mbPack,TeecUuid * uuidReturn,unsigned int loadTimes)597 static int LoadImageByFrame(const LoadImageParams *paramsIn,
598 struct MbLoad *mb, struct MbCmdPack *mbPack, TeecUuid *uuidReturn,
599 unsigned int loadTimes)
600 {
601 char *p = mb->mbLoadMem;
602 uint32_t loadSize;
603 int loadFlag = 1; /* 0:it's last block, 1:not last block */
604 uint32_t loadedSize = 0;
605 unsigned int index;
606 TcNsSmcCmd smcCmd = { {0}, 0 };
607 int smcRet;
608
609 for (index = 0; index < loadTimes; index++) {
610 if (index == (loadTimes - 1)) {
611 loadFlag = 0;
612 loadSize = paramsIn->fileSize - loadedSize;
613 } else {
614 loadSize = mb->mbLoadSize - sizeof(loadFlag);
615 }
616 *(int *)p = loadFlag;
617 if (loadSize > mb->mbLoadSize - sizeof(loadFlag)) {
618 tloge("invalid load size %u/%u\n", loadSize,
619 mb->mbLoadSize);
620 return -1;
621 }
622 if (copy_from_user(mb->mbLoadMem + sizeof(loadFlag),
623 (void __user *)(paramsIn->fileBuffer +
624 loadedSize), loadSize)) {
625 tloge("file buf get fail\n");
626 return -1;
627 }
628 PackDataForSmcCmd(loadSize, mb->mbLoadMem, mbPack,
629 uuidReturn, &smcCmd);
630 mbPack->operation.params[TEE_PARAM_FOUR].value.a = index;
631 smcCmd.devFileId = paramsIn->devFile->devFileId;
632 smcRet = TcNsSmc(&smcCmd);
633 tlogd("smc cmd ret %d\n", smcRet);
634 tlogd("configid=%u, ret=%d, loadFlag=%d, index=%u\n",
635 mbPack->operation.params[1].value.a, smcRet,
636 loadFlag, index);
637
638 if (smcRet != 0) {
639 tloge("smc_call returns error ret 0x%x\n", smcRet);
640 return -1;
641 }
642
643 loadedSize += loadSize;
644 }
645 return 0;
646 }
647
TcNsLoadImage(TcNsDevFile * devFile,char * fileBuffer,unsigned int fileSize)648 int TcNsLoadImage(TcNsDevFile *devFile, char *fileBuffer,
649 unsigned int fileSize)
650 {
651 int ret;
652 struct MbCmdPack *mbPack = NULL;
653 unsigned int mbLoadSize;
654 char *mbLoadMem = NULL;
655 TeecUuid *uuidReturn = NULL;
656 unsigned int loadTimes;
657 LoadImageParams paramsIn = {devFile, fileBuffer, fileSize};
658 bool checkValue = false;
659
660 checkValue = (devFile == NULL || fileBuffer == NULL);
661 if (checkValue) {
662 tloge("devFile or fileBuffer is NULL!\n");
663 return -EINVAL;
664 }
665 if (!IsValidTaSize(fileBuffer, fileSize)) {
666 return -EINVAL;
667 }
668
669 mbLoadSize = (fileSize > (SZ_1M - sizeof(int))) ? SZ_1M : ALIGN(fileSize, SZ_4K);
670
671 ret = AllocForLoadImage(&mbLoadSize, fileSize, &mbLoadMem,
672 &mbPack, &uuidReturn);
673 if (ret != 0) {
674 return ret;
675 }
676
677 if (mbLoadSize <= sizeof(int)) {
678 tloge("mbLoadSize is too small!\n");
679 ret = -ENOMEM;
680 goto FREE_MEM;
681 }
682
683 loadTimes = fileSize / (mbLoadSize - sizeof(int));
684 if (fileSize % (mbLoadSize - sizeof(int))) {
685 loadTimes += 1;
686 }
687 struct MbLoad mb;
688 mb.mbLoadMem = mbLoadMem;
689 mb.mbLoadSize = mbLoadSize;
690 ret = LoadImageByFrame(¶msIn, &mb, mbPack, uuidReturn, loadTimes);
691 FREE_MEM:
692 MailboxFree(mbLoadMem);
693 MailboxFree(mbPack);
694 MailboxFree(uuidReturn);
695 return ret;
696 }
697
CheckTaskState(LosTaskCB ** halStruct,const TcNsClientContext * context)698 static int CheckTaskState(LosTaskCB **halStruct,
699 const TcNsClientContext *context)
700 {
701 bool checkValue = false;
702
703 checkValue = (context->callingPid && !IsKernelThread(OsCurrTaskGet()));
704 if (checkValue == true) {
705 tloge("non hal service pass non-zero callingpid , reject please!!!\n");
706 return -EFAULT;
707 }
708 return 0;
709 }
710
CalcTaskHash(uint8_t kernelApi,TcNsSession * session,TcNsService * service,LosTaskCB * curStruct)711 static int CalcTaskHash(uint8_t kernelApi,
712 TcNsSession *session, TcNsService *service,
713 LosTaskCB *curStruct)
714 {
715 int rc, i;
716 int soFound = 0;
717 if (kernelApi == TEE_REQ_FROM_USER_MODE) {
718 for (i = 0; soFound < NUM_OF_SO && i < KIND_OF_SO; i++) {
719 rc = TeeCalcTaskSoHash(session->authHashBuf + MAX_SHA_256_SZ * soFound,
720 (uint32_t)SHA256_DIGEST_LENTH, curStruct, i);
721 if (rc == 0) {
722 soFound++;
723 }
724 }
725 if (soFound != NUM_OF_SO) {
726 tlogd("so library found: %d\n", soFound);
727 }
728 } else {
729 tlogd("request from kernel\n");
730 }
731
732 #ifdef CONFIG_ASAN_DEBUG
733 tloge("so auth disabled for ASAN debug\n");
734 uint32_t soHashLen = MAX_SHA_256_SZ * NUM_OF_SO;
735 errno_t sret = memset_s(session->authHashBuf, soHashLen, 0, soHashLen);
736 if (sret != EOK) {
737 tloge("memset so hash failed\n");
738 return -EFAULT;
739 }
740 #endif
741 rc = TeeCalcTaskHash(session->authHashBuf + MAX_SHA_256_SZ * NUM_OF_SO,
742 (uint32_t)SHA256_DIGEST_LENTH, curStruct);
743 if (rc != 0) {
744 tloge("tee calc ca hash failed\n");
745 return -EFAULT;
746 }
747 return 0;
748 }
749
CheckLoginMethod(TcNsDevFile * devFile,TcNsClientContext * context,uint8_t * flags)750 static int CheckLoginMethod(TcNsDevFile *devFile,
751 TcNsClientContext *context, uint8_t *flags)
752 {
753 bool checkValue = false;
754 int ret;
755
756 if (devFile == NULL || context == NULL || flags == NULL) {
757 return -EFAULT;
758 }
759 if (context->login.method == TEEC_LOGIN_IDENTIFY) {
760 tlogd("login method is IDENTIFY\n");
761 /* Check if params 0 and 1 are valid */
762 checkValue = devFile->kernelApi == TEE_REQ_FROM_USER_MODE &&
763 (TcUserParamValid(context, (unsigned int)TEE_PARAM_ONE) ||
764 TcUserParamValid(context, (unsigned int)TEE_PARAM_TWO));
765 if (checkValue == true) {
766 return -EFAULT;
767 }
768 ret = SetLoginInformation(devFile, context);
769 if (ret != 0) {
770 tloge("SetLoginInformation failed ret =%d\n", ret);
771 return ret;
772 }
773 *flags |= TC_CALL_LOGIN;
774 } else {
775 tlogd("login method is not supported\n");
776 return -EINVAL;
777 }
778 return 0;
779 }
780
FindService(TcNsDevFile * devFile,const TcNsClientContext * context)781 static TcNsService *FindService(TcNsDevFile *devFile,
782 const TcNsClientContext *context)
783 {
784 int ret;
785 TcNsService *service = NULL;
786 bool isNewService = false;
787 bool isFull = false;
788
789 mutex_lock(&devFile->serviceLock);
790 service = TcRefServiceInDev(devFile, context->uuid,
791 UUID_LEN, &isFull);
792 /* if service has been opened in this dev or ref cnt is full */
793 if (service != NULL || isFull == true) {
794 /* If service has been reference by this dev, TcFindServiceInDev
795 * will increase a ref count to declaim there's how many callers to
796 * this service from the devFile, instead of increase service->usage.
797 * While close session, dev->serviceRef[i] will decrease and till
798 * it get to 0 PutServiceStruct will be called.
799 */
800 mutex_unlock(&devFile->serviceLock);
801 return service;
802 }
803 mutex_lock(&g_serviceListLock);
804 service = TcFindServiceFromAll(context->uuid, (uint32_t)UUID_LEN);
805 /* if service has been opened in other dev */
806 if (service != NULL) {
807 GetServiceStruct(service);
808 mutex_unlock(&g_serviceListLock);
809 goto ADD_SERVICE;
810 }
811 /* Create a new service if we couldn't find it in list */
812 ret = TcNsServiceInit(context->uuid, (uint32_t)UUID_LEN, &service);
813 /* Put unlock after TcNsServiceInit to make sure TcFindServiceFromAll * is correct */
814 mutex_unlock(&g_serviceListLock);
815 if (ret) {
816 tloge("service init failed");
817 mutex_unlock(&devFile->serviceLock);
818 return NULL;
819 }
820 isNewService = true;
821 ADD_SERVICE:
822 ret = AddServiceToDev(devFile, service);
823 mutex_unlock(&devFile->serviceLock);
824 if (ret) {
825 if (isNewService) {
826 PutServiceStruct(service);
827 }
828 service = NULL;
829 tloge("fail to add service to dev\n");
830 return NULL;
831 }
832 return service;
833 }
834
ProcCalcTaskHash(TcNsDevFile * devFile,TcNsClientContext * context,TcNsSession * session,TcNsService * service,uint8_t * flags)835 static int ProcCalcTaskHash(TcNsDevFile *devFile,
836 TcNsClientContext *context, TcNsSession *session,
837 TcNsService *service, uint8_t *flags)
838 {
839 int ret;
840 LosTaskCB *curStruct = NULL;
841 LosTaskCB *halStruct = NULL;
842
843 ret = CheckLoginMethod(devFile, context, flags);
844 if (ret != 0) {
845 return ret;
846 }
847 context->cmdId = GLOBAL_CMD_ID_OPEN_SESSION;
848 mutex_init(&session->taSessionLock);
849
850 ret = CheckTaskState(&halStruct, context);
851 if (ret != 0) {
852 return ret;
853 }
854 if (halStruct != NULL) {
855 curStruct = halStruct;
856 } else {
857 curStruct = OsCurrTaskGet();
858 }
859 /* lock reason:
860 * TeeCalcTaskHash will use the global value g_tee_shash_tfm
861 */
862 ret = CalcTaskHash(devFile->kernelApi, session, service, curStruct);
863 return ret;
864 }
865
ProcAfterSmcCmd(TcNsDevFile * devFile,const TcNsClientContext * context,TcNsService * service,TcNsSession * session)866 static void ProcAfterSmcCmd(TcNsDevFile *devFile,
867 const TcNsClientContext *context, TcNsService *service,
868 TcNsSession *session)
869 {
870 session->sessionId = context->sessionId;
871 #ifdef TC_ASYNC_NOTIFY_SUPPORT
872 session->waitData.sendWaitFlag = 0;
873 init_waitqueue_head(&session->waitData.sendCmdWq);
874 #endif
875 atomic_set(&session->usage, 1);
876 session->owner = devFile;
877 mutex_lock(&service->SessionLock);
878 list_add_tail(&session->head, &service->sessionList);
879 mutex_unlock(&service->SessionLock);
880 }
881
ProcOpenSession(TcNsDevFile * devFile,TcNsClientContext * context,TcNsService * service,TcNsSession * session,uint8_t flags)882 static int ProcOpenSession(TcNsDevFile *devFile,
883 TcNsClientContext *context, TcNsService *service,
884 TcNsSession *session, uint8_t flags)
885 {
886 int ret;
887
888 mutex_lock(&service->operationLock);
889 ret = LoadTaImage(devFile, context);
890 if (ret != 0) {
891 tloge("load ta image failed\n");
892 mutex_unlock(&service->operationLock);
893 return ret;
894 }
895 /* send smc */
896 #ifdef SECURITY_AUTH_ENHANCE
897 ret = GetSessionSecureParams(devFile, context, session);
898 if (ret) {
899 tloge("Get session secure parameters failed, ret = %d.\n", ret);
900 /* Clean this session secure information */
901 CleanSessionSecureInformation(session);
902 mutex_unlock(&service->operationLock);
903 return ret;
904 }
905 session->TcNsToken.tokenBuffer =
906 calloc(1, TOKEN_BUFFER_LEN);
907 session->TcNsToken.tokenLen = TOKEN_BUFFER_LEN;
908 if (ZERO_OR_NULL_PTR((unsigned long)(uintptr_t)
909 session->TcNsToken.tokenBuffer)) {
910 tloge("calloc %d bytes token failed.\n", TOKEN_BUFFER_LEN);
911 /* Clean this session secure information */
912 CleanSessionSecureInformation(session);
913 mutex_unlock(&service->operationLock);
914 return -ENOMEM;
915 }
916 ret = TcClientCall(context, devFile, session, flags);
917 if (ret != 0) {
918 /* Clean this session secure information */
919 CleanSessionSecureInformation(session);
920 }
921 #else
922 ret = TcClientCall(context, devFile, session, flags);
923 #endif
924 if (ret != 0) {
925 mutex_unlock(&service->operationLock);
926 tloge("smc_call returns error, ret=0x%x\n", ret);
927 return ret;
928 }
929 ProcAfterSmcCmd(devFile, context, service, session);
930 /* sessionId in tee is unique, but in concurrency scene
931 * same sessionId may appear in tzdriver, put sessionList
932 * add/del in service->operationLock can avoid it.
933 */
934 mutex_unlock(&service->operationLock);
935 return ret;
936 }
937
ProcErrorSituation(TcNsDevFile * devFile,TcNsClientContext * context,TcNsService * service,TcNsSession * session)938 static void ProcErrorSituation(TcNsDevFile *devFile,
939 TcNsClientContext *context, TcNsService *service,
940 TcNsSession *session)
941 {
942 ReleaseFreeSession(devFile, context, session);
943 mutex_lock(&devFile->serviceLock);
944 DelServiceFromDev(devFile, service);
945 mutex_unlock(&devFile->serviceLock);
946 free(session);
947 return;
948 }
949
TcNsOpenSession(TcNsDevFile * devFile,TcNsClientContext * context)950 int TcNsOpenSession(TcNsDevFile *devFile,
951 TcNsClientContext *context)
952 {
953 int ret;
954 TcNsService *service = NULL;
955 TcNsSession *session = NULL;
956 uint8_t flags = TC_CALL_GLOBAL;
957 bool checkValue = (devFile == NULL || context == NULL);
958
959 if (checkValue == true) {
960 tloge("invalid devFile or context\n");
961 return -EINVAL;
962 }
963
964 ret = CheckProcessAccess(OsCurrTaskGet());
965 if (ret) {
966 tloge("tee driver fd may be leak\n");
967 return -EPERM;
968 }
969
970 service = FindService(devFile, context);
971 if (service == NULL) {
972 tloge("find service failed\n");
973 return -ENOMEM;
974 }
975 session = calloc(1, sizeof(*session));
976 if (ZERO_OR_NULL_PTR((unsigned long)(uintptr_t)session)) {
977 tloge("calloc failed\n");
978 mutex_lock(&devFile->serviceLock);
979 DelServiceFromDev(devFile, service);
980 mutex_unlock(&devFile->serviceLock);
981 return -ENOMEM;
982 }
983
984 ret = ProcCalcTaskHash(devFile, context, session, service,
985 &flags);
986 if (ret != 0) {
987 goto error;
988 }
989 ret = ProcOpenSession(devFile, context, service, session, flags);
990 if (ret == 0) {
991 return ret;
992 }
993 error:
994 ProcErrorSituation(devFile, context, service, session);
995 return ret;
996 }
997
GetService(TcNsDevFile * devFile,const TcNsClientContext * context)998 static TcNsService *GetService(TcNsDevFile *devFile,
999 const TcNsClientContext *context)
1000 {
1001 TcNsService *service = NULL;
1002
1003 mutex_lock(&devFile->serviceLock);
1004 service = TcFindServiceInDev(devFile,
1005 context->uuid, UUID_LEN);
1006 GetServiceStruct(service);
1007 mutex_unlock(&devFile->serviceLock);
1008 return service;
1009 }
1010
PutSessionStruct(struct TagTcNsSession * session)1011 void PutSessionStruct(struct TagTcNsSession *session)
1012 {
1013 if (session == NULL || !atomic_dec_and_test(&session->usage)) {
1014 return;
1015 }
1016
1017 #ifdef SECURITY_AUTH_ENHANCE
1018 if (session->TcNsToken.tokenBuffer != NULL) {
1019 if (memset_s(
1020 (void *)session->TcNsToken.tokenBuffer,
1021 session->TcNsToken.tokenLen,
1022 0,
1023 session->TcNsToken.tokenLen) != EOK) {
1024 tloge("Caution, memset failed!\n");
1025 }
1026 free(session->TcNsToken.tokenBuffer);
1027 session->TcNsToken.tokenBuffer = NULL;
1028 (void)session->TcNsToken.tokenBuffer; /* avoid Codex warning */
1029 }
1030 #endif
1031 if (memset_s((void *)session, sizeof(*session), 0, sizeof(*session)) != EOK) {
1032 tloge("Caution, memset failed!\n");
1033 }
1034 free(session);
1035 }
1036
GetSession(TcNsService * service,TcNsDevFile * devFile,const TcNsClientContext * context)1037 static TcNsSession *GetSession(TcNsService *service,
1038 TcNsDevFile *devFile, const TcNsClientContext *context)
1039 {
1040 TcNsSession *session = NULL;
1041
1042 mutex_lock(&service->SessionLock);
1043 session = TcFindSessionWithOwner(&service->sessionList,
1044 context->sessionId, devFile);
1045 GetSessionStruct(session);
1046 mutex_unlock(&service->SessionLock);
1047 return session;
1048 }
1049
GetServiceStruct(struct TagTcNsService * service)1050 void GetServiceStruct(struct TagTcNsService *service)
1051 {
1052 if (service != NULL) {
1053 atomic_inc(&service->usage);
1054 tlogd("service->usage = %d\n", atomic_read(&service->usage));
1055 }
1056 }
1057
PutServiceStruct(struct TagTcNsService * service)1058 void PutServiceStruct(struct TagTcNsService *service)
1059 {
1060 if (service != NULL) {
1061 tlogd("service->usage = %d\n", atomic_read(&service->usage));
1062 mutex_lock(&g_serviceListLock);
1063 if (atomic_dec_and_test(&service->usage)) {
1064 tlogd("del service [0x%x] from service list\n",
1065 *(uint32_t *)service->uuid);
1066 list_del(&service->head);
1067 free(service);
1068 }
1069 mutex_unlock(&g_serviceListLock);
1070 }
1071 }
1072
TcNsCloseSession(TcNsDevFile * devFile,TcNsClientContext * context)1073 int TcNsCloseSession(TcNsDevFile *devFile,
1074 TcNsClientContext *context)
1075 {
1076 int ret = -EINVAL;
1077 errno_t ret_err;
1078 TcNsService *service = NULL;
1079 TcNsSession *session = NULL;
1080
1081 if (devFile == NULL || context == NULL) {
1082 tloge("invalid devFile or context\n");
1083 return ret;
1084 }
1085 service = GetService(devFile, context);
1086 if (service == NULL) {
1087 tloge("invalid service\n");
1088 return ret;
1089 }
1090 /*
1091 * sessionId in tee is unique, but in concurrency scene
1092 * same sessionId may appear in tzdriver, put sessionList
1093 * add/del in service->operationLock can avoid it.
1094 */
1095 mutex_lock(&service->operationLock);
1096 session = GetSession(service, devFile, context);
1097 if (session != NULL) {
1098 int ret2;
1099 mutex_lock(&session->taSessionLock);
1100 ret2 = CloseSession(devFile, session, context->uuid,
1101 (unsigned int)UUID_LEN, context->sessionId);
1102 mutex_unlock(&session->taSessionLock);
1103 if (ret2 != TEEC_SUCCESS) {
1104 tloge("close session smc failed!\n");
1105 }
1106 #ifdef SECURITY_AUTH_ENHANCE
1107 /* Clean this session secure information */
1108 ret_err = memset_s((void *)&session->secureInfo,
1109 sizeof(session->secureInfo),
1110 0, sizeof(session->secureInfo));
1111 if (ret_err != EOK) {
1112 tloge("close session memset error=%d\n", ret_err);
1113 }
1114 #endif
1115 mutex_lock(&service->SessionLock);
1116 list_del(&session->head);
1117 mutex_unlock(&service->SessionLock);
1118
1119 PutSessionStruct(session);
1120 PutSessionStruct(session); /* pair with open session */
1121
1122 ret = TEEC_SUCCESS;
1123 mutex_lock(&devFile->serviceLock);
1124 DelServiceFromDev(devFile, service);
1125 mutex_unlock(&devFile->serviceLock);
1126 } else {
1127 tloge("invalid session\n");
1128 }
1129 mutex_unlock(&service->operationLock);
1130 PutServiceStruct(service);
1131 return ret;
1132 }
1133
TcNsSendCmd(TcNsDevFile * devFile,TcNsClientContext * context)1134 int TcNsSendCmd(TcNsDevFile *devFile,
1135 TcNsClientContext *context)
1136 {
1137 int ret = -EINVAL;
1138 TcNsService *service = NULL;
1139 TcNsSession *session = NULL;
1140 bool checkValue = (devFile == NULL || context == NULL);
1141
1142 if (checkValue == true) {
1143 tloge("invalid devFile or context\n");
1144 return ret;
1145 }
1146 tlogd("session id :%x\n", context->sessionId);
1147 service = GetService(devFile, context);
1148 /* check sessionid is validated or not */
1149 if (service != NULL) {
1150 session = GetSession(service, devFile, context);
1151 PutServiceStruct(service);
1152 if (session != NULL) {
1153 tlogd("send cmd find session id %x\n",
1154 context->sessionId);
1155 goto FIND_SESSION;
1156 }
1157 } else {
1158 tloge("can't find service\n");
1159 }
1160 tloge("send cmd can not find session id %u\n", context->sessionId);
1161 return ret;
1162 FIND_SESSION:
1163 /* send smc */
1164 mutex_lock(&session->taSessionLock);
1165 ret = TcClientCall(context, devFile, session, 0);
1166 mutex_unlock(&session->taSessionLock);
1167 PutSessionStruct(session);
1168 if (ret != 0) {
1169 tloge("smc_call returns error, ret=0x%x\n", ret);
1170 }
1171 return ret;
1172 }
1173
TcNsClientOpen(TcNsDevFile ** devFile,uint8_t kernelApi)1174 int TcNsClientOpen(TcNsDevFile **devFile, uint8_t kernelApi)
1175 {
1176 int ret = TEEC_ERROR_GENERIC;
1177 TcNsDevFile *dev = NULL;
1178
1179 tlogd("TcClientOpen\n");
1180 if (devFile == NULL) {
1181 tloge("devFile is NULL\n");
1182 return -EFAULT;
1183 }
1184 dev = calloc(1, sizeof(*dev));
1185 if (ZERO_OR_NULL_PTR((unsigned long)(uintptr_t)dev)) {
1186 tloge("dev malloc failed\n");
1187 return ret;
1188 }
1189 mutex_lock(&g_tcNsDevList.devLock);
1190 list_add_tail(&dev->head, &g_tcNsDevList.devFileList);
1191 mutex_unlock(&g_tcNsDevList.devLock);
1192 mutex_lock(&g_deviceFileCntLock);
1193 dev->devFileId = g_deviceFileCnt;
1194 g_deviceFileCnt++;
1195 mutex_unlock(&g_deviceFileCntLock);
1196 INIT_LIST_HEAD(&dev->sharedMemList);
1197 dev->loginSetup = 0;
1198 dev->kernelApi = kernelApi;
1199 dev->loadAppFlag = 0;
1200 mutex_init(&dev->serviceLock);
1201 mutex_init(&dev->sharedMemLock);
1202 mutex_init(&dev->LoginSetupLock);
1203 *devFile = dev;
1204 ret = TEEC_SUCCESS;
1205 return ret;
1206 }
1207
FreeDev(TcNsDevFile * dev)1208 void FreeDev(TcNsDevFile *dev)
1209 {
1210 DelDevNode(dev);
1211 TeeAgentClearDevOwner(dev);
1212 if (memset_s((void *)dev, sizeof(*dev), 0, sizeof(*dev)) != EOK) {
1213 tloge("Caution, memset dev fail!\n");
1214 }
1215 free(dev);
1216 }
1217
TcNsClientClose(TcNsDevFile * dev)1218 int TcNsClientClose(TcNsDevFile *dev)
1219 {
1220 int ret = TEEC_ERROR_GENERIC;
1221 uint32_t index;
1222
1223 if (dev == NULL) {
1224 tloge("invalid dev(null)\n");
1225 return ret;
1226 }
1227
1228 /* close unclosed session */
1229 for (index = 0; index < SERVICES_MAX_COUNT; index++) {
1230 CloseUnclosedSession(dev, index);
1231 }
1232
1233 // for thirdparty agent, code runs here only when agent crashed
1234 SendCrashedEventResponseAll(dev);
1235 ret = TEEC_SUCCESS;
1236 FreeDev(dev);
1237 return ret;
1238 }
1239
ReleaseVmaSharedMem(TcNsDevFile * devFile,const LosVmMapRegion * vma)1240 static void ReleaseVmaSharedMem(TcNsDevFile *devFile,
1241 const LosVmMapRegion *vma)
1242 {
1243 TcNsSharedMem *sharedMem = NULL;
1244 TcNsSharedMem *sharedMemTemp = NULL;
1245 bool find = false;
1246
1247 mutex_lock(&devFile->sharedMemLock);
1248 list_for_each_entry_safe(sharedMem, sharedMemTemp,
1249 &devFile->sharedMemList, head) {
1250 if (sharedMem != NULL) {
1251 if (sharedMem->userAddr ==
1252 (void *)(uintptr_t)vma->range.base) {
1253 sharedMem->userAddr = NULL;
1254 find = true;
1255 } else if (sharedMem->userAddrCa ==
1256 (void *)(uintptr_t)vma->range.base) {
1257 sharedMem->userAddrCa = NULL;
1258 find = true;
1259 }
1260
1261 if ((sharedMem->userAddr == NULL) &&
1262 (sharedMem->userAddrCa == NULL)) {
1263 list_del(&sharedMem->head);
1264 }
1265
1266 /* pair with TcClientMmap */
1267 if (find == true) {
1268 PutSharememStruct(sharedMem);
1269 break;
1270 }
1271 }
1272 }
1273 mutex_unlock(&devFile->sharedMemLock);
1274 }
1275
TcNsSharedMemUnmap(TcNsDevFile * devFile,const unsigned int argp)1276 static int TcNsSharedMemUnmap(TcNsDevFile *devFile, const unsigned int argp)
1277 {
1278 if (devFile == NULL) {
1279 tloge("unmap input error\n");
1280 return -EINVAL;
1281 }
1282
1283 LosVmMapRegion *vma = LOS_RegionFind(OsCurrProcessGet()->vmSpace, (vaddr_t)argp);
1284 if (vma == NULL) {
1285 tloge("unmap error memory\n");
1286 return -EINVAL;
1287 }
1288
1289 bool checkValue = (IsTeecdProcess(g_teecdTask, OsCurrTaskGet())) && (!TcNsGetUid()) &&
1290 ((g_teecdTask->taskStatus & OS_TASK_STATUS_EXIT) || (OsCurrTaskGet()->taskStatus & OS_TASK_STATUS_EXIT));
1291 if (checkValue == true) {
1292 tlogd("teecd is killed, just return in vma close\n");
1293 return 0;
1294 }
1295 ReleaseVmaSharedMem(devFile, vma);
1296 return 0;
1297 }
1298
AllocAndFindSharedMem(const LosVmMapRegion * vma,TcNsDevFile * devFile,bool * onlyRemap)1299 static TcNsSharedMem *AllocAndFindSharedMem(const LosVmMapRegion *vma,
1300 TcNsDevFile *devFile, bool *onlyRemap)
1301 {
1302 TcNsSharedMem *shmTmp = NULL;
1303 unsigned long len = vma->range.size;
1304
1305 /* using vma->vm_pgoff as share_mem index */
1306 /* check if aready allocated */
1307 list_for_each_entry(shmTmp, &devFile->sharedMemList, head) {
1308 if (atomic_read(&shmTmp->offset) == vma->pgOff) {
1309 tlogd("share_mem already allocated, shmTmp->offset=%d\n",
1310 atomic_read(&shmTmp->offset));
1311 /* args check:
1312 * 1. this shared mem is already mapped ?
1313 * 2. remap a different size sharedMem ?
1314 */
1315 if (shmTmp->userAddrCa != NULL ||
1316 vma->range.size != shmTmp->len) {
1317 tloge("already remap once!\n");
1318 return NULL;
1319 }
1320 /* return the same sharedmem specified by vma->vm_pgoff */
1321 *onlyRemap = true;
1322 GetSharememStruct(shmTmp);
1323 return shmTmp;
1324 }
1325 }
1326
1327 /* if not find, alloc a new sharemem */
1328 return TcMemAllocate(len);
1329 }
1330
RemapSharedMem(LosVmMapRegion * vma,TcNsSharedMem * sharedMem)1331 static int RemapSharedMem(LosVmMapRegion *vma, TcNsSharedMem *sharedMem)
1332 {
1333 int ret;
1334
1335 ret = RemapVmallocRange(vma, sharedMem->kernelAddr, 0);
1336 if (ret) {
1337 tloge("can't remap to user, ret = %d\n", ret);
1338 return -1;
1339 }
1340 return ret;
1341 }
1342
1343 /* in this func, we need to deal with follow cases:
1344 * vendor CA alloc sharedmem (alloc and remap);
1345 * HAL alloc sharedmem (alloc and remap);
1346 * system CA alloc sharedmem (only just remap);
1347 */
TcClientMmap(struct file * filp,LosVmMapRegion * vma)1348 static int TcClientMmap(struct file *filp, LosVmMapRegion *vma)
1349 {
1350 int ret;
1351 TcNsDevFile *devFile = NULL;
1352 TcNsSharedMem *sharedMem = NULL;
1353 bool onlyRemap = false;
1354 bool checkValue = false;
1355
1356 checkValue = (filp == NULL || vma == NULL || filp->f_priv == NULL);
1357 if (checkValue == true) {
1358 tloge("invalid args for tc mmap\n");
1359 return -EINVAL;
1360 }
1361 devFile = filp->f_priv;
1362
1363 mutex_lock(&devFile->sharedMemLock);
1364 sharedMem = AllocAndFindSharedMem(vma, devFile, &onlyRemap);
1365 if (IS_ERR_OR_NULL(sharedMem)) {
1366 tloge("alloc shared mem failed\n");
1367 mutex_unlock(&devFile->sharedMemLock);
1368 return -ENOMEM;
1369 }
1370
1371 ret = RemapSharedMem(vma, sharedMem);
1372 if (ret != 0) {
1373 if (onlyRemap) {
1374 PutSharememStruct(sharedMem);
1375 } else {
1376 TcMemFree(sharedMem);
1377 }
1378 mutex_unlock(&devFile->sharedMemLock);
1379 return ret;
1380 }
1381
1382 if (onlyRemap) {
1383 sharedMem->userAddrCa = (void *)vma->range.base;
1384 mutex_unlock(&devFile->sharedMemLock);
1385 return ret;
1386 }
1387 sharedMem->userAddr = (void *)vma->range.base;
1388 atomic_set(&sharedMem->offset, vma->pgOff);
1389 GetSharememStruct(sharedMem);
1390 list_add_tail(&sharedMem->head, &devFile->sharedMemList);
1391 mutex_unlock(&devFile->sharedMemLock);
1392 return ret;
1393 }
1394
IoctlSessionSendCmd(TcNsDevFile * devFile,TcNsClientContext * context,void * argp)1395 static int IoctlSessionSendCmd(TcNsDevFile *devFile,
1396 TcNsClientContext *context, void *argp)
1397 {
1398 int ret;
1399
1400 ret = TcNsSendCmd(devFile, context);
1401 if (ret) {
1402 tloge("TcNsSendCmd Failed ret is %d\n", ret);
1403 }
1404 if (copy_to_user(argp, context, sizeof(*context))) {
1405 if (ret == 0) {
1406 ret = -EFAULT;
1407 }
1408 }
1409 return ret;
1410 }
1411
TcClientSessionIoctl(struct file * file,unsigned int cmd,unsigned long arg)1412 static int TcClientSessionIoctl(struct file *file, unsigned int cmd,
1413 unsigned long arg)
1414 {
1415 int ret = TEEC_ERROR_GENERIC;
1416 void *argp = (void __user *)(uintptr_t)arg;
1417 TcNsDevFile *devFile = file->f_priv;
1418 TcNsClientContext context;
1419
1420 if (argp == NULL) {
1421 tloge("argp is NULL input buffer\n");
1422 ret = -EINVAL;
1423 return ret;
1424 }
1425 if (copy_from_user(&context, argp, sizeof(context))) {
1426 tloge("copy from user failed\n");
1427 return -EFAULT;
1428 }
1429 context.returns.origin = TEEC_ORIGIN_COMMS;
1430 switch (cmd) {
1431 case TC_NS_CLIENT_IOCTL_SES_OPEN_REQ: {
1432 ret = TcNsOpenSession(devFile, &context);
1433 if (ret) {
1434 tloge("TcNsOpenSession Failed ret is %d\n", ret);
1435 }
1436 if (copy_to_user(argp, &context, sizeof(context)) && ret == 0) {
1437 ret = -EFAULT;
1438 }
1439 break;
1440 }
1441 case TC_NS_CLIENT_IOCTL_SES_CLOSE_REQ: {
1442 ret = TcNsCloseSession(devFile, &context);
1443 break;
1444 }
1445 case TC_NS_CLIENT_IOCTL_SEND_CMD_REQ: {
1446 ret = IoctlSessionSendCmd(devFile, &context, argp);
1447 break;
1448 }
1449 default:
1450 tloge("invalid cmd:0x%x!\n", cmd);
1451 return ret;
1452 }
1453 /*
1454 * Don't leak ERESTARTSYS to user space.
1455 *
1456 * CloseSession is not reentrant, so convert to -EINTR.
1457 * In other case, RestartSyscall().
1458 *
1459 * It is better to call it right after the error code
1460 * is generated (in TcClientCall), but kernel CAs are
1461 * still exist when these words are written. Setting TIF
1462 * flags for callers of those CAs is very hard to analysis.
1463 *
1464 * For kernel CA, when ERESTARTSYS is seen, loop in kernel
1465 * instead of notifying user.
1466 *
1467 * P.S. ret code in this function is in mixed naming space.
1468 * See the definition of ret. However, this function never
1469 * return its default value, so using -EXXX is safe.
1470 */
1471 if (ret == -ERESTARTSYS) {
1472 if (cmd == TC_NS_CLIENT_IOCTL_SES_CLOSE_REQ) {
1473 ret = -EINTR;
1474 } else {
1475 return RestartSyscall();
1476 }
1477 }
1478 return ret;
1479 }
1480
IoctlRegisterAgent(TcNsDevFile * devFile,unsigned long arg)1481 static int IoctlRegisterAgent(TcNsDevFile *devFile, unsigned long arg)
1482 {
1483 int ret;
1484 struct AgentIoctlArgs args;
1485
1486 if (copy_from_user(&args, (void *)arg, sizeof(args))) {
1487 tloge("copy agent args failed\n");
1488 return -EFAULT;
1489 }
1490
1491 ret = TcNsRegisterAgent(devFile, args.id, args.bufferSize,
1492 &args.buffer, true);
1493 if (ret == 0) {
1494 if (copy_to_user((void *)arg, &args, sizeof(args))) {
1495 tloge("copy agent user addr failed\n");
1496 }
1497 }
1498
1499 return ret;
1500 }
1501
IoctlUnregisterAgent(const TcNsDevFile * devFile,unsigned long arg)1502 static int IoctlUnregisterAgent(const TcNsDevFile *devFile, unsigned long arg)
1503 {
1504 int ret;
1505 struct SmcEventData *eventData = NULL;
1506 eventData = FindEventControl((unsigned int)arg);
1507 if (eventData == NULL) {
1508 tloge("invalid agent id\n");
1509 return TEEC_ERROR_GENERIC;
1510 }
1511 if (eventData->owner != devFile) {
1512 tloge("invalid unregister request\n");
1513 PutAgentEvent(eventData);
1514 return TEEC_ERROR_GENERIC;
1515 }
1516 PutAgentEvent(eventData);
1517 ret = TcNsUnregisterAgent((unsigned int)arg);
1518 return ret;
1519 }
1520
TcAgentIoctl(struct file * file,unsigned int cmd,unsigned long arg)1521 static long TcAgentIoctl(struct file *file, unsigned int cmd, unsigned long arg)
1522 {
1523 int ret = TEEC_ERROR_GENERIC;
1524 TcNsDevFile *devFile = file->f_priv;
1525
1526 if (devFile == NULL) {
1527 tloge("invalid params\n");
1528 return ret;
1529 }
1530 switch (cmd) {
1531 case TC_NS_CLIENT_IOCTL_WAIT_EVENT: {
1532 ret = TcNsWaitEvent((unsigned int)arg);
1533 break;
1534 }
1535 case TC_NS_CLIENT_IOCTL_SEND_EVENT_RESPONSE: {
1536 ret = TcNsSendEventResponse((unsigned int)arg);
1537 break;
1538 }
1539 case TC_NS_CLIENT_IOCTL_REGISTER_AGENT: {
1540 ret = IoctlRegisterAgent(devFile, arg);
1541 break;
1542 }
1543 case TC_NS_CLIENT_IOCTL_UNREGISTER_AGENT: {
1544 ret = IoctlUnregisterAgent(devFile, arg);
1545 break;
1546 }
1547 case TC_NS_CLIENT_IOCTL_SYC_SYS_TIME: {
1548 ret = TcNsSyncSysTime((TcNsClientTime *)(uintptr_t)arg);
1549 break;
1550 }
1551 case TC_NS_CLIENT_IOCTL_SET_NATIVECA_IDENTITY: {
1552 ret = TcNsSetNativeHash(arg, GLOBAL_CMD_ID_SET_CA_HASH);
1553 break;
1554 }
1555 case TC_NS_CLIENT_IOCTL_LATEINIT: {
1556 ret = TcNsLateInit(arg);
1557 break;
1558 }
1559 default:
1560 tloge("invalid cmd!\n");
1561 return ret;
1562 }
1563 tlogd("TC_NS_ClientIoctl ret = 0x%x\n", ret);
1564 return ret;
1565 }
1566
TcClientIoctlOthers(struct file * file,int cmd,unsigned long arg)1567 static int TcClientIoctlOthers(struct file *file, int cmd, unsigned long arg)
1568 {
1569 void *argp = (void __user *)(uintptr_t)arg;
1570 int ret = TEEC_ERROR_GENERIC;
1571
1572 switch (cmd) {
1573 /* IOCTLs for the secure storage daemon */
1574 case TC_NS_CLIENT_IOCTL_WAIT_EVENT:
1575 case TC_NS_CLIENT_IOCTL_SEND_EVENT_RESPONSE:
1576 case TC_NS_CLIENT_IOCTL_REGISTER_AGENT:
1577 case TC_NS_CLIENT_IOCTL_UNREGISTER_AGENT:
1578 case TC_NS_CLIENT_IOCTL_SYC_SYS_TIME:
1579 case TC_NS_CLIENT_IOCTL_LOAD_TTF_FILE_AND_NOTCH_HEIGHT:
1580 case TC_NS_CLIENT_IOCTL_SET_NATIVECA_IDENTITY:
1581 case TC_NS_CLIENT_IOCTL_LATEINIT:
1582 ret = TcAgentIoctl(file, cmd, arg);
1583 break;
1584 #ifdef DEF_ENG
1585 case TC_NS_CLIENT_IOCTL_TST_CMD_REQ: {
1586 tlogd("come into tst cmd\n");
1587 ret = TcNsTstCmd(file->f_priv, argp);
1588 break;
1589 }
1590 #endif
1591 case TC_NS_CLIENT_IOCTL_GET_TEE_VERSION: {
1592 ret = TcNsGetTeeVersion(file->f_priv, argp);
1593 break;
1594 }
1595 case TC_NS_CLIENT_IOCTL_UNMAP_SHARED_MEM: {
1596 ret = TcNsSharedMemUnmap(file->f_priv, (unsigned int)(UINTPTR)argp);
1597 break;
1598 }
1599 default: {
1600 tloge("invalid cmd 0x%x!\n", cmd);
1601 break;
1602 }
1603 }
1604 return ret;
1605 }
1606
TcClientIoctl(struct file * file,int cmd,unsigned long arg)1607 static int TcClientIoctl(struct file *file, int cmd, unsigned long arg)
1608 {
1609 int ret = TEEC_ERROR_GENERIC;
1610 void *argp = (void __user *)(uintptr_t)arg;
1611 TcNsDevFile *devFile = file->f_priv;
1612 TcNsClientContext clientContext = {{0}};
1613
1614 switch (cmd) {
1615 /* IOCTLs for the CAs */
1616 case TC_NS_CLIENT_IOCTL_SES_OPEN_REQ:
1617 /* Upvote for peripheral zone votage, needed by Coresight.
1618 * Downvote will be processed inside CFC_RETURN_PMCLK_ON_COND
1619 */
1620 /* Fall through */
1621 case TC_NS_CLIENT_IOCTL_SES_CLOSE_REQ:
1622 case TC_NS_CLIENT_IOCTL_SEND_CMD_REQ:
1623 ret = TcClientSessionIoctl(file, cmd, arg);
1624 break;
1625 case TC_NS_CLIENT_IOCTL_LOAD_APP_REQ:
1626 ret = TcNsLoadSecfile(devFile, argp);
1627 break;
1628 case TC_NS_CLIENT_IOCTL_CANCEL_CMD_REQ:
1629 if (argp == NULL) {
1630 tloge("argp is NULL input buffer\n");
1631 ret = -EINVAL;
1632 break;
1633 }
1634 if (copy_from_user(&clientContext, argp,
1635 sizeof(clientContext))) {
1636 tloge("copy from user failed\n");
1637 ret = -ENOMEM;
1638 break;
1639 }
1640 ret = TcNsSendCmd(devFile, &clientContext);
1641 break;
1642 /* This is the login information
1643 * and is set teecd when client opens a new session
1644 */
1645 case TC_NS_CLIENT_IOCTL_LOGIN: {
1646 ret = TcNsClientLoginFunc(devFile, argp);
1647 break;
1648 }
1649 default:
1650 ret = TcClientIoctlOthers(file, cmd, arg);
1651 break;
1652 }
1653
1654 tlogd("tc client ioctl ret = 0x%x\n", ret);
1655 return ret;
1656 }
1657
TcClientOpen(struct file * file)1658 static int TcClientOpen(struct file *file)
1659 {
1660 int ret;
1661 TcNsDevFile *dev = NULL;
1662 ret = CheckProcessAccess(OsCurrTaskGet());
1663 if (ret) {
1664 tloge(KERN_ERR "teecd service may be exploited 0x%x\n", ret);
1665 return -EPERM;
1666 }
1667
1668 file->f_priv = NULL;
1669 ret = TcNsClientOpen(&dev, TEE_REQ_FROM_USER_MODE);
1670 if (ret == TEEC_SUCCESS) {
1671 file->f_priv = dev;
1672 }
1673 return ret;
1674 }
1675
TcClientClose(struct file * file)1676 static int TcClientClose(struct file *file)
1677 {
1678 int ret = TEEC_ERROR_GENERIC;
1679 TcNsDevFile *dev = file->f_priv;
1680 bool checkValue = false;
1681
1682 checkValue = (IsTeecdProcess(g_teecdTask, OsCurrTaskGet())) &&
1683 (!TcNsGetUid());
1684 if (checkValue == true) {
1685 /* for teecd close fd */
1686 checkValue = (g_teecdTask->taskStatus & OS_TASK_STATUS_EXIT) ||
1687 (OsCurrTaskGet()->taskStatus & OS_TASK_STATUS_EXIT);
1688 if (checkValue == true) {
1689 /* when teecd is be killed or crash */
1690 tloge("teecd is killed, something bad must be happened!!!\n");
1691 if (IsSystemAgent(dev)) {
1692 /* for teecd agent close fd */
1693 SendEventResponseSingle(dev);
1694 FreeDev(dev);
1695 } else {
1696 /* for ca damon close fd */
1697 ret = NsClientCloseTeecdNotAgent(dev);
1698 }
1699 } else {
1700 /* for ca damon close fd when ca damon close fd
1701 * later than HAL thread
1702 */
1703 ret = TcNsClientClose(dev);
1704 }
1705 } else {
1706 /* for CA(HAL thread) close fd */
1707 ret = TcNsClientClose(dev);
1708 }
1709 file->f_priv = NULL;
1710 return ret;
1711 }
1712
1713 static const struct file_operations_vfs g_tcNsClientFops = {
1714 .open = TcClientOpen,
1715 .close = TcClientClose,
1716 .ioctl = TcClientIoctl,
1717 .mmap = TcClientMmap,
1718 };
1719
ScheduleWorkOn(int cpu,struct work_struct * work)1720 bool ScheduleWorkOn(int cpu, struct work_struct *work)
1721 {
1722 return queue_work(g_tzdriverWq, work);
1723 }
1724
TcNsClientInit(void)1725 static int TcNsClientInit(void)
1726 {
1727 int ret;
1728
1729 tlogd("TcNsClientInit\n");
1730
1731 ret = CreateTcClientDevice(TC_NS_CLIENT_DEV_NAME, &g_tcNsClientFops);
1732 if (ret != EOK) {
1733 tloge("create tee device error.\n");
1734 return ret;
1735 }
1736 ret = memset_s(&g_tcNsDevList, sizeof(g_tcNsDevList), 0,
1737 sizeof(g_tcNsDevList));
1738 if (ret != EOK) {
1739 return ret;
1740 }
1741
1742 INIT_LIST_HEAD(&g_tcNsDevList.devFileList);
1743 mutex_init(&g_tcNsDevList.devLock);
1744 INIT_LIST_HEAD(&g_serviceList);
1745
1746 g_tzdriverWq = create_workqueue("g_tzdriverWq");
1747 if (g_tzdriverWq == NULL) {
1748 tloge("couldn't create workqueue.\n");
1749 return -ENOMEM;
1750 }
1751 return 0;
1752 }
1753
TcTeeosInit(void)1754 static int TcTeeosInit(void)
1755 {
1756 int ret;
1757
1758 ret = SmcInitData();
1759 if (ret < 0) {
1760 tloge("smc init failed\n");
1761 return ret;
1762 }
1763
1764 ret = TcMemInit();
1765 if (ret < 0) {
1766 tloge("tcmem init failed\n");
1767 goto SMC_DATA_FREE;
1768 }
1769
1770 // following failure don't block tzdriver init proc;
1771 AgentInit();
1772
1773 ret = TzSpiInit();
1774 if (ret) {
1775 tloge("tz spi init failed\n");
1776 }
1777 return 0;
1778
1779 SMC_DATA_FREE:
1780 SmcFreeData();
1781 return ret;
1782 }
1783
TcReInit(void)1784 static void TcReInit(void)
1785 {
1786 int ret = 0;
1787
1788 if (InitSmcSvcThread()) {
1789 tloge("init svc thread\n");
1790 ret = -EFAULT;
1791 }
1792
1793 if (ret) {
1794 tloge("Caution! Running environment init failed!\n");
1795 }
1796 }
1797
TcInit(void)1798 int TcInit(void)
1799 {
1800 int ret = TcNsClientInit();
1801 if (ret != 0) {
1802 goto TC_INIT_FAIL;
1803 }
1804
1805 ret = TcTeeosInit();
1806 if (ret != 0) {
1807 goto TC_INIT_FAIL;
1808 }
1809 // run-time environment init failure don't block tzdriver init proc;
1810 TcReInit();
1811
1812 #ifdef DEF_ENG
1813 TzdebugInit();
1814 #endif
1815 return 0;
1816
1817 TC_INIT_FAIL:
1818 ret = unregister_driver(TC_NS_CLIENT_DEV_NAME);
1819 if (g_tzdriverWq != NULL) {
1820 destroy_workqueue(g_tzdriverWq);
1821 }
1822 return ret;
1823 }
1824