Implement to request for SIM authentication 13/14513/2
authorwootak.jung <wootak.jung@samsung.com>
Tue, 10 Dec 2013 00:40:19 +0000 (09:40 +0900)
committeru <u@u-Samsung-DeskTop-System.(none)>
Tue, 7 Jan 2014 09:56:37 +0000 (18:56 +0900)
Change-Id: I9c29a9b71f473f92d123782366fe35075aea5ee1

include/s_common.h
src/s_common.c
src/s_sim.c

index 0250dec..5453f2c 100644 (file)
@@ -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);
 
index 430aa2f..f07f003 100644 (file)
@@ -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;
index 9c336eb..efc1579 100644 (file)
@@ -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)