• 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 "teek_client_api.h"
33 #include <securec.h>
34 #include "tc_ns_log.h"
35 #include "tzdriver_compat.h"
36 
EncdeForPartMem(TcNsClientContext * cliContext,const TeecOperation * operation,uint32_t paramCnt,uint32_t * paramType)37 static void EncdeForPartMem(TcNsClientContext *cliContext,
38     const TeecOperation *operation, uint32_t paramCnt, uint32_t *paramType)
39 {
40     uint32_t diff = (uint32_t)TEEC_MEMREF_PARTIAL_INPUT -
41         (uint32_t)TEEC_MEMREF_TEMP_INPUT;
42 
43     if (paramCnt < TEE_PARAM_NUM) {
44         /* buffer offset len */
45         if (paramType[paramCnt] == TEEC_MEMREF_WHOLE) {
46             cliContext->params[paramCnt].memref.offset = 0;
47             cliContext->params[paramCnt].memref.sizeAddr =
48                 (uint64_t)(uintptr_t)&operation->params[paramCnt].memref.parent->size;
49         } else {
50             cliContext->params[paramCnt].memref.offset =
51                 operation->params[paramCnt].memref.offset;
52             cliContext->params[paramCnt].memref.sizeAddr =
53                 (uint64_t)(uintptr_t)&operation->params[paramCnt].memref.size;
54         }
55         if (operation->params[paramCnt].memref.parent->isAllocated) {
56             cliContext->params[paramCnt].memref.buffer =
57                 (uint64_t)(uintptr_t)
58                 operation->params[paramCnt].memref.parent->buffer;
59         } else {
60             cliContext->params[paramCnt].memref.buffer =
61                 (uint64_t)(uintptr_t)
62                 operation->params[paramCnt].memref.parent->buffer +
63                 operation->params[paramCnt].memref.offset;
64             cliContext->params[paramCnt].memref.offset = 0;
65         }
66         /* translate the paramType to know the driver */
67         if (paramType[paramCnt] == TEEC_MEMREF_WHOLE) {
68             switch (operation->params[paramCnt].memref.parent->flags) {
69                 case TEEC_MEM_INPUT:
70                     paramType[paramCnt] = TEEC_MEMREF_PARTIAL_INPUT;
71                     break;
72                 case TEEC_MEM_OUTPUT:
73                     paramType[paramCnt] = TEEC_MEMREF_PARTIAL_OUTPUT;
74                     break;
75                 case TEEC_MEM_INOUT:
76                     paramType[paramCnt] = TEEC_MEMREF_PARTIAL_INOUT;
77                     break;
78                 default:
79                     paramType[paramCnt] = TEEC_MEMREF_PARTIAL_INOUT;
80                     break;
81             }
82         }
83         /* if is not allocated, translate TEEC_MEMREF_PARTIAL_XXX to TEEC_MEMREF_TEMP_XXX */
84         if (!operation->params[paramCnt].memref.parent->isAllocated) {
85             paramType[paramCnt] = paramType[paramCnt] - diff;
86         }
87     }
88     return;
89 }
90 
ProcTeekEncode(TcNsClientContext * cliContext,const TeecOperation * operation)91 static TeecResult ProcTeekEncode(TcNsClientContext *cliContext,
92     const TeecOperation *operation)
93 {
94     bool checkValue = false;
95     bool checkTempMem = false;
96     bool checkPartMem = false;
97     uint32_t paramType[TEE_PARAM_NUM];
98     uint32_t paramCnt;
99 
100     paramType[TEE_PARAM_ONE] =
101         TEEC_PARAM_TYPE_GET(operation->paramTypes, TEE_PARAM_ONE);
102     paramType[TEE_PARAM_TWO] =
103         TEEC_PARAM_TYPE_GET(operation->paramTypes, TEE_PARAM_TWO);
104     paramType[TEE_PARAM_THREE] =
105         TEEC_PARAM_TYPE_GET(operation->paramTypes, TEE_PARAM_THREE);
106     paramType[TEE_PARAM_FOUR] =
107         TEEC_PARAM_TYPE_GET(operation->paramTypes, TEE_PARAM_FOUR);
108     for (paramCnt = 0; paramCnt < TEE_PARAM_NUM; paramCnt++) {
109         checkTempMem = paramType[paramCnt] == TEEC_MEMREF_TEMP_INPUT ||
110             paramType[paramCnt] == TEEC_MEMREF_TEMP_OUTPUT ||
111             paramType[paramCnt] == TEEC_MEMREF_TEMP_INOUT;
112         checkPartMem = paramType[paramCnt] == TEEC_MEMREF_WHOLE ||
113             paramType[paramCnt] == TEEC_MEMREF_PARTIAL_INPUT ||
114             paramType[paramCnt] == TEEC_MEMREF_PARTIAL_OUTPUT ||
115             paramType[paramCnt] == TEEC_MEMREF_PARTIAL_INOUT;
116         checkValue = paramType[paramCnt] == TEEC_VALUE_INPUT ||
117             paramType[paramCnt] == TEEC_VALUE_OUTPUT ||
118             paramType[paramCnt] == TEEC_VALUE_INOUT;
119         if (checkTempMem == true) {
120             cliContext->params[paramCnt].memref.buffer =
121                 (uint64_t)(uintptr_t)(operation->params[paramCnt].tmpref.buffer);
122             cliContext->params[paramCnt].memref.sizeAddr =
123                 (uint64_t)(uintptr_t)(&operation->params[paramCnt].tmpref.size);
124         } else if (checkPartMem == true) {
125             EncdeForPartMem(cliContext, operation,
126                 paramCnt, paramType);
127         } else if (checkValue == true) {
128             cliContext->params[paramCnt].value.aAddr =
129                 (uint64_t)(uintptr_t)(&operation->params[paramCnt].value.a);
130             cliContext->params[paramCnt].value.bAddr =
131                 (uint64_t)(uintptr_t)(&operation->params[paramCnt].value.b);
132         } else if (paramType[paramCnt] == TEEC_NONE) {
133             /* do nothing */
134         } else {
135             tloge("paramType[%u]=%u not correct\n", paramCnt,
136                 paramType[paramCnt]);
137             return (TeecResult)TEEC_ERROR_BAD_PARAMETERS;
138         }
139     }
140     cliContext->paramTypes = TEEC_PARAM_TYPES(paramType[TEE_PARAM_ONE],
141         paramType[TEE_PARAM_TWO], paramType[TEE_PARAM_THREE],
142         paramType[TEE_PARAM_FOUR]);
143     return TEEC_SUCCESS;
144 }
145 
146 struct TeekEncodeMeg {
147     TeecUuid serviceId;
148     uint32_t sessionId;
149     uint32_t cmdId;
150 };
151 
TeekEncode(TcNsClientContext * cliContext,struct TeekEncodeMeg * msg,const TcNsClientLogin * cliLogin,const TeecOperation * operation)152 static TeecResult TeekEncode(TcNsClientContext *cliContext,
153     struct TeekEncodeMeg *msg,
154     const TcNsClientLogin *cliLogin, const TeecOperation *operation)
155 {
156     TeecResult ret;
157     errno_t sret;
158 
159     if (cliContext == NULL || cliLogin == NULL) {
160         tloge("cliContext or cliLogin is null.\n");
161         return (TeecResult)TEEC_ERROR_BAD_PARAMETERS;
162     }
163     sret = memset_s(cliContext, sizeof(*cliContext),
164         0x00, sizeof(*cliContext));
165     if (sret != EOK) {
166         tloge("memset error sret is %d.\n", sret);
167         return (TeecResult)TEEC_ERROR_BAD_PARAMETERS;
168     }
169     sret = memcpy_s(cliContext->uuid, sizeof(cliContext->uuid),
170         (uint8_t *)&msg->serviceId, sizeof(msg->serviceId));
171     if (sret != EOK) {
172         tloge("memcpy error sret is %d.\n", sret);
173         return (TeecResult)TEEC_ERROR_BAD_PARAMETERS;
174     }
175     cliContext->sessionId = msg->sessionId;
176     cliContext->cmdId = msg->cmdId;
177     cliContext->returns.code = 0;
178     cliContext->returns.origin = 0;
179     cliContext->login.method = cliLogin->method;
180     cliContext->login.mdata = cliLogin->mdata;
181     /* support when operation is null */
182     if (operation == NULL) {
183         return TEEC_SUCCESS;
184     }
185     cliContext->started = operation->cancelFlag;
186     ret = ProcTeekEncode(cliContext, operation);
187     tlogv("cli param type %u\n", cliContext->paramTypes);
188     return ret;
189 }
190 
TeekCheckTmpRef(TeecTempmemoryReference tmpref)191 static TeecResult TeekCheckTmpRef(TeecTempmemoryReference tmpref)
192 {
193     TeecResult ret;
194     bool checkValue = (tmpref.buffer == NULL) || (tmpref.size == 0);
195 
196     if (checkValue == true) {
197         tloge("tmpref buffer is null, or size is zero\n");
198         ret = (TeecResult) TEEC_ERROR_BAD_PARAMETERS;
199     } else {
200         ret = (TeecResult) TEEC_SUCCESS;
201     }
202     return ret;
203 }
204 
TeekCheckMemRef(TeecRegisteredmemoryReference memref,uint32_t paramType)205 static TeecResult TeekCheckMemRef(TeecRegisteredmemoryReference memref,
206     uint32_t paramType)
207 {
208     bool checkValue = (memref.parent == NULL) || (memref.parent->buffer == NULL);
209     bool checkOffset = false;
210 
211     if (checkValue == true) {
212         tloge("parent of memref is null, or the buffer is zero\n");
213         return (TeecResult) TEEC_ERROR_BAD_PARAMETERS;
214     }
215     if (paramType == TEEC_MEMREF_PARTIAL_INPUT) {
216         if (!(memref.parent->flags & TEEC_MEM_INPUT)) {
217             return (TeecResult) TEEC_ERROR_BAD_PARAMETERS;
218         }
219     } else if (paramType == TEEC_MEMREF_PARTIAL_OUTPUT) {
220         if (!(memref.parent->flags & TEEC_MEM_OUTPUT)) {
221             return (TeecResult) TEEC_ERROR_BAD_PARAMETERS;
222         }
223     } else if (paramType == TEEC_MEMREF_PARTIAL_INOUT) {
224         if (!(memref.parent->flags & TEEC_MEM_INPUT)) {
225             return (TeecResult) TEEC_ERROR_BAD_PARAMETERS;
226         }
227         if (!(memref.parent->flags & TEEC_MEM_OUTPUT)) {
228             return (TeecResult) TEEC_ERROR_BAD_PARAMETERS;
229         }
230     } else if (paramType == TEEC_MEMREF_WHOLE) {
231         /* if type is TEEC_MEMREF_WHOLE, ignore it */
232     } else {
233         return (TeecResult)TEEC_ERROR_BAD_PARAMETERS;
234     }
235 
236     checkValue = (paramType == TEEC_MEMREF_PARTIAL_INPUT) ||
237         (paramType == TEEC_MEMREF_PARTIAL_OUTPUT) ||
238         (paramType == TEEC_MEMREF_PARTIAL_INOUT);
239     if (checkValue == true) {
240         checkOffset = (memref.offset + memref.size) > memref.parent->size ||
241             (memref.offset + memref.size) < memref.offset ||
242             (memref.offset + memref.size) < memref.size;
243         if (checkOffset == true) {
244             tloge("offset + size exceed the parent size\n");
245             return (TeecResult) TEEC_ERROR_BAD_PARAMETERS;
246         }
247     }
248     return (TeecResult) TEEC_SUCCESS;
249 }
250 
251 /*
252  * This function checks an operation is valid or not.
253  */
TeekCheckOperation(const TeecOperation * operation)254 TeecResult TeekCheckOperation(const TeecOperation *operation)
255 {
256     uint32_t paramType[TEE_PARAM_NUM] = {0};
257     uint32_t paramCnt;
258     TeecResult ret = TEEC_SUCCESS;
259     bool checkValue = false;
260     bool checkTempMem = false;
261     bool checkPartMem = false;
262 
263     /* GP Support operation is NULL
264      * operation: a pointer to a Client Application initialized TeecOperation structure,
265      * or NULL if there is no payload to send or if the Command does not need to support
266      * cancellation.
267      */
268     if (operation == NULL) {
269         return (TeecResult)TEEC_SUCCESS;
270     }
271     if (!operation->started) {
272         tloge("sorry, cancellation not support\n");
273         return (TeecResult) TEEC_ERROR_NOT_IMPLEMENTED;
274     }
275     paramType[TEE_PARAM_ONE] = TEEC_PARAM_TYPE_GET(operation->paramTypes, TEE_PARAM_ONE);
276     paramType[TEE_PARAM_TWO] = TEEC_PARAM_TYPE_GET(operation->paramTypes, TEE_PARAM_TWO);
277     paramType[TEE_PARAM_THREE] = TEEC_PARAM_TYPE_GET(operation->paramTypes, TEE_PARAM_THREE);
278     paramType[TEE_PARAM_FOUR] = TEEC_PARAM_TYPE_GET(operation->paramTypes, TEE_PARAM_FOUR);
279     for (paramCnt = 0; paramCnt < TEE_PARAM_NUM; paramCnt++) {
280         checkTempMem = paramType[paramCnt] == TEEC_MEMREF_TEMP_INPUT ||
281             paramType[paramCnt] == TEEC_MEMREF_TEMP_OUTPUT || paramType[paramCnt] == TEEC_MEMREF_TEMP_INOUT;
282         checkPartMem = paramType[paramCnt] == TEEC_MEMREF_WHOLE ||
283             paramType[paramCnt] == TEEC_MEMREF_PARTIAL_INPUT ||
284             paramType[paramCnt] == TEEC_MEMREF_PARTIAL_OUTPUT ||
285             paramType[paramCnt] == TEEC_MEMREF_PARTIAL_INOUT;
286         checkValue = paramType[paramCnt] == TEEC_VALUE_INPUT ||
287             paramType[paramCnt] == TEEC_VALUE_OUTPUT || paramType[paramCnt] == TEEC_VALUE_INOUT;
288         if (checkTempMem == true) {
289             ret = TeekCheckTmpRef(operation->params[paramCnt].tmpref);
290             if (ret != TEEC_SUCCESS) {
291                 break;
292             }
293         } else if (checkPartMem == true) {
294             ret = TeekCheckMemRef(operation->params[paramCnt].memref, paramType[paramCnt]);
295             if (ret != TEEC_SUCCESS) {
296                 break;
297             }
298         } else if (checkValue == true) {
299             /* if type is value, ignore it */
300         } else if (paramType[paramCnt] == TEEC_NONE) {
301             /* if type is none, ignore it */
302         } else {
303             tloge("paramType[%u]=%x is not support\n", paramCnt, paramType[paramCnt]);
304             ret = (TeecResult) TEEC_ERROR_BAD_PARAMETERS;
305             break;
306         }
307     }
308     return ret;
309 }
310 
311 /*
312  * This function check if the special agent is launched.Used For HDCP key.
313  * e.g. If sfs agent is not alive, you can not do HDCP key write to SRAM.
314  */
TeekIsAgentAlive(unsigned int agentId)315 int TeekIsAgentAlive(unsigned int agentId)
316 {
317     return IsAgentAlive(agentId);
318 }
319 
320 /*
321  * This function initializes a new TEE Context, forming a connection between this Client Application
322  * and the TEE identified by the string identifier name.
323  */
TeekInitializeContext(const char * name,TeecContext * context)324 TeecResult TeekInitializeContext(const char *name, TeecContext *context)
325 {
326     int32_t ret;
327 
328     /* name current not used */
329     (void)(name);
330     tlogd("TeekInitializeContext Started:\n");
331     /* First, check parameters is valid or not */
332     if (context == NULL) {
333         tloge("context is null, not correct\n");
334         return (TeecResult) TEEC_ERROR_BAD_PARAMETERS;
335     }
336     context->dev = NULL;
337     /* Paramters right, start execution */
338     ret = TcNsClientOpen((TcNsDevFile **)&context->dev,
339         TEE_REQ_FROM_KERNEL_MODE);
340     if (ret != TEEC_SUCCESS) {
341         tloge("open device failed\n");
342         return (TeecResult) TEEC_ERROR_GENERIC;
343     }
344     tlogd("open device success\n");
345     TEEK_INIT_LIST_HEAD(&context->sessionList);
346     TEEK_INIT_LIST_HEAD(&context->shrdMemList);
347     return TEEC_SUCCESS;
348 }
349 
350 /*
351  * This function finalizes an initialized TEE Context.
352  */
TeekFinalizeContext(TeecContext * context)353 void TeekFinalizeContext(TeecContext *context)
354 {
355     struct ListNode *ptr = NULL;
356     TeecSession *session = NULL;
357     /* TeecSharedMemory* shrdmem */
358     tlogd("TeekFinalizeContext started\n");
359     /* First, check parameters is valid or not */
360     if (context == NULL || context->dev == NULL) {
361         tloge("context or dev is null, not correct\n");
362         return;
363     }
364     /* Paramters right, start execution */
365     if (!LIST_EMPTY(&context->sessionList)) {
366         tlogi("context still has sessions opened, close it\n");
367         LIST_FOR_EACH(ptr, &context->sessionList) {
368             session = list_entry(ptr, TeecSession, head);
369             TeekCloseSession(session);
370         }
371     }
372     tlogd("close device\n");
373     TcNsClientClose(context->dev);
374     context->dev = NULL;
375 }
376 
CheckParamsForOpenSession(TeecContext * context,const TeecOperation * operation,TcNsClientLogin * cliLogin)377 static TeecResult CheckParamsForOpenSession(TeecContext *context,
378     const TeecOperation *operation, TcNsClientLogin *cliLogin)
379 {
380     bool checkValue = false;
381     TcNsDevFile *devFile = NULL;
382     TeecResult teecRet;
383     errno_t sret;
384     uint32_t paramType[TEE_PARAM_NUM] = {0};
385 
386     paramType[TEE_PARAM_FOUR] = TEEC_PARAM_TYPE_GET(operation->paramTypes, TEE_PARAM_FOUR);
387     paramType[TEE_PARAM_THREE] = TEEC_PARAM_TYPE_GET(operation->paramTypes, TEE_PARAM_THREE);
388     checkValue = paramType[TEE_PARAM_FOUR] != TEEC_MEMREF_TEMP_INPUT ||
389         paramType[TEE_PARAM_THREE] != TEEC_MEMREF_TEMP_INPUT;
390     if (checkValue == true) {
391         tloge("invalid param type 0x%x\n", operation->paramTypes);
392         return (TeecResult)TEEC_ERROR_BAD_PARAMETERS;
393     }
394     checkValue = operation->params[TEE_PARAM_FOUR].tmpref.buffer == NULL ||
395         operation->params[TEE_PARAM_THREE].tmpref.buffer == NULL ||
396         operation->params[TEE_PARAM_FOUR].tmpref.size == 0 || operation->params[TEE_PARAM_THREE].tmpref.size == 0;
397     if (checkValue == true) {
398         tloge("invalid operation params(NULL)\n");
399         return (TeecResult)TEEC_ERROR_BAD_PARAMETERS;
400     }
401     cliLogin->method = TEEC_LOGIN_IDENTIFY;
402     devFile = (TcNsDevFile *)(context->dev);
403     if (devFile == NULL) {
404         tloge("invalid context->dev (NULL)\n");
405         return (TeecResult)TEEC_ERROR_BAD_PARAMETERS;
406     }
407     devFile->pkgNameLen = operation->params[TEE_PARAM_FOUR].tmpref.size;
408     if (operation->params[TEE_PARAM_FOUR].tmpref.size > (MAX_PACKAGE_NAME_LEN - 1)) {
409         return (TeecResult)TEEC_ERROR_BAD_PARAMETERS;
410     } else {
411         sret = memset_s(devFile->PkgName, sizeof(devFile->PkgName), 0, MAX_PACKAGE_NAME_LEN);
412         if (sret != EOK) {
413             tloge("memset error sret is %d.\n", sret);
414             return (TeecResult)TEEC_ERROR_BAD_PARAMETERS;
415         }
416         sret = memcpy_s(devFile->PkgName, sizeof(devFile->PkgName), operation->params[TEE_PARAM_FOUR].tmpref.buffer,
417             operation->params[TEE_PARAM_FOUR].tmpref.size);
418         if (sret != EOK) {
419             tloge("memcpy error sret is %d.\n", sret);
420             return (TeecResult)TEEC_ERROR_BAD_PARAMETERS;
421         }
422     }
423     devFile->pubKeyLen = 0;
424     devFile->loginSetup = 1;
425     teecRet = TeekCheckOperation(operation);
426     if (teecRet != TEEC_SUCCESS) {
427         tloge("operation is invalid\n");
428         return (TeecResult)TEEC_ERROR_BAD_PARAMETERS;
429     }
430     return teecRet;
431 }
432 
OpenSessionAndSwitchRet(TeecSession * session,TeecContext * context,const TeecUuid * destination,TcNsClientContext * cliContext,uint32_t * origin)433 static TeecResult OpenSessionAndSwitchRet(TeecSession *session,
434     TeecContext *context, const TeecUuid *destination,
435     TcNsClientContext *cliContext, uint32_t *origin)
436 {
437     int32_t ret;
438     TeecResult teecRet;
439 
440     ret = TcNsOpenSession(context->dev, cliContext);
441     if (ret == 0) {
442         tlogd("open session success\n");
443         session->sessionId = cliContext->sessionId;
444         session->serviceId = *destination;
445         session->opsCnt = 0;
446         TEEK_INIT_LIST_HEAD(&session->head);
447         ListInsertTail(&context->sessionList, &session->head);
448         session->context = context;
449         return TEEC_SUCCESS;
450     } else if (ret < 0) {
451         tloge("open session failed, ioctl errno = %u\n", ret);
452         if (ret == -EFAULT) {
453             teecRet = (TeecResult) TEEC_ERROR_ACCESS_DENIED;
454         } else if (ret == -ENOMEM) {
455             teecRet = (TeecResult) TEEC_ERROR_OUT_OF_MEMORY;
456         } else if (ret == -EINVAL) {
457             teecRet = (TeecResult) TEEC_ERROR_BAD_PARAMETERS;
458         } else if (ret == -ERESTARTSYS) {
459             teecRet = (TeecResult) TEEC_CLIENT_INTR;
460         } else {
461             teecRet = (TeecResult) TEEC_ERROR_GENERIC;
462         }
463         *origin = TEEC_ORIGIN_COMMS;
464         return teecRet;
465     } else {
466         tloge("open session failed, code=0x%x, origin=%u\n", cliContext->returns.code,
467               cliContext->returns.origin);
468         teecRet = (TeecResult)cliContext->returns.code;
469         *origin = cliContext->returns.origin;
470     }
471     return teecRet;
472 }
473 
474 /*
475  * Function:       TEEC_OpenSession
476  * Description:   This function opens a new Session
477  * Parameters:   context: a pointer to an initialized TEE Context.
478  * session: a pointer to a Session structure to open.
479  * destination: a pointer to a UUID structure.
480  * connectionMethod: the method of connection to use.
481  * connectionData: any necessary data required to support the connection method chosen.
482  * operation: a pointer to an Operation containing a set of Parameters.
483  * returnOrigin: a pointer to a variable which will contain the return origin.
484  * Return: TEEC_SUCCESS: success other: failure
485  */
ProcTeekOpenSession(TeecContext * context,TeecSession * session,const TeecUuid * destination,uint32_t connectionMethod,const void * connectionData,const TeecOperation * operation,uint32_t * returnOrigin)486 static TeecResult ProcTeekOpenSession(TeecContext *context,
487     TeecSession *session, const TeecUuid *destination,
488     uint32_t connectionMethod, const void *connectionData,
489     const TeecOperation *operation, uint32_t *returnOrigin)
490 {
491     TeecResult teecRet;
492     uint32_t origin = TEEC_ORIGIN_API;
493     TcNsClientContext cliContext;
494     TcNsClientLogin cliLogin = { 0, 0 };
495     bool checkValue = false;
496 
497     tlogd("TeekOpenSession Started:\n");
498     /* connectionData current not used */
499     (void)(connectionData);
500     /* returnOrigin maybe null, so only when it is valid, we set
501      * origin(error come from which module)
502      */
503     if (returnOrigin != NULL) {
504         *returnOrigin = origin;
505     }
506     /* First, check parameters is valid or not */
507     checkValue = (context == NULL || operation == NULL ||
508         connectionMethod != TEEC_LOGIN_IDENTIFY);
509     if (checkValue == true || destination == NULL || session == NULL) {
510         tloge("invalid input params\n");
511         return TEEC_ERROR_BAD_PARAMETERS;
512     }
513     teecRet = CheckParamsForOpenSession(context, operation, &cliLogin);
514     if (teecRet != TEEC_SUCCESS) {
515         goto RET_FAIL;
516     }
517     /* Paramters right, start execution
518      * note:before open session success,
519      * we should send session=0 as initial state.
520      */
521     struct TeekEncodeMeg msg = {
522         *destination, 0, GLOBAL_CMD_ID_OPEN_SESSION
523     };
524     teecRet = TeekEncode(&cliContext, &msg, &cliLogin, operation);
525     if (teecRet != TEEC_SUCCESS) {
526         tloge("encode failed\n");
527         goto RET_FAIL;
528     }
529 #ifdef SECURITY_AUTH_ENHANCE
530     cliContext.teecToken = session->teecToken;
531     cliContext.tokenLen = sizeof(session->teecToken);
532 #endif
533     teecRet = OpenSessionAndSwitchRet(session, context,
534         destination, &cliContext, &origin);
535     /* ONLY when ioctl returnCode!=0 and returnOrigin not NULL, set returnOrigin */
536     if (teecRet != TEEC_SUCCESS && returnOrigin != NULL) {
537         *returnOrigin = origin;
538     }
539 RET_FAIL:
540     return teecRet;
541 }
542 
543 #define RETRY_TIMES 5
TeekOpenSession(TeecContext * context,TeecSession * session,const TeecUuid * destination,uint32_t connectionMethod,const void * connectionData,const TeecOperation * operation,uint32_t * returnOrigin)544 TeecResult TeekOpenSession(TeecContext *context,
545     TeecSession *session, const TeecUuid *destination,
546     uint32_t connectionMethod, const void *connectionData,
547     const TeecOperation *operation, uint32_t *returnOrigin)
548 {
549     int i;
550     TeecResult ret;
551 
552     for (i = 0; i < RETRY_TIMES; i++) {
553         ret = ProcTeekOpenSession(context, session,
554             destination, connectionMethod, connectionData,
555             operation, returnOrigin);
556         if (ret != (TeecResult)TEEC_CLIENT_INTR) {
557             return ret;
558         }
559     }
560     return ret;
561 }
562 
CheckCloseSessionParam(TeecSession * session)563 static int CheckCloseSessionParam(TeecSession *session)
564 {
565     bool checkValue = false;
566     bool found = false;
567     TeecSession *tempSess = NULL;
568     struct ListNode *ptr = NULL;
569 
570     /* First, check parameters is valid or not */
571     checkValue = session == NULL || session->context == NULL;
572     if (checkValue || session->context->dev == NULL) {
573         tloge("input invalid session or session->context is null\n");
574         return -1;
575     }
576     LIST_FOR_EACH(ptr, &session->context->sessionList) {
577         tempSess = list_entry(ptr, TeecSession, head);
578         if (tempSess == session) {
579             found = true;
580             break;
581         }
582     }
583     if (!found) {
584         tloge("session is not in the context list\n");
585         return -1;
586     }
587     return 0;
588 }
589 
590 /*
591  * This function closes an opened Session.
592  */
TeekCloseSession(TeecSession * session)593 void TeekCloseSession(TeecSession *session)
594 {
595     int32_t ret;
596     TcNsClientContext cliContext;
597     TcNsClientLogin cliLogin = { 0, 0 };
598     errno_t sret;
599 
600     tlogd("TeekCloseSession started\n");
601     ret = CheckCloseSessionParam(session);
602     if (ret) {
603         return;
604     }
605     /* Paramters all right, start execution */
606     if (session->opsCnt) {
607         tloge("session still has commands running\n");
608     }
609     struct TeekEncodeMeg msg = {
610         session->serviceId, session->sessionId, GLOBAL_CMD_ID_CLOSE_SESSION
611     };
612     if (TeekEncode(&cliContext, &msg, &cliLogin, NULL) != TEEC_SUCCESS) {
613         tloge("encode failed, just return\n");
614         return;
615     }
616 #ifdef SECURITY_AUTH_ENHANCE
617     cliContext.teecToken = session->teecToken;
618     cliContext.tokenLen = sizeof(session->teecToken);
619 #endif
620     ret = TcNsCloseSession(session->context->dev, &cliContext);
621     if (ret == 0) {
622         tlogd("close session success\n");
623         session->sessionId = 0;
624         sret = memset_s((uint8_t *)(&session->serviceId), sizeof(session->serviceId), 0x00, UUID_LEN);
625         /* TeekCloseSession is void so go on execute */
626         if (sret != EOK) {
627             tloge("memset error sret is %d.\n", sret);
628         }
629 #ifdef SECURITY_AUTH_ENHANCE
630         sret = memset_s(session->teecToken, TOKEN_SAVE_LEN, 0x00, TOKEN_SAVE_LEN);
631         if (sret != EOK) {
632             tloge("memset session's member error ret value is %d.\n", sret);
633         }
634 #endif
635         session->opsCnt = 0;
636         ListRemove(&session->head);
637         session->context = NULL;
638     } else {
639         tloge("close session failed\n");
640     }
641 }
642 
InvokeCmdAndSwitchRet(TeecSession * session,TcNsClientContext * cliContext,uint32_t * origin)643 static TeecResult InvokeCmdAndSwitchRet(TeecSession *session,
644     TcNsClientContext *cliContext, uint32_t *origin)
645 {
646     int32_t ret;
647     TeecResult teecRet;
648 
649     ret = TcNsSendCmd(session->context->dev, cliContext);
650     if (ret == 0) {
651         tlogd("invoke cmd success\n");
652         teecRet = TEEC_SUCCESS;
653     } else if (ret < 0) {
654         tloge("invoke cmd failed, ioctl errno = %d\n", ret);
655         if (ret == -EFAULT) {
656             teecRet = (TeecResult)TEEC_ERROR_ACCESS_DENIED;
657         } else if (ret == -ENOMEM) {
658             teecRet = (TeecResult)TEEC_ERROR_OUT_OF_MEMORY;
659         } else if (ret == -EINVAL) {
660             teecRet = (TeecResult)TEEC_ERROR_BAD_PARAMETERS;
661         } else {
662             teecRet = (TeecResult)TEEC_ERROR_GENERIC;
663         }
664         *origin = TEEC_ORIGIN_COMMS;
665     } else {
666         tloge("invoke cmd failed, code=0x%x, origin=%d\n",
667             cliContext->returns.code, cliContext->returns.origin);
668         teecRet = (TeecResult)cliContext->returns.code;
669         *origin = cliContext->returns.origin;
670     }
671     return teecRet;
672 }
673 
674 /* This function invokes a Command within the specified Session. */
TeekInvokeCommand(TeecSession * session,uint32_t commandID,TeecOperation * operation,uint32_t * returnOrigin)675 TeecResult TeekInvokeCommand(TeecSession *session, uint32_t commandID,
676     TeecOperation *operation, uint32_t *returnOrigin)
677 {
678     TeecResult teecRet = (TeecResult) TEEC_ERROR_BAD_PARAMETERS;
679     uint32_t origin = TEEC_ORIGIN_API;
680     TcNsClientContext cliContext;
681     TcNsClientLogin cliLogin = { 0, 0 };
682 
683     tlogd("TeekInvokeCommand Started:\n");
684     /* First, check parameters is valid or not */
685     if (session == NULL || session->context == NULL) {
686         tloge("input invalid session or session->context is null\n");
687         if (returnOrigin != NULL) {
688             *returnOrigin = origin;
689         }
690         return teecRet;
691     }
692     teecRet = TeekCheckOperation(operation);
693     if (teecRet != TEEC_SUCCESS) {
694         tloge("operation is invalid\n");
695         if (returnOrigin != NULL) {
696             *returnOrigin = origin;
697         }
698         return teecRet;
699     }
700     /* Paramters all right, start execution */
701     session->opsCnt++;
702     struct TeekEncodeMeg msg = {
703         session->serviceId, session->sessionId, commandID
704     };
705     teecRet = TeekEncode(&cliContext, &msg, &cliLogin, operation);
706     if (teecRet != TEEC_SUCCESS) {
707         tloge("encode failed\n");
708         session->opsCnt--;
709         if (returnOrigin != NULL) {
710             *returnOrigin = origin;
711         }
712         return teecRet;
713     }
714 #ifdef SECURITY_AUTH_ENHANCE
715     cliContext.teecToken = session->teecToken;
716     cliContext.tokenLen = sizeof(session->teecToken);
717 #endif
718     teecRet = InvokeCmdAndSwitchRet(session, &cliContext, &origin);
719     session->opsCnt--;
720     /* ONLY when ioctl returnCode!=0 and returnOrigin not NULL, set *returnOrigin */
721     if ((teecRet != TEEC_SUCCESS) && (returnOrigin != NULL)) {
722         *returnOrigin = origin;
723     }
724     return teecRet;
725 }
726 
727 /*
728  * This function registers a block of existing Client Application memory
729  * as a block of Shared Memory within the scope of the specified TEE Context.
730  */
TeekRegisterSharedMemory(TeecContext * context,TeecSharedMemory * sharedMem)731 TeecResult TeekRegisterSharedMemory(TeecContext *context,
732     TeecSharedMemory *sharedMem)
733 {
734     tloge("TeekRegisterSharedMemory not supported\n");
735     return (TeecResult)TEEC_ERROR_NOT_SUPPORTED;
736 }
737 
738 /*
739  * This function allocates a new block of memory as a block of
740  *  Shared Memory within the scope of the specified TEE Context.
741  */
TeekAllocateSharedMemory(TeecContext * context,TeecSharedMemory * sharedMem)742 TeecResult TeekAllocateSharedMemory(TeecContext *context,
743     TeecSharedMemory *sharedMem)
744 {
745     tloge("TeekAllocateSharedMemory not supported\n");
746     return (TeecResult)TEEC_ERROR_NOT_SUPPORTED;
747 }
748 
749 /*
750  * This function deregisters or deallocates
751  * a previously initialized block of Shared Memory..
752  */
TeekReleaseSharedMemory(TeecSharedMemory * sharedMem)753 void TeekReleaseSharedMemory(TeecSharedMemory *sharedMem)
754 {
755     tloge("TeekReleaseSharedMemory not supported\n");
756 }
757 
758 /*
759  * This function requests the cancellation of a pending open Session operation or
760  * a Command invocation operation.
761  */
TeekRequestCancellation(TeecOperation * operation)762 void TeekRequestCancellation(TeecOperation *operation)
763 {
764     tloge("TeekRequestCancellation not supported\n");
765 }
766