Implement to request for SIM authentication
[platform/core/telephony/tel-plugin-imc.git] / src / s_sim.c
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)