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_sub_driver.h"
33 #include "agent.h"
34 #include "gp_ops.h"
35 #include "mailbox_mempool.h"
36 #ifdef SECURITY_AUTH_ENHANCE
37 #include "security_auth_enhance.h"
38 #endif
39 #include "smc.h"
40 #include "tc_client_driver.h"
41 #include "tc_ns_log.h"
42 #include "tzdriver_compat.h"
43
44 static DEFINE_MUTEX(g_loadAppLock);
45
46 #ifdef SECURITY_AUTH_ENHANCE
47
48 typedef struct {
49 TcNsDevFile *devFile;
50 TcNsClientContext *context;
51 TcNsSession *session;
52 } GetSecureInfoParams;
53
CheckRandomData(const uint8_t * data,uint32_t size)54 static int CheckRandomData(const uint8_t *data, uint32_t size)
55 {
56 uint32_t i;
57
58 for (i = 0; i < size; i++) {
59 if (data[i] != 0) {
60 break;
61 }
62 }
63 if (i >= size) {
64 return -1;
65 }
66 return 0;
67 }
68
GenerateRandomData(uint8_t * data,uint32_t size)69 int GenerateRandomData(uint8_t *data, uint32_t size)
70 {
71 if (data == NULL || size == 0) {
72 tloge("Bad parameters!\n");
73 return -EFAULT;
74 }
75 if (memset_s((void *)data, size, 0, size)) {
76 tloge("Clean the data buffer failed!\n");
77 return -EFAULT;
78 }
79 GetRandomBytesArch((void *)data, size);
80 if (CheckRandomData(data, size) != 0) {
81 return -EFAULT;
82 }
83 return 0;
84 }
85
IsValidEncryptionHead(const struct EncryptionHead * head,const uint8_t * data,uint32_t len)86 bool IsValidEncryptionHead(const struct EncryptionHead *head,
87 const uint8_t *data, uint32_t len)
88 {
89 if (head == NULL || data == NULL || len == 0) {
90 tloge("In parameters check failed.\n");
91 return false;
92 }
93
94 if (strncmp((const char *)head->magic, MAGIC_STRING, sizeof(MAGIC_STRING))) {
95 tloge("Magic string is invalid.\n");
96 return false;
97 }
98
99 if (head->payloadLen != len) {
100 tloge("Payload length is invalid.\n");
101 return false;
102 }
103 return true;
104 }
105
GenerateChallengeWord(uint8_t * challengeWord,uint32_t size)106 int GenerateChallengeWord(uint8_t *challengeWord, uint32_t size)
107 {
108 if (challengeWord == NULL) {
109 tloge("Parameter is null pointer!\n");
110 return -EINVAL;
111 }
112 return GenerateRandomData(challengeWord, size);
113 }
114
SetEncryptionHead(struct EncryptionHead * head,uint32_t len)115 int SetEncryptionHead(struct EncryptionHead *head,
116 uint32_t len)
117 {
118 if (head == NULL || len == 0) {
119 tloge("In parameters check failed.\n");
120 return -EINVAL;
121 }
122 if (strncpy_s((char *)head->magic, sizeof(head->magic),
123 MAGIC_STRING, strlen(MAGIC_STRING) + 1)) {
124 tloge("Copy magic string failed.\n");
125 return -EFAULT;
126 }
127 head->payloadLen = len;
128 return 0;
129 }
130
TcFindDevFile(unsigned int devFileId)131 static TcNsDevFile *TcFindDevFile(unsigned int devFileId)
132 {
133 TcNsDevFile *devFile = NULL;
134
135 list_for_each_entry(devFile, &GetTcNsDevList()->devFileList, head) {
136 if (devFile->devFileId == devFileId) {
137 return devFile;
138 }
139 }
140 return NULL;
141 }
142
TcFindSession2(unsigned int devFileId,const TcNsSmcCmd * cmd)143 TcNsSession *TcFindSession2(unsigned int devFileId,
144 const TcNsSmcCmd *cmd)
145 {
146 TcNsDevFile *devFile = NULL;
147 TcNsService *service = NULL;
148 TcNsSession *session = NULL;
149
150 if (cmd == NULL) {
151 tloge("Parameter is null pointer!\n");
152 return NULL;
153 }
154 mutex_lock(&GetTcNsDevList()->devLock);
155 devFile = TcFindDevFile(devFileId);
156 mutex_unlock(&GetTcNsDevList()->devLock);
157 if (devFile == NULL) {
158 tloge("Can't find dev file! devFileId %d\n", devFileId);
159 return NULL;
160 }
161 mutex_lock(&devFile->serviceLock);
162 service = TcFindServiceInDev(devFile, cmd->uuid, UUID_LEN);
163 GetServiceStruct(service);
164 mutex_unlock(&devFile->serviceLock);
165 if (service == NULL) {
166 tloge(" Can't find service!\n");
167 return NULL;
168 }
169 mutex_lock(&service->SessionLock);
170 session = TcFindSessionWithOwner(&service->sessionList,
171 cmd->contextId, devFile);
172 GetSessionStruct(session);
173 mutex_unlock(&service->SessionLock);
174 PutServiceStruct(service);
175 if (session == NULL) {
176 tloge("can't find session[0x%x]!\n", cmd->contextId);
177 return NULL;
178 }
179 return session;
180 }
181
AlginUp(uint32_t x,uint32_t align)182 static inline uint32_t AlginUp(uint32_t x, uint32_t align)
183 {
184 return (x + align - 1) & ~(align - 1);
185 }
186
CleanSessionSecureInformation(TcNsSession * session)187 void CleanSessionSecureInformation(TcNsSession *session)
188 {
189 if (session != NULL) {
190 if (memset_s((void *)&session->secureInfo,
191 sizeof(session->secureInfo), 0, sizeof(session->secureInfo)))
192 tloge("Clean this session secure information failed!\n");
193 }
194 }
195
AllocSecureParams(uint32_t secureParamsAlignedSize,uint32_t paramsSize,struct SessionSecureParams ** reeSecureParams,struct SessionSecureParams ** teeSecureParams)196 static int AllocSecureParams(uint32_t secureParamsAlignedSize,
197 uint32_t paramsSize, struct SessionSecureParams **reeSecureParams,
198 struct SessionSecureParams **teeSecureParams)
199 {
200 if (secureParamsAlignedSize == 0) {
201 tloge("secureParamsAlignedSize is invalid.\n");
202 return -ENOMEM;
203 }
204 *reeSecureParams = MailboxAlloc(paramsSize, 0);
205 if (*reeSecureParams == NULL) {
206 tloge("Malloc REE session secure parameters buffer failed.\n");
207 return -ENOMEM;
208 }
209 *teeSecureParams = calloc(1, secureParamsAlignedSize);
210 if (ZERO_OR_NULL_PTR((unsigned long)(uintptr_t)(*teeSecureParams))) {
211 tloge("Malloc TEE session secure parameters buffer failed.\n");
212 MailboxFree(*reeSecureParams);
213 *reeSecureParams = NULL;
214 return -ENOMEM;
215 }
216 return 0;
217 }
218
InitForAllocSecureParams(GetSecureInfoParams * paramsIn,uint32_t * secureParamsAlignedSize,uint32_t * paramsSize)219 static int InitForAllocSecureParams(GetSecureInfoParams *paramsIn,
220 uint32_t *secureParamsAlignedSize, uint32_t *paramsSize)
221 {
222 int ret;
223
224 ret = GenerateChallengeWord(
225 (uint8_t *)¶msIn->session->secureInfo.challengeWord,
226 sizeof(paramsIn->session->secureInfo.challengeWord));
227 if (ret) {
228 tloge("Generate challenge word failed, ret = %d\n", ret);
229 return ret;
230 }
231 *secureParamsAlignedSize =
232 AlginUp(sizeof(struct SessionSecureParams), CIPHER_BLOCK_BYTESIZE);
233 *paramsSize = *secureParamsAlignedSize + IV_BYTESIZE;
234 return 0;
235 }
236
SendSmcCmdForSecureParams(const GetSecureInfoParams * paramsIn,struct SessionSecureParams * reeSecureParams)237 static int SendSmcCmdForSecureParams(const GetSecureInfoParams *paramsIn,
238 struct SessionSecureParams *reeSecureParams)
239 {
240 int ret;
241 TcNsSmcCmd smcCmd = { {0}, 0 };
242 uint32_t uid;
243
244 uid = GetTaskUid(OsCurrTaskGet());
245 /* Transfer chanllenge word to secure world */
246 reeSecureParams->payload.ree2tee.challengeWord =
247 paramsIn->session->secureInfo.challengeWord;
248 smcCmd.globalCmd = true;
249 if (memcpy_s(smcCmd.uuid, sizeof(smcCmd.uuid),
250 paramsIn->context->uuid, UUID_LEN)) {
251 tloge("memcpy_s uuid error.\n");
252 return -EFAULT;
253 }
254 smcCmd.cmdId = GLOBAL_CMD_ID_GET_SESSION_SECURE_PARAMS;
255 smcCmd.devFileId = paramsIn->devFile->devFileId;
256 smcCmd.contextId = paramsIn->context->sessionId;
257 smcCmd.operationPhys = 0;
258 smcCmd.operationHphys = 0;
259 smcCmd.loginDataPhy = 0;
260 smcCmd.loginDataHaddr = 0;
261 smcCmd.loginDataLen = 0;
262 smcCmd.errOrigin = 0;
263 smcCmd.uid = uid;
264 smcCmd.started = paramsIn->context->started;
265 smcCmd.paramsPhys = LOS_PaddrQuery((void *)reeSecureParams);
266 smcCmd.paramsHphys = 0;
267 ret = TcNsSmc(&smcCmd);
268 if (ret) {
269 reeSecureParams->payload.ree2tee.challengeWord = 0;
270 tloge("TC_NS_SMC returns error, ret = %d\n", ret);
271 return ret;
272 }
273 return 0;
274 }
275
UpdateSecureParamsFromTee(GetSecureInfoParams * paramsIn,struct SessionSecureParams * reeSecureParams,struct SessionSecureParams * teeSecureParams,uint32_t secureParamsAlignedSize,uint32_t paramsSize)276 static int UpdateSecureParamsFromTee(GetSecureInfoParams *paramsIn,
277 struct SessionSecureParams *reeSecureParams,
278 struct SessionSecureParams *teeSecureParams,
279 uint32_t secureParamsAlignedSize,
280 uint32_t paramsSize)
281 {
282 int ret;
283 uint8_t *encSecureParams = NULL;
284 /* Get encrypted session secure parameters from secure world */
285 encSecureParams = (uint8_t *)reeSecureParams;
286 struct SessionCryptoInfo *rootKey = GetSessionRootKeyInstance();
287 if (rootKey == NULL) {
288 return -EINVAL;
289 }
290 ret = CryptoSessionAescbcKey256(encSecureParams, paramsSize,
291 (uint8_t *)teeSecureParams, secureParamsAlignedSize,
292 rootKey->key, NULL, DECRYPT);
293 if (ret) {
294 tloge("Decrypted session secure parameters failed, ret = %d.\n", ret);
295 return ret;
296 }
297 /* Analyze encryption head */
298
299 if (!IsValidEncryptionHead(&teeSecureParams->head,
300 (uint8_t *)&teeSecureParams->payload,
301 sizeof(teeSecureParams->payload)))
302 return -EFAULT;
303
304 /* Store session secure parameters */
305 ret = memcpy_s((void *)paramsIn->session->secureInfo.scrambling,
306 sizeof(paramsIn->session->secureInfo.scrambling),
307 (void *)&teeSecureParams->payload.tee2ree.scrambling,
308 sizeof(teeSecureParams->payload.tee2ree.scrambling));
309 if (ret) {
310 tloge("Memcpy scrambling data failed, ret = %d.\n", ret);
311 return ret;
312 }
313 ret = memcpy_s((void *)¶msIn->session->secureInfo.cryptoInfo,
314 sizeof(paramsIn->session->secureInfo.cryptoInfo),
315 (void *)&teeSecureParams->payload.tee2ree.cryptoInfo,
316 sizeof(teeSecureParams->payload.tee2ree.cryptoInfo));
317 if (ret) {
318 tloge("Memcpy session crypto information failed, ret = %d.\n", ret);
319 return ret;
320 }
321 return 0;
322 }
323
GetSessionSecureParams(TcNsDevFile * devFile,TcNsClientContext * context,TcNsSession * session)324 int GetSessionSecureParams(TcNsDevFile *devFile,
325 TcNsClientContext *context, TcNsSession *session)
326 {
327 int ret;
328 uint32_t paramsSize;
329 uint32_t secureParamsAlignedSize;
330 struct SessionSecureParams *reeSecureParams = NULL;
331 struct SessionSecureParams *teeSecureParams = NULL;
332 bool checkValue = false;
333 GetSecureInfoParams paramsIn = { devFile, context, session };
334
335 checkValue = (devFile == NULL || context == NULL || session == NULL);
336 if (checkValue == true) {
337 tloge("Parameter is null pointer!\n");
338 return -EINVAL;
339 }
340 ret = InitForAllocSecureParams(¶msIn,
341 &secureParamsAlignedSize, ¶msSize);
342 if (ret != 0) {
343 return ret;
344 }
345 ret = AllocSecureParams(secureParamsAlignedSize,
346 paramsSize, &reeSecureParams, &teeSecureParams);
347 if (ret != 0) {
348 return ret;
349 }
350 ret = SendSmcCmdForSecureParams(¶msIn, reeSecureParams);
351 if (ret != 0) {
352 goto free;
353 }
354
355 ret = UpdateSecureParamsFromTee(¶msIn, reeSecureParams,
356 teeSecureParams, secureParamsAlignedSize, paramsSize);
357 if (memset_s((void *)teeSecureParams, secureParamsAlignedSize,
358 0, secureParamsAlignedSize)) {
359 tloge("Clean the secure parameters buffer failed!\n");
360 }
361 free:
362 MailboxFree(reeSecureParams);
363 reeSecureParams = NULL;
364 free(teeSecureParams);
365 teeSecureParams = NULL;
366 if (ret) {
367 CleanSessionSecureInformation(session);
368 }
369 return ret;
370 }
371
GenerateEncryptedSessionSecureParams(const struct SessionSecureInfo * secureInfo,uint8_t * encSecureParams,size_t encParamsSize)372 int GenerateEncryptedSessionSecureParams(
373 const struct SessionSecureInfo *secureInfo,
374 uint8_t *encSecureParams, size_t encParamsSize)
375 {
376 int ret;
377 struct SessionSecureParams *reeSecureParams = NULL;
378 uint32_t secureParamsAlignedSize =
379 AlginUp(sizeof(*reeSecureParams), CIPHER_BLOCK_BYTESIZE);
380 uint32_t paramsSize = secureParamsAlignedSize + IV_BYTESIZE;
381
382 if (secureInfo == NULL || encSecureParams == NULL ||
383 encParamsSize < paramsSize) {
384 tloge("invalid enc params\n");
385 return -EINVAL;
386 }
387 reeSecureParams = calloc(1, secureParamsAlignedSize);
388 if (ZERO_OR_NULL_PTR((unsigned long)(uintptr_t)reeSecureParams)) {
389 tloge("Malloc REE session secure parameters buffer failed.\n");
390 return -ENOMEM;
391 }
392 /* Transfer chanllenge word to secure world */
393 reeSecureParams->payload.ree2tee.challengeWord = secureInfo->challengeWord;
394 /* Setting encryption head */
395 ret = SetEncryptionHead(&reeSecureParams->head,
396 sizeof(reeSecureParams->payload));
397 if (ret) {
398 tloge("Set encryption head failed, ret = %d.\n", ret);
399 reeSecureParams->payload.ree2tee.challengeWord = 0;
400 free(reeSecureParams);
401 return -EINVAL;
402 }
403 /* Setting padding data */
404 ret = CryptoAescbcCmsPadding((uint8_t *)reeSecureParams,
405 secureParamsAlignedSize,
406 sizeof(struct SessionSecureParams));
407 if (ret) {
408 tloge("Set encryption padding data failed, ret = %d.\n", ret);
409 reeSecureParams->payload.ree2tee.challengeWord = 0;
410 free(reeSecureParams);
411 return -EINVAL;
412 }
413 /* Encrypt buffer with current session key */
414 ret = CryptoSessionAescbcKey256((uint8_t *)reeSecureParams,
415 secureParamsAlignedSize,
416 encSecureParams, paramsSize, secureInfo->cryptoInfo.key,
417 NULL, ENCRYPT);
418 if (ret) {
419 tloge("Encrypted session secure parameters failed, ret = %d.\n",
420 ret);
421 reeSecureParams->payload.ree2tee.challengeWord = 0;
422 free(reeSecureParams);
423 return -EINVAL;
424 }
425 reeSecureParams->payload.ree2tee.challengeWord = 0;
426 free(reeSecureParams);
427 return 0;
428 }
429
CheckParamsForCryptoSession(const uint8_t * in,const uint8_t * out,const uint8_t * key,uint32_t inLen,uint32_t outLen)430 static int CheckParamsForCryptoSession(const uint8_t *in, const uint8_t *out,
431 const uint8_t *key, uint32_t inLen, uint32_t outLen)
432 {
433 if (in == NULL || out == NULL || key == NULL) {
434 tloge("AES-CBC crypto parameters have null pointer.\n");
435 return -EINVAL;
436 }
437 if (inLen < IV_BYTESIZE || outLen < IV_BYTESIZE) {
438 tloge("AES-CBC crypto data length is invalid.\n");
439 return -EINVAL;
440 }
441 return 0;
442 }
443
CryptoSessionAescbcKey256(uint8_t * in,uint32_t inLen,uint8_t * out,uint32_t outLen,const uint8_t * key,uint8_t * iv,uint32_t mode)444 int CryptoSessionAescbcKey256(uint8_t *in, uint32_t inLen, uint8_t *out,
445 uint32_t outLen, const uint8_t *key, uint8_t *iv, uint32_t mode)
446 {
447 int ret;
448 uint32_t srcLen;
449 uint32_t destLen;
450 uint8_t *aescbcIv = NULL;
451 bool checkValue = false;
452
453 ret = CheckParamsForCryptoSession(in, out, key, inLen, outLen);
454 if (ret) {
455 return ret;
456 }
457 /* For iv variable is null, iv is the first 16 bytes
458 * in cryptotext buffer.
459 */
460 switch (mode) {
461 case ENCRYPT:
462 srcLen = inLen;
463 destLen = outLen - IV_BYTESIZE;
464 aescbcIv = out + destLen;
465 break;
466 case DECRYPT:
467 srcLen = inLen - IV_BYTESIZE;
468 destLen = outLen;
469 aescbcIv = in + srcLen;
470 break;
471 default:
472 tloge("AES-CBC crypto use error mode = %u.\n", mode);
473 return -EINVAL;
474 }
475
476 /* IV is configured by user */
477 if (iv != NULL) {
478 srcLen = inLen;
479 destLen = outLen;
480 aescbcIv = iv;
481 }
482 checkValue = (srcLen != destLen) || (srcLen == 0) ||
483 (srcLen % CIPHER_BLOCK_BYTESIZE);
484 if (checkValue == true) {
485 tloge("AES-CBC, plaintext-len must be equal to cryptotext's. srcLen=%u, destLen=%u.\n",
486 srcLen, destLen);
487 return -EINVAL;
488 }
489 /* IV is configured in here */
490 checkValue = (iv == NULL) && (mode == ENCRYPT);
491 if (checkValue == true) {
492 ret = GenerateRandomData(aescbcIv, IV_BYTESIZE);
493 if (ret) {
494 tloge("Generate AES-CBC iv failed, ret = %d.\n", ret);
495 return ret;
496 }
497 }
498 struct AesParam param = {
499 aescbcIv, key, srcLen, mode
500 };
501 return CryptoAescbcKey256(out, in, ¶m);
502 }
503
CryptoAescbcCmsPadding(uint8_t * plaintext,uint32_t plaintextLen,uint32_t payloadLen)504 int CryptoAescbcCmsPadding(uint8_t *plaintext, uint32_t plaintextLen,
505 uint32_t payloadLen)
506 {
507 uint32_t paddingLen;
508 uint8_t padding;
509 bool checkValue = false;
510
511 if (plaintext == NULL) {
512 tloge("Plaintext is NULL.\n");
513 return -EINVAL;
514 }
515 checkValue = (!plaintextLen) ||
516 (plaintextLen % CIPHER_BLOCK_BYTESIZE) ||
517 (plaintextLen < payloadLen);
518 if (checkValue == true) {
519 tloge("Plaintext length is invalid.\n");
520 return -EINVAL;
521 }
522 paddingLen = plaintextLen - payloadLen;
523 if (paddingLen >= CIPHER_BLOCK_BYTESIZE) {
524 tloge("Padding length is error.\n");
525 return -EINVAL;
526 }
527 if (paddingLen == 0) {
528 /* No need padding */
529 return 0;
530 }
531 padding = (uint8_t)paddingLen;
532 if (memset_s((void *)(plaintext + payloadLen),
533 paddingLen, padding, paddingLen)) {
534 tloge("CMS-Padding is failed.\n");
535 return -EFAULT;
536 }
537 return 0;
538 }
539 #endif
540
GetProcessPath(LosTaskCB * task,char * tpath,int pathLen)541 char *GetProcessPath(LosTaskCB *task, char *tpath, int pathLen)
542 {
543 if (task == NULL || tpath == NULL || pathLen < 0 || pathLen > MAX_PATH_SIZE) {
544 return NULL;
545 }
546
547 struct Vnode *node = OsProcessExecVnodeGet(OS_PCB_FROM_PID(task->processID));
548 if (node == NULL) {
549 return NULL;
550 }
551 int ret = memset_s(tpath, pathLen, '\0', pathLen);
552 if (ret != EOK) {
553 tloge("memset error ret is %d\n", ret);
554 return NULL;
555 }
556
557 ret = memcpy_s(tpath, pathLen - 1, node->filePath, strlen(node->filePath));
558 if (ret != EOK) {
559 tloge("memcpy error ret is %d\n", ret);
560 return NULL;
561 }
562 return tpath;
563 }
564
CalcProcessPathHash(const unsigned char * data,unsigned long dataLen,unsigned char * digest,unsigned int digLen)565 int CalcProcessPathHash(const unsigned char *data,
566 unsigned long dataLen, unsigned char *digest, unsigned int digLen)
567 {
568 bool checkValue = false;
569 TeeSha256Context ctx;
570
571 checkValue = (data == NULL || digest == NULL ||
572 dataLen == 0 || digLen != SHA256_DIGEST_LENTH);
573 if (checkValue == true) {
574 tloge("Bad parameters!\n");
575 return -EFAULT;
576 }
577
578 TeeSha256Init(&ctx);
579 TeeSha256Update(&ctx, data, dataLen);
580 TeeSha256Final(&ctx, digest);
581 return 0;
582 }
583
PackCaCert(char * caCert,const char * path,LosTaskCB * caTask,int uid)584 int PackCaCert(char *caCert, const char *path,
585 LosTaskCB *caTask, int uid)
586 {
587 int messageSize;
588
589 if (caCert == NULL || path == NULL || caTask == NULL) {
590 return 0;
591 }
592
593 messageSize = snprintf_s(caCert, BUF_MAX_SIZE - 1,
594 BUF_MAX_SIZE - 1, "%s%u", path,
595 uid);
596
597 return messageSize;
598 }
599
600 #define MAX_REF_COUNT 255
TcRefServiceInDev(TcNsDevFile * dev,const unsigned char * uuid,int uuidSize,bool * isFull)601 TcNsService *TcRefServiceInDev(TcNsDevFile *dev, const unsigned char *uuid,
602 int uuidSize, bool *isFull)
603 {
604 uint32_t i;
605
606 if (dev == NULL || uuid == NULL || uuidSize != UUID_LEN ||
607 isFull == NULL) {
608 return NULL;
609 }
610 for (i = 0; i < SERVICES_MAX_COUNT; i++) {
611 if (dev->services[i] != NULL &&
612 memcmp(dev->services[i]->uuid, uuid, UUID_LEN) == 0) {
613 if (dev->serviceRef[i] == MAX_REF_COUNT) {
614 *isFull = true;
615 return NULL;
616 }
617 dev->serviceRef[i]++;
618 return dev->services[i];
619 }
620 }
621 return NULL;
622 }
623
TcFindServiceInDev(TcNsDevFile * dev,const unsigned char * uuid,int uuidSize)624 TcNsService *TcFindServiceInDev(TcNsDevFile *dev,
625 const unsigned char *uuid, int uuidSize)
626 {
627 uint32_t i;
628
629 if (dev == NULL || uuid == NULL || uuidSize != UUID_LEN) {
630 return NULL;
631 }
632 for (i = 0; i < SERVICES_MAX_COUNT; i++) {
633 if (dev->services[i] != NULL &&
634 memcmp(dev->services[i]->uuid, uuid, UUID_LEN) == 0) {
635 return dev->services[i];
636 }
637 }
638 return NULL;
639 }
640
TcFindServiceFromAll(const unsigned char * uuid,uint32_t uuidLen)641 TcNsService *TcFindServiceFromAll(const unsigned char *uuid, uint32_t uuidLen)
642 {
643 TcNsService *service = NULL;
644
645 if (uuid == NULL || uuidLen != UUID_LEN) {
646 return NULL;
647 }
648 list_for_each_entry(service, GetServiceList(), head) {
649 if (memcmp(service->uuid, uuid, sizeof(service->uuid)) == 0) {
650 return service;
651 }
652 }
653 return NULL;
654 }
655
AddServiceToDev(TcNsDevFile * dev,TcNsService * service)656 int AddServiceToDev(TcNsDevFile *dev, TcNsService *service)
657 {
658 uint32_t i;
659
660 if (dev == NULL || service == NULL) {
661 return -1;
662 }
663 for (i = 0; i < SERVICES_MAX_COUNT; i++) {
664 if (dev->services[i] == NULL) {
665 tlogd("add service %u to %u\n", i, dev->devFileId);
666 dev->services[i] = service;
667 dev->serviceRef[i] = 1;
668 return 0;
669 }
670 }
671 return -1;
672 }
673
DelServiceFromDev(TcNsDevFile * dev,TcNsService * service)674 void DelServiceFromDev(TcNsDevFile *dev, TcNsService *service)
675 {
676 uint32_t i;
677
678 if (dev == NULL || service == NULL) {
679 return;
680 }
681 for (i = 0; i < SERVICES_MAX_COUNT; i++) {
682 if (dev->services[i] != service) {
683 continue;
684 }
685 tlogd("dev->serviceRef[%u] = %u\n", i, dev->serviceRef[i]);
686 if (dev->serviceRef[i] == 0) {
687 tloge("Caution! No service to be deleted!\n");
688 break;
689 }
690 dev->serviceRef[i]--;
691 if (!dev->serviceRef[i]) {
692 tlogd("del service %u from %u\n", i, dev->devFileId);
693 dev->services[i] = NULL;
694 PutServiceStruct(service);
695 }
696 break;
697 }
698 }
699
TcFindSessionWithOwner(struct list_head * sessionList,unsigned int sessionId,TcNsDevFile * devFile)700 TcNsSession *TcFindSessionWithOwner(struct list_head *sessionList,
701 unsigned int sessionId, TcNsDevFile *devFile)
702 {
703 TcNsSession *session = NULL;
704 bool checkValue = false;
705
706 checkValue = (sessionList == NULL || devFile == NULL);
707 if (checkValue == true) {
708 tloge("sessionList or devFile is Null.\n");
709 return NULL;
710 }
711 list_for_each_entry(session, sessionList, head) {
712 checkValue = (session->sessionId == sessionId &&
713 session->owner == devFile);
714 if (checkValue == true) {
715 return session;
716 }
717 }
718 return NULL;
719 }
720
DumpServicesStatus(const char * param)721 void DumpServicesStatus(const char *param)
722 {
723 TcNsService *service = NULL;
724
725 (void)param;
726 mutex_lock(GetServiceListLock());
727 tlogi("show service list:\n");
728 list_for_each_entry(service, GetServiceList(), head) {
729 tlogi("uuid-%x, usage=%d\n", *(uint32_t *)service->uuid,
730 atomic_read(&service->usage));
731 }
732 mutex_unlock(GetServiceListLock());
733 }
734
InitContext(TcNsClientContext * context,const unsigned char * uuid,const unsigned int uuidLen)735 errno_t InitContext(TcNsClientContext *context, const unsigned char *uuid,
736 const unsigned int uuidLen)
737 {
738 errno_t sret;
739
740 if (context == NULL || uuid == NULL || uuidLen != UUID_LEN) {
741 return -1;
742 }
743 sret = memset_s(context, sizeof(*context), 0, sizeof(*context));
744 if (sret != EOK) {
745 return -1;
746 }
747
748 sret = memcpy_s(context->uuid, sizeof(context->uuid), uuid, uuidLen);
749 if (sret != EOK) {
750 return -1;
751 }
752 return 0;
753 }
754
CloseSession(TcNsDevFile * dev,TcNsSession * session,const unsigned char * uuid,unsigned int uuidLen,unsigned int sessionId)755 int CloseSession(TcNsDevFile *dev, TcNsSession *session,
756 const unsigned char *uuid, unsigned int uuidLen, unsigned int sessionId)
757 {
758 TcNsClientContext context;
759 int ret;
760 errno_t sret;
761 bool checkValue = false;
762
763 checkValue = (dev == NULL || session == NULL ||
764 uuid == NULL || uuidLen != UUID_LEN);
765 if (checkValue == true) {
766 return TEEC_ERROR_GENERIC;
767 }
768 sret = InitContext(&context, uuid, uuidLen);
769 if (sret != 0) {
770 return TEEC_ERROR_GENERIC;
771 }
772 context.sessionId = sessionId;
773 context.cmdId = GLOBAL_CMD_ID_CLOSE_SESSION;
774 ret = TcClientCall(&context, dev, session,
775 TC_CALL_GLOBAL | TC_CALL_SYNC);
776 if (ret) {
777 tloge("close session failed, ret=0x%x\n", ret);
778 }
779 return ret;
780 }
781
KillSession(TcNsDevFile * dev,const unsigned char * uuid,unsigned int uuidLen,unsigned int sessionId)782 void KillSession(TcNsDevFile *dev, const unsigned char *uuid,
783 unsigned int uuidLen, unsigned int sessionId)
784 {
785 TcNsClientContext context;
786 int ret;
787 errno_t sret;
788
789 if (dev == NULL || uuid == NULL || uuidLen != UUID_LEN) {
790 return;
791 }
792 sret = InitContext(&context, uuid, uuidLen);
793 if (sret != 0) {
794 return;
795 }
796 context.sessionId = sessionId;
797 context.cmdId = GLOBAL_CMD_ID_KILL_TASK;
798 tlogd("devFileId=%u\n", dev->devFileId);
799 /* do clear work in agent */
800 TeeAgentClearWork(&context, dev->devFileId);
801 ret = TcClientCall(&context, dev, NULL,
802 TC_CALL_GLOBAL | TC_CALL_SYNC);
803 if (ret) {
804 tloge("close session failed, ret=0x%x\n", ret);
805 }
806 return;
807 }
808
TcNsServiceInit(const unsigned char * uuid,uint32_t uuidLen,TcNsService ** newService)809 int TcNsServiceInit(const unsigned char *uuid, uint32_t uuidLen,
810 TcNsService **newService)
811 {
812 int ret = 0;
813 TcNsService *service = NULL;
814 errno_t sret;
815 bool checkValue = false;
816
817 checkValue = (uuid == NULL || newService == NULL ||
818 uuidLen != UUID_LEN);
819 if (checkValue == true) {
820 return -ENOMEM;
821 }
822 service = calloc(1, sizeof(*service));
823 if (ZERO_OR_NULL_PTR((unsigned long)(uintptr_t)service)) {
824 tloge("calloc failed\n");
825 ret = -ENOMEM;
826 return ret;
827 }
828 sret = memcpy_s(service->uuid, sizeof(service->uuid), uuid, uuidLen);
829 if (sret != EOK) {
830 free(service);
831 return -ENOMEM;
832 }
833 INIT_LIST_HEAD(&service->sessionList);
834 mutex_init(&service->SessionLock);
835 list_add_tail(&service->head, GetServiceList());
836 tlogd("add service [0x%x] to service list\n", *(uint32_t *)uuid);
837 atomic_set(&service->usage, 1);
838 mutex_init(&service->operationLock);
839 *newService = service;
840 return ret;
841 }
842
TcNsGetUid(void)843 uint32_t TcNsGetUid(void)
844 {
845 return GetTaskUid(OsCurrTaskGet());
846 }
847
GetPackNameLen(TcNsDevFile * devFile,const uint8_t * certBuffer,unsigned int certBufferSize)848 int GetPackNameLen(TcNsDevFile *devFile, const uint8_t *certBuffer,
849 unsigned int certBufferSize)
850 {
851 errno_t sret;
852
853 if (devFile == NULL || certBuffer == NULL || certBufferSize == 0) {
854 return -ENOMEM;
855 }
856 sret = memcpy_s(&devFile->pkgNameLen, sizeof(devFile->pkgNameLen),
857 certBuffer, sizeof(devFile->pkgNameLen));
858 if (sret != EOK) {
859 return -ENOMEM;
860 }
861 tlogd("package_name_len is %u\n", devFile->pkgNameLen);
862 if (devFile->pkgNameLen == 0 ||
863 devFile->pkgNameLen >= MAX_PACKAGE_NAME_LEN) {
864 tloge("Invalid size of package name len login info!\n");
865 return -EINVAL;
866 }
867 return 0;
868 }
869
GetPublicKeyLen(TcNsDevFile * devFile,const uint8_t * certBuffer,unsigned int certBufferSize)870 int GetPublicKeyLen(TcNsDevFile *devFile, const uint8_t *certBuffer,
871 unsigned int certBufferSize)
872 {
873 errno_t sret;
874
875 if (devFile == NULL || certBuffer == NULL || certBufferSize == 0) {
876 return -ENOMEM;
877 }
878 sret = memcpy_s(&devFile->pubKeyLen, sizeof(devFile->pubKeyLen),
879 certBuffer, sizeof(devFile->pubKeyLen));
880 if (sret != EOK) {
881 return -ENOMEM;
882 }
883 tlogd("publick_key_len is %u\n", devFile->pubKeyLen);
884 if (devFile->pubKeyLen > MAX_PUBKEY_LEN) {
885 tloge("Invalid public key length in login info!\n");
886 return -EINVAL;
887 }
888 return 0;
889 }
890
IsValidTaSize(const char * fileBuffer,unsigned int fileSize)891 bool IsValidTaSize(const char *fileBuffer, unsigned int fileSize)
892 {
893 if (fileBuffer == NULL || fileSize == 0) {
894 tloge("invalid load ta size\n");
895 return false;
896 }
897 if (fileSize > SZ_8M) {
898 tloge("larger than 8M TA is not supportedi, size=%d\n", fileSize);
899 return false;
900 }
901 return true;
902 }
903
TcNsNeedLoadImage(unsigned int fileId,const unsigned char * uuid,unsigned int uuidLen)904 int TcNsNeedLoadImage(unsigned int fileId, const unsigned char *uuid,
905 unsigned int uuidLen)
906 {
907 int ret = 0;
908 int smcRet;
909 TcNsSmcCmd smcCmd = { {0}, 0 };
910 struct MbCmdPack *mbPack = NULL;
911 char *mbParam = NULL;
912
913 if (uuid == NULL || uuidLen != UUID_LEN) {
914 tloge("invalid uuid\n");
915 return -ENOMEM;
916 }
917 mbPack = MailboxAllocCmdPack();
918 if (mbPack == NULL) {
919 tloge("alloc mb pack failed\n");
920 return -ENOMEM;
921 }
922
923 mbParam = MailboxCopyAlloc((void *)uuid, uuidLen);
924 if (mbParam == NULL) {
925 tloge("alloc mb param failed\n");
926 ret = -ENOMEM;
927 goto clean;
928 }
929
930 mbPack->operation.paramTypes = TEEC_MEMREF_TEMP_INOUT;
931 mbPack->operation.params[0].memref.buffer = LOS_PaddrQuery((void *)mbParam);
932 mbPack->operation.bufferHaddr[0] = 0;
933 mbPack->operation.params[0].memref.size = SZ_4K;
934 smcCmd.cmdId = GLOBAL_CMD_ID_NEED_LOAD_APP;
935 smcCmd.globalCmd = true;
936 smcCmd.devFileId = fileId;
937 smcCmd.contextId = 0;
938 smcCmd.operationPhys = LOS_PaddrQuery(&mbPack->operation);
939 smcCmd.operationHphys = 0;
940 tlogd("secure app load smc command\n");
941 smcRet = TcNsSmc(&smcCmd);
942 if (smcRet != 0) {
943 tloge("smc_call returns error ret 0x%x\n", smcRet);
944 ret = -1;
945 goto clean;
946 } else {
947 ret = *(int *)mbParam;
948 }
949
950 clean:
951 if (mbParam != NULL) {
952 MailboxFree(mbParam);
953 }
954 MailboxFree(mbPack);
955
956 return ret;
957 }
958
TcNsLoadSecfile(TcNsDevFile * devFile,const void * argp)959 int TcNsLoadSecfile(TcNsDevFile *devFile,
960 const void *argp)
961 {
962 int ret;
963 struct LoadSecfileIoctlStruct ioctlArg = { 0, {0}, 0, { NULL } };
964
965 if (devFile == NULL || argp == NULL) {
966 tloge("Invalid params !\n");
967 return -EINVAL;
968 }
969 if (copy_from_user(&ioctlArg, argp, sizeof(ioctlArg))) {
970 tloge("copy from user failed\n");
971 ret = -ENOMEM;
972 return ret;
973 }
974 mutex_lock(&g_loadAppLock);
975 if (ioctlArg.secfileType == LOAD_TA) {
976 ret = TcNsNeedLoadImage(devFile->devFileId,
977 ioctlArg.uuid, (unsigned int)UUID_LEN);
978 if (ret == 1) { // 1 means we need to load image
979 ret = TcNsLoadImage(devFile, ioctlArg.fileBuffer,
980 ioctlArg.fileSize);
981 }
982 } else if (ioctlArg.secfileType == LOAD_LIB) {
983 ret = TcNsLoadImage(devFile,
984 ioctlArg.fileBuffer, ioctlArg.fileSize);
985 } else {
986 tloge("invalid secfile type: %d!", ioctlArg.secfileType);
987 ret = -EINVAL;
988 }
989
990 if (ret) {
991 tloge("load TA secfile: %d failed, ret = %x", ioctlArg.secfileType, ret);
992 }
993 mutex_unlock(&g_loadAppLock);
994 return ret;
995 }
996
LoadTaImage(TcNsDevFile * devFile,TcNsClientContext * context)997 int LoadTaImage(TcNsDevFile *devFile, TcNsClientContext *context)
998 {
999 int ret;
1000
1001 if (devFile == NULL || context == NULL) {
1002 return -1;
1003 }
1004 mutex_lock(&g_loadAppLock);
1005 ret = TcNsNeedLoadImage(devFile->devFileId, context->uuid,
1006 (unsigned int)UUID_LEN);
1007 if (ret == 1) {
1008 if (context->fileBuffer == NULL) {
1009 tloge("context's fileBuffer is NULL");
1010 mutex_unlock(&g_loadAppLock);
1011 return -1;
1012 }
1013 ret = TcNsLoadImage(devFile, context->fileBuffer,
1014 context->fileSize);
1015 if (ret) {
1016 tloge("load image failed, ret=%x", ret);
1017 mutex_unlock(&g_loadAppLock);
1018 return ret;
1019 }
1020 }
1021 mutex_unlock(&g_loadAppLock);
1022 return ret;
1023 }
1024
ReleaseFreeSession(TcNsDevFile * devFile,TcNsClientContext * context,TcNsSession * session)1025 void ReleaseFreeSession(TcNsDevFile *devFile,
1026 TcNsClientContext *context, TcNsSession *session)
1027 {
1028 bool needKillSession = false;
1029 #ifdef SECURITY_AUTH_ENHANCE
1030 bool needFree = false;
1031 #endif
1032
1033 if (devFile == NULL || context == NULL || session == NULL) {
1034 return;
1035 }
1036 needKillSession = context->sessionId != 0;
1037 if (needKillSession) {
1038 KillSession(devFile, context->uuid, (unsigned int)UUID_LEN, context->sessionId);
1039 }
1040 #ifdef SECURITY_AUTH_ENHANCE
1041 needFree = (session != NULL &&
1042 session->TcNsToken.tokenBuffer != NULL);
1043 if (needFree) {
1044 if (memset_s((void *)session->TcNsToken.tokenBuffer,
1045 session->TcNsToken.tokenLen,
1046 0, session->TcNsToken.tokenLen) != EOK) {
1047 tloge("Caution, memset failed!\n");
1048 }
1049 free(session->TcNsToken.tokenBuffer);
1050 session->TcNsToken.tokenBuffer = NULL;
1051 }
1052 #endif
1053 }
1054
CloseSessionInServiceList(TcNsDevFile * dev,TcNsService * service,uint32_t index)1055 void CloseSessionInServiceList(TcNsDevFile *dev, TcNsService *service,
1056 uint32_t index)
1057 {
1058 TcNsSession *tmpSession = NULL;
1059 TcNsSession *session = NULL;
1060 errno_t retErr;
1061 int ret;
1062
1063 if (dev == NULL || service == NULL || index >= SERVICES_MAX_COUNT) {
1064 return;
1065 }
1066 list_for_each_entry_safe(session, tmpSession,
1067 &dev->services[index]->sessionList, head) {
1068 if (session->owner != dev) {
1069 continue;
1070 }
1071 ret = CloseSession(dev, session, service->uuid,
1072 (unsigned int)UUID_LEN, session->sessionId);
1073 if (ret != TEEC_SUCCESS) {
1074 tloge("close session smc(when close fd) failed!\n");
1075 }
1076 #ifdef SECURITY_AUTH_ENHANCE
1077 /* Clean session secure information */
1078 retErr = memset_s((void *)&session->secureInfo,
1079 sizeof(session->secureInfo),
1080 0,
1081 sizeof(session->secureInfo));
1082 if (retErr != EOK) {
1083 tloge("TcNsClientClose memset error=%d\n", retErr);
1084 }
1085 #endif
1086 mutex_lock(&service->SessionLock);
1087 list_del(&session->head);
1088 mutex_unlock(&service->SessionLock);
1089 PutSessionStruct(session); /* pair with open session */
1090 }
1091 }
1092
CloseUnclosedSession(TcNsDevFile * dev,uint32_t index)1093 void CloseUnclosedSession(TcNsDevFile *dev, uint32_t index)
1094 {
1095 TcNsService *service = NULL;
1096
1097 if (dev == NULL || index >= SERVICES_MAX_COUNT) {
1098 return;
1099 }
1100 if (dev->services[index] != NULL &&
1101 !list_empty(&dev->services[index]->sessionList)) {
1102 service = dev->services[index];
1103
1104 mutex_lock(&service->operationLock);
1105 CloseSessionInServiceList(dev, service, index);
1106 mutex_unlock(&service->operationLock);
1107 PutServiceStruct(service); /* pair with open session */
1108 }
1109 }
1110
DelDevNode(TcNsDevFile * dev)1111 void DelDevNode(TcNsDevFile *dev)
1112 {
1113 if (dev == NULL) {
1114 return;
1115 }
1116 mutex_lock(&GetTcNsDevList()->devLock);
1117 /* del dev from the list */
1118 list_del(&dev->head);
1119 mutex_unlock(&GetTcNsDevList()->devLock);
1120 }
1121
NsClientCloseTeecdNotAgent(TcNsDevFile * dev)1122 int NsClientCloseTeecdNotAgent(TcNsDevFile *dev)
1123 {
1124 if (dev == NULL) {
1125 tloge("invalid dev(null)\n");
1126 return TEEC_ERROR_GENERIC;
1127 }
1128 DelDevNode(dev);
1129 free(dev);
1130 return TEEC_SUCCESS;
1131 }
1132