//------------------------------------------------------------------------------ void TEEC_CloseSession(TEEC_Session *session) { mcResult_t mcRet; TEEC_Result teecRes = TEEC_SUCCESS; uint32_t returnOrigin; LOG_I("== %s() ==============", __func__); // ------------------------------------------------------------- //The Implementation MUST do nothing if the session parameter is NULL. if (session == NULL) { LOG_E("session is NULL"); return; } // ------------------------------------------------------------- if (session->imp.active) { // Let TA go through CloseSession and Destroy entry points LOG_I(" let TA go through close entry points"); pthread_mutex_lock(&session->imp.mutex_tci); ((_TEEC_TCI *)session->imp.tci)->operation.type = _TA_OPERATION_CLOSE_SESSION; teecRes = _TEEC_CallTA(session, NULL, &returnOrigin); if (teecRes != TEEC_SUCCESS ) { /* continue even in case of error */; LOG_E("_TEEC_CallTA failed(%08x)", teecRes); } if (session->imp.active) { // Close Session mcRet = mcCloseSession(&session->imp.handle); if (mcRet != MC_DRV_OK) { LOG_E("mcCloseSession failed (%08x)", mcRet); /* ignore error and also there shouldn't be one */ } } pthread_mutex_unlock(&session->imp.mutex_tci); } pthread_mutex_destroy(&session->imp.mutex_tci); if (session->imp.tci) { munmap(session->imp.tci, sysconf(_SC_PAGESIZE)); session->imp.tci = NULL; } session->imp.active = false; LOG_I(" %s() = 0x%x", __func__, teecRes); }
// ------------------------------------------------------------- void tlcClose(void) { mcResult_t ret; LOG_I("Closing the session"); ret = mcCloseSession(&sessionHandle); if (MC_DRV_OK != ret) { LOG_E("Closing session failed: %d", ret); /* continue even in case of error */ } LOG_I("Closing <t-base device"); ret = mcCloseDevice(DEVICE_ID); if (MC_DRV_OK != ret) { LOG_E("Closing <t-base device failed: %d", ret); /* continue even in case of error */; } free(tci); tci = NULL; }
mcResult_t tlc_close(mc_comm_ctx *comm_ctx) { mcResult_t mcRet; LOG_I("close() called"); do { // ------------------------------------------------------------- // Step 1: Free WSM LOG_I("Free WSM"); mcRet = mcFreeWsm((comm_ctx->device_id), (uint8_t *)(comm_ctx->tci_msg)); if (MC_DRV_OK != mcRet) { LOG_E("Free WSM failed: %d", mcRet); break; } // ------------------------------------------------------------- // Step 2: Close session with the Trustlet LOG_I("Closing the session"); mcRet = mcCloseSession(&(comm_ctx->handle)); if (MC_DRV_OK != mcRet) { LOG_E("Closing session failed: %d", mcRet); break; } // ------------------------------------------------------------- // Step 3: Close the MobiCore device LOG_I("Closing MobiCore device"); mcRet = mcCloseDevice(comm_ctx->device_id); if (MC_DRV_OK != mcRet) { LOG_E("Closing MobiCore device failed: %d", mcRet); break; } LOG_I("tlc_close() succeeded"); } while (false); return mcRet; }
//------------------------------------------------------------------------------ //TEEC_OpenSession: if the returnOrigin is different from TEEC_ORIGIN_TRUSTED_APP, an error code from Table 4-2 // If the returnOrigin is equal to TEEC_ORIGIN_TRUSTED_APP, a return code defined by the //protocol between the Client Application and the Trusted Application. TEEC_Result TEEC_OpenSession ( TEEC_Context *context, TEEC_Session *session, const TEEC_UUID *destination, uint32_t connectionMethod, void *connectionData, TEEC_Operation *operation, uint32_t *returnOrigin) { mcResult_t mcRet; TEEC_Result teecRes; uint32_t returnOrigin_local = TEEC_ORIGIN_API; mcUuid_t tauuid; LOG_I("== %s() ==============", __func__); // ------------------------------------------------------------- //The parameter context MUST point to an initialized TEE Context. if (context == NULL) { LOG_E("context is NULL"); if (returnOrigin != NULL) *returnOrigin = TEEC_ORIGIN_API; return TEEC_ERROR_BAD_PARAMETERS; } if (session == NULL) { LOG_E("session is NULL"); if (returnOrigin != NULL) *returnOrigin = TEEC_ORIGIN_API; return TEEC_ERROR_BAD_PARAMETERS; } if (connectionMethod != TEEC_LOGIN_PUBLIC) { //JACKET: Client authorization is not supported. The connectionMethod parameter //must be TEEC LOGIN PUBLIC, otherwise return TEEC ERROR NOT IMPLEMENTED. LOG_E("connectionMethod != TEEC_LOGIN_PUBLIC"); if (returnOrigin != NULL) *returnOrigin = TEEC_ORIGIN_API; return TEEC_ERROR_NOT_IMPLEMENTED; } // ------------------------------------------------------------- session->imp.active = false; _libUuidToArray((TEEC_UUID *)destination, (uint8_t *)tauuid.value); if (operation) operation->imp.session = &session->imp; //Allocate a 4kB page with mmap, zero it out, and set session->imp.tci to its address. session->imp.tci = NULL; void *bulkBuf = (void *)mmap(0, sysconf(_SC_PAGESIZE), PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); if (bulkBuf == MAP_FAILED) { LOG_E("mmap failed on tci buffer allocation"); if (returnOrigin != NULL) *returnOrigin = TEEC_ORIGIN_API; return TEEC_ERROR_OUT_OF_MEMORY; } session->imp.tci = bulkBuf; memset(session->imp.tci, 0, sysconf(_SC_PAGESIZE)); pthread_mutex_init(&session->imp.mutex_tci, NULL); pthread_mutex_lock(&session->imp.mutex_tci); //Fill the TCI buffer session.tci with the destination UUID. memcpy(&(((_TEEC_TCI *)session->imp.tci)->destination), destination, sizeof(TEEC_UUID)); // ------------------------------------------------------------- memset(&session->imp.handle, 0, sizeof(mcSessionHandle_t)); session->imp.handle.deviceId = context->imp.reserved ; // The device ID (default device is used) mcRet = mcOpenGPTA( &session->imp.handle, &tauuid, (uint8_t *)session->imp.tci, sizeof(_TEEC_TCI)); if (mcRet != MC_DRV_OK) { LOG_E("mcOpenGPTA failed (%08x)", mcRet); if (returnOrigin != NULL) *returnOrigin = TEEC_ORIGIN_COMMS; switch (mcRet) { case MC_DRV_ERR_TRUSTED_APPLICATION_NOT_FOUND: teecRes = TEEC_ERROR_ITEM_NOT_FOUND; break; case MC_DRV_ERR_SERVICE_BLOCKED: teecRes = TEEC_ERROR_SD_BLOCKED; break; case MC_DRV_ERR_SERVICE_LOCKED: teecRes = TEEC_ERROR_TA_LOCKED; break; case MC_DRV_ERR_SERVICE_KILLED: teecRes = TEEC_ERROR_TARGET_KILLED; break; case MC_DRV_ERR_NO_FREE_INSTANCES: teecRes = TEEC_ERROR_BUSY; break; default: //TODO: Improve the error codes teecRes = TEEC_ERROR_GENERIC; } goto error; } session->imp.active = true; // Let TA go through entry points LOG_I(" let TA go through entry points"); ((_TEEC_TCI *)session->imp.tci)->operation.type = _TA_OPERATION_OPEN_SESSION; teecRes = _TEEC_CallTA(session, operation, &returnOrigin_local); // Check for error on communication level if (teecRes != TEEC_SUCCESS ) { LOG_E("_TEEC_CallTA failed(%08x)", teecRes); // Nothing to do here because _TEEC_CallTA closes broken sessions if (returnOrigin != NULL) *returnOrigin = returnOrigin_local; goto error; } LOG_I(" no errors in com layer"); // Check for error from TA if (returnOrigin != NULL) *returnOrigin = ((_TEEC_TCI *)session->imp.tci)->returnOrigin; teecRes = ((_TEEC_TCI *)session->imp.tci)->returnStatus; if (teecRes != TEEC_SUCCESS ) { LOG_E("TA OpenSession EP failed(%08x)", teecRes); goto error; } LOG_I(" %s() = TEEC_SUCCESS ", __func__); pthread_mutex_unlock(&session->imp.mutex_tci); if (returnOrigin != NULL) *returnOrigin = TEEC_ORIGIN_TRUSTED_APP; return TEEC_SUCCESS; // ------------------------------------------------------------- error: if (session->imp.active) { // After notifying us, TA went to Destry EP, so close session now mcRet = mcCloseSession(&session->imp.handle); if (mcRet != MC_DRV_OK) { LOG_E("mcCloseSession failed (%08x)", mcRet); /* continue even in case of error */; } session->imp.active = false; } pthread_mutex_unlock(&session->imp.mutex_tci); pthread_mutex_destroy(&session->imp.mutex_tci); if (session->imp.tci) { munmap(session->imp.tci, sysconf(_SC_PAGESIZE)); session->imp.tci = NULL; } LOG_I(" %s() = 0x%x", __func__, teecRes); return teecRes; }
//------------------------------------------------------------------------------ static TEEC_Result _TEEC_CallTA( TEEC_Session *session, TEEC_Operation *operation, uint32_t *returnOrigin) { mcResult_t mcRet; TEEC_Result teecRes; TEEC_Result teecError = TEEC_SUCCESS; LOG_I(" %s()", __func__); // Phase 1: start the operation and wait for the result teecRes = _TEEC_SetupOperation((_TEEC_TCI *)session->imp.tci, &session->imp.handle, operation, returnOrigin); if (teecRes != TEEC_SUCCESS ) { LOG_E("_TEEC_SetupOperation failed (%08x)", teecRes); return teecRes; } // Signal the Trusted App mcRet = mcNotify(&session->imp.handle); if (MC_DRV_OK != mcRet) { LOG_E("Notify failed (%08x)", mcRet); teecError = TEEC_ERROR_COMMUNICATION; goto end; } // ------------------------------------------------------------- // Wait for the Trusted App response mcRet = mcWaitNotification(&session->imp.handle, MC_INFINITE_TIMEOUT); if (mcRet != MC_DRV_OK) { teecError = TEEC_ERROR_COMMUNICATION; if (mcRet == MC_DRV_INFO_NOTIFICATION) { int32_t lastErr = SESSION_ERR_NO; mcGetSessionErrorCode(&session->imp.handle, &lastErr); switch (lastErr) { case TA_EXIT_CODE_FINISHED: // We may get here if the TA_OpenSessionEntryPoint returns an error and TA goes fast through DestroyEntryPoint and exits the TA. teecError = TEEC_SUCCESS; break; case ERR_SESSION_KILLED: teecError = TEEC_ERROR_TARGET_KILLED; break; case ERR_INVALID_SID: case ERR_SID_NOT_ACTIVE: LOG_E("mcWaitNotification failed (%08x)", mcRet); LOG_E("mcGetSessionErrorCode returned %d", lastErr); break; default: LOG_E("Target is DEAD"); *returnOrigin = TEEC_ORIGIN_TEE; teecError = TEEC_ERROR_TARGET_DEAD; break; } } } // Phase 2: Return values and cleanup end: // unmap memory and copy values if no error teecRes = _TEEC_UnwindOperation((_TEEC_TCI *)session->imp.tci, &session->imp.handle, operation, (teecError == TEEC_SUCCESS), returnOrigin); if (teecRes != TEEC_SUCCESS ) { LOG_E("_TEEC_UnwindOperation (%08x)", teecRes); /* continue even in case of error */; } // Cleanup if (teecError != TEEC_SUCCESS) { // Previous interactions failed, either TA is dead or communication error mcRet = mcCloseSession(&session->imp.handle); if (mcRet != MC_DRV_OK) { LOG_E("mcCloseSession failed (%08x)", mcRet); /* continue even in case of error */; } session->imp.active = false; if (teecError == TEEC_ERROR_COMMUNICATION) { *returnOrigin = TEEC_ORIGIN_COMMS; } munmap(session->imp.tci, sysconf(_SC_PAGESIZE)); session->imp.tci = NULL; } return teecError; }