Home | History | Annotate | Download | only in eap_peer
      1 /*--------------------------------------------------------------------------
      2 Copyright (c) 2013, The Linux Foundation. All rights reserved.
      3 
      4 Redistribution and use in source and binary forms, with or without
      5 modification, are permitted provided that the following conditions are
      6 met:
      7     * Redistributions of source code must retain the above copyright
      8       notice, this list of conditions and the following disclaimer.
      9     * Redistributions in binary form must reproduce the above
     10       copyright notice, this list of conditions and the following
     11       disclaimer in the documentation and/or other materials provided
     12       with the distribution.
     13     * Neither the name of The Linux Foundation nor the names of its
     14       contributors may be used to endorse or promote products derived
     15       from this software without specific prior written permission.
     16 
     17 THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
     18 WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
     19 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
     20 ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
     21 BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     22 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     23 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
     24 BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     25 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
     26 OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
     27 IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     28 --------------------------------------------------------------------------*/
     29 
     30 #include "includes.h"
     31 #include "common.h"
     32 
     33 #ifdef CONFIG_EAP_PROXY
     34 #include "qmi_client.h"
     35 #include "eap_proxy_qmi.h"
     36 #include "qmi_client.h"
     37 #include "qmi_idl_lib.h"
     38 #include "authentication_service_v01.h"
     39 #include "user_identity_module_v01.h"
     40 #include "eap_config.h"
     41 #include "common/wpa_ctrl.h"
     42 #if defined(ANDROID)
     43 #include <cutils/properties.h>
     44 #ifdef CONFIG_EAP_PROXY_MDM_DETECT
     45 #include "mdm_detect.h"
     46 #endif /* CONFIG_EAP_PROXY_MDM_DETECT */
     47 #if defined(__BIONIC_FORTIFY)
     48 #include <sys/system_properties.h>
     49 #endif
     50 #endif
     51 #include <pthread.h>
     52 #include <sys/syscall.h>
     53 #include <sys/types.h>
     54 
     55 #define IMSI_LENGTH 15
     56 #define WPA_UIM_QMI_EVENT_MASK_CARD_STATUS        \
     57                                         (1 << QMI_UIM_EVENT_CARD_STATUS_BIT_V01)
     58 #define WPA_UIM_QMI_EVENT_READ_TRANSPARENT_REQ    \
     59                                         (1 << QMI_UIM_READ_TRANSPARENT_REQ_V01)
     60 
     61 /* Default timeout (in milli-seconds) for synchronous QMI message */
     62 #define WPA_UIM_QMI_DEFAULT_TIMEOUT               5000
     63 
     64 #define EAP_PROXY_PROPERTY_BASEBAND     "ro.baseband"
     65 #ifdef CONFIG_EAP_PROXY_MSM8994_TARGET
     66 #define EAP_PROXY_TARGET_PLATFORM       "ro.board.platform"
     67 #endif /* CONFIG_EAP_PROXY_MSM8994_TARGET */
     68 #if defined(__BIONIC_FORTIFY)
     69 #define EAP_PROXY_PROPERTY_BASEBAND_SIZE   PROP_VALUE_MAX
     70 #else
     71 #define EAP_PROXY_PROPERTY_BASEBAND_SIZE   10
     72 #endif
     73 #define EAP_PROXY_BASEBAND_VALUE_MSM       "msm"
     74 #define EAP_PROXY_BASEBAND_VALUE_APQ       "apq"
     75 #define EAP_PROXY_BASEBAND_VALUE_SVLTE1    "svlte1"
     76 #define EAP_PROXY_BASEBAND_VALUE_SVLTE2A   "svlte2a"
     77 #define EAP_PROXY_BASEBAND_VALUE_SGLTE     "sglte"
     78 #define EAP_PROXY_BASEBAND_VALUE_CSFB      "csfb"
     79 #define EAP_PROXY_BASEBAND_VALUE_MDMUSB    "mdm"
     80 #ifdef CONFIG_EAP_PROXY_MSM8994_TARGET
     81 #define EAP_PROXY_TARGET_PLATFORM_MSM8994  "msm8994"
     82 #endif /* CONFIG_EAP_PROXY_MSM8994_TARGET */
     83 #define EAP_PROXY_TARGET_FUSION4_5_PCIE    "fusion4_5_pcie"
     84 #define EAP_PROXY_BASEBAND_VALUE_UNDEFINED "undefined"
     85 
     86 #ifndef ANDROID
     87 #ifdef SYS_gettid
     88 static inline pid_t gettid(void)
     89 {
     90         return syscall(SYS_gettid);
     91 }
     92 #else
     93 static inline pid_t gettid(void)
     94 {
     95         return -1;
     96 }
     97 #endif
     98 #endif
     99 
    100 static Boolean wpa_qmi_ssr = FALSE;
    101 static void eap_proxy_qmi_deinit(struct eap_proxy_sm *eap_proxy);
    102 static void eap_proxy_eapol_sm_set_bool(struct eap_proxy_sm *sm,
    103                          enum eapol_bool_var var, Boolean value);
    104 struct eap_proxy_sm *
    105 eap_proxy_init(void *eapol_ctx, const struct eapol_callbacks *eapol_cb,
    106 	       void *msg_ctx);
    107 static Boolean eap_proxy_eapol_sm_get_bool(struct eap_proxy_sm *sm,
    108                                         enum eapol_bool_var var);
    109 
    110 /* Call-back function to process an authenticationr result indication from
    111  * QMI EAP service */
    112 static void handle_qmi_eap_ind(qmi_client_type user_handle,
    113                 unsigned int msg_id,
    114                 void* ind_buf,
    115                 unsigned int ind_buf_len,
    116                 void* ind_cb_data);
    117 
    118 static u8 *eap_proxy_getKey(struct eap_proxy_sm *eap_proxy);
    119 static enum eap_proxy_status eap_proxy_qmi_response_wait(struct eap_proxy_sm *eap_proxy);
    120 static int eap_proxy_is_state_changed(struct eap_proxy_sm *sm);
    121 static enum eap_proxy_status eap_proxy_process(struct eap_proxy_sm  *eap_proxy,
    122                                         u8 *eapReqData, int eapReqDataLen, struct eap_sm *eap_sm);
    123 static char bin_to_hexchar(u8 ch);
    124 
    125 static void wpa_qmi_client_indication_cb
    126 (
    127         qmi_client_type                user_handle,
    128         unsigned long                  msg_id,
    129         unsigned char                 *ind_buf_ptr,
    130         int                            ind_buf_len,
    131         void                          *ind_cb_data
    132 );
    133 static void dump_buff(u8 *buff, int len);
    134 #ifdef CONFIG_CTRL_IFACE
    135 static const char *eap_proxy_sm_state_txt(int state);
    136 #endif /* CONFIG_CTRL_IFACE */
    137 static Boolean eap_proxy_build_identity(struct eap_proxy_sm *eap_proxy, u8 id,
    138                                                  struct eap_sm *eap_sm);
    139 
    140 #ifdef SIM_AKA_IDENTITY_IMSI
    141 static char *imsi;
    142 static int imsi_len_g = 0;
    143 static int card_mnc_len = -1;
    144 #ifdef CONFIG_EAP_PROXY_DUAL_SIM
    145 static unsigned int slot = 0;
    146 static unsigned int session_type;
    147 #endif /* CONFIG_EAP_PROXY_DUAL_SIM */
    148 
    149 static Boolean wpa_qmi_register_events(int sim_num, wpa_uim_struct_type *wpa_uim);
    150 static Boolean wpa_qmi_read_card_imsi(int sim_num, wpa_uim_struct_type *wpa_uim);
    151 static Boolean wpa_qmi_read_card_status(int sim_num, wpa_uim_struct_type *wpa_uim);
    152 static Boolean wpa_qmi_register_auth_inds(struct eap_proxy_sm *eap_proxy);
    153 
    154 #endif
    155 #define EAP_SUB_TYPE_SIM_START     0x0a
    156 #define EAP_SUB_TYPE_AKA_IDENTITY  0x05
    157 #define EAP_RESP_TYPE_NAK             3
    158 
    159 
    160 #ifdef SIM_AKA_IDENTITY_IMSI
    161 static void wpa_qmi_client_indication_cb
    162 (
    163         qmi_client_type                user_handle,
    164         unsigned long                  msg_id,
    165         unsigned char                 *ind_buf_ptr,
    166         int                            ind_buf_len,
    167         void                          *ind_cb_data
    168 )
    169 {
    170 	u32 decoded_payload_len = 0;
    171 	qmi_client_error_type qmi_err = QMI_NO_ERR;
    172 	void * decoded_payload = NULL;
    173 	struct eap_proxy_sm *eap_proxy = ind_cb_data;
    174 	uim_status_change_ind_msg_v01* status_change_ind_ptr = NULL;
    175 	struct wpa_supplicant *wpa_s = NULL;
    176 	u32 i, card_info_len = 0;
    177 
    178 	wpa_printf(MSG_DEBUG, "eap_proxy: %s: msg_id=0x%lx", __func__, msg_id);
    179 
    180 	if (user_handle == NULL) {
    181 		wpa_printf(MSG_ERROR, "eap_proxy: qmi_client_type missing in callback");
    182 		return;
    183 	}
    184 
    185 	if (eap_proxy == NULL) {
    186 		wpa_printf(MSG_ERROR, "eap_proxy: not initialized, discard client indiataion");
    187 		return;
    188 	}
    189 
    190 	if (ind_buf_ptr == NULL) {
    191 		wpa_printf(MSG_ERROR, "eap_proxy: indication buffer NULL, discard client indiataion");
    192 		return;
    193 	}
    194 
    195 	qmi_idl_get_message_c_struct_len(uim_get_service_object_v01(),
    196 					 QMI_IDL_INDICATION, msg_id,
    197 					 &decoded_payload_len);
    198 
    199 	if(!decoded_payload_len) {
    200 		wpa_printf(MSG_ERROR, "eap_proxy: cann't decode payload, discard client indiataion");
    201 		return;
    202 	}
    203 
    204 	decoded_payload = os_zalloc(decoded_payload_len);
    205 	if (decoded_payload == NULL) {
    206 		wpa_printf(MSG_ERROR, "eap_proxy: failed to allocate memory");
    207 		return;
    208 	}
    209 
    210 	qmi_err = qmi_client_message_decode(user_handle,
    211 					    QMI_IDL_INDICATION, msg_id,
    212 					    ind_buf_ptr, ind_buf_len,
    213 					    decoded_payload, decoded_payload_len);
    214 
    215 	if (qmi_err == QMI_NO_ERR) {
    216 		switch (msg_id) {
    217 		case QMI_UIM_STATUS_CHANGE_IND_V01:
    218 			status_change_ind_ptr = (uim_status_change_ind_msg_v01*)decoded_payload;
    219 			if (!status_change_ind_ptr->card_status_valid)
    220 				goto fail;
    221 
    222 			card_info_len = status_change_ind_ptr->card_status.card_info_len;
    223 			for (i = 0; i < card_info_len; i++) {
    224 				if(UIM_CARD_STATE_PRESENT_V01 !=
    225 				    status_change_ind_ptr->card_status.card_info[i].card_state) {
    226 					wpa_printf(MSG_DEBUG, "eap_proxy: %s SIM card removed. flush pmksa entries.", __func__);
    227 					eap_proxy->eapol_cb->eap_proxy_notify_sim_status(eap_proxy->ctx, SIM_STATE_ERROR);
    228 					break; /* only one flush will do */
    229 				}
    230 			}
    231 			break;
    232 		default:
    233 			wpa_printf(MSG_DEBUG, "eap_proxy: Unknown QMI Indicaiton %lu", msg_id);
    234 			break;
    235 		}
    236 	}
    237 fail:
    238 	os_free(decoded_payload);
    239 	return;
    240 }
    241 
    242 static Boolean wpa_qmi_register_auth_inds(struct eap_proxy_sm *eap_proxy)
    243 {
    244         qmi_client_error_type               qmi_err_code      = 0;
    245         auth_indication_register_resp_msg_v01  event_resp_msg;
    246         auth_indication_register_req_msg_v01 event_reg_params;
    247 
    248         /* Register for events first */
    249         os_memset(&event_reg_params, 0, sizeof(auth_indication_register_req_msg_v01));
    250         os_memset(&event_resp_msg, 0, sizeof(auth_indication_register_resp_msg_v01));
    251 
    252         event_reg_params.report_eap_notification_code_valid = TRUE;
    253         event_reg_params.report_eap_notification_code = 1;
    254 
    255         wpa_printf(MSG_DEBUG, "registering for notification codes\n");
    256         qmi_err_code = qmi_client_send_msg_sync(
    257                         eap_proxy->qmi_auth_svc_client_ptr[eap_proxy->user_selected_sim],
    258                         QMI_AUTH_INDICATION_REGISTER_REQ_V01,
    259                         (void *) &event_reg_params,
    260                         sizeof(auth_indication_register_req_msg_v01),
    261                         (void*) &event_resp_msg,
    262                         sizeof(auth_indication_register_resp_msg_v01),
    263                         WPA_UIM_QMI_DEFAULT_TIMEOUT);
    264 
    265         if (qmi_err_code != QMI_NO_ERR ||
    266             (event_resp_msg.resp.result != QMI_RESULT_SUCCESS_V01 &&
    267              event_resp_msg.resp.error != QMI_ERR_NO_EFFECT_V01)) {
    268                 wpa_printf(MSG_ERROR,"QMI-ERROR Error for "
    269                            "QMI_AUTH_INDICATION_REGISTER_REQ_V01, qmi_err_code=%d"
    270                            "Error=%d\n", qmi_err_code,
    271                             event_resp_msg.resp.error);
    272                 return FALSE;
    273         }
    274 
    275         return TRUE;
    276 
    277 }
    278 
    279 static Boolean wpa_qmi_register_events(int sim_num, wpa_uim_struct_type *wpa_uim)
    280 {
    281         qmi_client_error_type               qmi_err_code      = 0;
    282         uim_event_reg_resp_msg_v01          event_resp_msg;
    283         uim_event_reg_req_msg_v01           event_reg_params;
    284 
    285         /* Register for events first */
    286         os_memset(&event_reg_params, 0, sizeof(uim_event_reg_req_msg_v01));
    287         os_memset(&event_resp_msg, 0, sizeof(uim_event_reg_resp_msg_v01));
    288 
    289         event_reg_params.event_mask |= (WPA_UIM_QMI_EVENT_MASK_CARD_STATUS);
    290         qmi_err_code = qmi_client_send_msg_sync(wpa_uim[sim_num].qmi_uim_svc_client_ptr,
    291                                                 QMI_UIM_EVENT_REG_REQ_V01,
    292                                                 (void *) &event_reg_params,
    293                                                 sizeof(uim_event_reg_req_msg_v01),
    294                                                 (void *) &event_resp_msg,
    295                                                 sizeof(uim_event_reg_resp_msg_v01),
    296                                                 WPA_UIM_QMI_DEFAULT_TIMEOUT);
    297 
    298         wpa_printf(MSG_ERROR, "eap_proxy: QMI_UIM_EVENT_REG_REQ_V01, "
    299                    "qmi_err_code: 0x%x wpa_uim[%d].qmi_uim_svc_client_ptr =%p"
    300                    "Error=0x%x", qmi_err_code, sim_num,
    301                     wpa_uim[sim_num].qmi_uim_svc_client_ptr,
    302                     event_resp_msg.resp.error);
    303 
    304         if (qmi_err_code != QMI_NO_ERR ||
    305             (event_resp_msg.resp.result != QMI_RESULT_SUCCESS_V01 &&
    306              event_resp_msg.resp.error != QMI_ERR_NO_EFFECT_V01)) {
    307                 wpa_printf(MSG_ERROR,"QMI-ERROR Error for "
    308                            "QMI_UIM_EVENT_REG_REQ_V01, qmi_err_code=%d"
    309                            "Error=%d\n", qmi_err_code,
    310                             event_resp_msg.resp.error);
    311                 return FALSE;
    312         }
    313 
    314         if(event_resp_msg.event_mask_valid)
    315         {
    316                 wpa_printf(MSG_ERROR, "eap_proxy: event_resp_msg.event=%d,\n",
    317                            event_resp_msg.event_mask);
    318 
    319         }
    320 
    321         if (wpa_qmi_read_card_status(sim_num, wpa_uim))
    322                 return TRUE;
    323         else {
    324                 wpa_printf(MSG_ERROR,"eap_proxy: Error while reading SIM card status\n");
    325                 return FALSE;
    326         }
    327 }
    328 
    329 static Boolean wpa_qmi_read_card_status(int sim_num, wpa_uim_struct_type *wpa_uim)
    330 {
    331         unsigned int                        i = 0, j = 0;
    332         Boolean                             card_found = FALSE;
    333         qmi_client_error_type               qmi_err_code      = 0;
    334         uim_get_card_status_resp_msg_v01   card_status_resp_msg;
    335 
    336         wpa_printf (MSG_ERROR, "eap_proxy: reading card %d values\n", sim_num+1);
    337         os_memset(&card_status_resp_msg,
    338                   0,
    339                   sizeof(uim_get_card_status_resp_msg_v01));
    340         qmi_err_code = qmi_client_send_msg_sync(wpa_uim[sim_num].qmi_uim_svc_client_ptr,
    341                                                 QMI_UIM_GET_CARD_STATUS_REQ_V01,
    342                                                 NULL,
    343                                                 0,
    344                                                 (void *)&card_status_resp_msg,
    345                                                 sizeof(uim_get_card_status_resp_msg_v01),
    346                                                 WPA_UIM_QMI_DEFAULT_TIMEOUT);
    347 
    348         if (qmi_err_code != QMI_NO_ERR ||
    349             card_status_resp_msg.resp.result != QMI_RESULT_SUCCESS_V01) {
    350                 wpa_printf(MSG_ERROR, "QMI-ERROR Error for "
    351                            "QMI_UIM_GET_CARD_STATUS_REQ_V01, qmi_err_code: 0x%x\n "
    352                            "resp_err = %d \n", qmi_err_code, card_status_resp_msg.resp.error);
    353                 return FALSE;
    354         }
    355 
    356         /* Updated global card status if needed */
    357         if (!card_status_resp_msg.card_status_valid ||
    358             (card_status_resp_msg.resp.result != QMI_RESULT_SUCCESS_V01)) {
    359                 wpa_printf(MSG_ERROR, "eap_proxy: card_status is not valid !\n");
    360                 return FALSE;
    361         }
    362         /* Update global in case of new card state or error code */
    363         i = sim_num;
    364         if ( i < QMI_UIM_CARDS_MAX_V01 &&
    365              i < card_status_resp_msg.card_status.card_info_len ) {
    366                 wpa_printf(MSG_ERROR, "eap_proxy: card_info[i].card_state: 0x%x\n",
    367                         card_status_resp_msg.card_status.card_info[i].card_state);
    368                 wpa_printf(MSG_ERROR, "eap_proxy: card_info[i].error_code: 0x%x\n",
    369                         card_status_resp_msg.card_status.card_info[i].error_code);
    370 
    371                 wpa_uim[sim_num].card_info[i].card_state =
    372                         card_status_resp_msg.card_status.card_info[i].card_state;
    373 
    374                 wpa_uim[sim_num].card_info[i].card_error_code =
    375                         card_status_resp_msg.card_status.card_info[i].error_code;
    376 #ifdef CONFIG_EAP_PROXY_DUAL_SIM
    377             do {
    378                    if (card_status_resp_msg.card_status.index_gw_pri != 0xFFFF) {
    379                         slot = (card_status_resp_msg.card_status.index_gw_pri & 0xFF00) >> 8;
    380                         if (slot == i) {
    381                             session_type = UIM_SESSION_TYPE_PRIMARY_GW_V01;
    382                             wpa_printf (MSG_ERROR, "eap_proxy: read_card_status:"
    383                                         " prime slot = %d\n", slot);
    384                             break;
    385                         }
    386                    }
    387                    if (card_status_resp_msg.card_status.index_gw_sec != 0xFFFF) {
    388                         slot = (card_status_resp_msg.card_status.index_gw_sec & 0xFF00) >> 8;
    389                         if (slot == i) {
    390                             session_type = UIM_SESSION_TYPE_SECONDARY_GW_V01;
    391                             wpa_printf (MSG_ERROR, "eap_proxy: read_card_status: "
    392                                         "second slot = %d\n", slot);
    393                             break;
    394                         }
    395                    }
    396                    wpa_printf (MSG_ERROR, "eap_proxy: read_card_status: Not GW it's 1x\n");
    397                    return FALSE;
    398                 }while(0);
    399 
    400                 if (slot > 1){
    401                             wpa_printf (MSG_ERROR, "eap_proxy: read_card_status: "
    402                                         "INVALID slot = %d and i = %d\n", slot, i);
    403                         return FALSE;
    404                 }
    405 #endif /* CONFIG_EAP_PROXY_DUAL_SIM */
    406 
    407                 if (card_status_resp_msg.card_status.card_info[i].card_state ==
    408                     UIM_CARD_STATE_PRESENT_V01) {
    409                         for (j = 0 ; j < QMI_UIM_APPS_MAX_V01 ; j++) {
    410                                 wpa_uim[sim_num].card_info[i].app_type = card_status_resp_msg.
    411                                         card_status.card_info[i].app_info[j].app_type;
    412 
    413                                 wpa_uim[sim_num].card_info[i].app_state = card_status_resp_msg.
    414                                         card_status.card_info[i].app_info[j].app_state;
    415 
    416                                 if (((card_status_resp_msg.card_status.card_info[i].
    417                                      app_info[j].app_type == 1) || (card_status_resp_msg.
    418                                      card_status.card_info[i].app_info[j].app_type == 2)) &&
    419                                     (card_status_resp_msg.card_status.card_info[i].app_info[j].
    420                                      app_state == UIM_APP_STATE_READY_V01)) {
    421                                         wpa_printf(MSG_ERROR, "eap_proxy: card READY\n");
    422                                         wpa_printf(MSG_ERROR, "eap_proxy: card_info[i].app_ty"
    423                                                 "pe: 0x%x\n", card_status_resp_msg.card_status.
    424                                                 card_info[i].app_info[j].app_type);
    425                                         wpa_printf(MSG_ERROR, "eap_proxy: card_info[i].app_sta"
    426                                                 "te : 0x%x\n", card_status_resp_msg.card_status
    427                                                 .card_info[i].app_info[j].app_state);
    428                                         card_found = TRUE;
    429                                         break;
    430                                 }
    431                         }
    432                 }
    433 
    434                 if (card_found) {
    435                         wpa_printf(MSG_ERROR, "eap_proxy: card found for SIM = %d\n", sim_num+1);
    436                 }
    437         }
    438 
    439         if ((!card_found) || (i == QMI_UIM_CARDS_MAX_V01) ||
    440                 (j == QMI_UIM_APPS_MAX_V01)) {
    441                 wpa_printf(MSG_ERROR, "eap_proxy: SIM/USIM not ready card_found=%d\n",card_found);
    442                 return FALSE;
    443         }
    444 
    445         wpa_printf(MSG_ERROR, "eap_proxy: SIM/USIM ready\n");
    446         wpa_uim[sim_num].card_ready_idx = i;
    447 
    448         return TRUE;
    449 } /* wpa_qmi_read_card_status */
    450 
    451 static int check_for_3_digit()
    452 {
    453         int mcc = 0,i =0;
    454         /*
    455         -- 3 digits if MCC belongs to this group: 302, 310, 311, 312, 313, 314, 315,
    456         316, 334, 348 (decimal)
    457         -- 2 digits in all other cases
    458         Note: imsi values are hex characters
    459         */
    460         int valid_mcc[] = {302, 310, 311, 312, 313, 314, 315, 316, 334, 348};
    461 
    462         mcc = ((imsi[0]-0x30)*100) + ((imsi[1]-0x30)*10) + (imsi[2]-0x30);
    463 
    464         wpa_printf(MSG_ERROR, "mcc from the SIM is %d\n", mcc);
    465         for(i = 0; i < sizeof(valid_mcc)/sizeof(valid_mcc[0]); i++)
    466         {
    467                 if(mcc == valid_mcc[i])
    468                         return 1;
    469         }
    470         return 0;
    471 }
    472 
    473 static Boolean wpa_qmi_read_card_imsi(int sim_num, wpa_uim_struct_type *wpa_uim)
    474 {
    475         int                     length;
    476         unsigned char           *data;
    477         int                     src = 0, dst = 0;
    478         Boolean                 card_found = FALSE,
    479         qmi_status = TRUE;
    480         qmi_client_error_type               qmi_err_code = 0;
    481         uim_read_transparent_req_msg_v01   qmi_read_trans_req;
    482         uim_read_transparent_resp_msg_v01  read_trans_resp;
    483         card_mnc_len = -1;
    484 
    485 
    486         os_memset(&read_trans_resp, 0,
    487                   sizeof(uim_read_transparent_resp_msg_v01));
    488         os_memset(&qmi_read_trans_req, 0,
    489                         sizeof(uim_read_transparent_req_msg_v01));
    490 
    491         qmi_read_trans_req.read_transparent.length = 0;
    492         qmi_read_trans_req.read_transparent.offset = 0;
    493         qmi_read_trans_req.file_id.file_id = 0x6F07;
    494         qmi_read_trans_req.file_id.path_len = 4;
    495 
    496 #ifdef CONFIG_EAP_PROXY_DUAL_SIM
    497         wpa_printf (MSG_ERROR, "eap_proxy: read_card_imsi: session_type = %d\n", session_type);
    498         qmi_read_trans_req.session_information.session_type = session_type;
    499 #else
    500         qmi_read_trans_req.session_information.session_type =
    501                                 UIM_SESSION_TYPE_PRIMARY_GW_V01;
    502 #endif /* CONFIG_EAP_PROXY_DUAL_SIM */
    503         qmi_read_trans_req.session_information.aid_len = 0;
    504 
    505         /* For USIM*/
    506         if ((wpa_uim[sim_num].card_info[wpa_uim[sim_num].card_ready_idx].app_type ==
    507                 UIM_APP_TYPE_USIM_V01)) {
    508                 qmi_read_trans_req.file_id.path[0] = 0x00;
    509                 qmi_read_trans_req.file_id.path[1] = 0x3F;
    510                 qmi_read_trans_req.file_id.path[2] = 0xFF;
    511                 qmi_read_trans_req.file_id.path[3] = 0x7F;
    512 
    513         } else /* For SIM*/
    514         if ((wpa_uim[sim_num].card_info[wpa_uim[sim_num].card_ready_idx].app_type ==
    515                 UIM_APP_TYPE_SIM_V01)) {
    516                 qmi_read_trans_req.file_id.path[0] = 0x00;
    517                 qmi_read_trans_req.file_id.path[1] = 0x3F;
    518                 qmi_read_trans_req.file_id.path[2] = 0x20;
    519                 qmi_read_trans_req.file_id.path[3] = 0x7F;
    520         }
    521         else {
    522                 return FALSE;
    523         }
    524 
    525         qmi_err_code = qmi_client_send_msg_sync(wpa_uim[sim_num].qmi_uim_svc_client_ptr,
    526                                         QMI_UIM_READ_TRANSPARENT_REQ_V01,
    527                                         (void *)&qmi_read_trans_req,
    528                                         sizeof(uim_read_transparent_req_msg_v01),
    529                                         (void *) &read_trans_resp,
    530                                         sizeof(uim_read_transparent_resp_msg_v01),
    531                                         WPA_UIM_QMI_DEFAULT_TIMEOUT);
    532         if (QMI_NO_ERR != qmi_err_code ||
    533             read_trans_resp.resp.result != QMI_RESULT_SUCCESS_V01) {
    534                 wpa_printf(MSG_ERROR, "QMI-ERROR Unable to read IMSI from UIM service;"
    535                            " error_ret=%d; qmi_err=%d\n", qmi_err_code,
    536                            read_trans_resp.resp.error);
    537                 qmi_status = FALSE;
    538         }
    539 
    540         if (QMI_NO_ERR == qmi_err_code) {
    541                 if (read_trans_resp.read_result_valid) {
    542                         length  =
    543                                 read_trans_resp.read_result.content_len;
    544                         data    =
    545                                 read_trans_resp.read_result.content;
    546                                 wpa_printf(MSG_ERROR,
    547                                         "eap_proxy: IMSI SIM content length = %d\n",
    548                                         length);
    549 
    550                         /* Received IMSI is in the 3GPP format
    551                                 converting it into ascii string */
    552                         imsi = os_zalloc(2 * length);
    553                         if (imsi == NULL) {
    554                                 wpa_printf(MSG_ERROR,
    555                                         "eap_proxy: Couldn't allocate memmory for imsi");
    556                                 return FALSE;
    557                         }
    558                         for (src = 1, dst = 0;
    559                                 (src < length) && (dst < (length * 2));
    560                                 src++) {
    561                                 wpa_printf(MSG_ERROR,
    562                                         "eap_proxy: IMSI read from SIM = %d src %d\n",
    563                                         data[src], src);
    564                                 if(data[src] == 0xFF) {
    565                                         break;
    566                                 }
    567                                 if (src > 1) {
    568                                         imsi[dst] = bin_to_hexchar(data[src] & 0x0F);
    569                                         dst++;
    570                                         wpa_printf(MSG_ERROR,
    571                                         "eap_proxy: IMSI dst = %d dst %d\n",
    572                                         imsi[dst-1], dst);
    573                                 }
    574                                 /* Process upper part of byte for all bytes */
    575                                 imsi[dst] = bin_to_hexchar(data[src] >> 4);
    576                                 dst++;
    577                                 wpa_printf(MSG_ERROR,
    578                                         "eap_proxy: IMSI dst = %d dst %d\n",
    579                                         imsi[dst-1], dst);
    580                         }
    581                                 imsi_len_g = (data[0]*2 - 1); //dst;
    582                                 wpa_printf(MSG_ERROR,
    583                                         "eap_proxy: IMSI first digit = %d read length = %d"
    584                                         "imsi %20s\n", data[0],imsi_len_g, imsi);
    585                         } else{
    586                                 wpa_printf(MSG_ERROR,
    587                                         "eap_proxy: IMSI read failure read_result_valid = %d\n",
    588                                         read_trans_resp.read_result_valid);
    589                                 qmi_status = FALSE;
    590                         }
    591                 }
    592         /* READ EF_AD */
    593         /* if qmi_status is FALSE, UIM read for mnc may not be required - To Do */
    594         qmi_read_trans_req.file_id.file_id = 0x6FAD;
    595         qmi_err_code = qmi_client_send_msg_sync(wpa_uim[sim_num].qmi_uim_svc_client_ptr,
    596                                         QMI_UIM_READ_TRANSPARENT_REQ_V01,
    597                                         (void *)&qmi_read_trans_req,
    598                                         sizeof(uim_read_transparent_req_msg_v01),
    599                                         (void *)&read_trans_resp,
    600                                         sizeof(uim_read_transparent_resp_msg_v01),
    601                                         WPA_UIM_QMI_DEFAULT_TIMEOUT);
    602         if (QMI_NO_ERR != qmi_err_code ||
    603            read_trans_resp.resp.result != QMI_RESULT_SUCCESS_V01) {
    604                 wpa_printf(MSG_ERROR, "QMI-ERROR Unable to read MNC from UIM service;"
    605                            " error_ret=%d; qmi_err=%d\n", qmi_err_code,
    606                            read_trans_resp.resp.error);
    607                 qmi_status = FALSE;
    608         }
    609         if (QMI_NO_ERR == qmi_err_code) {
    610                 if (read_trans_resp.read_result_valid) {
    611                         length  =
    612                                 read_trans_resp.read_result.content_len;
    613                         data    =
    614                                 read_trans_resp.read_result.content;
    615 
    616                         if(length >= 4)
    617                                 card_mnc_len = 0x0f & data[3];
    618                         if ((card_mnc_len != 2) && (card_mnc_len != 3)) {
    619                                 if(check_for_3_digit())
    620                                         card_mnc_len = 3;
    621                                 else
    622                                         card_mnc_len = 2;
    623                                 wpa_printf(MSG_ERROR, "Failed to get MNC length from (U)SIM "
    624                                 "assuming %d as mcc %s to 3 digit mnc group\n",
    625                                 card_mnc_len, card_mnc_len == 3? "belongs":"not belongs");
    626                         }
    627                 }
    628         }
    629 
    630 
    631         return qmi_status;
    632 } /* wpa_qmi_read_card_imsi */
    633 #endif /* SIM_AKA_IDENTITY_IMSI */
    634 
    635 #ifdef CONFIG_EAP_PROXY_MDM_DETECT
    636 static int eap_modem_compatible(struct dev_info *mdm_detect_info)
    637 {
    638         char args[EAP_PROXY_PROPERTY_BASEBAND_SIZE] = {0};
    639         int ret = 0;
    640 
    641         /* Get the hardware property */
    642         ret = property_get(EAP_PROXY_PROPERTY_BASEBAND, args, "");
    643         if (ret > EAP_PROXY_PROPERTY_BASEBAND_SIZE){
    644                 wpa_printf(MSG_ERROR,"eap_proxy: property [%s] has size [%d] that exceeds max [%d]",
    645                            EAP_PROXY_PROPERTY_BASEBAND,
    646                            ret,
    647                            EAP_PROXY_PROPERTY_BASEBAND_SIZE);
    648                 return FALSE;
    649         }
    650 
    651         /* This will check for the type of hardware, and if the hardware type
    652          * needs external modem, it will check if the modem type is external */
    653         if(!os_strncmp(EAP_PROXY_BASEBAND_VALUE_APQ, args, 3)) {
    654                 for (ret = 0; ret < mdm_detect_info->num_modems; ret++) {
    655                         if (mdm_detect_info->mdm_list[ret].type == MDM_TYPE_EXTERNAL) {
    656                                 wpa_printf(MSG_INFO, "eap_proxy: hardware supports external modem");
    657                                 return TRUE;
    658                         }
    659                 }
    660                 wpa_printf(MSG_ERROR, "eap_proxy: hardware does not support external modem");
    661                 return FALSE;
    662         }
    663         return TRUE;
    664 }
    665 #endif /* CONFIG_EAP_PROXY_MDM_DETECT */
    666 
    667 void wpa_qmi_register_notification(void *eloop_ctx, void *timeout_ctx)
    668 {
    669         struct eap_proxy_sm *eap_proxy = eloop_ctx;
    670         wpa_printf(MSG_DEBUG, "eap_proxy: %s", __func__);
    671 
    672         eap_proxy_qmi_deinit(eap_proxy);
    673         eap_proxy_init(eap_proxy, NULL, NULL);
    674 }
    675 
    676 void wpa_qmi_handle_ssr(qmi_client_type user_handle, qmi_client_error_type error, void *err_cb_data)
    677 {
    678         struct eap_proxy_sm *eap_proxy = err_cb_data;
    679 
    680         wpa_printf(MSG_DEBUG, "eap_proxy: %s ", __func__);
    681 
    682         wpa_qmi_ssr = TRUE;
    683         eloop_register_timeout(0, 0, wpa_qmi_register_notification, eap_proxy, NULL);
    684 }
    685 
    686 
    687 static void exit_proxy_init(int signum)
    688 {
    689        pthread_exit(NULL);
    690 }
    691 
    692 static void eap_proxy_post_init(struct eap_proxy_sm *eap_proxy)
    693 {
    694         int qmiErrorCode;
    695         int qmiRetCode;
    696         qmi_idl_service_object_type qmi_client_service_obj[MAX_NO_OF_SIM_SUPPORTED];
    697         int index;
    698         static Boolean flag = FALSE;
    699         struct sigaction    actions;
    700         int ret = 0;
    701         wpa_uim_struct_type *wpa_uim = eap_proxy->wpa_uim;
    702 #ifdef CONFIG_EAP_PROXY_MDM_DETECT
    703         struct dev_info mdm_detect_info;
    704 
    705         /* Call ESOC API to get the number of modems.
    706          * If the number of modems is not zero, only then proceed
    707          * with the eap_proxy intialization.
    708          */
    709         ret = get_system_info(&mdm_detect_info);
    710         if (ret > 0)
    711                 wpa_printf(MSG_ERROR, "eap_proxy: Failed to get system info, ret %d", ret);
    712 
    713         if (mdm_detect_info.num_modems == 0) {
    714                 eap_proxy->proxy_state = EAP_PROXY_DISABLED;
    715                 wpa_printf(MSG_ERROR, "eap_proxy: No Modem support for this target"
    716                            " number of modems is %d", mdm_detect_info.num_modems);
    717                 return;
    718         }
    719         wpa_printf(MSG_DEBUG, "eap_proxy: num_modems = %d", mdm_detect_info.num_modems);
    720 
    721         if(eap_modem_compatible(&mdm_detect_info) == FALSE) {
    722                 eap_proxy->proxy_state = EAP_PROXY_DISABLED;
    723                 wpa_printf(MSG_ERROR, "eap_proxy: build does not support EAP-SIM feature");
    724                 return;
    725         }
    726 #endif /* CONFIG_EAP_PROXY_MDM_DETECT */
    727 
    728         sigemptyset(&actions.sa_mask);
    729         actions.sa_flags = 0;
    730         actions.sa_handler = exit_proxy_init;
    731         ret = sigaction(SIGUSR1,&actions,NULL);
    732         if(ret < 0)
    733                 wpa_printf(MSG_DEBUG, "sigaction\n");
    734         eap_proxy->proxy_state = EAP_PROXY_INITIALIZE;
    735         eap_proxy->qmi_state = QMI_STATE_IDLE;
    736         eap_proxy->key = NULL;
    737         eap_proxy->iskey_valid = FALSE;
    738         eap_proxy->is_state_changed = FALSE;
    739         eap_proxy->isEap = FALSE;
    740         eap_proxy->eap_type = EAP_TYPE_NONE;
    741         eap_proxy->user_selected_sim = 0;
    742 
    743 #ifdef CONFIG_EAP_PROXY_DUAL_SIM
    744         wpa_printf (MSG_ERROR,
    745                 "eap_proxy: eap_proxy Initializing for DUAL SIM build %d tid %d",
    746                 MAX_NO_OF_SIM_SUPPORTED, gettid());
    747 #else
    748         wpa_printf (MSG_ERROR,
    749                 "eap_proxy: eap_proxy Initializing for Single SIM build %d tid %d",
    750                 MAX_NO_OF_SIM_SUPPORTED, gettid());
    751 #endif
    752 
    753 
    754         for (index = 0; index < MAX_NO_OF_SIM_SUPPORTED; ++index) {
    755 
    756 #ifdef SIM_AKA_IDENTITY_IMSI
    757                 if (FALSE == eap_proxy->qmi_uim_svc_client_initialized[index])  {
    758                         qmi_client_os_params eap_os_params;
    759                         /* Init QMI_UIM service for EAP-SIM/AKA */
    760                         os_memset(&eap_os_params, 0, sizeof(qmi_client_os_params));
    761 
    762                         qmiErrorCode = qmi_client_init_instance(
    763                                         uim_get_service_object_v01(),
    764                                         QMI_CLIENT_INSTANCE_ANY,
    765                                         wpa_qmi_client_indication_cb,
    766                                         eap_proxy, &eap_os_params,
    767                                         10000,
    768                                         &wpa_uim[index].qmi_uim_svc_client_ptr);
    769 
    770                         if ((wpa_uim[index].qmi_uim_svc_client_ptr == NULL) || (qmiErrorCode > 0)) {
    771                                 wpa_printf(MSG_ERROR, "eap_proxy: Could not register with QMI UIM"
    772                                         "Service, qmi_uim_svc_client_ptr: %p,qmi_err_code: %d\n",
    773                                         wpa_uim[index].qmi_uim_svc_client_ptr, qmiErrorCode);
    774                                 wpa_uim[index].qmi_uim_svc_client_ptr = NULL;
    775                                 flag = FALSE;
    776                                 continue;
    777                         }
    778                         eap_proxy->qmi_uim_svc_client_initialized[index] = TRUE;
    779 
    780                         wpa_printf (MSG_ERROR, "eap_proxy: QMI uim service client initialized with"
    781                                 "success tid is %d %p %d\n",
    782                                 gettid(), wpa_uim[index].qmi_uim_svc_client_ptr, qmiErrorCode);
    783                         /* Register the card events with the QMI / UIM */
    784                         wpa_qmi_register_events(index, wpa_uim);
    785                         qmiErrorCode = qmi_client_register_error_cb(
    786                                 wpa_uim[index].qmi_uim_svc_client_ptr, wpa_qmi_handle_ssr, eap_proxy);
    787                         wpa_printf(MSG_DEBUG,
    788                                 "eap_proxy: qmi_client_register_error_cb() status %d\n", qmiErrorCode);
    789                         wpa_qmi_ssr = FALSE;
    790                 } else
    791                         wpa_printf (MSG_ERROR, "eap_proxy: QMI uim service client is already init"
    792                                 "ialized tid is %d \n", gettid());
    793 
    794 
    795                 qmi_client_os_params eap_os_params;
    796                 os_memset(&eap_os_params, 0, sizeof(qmi_client_os_params));
    797 
    798                 qmiErrorCode = qmi_client_init_instance(auth_get_service_object_v01(),
    799                                                         QMI_CLIENT_INSTANCE_ANY,
    800                                                         handle_qmi_eap_ind,
    801                                                         eap_proxy,
    802                                                         &eap_os_params,
    803                                                         10000,
    804                                                         &eap_proxy->qmi_auth_svc_client_ptr[index]);
    805 
    806 
    807                 if ((eap_proxy->qmi_auth_svc_client_ptr[index] == NULL) || (qmiErrorCode > 0)) {
    808                         wpa_printf(MSG_ERROR, "eap_proxy: Could not register with QMI auth Service "
    809                                         "qmi_auth_svc_client_ptr: %p,qmi_err_code: %d\n",
    810                                         eap_proxy->qmi_auth_svc_client_ptr[index], qmiErrorCode);
    811                         eap_proxy->qmi_auth_svc_client_ptr[index] = NULL;
    812                         flag = FALSE;
    813                         continue;
    814                 }
    815                 wpa_printf (MSG_ERROR, "eap_proxy: QMI auth service client initialized with success"
    816                         " tid is %d  %p eapol_proxy=%p\n", gettid(),
    817                                 eap_proxy->qmi_auth_svc_client_ptr[index], eap_proxy);
    818                 flag = TRUE;
    819                 /* Register for the notifications from QMI / AUTH */
    820                 wpa_qmi_register_auth_inds(eap_proxy);
    821 #endif /* SIM_AKA_IDENTITY_IMSI */
    822         }
    823 
    824         if ( flag == FALSE ) {
    825                 eap_proxy->proxy_state = EAP_PROXY_DISABLED;
    826                 wpa_printf(MSG_ERROR, "eap_proxy: flag = %d proxy init failed\n", flag);
    827                 return;
    828         }
    829 
    830         eap_proxy->proxy_state = EAP_PROXY_IDLE;
    831         eap_proxy_eapol_sm_set_bool(eap_proxy, EAPOL_eapSuccess, FALSE);
    832         eap_proxy_eapol_sm_set_bool(eap_proxy, EAPOL_eapFail, FALSE);
    833         eap_proxy_eapol_sm_set_bool(eap_proxy, EAPOL_eapRestart, FALSE);
    834         eap_proxy_eapol_sm_set_bool(eap_proxy, EAPOL_eapResp, FALSE);
    835         eap_proxy_eapol_sm_set_bool(eap_proxy, EAPOL_eapNoResp, FALSE);
    836         wpa_printf (MSG_ERROR, "eap_proxy: Eap_proxy initialized successfully"
    837                 " tid is %d \n", gettid());
    838         return;
    839 
    840 }
    841 
    842 int eap_auth_end_eap_session(qmi_client_type qmi_auth_svc_client_ptr)
    843 {
    844         qmi_client_error_type qmiRetCode = 0;
    845         auth_end_eap_session_resp_msg_v01 end_eap_session_resp_msg ;
    846 
    847         wpa_printf(MSG_ERROR, "eap_proxy: eap_auth_end_eap_session: Ending EAP auth session");
    848 
    849 
    850         /* Send QMI_AUTH_END_EAP_SESSION_REQ */
    851 
    852         os_memset(&end_eap_session_resp_msg,
    853                         0,
    854                         sizeof(auth_end_eap_session_resp_msg_v01));
    855 
    856         qmiRetCode = qmi_client_send_msg_sync(qmi_auth_svc_client_ptr,
    857                                               QMI_AUTH_END_EAP_SESSION_REQ_V01,
    858                                               NULL,
    859                                               0,
    860                                               (void *) &end_eap_session_resp_msg,
    861                                               sizeof(auth_end_eap_session_resp_msg_v01),
    862                                               WPA_UIM_QMI_DEFAULT_TIMEOUT);
    863 
    864         if (QMI_NO_ERR != qmiRetCode ||
    865             end_eap_session_resp_msg.resp.result != QMI_RESULT_SUCCESS_V01) {
    866                 wpa_printf(MSG_ERROR, "QMI-ERROR Unable to End the EAP session;"
    867                                 " error_ret=%d; qmi_err=%d\n", qmiRetCode,
    868                                 end_eap_session_resp_msg.resp.error);
    869                 return -1;
    870         }
    871 
    872         wpa_printf(MSG_ERROR, "eap_proxy: eap_auth_end_eap_session:"
    873                 " EAP auth session ended successfuly");
    874 
    875         return 0;
    876 }
    877 
    878 static void eap_proxy_schedule_thread(void *eloop_ctx, void *timeout_ctx)
    879 {
    880         struct eap_proxy_sm *eap_proxy = eloop_ctx;
    881         pthread_attr_t attr;
    882         int ret = -1;
    883 
    884         pthread_attr_init(&attr);
    885         pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
    886         ret = pthread_create(&eap_proxy->thread_id, &attr, eap_proxy_post_init, eap_proxy);
    887         if(ret < 0)
    888                wpa_printf(MSG_ERROR, "eap_proxy: starting thread is failed %d\n", ret);
    889 }
    890 
    891 struct eap_proxy_sm *
    892 eap_proxy_init(void *eapol_ctx, const struct eapol_callbacks *eapol_cb,
    893                void *msg_ctx)
    894 {
    895         int qmiErrorCode;
    896         int qmiRetCode;
    897         struct eap_proxy_sm *eap_proxy;
    898         qmi_idl_service_object_type    qmi_client_service_obj;
    899 
    900         wpa_printf(MSG_DEBUG, "eap_proxy: %s  "
    901                  "wpa_qmi_ssr %d", __func__, wpa_qmi_ssr);
    902         if(wpa_qmi_ssr) {
    903                 eap_proxy = eapol_ctx;
    904         } else {
    905                 eap_proxy =  os_malloc(sizeof(struct eap_proxy_sm));
    906                 if (NULL == eap_proxy) {
    907                         wpa_printf(MSG_ERROR, "Error memory alloc  for eap_proxy"
    908                                 "eap_proxy_init\n");
    909                         return NULL;
    910                 }
    911                 os_memset(eap_proxy, 0, sizeof(*eap_proxy));
    912                 eap_proxy->ctx = eapol_ctx;
    913                 eap_proxy->eapol_cb = eapol_cb;
    914                 eap_proxy->msg_ctx = msg_ctx;
    915         }
    916 
    917         eap_proxy->proxy_state = EAP_PROXY_DISABLED;
    918         eap_proxy->qmi_state = QMI_STATE_IDLE;
    919         eap_proxy->key = NULL;
    920         eap_proxy->iskey_valid = FALSE;
    921         eap_proxy->is_state_changed = FALSE;
    922         eap_proxy->isEap = FALSE;
    923         eap_proxy->eap_type = EAP_TYPE_NONE;
    924 
    925         /* delay the qmi client initialization after the eloop_run starts,
    926         * in order to avoid the case of daemonize enabled, which exits the
    927         * parent process that created the qmi client context.
    928         */
    929 
    930         eloop_register_timeout(0, 0, eap_proxy_schedule_thread, eap_proxy, NULL);
    931         return eap_proxy;
    932 }
    933 
    934 
    935 static void eap_proxy_qmi_deinit(struct eap_proxy_sm *eap_proxy)
    936 {
    937         int qmiRetCode;
    938         int qmiErrorCode;
    939         int index;
    940         wpa_uim_struct_type *wpa_uim = eap_proxy->wpa_uim;
    941 
    942         if (NULL == eap_proxy)
    943                 return;
    944 
    945         pthread_kill(eap_proxy->thread_id, SIGUSR1);
    946         eap_proxy->proxy_state = EAP_PROXY_DISABLED;
    947 
    948         for (index = 0; index < MAX_NO_OF_SIM_SUPPORTED; ++index) {
    949                 if (TRUE == eap_proxy->eap_auth_session_flag[index]) {
    950 
    951                         /* end the current EAP session */
    952                         if(eap_auth_end_eap_session(eap_proxy->qmi_auth_svc_client_ptr[index]) < 0 ){
    953                                 wpa_printf(MSG_ERROR, "eap_proxy: Unable to end the EAP session for"
    954                                                 " client %d", index+1);
    955                         } else {
    956                                 wpa_printf(MSG_ERROR, "eap_proxy: Ended the QMI EAP session for "
    957                                                 "client %d\n",
    958                                                 index+1);
    959                                 eap_proxy->eap_auth_session_flag[index] = FALSE;
    960                         }
    961                 } else {
    962                         wpa_printf (MSG_ERROR, "eap_proxy: session not started"
    963                                 " for client = %d\n", index+1);
    964                         continue;
    965                 }
    966 
    967                 if ((TRUE == eap_proxy->qmi_uim_svc_client_initialized[index]))  {
    968                         qmiRetCode = qmi_client_release(wpa_uim[index].qmi_uim_svc_client_ptr);
    969                         if (QMI_NO_ERR != qmiRetCode) {
    970                                 wpa_printf (MSG_ERROR, "eap_proxy: Unable to Releas the connection"
    971                                                 " to uim service for client=%d; error_ret=%d\n;",
    972                                                 index+1, qmiRetCode);
    973                         }
    974                         wpa_printf(MSG_ERROR, "eap_proxy: Released QMI UIM service client\n");
    975                         eap_proxy->qmi_uim_svc_client_initialized[index] = FALSE;
    976                 }
    977 
    978                 qmiRetCode = qmi_client_release(eap_proxy->qmi_auth_svc_client_ptr[index]);
    979                 if (QMI_NO_ERR != qmiRetCode) {
    980                         wpa_printf (MSG_ERROR, "eap_proxy: Unable to Releas the connection"
    981                                         " to auth service for client=%d; error_ret=%d\n;",
    982                                         index+1, qmiRetCode);
    983                 }  else {
    984                         wpa_printf(MSG_ERROR, "eap_proxy: Released QMI EAP service client\n");
    985                 }
    986 
    987         }
    988 
    989         if (NULL != eap_proxy->key) {
    990                 os_free(eap_proxy->key);
    991                 eap_proxy->key = NULL;
    992         }
    993 
    994         eap_proxy->iskey_valid = FALSE;
    995         eap_proxy->is_state_changed = FALSE;
    996         eap_proxy->user_selected_sim = 0;
    997 
    998 }
    999 
   1000 void eap_proxy_deinit(struct eap_proxy_sm *eap_proxy)
   1001 {
   1002         eap_proxy_qmi_deinit(eap_proxy);
   1003         if (eap_proxy != NULL) {
   1004             os_free(eap_proxy);
   1005             eap_proxy = NULL;
   1006             wpa_printf(MSG_INFO, "eap_proxy: eap_proxy Deinitialzed\n");
   1007         }
   1008 }
   1009 
   1010 /* Call-back function to process an authentication result indication
   1011 *  from QMI EAP service */
   1012 static void handle_qmi_eap_ind(qmi_client_type user_handle,
   1013                                unsigned int msg_id,
   1014                                void* ind_buf,
   1015                                unsigned int ind_buf_len,
   1016                                void* ind_cb_data)
   1017 {
   1018         qmi_client_error_type qmi_err;
   1019         auth_eap_session_result_ind_msg_v01 eap_session_result;
   1020         memset(&eap_session_result, 0, sizeof(auth_eap_session_result_ind_msg_v01));
   1021         eap_session_result.eap_result = -1;
   1022         struct eap_proxy_sm *sm = (struct eap_proxy_sm *)ind_cb_data;
   1023 
   1024         auth_eap_notification_code_ind_msg_v01 eap_notification;
   1025         memset(&eap_notification, 0, sizeof(auth_eap_notification_code_ind_msg_v01));
   1026 
   1027         wpa_printf(MSG_ERROR, "eap_proxy: Handle_qmi_eap_ind msgId =%d  sm=%p\n", msg_id,sm);
   1028         /* Decode */
   1029 
   1030         switch(msg_id)
   1031         {
   1032                 case QMI_AUTH_EAP_SESSION_RESULT_IND_V01:
   1033 
   1034                         qmi_err = qmi_client_message_decode(user_handle, QMI_IDL_INDICATION,
   1035                                         msg_id, (void*)ind_buf, ind_buf_len,
   1036                                         &eap_session_result,
   1037                                         sizeof(auth_eap_session_result_ind_msg_v01));
   1038                         if (qmi_err != QMI_NO_ERR)
   1039                         {
   1040                                 wpa_printf(MSG_ERROR, "eap_proxy: Error in qmi_client_message_de"
   1041                                         "code; error_code=%d \n", qmi_err);
   1042                                 sm->srvc_result = EAP_PROXY_QMI_SRVC_FAILURE;
   1043                                 return;
   1044                         }
   1045                         if ((eap_session_result.eap_result == 0) &&
   1046                             (QMI_STATE_RESP_TIME_OUT != sm->qmi_state)) {
   1047                                 sm->proxy_state = EAP_PROXY_AUTH_SUCCESS;
   1048                                 sm->qmi_state = QMI_STATE_RESP_RECEIVED;
   1049                                 wpa_printf(MSG_ERROR, "eap_proxy: Handle_qmi_eap_ind EAP PROXY AUTH"
   1050                                         " SUCCESS %p set to %d\n",
   1051                                         (void *)&sm->qmi_state, sm->qmi_state);
   1052                         } else {
   1053                                 sm->proxy_state = EAP_PROXY_AUTH_FAILURE;
   1054                                 wpa_printf(MSG_ERROR, "eap_proxy: Handle_qmi_eap_ind EAP PROXY AUTH"
   1055                                         " FAILURE \n");
   1056                         }
   1057                         sm->srvc_result = EAP_PROXY_QMI_SRVC_SUCCESS;
   1058                         break;
   1059 
   1060                 case QMI_AUTH_EAP_NOTIFICATION_CODE_IND_V01:
   1061 
   1062                         qmi_err = qmi_client_message_decode(user_handle, QMI_IDL_INDICATION,
   1063                                         msg_id, (void*)ind_buf, ind_buf_len,
   1064                                         &eap_notification,
   1065                                         sizeof(auth_eap_notification_code_ind_msg_v01));
   1066                         if (qmi_err != QMI_NO_ERR)
   1067                         {
   1068                                 wpa_printf(MSG_ERROR, "eap_proxy: Error in qmi_client_"
   1069                                         "message_decode; error_code=%d \n", qmi_err);
   1070                         }
   1071                         sm->notification_code = eap_notification.eap_notification_code;
   1072                         wpa_printf(MSG_ERROR, "eap_proxy: notificatio code is %x\n",
   1073                                         eap_notification.eap_notification_code);
   1074                         break;
   1075 
   1076                 default:
   1077                         wpa_printf(MSG_ERROR, "eap_proxy: An unexpected msg Id=%d"
   1078                                         " is given\n", msg_id);
   1079                         break;
   1080         }
   1081 
   1082 
   1083 }
   1084 
   1085 
   1086 /* Call-back function to process an EAP response from QMI EAP service */
   1087 static void handle_qmi_eap_reply(
   1088                 qmi_client_type userHandle, unsigned int msg_id,
   1089                 void *resp_c_struct, unsigned int resp_c_struct_len,
   1090                 void *userData, qmi_client_error_type sysErrCode)
   1091 {
   1092         struct eap_proxy_sm *eap_proxy = (struct eap_proxy_sm *)userData;
   1093         auth_send_eap_packet_resp_msg_v01* rspData =
   1094                 (auth_send_eap_packet_resp_msg_v01*)resp_c_struct;
   1095 
   1096         u8 *resp_data;
   1097         u32 length;
   1098 
   1099         wpa_printf(MSG_ERROR, "eap_proxy: %s started\n", __func__);
   1100         if (eap_proxy == NULL) {
   1101                 wpa_printf(MSG_ERROR, "eap_proxy: eap_proxy is NULL");
   1102                 return;
   1103         }
   1104         if (QMI_STATE_RESP_PENDING == eap_proxy->qmi_state) {
   1105 
   1106                 wpa_printf(MSG_ERROR, "eap_proxy: user_selected_sim = %d\n",
   1107                            eap_proxy->user_selected_sim+1);
   1108 
   1109 
   1110                 if (QMI_NO_ERR != sysErrCode) {
   1111                         wpa_printf(MSG_ERROR, "eap_proxy: An error is encountered with"
   1112                                         " the request: sysErrorCode=%d\n",
   1113                                         sysErrCode);
   1114                         eap_proxy->qmi_state = QMI_STATE_RESP_TIME_OUT;
   1115                         return;
   1116                 }
   1117 
   1118                 if (NULL == rspData) {
   1119                         wpa_printf(MSG_ERROR, "eap_proxy: Response data is NULL\n");
   1120                         eap_proxy->qmi_state = QMI_STATE_RESP_TIME_OUT;
   1121                         return;
   1122                 }
   1123                 if((QMI_AUTH_SEND_EAP_PACKET_REQ_V01 != msg_id) &&
   1124                    (QMI_AUTH_SEND_EAP_PACKET_EXT_REQ_V01 != msg_id))
   1125                 {
   1126                         wpa_printf(MSG_ERROR, "eap_proxy: Invalid msgId =%d\n", msg_id);
   1127                         eap_proxy->qmi_state = QMI_STATE_RESP_TIME_OUT;
   1128                         return;
   1129                 }
   1130 
   1131                 /* ensure the reply packet exists  */
   1132                 if (rspData->eap_response_pkt_len <= 0 ||
   1133                     rspData->eap_response_pkt_len > QMI_AUTH_EAP_RESP_PACKET_EXT_MAX_V01) {
   1134                         wpa_printf(MSG_ERROR, "eap_proxy: Reply packet is of invalid length %d"
   1135                                 " error %d result %d\n", rspData->eap_response_pkt_len,
   1136                                 rspData->resp.error, rspData->resp.result);
   1137                         eap_proxy->qmi_state = QMI_STATE_RESP_TIME_OUT;
   1138                         return;
   1139                 }
   1140 
   1141                 length = rspData->eap_response_pkt_len;
   1142                 eap_proxy->qmi_resp_data.eap_send_pkt_resp.length = length;
   1143                 /* allocate a buffer to store the response data; size is EAP resp len field */
   1144                 eap_proxy->qmi_resp_data.eap_send_pkt_resp.resp_data =
   1145                         os_malloc(rspData->eap_response_pkt_len);
   1146 
   1147                 resp_data =
   1148                         (u8 *)eap_proxy->qmi_resp_data.eap_send_pkt_resp.resp_data;
   1149 
   1150                 if (NULL == resp_data) {
   1151                         wpa_printf(MSG_ERROR, "eap_proxy: Unable to allocate memory for"
   1152                                         " reply packet\n");
   1153                         eap_proxy->qmi_state = QMI_STATE_RESP_TIME_OUT;
   1154 
   1155                         return;
   1156                 }
   1157 
   1158                 /* copy the response data to the allocated buffer */
   1159                 os_memcpy(resp_data,
   1160                                 rspData->eap_response_pkt, length);
   1161                 eap_proxy->qmi_state = QMI_STATE_RESP_RECEIVED;
   1162                 wpa_printf(MSG_ERROR, "eap_proxy: **HANDLE_QMI_EAP_REPLY CALLBACK ENDDED **");
   1163 
   1164                 wpa_printf(MSG_ERROR, "eap_proxy: Dump Resp Data len %d\n", length);
   1165                 dump_buff(resp_data, length);
   1166         }
   1167 
   1168         return;
   1169 }
   1170 
   1171 static enum eap_proxy_status eap_proxy_process(struct eap_proxy_sm  *eap_proxy,
   1172                                         u8 *eapReqData, int eapReqDataLen, struct eap_sm *eap_sm)
   1173 {
   1174         struct eap_hdr *hdr;
   1175         int qmiErrorCode;
   1176         enum eap_proxy_status proxy_status = EAP_PROXY_SUCCESS;
   1177         auth_send_eap_packet_req_msg_v01 eap_send_packet_req;
   1178         auth_send_eap_packet_resp_msg_v01 eap_send_packet_resp;
   1179         qmi_txn_handle async_txn_hdl = 0;
   1180 
   1181         auth_send_eap_packet_ext_req_msg_v01 eap_send_packet_ext_req;
   1182         auth_send_eap_packet_ext_resp_msg_v01 eap_send_packet_ext_resp;
   1183 
   1184 
   1185         hdr = (struct eap_hdr *)eapReqData;
   1186         if ((EAP_CODE_REQUEST == hdr->code) &&
   1187             (EAP_TYPE_IDENTITY == eapReqData[4])) {
   1188                 if (eap_proxy_eapol_sm_get_bool(eap_proxy, EAPOL_eapRestart) &&
   1189                     eap_proxy_eapol_sm_get_bool(eap_proxy, EAPOL_portEnabled)) {
   1190                         wpa_printf (MSG_ERROR, "eap_proxy: Already Authenticated."
   1191                                     " Clear all the flags");
   1192                         eap_proxy_eapol_sm_set_bool(eap_proxy, EAPOL_eapSuccess, FALSE);
   1193                         eap_proxy_eapol_sm_set_bool(eap_proxy, EAPOL_eapFail, FALSE);
   1194                         eap_proxy_eapol_sm_set_bool(eap_proxy, EAPOL_eapResp, FALSE);
   1195                         eap_proxy_eapol_sm_set_bool(eap_proxy, EAPOL_eapNoResp, FALSE);
   1196                         if (eap_proxy->key) {
   1197                                 os_free(eap_proxy->key);
   1198                                 eap_proxy->key = NULL;
   1199                         }
   1200                         eap_proxy->iskey_valid = FALSE;
   1201                         eap_proxy->is_state_changed = TRUE;
   1202                 }
   1203                 eap_proxy_eapol_sm_set_bool(eap_proxy, EAPOL_eapRestart, FALSE);
   1204 
   1205                 if(eap_proxy_build_identity(eap_proxy, hdr->identifier, eap_sm)) {
   1206                         eap_proxy->proxy_state = EAP_PROXY_IDENTITY;
   1207                 } else {
   1208                         wpa_printf(MSG_ERROR, "eap_proxy: Error in build identity\n");
   1209                         return EAP_PROXY_FAILURE;
   1210                 }
   1211         }
   1212         wpa_printf(MSG_ERROR, "eap_proxy: ***********Dump ReqData len %d***********",
   1213                 eapReqDataLen);
   1214         dump_buff(eapReqData, eapReqDataLen);
   1215         if (eapReqDataLen <= QMI_AUTH_EAP_REQ_PACKET_MAX_V01) {
   1216                 os_memset(&eap_send_packet_req, 0, sizeof(auth_send_eap_packet_req_msg_v01));
   1217                 os_memset(&eap_send_packet_resp, 0, sizeof(auth_send_eap_packet_resp_msg_v01));
   1218                 eap_send_packet_req.eap_request_pkt_len = eapReqDataLen ;
   1219                 memcpy(eap_send_packet_req.eap_request_pkt, eapReqData, eapReqDataLen);
   1220         } else if (eapReqDataLen <= QMI_AUTH_EAP_REQ_PACKET_EXT_MAX_V01) {
   1221                 os_memset(&eap_send_packet_ext_req, 0,
   1222                         sizeof(auth_send_eap_packet_ext_req_msg_v01));
   1223                 os_memset(&eap_send_packet_ext_resp, 0,
   1224                         sizeof(auth_send_eap_packet_ext_resp_msg_v01));
   1225                 eap_send_packet_ext_req.eap_request_ext_pkt_len = eapReqDataLen;
   1226                 memcpy(eap_send_packet_ext_req.eap_request_ext_pkt, eapReqData, eapReqDataLen);
   1227         } else {
   1228                         wpa_printf(MSG_ERROR, "eap_proxy: Error in eap_send_packet_req\n");
   1229                         return EAP_PROXY_FAILURE;
   1230         }
   1231 
   1232         wpa_printf(MSG_ERROR, "eap_proxy: SIM selected by User: Selected sim = %d\n",
   1233                 eap_proxy->user_selected_sim+1);
   1234         if (eap_proxy->qmi_state != QMI_STATE_IDLE) {
   1235                 wpa_printf(MSG_ERROR, "Error in QMI state=%d\n",
   1236                                          eap_proxy->qmi_state);
   1237                 return EAP_PROXY_FAILURE;
   1238         }
   1239 
   1240         wpa_printf (MSG_ERROR, "eap_proxy: In eap_proxy_process case %d\n", hdr->code);
   1241         eap_proxy->qmi_state = QMI_STATE_RESP_PENDING;
   1242 
   1243         if(eapReqDataLen <= QMI_AUTH_EAP_REQ_PACKET_MAX_V01) {
   1244                 qmiErrorCode = qmi_client_send_msg_async(
   1245                                 eap_proxy->qmi_auth_svc_client_ptr[eap_proxy->user_selected_sim],
   1246                                 QMI_AUTH_SEND_EAP_PACKET_REQ_V01,
   1247                                 (void *) &eap_send_packet_req,
   1248                                 sizeof(auth_send_eap_packet_req_msg_v01),
   1249                                 (void *) &eap_send_packet_resp,
   1250                                 sizeof(auth_send_eap_packet_resp_msg_v01),
   1251                                 &handle_qmi_eap_reply, eap_proxy,
   1252                                 &async_txn_hdl);
   1253         } else if(eapReqDataLen <= QMI_AUTH_EAP_REQ_PACKET_EXT_MAX_V01) {
   1254                 qmiErrorCode = qmi_client_send_msg_async(
   1255                                 eap_proxy->qmi_auth_svc_client_ptr[eap_proxy->user_selected_sim],
   1256                                 QMI_AUTH_SEND_EAP_PACKET_EXT_REQ_V01,
   1257                                 (void *) &eap_send_packet_ext_req,
   1258                                 sizeof(auth_send_eap_packet_ext_req_msg_v01),
   1259                                 (void *) &eap_send_packet_ext_resp,
   1260                                 sizeof(auth_send_eap_packet_ext_resp_msg_v01),
   1261                                 &handle_qmi_eap_reply, eap_proxy,
   1262                                 &async_txn_hdl);
   1263         }
   1264 
   1265         if (QMI_NO_ERR != qmiErrorCode) {
   1266                 wpa_printf(MSG_ERROR, "QMI-ERROR Error in sending EAP packet;"
   1267                                 " error_code=%d\n", qmiErrorCode);
   1268                 eap_proxy->proxy_state = EAP_PROXY_DISCARD;
   1269                 eap_proxy_eapol_sm_set_bool(eap_proxy, EAPOL_eapNoResp, TRUE);
   1270                 eap_proxy->qmi_state = QMI_STATE_RESP_PENDING;
   1271                 return EAP_PROXY_FAILURE;
   1272         } else {
   1273                 wpa_printf (MSG_ERROR, "eap_proxy: In eap_proxy_process case %d\n", hdr->code);
   1274                 switch (hdr->code) {
   1275                 case EAP_CODE_SUCCESS:
   1276                         if (EAP_PROXY_SUCCESS !=
   1277                                 eap_proxy_qmi_response_wait(eap_proxy)) {
   1278                                 eap_proxy->proxy_state = EAP_PROXY_DISCARD;
   1279                                 eap_proxy_eapol_sm_set_bool(eap_proxy,
   1280                                                         EAPOL_eapNoResp, TRUE);
   1281                                 return EAP_PROXY_FAILURE;
   1282                         } else if( eap_proxy->proxy_state == EAP_PROXY_AUTH_SUCCESS ) {
   1283                                 eap_proxy_getKey(eap_proxy);
   1284                                 eap_proxy_eapol_sm_set_bool(eap_proxy,
   1285                                                  EAPOL_eapSuccess, TRUE);
   1286         /*
   1287          * RFC 4137 does not clear eapReq here, but this seems to be required
   1288          * to avoid processing the same request twice when state machine is
   1289          * initialized.
   1290          */
   1291                         eap_proxy_eapol_sm_set_bool(eap_proxy,
   1292                                                         EAPOL_eapReq, FALSE);
   1293 
   1294         /*
   1295          * RFC 4137 does not set eapNoResp here, but this seems to be required
   1296          * to get EAPOL Supplicant backend state machine into SUCCESS state. In
   1297          * addition, either eapResp or eapNoResp is required to be set after
   1298          * processing the received EAP frame.
   1299          */
   1300                         eap_proxy_eapol_sm_set_bool(eap_proxy,
   1301                                                 EAPOL_eapNoResp, TRUE);
   1302 
   1303                         wpa_msg(eap_proxy->msg_ctx, MSG_INFO, WPA_EVENT_EAP_SUCCESS
   1304                                 "eap_proxy: EAP authentication completed successfully");
   1305 
   1306                         eap_proxy->is_state_changed = TRUE;
   1307 
   1308                                 /* Retrieve the keys  and store*/
   1309                         } else if( eap_proxy->proxy_state == EAP_PROXY_AUTH_FAILURE ){
   1310 
   1311                                 eap_proxy_eapol_sm_set_bool(eap_proxy,
   1312                                                 EAPOL_eapFail, TRUE);
   1313                                 eap_proxy_eapol_sm_set_bool(eap_proxy,
   1314                                                 EAPOL_eapReq, FALSE);
   1315                                 eap_proxy_eapol_sm_set_bool(eap_proxy,
   1316                                                 EAPOL_eapNoResp, TRUE);
   1317                                 eap_proxy->is_state_changed = TRUE;
   1318 
   1319                         }
   1320 
   1321                         break;
   1322 
   1323                 case EAP_CODE_FAILURE:
   1324                         wpa_printf (MSG_ERROR,
   1325                                 "eap_proxy: in eap_proxy_process case EAP_CODE_FAILURE\n");
   1326                         eap_proxy->proxy_state = EAP_PROXY_AUTH_FAILURE;
   1327                         eap_proxy_eapol_sm_set_bool(eap_proxy,
   1328                                                 EAPOL_eapFail, TRUE);
   1329 
   1330         /*
   1331          * RFC 4137 does not clear eapReq here, but this seems to be required
   1332          * to avoid processing the same request twice when state machine is
   1333          * initialized.
   1334         */
   1335                         eap_proxy_eapol_sm_set_bool(eap_proxy,
   1336                                                 EAPOL_eapReq, FALSE);
   1337 
   1338         /*
   1339          * RFC 4137 does not set eapNoResp here. However, either eapResp or
   1340          * eapNoResp is required to be set after processing the received EAP
   1341          * frame.
   1342          */
   1343                         eap_proxy_eapol_sm_set_bool(eap_proxy,
   1344                                                 EAPOL_eapNoResp, TRUE);
   1345 
   1346                         wpa_msg(eap_proxy->msg_ctx, MSG_INFO, WPA_EVENT_EAP_FAILURE
   1347                                 "EAP authentication failed notification code 0x%x",
   1348                                 eap_proxy->notification_code);
   1349 
   1350                         eap_proxy->is_state_changed = TRUE;
   1351                         break;
   1352 
   1353                 case EAP_CODE_REQUEST:
   1354                                         eap_proxy->proxy_state = EAP_PROXY_SEND_RESPONSE;
   1355                         if (EAP_PROXY_SUCCESS !=
   1356                                 eap_proxy_qmi_response_wait(eap_proxy)) {
   1357                                 eap_proxy->proxy_state = EAP_PROXY_DISCARD;
   1358                                 eap_proxy_eapol_sm_set_bool(eap_proxy,
   1359                                                         EAPOL_eapNoResp, TRUE);
   1360                                 return EAP_PROXY_FAILURE;
   1361                         } else {
   1362                                 eap_proxy_eapol_sm_set_bool(eap_proxy,
   1363                                                         EAPOL_eapResp, TRUE);
   1364                                 eap_proxy->proxy_state =
   1365                                                 EAP_PROXY_SEND_RESPONSE;
   1366                         }
   1367 
   1368                         eap_proxy_eapol_sm_set_bool(eap_proxy,
   1369                                                 EAPOL_eapReq, FALSE);
   1370                         eap_proxy->is_state_changed = TRUE;
   1371                         break;
   1372 
   1373                 default:
   1374                         wpa_printf(MSG_ERROR, "eap_proxy: Error in sending EAP packet;"
   1375                                          " error_code=%d\n", qmiErrorCode);
   1376                         eap_proxy->proxy_state = EAP_PROXY_DISCARD;
   1377                         eap_proxy_eapol_sm_set_bool(eap_proxy,
   1378                                 EAPOL_eapNoResp, TRUE);
   1379                         return EAP_PROXY_FAILURE;
   1380                 }
   1381         }
   1382 
   1383         return EAP_PROXY_SUCCESS;
   1384 }
   1385 
   1386 
   1387 
   1388 static u8 *eap_proxy_getKey(struct eap_proxy_sm *eap_proxy)
   1389 {
   1390         int qmiErrorCode;
   1391         int qmiRetCode;
   1392 
   1393         auth_get_eap_session_keys_resp_msg_v01 key_resp_msg;
   1394         os_memset(&key_resp_msg, 0, sizeof(auth_get_eap_session_keys_resp_msg_v01));
   1395 
   1396         qmiRetCode = qmi_client_send_msg_sync(
   1397                         eap_proxy->qmi_auth_svc_client_ptr[eap_proxy->user_selected_sim],
   1398                         QMI_AUTH_GET_EAP_SESSION_KEYS_REQ_V01,
   1399                         NULL,
   1400                         0,
   1401                         (void *) &key_resp_msg,
   1402                         sizeof(auth_get_eap_session_keys_resp_msg_v01),
   1403                         WPA_UIM_QMI_DEFAULT_TIMEOUT);
   1404 
   1405 
   1406         /* see if the MSK is acquired successfully */
   1407         if (QMI_NO_ERR != qmiRetCode || key_resp_msg.resp.result != QMI_RESULT_SUCCESS_V01) {
   1408                 wpa_printf(MSG_ERROR, "QMI-ERROR Unable to get session keys;"
   1409                                  " err_code=%d qmiErr=%d\n", qmiRetCode, key_resp_msg.resp.error);
   1410                 eap_proxy->key = NULL;
   1411                 return NULL;
   1412         }
   1413         wpa_printf(MSG_ERROR, "eap_proxy: %s:session_key_len =%d", __func__,
   1414                 key_resp_msg.session_key_len);
   1415 
   1416         if(key_resp_msg.session_key_len <=0 ||
   1417            key_resp_msg.session_key_len > EAP_PROXY_KEYING_DATA_LEN)
   1418         {
   1419                 return NULL;
   1420 
   1421         }
   1422         eap_proxy->key = os_malloc(EAP_PROXY_KEYING_DATA_LEN);
   1423         if(eap_proxy->key == NULL)
   1424                 return NULL;
   1425 
   1426         memset(eap_proxy->key, 0, EAP_PROXY_KEYING_DATA_LEN);
   1427         memcpy(eap_proxy->key, key_resp_msg.session_key, key_resp_msg.session_key_len);
   1428 
   1429         eap_proxy->iskey_valid = TRUE;
   1430         eap_proxy->proxy_state = EAP_PROXY_AUTH_SUCCESS;
   1431 
   1432         wpa_printf(MSG_ERROR, "eap_proxy: eap_proxy_getkey EAP KEYS ");
   1433         dump_buff(eap_proxy->key, EAP_PROXY_KEYING_DATA_LEN);
   1434         return eap_proxy->key;
   1435 }
   1436 
   1437 
   1438 /**
   1439  * eap_key_available - Get key availability (eapKeyAvailable variable)
   1440  * @sm: Pointer to EAP state machine allocated with eap_sm_init()
   1441  * Returns: 1 if EAP keying material is available, 0 if not
   1442  */
   1443 int eap_proxy_key_available(struct eap_proxy_sm *sm)
   1444 {
   1445         return sm ? sm->iskey_valid : 0;
   1446 }
   1447 
   1448 
   1449 static int eap_proxy_is_state_changed(struct eap_proxy_sm *sm)
   1450 {
   1451         if (NULL == sm)
   1452                 return 0;
   1453 
   1454         if (TRUE == sm->is_state_changed) {
   1455                 sm->is_state_changed = FALSE;
   1456                 return 1;
   1457         } else {
   1458                 return 0;
   1459         }
   1460 }
   1461 
   1462 
   1463 /**
   1464  * eap_get_eapKeyData - Get master session key (MSK) from EAP state machine
   1465  * @sm: Pointer to EAP state machine allocated with eap_sm_init()
   1466  * @len: Pointer to variable that will be set to number of bytes in the key
   1467  * Returns: Pointer to the EAP keying data or %NULL on failure
   1468  *
   1469  * Fetch EAP keying material (MSK, eapKeyData) from the EAP state machine. The
   1470  * key is available only after a successful authentication. EAP state machine
   1471  * continues to manage the key data and the caller must not change or free the
   1472  * returned data.
   1473  */
   1474 const u8 * eap_proxy_get_eapKeyData(struct eap_proxy_sm *sm, size_t *len)
   1475 {
   1476         if (sm == NULL || sm->key == NULL) {
   1477                 *len = 0;
   1478                 return NULL;
   1479         }
   1480 
   1481         *len = EAP_PROXY_KEYING_DATA_LEN;
   1482         return sm->key;
   1483 }
   1484 
   1485 /**
   1486  * eap_proxy_get_eapRespData - Get EAP response data
   1487  * @sm: Pointer to EAP state machine allocated with eap_sm_init()
   1488  * @len: Pointer to variable that will be set to the length of the response
   1489  * Returns: Pointer to the EAP response (eapRespData) or %NULL on failure
   1490  *
   1491  * Fetch EAP response (eapRespData) from the EAP state machine. This data is
   1492  * available when EAP state machine has processed an incoming EAP request. The
   1493  * EAP state machine does not maintain a reference to the response after this
   1494  * function is called and the caller is responsible for freeing the data.
   1495  */
   1496 struct wpabuf * eap_proxy_get_eapRespData(struct eap_proxy_sm *eap_proxy)
   1497 {
   1498         struct wpabuf *resp;
   1499         int len;
   1500         //int i;
   1501 
   1502         wpa_printf(MSG_ERROR, "eap_proxy: eap_proxy_get_eapRespData");
   1503         if ( (eap_proxy == NULL) ||
   1504              (eap_proxy->qmi_resp_data.eap_send_pkt_resp.resp_data == NULL)
   1505            )
   1506         {
   1507                 return NULL;
   1508         }
   1509 
   1510         len = eap_proxy->qmi_resp_data.eap_send_pkt_resp.length;
   1511         wpa_printf(MSG_ERROR, "eap_proxy: eap_proxy_get_eapRespData len = %d", len);
   1512         resp = wpabuf_alloc(len);
   1513         if (resp == NULL) {
   1514                 wpa_printf(MSG_ERROR, "eap_proxy: buf allocation failed\n");
   1515                 return NULL;
   1516         }
   1517 
   1518         resp->used = len;
   1519         os_memcpy(resp->buf, eap_proxy->qmi_resp_data.eap_send_pkt_resp.resp_data,
   1520                    len);
   1521         /*
   1522         for (i = 0; i < len; i++) {
   1523                 wpa_printf (MSG_ERROR, "%c", resp->buf[i]);
   1524         }
   1525         */
   1526         os_free(eap_proxy->qmi_resp_data.eap_send_pkt_resp.resp_data);
   1527         eap_proxy->qmi_resp_data.eap_send_pkt_resp.resp_data = NULL;
   1528         eap_proxy->qmi_resp_data.eap_send_pkt_resp.length = 0;
   1529 
   1530         return resp;
   1531 }
   1532 
   1533 
   1534 static enum eap_proxy_status eap_proxy_qmi_response_wait(struct eap_proxy_sm *eap_proxy)
   1535 {
   1536 
   1537         int count = 0;
   1538 
   1539         wpa_printf(MSG_DEBUG, "eap_proxy_qmi_response_wait: Start blocking "
   1540                    "wait eap_proxy=%p",eap_proxy);
   1541         do {
   1542                 count++;
   1543                 if (count > QMI_RESP_TIME_OUT / 2) {
   1544                         wpa_printf(MSG_ERROR,
   1545                                    "eap_proxy: eap_proxy_qmi_response_wait "
   1546                                    "!QMI STATE %d TIME_OUT\n",
   1547                                    eap_proxy->qmi_state);
   1548                         eap_proxy->qmi_state = QMI_STATE_RESP_TIME_OUT;
   1549                         break;
   1550                 }
   1551 
   1552                 os_sleep(0, 2000);
   1553 
   1554                 if ((QMI_STATE_RESP_RECEIVED == eap_proxy->qmi_state) ||
   1555                    (QMI_STATE_RESP_TIME_OUT == eap_proxy->qmi_state))
   1556                         break;
   1557         } while (1);
   1558 
   1559         wpa_printf(MSG_DEBUG, "eap_proxy: eap_proxy_qmi_response_wait: Wait done after %d "
   1560                    "iterations: qmi_state=%d", count,
   1561                    eap_proxy->qmi_state);
   1562 
   1563         if (QMI_STATE_RESP_TIME_OUT == eap_proxy->qmi_state) {
   1564                 wpa_printf(MSG_ERROR, "eap_proxy: QMI state Response Time out\n");
   1565                 eap_proxy->proxy_state = EAP_PROXY_DISCARD;
   1566                 return EAP_PROXY_FAILURE;
   1567         }
   1568         eap_proxy->qmi_state = QMI_STATE_IDLE;
   1569 
   1570         return EAP_PROXY_SUCCESS;
   1571 }
   1572 
   1573 
   1574 static void eap_proxy_eapol_sm_set_bool(struct eap_proxy_sm *sm,
   1575                         enum eapol_bool_var var, Boolean value)
   1576 {
   1577         sm->eapol_cb->set_bool(sm->ctx, var, value);
   1578 }
   1579 
   1580 
   1581 static Boolean eap_proxy_eapol_sm_get_bool(struct eap_proxy_sm *sm,
   1582                          enum eapol_bool_var var)
   1583 {
   1584         return  sm->eapol_cb->get_bool(sm->ctx, var);
   1585 }
   1586 
   1587 
   1588 int eap_proxy_sm_step(struct eap_proxy_sm *sm, struct eap_sm *eap_sm)
   1589 {
   1590         if ((sm->proxy_state != EAP_PROXY_INITIALIZE) &&
   1591                                  (sm->proxy_state != EAP_PROXY_DISABLED)) {
   1592                 if (TRUE == sm->isEap) {
   1593                         if(!eap_proxy_process(sm, sm->eapReqData,
   1594                                                  sm->eapReqDataLen,eap_sm)) {
   1595                                 sm->proxy_state = EAP_PROXY_AUTH_FAILURE;
   1596                                 eap_proxy_eapol_sm_set_bool(sm, EAPOL_eapRestart, TRUE);
   1597                         }
   1598                         sm->isEap = FALSE;
   1599                 }
   1600         }
   1601         return eap_proxy_is_state_changed(sm);
   1602 }
   1603 
   1604 
   1605 enum eap_proxy_status
   1606 eap_proxy_packet_update(struct eap_proxy_sm *eap_proxy, u8 *eapReqData,
   1607                         int eapReqDataLen)
   1608 {
   1609         eap_proxy->eapReqData = eapReqData;
   1610         eap_proxy->eapReqDataLen = eapReqDataLen;
   1611         eap_proxy->isEap = TRUE;
   1612         return EAP_PROXY_SUCCESS;
   1613 }
   1614 
   1615 
   1616 u8 * eap_proxy_get_eap_session_id(struct eap_proxy_sm *sm, size_t *len)
   1617 {
   1618         wpa_printf(MSG_ERROR, "%s: enter: not implemented\n", __func__);
   1619         return NULL;
   1620 }
   1621 
   1622 
   1623 u8 * eap_proxy_get_emsk(struct eap_proxy_sm *sm, size_t *len)
   1624 {
   1625         wpa_printf(MSG_ERROR, "%s: enter: not implemented\n", __func__);
   1626         return NULL;
   1627 }
   1628 
   1629 
   1630 void eap_proxy_sm_abort(struct eap_proxy_sm *sm)
   1631 {
   1632         wpa_printf(MSG_ERROR, "%s: enter: not implemented\n", __func__);
   1633         return;
   1634 }
   1635 
   1636 
   1637 static void dump_buff(u8 *buff, int len)
   1638 {
   1639         int i ;
   1640 
   1641         wpa_printf(MSG_ERROR, "eap_proxy: ---- EAP Buffer----LEN %d\n",len);
   1642         for (i = 0; i < len; i++) {
   1643                 if (0 == i%8)
   1644                         wpa_printf(MSG_DEBUG, " \n");
   1645                 wpa_printf(MSG_ERROR, "eap_proxy: 0x%x  ", buff[i]);
   1646         }
   1647         return;
   1648 }
   1649 static char bin_to_hexchar(u8 ch)
   1650 {
   1651         if (ch < 0x0a) {
   1652                 return ch + '0';
   1653         }
   1654         return ch + 'a' - 10;
   1655 }
   1656 static Boolean eap_proxy_build_identity(struct eap_proxy_sm *eap_proxy, u8 id, struct eap_sm *eap_sm)
   1657 {
   1658         struct eap_hdr *resp;
   1659         unsigned int len;
   1660         u8 identity_len = 0, ret;
   1661         u8 imsi_id_len = 0;
   1662         int mnc_len = -1;
   1663         u8 *pos;
   1664         int qmiRetCode;
   1665         u8 idx = 0, mcc_idx = 0;
   1666         unsigned char *identity = NULL;
   1667         unsigned char *imsi_identity = NULL;
   1668         auth_start_eap_session_req_msg_v01 eap_auth_start;
   1669         auth_start_eap_session_resp_msg_v01 eap_auth_start_resp;
   1670         auth_set_subscription_binding_req_msg_v01 sub_req_binding;
   1671         auth_set_subscription_binding_resp_msg_v01 sub_resp_binding;
   1672 
   1673         struct eap_method_type *m;
   1674         eap_identity_format_e identity_format = EAP_IDENTITY_ANNONYMOUS;
   1675         Boolean simEnabled = FALSE, akaEnabled = FALSE;
   1676         struct eap_peer_config *config = eap_get_config(eap_sm);
   1677         const char *realm_3gpp = "@wlan.mnc000.mcc000.3gppnetwork.org";
   1678         int sim_num;
   1679 
   1680         wpa_printf(MSG_ERROR, "eap_proxy: %s\n", __func__);
   1681         sim_num = config->sim_num - 1;
   1682         os_memset(&eap_auth_start, 0, sizeof(eap_auth_start));
   1683         os_memset(&eap_auth_start_resp, 0, sizeof(eap_auth_start_resp));
   1684 
   1685         eap_auth_start.user_id_len = 0;
   1686         m = config->eap_methods;
   1687 
   1688         if (sim_num >= MAX_NO_OF_SIM_SUPPORTED || sim_num < 0) {
   1689                 wpa_printf (MSG_ERROR, "eap_proxy: Invalid SIM selected sim by user = %d\n",
   1690                              sim_num+1);
   1691                 return FALSE;
   1692         }
   1693         wpa_printf(MSG_ERROR, "eap_proxy: User selected sim = %d\n", sim_num + 1);
   1694 
   1695         if (m != NULL) {
   1696                 for (idx = 0; m[idx].vendor != EAP_VENDOR_IETF ||
   1697                                 m[idx].method != EAP_TYPE_NONE; idx++) {
   1698                         if (m[idx].method == EAP_TYPE_AKA) {
   1699                                 akaEnabled = TRUE;
   1700                                 eap_auth_start.eap_method_mask_valid = 1;
   1701                                 eap_auth_start.eap_method_mask |= QMI_AUTH_EAP_METHOD_MASK_AKA_V01;
   1702                                 wpa_printf(MSG_ERROR, "eap_proxy: AKA Enabled\n");
   1703                         } else if (m[idx].method == EAP_TYPE_SIM) {
   1704                                 simEnabled = TRUE;
   1705                                 eap_auth_start.eap_method_mask_valid = 1;
   1706                                 eap_auth_start.eap_method_mask |= QMI_AUTH_EAP_METHOD_MASK_SIM_V01;
   1707                                 wpa_printf(MSG_ERROR, "eap_proxy: SIM Enabled\n");
   1708 #ifdef CONFIG_EAP_PROXY_AKA_PRIME
   1709                         } else if (m[idx].method == EAP_TYPE_AKA_PRIME) {
   1710                                 eap_auth_start.eap_method_mask_valid = 1;
   1711                                 eap_auth_start.eap_method_mask |=
   1712                                         QMI_AUTH_EAP_METHOD_MASK_AKA_PRIME_V01;
   1713                                 wpa_printf(MSG_ERROR, "eap_proxy: AKA Prime Enabled\n");
   1714 #endif /* CONFIG_EAP_PROXY_AKA_PRIME */
   1715                         }
   1716                 }
   1717         } else {
   1718                 wpa_printf(MSG_ERROR, "eap_proxy: eap_methods is NULL!\n");
   1719                 return FALSE;
   1720         }
   1721 
   1722         eap_auth_start.eap_method_mask_valid = 1;
   1723 
   1724         idx = 0;
   1725 #ifdef SIM_AKA_IMSI_RAW_ENABLED
   1726 
   1727         identity_format = EAP_IDENTITY_IMSI_RAW;
   1728         eap_auth_start.user_id_valid = 1;
   1729         wpa_printf(MSG_ERROR, "eap_proxy: EAP_IDENTITY_IMSI_RAW selected %d \n",
   1730                 eap_auth_start.user_id_len);
   1731 
   1732 #else /* SIM_AKA_IMSI_RAW_ENABLED */
   1733 
   1734         if (config->identity_len && config->identity != NULL) {
   1735                 for (idx = 0; idx < config->identity_len; idx++) {
   1736                         if (config->identity[idx] == 64) {
   1737                                 wpa_printf(MSG_ERROR, "eap_proxy: @ found \n");
   1738                                 mcc_idx = idx;
   1739                                 if ((mcc_idx + 18) > config->identity_len)
   1740                                         mcc_idx = 0;
   1741                                 else {
   1742                                         /* Looking for mnc and mcc pattern */
   1743                                         if (109 == config->identity[mcc_idx + 6] &&
   1744                                                 (110 == config->identity[mcc_idx + 7]) &&
   1745                                                 (99 == config->identity[mcc_idx + 8]) &&
   1746                                                 (109 == config->identity[mcc_idx + 13]) &&
   1747                                                 (99 == config->identity[mcc_idx + 14]) &&
   1748                                                 (99 == config->identity[mcc_idx + 15])) {
   1749                                                 mcc_idx += 9;
   1750                                         } else
   1751                                                 mcc_idx = 0;
   1752                                 }
   1753                                 break;
   1754                         }
   1755                 }
   1756 
   1757                 wpa_printf(MSG_ERROR, "eap_proxy: idx %d\n", idx);
   1758                 wpa_printf(MSG_ERROR, "eap_proxy: mcc idx %d\n", mcc_idx);
   1759 
   1760                 if (!idx && (config->identity_len == 1)) {
   1761                         /* config file : @ */
   1762                         config->identity_len = 0;
   1763                         identity_format = EAP_IDENTITY_IMSI_3GPP_REALM;
   1764                         wpa_printf(MSG_ERROR, "eap_proxy: EAP_IDENTITY_IMSI_3GPP_REALM "
   1765                                 "selected \n");
   1766                 } else if (idx && (idx < config->identity_len) && (config->identity != NULL)) {
   1767 
   1768                         /* config file : <>@<> or <>@<wlan.mnc000.mcc000.<>.<> */
   1769                         identity_len = config->identity_len;
   1770                         identity = os_malloc(config->identity_len);
   1771 
   1772                         if (NULL != identity) {
   1773                                 os_memset(identity, 0, config->identity_len);
   1774                                 os_memcpy(identity, config->identity,
   1775                                                 config->identity_len);
   1776                         }
   1777 
   1778                         /* To Do for 3GPP realm */
   1779                         identity_format = EAP_IDENTITY_CFG_3GPP_REALM;
   1780                         eap_auth_start.user_id_valid = 1;
   1781                         wpa_printf(MSG_ERROR, "eap_proxy: EAP_IDENTITY_CFG_3GPP_REALM "
   1782                                 "selected %d \n", eap_auth_start.user_id_len);
   1783 
   1784                 } else if ((idx == config->identity_len) && config->identity_len &&
   1785                                         (config->identity != NULL)) {
   1786 
   1787                         /* config file : <identity in RAW format >*/
   1788                         identity_len = config->identity_len;
   1789                         identity = os_malloc(config->identity_len);
   1790 
   1791                         if (NULL != identity) {
   1792                                 os_memset(identity, 0, config->identity_len);
   1793                                 os_memcpy(identity, config->identity,
   1794                                                 config->identity_len);
   1795                         }
   1796 
   1797                         identity_format = EAP_IDENTITY_CFG_RAW;
   1798                         eap_auth_start.user_id_valid = 1;
   1799                         wpa_printf(MSG_ERROR, "eap_proxy: EAP_IDENTITY_CFG_RAW selected %d \n",
   1800                                 eap_auth_start.user_id_len);
   1801                 } else if (!idx && mcc_idx) {
   1802 
   1803                         /* config file: @wlan.mnc000.mcc000.<>.<> */
   1804                         identity_len = config->identity_len;
   1805                         identity = os_malloc(config->identity_len);
   1806 
   1807                         if (NULL != identity) {
   1808                                 os_memset(identity, 0, config->identity_len);
   1809                                 os_memcpy(identity, config->identity,
   1810                                          config->identity_len);
   1811                         }
   1812 
   1813                         identity_format = EAP_IDENTITY_IMSI_3GPP_REALM;
   1814                         eap_auth_start.user_id_valid = 1;
   1815                         wpa_printf(MSG_ERROR, "eap_proxy: config EAP_IDENTITY_IMSI_3GPP_REALM "
   1816                                 "selected %d\n", eap_auth_start.user_id_len);
   1817                 }
   1818         } else {
   1819 
   1820                 if (config->anonymous_identity_len && config->anonymous_identity != NULL) {
   1821 
   1822                         eap_auth_start.eap_meta_identity_len = config->anonymous_identity_len;
   1823                         os_memcpy(&eap_auth_start.eap_meta_identity ,
   1824                                                 config->anonymous_identity ,
   1825                                                 config->anonymous_identity_len);
   1826 
   1827                         identity_format = EAP_IDENTITY_ANNONYMOUS;
   1828                         eap_auth_start.eap_meta_identity_valid = 1;
   1829                         wpa_printf(MSG_ERROR, "eap_proxy: EAP_IDENTITY_ANNONYMOUS selected user id "
   1830                                 "%d, annonymous %d\n", eap_auth_start.user_id_len,
   1831                                 eap_auth_start.eap_meta_identity_len);
   1832                 } else {
   1833                         /* config file doesn't contain any identity
   1834                                 generating IMSI@realm */
   1835                         identity_format = EAP_IDENTITY_IMSI_3GPP_REALM;
   1836                         eap_auth_start.user_id_valid = 1;
   1837                         wpa_printf(MSG_ERROR, "eap_proxy: EAP_IDENTITY_IMSI_3GPP_REALM id len %d\n",
   1838                                 eap_auth_start.user_id_len);
   1839                 }
   1840         }
   1841 #endif /* SIM_AKA_IMSI_RAW_ENABLED */
   1842         if (identity_format == EAP_IDENTITY_IMSI_3GPP_REALM ||
   1843                 identity_format == EAP_IDENTITY_IMSI_RAW || mcc_idx) {
   1844 
   1845                 wpa_printf(MSG_ERROR, "eap_proxy: EAP_IDENTITY_IMSI_3GPP_REALM is selected\n");
   1846                 if (!wpa_qmi_read_card_status(sim_num, eap_proxy->wpa_uim)) {
   1847                         wpa_printf(MSG_INFO, "eap_proxy: Read Card Status failed, return\n");
   1848                         if (NULL != identity) {
   1849                                 os_free(identity);
   1850                                 identity = NULL;
   1851                         }
   1852                         return FALSE;
   1853                 }
   1854 
   1855                 if (!wpa_qmi_read_card_imsi(sim_num, eap_proxy->wpa_uim)) {
   1856                         wpa_printf(MSG_INFO, "eap_proxy: Read Card IMSI failed, return\n");
   1857                         if (NULL != identity) {
   1858                                 os_free(identity);
   1859                                 identity = NULL;
   1860                         }
   1861                         return FALSE;
   1862                 }
   1863 
   1864                 if (imsi == NULL) {
   1865                         wpa_printf(MSG_INFO, "eap_proxy: IMSI not available, return\n");
   1866                         if (NULL != identity) {
   1867                                 os_free(identity);
   1868                                 identity = NULL;
   1869                         }
   1870                         return FALSE;
   1871                 } else {
   1872                         wpa_printf(MSG_ERROR, "eap_proxy: IMSI not NULL \n");
   1873                         if (NULL == identity)
   1874                                 wpa_printf(MSG_ERROR,
   1875                                         "eap_proxy: config file doesn't contain identity \n");
   1876                         else
   1877                                 wpa_printf(MSG_ERROR, "eap_proxy: config file contains identity\n");
   1878 
   1879                         wpa_printf(MSG_ERROR, "eap_proxy: eap_type: %d\n", eap_proxy->eap_type);
   1880 
   1881                         if (!idx) {
   1882 
   1883                                 /* IMSI is expected as username */
   1884                                 wpa_printf(MSG_ERROR, "eap_proxy:  username is not available in"
   1885                                         " config picking IMSI \n");
   1886 
   1887                                 if (config->identity_len > 1)
   1888                                         /* @realm provided in config */
   1889                                         imsi_identity =
   1890                                                 os_malloc(1 + IMSI_LENGTH + config->identity_len);
   1891                                 else if (identity_format == EAP_IDENTITY_IMSI_3GPP_REALM)
   1892                                         /* IMSI@realm not provided through config */
   1893                                         imsi_identity =
   1894                                                 os_malloc(1 + IMSI_LENGTH + os_strlen(realm_3gpp));
   1895                                 else
   1896                                         /* IMSI RAW */
   1897                                         imsi_identity = os_malloc(1 + IMSI_LENGTH);
   1898 
   1899                                 if (NULL == imsi_identity) {
   1900                                         wpa_printf(MSG_ERROR, "eap_proxy: Memory not available\n");
   1901                                         if (NULL != identity) {
   1902                                                 os_free(identity);
   1903                                                 identity = NULL;
   1904                                         }
   1905                                         return FALSE;
   1906                                 } else {
   1907                                         if (config->identity_len > 1)
   1908                                                 os_memset(imsi_identity, 0,
   1909                                                         (1 + IMSI_LENGTH + config->identity_len));
   1910                                         else if (identity_format == EAP_IDENTITY_IMSI_3GPP_REALM)
   1911                                                 os_memset(imsi_identity, 0,
   1912                                                         (1 + IMSI_LENGTH + os_strlen(realm_3gpp)));
   1913                                         else
   1914                                                 os_memset(imsi_identity, 0, (1 + IMSI_LENGTH));
   1915 
   1916                                         if (eap_proxy->eap_type == EAP_TYPE_SIM)
   1917                                                 imsi_identity[0] = '1';
   1918                                         else if (eap_proxy->eap_type == EAP_TYPE_AKA)
   1919                                                 imsi_identity[0] = '0';
   1920 #ifdef CONFIG_EAP_PROXY_AKA_PRIME
   1921                                         else if (eap_proxy->eap_type == EAP_TYPE_AKA_PRIME)
   1922                                                 imsi_identity[0] = '6';
   1923 #endif /* CONFIG_EAP_PROXY_AKA_PRIME */
   1924                                         else
   1925                                                 /* Default value is set as SIM */
   1926                                                 imsi_identity[0] = '1';
   1927 
   1928                                         /* copying IMSI value */
   1929                                         os_memcpy(imsi_identity + 1 , imsi , imsi_len_g);
   1930 
   1931                                         if (config->identity_len > 1 && NULL != identity) {
   1932                                                 /* copying realm tag */
   1933                                                 os_memcpy(imsi_identity + 1 + imsi_len_g , identity,
   1934                                                         config->identity_len);
   1935                                                 imsi_id_len = imsi_len_g + 1 + config->identity_len;
   1936                                                 os_free(identity);
   1937                                                 identity = NULL;
   1938                                         } else if(identity_format == EAP_IDENTITY_IMSI_3GPP_REALM) {
   1939                                                 /* realm is not available so append it */
   1940                                                 os_memcpy(imsi_identity + 1 + imsi_len_g,
   1941                                                         realm_3gpp, os_strlen(realm_3gpp));
   1942                                                 imsi_id_len = imsi_len_g + 1 +
   1943                                                         os_strlen(realm_3gpp);
   1944                                         } else
   1945                                                 /* IMSI RAW */
   1946                                                 imsi_id_len = imsi_len_g + 1;
   1947                                 }
   1948                         } else if (identity) {
   1949                                 /* idx is non-zero implies username available */
   1950                                 imsi_identity = identity;
   1951                                 imsi_id_len = config->identity_len;
   1952                         }
   1953                 }
   1954 
   1955                 if (identity_format == EAP_IDENTITY_IMSI_3GPP_REALM || mcc_idx) {
   1956 
   1957                         if (0 == idx) {
   1958                         /* id = @wlan.mnc000.mcc000.<>.<> realm exist
   1959                                 but need to insert mnc and mcc values */
   1960                                 idx = imsi_len_g + 1;
   1961                         }
   1962 
   1963                         if (imsi_identity != NULL) {
   1964                                 /* mcc valus */
   1965                                 imsi_identity[idx + 16] = imsi[0];
   1966                                 imsi_identity[idx + 17] = imsi[1];
   1967                                 imsi_identity[idx + 18] = imsi[2];
   1968                         }
   1969 
   1970                         /* mnc valus */
   1971                         mnc_len = card_mnc_len;
   1972                         wpa_printf(MSG_ERROR, "eap_proxy: card mnc len %d\n", card_mnc_len);
   1973 
   1974                         if ((mnc_len == 2) && (imsi_identity != NULL)) {
   1975                                 imsi_identity[idx + 9]  = '0';
   1976                                 imsi_identity[idx + 10] = imsi[3];
   1977                                 imsi_identity[idx + 11] = imsi[4];
   1978                         } else if ((mnc_len == 3) && (imsi_identity != NULL)) {
   1979                                 imsi_identity[idx + 9]  = imsi[3];
   1980                                 imsi_identity[idx + 10] = imsi[4];
   1981                                 imsi_identity[idx + 11] = imsi[5];
   1982                         }
   1983                         wpa_printf(MSG_ERROR, "eap_proxy:  Appending 3gpp realm\n ");
   1984                 }
   1985                 identity = imsi_identity;
   1986                 identity_len = imsi_id_len;
   1987                 eap_auth_start.user_id_valid = 1;
   1988         }
   1989 
   1990         eap_auth_start.user_id_len = identity_len;
   1991 
   1992         if(identity_len >= QMI_AUTH_EAP_IDENTITY_MAX_CHAR_V01)
   1993         {
   1994                 wpa_printf(MSG_ERROR, "eap_proxy: Invalid User Identity length =%d",identity_len);
   1995                 return FALSE;
   1996         }
   1997 
   1998         if(identity)
   1999         {
   2000                 memcpy(&eap_auth_start.user_id, identity, identity_len);
   2001                 eap_auth_start.user_id_valid = 1;
   2002         }
   2003 
   2004         wpa_printf(MSG_ERROR, "eap_proxy: eap auth user identity  - %20s length-%d\n ",
   2005                     eap_auth_start.user_id, eap_auth_start.user_id_len);
   2006 
   2007         if ( (sim_num < 0) || (sim_num >= MAX_NO_OF_SIM_SUPPORTED)) {
   2008                 wpa_printf(MSG_ERROR, "eap_proxy: SIM: Invalid SIM selected by "
   2009                             "User: Selected sim = %d\n", sim_num+1);
   2010                 return FALSE;
   2011         }
   2012 
   2013 
   2014         eap_proxy->user_selected_sim = sim_num;
   2015         wpa_printf(MSG_ERROR, "eap_proxy: SIM selected by User: Selected sim = %d\n",
   2016                     eap_proxy->user_selected_sim+1);
   2017 
   2018         memset(&sub_req_binding, 0, sizeof(auth_set_subscription_binding_req_msg_v01));
   2019         memset(&sub_resp_binding, 0, sizeof(auth_set_subscription_binding_resp_msg_v01));
   2020 #ifdef CONFIG_EAP_PROXY_DUAL_SIM
   2021         if (sim_num == 0) {
   2022                 sub_req_binding.bind_subs = AUTH_PRIMARY_SUBS_V01;
   2023                 qmiRetCode = qmi_client_send_msg_sync(eap_proxy->qmi_auth_svc_client_ptr[sim_num],
   2024                                 QMI_AUTH_SET_SUBSCRIPTION_BINDING_REQ_V01,
   2025                                                 (void *) &sub_req_binding,
   2026                                                 sizeof(auth_set_subscription_binding_req_msg_v01),
   2027                                                 (void *) &sub_resp_binding,
   2028                                                 sizeof(auth_set_subscription_binding_resp_msg_v01),
   2029                                                 WPA_UIM_QMI_DEFAULT_TIMEOUT);
   2030 
   2031                 if ((QMI_NO_ERR != qmiRetCode ||
   2032                      sub_resp_binding.resp.result != QMI_RESULT_SUCCESS_V01 ) &&
   2033                     (QMI_ERR_OP_DEVICE_UNSUPPORTED_V01 != sub_resp_binding.resp.error)) {
   2034                         wpa_printf(MSG_ERROR, "QMI-ERROR Unable to get the qmi_auth_set_subscriptio"
   2035                                 "n_binding for sim 1; error_ret=%d; error_code=%d\n", qmiRetCode,
   2036                                 sub_resp_binding.resp.error);
   2037                         return FALSE;
   2038                 }
   2039                 wpa_printf (MSG_ERROR, "eap_proxy: Binded with PRIMARY Subscription\n");
   2040         } else if (sim_num == 1) {
   2041                 sub_req_binding.bind_subs = AUTH_SECONDARY_SUBS_V01;
   2042                 qmiRetCode = qmi_client_send_msg_sync(eap_proxy->qmi_auth_svc_client_ptr[sim_num],
   2043                                 QMI_AUTH_SET_SUBSCRIPTION_BINDING_REQ_V01,
   2044                                                 (void *) &sub_req_binding,
   2045                                                 sizeof(auth_set_subscription_binding_req_msg_v01),
   2046                                                 (void *) &sub_resp_binding,
   2047                                                 sizeof(auth_set_subscription_binding_resp_msg_v01),
   2048                                                 WPA_UIM_QMI_DEFAULT_TIMEOUT);
   2049 
   2050                 if (QMI_NO_ERR != qmiRetCode ||
   2051                     sub_resp_binding.resp.result != QMI_RESULT_SUCCESS_V01 ) {
   2052                         wpa_printf(MSG_ERROR, "QMI-ERROR Unable to get the qmi_auth_set_subscriptio"
   2053                                 "n_binding for sim 2; error_ret=%d; error_code=%d\n", qmiRetCode,
   2054                                 sub_resp_binding.resp.error);
   2055                         return FALSE;
   2056                 }
   2057 
   2058                 wpa_printf (MSG_ERROR, "eap_proxy: Binded with SECONDARY Subscription\n");
   2059         } else {
   2060                 wpa_printf(MSG_ERROR, "eap_proxy: Invalid SIM selected by User: "
   2061                         "Selected sim = %d\n", sim_num+1);
   2062                 return FALSE;
   2063         }
   2064 #endif
   2065         if (TRUE == eap_proxy->eap_auth_session_flag[sim_num]) {
   2066                 if(eap_auth_end_eap_session(eap_proxy->qmi_auth_svc_client_ptr[sim_num]) < 0) {
   2067                         wpa_printf(MSG_ERROR, "eap_proxy: Unable to end the EAP session;"
   2068                                                 " sim_num%d;", sim_num);
   2069                         }
   2070                         eap_proxy->eap_auth_session_flag[sim_num] = FALSE;
   2071         }
   2072 
   2073         if (FALSE == eap_proxy->eap_auth_session_flag[sim_num]) {
   2074                         wpa_printf(MSG_ERROR, "eap_proxy: eap_auth_start values\n");
   2075                         wpa_printf(MSG_ERROR, "eap_proxy: eap_auth_start.eap_method_mask = %d\n",
   2076                                 eap_auth_start.eap_method_mask);
   2077                         wpa_printf(MSG_ERROR, "eap_proxy: eap_auth_start.user_id_len = %d\n",
   2078                                 eap_auth_start.user_id_len);
   2079                         wpa_printf(MSG_ERROR, "eap_proxy: eap_auth_start.eap_meta_id_len = %d\n",
   2080                                 eap_auth_start.eap_meta_identity_len);
   2081                         wpa_printf(MSG_ERROR, "eap_auth_start.eap_sim_aka_algo = %d\n",
   2082                                 eap_auth_start.eap_sim_aka_algo);
   2083         qmiRetCode = qmi_client_send_msg_sync(eap_proxy->qmi_auth_svc_client_ptr[sim_num],
   2084                                                 QMI_AUTH_START_EAP_SESSION_REQ_V01,
   2085                                                 (void *) &eap_auth_start,
   2086                                                 sizeof(auth_start_eap_session_req_msg_v01),
   2087                                                 (void *) &eap_auth_start_resp,
   2088                                                 sizeof(auth_start_eap_session_resp_msg_v01),
   2089                                                 WPA_UIM_QMI_DEFAULT_TIMEOUT);
   2090         if (QMI_NO_ERR != qmiRetCode ||
   2091             eap_auth_start_resp.resp.result != QMI_RESULT_SUCCESS_V01) {
   2092                 wpa_printf(MSG_ERROR, " QMI-ERROR Unable to start the EAP session;"
   2093                            " error_ret=%d; qmi_err=%d\n", qmiRetCode,
   2094                            eap_auth_start_resp.resp.error);
   2095                 if(eap_auth_start.eap_method_mask == QMI_AUTH_EAP_METHOD_MASK_AKA_PRIME_V01 &&
   2096                    eap_auth_start_resp.resp.error == QMI_ERR_INVALID_ARG_V01)
   2097                         wpa_printf(MSG_ERROR, "QMI-ERROR AKA' not supported\n");
   2098 
   2099                 return FALSE;
   2100                 }
   2101                 eap_proxy->eap_auth_session_flag[sim_num] = TRUE;
   2102                 eap_proxy->notification_code = 0;
   2103                 eap_proxy->qmi_state = QMI_STATE_IDLE;
   2104                 wpa_printf(MSG_ERROR, "eap_proxy: EAP session started"
   2105                            " error_ret=%d; Resp=%d\n", qmiRetCode,
   2106                             eap_auth_start_resp.resp.error);
   2107         }
   2108 
   2109         return TRUE;
   2110 }
   2111 
   2112 
   2113 
   2114 #ifdef CONFIG_CTRL_IFACE
   2115 
   2116 /**
   2117  * eap_proxyl_sm_get_status - Get EAP state machine status
   2118  * @sm: Pointer to EAP state machine allocated with eap_sm_init()
   2119  * @buf: Buffer for status information
   2120  * @buflen: Maximum buffer length
   2121  * @verbose: Whether to include verbose status information
   2122  * Returns: Number of bytes written to buf.
   2123  *
   2124  * Query EAP state machine for status information. This function fills in a
   2125  * text area with current status information from the EAPOL state machine. If
   2126  * the buffer (buf) is not large enough, status information will be truncated
   2127  * to fit the buffer.
   2128  */
   2129 int eap_proxy_sm_get_status(struct eap_proxy_sm *sm, char *buf, size_t buflen,
   2130                             int verbose)
   2131 {
   2132         int len, ret;
   2133 
   2134         if (sm == NULL)
   2135                 return 0;
   2136 
   2137         len = os_snprintf(buf, buflen, "eap_proxy: EAP state=%s\n",
   2138                           eap_proxy_sm_state_txt(sm->proxy_state));
   2139         if (len < 0 || (size_t)len >= buflen)
   2140                 return 0;
   2141 
   2142         if (sm->eap_type != EAP_TYPE_NONE) {
   2143                 char name[8];
   2144 
   2145                 if (sm->eap_type == EAP_TYPE_SIM)
   2146                         os_strlcpy(name, "SIM", 4);
   2147                 else if (sm->eap_type == EAP_TYPE_AKA)
   2148                         os_strlcpy(name, "AKA", 4);
   2149                 else if (sm->eap_type == EAP_TYPE_AKA_PRIME)
   2150                         os_strlcpy(name, "AKA'", 5);
   2151                 else
   2152                         os_strlcpy(name, "Unknown", 8);
   2153 
   2154                 ret = os_snprintf(buf + len, buflen - len,
   2155                                 "selectedMethod=%d (EAP-%s)\n",
   2156                                         sm->eap_type, name);
   2157                 if (ret < 0 || (size_t)ret >= buflen - len)
   2158                         return len;
   2159                 len += ret;
   2160         }
   2161 
   2162         return len;
   2163 }
   2164 
   2165 
   2166 static const char *eap_proxy_sm_state_txt(int state)
   2167 {
   2168         switch (state) {
   2169         case EAP_PROXY_INITIALIZE:
   2170                 return "INITIALIZE";
   2171         case EAP_PROXY_DISABLED:
   2172                 return "DISABLED";
   2173         case EAP_PROXY_IDLE:
   2174                 return "IDLE";
   2175         case EAP_PROXY_RECEIVED:
   2176                 return "RECEIVED";
   2177         case EAP_PROXY_GET_METHOD:
   2178                 return "GET_METHOD";
   2179         case EAP_PROXY_METHOD:
   2180                 return "METHOD";
   2181         case EAP_PROXY_SEND_RESPONSE:
   2182                 return "SEND_RESPONSE";
   2183         case EAP_PROXY_DISCARD:
   2184                 return "DISCARD";
   2185         case EAP_PROXY_IDENTITY:
   2186                 return "IDENTITY";
   2187         case EAP_PROXY_NOTIFICATION:
   2188                 return "NOTIFICATION";
   2189         case EAP_PROXY_RETRANSMIT:
   2190                 return "RETRANSMIT";
   2191         case EAP_PROXY_AUTH_SUCCESS:
   2192                 return "SUCCESS";
   2193         case EAP_PROXY_AUTH_FAILURE:
   2194                 return "FAILURE";
   2195         default:
   2196                 return "UNKNOWN";
   2197         }
   2198 }
   2199 #endif /* CONFIG_CTRL_IFACE */
   2200 
   2201 
   2202 /**
   2203  * eap_proxy_get_mcc_mnc - Get MCC/MNC
   2204  * @imsi_buf: Buffer for returning IMSI
   2205  * @imsi_len: Buffer for returning IMSI length
   2206  * Returns: MNC length (2 or 3) or -1 on error
   2207  */
   2208 int eap_proxy_get_imsi(struct eap_proxy_sm *eap_proxy, char *imsi_buf,
   2209                         size_t *imsi_len)
   2210 {
   2211 #ifdef SIM_AKA_IDENTITY_IMSI
   2212         int mnc_len;
   2213         int sim_num = eap_proxy->user_selected_sim;
   2214 
   2215         if ((eap_proxy->proxy_state == EAP_PROXY_DISABLED) ||
   2216             (eap_proxy->proxy_state == EAP_PROXY_INITIALIZE)) {
   2217                 wpa_printf(MSG_ERROR, "eap_proxy:%s: Not initialized\n", __func__);
   2218                 return FALSE;
   2219         }
   2220         if (!wpa_qmi_read_card_status(sim_num, eap_proxy->wpa_uim)) {
   2221         wpa_printf(MSG_INFO, "eap_proxy: Card not ready");
   2222                 return -1;
   2223         }
   2224 
   2225         if (!wpa_qmi_read_card_imsi(sim_num, eap_proxy->wpa_uim) || imsi == NULL) {
   2226                 wpa_printf(MSG_INFO, "eap_proxy: Failed to read card IMSI");
   2227                 return -1;
   2228         }
   2229 
   2230         *imsi_len = os_strlen(imsi);
   2231         os_memcpy(imsi_buf, imsi, *imsi_len + 1);
   2232 
   2233         mnc_len = card_mnc_len;
   2234         if (mnc_len < 2 || mnc_len > 3)
   2235                 mnc_len = 3; /* Default to 3 if MNC length is unknown */
   2236 
   2237         os_free(imsi);
   2238         imsi = NULL;
   2239 
   2240         return mnc_len;
   2241 #else /* SIM_AKA_IDENTITY_IMSI */
   2242         return -1;
   2243 #endif /* SIM_AKA_IDENTITY_IMSI */
   2244 }
   2245 
   2246 int eap_proxy_notify_config(struct eap_proxy_sm *eap_proxy,
   2247                             struct eap_peer_config *config)
   2248 {
   2249         int ret_val;
   2250 
   2251         wpa_printf(MSG_ERROR, "eap_proxy: eap_proxy_notify_config\n");
   2252         if (!eap_proxy) {
   2253                 wpa_printf(MSG_ERROR, "eap_proxy: is NULL");
   2254                 return FALSE;
   2255         }
   2256 
   2257         if ((eap_proxy->proxy_state == EAP_PROXY_DISABLED) ||
   2258             (eap_proxy->proxy_state == EAP_PROXY_INITIALIZE)) {
   2259                 wpa_printf(MSG_ERROR, "eap_proxy: Not initialized\n");
   2260                 return FALSE;
   2261         }
   2262 
   2263         if ( config && eap_proxy_allowed_method(config, EAP_VENDOR_IETF,
   2264                         EAP_TYPE_SIM)) {
   2265                 eap_proxy->eap_type =  EAP_TYPE_SIM;
   2266                 ret_val = TRUE;
   2267         } else if ( config && eap_proxy_allowed_method(config, EAP_VENDOR_IETF,
   2268                                 EAP_TYPE_AKA)) {
   2269                 eap_proxy->eap_type =  EAP_TYPE_AKA;
   2270                 ret_val = TRUE;
   2271         } else if ( config && eap_proxy_allowed_method(config, EAP_VENDOR_IETF,
   2272                                 EAP_TYPE_AKA_PRIME)) {
   2273                 eap_proxy->eap_type =  EAP_TYPE_AKA_PRIME;
   2274                 ret_val = TRUE;
   2275         } else
   2276                 ret_val = FALSE;
   2277 
   2278         return ret_val;
   2279 }
   2280 
   2281 int eap_proxy_allowed_method(struct eap_peer_config *config, int vendor,
   2282                               u32 method)
   2283 {
   2284         int i;
   2285         struct eap_method_type *m;
   2286 
   2287         wpa_printf(MSG_ERROR, "eap_proxy: eap_proxy_allowed_method");
   2288         if (config == NULL || config->eap_methods == NULL)
   2289                 return -1;
   2290 
   2291         m = config->eap_methods;
   2292         for (i = 0; m[i].vendor != EAP_VENDOR_IETF ||
   2293                      m[i].method != EAP_TYPE_NONE; i++) {
   2294                 if (m[i].vendor == vendor && m[i].method == method)
   2295                         return 1;
   2296         }
   2297         return 0;
   2298 }
   2299 
   2300 #endif  /* CONFIG_EAP_PROXY */
   2301