/* * Copyright (C) 2016 The Android Open Source Project * Copyright (C) 2016 The CyanogenMod Project * Copyright (C) 2016 The Mokee Project * * Licensed under the Apache License, Version 2.0 (the "License"); you * may not use this file except in compliance with the License. You may * obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or * implied. See the License for the specific language governing * permissions and limitations under the License. */ #define LOG_TAG "Fingerprint_tz" #define LOG_NDEBUG 1 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "fingerprint_tz.h" #include "fp_klte.h" extern vcs_sensor_t sensor; trust_zone_t tz; worker_state_t get_tz_state() { worker_state_t state; pthread_mutex_lock(&tz.lock); state = tz.state; pthread_mutex_unlock(&tz.lock); return state; } void set_tz_state(worker_state_t state) { pthread_mutex_lock(&tz.lock); tz.state = state; pthread_mutex_unlock(&tz.lock); } /* * cmd: vendorUpdateCalData */ int vcs_update_cal_data() { struct QSEECom_handle *handle = (struct QSEECom_handle *)(tz.qhandle); trust_zone_vendor_cmd_t *send_vendor_cmd = NULL; trust_zone_normal_result_t *resp = NULL; int ret = 0; send_vendor_cmd = (trust_zone_vendor_cmd_t *)handle->ion_sbuffer; resp = (trust_zone_normal_result_t *)(handle->ion_sbuffer + QSEECOM_ALIGN(sizeof(trust_zone_vendor_cmd_t))); memset(send_vendor_cmd, 0, QSEECOM_ALIGN(sizeof(*send_vendor_cmd)) + QSEECOM_ALIGN(sizeof(*resp))); send_vendor_cmd->cmd = vfmVendorDefinedOperation; send_vendor_cmd->vendor_cmd = vendorUpdateCalData; resp->data[0] = CALIBRATE_DATA_MAX_LENGTH; ret = QSEECom_send_cmd(handle, send_vendor_cmd, QSEECOM_ALIGN(sizeof(*send_vendor_cmd)), resp, QSEECOM_ALIGN(sizeof(*resp))); if (ret || resp->result) { ALOGE("Update Cal Data error"); return ret; } tz.calibrate_len = resp->data[3] + 0xf; memcpy(&tz.calibrate_data, &resp->data[2], tz.calibrate_len); ALOGV("Sended vendorUpdateCalData"); return ret; } int vcs_check_state() { struct QSEECom_handle *handle = (struct QSEECom_handle *)(tz.qhandle); trust_zone_base_cmd_t *send_cmd = NULL; trust_zone_normal_result_t *resp = NULL; int ret = 0; send_cmd = (trust_zone_base_cmd_t *)handle->ion_sbuffer; resp = (trust_zone_normal_result_t *)(handle->ion_sbuffer + QSEECOM_ALIGN(sizeof(int))); if (get_tz_state() == STATE_IDLE) return 1; if (get_tz_state() == STATE_CANCEL) { memset(send_cmd, 0, QSEECOM_ALIGN(sizeof(int)) + QSEECOM_ALIGN(sizeof(int))); send_cmd->cmd = vfmCaptureAbort; ret = QSEECom_send_cmd(handle, send_cmd, QSEECOM_ALIGN(sizeof(int)), resp, QSEECOM_ALIGN(sizeof(int))); set_tz_state(STATE_IDLE); return 1; } return 0; } /* * cmd: 1.vfmCaptureStart * 2.vfmCaptureReadData * N * 3.vfmCaptureProcessData */ int vcs_start_capture(void *vdev, time_t t) { struct QSEECom_handle *handle = (struct QSEECom_handle *)(tz.qhandle); trust_zone_base_cmd_t *send_cmd = NULL; trust_zone_normal_result_t *resp = NULL; int ret = 0; send_cmd = (trust_zone_base_cmd_t *)handle->ion_sbuffer; resp = (trust_zone_normal_result_t *)(handle->ion_sbuffer + QSEECOM_ALIGN(sizeof(trust_zone_base_cmd_t))); memset(send_cmd, 0, QSEECOM_ALIGN(sizeof(*send_cmd)) + QSEECOM_ALIGN(sizeof(int))); send_cmd->cmd = vfmCaptureStart; send_cmd->len = 0x1c; send_cmd->data[16] = 0x1; if (t) { *(time_t*)(&send_cmd->data[20]) = t; } send_cmd->data[24] = 0xc0; send_cmd->data[25] = 0x12; ret = QSEECom_send_cmd(handle, send_cmd, QSEECOM_ALIGN(sizeof(*send_cmd)), resp, QSEECOM_ALIGN(sizeof(int))); if (ret || resp->result) { ALOGE("Send vfmCaptureStart error"); return ret; } vcs_update_cal_data(); pthread_mutex_lock(&sensor.lock); sensor_capture_start(); pthread_mutex_unlock(&sensor.lock); pthread_mutex_lock(&sensor.lock); while ((!vcs_check_state()) && !sensor.signal) { pthread_cond_wait(&sensor.cond, &sensor.lock); } pthread_mutex_unlock(&sensor.lock); if (vcs_check_state()) { return -1; } pthread_mutex_lock(&sensor.lock); if (sensor.signal == true) { sensor.signal = false; } pthread_mutex_unlock(&sensor.lock); while(1) { if (vcs_check_state()) { return -1; } resp = (trust_zone_normal_result_t *)(handle->ion_sbuffer + QSEECOM_ALIGN(sizeof(int))); memset(send_cmd, 0, QSEECOM_ALIGN(sizeof(int)) + QSEECOM_ALIGN(sizeof(*resp))); send_cmd->cmd = vfmCaptureReadData; send_cmd->len = 0x8000; resp->data[0] = 0xc; ret = QSEECom_send_cmd(handle, send_cmd, QSEECOM_ALIGN(sizeof(int)), resp, QSEECOM_ALIGN(sizeof(*resp))); if (ret || resp->result) { ALOGE("Send vfmCaptureReadData error"); continue; } if (resp->data[2] == 2) { ALOGV("User's finger removed from sensor"); break; } //usleep(200000); } resp = (trust_zone_normal_result_t *)(handle->ion_sbuffer + QSEECOM_ALIGN(sizeof(trust_zone_base_cmd_t))); memset(send_cmd, 0, QSEECOM_ALIGN(sizeof(*send_cmd)) + QSEECOM_ALIGN(sizeof(*resp))); send_cmd->cmd = vfmCaptureProcessData; send_cmd->len = 0x1c; send_cmd->data[16] = 0x1; *(time_t*)(&send_cmd->data[20]) = time(NULL); send_cmd->data[24] = 0xc0; send_cmd->data[25] = 0x12; resp->data[0] = 0xc; ret = QSEECom_send_cmd(handle, send_cmd, QSEECOM_ALIGN(sizeof(int)), resp, QSEECOM_ALIGN(sizeof(*resp))); if (ret) { ALOGE("Send vfmCaptureProcessData error"); return -1; } if (resp->result != 0) { ALOGE("resp->result=%d",resp->result); send_acquired_notice(vdev, resp->result); return vcs_start_capture(vdev, time(NULL)); } return 0; } /* * cmd: 1.vendorUnknown0 * 2.vcs_start_capture * 3.vfmMatchImageToTemplates * 4.vfmPayloadRelease */ void* vcs_authenticate(void* vdev) { struct QSEECom_handle *handle = (struct QSEECom_handle *)(tz.qhandle); trust_zone_vendor_cmd_t *send_vendor_cmd = NULL; trust_zone_normal_result_t *resp = NULL; int ret = 0; send_vendor_cmd = (trust_zone_vendor_cmd_t *)handle->ion_sbuffer; resp = (trust_zone_normal_result_t *)(handle->ion_sbuffer + QSEECOM_ALIGN(sizeof(trust_zone_vendor_cmd_t))); int fingerindex = 0; int len = 0; int fake_fid = 0; memset(send_vendor_cmd, 0, QSEECOM_ALIGN(sizeof(*send_vendor_cmd)) + QSEECOM_ALIGN(sizeof(*resp))); send_vendor_cmd->cmd = vfmVendorDefinedOperation; send_vendor_cmd->vendor_cmd = vendorUnknown0; resp->data[0] = 0x4; ret = QSEECom_send_cmd(handle, send_vendor_cmd, QSEECOM_ALIGN(sizeof(*send_vendor_cmd)), resp, QSEECOM_ALIGN(sizeof(*resp))); if (resp->result) { ALOGE("%s:Send vendor unknown 0 cmd error", __FUNCTION__); } while (get_tz_state() == STATE_SCAN) { ret = vcs_start_capture(vdev, 0); if (ret == -1) goto out; trust_zone_5x_cmd_t *send_5x_cmd = NULL; trust_zone_2x_result_t *resp_2x = NULL; int idx = 1; send_5x_cmd = (trust_zone_5x_cmd_t *)handle->ion_sbuffer; resp_2x = (trust_zone_2x_result_t *)(handle->ion_sbuffer + QSEECOM_ALIGN(sizeof(trust_zone_5x_cmd_t))); memset(send_5x_cmd, 0, QSEECOM_ALIGN(sizeof(*send_5x_cmd)) + QSEECOM_ALIGN(sizeof(*resp_2x))); send_5x_cmd->cmd = vfmMatchImageToTemplates; send_5x_cmd->len = 0x14; send_5x_cmd->unknown[0] = 1; send_5x_cmd->unknown[1] = 100000; send_5x_cmd->time_now = time(NULL); send_5x_cmd->data[0] = 0x1; send_5x_cmd->data[102388] = vcs_get_enrolled_finger_num(); len = 0; for (idx = 1; idx <= MAX_NUM_FINGERS; idx++) if (tz.finger[idx].exist) { len++; int address = 102392 + (len - 1) * 15364; send_5x_cmd->data[address] = 0x45; send_5x_cmd->data[address + 1] = 0x28; memcpy(&send_5x_cmd->data[address + 4], &tz.finger[idx].data, FINGER_DATA_MAX_LENGTH); } resp_2x->data[0] = 0x5c; resp_2x->data[25602] = 0x3000; ret = QSEECom_send_cmd(handle, send_5x_cmd, QSEECOM_ALIGN(sizeof(*send_5x_cmd)), resp_2x, QSEECOM_ALIGN(sizeof(*resp_2x))); if (ret) { ALOGE("%s:send vfmMatchImageToTemplates error", __FUNCTION__); send_error_notice(vdev, FINGERPRINT_ERROR_UNABLE_TO_PROCESS); goto out; } if (resp_2x->result != 0) { send_acquired_notice(vdev, resp_2x->result); continue; } fake_fid = (int)resp_2x->data[22] + 1; len = 0; for (idx = 1; idx <= MAX_NUM_FINGERS; idx++) { if (tz.finger[idx].exist) { len++; if (len == fake_fid) { fingerindex = idx; break; } } } ALOGV("Auth fingerindex=%d", fingerindex); //memcpy(&tz.finger[fingerindex].data, &resp_2x->data[102419], FINGER_DATA_MAX_LENGTH); //db_write_to_db(vdev, false, fingerindex); trust_zone_2x_cmd_t *send_2x_cmd = NULL; send_2x_cmd = (trust_zone_2x_cmd_t *)handle->ion_sbuffer; resp = (trust_zone_normal_result_t *)(handle->ion_sbuffer + QSEECOM_ALIGN(sizeof(trust_zone_2x_cmd_t))); memset(send_2x_cmd, 0, QSEECOM_ALIGN(sizeof(*send_2x_cmd)) + QSEECOM_ALIGN(sizeof(*resp))); send_2x_cmd->cmd = vfmPayloadRelease; send_2x_cmd->len = PAYLOAD_MAX_LENGTH; memcpy(&send_2x_cmd->data, &tz.finger[fingerindex].payload, PAYLOAD_MAX_LENGTH); resp->data[0] = 0x24; ret = QSEECom_send_cmd(handle, send_2x_cmd, QSEECOM_ALIGN(sizeof(*send_2x_cmd)), resp, QSEECOM_ALIGN(sizeof(*resp))); break; } out: sensor_uninit(); vcs_uninit(); set_tz_state(STATE_IDLE); if (fingerindex) { send_authenticated_notice(vdev, fingerindex); } return NULL; } /* * cmd: 1.vfmEnrollBegin * 2.vendorUnknownA * 3.vcs_start_capture * 8 * 4.vfmEnrollAddImage * 5.vfmEnrollFinish * 6.vfmPayloadBind * 7.vfmEnrollmentPasswordSet */ void* vcs_enroll(void* vdev) { int count = 8; struct QSEECom_handle *handle = (struct QSEECom_handle *)(tz.qhandle); trust_zone_base_cmd_t *send_cmd = NULL; trust_zone_vendor_cmd_t *send_vendor_cmd = NULL; trust_zone_normal_result_t *resp = NULL; int ret = 0; int i = 0; send_cmd = (trust_zone_base_cmd_t *)handle->ion_sbuffer; send_vendor_cmd = (trust_zone_vendor_cmd_t *)handle->ion_sbuffer; resp = (trust_zone_normal_result_t *)(handle->ion_sbuffer + QSEECOM_ALIGN(sizeof(trust_zone_base_cmd_t))); int idx = 1; for (idx = 1; idx <= MAX_NUM_FINGERS; idx++) { if (!tz.finger[idx].exist) { break; } } memset(send_cmd, 0, QSEECOM_ALIGN(sizeof(*send_cmd)) + QSEECOM_ALIGN(sizeof(int))); send_cmd->cmd = vfmEnrollBegin; send_cmd->data[102400] = idx; ret = QSEECom_send_cmd(handle, send_cmd, QSEECOM_ALIGN(sizeof(*send_cmd)), resp, QSEECOM_ALIGN(sizeof(int))); if (ret || resp->result) { ALOGE("send EnrollBegin error"); set_tz_state(STATE_IDLE); send_error_notice(vdev, FINGERPRINT_ERROR_UNABLE_TO_PROCESS); return NULL; } memset(send_vendor_cmd, 0, QSEECOM_ALIGN(sizeof(*send_vendor_cmd)) + QSEECOM_ALIGN(sizeof(*resp))); send_vendor_cmd->cmd = vfmVendorDefinedOperation; send_vendor_cmd->vendor_cmd = vendorUnknownA; resp->data[0] = 0x4; ret = QSEECom_send_cmd(handle, send_vendor_cmd, QSEECOM_ALIGN(sizeof(*send_vendor_cmd)), resp, QSEECOM_ALIGN(sizeof(*resp))); if (ret || resp->result) { ALOGE("send vendorUnknownA error"); set_tz_state(STATE_IDLE); send_error_notice(vdev, FINGERPRINT_ERROR_UNABLE_TO_PROCESS); return NULL; } while (get_tz_state() == STATE_ENROLL) { ret = vcs_start_capture(vdev, 0); if (ret == -1) goto out; resp = (trust_zone_normal_result_t *)(handle->ion_sbuffer + QSEECOM_ALIGN(sizeof(int))); memset(send_cmd, 0, QSEECOM_ALIGN(sizeof(int)) + QSEECOM_ALIGN(sizeof(*resp))); send_cmd->cmd = vfmEnrollAddImage; resp->data[0] = 0x8; ret = QSEECom_send_cmd(handle, send_cmd, QSEECOM_ALIGN(sizeof(int)), resp, QSEECOM_ALIGN(sizeof(*resp))); if (ret) { ALOGE("%s:send vfmEnrollAddImage error", __FUNCTION__); set_tz_state(STATE_IDLE); send_error_notice(vdev, FINGERPRINT_ERROR_UNABLE_TO_PROCESS); return NULL; } if (resp->result != 0) { send_acquired_notice(vdev, resp->result); continue; } count--; if (resp->data[2] == 0x1) count = 0; if (resp->data[2] != 0x1 && count == 0) count = 1; send_enroll_notice(vdev, idx, count); if (count == 0) break; } resp = (trust_zone_normal_result_t *)(handle->ion_sbuffer + QSEECOM_ALIGN(sizeof(trust_zone_base_cmd_t))); memset(send_cmd, 0, QSEECOM_ALIGN(sizeof(*send_cmd)) + QSEECOM_ALIGN(sizeof(*resp))); send_cmd->cmd = vfmEnrollFinish; send_cmd->len = AUTH_SESSION_TOKEN_LENGTH; resp->data[0] = 0x2845; memcpy(&send_cmd->data, &tz.auth_session_token, AUTH_SESSION_TOKEN_LENGTH); ret = QSEECom_send_cmd(handle, send_cmd, QSEECOM_ALIGN(sizeof(*send_cmd)), resp, QSEECOM_ALIGN(sizeof(*resp))); if (ret || resp->result) { ALOGE("Send vfmEnrollFinish error"); } memcpy(&tz.finger[idx].data, &resp->data[2], FINGER_DATA_MAX_LENGTH); for (i = 0; i < 2; i++) { memset(send_cmd, 0, QSEECOM_ALIGN(sizeof(*send_cmd)) + QSEECOM_ALIGN(sizeof(*resp))); send_cmd->cmd = vfmPayloadBind; send_cmd->len = 0x1; send_cmd->zero = 0x7; sprintf(&send_cmd->data[4], "User_0"); if (i == 1) { resp->data[0] = 0x50; } ret = QSEECom_send_cmd(handle, send_cmd, QSEECOM_ALIGN(sizeof(*send_cmd)), resp, QSEECOM_ALIGN(sizeof(*resp))); } if (ret || resp->result) { ALOGE("Send vfmPayloadBind error"); } memcpy(&tz.finger[idx].payload, &resp->data[2], PAYLOAD_MAX_LENGTH); tz.finger[idx].exist = true; db_write_to_db(vdev, false, idx); // We may not need to send vfmEnrollmentPasswordSet. for (i = 0; i < 2; i++) { trust_zone_3x_cmd_t *send_3x_cmd = NULL; send_3x_cmd = (trust_zone_3x_cmd_t *)handle->ion_sbuffer; resp = (trust_zone_normal_result_t *)(handle->ion_sbuffer + QSEECOM_ALIGN(sizeof(trust_zone_3x_cmd_t))); memset(send_3x_cmd, 0, QSEECOM_ALIGN(sizeof(*send_3x_cmd)) + QSEECOM_ALIGN(sizeof(*resp))); send_3x_cmd->cmd = vfmEnrollmentPasswordSet; send_3x_cmd->len = AUTH_SESSION_TOKEN_LENGTH; memcpy(&send_3x_cmd->data, &tz.auth_session_token, AUTH_SESSION_TOKEN_LENGTH); if (i == 0) { resp->data[0] = 0x90; } else { resp->data[0] = 0x80; } ret = QSEECom_send_cmd(handle, send_3x_cmd, QSEECOM_ALIGN(sizeof(*send_3x_cmd)), resp, QSEECOM_ALIGN(sizeof(*resp))); } if (ret || resp->result) { ALOGE("Send vfmEnrollmentPasswordSet error"); } out: set_tz_state(STATE_IDLE); sensor_uninit(); vcs_uninit(); return NULL; } void* vcs_timeout(void* vdev) { struct timeval now; struct timespec outtime; int ret = 0; pthread_mutex_lock(&tz.timeout.lock); gettimeofday(&now, NULL); outtime.tv_sec = now.tv_sec + tz.timeout.timeout; outtime.tv_nsec = now.tv_usec * 1000; ret = pthread_cond_timedwait(&tz.timeout.cond, &tz.timeout.lock, &outtime); pthread_mutex_unlock(&tz.timeout.lock); if (ret == ETIMEDOUT) { ALOGI("Enroll timeout! Exit!"); int flag = 0; if (get_tz_state() != STATE_IDLE && get_tz_state() != STATE_CANCEL) { set_tz_state(STATE_CANCEL); ioctl(sensor.fd, VFSSPI_IOCTL_SET_DRDY_INT, &flag); while (1) { usleep(100000); if (get_tz_state() == STATE_IDLE) break; } } send_error_notice(vdev, FINGERPRINT_ERROR_TIMEOUT); } return NULL; } int vcs_start_authenticate(void *vdev) { int times = 0; for (times = 0; times < 5; times++) if (get_tz_state() != STATE_IDLE) { ALOGE("%s:Sensor is busy!", __FUNCTION__); if (times < 4) { usleep(100000); continue; } return -1; } set_tz_state(STATE_SCAN); int ret = 0; sensor_init(); ret = vcs_init(); if (ret) return ret; ret = pthread_create(&tz.auth_thread, NULL, vcs_authenticate, vdev); if (ret) { ALOGE("Can't create authenticate thread!!"); } return ret; } int vcs_start_enroll(void *vdev, uint32_t timeout) { if (get_tz_state() != STATE_IDLE) { ALOGE("%s:Sensor is busy!", __FUNCTION__); return -1; } set_tz_state(STATE_ENROLL); int ret = 0; sensor_init(); ret = vcs_init(); if (ret) { return ret; } ret = pthread_create(&tz.enroll_thread, NULL, vcs_enroll, vdev); if (ret) { ALOGE("Can't create enroll thread!!"); return ret; } if (timeout) { tz.timeout.timeout = timeout; ret = pthread_create(&tz.timeout.timeout_thread, NULL, vcs_timeout, vdev); if (ret) { ALOGE("Can't create timeout thread!!"); } } return ret; } int vcs_get_enrolled_finger_num() { int num = 0; int idx = 1; for (idx = 1; idx <= MAX_NUM_FINGERS; idx++) if (tz.finger[idx].exist) num++; ALOGV("%s: num=%d", __FUNCTION__, num); return num; } /* * cmd: vendorGetAuthToken */ int vcs_update_auth_token() { struct QSEECom_handle *handle = (struct QSEECom_handle *)(tz.qhandle); trust_zone_vendor_cmd_t *send_vendor_cmd = NULL; trust_zone_normal_result_t *resp = NULL; int ret = 0; send_vendor_cmd = (trust_zone_vendor_cmd_t *)handle->ion_sbuffer; resp = (trust_zone_normal_result_t *)(handle->ion_sbuffer + QSEECOM_ALIGN(sizeof(trust_zone_vendor_cmd_t))); int i = 0; for (i = 0;i < 2; i++) { memset(send_vendor_cmd, 0, QSEECOM_ALIGN(sizeof(*send_vendor_cmd)) + QSEECOM_ALIGN(sizeof(*resp))); send_vendor_cmd->cmd = vfmVendorDefinedOperation; send_vendor_cmd->vendor_cmd = vendorGetAuthToken; if (i == 1) { resp->data[0] = 0x80; } ret = QSEECom_send_cmd(handle, send_vendor_cmd, QSEECOM_ALIGN(sizeof(*send_vendor_cmd)), resp, QSEECOM_ALIGN(sizeof(*resp))); } if (resp->result) { ALOGE("send vendorGetAuthToken failed, qsapp result=%d", resp->result); return resp->result; } memcpy(&tz.auth_token, &resp->data[2], AUTH_TOKEN_LENGTH); ALOGV("Sended vendorGetAuthToken"); return ret; } /* * cmd: vfmAuthSessionBegin */ int vcs_start_auth_session() { struct QSEECom_handle *handle = (struct QSEECom_handle *)(tz.qhandle); trust_zone_base_cmd_t *send_cmd = NULL; trust_zone_vendor_cmd_t *send_vendor_cmd = NULL; trust_zone_normal_result_t *resp = NULL; int ret = 0; send_cmd = (trust_zone_base_cmd_t *)handle->ion_sbuffer; send_vendor_cmd = (trust_zone_vendor_cmd_t *)handle->ion_sbuffer; int i = 0; resp = (trust_zone_normal_result_t *)(handle->ion_sbuffer + QSEECOM_ALIGN(sizeof(int))); memset(send_cmd, 0, QSEECOM_ALIGN(sizeof(int)) + QSEECOM_ALIGN(sizeof(*resp))); send_cmd->cmd = vfmAuthSessionBegin; resp->data[0] = AUTH_SESSION_TOKEN_LENGTH; ret = QSEECom_send_cmd(handle, send_cmd, QSEECOM_ALIGN(sizeof(int)), resp, QSEECOM_ALIGN(sizeof(*resp))); if (ret || resp->result) { ALOGE("send vfmAuthSessionBegin failed, qsapp result=%d", resp->result); return ret; } memcpy(&tz.auth_session_token, &resp->data[2], AUTH_SESSION_TOKEN_LENGTH); tz.auth_session_opend = true; ALOGV("Sended vfmAuthSessionBegin"); return ret; } /* * cmd: vfmAuthSessionEnd */ int vcs_stop_auth_session() { struct QSEECom_handle *handle = (struct QSEECom_handle *)(tz.qhandle); trust_zone_base_cmd_t *send_cmd = NULL; trust_zone_normal_result_t *resp = NULL; int ret = 0; send_cmd = (trust_zone_base_cmd_t *)handle->ion_sbuffer; resp = (trust_zone_normal_result_t *)(handle->ion_sbuffer + QSEECOM_ALIGN(sizeof(int))); memset(send_cmd, 0, QSEECOM_ALIGN(sizeof(int)) + QSEECOM_ALIGN(sizeof(int))); send_cmd->cmd = vfmAuthSessionEnd; ret = QSEECom_send_cmd(handle, send_cmd, QSEECOM_ALIGN(sizeof(int)), resp, QSEECOM_ALIGN(sizeof(int))); if (ret || resp->result) { ALOGE("send vfmAuthSessionEnd failed, qsapp result=%d", resp->result); } memset(tz.auth_session_token, 0, AUTH_SESSION_TOKEN_LENGTH); tz.auth_session_opend = false; ALOGV("Sended vfmAuthSessionEnd"); return ret; } /* * cmd: 1.vfmInitialize * 2.vendorEnterAuthSession * 3.vfmDeviceInitialize * 4.vfmDeviceCalibrate */ int vcs_resume() { struct QSEECom_handle *handle = (struct QSEECom_handle *)(tz.qhandle); trust_zone_base_cmd_t *send_cmd = NULL; trust_zone_normal_result_t *resp = NULL; int ret = 0; send_cmd = (trust_zone_base_cmd_t *)handle->ion_sbuffer; resp = (trust_zone_normal_result_t *)(handle->ion_sbuffer + QSEECOM_ALIGN(sizeof(trust_zone_base_cmd_t))); memset(send_cmd, 0, QSEECOM_ALIGN(sizeof(*send_cmd)) + QSEECOM_ALIGN(sizeof(int))); send_cmd->cmd = vfmInitialize; send_cmd->len = 4; send_cmd->data[0] = 2; ret = QSEECom_send_cmd(handle, send_cmd, QSEECOM_ALIGN(sizeof(*send_cmd)), resp, QSEECOM_ALIGN(sizeof(int))); if (ret || resp->result) { ALOGE("send vfmInitialize failed, qsapp result=%d", resp->result); return ret; } ALOGV("Sended vfmInitialize"); if (tz.auth_session_opend) { trust_zone_vendor_cmd_t *send_vendor_cmd = NULL; send_vendor_cmd = (trust_zone_vendor_cmd_t *)handle->ion_sbuffer; memset(send_vendor_cmd, 0, QSEECOM_ALIGN(sizeof(*send_vendor_cmd)) + QSEECOM_ALIGN(sizeof(*resp))); send_vendor_cmd->cmd = vfmVendorDefinedOperation; send_vendor_cmd->vendor_cmd = vendorEnterAuthSession; send_vendor_cmd->len = 0x70; memcpy(&send_vendor_cmd->data, &tz.auth_token, 0x70); ret = QSEECom_send_cmd(handle, send_vendor_cmd, QSEECOM_ALIGN(sizeof(*send_vendor_cmd)), resp, QSEECOM_ALIGN(sizeof(*resp))); if (ret || resp->result) { ALOGE("send EnterAuthSession failed, qsapp result=%d", resp->result); return resp->result; } } ALOGV("Sended EnterAuthSession"); memset(send_cmd, 0, QSEECOM_ALIGN(sizeof(*send_cmd)) + QSEECOM_ALIGN(sizeof(int))); send_cmd->cmd = vfmDeviceInitialize; ret = QSEECom_send_cmd(handle, send_cmd, QSEECOM_ALIGN(sizeof(*send_cmd)), resp, QSEECOM_ALIGN(sizeof(int))); if (ret || resp->result) { ALOGE("send vfmDeviceInitialize failed, qsapp result=%d", resp->result); return ret; } ALOGV("Sended vfmDeviceInitialize"); memset(send_cmd, 0, QSEECOM_ALIGN(sizeof(*send_cmd)) + QSEECOM_ALIGN(sizeof(*resp))); send_cmd->cmd = vfmDeviceCalibrate; send_cmd->data[0] = 0xc0; send_cmd->data[1] = 0x12; resp->data[0] = CALIBRATE_DATA_MAX_LENGTH; if (tz.calibrate_len) { send_cmd->len = tz.calibrate_len; memcpy(&send_cmd->data[4], &tz.calibrate_data, tz.calibrate_len); } else { send_cmd->len = 0x10; } ret = QSEECom_send_cmd(handle, send_cmd, QSEECOM_ALIGN(sizeof(*send_cmd)), resp, QSEECOM_ALIGN(sizeof(*resp))); if (ret || resp->result) { ALOGE("send vfmDeviceCalibrate failed, qsapp result=%d", resp->result); return ret; } if (tz.calibrate_len == 0) { tz.calibrate_len = resp->data[3] + 0xf; memcpy(&tz.calibrate_data, &resp->data[2], tz.calibrate_len); } ALOGV("Sended vfmDeviceCalibrate"); return ret; } /* * cmd: vfmUninitialize * set bandwidth to low and shutdown app */ int vcs_uninit() { struct QSEECom_handle *handle = (struct QSEECom_handle *)(tz.qhandle); trust_zone_base_cmd_t *send_cmd = NULL; trust_zone_normal_result_t *resp = NULL; send_cmd = (trust_zone_base_cmd_t *)handle->ion_sbuffer; resp = (trust_zone_normal_result_t *)(handle->ion_sbuffer + QSEECOM_ALIGN(sizeof(trust_zone_base_cmd_t))); if (tz.auth_session_opend) { vcs_update_auth_token(); } memset(send_cmd, 0, QSEECOM_ALIGN(sizeof(int)) + QSEECOM_ALIGN(sizeof(int))); send_cmd->cmd = vfmUninitialize; QSEECom_send_cmd(handle, send_cmd, QSEECOM_ALIGN(sizeof(int)), resp, QSEECOM_ALIGN(sizeof(int))); QSEECom_set_bandwidth(handle, false); QSEECom_shutdown_app((struct QSEECom_handle **)&tz.qhandle); tz.init = false; set_tz_state(STATE_IDLE); ALOGV("Closed securefp qsapp"); return 0; } /* * start app and set bandwidth to high * Call vcs_resume */ int vcs_init() { int ret = 0; if (tz.init) { ALOGI("securefp qsapp is already running!"); return ret; } ret = QSEECom_start_app((struct QSEECom_handle **)&tz.qhandle, "/firmware/image", "securefp", SB_LENGTH); if (ret) { ALOGE("Loading securefp app failed"); return -1; } struct QSEECom_handle *handle = (struct QSEECom_handle *)(tz.qhandle); ret = QSEECom_set_bandwidth(handle, true); if (ret) { ALOGE("Set bandwidth failed"); return -1; } tz.init = true; ALOGV("securefp qsapp init success!"); ret = vcs_resume(); return ret; }