Implement to request for SIM authentication
[platform/core/telephony/tel-plugin-imc.git] / src / s_sim.c
index 90d0366..efc1579 100644 (file)
@@ -905,7 +905,7 @@ static void _response_get_file_info(TcorePending *p, int data_len, const void *d
                        tmp = util_removeQuotes(hexData);
                        recordData = util_hexStringToBytes(tmp);
                        util_hex_dump("   ", strlen(hexData) / 2, recordData);
-                       free(tmp);
+                       g_free(tmp);
 
                        ptr_data = (unsigned char *)recordData;
                        if (tcore_sim_get_type(co_sim) == SIM_TYPE_USIM) {
@@ -998,7 +998,7 @@ static void _response_get_file_info(TcorePending *p, int data_len, const void *d
                                        } else {
                                                dbg("INVALID FCP received - DEbug!");
                                                tcore_at_tok_free(tokens);
-                                               free(recordData);
+                                               g_free(recordData);
                                                return;
                                        }
 
@@ -1021,7 +1021,7 @@ static void _response_get_file_info(TcorePending *p, int data_len, const void *d
                                        } else {
                                                dbg("INVALID FCP received - DEbug!");
                                                tcore_at_tok_free(tokens);
-                                               free(recordData);
+                                               g_free(recordData);
                                                return;
                                        }
 
@@ -1103,7 +1103,7 @@ static void _response_get_file_info(TcorePending *p, int data_len, const void *d
                                        } else {
                                                dbg("INVALID FCP received[0x%x] - DEbug!", *ptr_data);
                                                tcore_at_tok_free(tokens);
-                                               free(recordData);
+                                               g_free(recordData);
                                                return;
                                        }
 
@@ -1125,7 +1125,7 @@ static void _response_get_file_info(TcorePending *p, int data_len, const void *d
                                        } else {
                                                dbg("INVALID FCP received - DEbug!");
                                                tcore_at_tok_free(tokens);
-                                               free(recordData);
+                                               g_free(recordData);
                                                return;
                                        }
 
@@ -1151,7 +1151,7 @@ static void _response_get_file_info(TcorePending *p, int data_len, const void *d
                                } else {
                                        dbg("INVALID FCP received - DEbug!");
                                        tcore_at_tok_free(tokens);
-                                       free(recordData);
+                                       g_free(recordData);
                                        return;
                                }
                        } else if (tcore_sim_get_type(co_sim) == SIM_TYPE_GSM) {
@@ -1248,7 +1248,7 @@ static void _response_get_file_info(TcorePending *p, int data_len, const void *d
                        file_meta->rec_count = num_of_records;
                        file_meta->current_index = 0; // reset for new record type EF
                        rt = SIM_ACCESS_SUCCESS;
-                       free(recordData);
+                       g_free(recordData);
                } else {
                        /*2. SIM access fail case*/
                        dbg("error to get ef[0x%x]", file_meta->file_id);
@@ -1311,7 +1311,7 @@ static void _response_get_file_data(TcorePending *p, int data_len, const void *d
 
                tmp = util_removeQuotes(res);
                res = util_hexStringToBytes(tmp);
-               res_len = strlen((const char *)res);
+               res_len = strlen(tmp) / 2;
                dbg("Response: [%s] Response length: [%d]", res, res_len);
 
                if ((sw1 == 0x90 && sw2 == 0x00) || sw1 == 0x91) {
@@ -1985,7 +1985,6 @@ static TReturn _get_retry_count(CoreObject *o, UserRequest *ur)
        return TCORE_RETURN_SUCCESS;
 }
 
-
 static gboolean on_event_facility_lock_status(CoreObject *o, const void *event_info, void *user_data)
 {
        struct s_sim_property *sp = NULL;
@@ -2017,27 +2016,56 @@ OUT:
        return TRUE;
 }
 
+static void notify_sms_state(TcorePlugin *plugin, CoreObject *co_sim,
+                               gboolean sms_ready)
+{
+       Server *server = tcore_plugin_ref_server(plugin);
+       struct tnoti_sms_ready_status sms_ready_noti;
+       CoreObject *co_sms;
+
+       dbg("Entry");
+
+       co_sms = tcore_plugin_ref_core_object(plugin, CORE_OBJECT_TYPE_SMS);
+       if (co_sms == NULL) {
+               err("Can't find SMS core object");
+               return;
+       }
+
+       if (tcore_sms_get_ready_status(co_sms) == sms_ready)
+               return;
+
+       tcore_sms_set_ready_status(co_sms, sms_ready);
+
+       if (tcore_sim_get_status(co_sim) == SIM_STATUS_INIT_COMPLETED) {
+               sms_ready_noti.status = sms_ready;
+               tcore_server_send_notification(server, co_sms,
+                                               TNOTI_SMS_DEVICE_READY,
+                                               sizeof(sms_ready_noti),
+                                               &sms_ready_noti);
+       }
+
+       dbg("Exit");
+}
 
 static gboolean on_event_pin_status(CoreObject *o, const void *event_info, void *user_data)
 {
-       struct s_sim_property *sp = NULL;
+       TcorePlugin *plugin = tcore_object_ref_plugin(o);
        enum tel_sim_status sim_status = SIM_STATUS_INITIALIZING;
        GSList *tokens = NULL;
-       GSList *lines = NULL;
-       const char *line = NULL;
+       GSList *lines;
+       const char *line;
        int sim_state = 0;
        int sms_state = 0;
 
        dbg("Entry");
 
-       sp = tcore_sim_ref_userdata(o);
-
        lines = (GSList *)event_info;
        if (g_slist_length(lines) != 1) {
                err("Unsolicited message BUT multiple lines");
-               goto OUT;
+               goto out;
        }
-       line = (char *)(lines->data);
+
+       line = lines->data;
 
        /* Create 'tokens' */
        tokens = tcore_at_tok_new(line);
@@ -2046,180 +2074,113 @@ static gboolean on_event_pin_status(CoreObject *o, const void *event_info, void
        if (g_slist_length(tokens) == 4) {
                sim_state = atoi(g_slist_nth_data(tokens, 1));
                sms_state = atoi(g_slist_nth_data(tokens, 3));
-       } else if (g_slist_length(tokens) == 1)
+               notify_sms_state(plugin, o, (sms_state > 0));
+       } else if (g_slist_length(tokens) == 1) {
                sim_state = atoi(g_slist_nth_data(tokens, 0));
-       else {
+       else {
                err("Invalid message");
-
-               /* Free 'tokens' */
-               tcore_at_tok_free(tokens);
-               return TRUE;
+               goto out;
        }
 
        switch (sim_state) {
-       case 0:                                 /* SIM NOT PRESENT */
+       case 0:
                sim_status = SIM_STATUS_CARD_NOT_PRESENT;
                dbg("NO SIM");
-       break;
+               break;
 
-       case 1:                                 /* PIN VERIFICATION NEEDED */
+       case 1:
                sim_status = SIM_STATUS_PIN_REQUIRED;
                dbg("PIN REQUIRED");
-       break;
+               break;
 
-       case 2:                                 /* PIN VERIFICATION NOT NEEDED \96 READY */
+       case 2:
                sim_status = SIM_STATUS_INITIALIZING;
                dbg("PIN DISABLED AT BOOT UP");
-       break;
+               break;
 
-       case 3:                                 /* PIN VERIFIED \96 READY */
+       case 3:
                sim_status = SIM_STATUS_INITIALIZING;
                dbg("PIN VERIFIED");
-       break;
+               break;
 
-       case 4:                                 /* PUK VERIFICATION NEEDED */
+       case 4:
                sim_status = SIM_STATUS_PUK_REQUIRED;
-               dbg("PUK REQUIED");
-       break;
+               dbg("PUK REQUIRED");
+               break;
 
-       case 5:                                 /* SIM PERMANENTLY BLOCKED */
+       case 5:
                sim_status = SIM_STATUS_CARD_BLOCKED;
                dbg("CARD PERMANENTLY BLOCKED");
-       break;
+               break;
 
-       case 6:                                 /* SIM ERROR */
+       case 6:
                sim_status = SIM_STATUS_CARD_ERROR;
                dbg("SIM CARD ERROR");
                break;
 
-       case 7:                                 /* SIM READY FOR ATTACH (+COPS) */
+       case 7:
                sim_status = SIM_STATUS_INIT_COMPLETED;
                dbg("SIM INIT COMPLETED");
-       break;
+               break;
 
-       case 8:                                 /* SIM TECHNICAL PROBLEM */
+       case 8:
                sim_status = SIM_STATUS_CARD_ERROR;
                dbg("SIM CARD ERROR");
-       break;
+               break;
 
-       case 9:                                 /* SIM REMOVED */
+       case 9:
                sim_status = SIM_STATUS_CARD_REMOVED;
                dbg("SIM REMOVED");
-       break;
+               break;
 
-       case 99:                                /* SIM STATE UNKNOWN */
+       case 12:
+               dbg("SIM SMS Ready");
+               notify_sms_state(plugin, o, TRUE);
+               goto out;
+
+       case 99:
                sim_status = SIM_STATUS_UNKNOWN;
                dbg("SIM STATE UNKNOWN");
-       break;
-
-       case 12:                                /* SIM SMS CACHING COMPLETED */
-       {
-               struct tnoti_sms_ready_status sms_ready_noti = {0, };
-               CoreObject *sms;
-               TcorePlugin *plugin;
-
-               dbg("SIM State: [%d] - SMS Ready", sim_state);
-
-               sms_ready_noti.status = TRUE;
-               plugin = tcore_object_ref_plugin(o);
-               dbg("Plug-in name: [%s] SMS State: [%s]",
-                       tcore_plugin_ref_plugin_name(plugin),
-                       sms_ready_noti.status ? "TRUE" : "FALSE");
-
-               /* Set SMS State to Ready */
-               sms = tcore_plugin_ref_core_object(plugin, CORE_OBJECT_TYPE_SMS);
-               tcore_sms_set_ready_status(sms, sms_ready_noti.status);
-
-               /* Send notification - SMS Ready */
-               tcore_server_send_notification(tcore_plugin_ref_server(plugin), sms,
-                       TNOTI_SMS_DEVICE_READY, sizeof(sms_ready_noti), &sms_ready_noti);
-
-               goto OUT;
-       }
+               break;
 
        default:
                err("Unknown/Unsupported SIM state: [%d]", sim_state);
-       break;
+               goto out;
        }
 
        switch (sim_status) {
        case SIM_STATUS_INIT_COMPLETED:
                dbg("[SIM] SIM INIT COMPLETED");
                if (tcore_sim_get_type(o) == SIM_TYPE_UNKNOWN) {
-                       /* Get SIM Type */
                        _get_sim_type(o);
-
-                       goto OUT;
+                       goto out;
                }
-       break;
-
-       case SIM_STATUS_INITIALIZING:
-               dbg("[SIM] SIM CARD INITIALIZING");
-       break;
 
-       case SIM_STATUS_PIN_REQUIRED:
-               dbg("[SIM] PIN REQUIRED");
-       break;
-
-       case SIM_STATUS_PUK_REQUIRED:
-               dbg("[SIM] PUK REQUIRED");
-       break;
-
-       case SIM_STATUS_CARD_BLOCKED:
-               dbg("[SIM] SIM CARD BLOCKED");
-       break;
-
-       case SIM_STATUS_NCK_REQUIRED:
-               dbg("[SIM] NCK REQUIRED");
-       break;
-
-       case SIM_STATUS_NSCK_REQUIRED:
-               dbg("[SIM] NSCK REQUIRED");
-       break;
-
-       case SIM_STATUS_SPCK_REQUIRED:
-               dbg("[SIM] SPCK REQUIRED");
-       break;
-
-       case SIM_STATUS_CCK_REQUIRED:
-               dbg("[SIM] CCK REQUIRED");
-       break;
-
-       case SIM_STATUS_LOCK_REQUIRED:
-               dbg("[SIM] PHONE-SIM LOCK REQUIRED");
-       break;
+               break;
 
        case SIM_STATUS_CARD_REMOVED:
                dbg("[SIM] SIM CARD REMOVED");
-
-               /* Update SIM Type - UNKNOWN */
                tcore_sim_set_type(o, SIM_TYPE_UNKNOWN);
-       break;
+               break;
 
        case SIM_STATUS_CARD_NOT_PRESENT:
                dbg("[SIM] SIM CARD NOT PRESENT");
-
-               /* Update SIM Type - UNKNOWN */
                tcore_sim_set_type(o, SIM_TYPE_UNKNOWN);
-       break;
+               break;
 
        case SIM_STATUS_CARD_ERROR:
                dbg("[SIM] SIM CARD ERROR");
-
-               /* Update SIM Type - UNKNOWN */
                tcore_sim_set_type(o, SIM_TYPE_UNKNOWN);
-       break;
+               break;
 
        default:
-               err("Not handled SIM State: [0x%02x]", sim_status);
-               goto OUT;
+               dbg("SIM Status: [0x%02x]", sim_status);
+               break;
        }
 
-       /* Update SIM State */
        _sim_status_update(o, sim_status);
 
-OUT:
-       /* Free tokens */
+out:
        tcore_at_tok_free(tokens);
 
        dbg("Exit");
@@ -2838,8 +2799,8 @@ static void on_response_transmit_apdu(TcorePending *p, int data_len, const void
                        decoded_data = util_hexStringToBytes(tmp);
 
                        memcpy((char *)res.apdu_resp, decoded_data, res.apdu_resp_length);
-                       free(tmp);
-                       free(decoded_data);
+                       g_free(tmp);
+                       g_free(decoded_data);
                        res.result = SIM_ACCESS_SUCCESS;
                }
        } else {
@@ -2885,10 +2846,10 @@ static void on_response_get_atr(TcorePending *p, int data_len, const void *data,
                        tmp = util_removeQuotes(g_slist_nth_data(tokens, 0));
                        decoded_data = util_hexStringToBytes(tmp);
 
-                       res.atr_length = strlen(decoded_data);
+                       res.atr_length = strlen(tmp) / 2;
                        memcpy((char *)res.atr, decoded_data, res.atr_length);
-                       free(tmp);
-                       free(decoded_data);
+                       g_free(tmp);
+                       g_free(decoded_data);
                        res.result = SIM_ACCESS_SUCCESS;
                }
        } else {
@@ -2905,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;
@@ -3619,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,
@@ -3632,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)