void *string2data(const char *string) { void *data; size_t size; size_t length; int shift; unsigned char *p; unsigned int b; size_t i; int rc; if (string == NULL) return NULL; length = strlen(string); if (length == 0) return NULL; if (length % 2 == 0) shift = 0; else shift = 1; size = string2data_size(string); if (size == 0) return NULL; data = calloc(1, size); p = (unsigned char *) data; for (i = 0; i < length; i++) { rc = sscanf(&string[i], "%01x", &b); if (rc < 1) b = 0; if ((shift % 2) == 0) *p |= ((b & 0x0f) << 4); else *p++ |= b & 0x0f; shift++; } return data; }
int ril_request_get_sim_status(void *data, size_t size, RIL_Token token) { void *card_status_data; size_t card_status_size; #if RIL_VERSION >= 6 RIL_CardStatus_v6 *card_status; #else RIL_CardStatus *card_status; #endif struct ril_request *request; int rc; rc = ril_radio_state_check(RADIO_STATE_SIM_NOT_READY); if (rc < 0) return RIL_REQUEST_UNHANDLED; request = ril_request_find_request_status(RIL_REQUEST_GET_SIM_STATUS, RIL_REQUEST_HANDLED); if (request != NULL) return RIL_REQUEST_UNHANDLED; card_status_size = ril_request_data_size_get(RIL_REQUEST_GET_SIM_STATUS); card_status_data = ril_request_data_get(RIL_REQUEST_GET_SIM_STATUS); #if RIL_VERSION >= 6 if (card_status_data != NULL && card_status_size >= sizeof(RIL_CardStatus_v6)) { card_status = (RIL_CardStatus_v6 *) ril_request_data_get(RIL_REQUEST_GET_SIM_STATUS); #else if (card_status_data != NULL && card_status_size >= sizeof(RIL_CardStatus)) { card_status = (RIL_CardStatus *) ril_request_data_get(RIL_REQUEST_GET_SIM_STATUS); #endif ril_request_complete(token, RIL_E_SUCCESS, card_status_data, card_status_size); free(card_status_data); return RIL_REQUEST_COMPLETED; } else { rc = ipc_fmt_send(ipc_fmt_request_seq(token), IPC_SEC_PIN_STATUS, IPC_TYPE_GET, NULL, 0); if (rc < 0) { ril_request_complete(token, RIL_E_GENERIC_FAILURE, NULL, 0); return RIL_REQUEST_COMPLETED; } return RIL_REQUEST_HANDLED; } } int ipc_sec_phone_lock(struct ipc_message *message) { struct ipc_sec_phone_lock_response_data *data; int active; if (message == NULL || message->data == NULL || message->size < sizeof(struct ipc_sec_phone_lock_response_data)) return -1; if (message->type != IPC_TYPE_RESP || !ipc_seq_valid(message->aseq)) return 0; data = (struct ipc_sec_phone_lock_response_data *) message->data; active = !!data->active; ril_request_complete(ipc_fmt_request_token(message->aseq), RIL_E_SUCCESS, &active, sizeof(active)); return 0; } int ril_request_query_facility_lock(void *data, size_t size, RIL_Token token) { struct ipc_sec_phone_lock_request_get_data request_data; char **values = NULL; int rc; if (data == NULL || size < 4 * sizeof(char *)) goto error; rc = ril_radio_state_check(RADIO_STATE_SIM_READY); if (rc < 0) return RIL_REQUEST_UNHANDLED; values = (char **) data; request_data.facility_type = ril2ipc_sec_facility_type(values[0]); if (request_data.facility_type == 0) goto error; strings_array_free(values, size); values = NULL; rc = ipc_fmt_send(ipc_fmt_request_seq(token), IPC_SEC_PHONE_LOCK, IPC_TYPE_GET, (void *) &request_data, sizeof(request_data)); if (rc < 0) goto error; rc = RIL_REQUEST_HANDLED; goto complete; error: if (values != NULL) strings_array_free(values, size); ril_request_complete(token, RIL_E_GENERIC_FAILURE, NULL, 0); rc = RIL_REQUEST_COMPLETED; complete: return rc; } int ipc_sec_callback(struct ipc_message *message) { struct ipc_sec_lock_infomation_request_data request_data; struct ipc_gen_phone_res_data *data; struct ril_request *request = NULL; void *request_complete_data; size_t request_complete_size; unsigned char facility_type; char **values; int retry_count; int rc; if (message == NULL || message->data == NULL || message->size < sizeof(struct ipc_gen_phone_res_data)) return -1; data = (struct ipc_gen_phone_res_data *) message->data; request = ril_request_find_token(ipc_fmt_request_token(message->aseq)); if (request == NULL) goto error; if (request->request == RIL_REQUEST_ENTER_SIM_PIN || request->request == RIL_REQUEST_CHANGE_SIM_PIN) { // Grab the count of remaining tries before completing the request ril_request_data_set_uniq(request->request, (void *) data, sizeof(struct ipc_gen_phone_res_data)); rc = ipc_sec_lock_infomation_setup(&request_data, IPC_SEC_PIN_TYPE_PIN1); if (rc < 0) { ril_request_data_free(request->request); goto error; } rc = ipc_fmt_send(message->aseq, IPC_SEC_LOCK_INFOMATION, IPC_TYPE_GET, (void *) &request_data, sizeof(request_data)); if (rc < 0) { ril_request_data_free(request->request); goto error; } } else if (request->request == RIL_REQUEST_ENTER_SIM_PIN2 || request->request == RIL_REQUEST_CHANGE_SIM_PIN2) { // Grab the count of remaining tries before completing the request ril_request_data_set_uniq(request->request, (void *) data, sizeof(struct ipc_gen_phone_res_data)); rc = ipc_sec_lock_infomation_setup(&request_data, IPC_SEC_PIN_TYPE_PIN2); if (rc < 0) { ril_request_data_free(request->request); goto error; } rc = ipc_fmt_send(message->aseq, IPC_SEC_LOCK_INFOMATION, IPC_TYPE_GET, (void *) &request_data, sizeof(request_data)); if (rc < 0) { ril_request_data_free(request->request); goto error; } } else if (request->request == RIL_REQUEST_SET_FACILITY_LOCK) { values = (char **) request->data; request_complete_size = ril_request_data_size_get(RIL_REQUEST_SET_FACILITY_LOCK); request_complete_data = ril_request_data_get(RIL_REQUEST_SET_FACILITY_LOCK); rc = ipc_gen_phone_res_check(data); if (request_complete_data != NULL && request_complete_size > 0 && rc >= 0) { rc = ipc_gen_phone_res_expect_callback(message->aseq, IPC_SEC_PHONE_LOCK, ipc_sec_callback); if (rc < 0) { strings_array_free(values, request->size); goto error; } rc = ipc_fmt_send(message->aseq, IPC_SEC_PHONE_LOCK, IPC_TYPE_SET, request_complete_data, request_complete_size); if (rc < 0) { strings_array_free(values, request->size); goto error; } } else { // When FD facility PIN2 unlock failed, ask the count of remaining tries directly facility_type = ril2ipc_sec_facility_type(values[0]); strings_array_free(values, request->size); // Grab the count of remaining tries before completing the request ril_request_data_set_uniq(RIL_REQUEST_SET_FACILITY_LOCK, (void *) data, sizeof(struct ipc_gen_phone_res_data)); if (facility_type == IPC_SEC_FACILITY_TYPE_FD) { rc = ipc_sec_lock_infomation_setup(&request_data, IPC_SEC_PIN_TYPE_PIN2); if (rc < 0) { ril_request_data_free(request->request); goto error; } } else { rc = ipc_sec_lock_infomation_setup(&request_data, IPC_SEC_PIN_TYPE_PIN1); if (rc < 0) { ril_request_data_free(request->request); goto error; } } rc = ipc_fmt_send(message->aseq, IPC_SEC_LOCK_INFOMATION, IPC_TYPE_GET, (void *) &request_data, sizeof(request_data)); if (rc < 0) { ril_request_data_free(request->request); goto error; } } } else if (request->request == RIL_REQUEST_SIM_IO) { request_complete_size = ril_request_data_size_get(RIL_REQUEST_SIM_IO); request_complete_data = ril_request_data_get(RIL_REQUEST_SIM_IO); rc = ipc_gen_phone_res_check(data); if (rc < 0) { ril_request_complete(request->token, RIL_E_SIM_PIN2, NULL, 0); goto complete; } if (request_complete_data != NULL && request_complete_size > 0) { rc = ipc_fmt_send(message->aseq, IPC_SEC_RSIM_ACCESS, IPC_TYPE_GET, request_complete_data, request_complete_size); if (rc < 0) goto error; } else { goto error; } } else { retry_count = -1; rc = ipc_gen_phone_res_check(data); if (rc < 0) { if ((data->code & 0xff) == 0x10) { RIL_LOGE("%s: Wrong password", __func__); ril_request_complete(ipc_fmt_request_token(message->aseq), RIL_E_PASSWORD_INCORRECT, &retry_count, sizeof(retry_count)); } else if ((data->code & 0xff) == 0x0c) { RIL_LOGE("%s: Wrong password and no attempts left", __func__); retry_count = 0; ril_request_complete(ipc_fmt_request_token(message->aseq), RIL_E_PASSWORD_INCORRECT, &retry_count, sizeof(retry_count)); } else { ril_request_complete(ipc_fmt_request_token(message->aseq), RIL_E_GENERIC_FAILURE, &retry_count, sizeof(retry_count)); } } else { ril_request_complete(ipc_fmt_request_token(message->aseq), RIL_E_SUCCESS, &retry_count, sizeof(retry_count)); } } if (request->request == RIL_REQUEST_ENTER_SIM_PUK || request->request == RIL_REQUEST_ENTER_SIM_PUK2) ril_request_unsolicited(RIL_UNSOL_RESPONSE_SIM_STATUS_CHANGED, NULL, 0); goto complete; error: if (request != NULL) ril_request_complete(request->token, RIL_E_GENERIC_FAILURE, NULL, 0); complete: return 0; } int ril_request_set_facility_lock(void *data, size_t size, RIL_Token token) { struct ipc_sec_phone_lock_request_set_data request_data; struct ipc_sec_pin_status_request_data pin_request_data; struct ril_request *request; unsigned char facility_type; unsigned char active; char **values = NULL; int rc; if (data == NULL || size < 4 * sizeof(char *)) goto error; rc = ril_radio_state_check(RADIO_STATE_SIM_READY); if (rc < 0) return RIL_REQUEST_UNHANDLED; request = ril_request_find_request_status(RIL_REQUEST_SET_FACILITY_LOCK, RIL_REQUEST_HANDLED); if (request != NULL) return RIL_REQUEST_UNHANDLED; values = (char **) data; facility_type = ril2ipc_sec_facility_type(values[0]); if (facility_type == 0) goto error; active = values[1][0] == '1'; rc = ipc_sec_phone_lock_request_set_setup(&request_data, facility_type, active, values[2]); if (rc < 0) goto error; if (facility_type == IPC_SEC_FACILITY_TYPE_FD) { // FD facility requires PIN2 unlock first rc = ipc_sec_pin_status_setup(&pin_request_data, IPC_SEC_PIN_TYPE_PIN2, values[2], NULL); if (rc < 0) goto error; ril_request_data_set_uniq(RIL_REQUEST_SET_FACILITY_LOCK, &request_data, sizeof(request_data)); rc = ipc_gen_phone_res_expect_callback(ipc_fmt_request_seq(token), IPC_SEC_PIN_STATUS, ipc_sec_callback); if (rc < 0) { ril_request_data_free(RIL_REQUEST_SET_FACILITY_LOCK); goto error; } rc = ipc_fmt_send(ipc_fmt_request_seq(token), IPC_SEC_PIN_STATUS, IPC_TYPE_SET, (void *) &pin_request_data, sizeof(pin_request_data)); if (rc < 0) { ril_request_data_free(RIL_REQUEST_SET_FACILITY_LOCK); goto error; } rc = RIL_REQUEST_HANDLED; goto complete; } rc = ipc_gen_phone_res_expect_callback(ipc_fmt_request_seq(token), IPC_SEC_PHONE_LOCK, ipc_sec_callback); if (rc < 0) goto error; rc = ipc_fmt_send(ipc_fmt_request_seq(token), IPC_SEC_PHONE_LOCK, IPC_TYPE_SET, (void *) &request_data, sizeof(request_data)); if (rc < 0) goto error; rc = RIL_REQUEST_HANDLED; goto complete; error: if (values != NULL) strings_array_free(values, size); ril_request_complete(token, RIL_E_GENERIC_FAILURE, NULL, 0); rc = RIL_REQUEST_COMPLETED; complete: return rc; } int ril_request_enter_sim_pin(void *data, size_t size, RIL_Token token) { struct ipc_sec_pin_status_request_data request_data; struct ril_request *request; char **values = NULL; int rc; if (data == NULL || size < 2 * sizeof(char *) || ril_data == NULL) goto error; rc = ril_radio_state_check(RADIO_STATE_SIM_NOT_READY); if (rc < 0) return RIL_REQUEST_UNHANDLED; request = ril_request_find_request_status(RIL_REQUEST_ENTER_SIM_PIN, RIL_REQUEST_HANDLED); if (request != NULL) return RIL_REQUEST_UNHANDLED; values = (char **) data; if (values[0] == NULL) goto error; if (ril_data->sim_pin != NULL) free(ril_data->sim_pin); ril_data->sim_pin = strdup(values[0]); rc = ipc_sec_pin_status_setup(&request_data, IPC_SEC_PIN_TYPE_PIN1, values[0], NULL); if (rc < 0) goto error; strings_array_free(values, size); values = NULL; rc = ipc_gen_phone_res_expect_callback(ipc_fmt_request_seq(token), IPC_SEC_PIN_STATUS, ipc_sec_callback); if (rc < 0) goto error; rc = ipc_fmt_send(ipc_fmt_request_seq(token), IPC_SEC_PIN_STATUS, IPC_TYPE_SET, (void *) &request_data, sizeof(request_data)); if (rc < 0) goto error; rc = RIL_REQUEST_HANDLED; goto complete; error: if (values != NULL) strings_array_free(values, size); ril_request_complete(token, RIL_E_GENERIC_FAILURE, NULL, 0); rc = RIL_REQUEST_COMPLETED; complete: return rc; } int ril_request_enter_sim_puk(void *data, size_t size, RIL_Token token) { struct ipc_sec_pin_status_request_data request_data; struct ril_request *request; char **values = NULL; int rc; if (data == NULL || size < 2 * sizeof(char *)) goto error; rc = ril_radio_state_check(RADIO_STATE_SIM_NOT_READY); if (rc < 0) return RIL_REQUEST_UNHANDLED; request = ril_request_find_request_status(RIL_REQUEST_ENTER_SIM_PUK, RIL_REQUEST_HANDLED); if (request != NULL) return RIL_REQUEST_UNHANDLED; values = (char **) data; rc = ipc_sec_pin_status_setup(&request_data, IPC_SEC_PIN_TYPE_PIN1, values[1], values[0]); if (rc < 0) goto error; strings_array_free(values, size); values = NULL; rc = ipc_gen_phone_res_expect_callback(ipc_fmt_request_seq(token), IPC_SEC_PIN_STATUS, ipc_sec_callback); if (rc < 0) goto error; rc = ipc_fmt_send(ipc_fmt_request_seq(token), IPC_SEC_PIN_STATUS, IPC_TYPE_SET, (void *) &request_data, sizeof(request_data)); if (rc < 0) goto error; rc = RIL_REQUEST_HANDLED; goto complete; error: if (values != NULL) strings_array_free(values, size); ril_request_complete(token, RIL_E_GENERIC_FAILURE, NULL, 0); rc = RIL_REQUEST_COMPLETED; complete: return rc; } int ril_request_enter_sim_pin2(void *data, size_t size, RIL_Token token) { struct ipc_sec_pin_status_request_data request_data; struct ril_request *request; char **values = NULL; int rc; if (data == NULL || size < 2 * sizeof(char *)) goto error; rc = ril_radio_state_check(RADIO_STATE_SIM_NOT_READY); if (rc < 0) return RIL_REQUEST_UNHANDLED; request = ril_request_find_request_status(RIL_REQUEST_ENTER_SIM_PIN2, RIL_REQUEST_HANDLED); if (request != NULL) return RIL_REQUEST_UNHANDLED; values = (char **) data; rc = ipc_sec_pin_status_setup(&request_data, IPC_SEC_PIN_TYPE_PIN2, values[0], NULL); if (rc < 0) goto error; strings_array_free(values, size); values = NULL; rc = ipc_gen_phone_res_expect_callback(ipc_fmt_request_seq(token), IPC_SEC_PIN_STATUS, ipc_sec_callback); if (rc < 0) goto error; rc = ipc_fmt_send(ipc_fmt_request_seq(token), IPC_SEC_PIN_STATUS, IPC_TYPE_SET, (void *) &request_data, sizeof(request_data)); if (rc < 0) goto error; rc = RIL_REQUEST_HANDLED; goto complete; error: if (values != NULL) strings_array_free(values, size); ril_request_complete(token, RIL_E_GENERIC_FAILURE, NULL, 0); rc = RIL_REQUEST_COMPLETED; complete: return rc; } int ril_request_enter_sim_puk2(void *data, size_t size, RIL_Token token) { struct ipc_sec_pin_status_request_data request_data; struct ril_request *request; char **values = NULL; int rc; if (data == NULL || size < 2 * sizeof(char *)) goto error; rc = ril_radio_state_check(RADIO_STATE_SIM_NOT_READY); if (rc < 0) return RIL_REQUEST_UNHANDLED; request = ril_request_find_request_status(RIL_REQUEST_ENTER_SIM_PUK2, RIL_REQUEST_HANDLED); if (request != NULL) return RIL_REQUEST_UNHANDLED; values = (char **) data; rc = ipc_sec_pin_status_setup(&request_data, IPC_SEC_PIN_TYPE_PIN2, values[1], values[0]); if (rc < 0) goto error; strings_array_free(values, size); values = NULL; rc = ipc_gen_phone_res_expect_callback(ipc_fmt_request_seq(token), IPC_SEC_PIN_STATUS, ipc_sec_callback); if (rc < 0) goto error; rc = ipc_fmt_send(ipc_fmt_request_seq(token), IPC_SEC_PIN_STATUS, IPC_TYPE_SET, (void *) &request_data, sizeof(request_data)); if (rc < 0) goto error; rc = RIL_REQUEST_HANDLED; goto complete; error: if (values != NULL) strings_array_free(values, size); ril_request_complete(token, RIL_E_GENERIC_FAILURE, NULL, 0); rc = RIL_REQUEST_COMPLETED; complete: return rc; } int ril_request_change_sim_pin(void *data, size_t size, RIL_Token token) { struct ipc_sec_change_locking_pw_data request_data; struct ril_request *request; char **values = NULL; int rc; if (data == NULL || size < 3 * sizeof(char *)) goto error; request = ril_request_find_request_status(RIL_REQUEST_CHANGE_SIM_PIN, RIL_REQUEST_HANDLED); if (request != NULL) return RIL_REQUEST_UNHANDLED; rc = ril_radio_state_check(RADIO_STATE_SIM_READY); if (rc < 0) return RIL_REQUEST_UNHANDLED; values = (char **) data; rc = ipc_sec_change_locking_pw_setup(&request_data, IPC_SEC_FACILITY_TYPE_SC, values[0], values[1]); if (rc < 0) goto error; strings_array_free(values, size); values = NULL; rc = ipc_gen_phone_res_expect_callback(ipc_fmt_request_seq(token), IPC_SEC_CHANGE_LOCKING_PW, ipc_sec_callback); if (rc < 0) goto error; rc = ipc_fmt_send(ipc_fmt_request_seq(token), IPC_SEC_CHANGE_LOCKING_PW, IPC_TYPE_SET, (void *) &request_data, sizeof(request_data)); if (rc < 0) goto error; rc = RIL_REQUEST_HANDLED; goto complete; error: if (values != NULL) strings_array_free(values, size); ril_request_complete(token, RIL_E_GENERIC_FAILURE, NULL, 0); rc = RIL_REQUEST_COMPLETED; complete: return rc; } int ril_request_change_sim_pin2(void *data, size_t size, RIL_Token token) { struct ipc_sec_change_locking_pw_data request_data; struct ril_request *request; char **values = NULL; int rc; if (data == NULL || size < 3 * sizeof(char *)) goto error; request = ril_request_find_request_status(RIL_REQUEST_CHANGE_SIM_PIN, RIL_REQUEST_HANDLED); if (request != NULL) return RIL_REQUEST_UNHANDLED; rc = ril_radio_state_check(RADIO_STATE_SIM_READY); if (rc < 0) return RIL_REQUEST_UNHANDLED; values = (char **) data; rc = ipc_sec_change_locking_pw_setup(&request_data, IPC_SEC_FACILITY_TYPE_FD, values[0], values[1]); if (rc < 0) goto error; strings_array_free(values, size); values = NULL; rc = ipc_gen_phone_res_expect_callback(ipc_fmt_request_seq(token), IPC_SEC_CHANGE_LOCKING_PW, ipc_sec_callback); if (rc < 0) goto error; rc = ipc_fmt_send(ipc_fmt_request_seq(token), IPC_SEC_CHANGE_LOCKING_PW, IPC_TYPE_SET, (void *) &request_data, sizeof(request_data)); if (rc < 0) goto error; rc = RIL_REQUEST_HANDLED; goto complete; error: if (values != NULL) strings_array_free(values, size); ril_request_complete(token, RIL_E_GENERIC_FAILURE, NULL, 0); rc = RIL_REQUEST_COMPLETED; complete: return rc; } int ipc_sec_rsim_access(struct ipc_message *message) { struct ipc_sec_rsim_access_response_header *header; struct ipc_sec_rsim_access_usim_response_header *usim_header; struct sim_file_response sim_file_response; struct ril_request *request; struct ril_client *client; struct ipc_fmt_data *ipc_fmt_data; RIL_SIM_IO_Response response; #if RIL_VERSION >= 6 RIL_SIM_IO_v6 *sim_io; #else RIL_SIM_IO *sim_io; #endif unsigned char *p; unsigned int offset; unsigned int i; void *data; size_t size; if (message == NULL || message->data == NULL || message->size < sizeof(struct ipc_sec_rsim_access_response_header)) return -1; client = ril_client_find_id(RIL_CLIENT_IPC_FMT); if (client == NULL || client->data == NULL) return 0; if (message->type != IPC_TYPE_RESP || !ipc_seq_valid(message->aseq)) return 0; ipc_fmt_data = (struct ipc_fmt_data *) client->data; header = (struct ipc_sec_rsim_access_response_header *) message->data; size = ipc_sec_rsim_access_size_extract(message->data, message->size); data = ipc_sec_rsim_access_extract(message->data, message->size); request = ril_request_find_token(ipc_fmt_request_token(message->aseq)); #if RIL_VERSION >= 6 if (request == NULL || request->data == NULL || request->size < sizeof(RIL_SIM_IO_v6)) #else if (request == NULL || request->data == NULL || request->size < sizeof(RIL_SIM_IO)) #endif return 0; #if RIL_VERSION >= 6 sim_io = (RIL_SIM_IO_v6 *) request->data; #else sim_io = (RIL_SIM_IO *) request->data; #endif memset(&response, 0, sizeof(response)); response.sw1 = header->sw1; response.sw2 = header->sw2; switch (sim_io->command) { case SIM_COMMAND_READ_BINARY: case SIM_COMMAND_READ_RECORD: if (header->length == 0) break; response.simResponse = data2string(data, header->length); break; case SIM_COMMAND_GET_RESPONSE: if (header->length == 0) break; if (ipc_fmt_data->sim_icc_type_data.type == 0x01) { response.simResponse = data2string(data, header->length); break; } if (header->length < sizeof(struct ipc_sec_rsim_access_usim_response_header)) break; usim_header = (struct ipc_sec_rsim_access_usim_response_header *) data; memset(&sim_file_response, 0, sizeof(sim_file_response)); offset = sizeof(struct ipc_sec_rsim_access_usim_response_header) + usim_header->offset; if (offset > header->length) break; offset = usim_header->offset - 2; p = (unsigned char *) usim_header + offset; sim_file_response.file_id[0] = p[0]; sim_file_response.file_id[1] = p[1]; offset = header->length - 2; p = (unsigned char *) usim_header; while (offset > 2) { if (p[offset] == 0x88) { offset -= 2; break; } offset--; } if (offset <= 2) break; p = (unsigned char *) usim_header + offset; sim_file_response.file_size[0] = p[0]; sim_file_response.file_size[1] = p[1]; // Fallback to EF sim_file_response.file_type = SIM_FILE_TYPE_EF; for (i = 0; i < sim_file_ids_count; i++) { if (sim_io->fileid == sim_file_ids[i].file_id) { sim_file_response.file_type = sim_file_ids[i].type; break; } } sim_file_response.access_condition[0] = 0x00; sim_file_response.access_condition[1] = 0xff; sim_file_response.access_condition[2] = 0xff; sim_file_response.file_status = 0x01; sim_file_response.file_length = 0x02; switch (usim_header->file_structure) { case IPC_SEC_RSIM_FILE_STRUCTURE_TRANSPARENT: sim_file_response.file_structure = SIM_FILE_STRUCTURE_TRANSPARENT; break; case IPC_SEC_RSIM_FILE_STRUCTURE_LINEAR_FIXED: default: sim_file_response.file_structure = SIM_FILE_STRUCTURE_LINEAR_FIXED; break; } sim_file_response.record_length = usim_header->length; response.simResponse = data2string((void *) &sim_file_response, sizeof(sim_file_response)); break; case SIM_COMMAND_UPDATE_BINARY: case SIM_COMMAND_UPDATE_RECORD: case SIM_COMMAND_SEEK: default: response.simResponse = NULL; break; } ril_request_complete(ipc_fmt_request_token(message->aseq), RIL_E_SUCCESS, (void *) &response, sizeof(response)); if (response.simResponse != NULL) free(response.simResponse); return 0; } int ril_request_sim_io(void *data, size_t size, RIL_Token token) { struct ipc_sec_rsim_access_request_header request_header; struct ipc_sec_pin_status_request_data pin_request_data; struct ril_request *request; #if RIL_VERSION >= 6 RIL_SIM_IO_v6 *sim_io = NULL; #else RIL_SIM_IO *sim_io = NULL; #endif void *sim_io_data = NULL; size_t sim_io_size = 0; void *request_data = NULL; size_t request_size = 0; int pin_request = 0; int rc; #if RIL_VERSION >= 6 if (data == NULL || size < sizeof(RIL_SIM_IO_v6)) #else if (data == NULL || size < sizeof(RIL_SIM_IO)) #endif goto error; rc = ril_radio_state_check(RADIO_STATE_SIM_READY); if (rc < 0) return RIL_REQUEST_UNHANDLED; request = ril_request_find_request_status(RIL_REQUEST_SIM_IO, RIL_REQUEST_HANDLED); if (request != NULL) return RIL_REQUEST_UNHANDLED; #if RIL_VERSION >= 6 sim_io = (RIL_SIM_IO_v6 *) data; #else sim_io = (RIL_SIM_IO *) data; #endif if (sim_io->data != NULL) { sim_io_size = string2data_size(sim_io->data); if (sim_io_size == 0) goto error; sim_io_data = string2data(sim_io->data); if (sim_io_data == NULL) goto error; } if (sim_io->pin2 != NULL) { // PIN2 unlock first pin_request = 1; rc = ipc_sec_pin_status_setup(&pin_request_data, IPC_SEC_PIN_TYPE_PIN2, sim_io->pin2, NULL); if (rc < 0) goto error; } if (sim_io->path != NULL) free(sim_io->path); if (sim_io->data != NULL) free(sim_io->data); if (sim_io->pin2 != NULL) free(sim_io->pin2); #if RIL_VERSION >= 6 if (sim_io->aidPtr != NULL) free(sim_io->aidPtr); #endif memset(&request_header, 0, sizeof(request_header)); request_header.command = sim_io->command; request_header.file_id = sim_io->fileid; request_header.p1 = sim_io->p1; request_header.p2 = sim_io->p2; request_header.p3 = sim_io->p3; sim_io = NULL; request_size = ipc_sec_rsim_access_size_setup(&request_header, sim_io_data, sim_io_size); if (request_size == 0) goto error; request_data = ipc_sec_rsim_access_setup(&request_header, sim_io_data, sim_io_size); if (request_data == NULL) goto error; if (pin_request) { // PIN2 unlock first ril_request_data_set_uniq(RIL_REQUEST_SIM_IO, request_data, request_size); rc = ipc_gen_phone_res_expect_callback(ipc_fmt_request_seq(token), IPC_SEC_PIN_STATUS, ipc_sec_callback); if (rc < 0) { ril_request_data_free(RIL_REQUEST_SIM_IO); goto error; } rc = ipc_fmt_send(ipc_fmt_request_seq(token), IPC_SEC_PIN_STATUS, IPC_TYPE_SET, (void *) &pin_request_data, sizeof(pin_request_data)); if (rc < 0) { ril_request_data_free(RIL_REQUEST_SIM_IO); goto error; } rc = RIL_REQUEST_HANDLED; goto complete; } rc = ipc_fmt_send(ipc_fmt_request_seq(token), IPC_SEC_RSIM_ACCESS, IPC_TYPE_GET, request_data, request_size); if (rc < 0) goto error; rc = RIL_REQUEST_HANDLED; goto complete; error: if (sim_io != NULL) { if (sim_io->path != NULL) free(sim_io->path); if (sim_io->data != NULL) free(sim_io->data); if (sim_io->pin2 != NULL) free(sim_io->pin2); #if RIL_VERSION >= 6 if (sim_io->aidPtr != NULL) free(sim_io->aidPtr); #endif } ril_request_complete(token, RIL_E_GENERIC_FAILURE, NULL, 0); rc = RIL_REQUEST_COMPLETED; complete: if (sim_io_data != NULL && sim_io_size > 0) free(sim_io_data); if (request_data != NULL && request_size > 0) free(request_data); return rc; } int ipc_sec_sim_icc_type(struct ipc_message *message) { struct ipc_sec_sim_icc_type_data *data; struct ril_client *client; struct ipc_fmt_data *ipc_fmt_data; if (message == NULL || message->data == NULL || message->size < sizeof(struct ipc_sec_sim_icc_type_data)) return -1; client = ril_client_find_id(RIL_CLIENT_IPC_FMT); if (client == NULL || client->data == NULL) return 0; ipc_fmt_data = (struct ipc_fmt_data *) client->data; data = (struct ipc_sec_sim_icc_type_data *) message->data; if (ipc_fmt_data->sim_icc_type_data.type != data->type) ipc_fmt_data->sim_icc_type_data.type = data->type; return 0; } int ipc_sec_lock_infomation(struct ipc_message *message) { struct ipc_sec_lock_infomation_response_data *data; struct ipc_gen_phone_res_data *gen_phone_res; int requests[] = { RIL_REQUEST_ENTER_SIM_PIN, RIL_REQUEST_CHANGE_SIM_PIN, RIL_REQUEST_ENTER_SIM_PIN2, RIL_REQUEST_CHANGE_SIM_PIN2, RIL_REQUEST_SET_FACILITY_LOCK }; void *gen_phone_res_data = NULL; size_t gen_phone_res_size = 0; int retry_count; unsigned int count; unsigned int i; int rc; if (message == NULL || message->data == NULL || message->size < sizeof(struct ipc_sec_lock_infomation_response_data)) return -1; rc = ril_radio_state_check(RADIO_STATE_SIM_NOT_READY); if (rc < 0) return 0; if (message->type != IPC_TYPE_RESP || !ipc_seq_valid(message->aseq)) return 0; data = (struct ipc_sec_lock_infomation_response_data *) message->data; if (data->type != IPC_SEC_PIN_TYPE_PIN1 && data->type != IPC_SEC_PIN_TYPE_PIN2) return 0; count = sizeof(requests) / sizeof(int); for (i = 0; i < count; i++) { gen_phone_res_size = ril_request_data_size_get(requests[i]); if (gen_phone_res_size < sizeof(struct ipc_gen_phone_res_data)) continue; gen_phone_res_data = ril_request_data_get(requests[i]); if (gen_phone_res_data == NULL) continue; break; } if (gen_phone_res_data == NULL || gen_phone_res_size < sizeof(struct ipc_gen_phone_res_data)) return 0; gen_phone_res = (struct ipc_gen_phone_res_data *) gen_phone_res_data; retry_count = data->retry_count; rc = ipc_gen_phone_res_check(gen_phone_res); if (rc < 0) { if ((gen_phone_res->code & 0xff) == 0x10) { RIL_LOGE("%s: Wrong password and %d attempts left", __func__, retry_count); ril_request_complete(ipc_fmt_request_token(message->aseq), RIL_E_PASSWORD_INCORRECT, &retry_count, sizeof(retry_count)); } else if ((gen_phone_res->code & 0xff) == 0x0c) { RIL_LOGE("%s: Wrong password and no attempts left", __func__); retry_count = 0; ril_request_complete(ipc_fmt_request_token(message->aseq), RIL_E_PASSWORD_INCORRECT, &retry_count, sizeof(retry_count)); } else { ril_request_complete(ipc_fmt_request_token(message->aseq), RIL_E_GENERIC_FAILURE, &retry_count, sizeof(retry_count)); } } else { ril_request_complete(ipc_fmt_request_token(message->aseq), RIL_E_SUCCESS, &retry_count, sizeof(retry_count)); } free(gen_phone_res_data); return 0; }