libdisplaymodule: fix compilation
[GitHub/LineageOS/android_hardware_samsung_slsi_exynos7580.git] / mobicore / ClientLib / src / tee_client_api.cpp
1 /*
2 * Copyright (c) 2013-2015 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
32 #include <stdlib.h>
33 #include <unistd.h>
34 #include <stdint.h>
35 #include <string.h>
36 #include <errno.h>
37 #include <sys/ioctl.h>
38 #include <sys/mman.h>
39 #include <sys/types.h>
40 #include <sys/stat.h>
41 #include <fcntl.h>
42
43 #include "Mci/mcinq.h" /* TA termination codes */
44
45 #undef LOG_TAG
46 #define LOG_TAG "TeeGpClient"
47 #include "log.h"
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 */
51
52 //------------------------------------------------------------------------------
53 // Macros
54 #define _TEEC_GET_PARAM_TYPE(t, i) (((t) >> (4*i)) & 0xF)
55
56 //Parameter number
57 #define _TEEC_PARAMETER_NUMBER 4
58
59 /**
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.
63 */
64 #define TEEC_ERROR_TA_LOCKED 0xFFFF0257
65 #define TEEC_ERROR_SD_BLOCKED 0xFFFF0258
66 #define TEEC_ERROR_TARGET_KILLED 0xFFFF0259
67
68 static const size_t page_size = static_cast<size_t>(sysconf(_SC_PAGESIZE));
69 static CommonClient& client = CommonClient::getInstance();
70
71 //------------------------------------------------------------------------------
72 // Local functions
73 static TEEC_Result _TEEC_UnwindOperation(
74 TEEC_Session_IMP* session,
75 _TEEC_TCI* tci,
76 TEEC_Operation* operation,
77 bool copyValues,
78 uint32_t* returnOrigin);
79
80 //------------------------------------------------------------------------------
81 static void _libUuidToArray(
82 const TEEC_UUID* uuid,
83 uint8_t* uuidArr) {
84 uint8_t* pIdentifierCursor = (uint8_t*)uuid;
85 /* offsets and syntax constants. See explanations above */
86 #ifdef S_BIG_ENDIAN
87 uint32_t offsets = 0;
88 #else
89 uint32_t offsets = 0xF1F1DF13;
90 #endif
91 uint32_t i;
92
93 for (i = 0; i < sizeof(TEEC_UUID); i++) {
94 /* Two-digit hex number */
95 uint8_t number;
96 int32_t offset = ((int32_t)((offsets & 0xF) << 28)) >> 28;
97 number = pIdentifierCursor[offset];
98 offsets >>= 4;
99 pIdentifierCursor++;
100
101 uuidArr[i] = number;
102 }
103 }
104
105 //------------------------------------------------------------------------------
106 static TEEC_Result _TEEC_SetupOperation(
107 TEEC_Session_IMP* session,
108 _TEEC_TCI* tci,
109 TEEC_Operation* operation,
110 uint32_t* returnOrigin) {
111 uint32_t i;
112 _TEEC_ParameterInternal* imp;
113 TEEC_Parameter* ext;
114 TEEC_Result teecResult = TEEC_SUCCESS;
115
116 LOG_D(" %s()", __func__);
117
118 tci->operation.isCancelled = false;
119 tci->operation.paramTypes = 0;
120
121 //operation can be NULL
122 if (operation) {
123 uint32_t n_buf = 0;
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 };
130
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.
134
135 for (i = 0; i < _TEEC_PARAMETER_NUMBER && teecResult == TEEC_SUCCESS; i++) {
136 uint8_t paramType = _TEEC_GET_PARAM_TYPE(operation->paramTypes, i);
137
138 imp = &tci->operation.params[i];
139 ext = &operation->params[i];
140
141 switch (paramType) {
142 case TEEC_VALUE_OUTPUT:
143 LOG_D(" cycle %d, TEEC_VALUE_OUTPUT", i);
144 break;
145 case TEEC_NONE:
146 LOG_D(" cycle %d, TEEC_NONE", i);
147 break;
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;
153 break;
154 }
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;
167 imps[n_buf] = imp;
168 n_buf++;
169 } else {
170 LOG_D(" cycle %d, TEEC_TEMP_IN* - zero pointer or size", i);
171 }
172 break;
173 }
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;
180 imps[n_buf] = imp;
181 n_buf++;
182 }
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;
186 break;
187 }
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;
200 break;
201 }
202 /* We don't transmit that the mem ref is partial */
203 paramType &= TEEC_MEMREF_TEMP_INOUT;
204
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;
209 break;
210 }
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;
215 imps[n_buf] = imp;
216 n_buf++;
217 }
218 break;
219 }
220 default:
221 LOG_E("cycle %d, default", i);
222 *returnOrigin = TEEC_ORIGIN_API;
223 teecResult = TEEC_ERROR_BAD_PARAMETERS;
224 break;
225 }
226 tci->operation.paramTypes |= (uint32_t)(paramType << i * 4);
227 }
228
229 if (n_buf > MC_MAP_MAX) {
230 LOG_E("too many buffers: %s", strerror(errno));
231 teecResult = TEEC_ERROR_EXCESS_DATA;
232 }
233
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;
238 }
239
240 // Map buffers
241 if ((teecResult == TEEC_SUCCESS) && (n_buf > 0)) {
242 for (i = n_buf; i < MC_MAP_MAX; i++) {
243 map.bufs[i].va = 0;
244 }
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;
250 }
251 }
252 } else {
253 LOG_E("client map failed: %s", strerror(errno));
254 *returnOrigin = TEEC_ORIGIN_COMMS;
255 teecResult = TEEC_ERROR_GENERIC;
256 }
257 }
258
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));
264 return teecResult;
265 }
266 }
267
268 //Copy version indicator field
269 ::memcpy(tci->header, "TCIGP000", sizeof(tci->header));
270
271 // Fill in invalid values for secure world to overwrite
272 tci->returnStatus = TEEC_ERROR_BAD_STATE;
273
274 // Signal completion of request writing
275 tci->ready = 1;
276
277 return teecResult;
278 }
279
280 //------------------------------------------------------------------------------
281 static TEEC_Result _TEEC_UnwindOperation(
282 TEEC_Session_IMP* session,
283 _TEEC_TCI* tci,
284 TEEC_Operation* operation,
285 bool copyValues,
286 uint32_t* returnOrigin) {
287 uint32_t i;
288 _TEEC_ParameterInternal* imp;
289 TEEC_Parameter* ext;
290 uint32_t n_buf = 0;
291
292 //operation can be NULL
293 if (operation == NULL) {
294 return TEEC_SUCCESS;
295 }
296
297 LOG_D(" %s()", __func__);
298
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;
309 }
310 *returnOrigin = tci->returnOrigin;
311
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];
316
317 switch (_TEEC_GET_PARAM_TYPE(operation->paramTypes, i)) {
318 case TEEC_VALUE_INPUT:
319 LOG_D(" cycle %d, TEEC_VALUE_INPUT", i);
320 break;
321 case TEEC_NONE:
322 LOG_D(" cycle %d, TEEC_NONE", i);
323 break;
324 case TEEC_VALUE_OUTPUT:
325 case TEEC_VALUE_INOUT: {
326 LOG_D(" cycle %d, TEEC_VALUE_*OUT", i);
327 if (copyValues) {
328 ext->value.a = imp->value.a;
329 ext->value.b = imp->value.b;
330 }
331 break;
332 }
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);
337 if ((copyValues) &&
338 (_TEEC_GET_PARAM_TYPE(operation->paramTypes, i) != TEEC_MEMREF_TEMP_INPUT)) {
339 ext->tmpref.size = imp->memref.outputSize;
340 }
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;
345 n_buf++;
346 }
347 break;
348 }
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;
353 }
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;
358 n_buf++;
359 }
360 break;
361 }
362
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);
367 if ((copyValues) &&
368 (_TEEC_GET_PARAM_TYPE(operation->paramTypes, i) != TEEC_MEMREF_PARTIAL_INPUT)) {
369 ext->memref.size = imp->memref.outputSize;
370 }
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;
375 n_buf++;
376 }
377 break;
378 }
379 default:
380 LOG_E("cycle %d, bad parameter", i);
381 break;
382 }
383 }
384
385 if (n_buf > MC_MAP_MAX) {
386 LOG_E("too many buffers: %s", strerror(errno));
387 return TEEC_ERROR_EXCESS_DATA;
388 }
389
390 for (i = n_buf; i < MC_MAP_MAX; i++) {
391 map.bufs[i].va = 0;
392 }
393
394 if (n_buf > 0) {
395 // This function assumes that we cannot handle errors
396 if (client.unmap(map) < 0) {
397 LOG_E("client unmap failed: %s", strerror(errno));
398 }
399 }
400
401 return tci->returnStatus;
402 }
403
404 //------------------------------------------------------------------------------
405 //TEEC_InitializeContext: TEEC_SUCCESS, Another error code from Table 4-2.
406 TEEC_Result TEEC_InitializeContext(
407 const char* name,
408 TEEC_Context* context) {
409 (void) name;
410 LOG_D("== %s() ==============", __func__);
411
412 if (context == NULL) {
413 LOG_E("context is NULL");
414 return TEEC_ERROR_BAD_PARAMETERS;
415 }
416
417 // For test purpose
418 switch (context->imp.reserved) {
419 case CommonClient::DRIVER:
420 client.setOpenMode(CommonClient::DRIVER);
421 break;
422 case CommonClient::PROXY:
423 client.setOpenMode(CommonClient::PROXY);
424 break;
425 }
426
427 if (client.open()) {
428 switch (errno) {
429 case ENOENT:
430 return TEEC_ERROR_COMMUNICATION;
431 case EINVAL:
432 return TEEC_ERROR_BAD_PARAMETERS;
433 default:
434 return TEEC_ERROR_GENERIC;
435 }
436 }
437
438 return TEEC_SUCCESS;
439 }
440
441 //------------------------------------------------------------------------------
442 //TEEC_FinalizeContext: void
443
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.
446
447 void TEEC_FinalizeContext(
448 TEEC_Context* context) {
449 LOG_D("== %s() ==============", __func__);
450
451 // The parameter context MUST point to an initialized TEE Context.
452 if (context == NULL) {
453 LOG_E("context is NULL");
454 return;
455 }
456
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 */;
462 }
463 }
464
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;
469 }
470 }
471
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));
475 }
476 session_imp->active = false;
477 }
478
479 //------------------------------------------------------------------------------
480 static TEEC_Result _TEEC_CallTA(
481 TEEC_Session_IMP* session,
482 TEEC_Operation* operation,
483 uint32_t* returnOrigin) {
484 TEEC_Result teecRes;
485 TEEC_Result teecError = TEEC_SUCCESS;
486 int ret = 0;
487
488 LOG_D(" %s()", __func__);
489
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);
495 return teecRes;
496 }
497
498 // Signal the Trusted App
499 ret = client.notify(session->sessionId);
500 if (ret) {
501 LOG_E("Notify failed: %s", strerror(errno));
502 teecError = TEEC_ERROR_COMMUNICATION;
503 } else {
504 // -------------------------------------------------------------
505 // Wait for the Trusted App response
506 struct mc_ioctl_wait wait;
507 wait.sid = session->sessionId;
508 wait.timeout = -1;
509 ret = client.waitNotification(wait);
510 if (ret) {
511 teecError = TEEC_ERROR_COMMUNICATION;
512 if (errno == ECOMM) {
513 struct mc_ioctl_geterr err;
514 err.sid = session->sessionId;
515
516 ret = client.getError(err);
517 switch (err.value) {
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;
521 break;
522 case ERR_SESSION_KILLED:
523 teecError = TEEC_ERROR_TARGET_KILLED;
524 break;
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);
529 break;
530 default:
531 LOG_E("Target is DEAD");
532 *returnOrigin = TEEC_ORIGIN_TEE;
533 teecError = TEEC_ERROR_TARGET_DEAD;
534 break;
535 }
536 }
537 }
538 }
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 */;
546 }
547
548 // Cleanup
549 if (teecError != TEEC_SUCCESS) {
550 if (teecError == TEEC_ERROR_COMMUNICATION) {
551 *returnOrigin = TEEC_ORIGIN_COMMS;
552 }
553 // Previous interactions failed, either TA is dead or communication error
554 _TEEC_CloseSession(session);
555 _TEEC_DeleteTci(session);
556 }
557 return teecError;
558 }
559
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) {
572 TEEC_Result teecRes;
573 uint32_t returnOrigin_local = TEEC_ORIGIN_API;
574 struct mc_uuid_t tauuid;
575 int ret = 0;
576
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");
582 if (returnOrigin) {
583 *returnOrigin = TEEC_ORIGIN_API;
584 }
585 return TEEC_ERROR_BAD_PARAMETERS;
586 }
587
588 if (session == NULL) {
589 LOG_E("session is NULL");
590 if (returnOrigin) {
591 *returnOrigin = TEEC_ORIGIN_API;
592 }
593 return TEEC_ERROR_BAD_PARAMETERS;
594 }
595
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");
603 if (returnOrigin) {
604 *returnOrigin = TEEC_ORIGIN_API;
605 }
606 return TEEC_ERROR_NOT_IMPLEMENTED;
607 }
608
609 if ((TEEC_LOGIN_GROUP == connectionMethod) ||
610 (TEEC_LOGIN_GROUP_APPLICATION == connectionMethod)) {
611 if (NULL == connectionData) {
612 LOG_E("connectionData is NULL");
613 if (returnOrigin) {
614 *returnOrigin = TEEC_ORIGIN_API;
615 }
616 return TEEC_ERROR_BAD_PARAMETERS;
617 }
618 }
619
620 // -------------------------------------------------------------
621 session->imp.active = false;
622
623 _libUuidToArray(destination, tauuid.value);
624
625 if (operation) {
626 operation->imp.session = &session->imp;
627 }
628
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");
635 if (returnOrigin) {
636 *returnOrigin = TEEC_ORIGIN_API;
637 }
638 return TEEC_ERROR_OUT_OF_MEMORY;
639 }
640
641 session->imp.tci = bulkBuf;
642 ::memset(session->imp.tci, 0, page_size);
643
644 ::pthread_mutex_init(&session->imp.mutex_tci, NULL);
645 ::pthread_mutex_lock(&session->imp.mutex_tci);
646
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;
652 sess.sid = 0;
653 sess.tci = (uintptr_t)tci;
654 sess.tcilen = sizeof(_TEEC_TCI);
655 sess.uuid = tauuid;
656 sess.is_gp_uuid = 1;
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));
662 }
663
664 ret = client.openSession(sess);
665 if (ret) {
666 LOG_E("%s failed: %s", __func__, strerror(errno));
667 if (returnOrigin) {
668 *returnOrigin = TEEC_ORIGIN_COMMS;
669 }
670 switch (errno) {
671 case ENOENT:
672 teecRes = TEEC_ERROR_ITEM_NOT_FOUND;
673 break;
674 case EACCES:
675 teecRes = TEEC_ERROR_ACCESS_DENIED;
676 break;
677 case EINVAL:
678 teecRes = TEEC_ERROR_NOT_IMPLEMENTED;
679 break;
680 case ENOSPC:
681 teecRes = TEEC_ERROR_OUT_OF_MEMORY;
682 break;
683 case ECONNREFUSED:
684 teecRes = TEEC_ERROR_SD_BLOCKED;
685 break;
686 case ECONNABORTED:
687 teecRes = TEEC_ERROR_TA_LOCKED;
688 break;
689 case ECONNRESET:
690 teecRes = TEEC_ERROR_TARGET_KILLED;
691 break;
692 case EBUSY:
693 teecRes = TEEC_ERROR_BUSY;
694 break;
695 default:
696 teecRes = TEEC_ERROR_GENERIC;
697 }
698 goto error;
699 }
700
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);
705
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);
710
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
715 if (returnOrigin) {
716 *returnOrigin = returnOrigin_local;
717 }
718 goto error;
719 }
720 LOG_D(" no errors in com layer");
721
722 // Check for error from TA
723 if (returnOrigin) {
724 *returnOrigin = tci->returnOrigin;
725 }
726 teecRes = tci->returnStatus;
727 if (teecRes != TEEC_SUCCESS ) {
728 LOG_E("TA OpenSession EP failed(%08x)", teecRes);
729 goto error;
730 }
731
732 LOG_D(" %s() = TEEC_SUCCESS ", __func__);
733 ::pthread_mutex_unlock(&session->imp.mutex_tci);
734
735 if (returnOrigin) {
736 *returnOrigin = TEEC_ORIGIN_TRUSTED_APP;
737 }
738 return TEEC_SUCCESS;
739
740 // -------------------------------------------------------------
741 error:
742 if (session->imp.active) {
743 // After notifying us, TA went to Destry EP, so close session now
744 _TEEC_CloseSession(&session->imp);
745 }
746
747 ::pthread_mutex_unlock(&session->imp.mutex_tci);
748 ::pthread_mutex_destroy(&session->imp.mutex_tci);
749 _TEEC_DeleteTci(&session->imp);
750
751 LOG_D(" %s() = 0x%x", __func__, teecRes);
752 return teecRes;
753 }
754
755 //------------------------------------------------------------------------------
756 TEEC_Result TEEC_InvokeCommand(
757 TEEC_Session* session,
758 uint32_t commandID,
759 TEEC_Operation* operation,
760 uint32_t* returnOrigin) {
761 TEEC_Result teecRes;
762 uint32_t returnOrigin_local = TEEC_ORIGIN_API;
763
764 LOG_D("== %s() ==============", __func__);
765
766 // -------------------------------------------------------------
767 if (session == NULL) {
768 LOG_E("session is NULL");
769 if (returnOrigin) {
770 *returnOrigin = TEEC_ORIGIN_API;
771 }
772 return TEEC_ERROR_BAD_PARAMETERS;
773 }
774
775 if (!session->imp.active) {
776 LOG_E("session is inactive");
777 if (returnOrigin) {
778 *returnOrigin = TEEC_ORIGIN_API;
779 }
780 return TEEC_ERROR_BAD_STATE;
781 }
782 // -------------------------------------------------------------
783 if (operation) {
784 operation->imp.session = &session->imp;
785 }
786
787 ::pthread_mutex_lock(&session->imp.mutex_tci);
788
789 // Call TA
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);
796 if (returnOrigin) {
797 *returnOrigin = returnOrigin_local;
798 }
799 } else {
800 if (returnOrigin) {
801 *returnOrigin = tci->returnOrigin;
802 }
803 teecRes = tci->returnStatus;
804 }
805
806 ::pthread_mutex_unlock(&session->imp.mutex_tci);
807 LOG_D(" %s() = 0x%x", __func__, teecRes);
808 return teecRes;
809 }
810
811 //------------------------------------------------------------------------------
812 void TEEC_CloseSession(TEEC_Session* session) {
813 TEEC_Result teecRes = TEEC_SUCCESS;
814 uint32_t returnOrigin;
815
816 LOG_D("== %s() ==============", __func__);
817
818 // -------------------------------------------------------------
819 //The Implementation MUST do nothing if the session parameter is NULL.
820 if (session == NULL) {
821 LOG_E("session is NULL");
822 return;
823 }
824
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);
836 }
837
838 if (session->imp.active) {
839 _TEEC_CloseSession(&session->imp);
840 }
841 ::pthread_mutex_unlock(&session->imp.mutex_tci);
842 }
843
844 ::pthread_mutex_destroy(&session->imp.mutex_tci);
845 _TEEC_DeleteTci(&session->imp);
846
847 LOG_D(" %s() = 0x%x", __func__, teecRes);
848 }
849
850 //------------------------------------------------------------------------------
851 TEEC_Result TEEC_RegisterSharedMemory(
852 TEEC_Context* context,
853 TEEC_SharedMemory* sharedMem) {
854 LOG_D("== %s() ==============", __func__);
855
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;
860 }
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;
866 }
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;
871 }
872 if ((static_cast<int>(sharedMem->flags) & ~TEEC_MEM_INOUT)) {
873 LOG_E("sharedMem->flags is incorrect");
874 return TEEC_ERROR_BAD_PARAMETERS;
875 }
876 if (sharedMem->flags == 0) {
877 LOG_E("sharedMem->flags is incorrect");
878 return TEEC_ERROR_BAD_PARAMETERS;
879 }
880
881 sharedMem->imp.implementation_allocated = false;
882 return TEEC_SUCCESS;
883 }
884
885 //------------------------------------------------------------------------------
886 TEEC_Result TEEC_AllocateSharedMemory(
887 TEEC_Context* context,
888 TEEC_SharedMemory* sharedMem) {
889 //No connection to "context"?
890 LOG_D("== %s() ==============", __func__);
891
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;
896 }
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;
902 }
903 if (static_cast<int>(sharedMem->flags) & ~TEEC_MEM_INOUT) {
904 LOG_E("sharedMem->flags is incorrect");
905 return TEEC_ERROR_BAD_PARAMETERS;
906 }
907 if (sharedMem->flags == 0) {
908 LOG_E("sharedMem->flags is incorrect");
909 return TEEC_ERROR_BAD_PARAMETERS;
910 }
911
912 sharedMem->buffer = malloc(sharedMem->size);
913 if (sharedMem->buffer == NULL) {
914 LOG_E("malloc failed");
915 return TEEC_ERROR_OUT_OF_MEMORY;
916 }
917 sharedMem->imp.implementation_allocated = true;
918
919 return TEEC_SUCCESS;
920 }
921
922 //------------------------------------------------------------------------------
923 void TEEC_ReleaseSharedMemory (
924 TEEC_SharedMemory* sharedMem) {
925 //No connection to "context"?
926 LOG_D("== %s() ==============", __func__);
927
928 //The Implementation MUST do nothing if the sharedMem parameter is NULL
929 if (sharedMem == NULL) {
930 LOG_E("sharedMem is NULL");
931 return;
932 }
933
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;
940 sharedMem->size = 0;
941 }
942 }
943 }
944
945 //------------------------------------------------------------------------------
946 void TEEC_RequestCancellation(
947 TEEC_Operation* operation) {
948 LOG_D("== %s() ==============", __func__);
949
950 while (operation->started == 0);
951
952 LOG_D("while(operation->started ==0) passed");
953
954 if (operation->started > 1) {
955 LOG_D("The operation has finished");
956 return;
957 }
958
959 TEEC_Session_IMP* session = operation->imp.session;
960 operation->started = 2;
961
962 if (!session->active) {
963 LOG_D("Corresponding session is not active");
964 return;
965 }
966
967 if (client.gpRequestCancellation(session->sessionId)) {
968 LOG_ERRNO("gpRequestCancellation");
969 }
970 }
971
972 //------------------------------------------------------------------------------