blob: 1475e068e2111a3a3e761fe0db1908f5217857fa [file] [log] [blame]
Oana Medvesan8dfbf012013-12-20 15:40:49 +01001/*
2 * Copyright (c) 2013 TRUSTONIC LIMITED
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 *
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.
14 *
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.
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
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.
30 */
31#undef LOG_TAG
32#define LOG_TAG "GpClient"
33#include "tee_client_api.h"
34#include "log.h"
35#include "MobiCoreDriverApi.h"
36#include "Mci/mcinq.h"
37#include <sys/mman.h>
38#include "GpTci.h"
39
40//------------------------------------------------------------------------------
41// Macros
42#define _TEEC_GET_PARAM_TYPE(t, i) (((t) >> (4*i)) & 0xF)
43
44// Max. session number
45#define _TEEC_SESSION_NUMBER 50
46
47//Parameter number
48#define _TEEC_PARAMETER_NUMBER 4
49
50
51//------------------------------------------------------------------------------
52//Local satic functions
53static void _libUuidToArray(
54 const TEEC_UUID *uuid,
55 uint8_t *uuid_str);
56
57
58static TEEC_Result _TEEC_UnwindOperation(
59 _TEEC_TCI *tci,
60 mcSessionHandle_t *handle,
61 TEEC_Operation *operation,
62 bool copyValues,
63 uint32_t *returnOrigin);
64
65static TEEC_Result _TEEC_SetupOperation(
66 _TEEC_TCI *tci,
67 mcSessionHandle_t *handle,
68 TEEC_Operation *operation,
69 uint32_t *returnOrigin);
70
71static TEEC_Result _TEEC_CallTA(
72 TEEC_Session *session,
73 TEEC_Operation *operation,
74 uint32_t *returnOrigin);
75
76//------------------------------------------------------------------------------
77static void _libUuidToArray(
78 const TEEC_UUID *uuid,
79 uint8_t *uuidArr)
80{
81 uint8_t *pIdentifierCursor = (uint8_t *)uuid;
82 /* offsets and syntax constants. See explanations above */
83#ifdef S_BIG_ENDIAN
84 uint32_t offsets = 0;
85#else
86 uint32_t offsets = 0xF1F1DF13;
87#endif
88 uint32_t i;
89
90 for (i = 0; i < sizeof(TEEC_UUID); i++) {
91 /* Two-digit hex number */
92 uint8_t number;
93 int32_t offset = ((int32_t)((offsets & 0xF) << 28)) >> 28;
94 number = pIdentifierCursor[offset];
95 offsets >>= 4;
96 pIdentifierCursor++;
97
98 uuidArr[i] = number;
99 }
100}
101
102//------------------------------------------------------------------------------
103static TEEC_Result _TEEC_SetupOperation(
104 _TEEC_TCI *tci,
105 mcSessionHandle_t *handle,
106 TEEC_Operation *operation,
107 uint32_t *returnOrigin)
108{
109 uint32_t i;
110 _TEEC_ParameterInternal *imp;
111 TEEC_Parameter *ext;
112 mcResult_t mcRet = MC_DRV_OK;
113 TEEC_Result teecResult = TEEC_SUCCESS;
114
115 //operation can be NULL
116 tci->operation.isCancelled = false;
117 if (operation != NULL) {
118 LOG_I(" %s()", __func__);
119
120 tci->operation.paramTypes = operation->paramTypes;
121 operation->started = 1;
122
123 //TODO: This design allows a non-NULL buffer with a size of 0 bytes to allow trivial integration with any
124 //implementations of the C library malloc, in which is valid to allocate a zero byte buffer and receive a non-
125 //NULL pointer which may not be de-referenced in return.
126
127
128 for (i = 0; i < _TEEC_PARAMETER_NUMBER; i++) {
129 imp = &tci->operation.params[i];
130 ext = &operation->params[i];
131
132 switch (_TEEC_GET_PARAM_TYPE(operation->paramTypes, i)) {
133 case TEEC_VALUE_OUTPUT:
134 break;
135 case TEEC_NONE:
136 LOG_I(" cycle %d, TEEC_NONE", i);
137 break;
138 case TEEC_VALUE_INPUT:
139 case TEEC_VALUE_INOUT: {
140 LOG_I(" cycle %d, TEEC_VALUE_IN*", i);
141 imp->value.a = ext->value.a;
142 imp->value.b = ext->value.b;
143 break;
144 }
145 case TEEC_MEMREF_TEMP_INPUT:
146 case TEEC_MEMREF_TEMP_OUTPUT:
147 case TEEC_MEMREF_TEMP_INOUT: {
148 //TODO: A Temporary Memory Reference may be null, which can be used to denote a special case for the
149 //parameter. Output Memory References that are null are typically used to request the required output size.
150 LOG_I(" cycle %d, TEEC_TEMP_IN*", i);
151 imp->memref.mapInfo.sVirtualLen = 0;
152 if ((ext->tmpref.size) && (ext->tmpref.buffer)) {
153 mcRet = mcMap(handle, ext->tmpref.buffer, ext->tmpref.size, &imp->memref.mapInfo);
154 if (mcRet != MC_DRV_OK) {
155 LOG_E("mcMap failed, mcRet=0x%08X", mcRet);
156 *returnOrigin = TEEC_ORIGIN_COMMS;
157 i = _TEEC_PARAMETER_NUMBER;
158 }
159 } else {
160 LOG_I(" cycle %d, TEEC_TEMP_IN* - zero pointer or size", i);
161 }
162 break;
163 }
164 case TEEC_MEMREF_WHOLE: {
165 LOG_I(" cycle %d, TEEC_MEMREF_WHOLE", i);
166 imp->memref.mapInfo.sVirtualLen = 0;
167 if (ext->memref.parent->size) {
168 mcRet = mcMap(handle, ext->memref.parent->buffer, ext->memref.parent->size, &imp->memref.mapInfo);
169 if (mcRet != MC_DRV_OK) {
170 LOG_E("mcMap failed, mcRet=0x%08X", mcRet);
171 *returnOrigin = TEEC_ORIGIN_COMMS;
172 i = _TEEC_PARAMETER_NUMBER;
173 }
174 }
175 break;
176 }
177 case TEEC_MEMREF_PARTIAL_INPUT:
178 case TEEC_MEMREF_PARTIAL_OUTPUT:
179 case TEEC_MEMREF_PARTIAL_INOUT: {
180 LOG_I(" cycle %d, TEEC_PARTIAL_IN*", i);
181 //Check data flow consistency
182 if ((((ext->memref.parent->flags & (TEEC_MEM_INPUT | TEEC_MEM_OUTPUT)) == TEEC_MEM_INPUT) &&
183 (_TEEC_GET_PARAM_TYPE(operation->paramTypes, i) == TEEC_MEMREF_PARTIAL_OUTPUT)) ||
184 (((ext->memref.parent->flags & (TEEC_MEM_INPUT | TEEC_MEM_OUTPUT)) == TEEC_MEM_OUTPUT) &&
185 (_TEEC_GET_PARAM_TYPE(operation->paramTypes, i) == TEEC_MEMREF_PARTIAL_INPUT))) {
186 LOG_E("PARTIAL data flow inconsistency");
187 *returnOrigin = TEEC_ORIGIN_API;
188 teecResult = TEEC_ERROR_BAD_PARAMETERS;
189 i = _TEEC_PARAMETER_NUMBER;
190 break;
191 }
192
193 if (ext->memref.offset + ext->memref.size > ext->memref.parent->size) {
194 LOG_E("PARTIAL offset/size error");
195 *returnOrigin = TEEC_ORIGIN_API;
196 teecResult = TEEC_ERROR_BAD_PARAMETERS;
197 i = _TEEC_PARAMETER_NUMBER;
198 break;
199 }
200 imp->memref.mapInfo.sVirtualLen = 0;
201 if (ext->memref.size) {
202 mcRet = mcMap(handle, (uint8_t *)ext->memref.parent->buffer + ext->memref.offset, ext->memref.size, &imp->memref.mapInfo);
203 if (mcRet != MC_DRV_OK) {
204 LOG_E("mcMap failed, mcRet=0x%08X", mcRet);
205 *returnOrigin = TEEC_ORIGIN_COMMS;
206 i = _TEEC_PARAMETER_NUMBER;
207 }
208 }
209 break;
210 }
211 default:
212 LOG_E("cycle %d, default", i);
213 *returnOrigin = TEEC_ORIGIN_API;
214 teecResult = TEEC_ERROR_BAD_PARAMETERS;
215 i = _TEEC_PARAMETER_NUMBER;
216 break;
217 }
218 }
219
220 if (tci->operation.isCancelled) {
221 LOG_E("the operation has been cancelled in COMMS");
222 *returnOrigin = TEEC_ORIGIN_COMMS;
223 teecResult = TEEC_ERROR_CANCEL;
224 }
225
226 if ((mcRet != MC_DRV_OK) || (teecResult != TEEC_SUCCESS)) {
227 uint32_t retOrigIgnored;
228 _TEEC_UnwindOperation(tci, handle, operation, false, &retOrigIgnored);
229 //Zeroing out tci->operation
230 memset(&tci->operation, 0, sizeof(TEEC_Operation));
231 if (teecResult != TEEC_SUCCESS) return teecResult;
232 return TEEC_ERROR_GENERIC;
233 }
234 }
235
236 //Copy version indicator field
Oana Medvesan7e955202014-10-27 17:00:41 +0100237 memcpy(tci->header, "TCIGP000", sizeof(tci->header));
Oana Medvesan8dfbf012013-12-20 15:40:49 +0100238
239 // Fill in invalid values for secure world to overwrite
240 tci->returnStatus = 0;
Jerome Neanne73eaddb2014-02-19 10:55:50 +0100241 tci->returnStatus = TEEC_ERROR_BAD_STATE;
Oana Medvesan8dfbf012013-12-20 15:40:49 +0100242
243 // Signal completion of request writing
244 tci->ready = 1;
245
246 return teecResult;
247}
248
249//------------------------------------------------------------------------------
250static TEEC_Result _TEEC_UnwindOperation(
251 _TEEC_TCI *tci,
252 mcSessionHandle_t *handle,
253 TEEC_Operation *operation,
254 bool copyValues,
255 uint32_t *returnOrigin)
256{
257 uint32_t i;
258 _TEEC_ParameterInternal *imp;
259 TEEC_Parameter *ext;
260 //mcResult_t mcRet = MC_DRV_OK;
261 //bool doUnmap = false;
262 uint8_t *buffer;
263
264 //operation can be NULL
265 if (operation == NULL) return TEEC_SUCCESS;
266
267 LOG_I(" %s()", __func__);
268
269 operation->started = 2;
270
271 // Some sanity checks
272 if (tci->returnOrigin == 0 ||
273 ((tci->returnOrigin != TEEC_ORIGIN_TRUSTED_APP) && (tci->returnStatus != TEEC_SUCCESS))) {
274 *returnOrigin = TEEC_ORIGIN_COMMS;
275 return TEEC_ERROR_COMMUNICATION;
276 }
277 *returnOrigin = tci->returnOrigin;
278
279 //Clear sVirtualLen to unMap further
280 for (i = 0; i < _TEEC_PARAMETER_NUMBER; i++) {
281 imp = &tci->operation.params[i];
282 ext = &operation->params[i];
283 buffer = NULL;
284
285 switch (_TEEC_GET_PARAM_TYPE(operation->paramTypes, i)) {
286 case TEEC_VALUE_INPUT:
287 LOG_I(" cycle %d, TEEC_VALUE_INPUT", i);
288 break;
289 case TEEC_NONE:
290 LOG_I(" cycle %d, TEEC_NONE", i);
291 break;
292 case TEEC_VALUE_OUTPUT:
293 case TEEC_VALUE_INOUT: {
294 LOG_I(" cycle %d, TEEC_VALUE_OUT*", i);
295 if (copyValues) {
296 ext->value.a = imp->value.a;
297 ext->value.b = imp->value.b;
298 }
299 break;
300 }
301 case TEEC_MEMREF_TEMP_OUTPUT:
302 case TEEC_MEMREF_TEMP_INPUT:
303 case TEEC_MEMREF_TEMP_INOUT: {
304 LOG_I(" cycle %d, TEEC_TEMP*", i);
305 if ((copyValues) && (_TEEC_GET_PARAM_TYPE(operation->paramTypes, i) != TEEC_MEMREF_TEMP_INPUT)) {
306 ext->tmpref.size = imp->memref.outputSize;
307 }
308 //doUnmap = true;
309 buffer = (uint8_t *)ext->tmpref.buffer;
310 break;
311 }
312 case TEEC_MEMREF_WHOLE: {
313 LOG_I(" cycle %d, TEEC_MEMREF_WHOLE", i);
314 if (copyValues) ext->memref.size = imp->memref.outputSize;
315 //doUnmap = true;
316 buffer = (uint8_t *)ext->memref.parent->buffer;
317 break;
318 }
319
320 case TEEC_MEMREF_PARTIAL_OUTPUT:
321 case TEEC_MEMREF_PARTIAL_INOUT:
322 case TEEC_MEMREF_PARTIAL_INPUT: {
323 LOG_I(" cycle %d, TEEC_MEMREF_PARTIAL*", i);
324 if ((copyValues) && (_TEEC_GET_PARAM_TYPE(operation->paramTypes, i) != TEEC_MEMREF_PARTIAL_INPUT)) {
325 ext->memref.size = imp->memref.outputSize;
326 }
327 buffer = (uint8_t *)ext->memref.parent->buffer + ext->memref.offset;
328 break;
329 }
330 default:
331 LOG_E("cycle %d, bad parameter", i);
332 break;
333 }
334
335 if ((buffer != NULL) && (imp->memref.mapInfo.sVirtualLen != 0)) {
336 // This function assumes that we cannot handle error of mcUnmap
337 mcUnmap(handle, buffer, &imp->memref.mapInfo);
338 }
339 }
340
341 return tci->returnStatus;
342}
343
344//------------------------------------------------------------------------------
345//TEEC_InitializeContext: TEEC_SUCCESS, Another error code from Table 4-2.
346//MC_DRV_OK, MC_DRV_ERR_INVALID_OPERATION, MC_DRV_ERR_DAEMON_UNREACHABLE, MC_DRV_ERR_UNKNOWN_DEVICE, MC_DRV_ERR_INVALID_DEVICE_FILE
347TEEC_Result TEEC_InitializeContext(
348 const char *name,
349 TEEC_Context *context)
350{
351 LOG_I("== %s() ==============", __func__);
352
353 if (context == NULL) return TEEC_ERROR_BAD_PARAMETERS;
354 context->imp.reserved = MC_DEVICE_ID_DEFAULT;
355
356 switch (mcOpenDevice(MC_DEVICE_ID_DEFAULT)) {
357 case MC_DRV_OK:
358 return TEEC_SUCCESS;
359 case MC_DRV_ERR_INVALID_OPERATION:
360 return TEEC_ERROR_BAD_STATE;
361 case MC_DRV_ERR_DAEMON_UNREACHABLE:
362 return TEEC_ERROR_COMMUNICATION;
363 case MC_DRV_ERR_UNKNOWN_DEVICE:
364 return TEEC_ERROR_BAD_PARAMETERS;
365 case MC_DRV_ERR_INVALID_DEVICE_FILE:
366 return TEEC_ERROR_COMMUNICATION;
367 }
368
369 return TEEC_ERROR_GENERIC;
370}
371
372//------------------------------------------------------------------------------
373//mcCloseDevice: MC_DRV_OK, MC_DRV_ERR_UNKNOWN_DEVICE, MC_DRV_ERR_SESSION_PENDING, MC_DRV_ERR_DAEMON_UNREACHABLE
374//TEEC_FinalizeContext: void
375
376//TODO: The implementation of this function MUST NOT be able to fail: after this function returns the Client
377//Application must be able to consider that the Context has been closed.
378
379void TEEC_FinalizeContext(TEEC_Context *context)
380{
381 mcResult_t mcRet;
382
383 LOG_I("== %s() ==============", __func__);
384
385 //The parameter context MUST point to an initialized TEE Context.
386 //Just realized: The function implementation MUST do nothing if context is NULL.
387 if (context == NULL) {
388 LOG_E("context is NULL");
389 return;
390 }
391
392 //The implementation of this function MUST NOT be able to fail: after this function returns the Client
393 //Application must be able to consider that the Context has been closed.
394 mcRet = mcCloseDevice(context->imp.reserved);
395 if (mcRet != MC_DRV_OK) {
396 LOG_E("mcCloseDevice failed (%08x)", mcRet);
397 /* continue even in case of error */;
398 }
399}
400
401//------------------------------------------------------------------------------
402static TEEC_Result _TEEC_CallTA(
403 TEEC_Session *session,
404 TEEC_Operation *operation,
405 uint32_t *returnOrigin)
406{
407 mcResult_t mcRet;
408 TEEC_Result teecRes;
409 TEEC_Result teecError = TEEC_SUCCESS;
410
411 LOG_I(" %s()", __func__);
412
413 // Phase 1: start the operation and wait for the result
414 teecRes = _TEEC_SetupOperation((_TEEC_TCI *)session->imp.tci, &session->imp.handle, operation, returnOrigin);
415 if (teecRes != TEEC_SUCCESS ) {
416 LOG_E("_TEEC_SetupOperation failed (%08x)", teecRes);
417 return teecRes;
418 }
419
420 // Signal the Trusted App
421 mcRet = mcNotify(&session->imp.handle);
422 if (MC_DRV_OK != mcRet) {
423 LOG_E("Notify failed (%08x)", mcRet);
424 teecError = TEEC_ERROR_COMMUNICATION;
425 goto end;
426 }
427
428 // -------------------------------------------------------------
429 // Wait for the Trusted App response
430 mcRet = mcWaitNotification(&session->imp.handle, MC_INFINITE_TIMEOUT);
431 if (mcRet != MC_DRV_OK) {
432 LOG_E("mcWaitNotification failed (%08x)", mcRet);
433 teecError = TEEC_ERROR_COMMUNICATION;
434 if (mcRet == MC_DRV_INFO_NOTIFICATION) {
435 int32_t lastErr;
436 mcGetSessionErrorCode(&session->imp.handle, &lastErr);
437 LOG_E("mcGetSessionErrorCode returned %d", lastErr);
438 if (lastErr == TA_EXIT_CODE_FINISHED) {
439 // We may get here if the TA_OpenSessionEntryPoint returns an error and TA goes fast through DestroyEntryPoint and exits the TA.
440 teecError = TEEC_SUCCESS;
441 } else if (lastErr != ERR_INVALID_SID && lastErr != ERR_SID_NOT_ACTIVE) {
442 LOG_E("Target is DEAD");
443
444 *returnOrigin = TEEC_ORIGIN_TEE;
Jerome Neanne73eaddb2014-02-19 10:55:50 +0100445 teecError = TEEC_ERROR_TARGET_DEAD;
Oana Medvesan8dfbf012013-12-20 15:40:49 +0100446 }
447 }
448 }
449 // Phase 2: Return values and cleanup
450end:
451 // unmap memory and copy values if no error
452 teecRes = _TEEC_UnwindOperation((_TEEC_TCI *)session->imp.tci, &session->imp.handle, operation,
453 (teecError == TEEC_SUCCESS), returnOrigin);
454 if (teecRes != TEEC_SUCCESS ) {
455 LOG_E("_TEEC_UnwindOperation (%08x)", teecRes);
456 /* continue even in case of error */;
457 }
458
459 // Cleanup
460 if (teecError != TEEC_SUCCESS) {
461 // Previous interactions failed, either TA is dead or communication error
462 mcRet = mcCloseSession(&session->imp.handle);
463 if (mcRet != MC_DRV_OK) {
464 LOG_E("mcCloseSession failed (%08x)", mcRet);
465 /* continue even in case of error */;
466 }
467 session->imp.active = false;
468 if (teecError == TEEC_ERROR_COMMUNICATION) {
469 *returnOrigin = TEEC_ORIGIN_COMMS;
470 }
471 munmap(session->imp.tci, sysconf(_SC_PAGESIZE));
472 session->imp.tci = NULL;
473 }
474 return teecError;
475}
476
477//------------------------------------------------------------------------------
478__MC_CLIENT_LIB_API mcResult_t mcOpenGPTA(
479 mcSessionHandle_t *session,
480 const mcUuid_t *uuid,
481 uint8_t *tci,
482 uint32_t len
483);
484//------------------------------------------------------------------------------
485//TEEC_OpenSession: if the returnOrigin is different from TEEC_ORIGIN_TRUSTED_APP, an error code from Table 4-2
486// If the returnOrigin is equal to TEEC_ORIGIN_TRUSTED_APP, a return code defined by the
487//protocol between the Client Application and the Trusted Application.
488TEEC_Result TEEC_OpenSession (
489 TEEC_Context *context,
490 TEEC_Session *session,
491 const TEEC_UUID *destination,
492 uint32_t connectionMethod,
493 void *connectionData,
494 TEEC_Operation *operation,
495 uint32_t *returnOrigin)
496{
497 mcResult_t mcRet;
498 TEEC_Result teecRes;
499 uint32_t returnOrigin_local;
500 mcUuid_t tauuid;
501
502 LOG_I("== %s() ==============", __func__);
503 // -------------------------------------------------------------
504 //The parameter context MUST point to an initialized TEE Context.
505 if (context == NULL) {
506 LOG_E("context is NULL");
507 if (returnOrigin != NULL) *returnOrigin = TEEC_ORIGIN_API;
508 return TEEC_ERROR_BAD_PARAMETERS;
509 }
510
511 if (session == NULL) {
512 LOG_E("session is NULL");
513 if (returnOrigin != NULL) *returnOrigin = TEEC_ORIGIN_API;
514 return TEEC_ERROR_BAD_PARAMETERS;
515 }
516
517 if (connectionMethod != TEEC_LOGIN_PUBLIC) {
518 //JACKET: Client authorization is not supported. The connectionMethod parameter
519 //must be TEEC LOGIN PUBLIC, otherwise return TEEC ERROR NOT IMPLEMENTED.
520 LOG_E("connectionMethod != TEEC_LOGIN_PUBLIC");
521 if (returnOrigin != NULL) *returnOrigin = TEEC_ORIGIN_API;
522 return TEEC_ERROR_NOT_IMPLEMENTED;
523 }
524
525 // -------------------------------------------------------------
526 session->imp.active = false;
527
528 _libUuidToArray((TEEC_UUID *)destination, (uint8_t *)tauuid.value);
529
530 if (operation) operation->imp.session = &session->imp;
531
532 //Allocate a 4kB page with mmap, zero it out, and set session->imp.tci to its address.
533 session->imp.tci = NULL;
534 void *bulkBuf = (void *)mmap(0, sysconf(_SC_PAGESIZE), PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
535 if (bulkBuf == MAP_FAILED) {
536 LOG_E("mmap filed on tci buffer allocation");
537 if (returnOrigin != NULL) *returnOrigin = TEEC_ORIGIN_API;
538 return TEEC_ERROR_OUT_OF_MEMORY;
539 }
540
541 session->imp.tci = bulkBuf;
542 memset(session->imp.tci, 0, sysconf(_SC_PAGESIZE));
543
544 pthread_mutex_init(&session->imp.mutex_tci, NULL);
545 pthread_mutex_lock(&session->imp.mutex_tci);
546
547 //Fill the TCI buffer session.tci with the destination UUID.
548 memcpy(&(((_TEEC_TCI *)session->imp.tci)->destination), destination, sizeof(TEEC_UUID));
549 // -------------------------------------------------------------
550 memset(&session->imp.handle, 0, sizeof(mcSessionHandle_t));
551 session->imp.handle.deviceId = context->imp.reserved ; // The device ID (default device is used)
552 mcRet = mcOpenGPTA(
553 &session->imp.handle,
554 &tauuid,
555 (uint8_t *)session->imp.tci,
556 sizeof(_TEEC_TCI));
557 if (mcRet != MC_DRV_OK) {
558 LOG_E("mcOpenTrustlet failed (%08x)", mcRet);
559 if (returnOrigin != NULL) *returnOrigin = TEEC_ORIGIN_COMMS;
560 if (mcRet == MC_DRV_ERR_TRUSTED_APPLICATION_NOT_FOUND) {
561 teecRes = TEEC_ERROR_ITEM_NOT_FOUND;
562 } else {
563 //TODO: Improve the error codes
564 teecRes = TEEC_ERROR_GENERIC;
565 }
566 goto error;
567 }
568
569 session->imp.active = true;
570
571 // Let TA go through entry points
572 LOG_I(" let TA go through entry points");
573 ((_TEEC_TCI *)session->imp.tci)->operation.type = _TA_OPERATION_OPEN_SESSION;
574 teecRes = _TEEC_CallTA(session, operation, &returnOrigin_local);
575
576 // Check for error on communication level
577 if (teecRes != TEEC_SUCCESS ) {
578 LOG_E("_TEEC_CallTA failed(%08x)", teecRes);
579 // Nothing to do here because _TEEC_CallTA closes broken sessions
580 if (returnOrigin != NULL) *returnOrigin = returnOrigin_local;
581 goto error;
582 }
583 LOG_I(" no errors in com layer");
584
585 // Check for error from TA
586 if (returnOrigin != NULL) *returnOrigin = ((_TEEC_TCI *)session->imp.tci)->returnOrigin;
587 teecRes = ((_TEEC_TCI *)session->imp.tci)->returnStatus;
588 if (teecRes != TEEC_SUCCESS ) {
589 LOG_E("TA OpenSession EP failed(%08x)", teecRes);
590 goto error;
591 }
592
593 LOG_I(" %s() = TEEC_SUCCESS ", __func__);
594 pthread_mutex_unlock(&session->imp.mutex_tci);
595
596 if (returnOrigin != NULL) *returnOrigin = TEEC_ORIGIN_TRUSTED_APP;
597 return TEEC_SUCCESS;
598
599 // -------------------------------------------------------------
600error:
601 if (session->imp.active) {
602 // After notifying us, TA went to Destry EP, so close session now
603 mcRet = mcCloseSession(&session->imp.handle);
604 if (mcRet != MC_DRV_OK) {
605 LOG_E("mcCloseSession failed (%08x)", mcRet);
606 /* continue even in case of error */;
607 }
608 session->imp.active = false;
609 }
610
611 pthread_mutex_unlock(&session->imp.mutex_tci);
612 pthread_mutex_destroy(&session->imp.mutex_tci);
613 if (session->imp.tci) {
614 munmap(session->imp.tci, sysconf(_SC_PAGESIZE));
615 session->imp.tci = NULL;
616 }
617
618 LOG_I(" %s() = 0x%x", __func__, teecRes);
619 return teecRes;
620}
621
622//------------------------------------------------------------------------------
623TEEC_Result TEEC_InvokeCommand(
624 TEEC_Session *session,
625 uint32_t commandID,
626 TEEC_Operation *operation,
627 uint32_t *returnOrigin)
628{
629 TEEC_Result teecRes;
630 uint32_t returnOrigin_local;
631
632 LOG_I("== %s() ==============", __func__);
633
634 // -------------------------------------------------------------
635 if (session == NULL) {
636 LOG_E("session is NULL");
637 if (returnOrigin != NULL) *returnOrigin = TEEC_ORIGIN_API;
638 return TEEC_ERROR_BAD_PARAMETERS;
639 }
640
641 if (!session->imp.active) {
642 LOG_E("session is inactive");
643 if (returnOrigin != NULL) *returnOrigin = TEEC_ORIGIN_API;
644 return TEEC_ERROR_BAD_STATE;
645 }
646 // -------------------------------------------------------------
647 if (operation) operation->imp.session = &session->imp;
648
649 pthread_mutex_lock(&session->imp.mutex_tci);
650
651 // Call TA
652 ((_TEEC_TCI *)session->imp.tci)->operation.commandId = commandID;
653 ((_TEEC_TCI *)session->imp.tci)->operation.type = _TA_OPERATION_INVOKE_COMMAND;
654 teecRes = _TEEC_CallTA(session, operation, &returnOrigin_local);
655 if (teecRes != TEEC_SUCCESS ) {
656 LOG_E("_TEEC_CallTA failed(%08x)", teecRes);
657 if (returnOrigin != NULL) *returnOrigin = returnOrigin_local;
658 } else {
659 if (returnOrigin != NULL) *returnOrigin = ((_TEEC_TCI *)session->imp.tci)->returnOrigin;
660 teecRes = ((_TEEC_TCI *)session->imp.tci)->returnStatus;
661 }
662
663 pthread_mutex_unlock(&session->imp.mutex_tci);
664 LOG_I(" %s() = 0x%x", __func__, teecRes);
665 return teecRes;
666}
667
668//------------------------------------------------------------------------------
669void TEEC_CloseSession(TEEC_Session *session)
670{
671 mcResult_t mcRet;
672 TEEC_Result teecRes = TEEC_SUCCESS;
673 uint32_t returnOrigin;
674
675 LOG_I("== %s() ==============", __func__);
676
677 // -------------------------------------------------------------
678 //The Implementation MUST do nothing if the session parameter is NULL.
679 if (session == NULL) {
680 LOG_E("session is NULL");
681 return;
682 }
683
684 // -------------------------------------------------------------
685 if (session->imp.active) {
686 // Let TA go through CloseSession and Destroy entry points
687 LOG_I(" let TA go through close entry points");
688 pthread_mutex_lock(&session->imp.mutex_tci);
689 ((_TEEC_TCI *)session->imp.tci)->operation.type = _TA_OPERATION_CLOSE_SESSION;
690 teecRes = _TEEC_CallTA(session, NULL, &returnOrigin);
691 if (teecRes != TEEC_SUCCESS ) {
692 /* continue even in case of error */;
693 LOG_E("_TEEC_CallTA failed(%08x)", teecRes);
694 }
695
696 if (session->imp.active) {
697 // Close Session
698 mcRet = mcCloseSession(&session->imp.handle);
699 if (mcRet != MC_DRV_OK) {
700 LOG_E("mcCloseSession failed (%08x)", mcRet);
701 /* ignore error and also there shouldn't be one */
702 }
703 }
704 pthread_mutex_unlock(&session->imp.mutex_tci);
705 }
706
707 pthread_mutex_destroy(&session->imp.mutex_tci);
708 if (session->imp.tci) {
709 munmap(session->imp.tci, sysconf(_SC_PAGESIZE));
710 session->imp.tci = NULL;
711 }
712 session->imp.active = false;
713
714 LOG_I(" %s() = 0x%x", __func__, teecRes);
715}
716
717//------------------------------------------------------------------------------
718TEEC_Result TEEC_RegisterSharedMemory(
719 TEEC_Context *context,
720 TEEC_SharedMemory *sharedMem)
721{
722 LOG_I("== %s() ==============", __func__);
723
724 //The parameter context MUST point to an initialized TEE Context.
725 if (context == NULL) {
726 LOG_E("context is NULL");
727 return TEEC_ERROR_BAD_PARAMETERS;
728 }
729 //The parameter sharedMem MUST point to the Shared Memory structure defining
730 //the memory region to register.
731 if (sharedMem == NULL) {
732 LOG_E("sharedMem is NULL");
733 return TEEC_ERROR_BAD_PARAMETERS;
734 }
735 //The buffer field MUST point to the memory region to be shared, and MUST not be NULL.
736 if (sharedMem->buffer == NULL) {
737 LOG_E("sharedMem->buffer is NULL");
738 return TEEC_ERROR_BAD_PARAMETERS;
739 }
740
741 sharedMem->imp.implementation_allocated = false;
742 return TEEC_SUCCESS;
743}
744
745//------------------------------------------------------------------------------
746TEEC_Result TEEC_AllocateSharedMemory(
747 TEEC_Context *context,
748 TEEC_SharedMemory *sharedMem)
749{
750 //No connection to "context"?
751 LOG_I("== %s() ==============", __func__);
752
753 //The parameter context MUST point to an initialized TEE Context.
754 if (context == NULL) {
755 LOG_E("context is NULL");
756 return TEEC_ERROR_BAD_PARAMETERS;
757 }
758 //The parameter sharedMem MUST point to the Shared Memory structure defining
759 //the memory region to register.
760 if (sharedMem == NULL) {
761 LOG_E("sharedMem is NULL");
762 return TEEC_ERROR_BAD_PARAMETERS;
763 }
764
765 sharedMem->buffer = malloc(sharedMem->size);
766 if (sharedMem->buffer == NULL) {
767 LOG_E("malloc failed");
768 return TEEC_ERROR_OUT_OF_MEMORY;
769 }
770 sharedMem->imp.implementation_allocated = true;
771
772 return TEEC_SUCCESS;
773}
774
775//------------------------------------------------------------------------------
776void TEEC_ReleaseSharedMemory (
777 TEEC_SharedMemory *sharedMem)
778{
779 //No connection to "context"?
780 LOG_I("== %s() ==============", __func__);
781
782 //The Implementation MUST do nothing if the sharedMem parameter is NULL
783 if (sharedMem == NULL) {
784 LOG_E("sharedMem is NULL");
785 return;
786 }
787
788 //For a memory buffer allocated using TEEC_AllocateSharedMemory the Implementation
789 //MUST free the underlying memory
790 if (sharedMem->imp.implementation_allocated) {
791 if (sharedMem->buffer) {
792 free(sharedMem->buffer);
793 sharedMem->buffer = NULL;
794 sharedMem->size = 0;
795 }
796 }
797
798 //TODO: Attempting to release Shared Memory which is used by a pending operation.
799
800}
801
802//------------------------------------------------------------------------------
803void TEEC_RequestCancellation(
804 TEEC_Operation *operation)
805{
806 LOG_I("== %s() ==============", __func__);
807
808 while (operation->started == 0);
809
810 LOG_I("while(operation->started ==0) passed");
811
812 if (operation->started > 1) {
813 LOG_I("The operation has finished");
814 return;
815 }
816
817 TEEC_Session_IMP *session = operation->imp.session;
818 operation->started = 2;
819
820 if (!session->active) {
821 LOG_I("Corresponding session is not active");
822 return;
823 }
824 ((_TEEC_TCI *)session->tci)->operation.isCancelled = true;
825
826 // Step 4.3: signal the Trustlet
827 mcResult_t mcRet = mcNotify(&session->handle);
828 if (MC_DRV_OK != mcRet) {
829 LOG_E("Notify failed (%08x)", mcRet);
830 }
831}
832
833//------------------------------------------------------------------------------