//------------------------------------------------------------------------------
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);
}
예제 #2
0
// -------------------------------------------------------------
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;
}