2 * Copyright (c) 2013-2015 TRUSTONIC LIMITED
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the TRUSTONIC LIMITED nor the names of its
16 * contributors may be used to endorse or promote products derived from
17 * this software without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, 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.
37 #include <sys/ioctl.h>
39 #include <sys/types.h>
43 #include "Mci/mcinq.h" /* TA termination codes */
46 #define LOG_TAG "TeeGpClient"
48 #include "common_client.h"
49 #include "tee_client_api.h"
50 #include "GpTci.h" /* Needs stuff from tee_client_api.h or its includes */
52 //------------------------------------------------------------------------------
54 #define _TEEC_GET_PARAM_TYPE(t, i) (((t) >> (4*i)) & 0xF)
57 #define _TEEC_PARAMETER_NUMBER 4
60 * These error codes are still to be decided by GP and as we do not wish to
61 * expose any part of the GP TAF as of yet, for now they will have to live here
62 * until we decide what to do about them.
64 #define TEEC_ERROR_TA_LOCKED 0xFFFF0257
65 #define TEEC_ERROR_SD_BLOCKED 0xFFFF0258
66 #define TEEC_ERROR_TARGET_KILLED 0xFFFF0259
68 static const size_t page_size
= static_cast<size_t>(sysconf(_SC_PAGESIZE
));
69 static CommonClient
& client
= CommonClient::getInstance();
71 //------------------------------------------------------------------------------
73 static TEEC_Result
_TEEC_UnwindOperation(
74 TEEC_Session_IMP
* session
,
76 TEEC_Operation
* operation
,
78 uint32_t* returnOrigin
);
80 //------------------------------------------------------------------------------
81 static void _libUuidToArray(
82 const TEEC_UUID
* uuid
,
84 uint8_t* pIdentifierCursor
= (uint8_t*)uuid
;
85 /* offsets and syntax constants. See explanations above */
89 uint32_t offsets
= 0xF1F1DF13;
93 for (i
= 0; i
< sizeof(TEEC_UUID
); i
++) {
94 /* Two-digit hex number */
96 int32_t offset
= ((int32_t)((offsets
& 0xF) << 28)) >> 28;
97 number
= pIdentifierCursor
[offset
];
105 //------------------------------------------------------------------------------
106 static TEEC_Result
_TEEC_SetupOperation(
107 TEEC_Session_IMP
* session
,
109 TEEC_Operation
* operation
,
110 uint32_t* returnOrigin
) {
112 _TEEC_ParameterInternal
* imp
;
114 TEEC_Result teecResult
= TEEC_SUCCESS
;
116 LOG_D(" %s()", __func__
);
118 tci
->operation
.isCancelled
= false;
119 tci
->operation
.paramTypes
= 0;
121 //operation can be NULL
124 operation
->started
= 1;
125 // Buffers to map to SWd
126 struct mc_ioctl_map map
;
127 map
.sid
= session
->sessionId
;
128 // Operation parameters for the buffers above
129 _TEEC_ParameterInternal
* imps
[_TEEC_PARAMETER_NUMBER
] = { NULL
};
131 //This design allows a non-NULL buffer with a size of 0 bytes to allow trivial integration with any
132 //implementations of the C library malloc, in which is valid to allocate a zero byte buffer and receive a non-
133 //NULL pointer which may not be de-referenced in return.
135 for (i
= 0; i
< _TEEC_PARAMETER_NUMBER
&& teecResult
== TEEC_SUCCESS
; i
++) {
136 uint8_t paramType
= _TEEC_GET_PARAM_TYPE(operation
->paramTypes
, i
);
138 imp
= &tci
->operation
.params
[i
];
139 ext
= &operation
->params
[i
];
142 case TEEC_VALUE_OUTPUT
:
143 LOG_D(" cycle %d, TEEC_VALUE_OUTPUT", i
);
146 LOG_D(" cycle %d, TEEC_NONE", i
);
148 case TEEC_VALUE_INPUT
:
149 case TEEC_VALUE_INOUT
: {
150 LOG_D(" cycle %d, TEEC_VALUE_IN*", i
);
151 imp
->value
.a
= ext
->value
.a
;
152 imp
->value
.b
= ext
->value
.b
;
155 case TEEC_MEMREF_TEMP_INPUT
:
156 case TEEC_MEMREF_TEMP_OUTPUT
:
157 case TEEC_MEMREF_TEMP_INOUT
: {
158 // A Temporary Memory Reference may be null, which can be used
159 // to denote a special case for the parameter. Output Memory
160 // References that are null are typically used to request the
161 // required output size.
162 LOG_D(" cycle %d, TEEC_MEMREF_TEMP_*", i
);
163 if ((ext
->tmpref
.size
) && (ext
->tmpref
.buffer
)) {
164 map
.bufs
[n_buf
].va
= (uintptr_t)ext
->tmpref
.buffer
;
165 map
.bufs
[n_buf
].len
= (uint32_t)ext
->tmpref
.size
;
166 map
.bufs
[n_buf
].flags
= paramType
& TEEC_MEM_INOUT
;
170 LOG_D(" cycle %d, TEEC_TEMP_IN* - zero pointer or size", i
);
174 case TEEC_MEMREF_WHOLE
: {
175 LOG_D(" cycle %d, TEEC_MEMREF_WHOLE", i
);
176 if (ext
->memref
.parent
->size
) {
177 map
.bufs
[n_buf
].va
= (uintptr_t)ext
->memref
.parent
->buffer
;
178 map
.bufs
[n_buf
].len
= (uint32_t)ext
->memref
.parent
->size
;
179 map
.bufs
[n_buf
].flags
= ext
->memref
.parent
->flags
& TEEC_MEM_INOUT
;
183 /* We don't transmit that the mem ref is the whole shared mem */
184 /* Magic number 4 means that it is a mem ref */
185 paramType
= (uint8_t)ext
->memref
.parent
->flags
| 4;
188 case TEEC_MEMREF_PARTIAL_INPUT
:
189 case TEEC_MEMREF_PARTIAL_OUTPUT
:
190 case TEEC_MEMREF_PARTIAL_INOUT
: {
191 LOG_D(" cycle %d, TEEC_MEMREF_PARTIAL_*", i
);
192 //Check data flow consistency
193 if ((((ext
->memref
.parent
->flags
& TEEC_MEM_INOUT
) == TEEC_MEM_INPUT
) &&
194 (paramType
== TEEC_MEMREF_PARTIAL_OUTPUT
)) ||
195 (((ext
->memref
.parent
->flags
& TEEC_MEM_INOUT
) == TEEC_MEM_OUTPUT
) &&
196 (paramType
== TEEC_MEMREF_PARTIAL_INPUT
))) {
197 LOG_E("PARTIAL data flow inconsistency");
198 *returnOrigin
= TEEC_ORIGIN_API
;
199 teecResult
= TEEC_ERROR_BAD_PARAMETERS
;
202 /* We don't transmit that the mem ref is partial */
203 paramType
&= TEEC_MEMREF_TEMP_INOUT
;
205 if (ext
->memref
.offset
+ ext
->memref
.size
> ext
->memref
.parent
->size
) {
206 LOG_E("PARTIAL offset/size error");
207 *returnOrigin
= TEEC_ORIGIN_API
;
208 teecResult
= TEEC_ERROR_BAD_PARAMETERS
;
211 if (ext
->memref
.size
) {
212 map
.bufs
[n_buf
].va
= (uintptr_t)ext
->memref
.parent
->buffer
+ ext
->memref
.offset
;
213 map
.bufs
[n_buf
].len
= (uint32_t)ext
->memref
.size
;
214 map
.bufs
[n_buf
].flags
= paramType
& TEEC_MEM_INOUT
;
221 LOG_E("cycle %d, default", i
);
222 *returnOrigin
= TEEC_ORIGIN_API
;
223 teecResult
= TEEC_ERROR_BAD_PARAMETERS
;
226 tci
->operation
.paramTypes
|= (uint32_t)(paramType
<< i
* 4);
229 if (n_buf
> MC_MAP_MAX
) {
230 LOG_E("too many buffers: %s", strerror(errno
));
231 teecResult
= TEEC_ERROR_EXCESS_DATA
;
234 if ((teecResult
== TEEC_SUCCESS
) && (tci
->operation
.isCancelled
)) {
235 LOG_E("the operation has been cancelled in COMMS");
236 *returnOrigin
= TEEC_ORIGIN_COMMS
;
237 teecResult
= TEEC_ERROR_CANCEL
;
241 if ((teecResult
== TEEC_SUCCESS
) && (n_buf
> 0)) {
242 for (i
= n_buf
; i
< MC_MAP_MAX
; i
++) {
245 if (client
.map(map
) == 0) {
246 for (i
= 0; i
< MC_MAP_MAX
; i
++) {
247 if (map
.bufs
[i
].va
) {
248 imps
[i
]->memref
.sVirtualAddr
= (uint32_t)map
.bufs
[i
].sva
;
249 imps
[i
]->memref
.sVirtualLen
= map
.bufs
[i
].len
;
253 LOG_E("client map failed: %s", strerror(errno
));
254 *returnOrigin
= TEEC_ORIGIN_COMMS
;
255 teecResult
= TEEC_ERROR_GENERIC
;
259 if (teecResult
!= TEEC_SUCCESS
) {
260 uint32_t retOrigIgnored
;
261 _TEEC_UnwindOperation(session
, tci
, operation
, false, &retOrigIgnored
);
262 //Zeroing out tci->operation
263 ::memset(&tci
->operation
, 0, sizeof(tci
->operation
));
268 //Copy version indicator field
269 ::memcpy(tci
->header
, "TCIGP000", sizeof(tci
->header
));
271 // Fill in invalid values for secure world to overwrite
272 tci
->returnStatus
= TEEC_ERROR_BAD_STATE
;
274 // Signal completion of request writing
280 //------------------------------------------------------------------------------
281 static TEEC_Result
_TEEC_UnwindOperation(
282 TEEC_Session_IMP
* session
,
284 TEEC_Operation
* operation
,
286 uint32_t* returnOrigin
) {
288 _TEEC_ParameterInternal
* imp
;
292 //operation can be NULL
293 if (operation
== NULL
) {
297 LOG_D(" %s()", __func__
);
299 operation
->started
= 2;
300 // Buffers to unmap from SWd
301 struct mc_ioctl_map map
;
302 map
.sid
= session
->sessionId
;
303 // Some sanity checks
304 if (tci
->returnOrigin
== 0 ||
305 ((tci
->returnOrigin
!= TEEC_ORIGIN_TRUSTED_APP
) &&
306 (tci
->returnStatus
!= TEEC_SUCCESS
))) {
307 *returnOrigin
= TEEC_ORIGIN_COMMS
;
308 return TEEC_ERROR_COMMUNICATION
;
310 *returnOrigin
= tci
->returnOrigin
;
312 //Clear sVirtualLen to unMap further
313 for (i
= 0; i
< _TEEC_PARAMETER_NUMBER
; i
++) {
314 imp
= &tci
->operation
.params
[i
];
315 ext
= &operation
->params
[i
];
317 switch (_TEEC_GET_PARAM_TYPE(operation
->paramTypes
, i
)) {
318 case TEEC_VALUE_INPUT
:
319 LOG_D(" cycle %d, TEEC_VALUE_INPUT", i
);
322 LOG_D(" cycle %d, TEEC_NONE", i
);
324 case TEEC_VALUE_OUTPUT
:
325 case TEEC_VALUE_INOUT
: {
326 LOG_D(" cycle %d, TEEC_VALUE_*OUT", i
);
328 ext
->value
.a
= imp
->value
.a
;
329 ext
->value
.b
= imp
->value
.b
;
333 case TEEC_MEMREF_TEMP_OUTPUT
:
334 case TEEC_MEMREF_TEMP_INPUT
:
335 case TEEC_MEMREF_TEMP_INOUT
: {
336 LOG_D(" cycle %d, TEEC_TEMP*", i
);
338 (_TEEC_GET_PARAM_TYPE(operation
->paramTypes
, i
) != TEEC_MEMREF_TEMP_INPUT
)) {
339 ext
->tmpref
.size
= imp
->memref
.outputSize
;
341 if (imp
->memref
.sVirtualLen
> 0) {
342 map
.bufs
[n_buf
].va
= (uintptr_t)ext
->tmpref
.buffer
;
343 map
.bufs
[n_buf
].sva
= imp
->memref
.sVirtualAddr
;
344 map
.bufs
[n_buf
].len
= imp
->memref
.sVirtualLen
;
349 case TEEC_MEMREF_WHOLE
: {
350 LOG_D(" cycle %d, TEEC_MEMREF_WHOLE", i
);
351 if ((copyValues
) && (ext
->memref
.parent
->flags
!= TEEC_MEM_INPUT
)) {
352 ext
->memref
.size
= imp
->memref
.outputSize
;
354 if (imp
->memref
.sVirtualLen
> 0) {
355 map
.bufs
[n_buf
].va
= (uintptr_t)ext
->memref
.parent
->buffer
;
356 map
.bufs
[n_buf
].sva
= imp
->memref
.sVirtualAddr
;
357 map
.bufs
[n_buf
].len
= imp
->memref
.sVirtualLen
;
363 case TEEC_MEMREF_PARTIAL_OUTPUT
:
364 case TEEC_MEMREF_PARTIAL_INOUT
:
365 case TEEC_MEMREF_PARTIAL_INPUT
: {
366 LOG_D(" cycle %d, TEEC_MEMREF_PARTIAL*", i
);
368 (_TEEC_GET_PARAM_TYPE(operation
->paramTypes
, i
) != TEEC_MEMREF_PARTIAL_INPUT
)) {
369 ext
->memref
.size
= imp
->memref
.outputSize
;
371 if (imp
->memref
.sVirtualLen
> 0) {
372 map
.bufs
[n_buf
].va
= (uintptr_t)ext
->memref
.parent
->buffer
+ ext
->memref
.offset
;
373 map
.bufs
[n_buf
].sva
= imp
->memref
.sVirtualAddr
;
374 map
.bufs
[n_buf
].len
= imp
->memref
.sVirtualLen
;
380 LOG_E("cycle %d, bad parameter", i
);
385 if (n_buf
> MC_MAP_MAX
) {
386 LOG_E("too many buffers: %s", strerror(errno
));
387 return TEEC_ERROR_EXCESS_DATA
;
390 for (i
= n_buf
; i
< MC_MAP_MAX
; i
++) {
395 // This function assumes that we cannot handle errors
396 if (client
.unmap(map
) < 0) {
397 LOG_E("client unmap failed: %s", strerror(errno
));
401 return tci
->returnStatus
;
404 //------------------------------------------------------------------------------
405 //TEEC_InitializeContext: TEEC_SUCCESS, Another error code from Table 4-2.
406 TEEC_Result
TEEC_InitializeContext(
408 TEEC_Context
* context
) {
410 LOG_D("== %s() ==============", __func__
);
412 if (context
== NULL
) {
413 LOG_E("context is NULL");
414 return TEEC_ERROR_BAD_PARAMETERS
;
418 switch (context
->imp
.reserved
) {
419 case CommonClient::DRIVER
:
420 client
.setOpenMode(CommonClient::DRIVER
);
422 case CommonClient::PROXY
:
423 client
.setOpenMode(CommonClient::PROXY
);
430 return TEEC_ERROR_COMMUNICATION
;
432 return TEEC_ERROR_BAD_PARAMETERS
;
434 return TEEC_ERROR_GENERIC
;
441 //------------------------------------------------------------------------------
442 //TEEC_FinalizeContext: void
444 // The implementation of this function MUST NOT be able to fail: after this function returns the Client
445 // Application must be able to consider that the Context has been closed.
447 void TEEC_FinalizeContext(
448 TEEC_Context
* context
) {
449 LOG_D("== %s() ==============", __func__
);
451 // The parameter context MUST point to an initialized TEE Context.
452 if (context
== NULL
) {
453 LOG_E("context is NULL");
457 // The implementation of this function MUST NOT be able to fail: after this function returns the Client
458 // Application must be able to consider that the Context has been closed.
459 if (client
.close()) {
460 LOG_E("mcCloseDevice failed: %s", strerror(errno
));
461 /* continue even in case of error */;
465 static void _TEEC_DeleteTci(TEEC_Session_IMP
* session_imp
) {
466 if (session_imp
->tci
) {
467 ::munmap(session_imp
->tci
, page_size
);
468 session_imp
->tci
= NULL
;
472 static void _TEEC_CloseSession(TEEC_Session_IMP
* session_imp
) {
473 if (client
.closeSession(session_imp
->sessionId
)) {
474 LOG_E("%s failed: %s", __func__
, strerror(errno
));
476 session_imp
->active
= false;
479 //------------------------------------------------------------------------------
480 static TEEC_Result
_TEEC_CallTA(
481 TEEC_Session_IMP
* session
,
482 TEEC_Operation
* operation
,
483 uint32_t* returnOrigin
) {
485 TEEC_Result teecError
= TEEC_SUCCESS
;
488 LOG_D(" %s()", __func__
);
490 // Phase 1: start the operation and wait for the result
491 _TEEC_TCI
* tci
= static_cast<_TEEC_TCI
*>(session
->tci
);
492 teecRes
= _TEEC_SetupOperation(session
, tci
, operation
, returnOrigin
);
493 if (teecRes
!= TEEC_SUCCESS
) {
494 LOG_E("_TEEC_SetupOperation failed (%08x)", teecRes
);
498 // Signal the Trusted App
499 ret
= client
.notify(session
->sessionId
);
501 LOG_E("Notify failed: %s", strerror(errno
));
502 teecError
= TEEC_ERROR_COMMUNICATION
;
504 // -------------------------------------------------------------
505 // Wait for the Trusted App response
506 struct mc_ioctl_wait wait
;
507 wait
.sid
= session
->sessionId
;
509 ret
= client
.waitNotification(wait
);
511 teecError
= TEEC_ERROR_COMMUNICATION
;
512 if (errno
== ECOMM
) {
513 struct mc_ioctl_geterr err
;
514 err
.sid
= session
->sessionId
;
516 ret
= client
.getError(err
);
518 case TA_EXIT_CODE_FINISHED
:
519 // We may get here if the TA_OpenSessionEntryPoint returns an error and TA goes fast through DestroyEntryPoint and exits the TA.
520 teecError
= TEEC_SUCCESS
;
522 case ERR_SESSION_KILLED
:
523 teecError
= TEEC_ERROR_TARGET_KILLED
;
525 case ERR_INVALID_SID
:
526 case ERR_SID_NOT_ACTIVE
:
527 LOG_E("mcWaitNotification failed: %s", strerror(errno
));
528 LOG_E("mcGetSessionErrorCode returned %d", err
.value
);
531 LOG_E("Target is DEAD");
532 *returnOrigin
= TEEC_ORIGIN_TEE
;
533 teecError
= TEEC_ERROR_TARGET_DEAD
;
539 // Phase 2: Return values and cleanup
540 // unmap memory and copy values if no error
541 teecRes
= _TEEC_UnwindOperation(session
, tci
, operation
,
542 (teecError
== TEEC_SUCCESS
), returnOrigin
);
543 if (teecRes
!= TEEC_SUCCESS
) {
544 LOG_E("_TEEC_UnwindOperation (%08x)", teecRes
);
545 /* continue even in case of error */;
549 if (teecError
!= TEEC_SUCCESS
) {
550 if (teecError
== TEEC_ERROR_COMMUNICATION
) {
551 *returnOrigin
= TEEC_ORIGIN_COMMS
;
553 // Previous interactions failed, either TA is dead or communication error
554 _TEEC_CloseSession(session
);
555 _TEEC_DeleteTci(session
);
560 //------------------------------------------------------------------------------
561 //TEEC_OpenSession: if the returnOrigin is different from TEEC_ORIGIN_TRUSTED_APP, an error code from Table 4-2
562 // If the returnOrigin is equal to TEEC_ORIGIN_TRUSTED_APP, a return code defined by the
563 //protocol between the Client Application and the Trusted Application.
564 TEEC_Result
TEEC_OpenSession (
565 TEEC_Context
* context
,
566 TEEC_Session
* session
,
567 const TEEC_UUID
* destination
,
568 uint32_t connectionMethod
,
569 const void* connectionData
,
570 TEEC_Operation
* operation
,
571 uint32_t* returnOrigin
) {
573 uint32_t returnOrigin_local
= TEEC_ORIGIN_API
;
574 struct mc_uuid_t tauuid
;
577 LOG_D("== %s() ==============", __func__
);
578 // -------------------------------------------------------------
579 //The parameter context MUST point to an initialized TEE Context.
580 if (context
== NULL
) {
581 LOG_E("context is NULL");
583 *returnOrigin
= TEEC_ORIGIN_API
;
585 return TEEC_ERROR_BAD_PARAMETERS
;
588 if (session
== NULL
) {
589 LOG_E("session is NULL");
591 *returnOrigin
= TEEC_ORIGIN_API
;
593 return TEEC_ERROR_BAD_PARAMETERS
;
596 if ((connectionMethod
!= TEEC_LOGIN_PUBLIC
) &&
597 (connectionMethod
!= TEEC_LOGIN_USER
) &&
598 (connectionMethod
!= TEEC_LOGIN_GROUP
) &&
599 (connectionMethod
!= TEEC_LOGIN_APPLICATION
) &&
600 (connectionMethod
!= TEEC_LOGIN_USER_APPLICATION
) &&
601 (connectionMethod
!= TEEC_LOGIN_GROUP_APPLICATION
)) {
602 LOG_E("connectionMethod not supported");
604 *returnOrigin
= TEEC_ORIGIN_API
;
606 return TEEC_ERROR_NOT_IMPLEMENTED
;
609 if ((TEEC_LOGIN_GROUP
== connectionMethod
) ||
610 (TEEC_LOGIN_GROUP_APPLICATION
== connectionMethod
)) {
611 if (NULL
== connectionData
) {
612 LOG_E("connectionData is NULL");
614 *returnOrigin
= TEEC_ORIGIN_API
;
616 return TEEC_ERROR_BAD_PARAMETERS
;
620 // -------------------------------------------------------------
621 session
->imp
.active
= false;
623 _libUuidToArray(destination
, tauuid
.value
);
626 operation
->imp
.session
= &session
->imp
;
629 //Allocate a 4kB page with mmap, zero it out, and set session->imp.tci to its address.
630 session
->imp
.tci
= NULL
;
631 void* bulkBuf
= (void*)::mmap(0, page_size
, PROT_READ
| PROT_WRITE
,
632 MAP_PRIVATE
| MAP_ANONYMOUS
, -1, 0);
633 if (bulkBuf
== MAP_FAILED
) {
634 LOG_E("mmap failed on tci buffer allocation");
636 *returnOrigin
= TEEC_ORIGIN_API
;
638 return TEEC_ERROR_OUT_OF_MEMORY
;
641 session
->imp
.tci
= bulkBuf
;
642 ::memset(session
->imp
.tci
, 0, page_size
);
644 ::pthread_mutex_init(&session
->imp
.mutex_tci
, NULL
);
645 ::pthread_mutex_lock(&session
->imp
.mutex_tci
);
647 //Fill the TCI buffer session.tci with the destination UUID.
648 _TEEC_TCI
* tci
= static_cast<_TEEC_TCI
*>(session
->imp
.tci
);
649 ::memcpy(&tci
->destination
, destination
, sizeof(tci
->destination
));
650 // -------------------------------------------------------------
651 struct mc_ioctl_open_session sess
;
653 sess
.tci
= (uintptr_t)tci
;
654 sess
.tcilen
= sizeof(_TEEC_TCI
);
657 sess
.identity
.login_type
= static_cast<mc_login_type
>(connectionMethod
);
658 sess
.identity
.pid
= 0;
659 if (connectionData
) {
660 ::memcpy(&sess
.identity
.login_data
, connectionData
,
661 sizeof(sess
.identity
.login_data
));
664 ret
= client
.openSession(sess
);
666 LOG_E("%s failed: %s", __func__
, strerror(errno
));
668 *returnOrigin
= TEEC_ORIGIN_COMMS
;
672 teecRes
= TEEC_ERROR_ITEM_NOT_FOUND
;
675 teecRes
= TEEC_ERROR_ACCESS_DENIED
;
678 teecRes
= TEEC_ERROR_NOT_IMPLEMENTED
;
681 teecRes
= TEEC_ERROR_OUT_OF_MEMORY
;
684 teecRes
= TEEC_ERROR_SD_BLOCKED
;
687 teecRes
= TEEC_ERROR_TA_LOCKED
;
690 teecRes
= TEEC_ERROR_TARGET_KILLED
;
693 teecRes
= TEEC_ERROR_BUSY
;
696 teecRes
= TEEC_ERROR_GENERIC
;
701 session
->imp
.context
= context
->imp
;
702 session
->imp
.sessionId
= sess
.sid
;
703 session
->imp
.active
= true;
704 LOG_I(" created session ID %x", session
->imp
.sessionId
);
706 // Let TA go through entry points
707 LOG_D(" let TA go through entry points");
708 tci
->operation
.type
= _TA_OPERATION_OPEN_SESSION
;
709 teecRes
= _TEEC_CallTA(&session
->imp
, operation
, &returnOrigin_local
);
711 // Check for error on communication level
712 if (teecRes
!= TEEC_SUCCESS
) {
713 LOG_E("_TEEC_CallTA failed(%08x)", teecRes
);
714 // Nothing to do here because _TEEC_CallTA closes broken sessions
716 *returnOrigin
= returnOrigin_local
;
720 LOG_D(" no errors in com layer");
722 // Check for error from TA
724 *returnOrigin
= tci
->returnOrigin
;
726 teecRes
= tci
->returnStatus
;
727 if (teecRes
!= TEEC_SUCCESS
) {
728 LOG_E("TA OpenSession EP failed(%08x)", teecRes
);
732 LOG_D(" %s() = TEEC_SUCCESS ", __func__
);
733 ::pthread_mutex_unlock(&session
->imp
.mutex_tci
);
736 *returnOrigin
= TEEC_ORIGIN_TRUSTED_APP
;
740 // -------------------------------------------------------------
742 if (session
->imp
.active
) {
743 // After notifying us, TA went to Destry EP, so close session now
744 _TEEC_CloseSession(&session
->imp
);
747 ::pthread_mutex_unlock(&session
->imp
.mutex_tci
);
748 ::pthread_mutex_destroy(&session
->imp
.mutex_tci
);
749 _TEEC_DeleteTci(&session
->imp
);
751 LOG_D(" %s() = 0x%x", __func__
, teecRes
);
755 //------------------------------------------------------------------------------
756 TEEC_Result
TEEC_InvokeCommand(
757 TEEC_Session
* session
,
759 TEEC_Operation
* operation
,
760 uint32_t* returnOrigin
) {
762 uint32_t returnOrigin_local
= TEEC_ORIGIN_API
;
764 LOG_D("== %s() ==============", __func__
);
766 // -------------------------------------------------------------
767 if (session
== NULL
) {
768 LOG_E("session is NULL");
770 *returnOrigin
= TEEC_ORIGIN_API
;
772 return TEEC_ERROR_BAD_PARAMETERS
;
775 if (!session
->imp
.active
) {
776 LOG_E("session is inactive");
778 *returnOrigin
= TEEC_ORIGIN_API
;
780 return TEEC_ERROR_BAD_STATE
;
782 // -------------------------------------------------------------
784 operation
->imp
.session
= &session
->imp
;
787 ::pthread_mutex_lock(&session
->imp
.mutex_tci
);
790 _TEEC_TCI
* tci
= static_cast<_TEEC_TCI
*>(session
->imp
.tci
);
791 tci
->operation
.commandId
= commandID
;
792 tci
->operation
.type
= _TA_OPERATION_INVOKE_COMMAND
;
793 teecRes
= _TEEC_CallTA(&session
->imp
, operation
, &returnOrigin_local
);
794 if (teecRes
!= TEEC_SUCCESS
) {
795 LOG_E("_TEEC_CallTA failed(%08x)", teecRes
);
797 *returnOrigin
= returnOrigin_local
;
801 *returnOrigin
= tci
->returnOrigin
;
803 teecRes
= tci
->returnStatus
;
806 ::pthread_mutex_unlock(&session
->imp
.mutex_tci
);
807 LOG_D(" %s() = 0x%x", __func__
, teecRes
);
811 //------------------------------------------------------------------------------
812 void TEEC_CloseSession(TEEC_Session
* session
) {
813 TEEC_Result teecRes
= TEEC_SUCCESS
;
814 uint32_t returnOrigin
;
816 LOG_D("== %s() ==============", __func__
);
818 // -------------------------------------------------------------
819 //The Implementation MUST do nothing if the session parameter is NULL.
820 if (session
== NULL
) {
821 LOG_E("session is NULL");
825 // -------------------------------------------------------------
826 if (session
->imp
.active
) {
827 // Let TA go through CloseSession and Destroy entry points
828 LOG_D(" let TA go through close entry points");
829 ::pthread_mutex_lock(&session
->imp
.mutex_tci
);
830 _TEEC_TCI
* tci
= static_cast<_TEEC_TCI
*>(session
->imp
.tci
);
831 tci
->operation
.type
= _TA_OPERATION_CLOSE_SESSION
;
832 teecRes
= _TEEC_CallTA(&session
->imp
, NULL
, &returnOrigin
);
833 if (teecRes
!= TEEC_SUCCESS
) {
834 /* continue even in case of error */;
835 LOG_E("_TEEC_CallTA failed(%08x)", teecRes
);
838 if (session
->imp
.active
) {
839 _TEEC_CloseSession(&session
->imp
);
841 ::pthread_mutex_unlock(&session
->imp
.mutex_tci
);
844 ::pthread_mutex_destroy(&session
->imp
.mutex_tci
);
845 _TEEC_DeleteTci(&session
->imp
);
847 LOG_D(" %s() = 0x%x", __func__
, teecRes
);
850 //------------------------------------------------------------------------------
851 TEEC_Result
TEEC_RegisterSharedMemory(
852 TEEC_Context
* context
,
853 TEEC_SharedMemory
* sharedMem
) {
854 LOG_D("== %s() ==============", __func__
);
856 //The parameter context MUST point to an initialized TEE Context.
857 if (context
== NULL
) {
858 LOG_E("context is NULL");
859 return TEEC_ERROR_BAD_PARAMETERS
;
861 //The parameter sharedMem MUST point to the Shared Memory structure defining
862 //the memory region to register.
863 if (sharedMem
== NULL
) {
864 LOG_E("sharedMem is NULL");
865 return TEEC_ERROR_BAD_PARAMETERS
;
867 //The buffer field MUST point to the memory region to be shared, and MUST not be NULL.
868 if (sharedMem
->buffer
== NULL
) {
869 LOG_E("sharedMem->buffer is NULL");
870 return TEEC_ERROR_BAD_PARAMETERS
;
872 if ((static_cast<int>(sharedMem
->flags
) & ~TEEC_MEM_INOUT
)) {
873 LOG_E("sharedMem->flags is incorrect");
874 return TEEC_ERROR_BAD_PARAMETERS
;
876 if (sharedMem
->flags
== 0) {
877 LOG_E("sharedMem->flags is incorrect");
878 return TEEC_ERROR_BAD_PARAMETERS
;
881 sharedMem
->imp
.implementation_allocated
= false;
885 //------------------------------------------------------------------------------
886 TEEC_Result
TEEC_AllocateSharedMemory(
887 TEEC_Context
* context
,
888 TEEC_SharedMemory
* sharedMem
) {
889 //No connection to "context"?
890 LOG_D("== %s() ==============", __func__
);
892 //The parameter context MUST point to an initialized TEE Context.
893 if (context
== NULL
) {
894 LOG_E("context is NULL");
895 return TEEC_ERROR_BAD_PARAMETERS
;
897 //The parameter sharedMem MUST point to the Shared Memory structure defining
898 //the memory region to register.
899 if (sharedMem
== NULL
) {
900 LOG_E("sharedMem is NULL");
901 return TEEC_ERROR_BAD_PARAMETERS
;
903 if (static_cast<int>(sharedMem
->flags
) & ~TEEC_MEM_INOUT
) {
904 LOG_E("sharedMem->flags is incorrect");
905 return TEEC_ERROR_BAD_PARAMETERS
;
907 if (sharedMem
->flags
== 0) {
908 LOG_E("sharedMem->flags is incorrect");
909 return TEEC_ERROR_BAD_PARAMETERS
;
912 sharedMem
->buffer
= malloc(sharedMem
->size
);
913 if (sharedMem
->buffer
== NULL
) {
914 LOG_E("malloc failed");
915 return TEEC_ERROR_OUT_OF_MEMORY
;
917 sharedMem
->imp
.implementation_allocated
= true;
922 //------------------------------------------------------------------------------
923 void TEEC_ReleaseSharedMemory (
924 TEEC_SharedMemory
* sharedMem
) {
925 //No connection to "context"?
926 LOG_D("== %s() ==============", __func__
);
928 //The Implementation MUST do nothing if the sharedMem parameter is NULL
929 if (sharedMem
== NULL
) {
930 LOG_E("sharedMem is NULL");
934 //For a memory buffer allocated using TEEC_AllocateSharedMemory the Implementation
935 //MUST free the underlying memory
936 if (sharedMem
->imp
.implementation_allocated
) {
937 if (sharedMem
->buffer
) {
938 free(sharedMem
->buffer
);
939 sharedMem
->buffer
= NULL
;
945 //------------------------------------------------------------------------------
946 void TEEC_RequestCancellation(
947 TEEC_Operation
* operation
) {
948 LOG_D("== %s() ==============", __func__
);
950 while (operation
->started
== 0);
952 LOG_D("while(operation->started ==0) passed");
954 if (operation
->started
> 1) {
955 LOG_D("The operation has finished");
959 TEEC_Session_IMP
* session
= operation
->imp
.session
;
960 operation
->started
= 2;
962 if (!session
->active
) {
963 LOG_D("Corresponding session is not active");
967 if (client
.gpRequestCancellation(session
->sessionId
)) {
968 LOG_ERRNO("gpRequestCancellation");
972 //------------------------------------------------------------------------------