• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 *)&paramsIn->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 *)&paramsIn->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(&paramsIn,
341         &secureParamsAlignedSize, &paramsSize);
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(&paramsIn, reeSecureParams);
351     if (ret != 0) {
352         goto free;
353     }
354 
355     ret = UpdateSecureParamsFromTee(&paramsIn, 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, &param);
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