From 175d273421a77309da6af75f63c596e416c41ca2 Mon Sep 17 00:00:00 2001 From: "wootak.jung" Date: Tue, 10 Dec 2013 09:40:19 +0900 Subject: [PATCH] Implement to request for SIM authentication Change-Id: I9c29a9b71f473f92d123782366fe35075aea5ee1 --- include/s_common.h | 1 + src/s_common.c | 18 ++++ src/s_sim.c | 299 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 317 insertions(+), 1 deletion(-) diff --git a/include/s_common.h b/include/s_common.h index 0250dec..5453f2c 100644 --- a/include/s_common.h +++ b/include/s_common.h @@ -25,6 +25,7 @@ void util_hex_dump(char *pad, int size, const void *data); unsigned char util_hexCharToInt(char c); +char *util_hex_to_string(const char *src, unsigned int src_len); char* util_hexStringToBytes(char *s); char* util_removeQuotes(void *data); diff --git a/src/s_common.c b/src/s_common.c index 430aa2f..f07f003 100644 --- a/src/s_common.c +++ b/src/s_common.c @@ -99,6 +99,24 @@ unsigned char util_hexCharToInt(char c) } } +char *util_hex_to_string(const char *src, unsigned int src_len) +{ + char *dest; + int i; + + if (src == NULL) + return NULL; + + dest = g_malloc0(src_len * 2 + 1); + for (i = 0; i < src_len; i++) { + sprintf(dest + (i * 2), "%02x", (unsigned char)src[i]); + } + + dest[src_len * 2] = '\0'; + + return dest; +} + char* util_hexStringToBytes(char *s) { char *ret; diff --git a/src/s_sim.c b/src/s_sim.c index 9c336eb..efc1579 100644 --- a/src/s_sim.c +++ b/src/s_sim.c @@ -2866,6 +2866,225 @@ OUT: dbg("Exit"); } +static void on_response_req_authentication(TcorePending *p, int data_len, + const void *data, void *user_data) +{ + const TcoreATResponse *at_resp = data; + GSList *tokens = NULL; + struct tresp_sim_req_authentication resp_auth; + const struct treq_sim_req_authentication *req_data; + UserRequest *ur = tcore_pending_ref_user_request(p); + + dbg("Entry"); + + memset(&resp_auth, 0, sizeof(struct tresp_sim_req_authentication)); + + if (at_resp == NULL) { + err("at_resp is NULL"); + resp_auth.result = SIM_ACCESS_FAILED; + resp_auth.auth_result = SIM_AUTH_CANNOT_PERFORM; + goto out; + } + + req_data = tcore_user_request_ref_data(ur, NULL); + if (req_data == NULL) { + err("req_data is NULL"); + resp_auth.result = SIM_ACCESS_FAILED; + resp_auth.auth_result = SIM_AUTH_CANNOT_PERFORM; + goto out; + } + resp_auth.auth_type = req_data->auth_type; + + if (at_resp->success == TRUE) { + const char *line; + int status; + + dbg("RESPONSE OK"); + if (at_resp->lines != NULL) { + line = at_resp->lines->data; + dbg("Received data: [%s]", line); + } else { + err("at_resp->lines is NULL"); + resp_auth.result = SIM_ACCESS_FAILED; + resp_auth.auth_result = SIM_AUTH_CANNOT_PERFORM; + goto out; + } + + tokens = tcore_at_tok_new(line); + if (tokens == NULL) { + err("tokens is NULL"); + resp_auth.result = SIM_ACCESS_FAILED; + resp_auth.auth_result = SIM_AUTH_CANNOT_PERFORM; + goto out; + } + + status = atoi(g_slist_nth_data(tokens, 0)); + switch (status) { + case 0: + dbg("Authentications successful"); + resp_auth.auth_result = SIM_AUTH_NO_ERROR; + break; + case 1: + err("Synchronize fail"); + resp_auth.auth_result = SIM_AUTH_SYNCH_FAILURE; + goto out; + case 2: + err("MAC wrong"); + resp_auth.auth_result = SIM_AUTH_MAK_CODE_FAILURE; + goto out; + case 3: + err("Does not support security context"); + resp_auth.auth_result = SIM_AUTH_UNSUPPORTED_CONTEXT; + goto out; + default: + err("Other failure"); + resp_auth.auth_result = SIM_AUTH_CANNOT_PERFORM; + goto out; + } + + if (resp_auth.auth_type == SIM_AUTH_TYPE_GSM) { + char *kc, *sres; + char *convert_kc, *convert_sres; + + kc = g_slist_nth_data(tokens, 1); + if (kc != NULL) { + kc = tcore_at_tok_extract(kc); + dbg("Kc: [%s]", kc); + convert_kc = util_hexStringToBytes(kc); + if (convert_kc && strlen(convert_kc) <= SIM_AUTH_RESP_DATA_LEN_MAX) { + resp_auth.authentication_key_length = strlen(convert_kc); + memcpy(&resp_auth.authentication_key, convert_kc, strlen(convert_kc)); + } else { + err("Invalid Kc"); + resp_auth.auth_result = SIM_AUTH_CANNOT_PERFORM; + } + g_free(kc); + g_free(convert_kc); + } else { + err("Invalid Kc"); + resp_auth.auth_result = SIM_AUTH_CANNOT_PERFORM; + goto out; + } + + sres = g_slist_nth_data(tokens, 2); + if (sres != NULL) { + sres = tcore_at_tok_extract(sres); + dbg("SRES: [%s]", sres); + convert_sres = util_hexStringToBytes(sres); + if (convert_sres && strlen(sres) <= SIM_AUTH_RESP_DATA_LEN_MAX) { + resp_auth.resp_length = strlen(convert_sres); + memcpy(&resp_auth.resp_data, convert_sres, strlen(convert_sres)); + } else { + err("Invalid SRES"); + resp_auth.auth_result = SIM_AUTH_CANNOT_PERFORM; + } + g_free(sres); + g_free(convert_sres); + } else { + err("Invalid SRES"); + resp_auth.auth_result = SIM_AUTH_CANNOT_PERFORM; + goto out; + } + } else if (resp_auth.auth_type == SIM_AUTH_TYPE_3G) { + char *res, *ck, *ik, *kc; + char *convert_res, *convert_ck; + char *convert_ik, *convert_kc; + + res = g_slist_nth_data(tokens, 1); + if (res != NULL) { + res = tcore_at_tok_extract(res); + dbg("RES/AUTS: [%s]", res); + convert_res = util_hexStringToBytes(res); + if (convert_ck && strlen(res) <= SIM_AUTH_RESP_DATA_LEN_MAX) { + resp_auth.resp_length = strlen(convert_res); + memcpy(resp_auth.resp_data, convert_res, strlen(convert_res)); + } else { + err("Invalid RES/AUTS"); + resp_auth.auth_result = SIM_AUTH_CANNOT_PERFORM; + } + g_free(res); + g_free(convert_res); + } else { + err("Invalid RES/AUTS"); + resp_auth.auth_result = SIM_AUTH_CANNOT_PERFORM; + goto out; + } + + ck = g_slist_nth_data(tokens, 2); + if (ck != NULL) { + ck = tcore_at_tok_extract(ck); + dbg("CK: [%s]", ck); + convert_ck = util_hexStringToBytes(ck); + if (convert_ck && strlen(ck) <= SIM_AUTH_RESP_DATA_LEN_MAX) { + resp_auth.cipher_length = strlen(convert_ck); + memcpy(&resp_auth.cipher_data, convert_ck, strlen(convert_ck)); + } else { + err("Invalid CK"); + resp_auth.auth_result = SIM_AUTH_CANNOT_PERFORM; + } + g_free(ck); + g_free(convert_ck); + } else { + err("Invalid CK"); + resp_auth.auth_result = SIM_AUTH_CANNOT_PERFORM; + goto out; + } + + ik = g_slist_nth_data(tokens, 3); + if (ik != NULL) { + ik = tcore_at_tok_extract(ik); + dbg("IK: [%s]", ik); + convert_ik = util_hexStringToBytes(ik); + if (convert_ik && strlen(ik) <= SIM_AUTH_RESP_DATA_LEN_MAX) { + resp_auth.integrity_length = strlen(convert_ik); + memcpy(&resp_auth.integrity_data, convert_ik, strlen(convert_ik)); + } else { + err("Invalid IK"); + resp_auth.auth_result = SIM_AUTH_CANNOT_PERFORM; + } + g_free(ik); + g_free(convert_ik); + } else { + err("Invalid IK"); + resp_auth.auth_result = SIM_AUTH_CANNOT_PERFORM; + goto out; + } + + kc = g_slist_nth_data(tokens, 4); + if (kc != NULL) { + kc = tcore_at_tok_extract(kc); + dbg("Kc: [%s]", kc); + convert_kc = util_hexStringToBytes(kc); + if (convert_kc && strlen(convert_kc) <= SIM_AUTH_RESP_DATA_LEN_MAX) { + resp_auth.authentication_key_length = strlen(convert_kc); + memcpy(&resp_auth.authentication_key, convert_kc, strlen(convert_kc)); + } else { + err("Invalid Kc"); + resp_auth.auth_result = SIM_AUTH_CANNOT_PERFORM; + } + g_free(kc); + g_free(convert_kc); + } else { + err("Invalid Kc"); + resp_auth.auth_result = SIM_AUTH_CANNOT_PERFORM; + goto out; + } + } else if (resp_auth.auth_type == SIM_AUTH_TYPE_IMS) { + err("Not supported"); + } + } else { + err("RESPONSE NOK"); + resp_auth.result = SIM_ACCESS_FAILED; + resp_auth.auth_result = SIM_AUTH_CANNOT_PERFORM; + } + +out: + tcore_user_request_send_response(ur, TRESP_SIM_REQ_AUTHENTICATION, + sizeof(struct tresp_sim_req_authentication), &resp_auth); + + tcore_at_tok_free(tokens); +} + static TReturn s_verify_pins(CoreObject *o, UserRequest *ur) { TcoreHal *hal = NULL; @@ -3580,6 +3799,84 @@ static TReturn s_get_atr(CoreObject *o, UserRequest *ur) NULL, NULL); } +static TReturn s_req_authentication(CoreObject *co, UserRequest *ur) +{ + const struct treq_sim_req_authentication *req_data; + char *cmd_str = NULL; + enum tel_sim_type sim_type; + int session_id; + int context_type; + TReturn ret = TCORE_RETURN_FAILURE; + char *convert_rand = NULL; + char *convert_autn = NULL; + + dbg("Entry"); + + req_data = tcore_user_request_ref_data(ur, NULL); + if (req_data == NULL) { + err("req_data is NULL"); + return ret; + } + + if (req_data->rand_data != NULL) { + convert_rand = util_hex_to_string(req_data->rand_data, + req_data->rand_length); + dbg("Convert RAND hex to string: [%s]", convert_rand); + } else { + err("rand_data is NULL"); + return ret; + } + + sim_type = tcore_sim_get_type(co); + switch (sim_type) { + case SIM_TYPE_GSM: + case SIM_TYPE_USIM: + session_id = 0; + break; + default: + err("Not supported"); + ret = TCORE_RETURN_ENOSYS; + goto out; + } + + switch (req_data->auth_type) { + case SIM_AUTH_TYPE_GSM: + context_type = 2; + cmd_str = g_strdup_printf("AT+XAUTH=%d,%d,\"%s\"", session_id, + context_type, convert_rand); + break; + case SIM_AUTH_TYPE_3G: + context_type = 1; + if (req_data->autn_data != NULL) { + convert_autn = util_hex_to_string(req_data->autn_data, + req_data->autn_length); + dbg("Convert AUTN hex to string: [%s]", convert_autn); + } else { + err("autn_data is NULL"); + goto out; + } + cmd_str = g_strdup_printf("AT+XAUTH=%d,%d,\"%s\",\"%s\"", + session_id, context_type, + convert_rand, convert_autn); + break; + default: + err("Not supported"); + ret = TCORE_RETURN_ENOSYS; + goto out; + } + + ret = tcore_prepare_and_send_at_request(co, cmd_str, "+XAUTH", + TCORE_AT_SINGLELINE, ur, + on_response_req_authentication, NULL, NULL, NULL); + +out: + g_free(cmd_str); + g_free(convert_rand); + g_free(convert_autn); + + return ret; +} + /* SIM Operations */ static struct tcore_sim_operations sim_ops = { .verify_pins = s_verify_pins, @@ -3593,7 +3890,7 @@ static struct tcore_sim_operations sim_ops = { .update_file = s_update_file, .transmit_apdu = s_transmit_apdu, .get_atr = s_get_atr, - .req_authentication = NULL, + .req_authentication = s_req_authentication, }; gboolean s_sim_init(TcorePlugin *cp, CoreObject *co_sim) -- 2.7.4