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_oc.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
gettid(void)88 static inline pid_t gettid(void)
89 {
90 return syscall(SYS_gettid);
91 }
92 #else
gettid(void)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
wpa_qmi_client_indication_cb(qmi_client_type user_handle,unsigned long msg_id,unsigned char * ind_buf_ptr,int ind_buf_len,void * ind_cb_data)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
wpa_qmi_register_auth_inds(struct eap_proxy_sm * eap_proxy)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
wpa_qmi_register_events(int sim_num,wpa_uim_struct_type * wpa_uim)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
wpa_qmi_read_card_status(int sim_num,wpa_uim_struct_type * wpa_uim)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
check_for_3_digit()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
wpa_qmi_read_card_imsi(int sim_num,wpa_uim_struct_type * wpa_uim)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
eap_modem_compatible(struct dev_info * mdm_detect_info)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
wpa_qmi_register_notification(void * eloop_ctx,void * timeout_ctx)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
wpa_qmi_handle_ssr(qmi_client_type user_handle,qmi_client_error_type error,void * err_cb_data)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
exit_proxy_init(int signum)687 static void exit_proxy_init(int signum)
688 {
689 pthread_exit(NULL);
690 }
691
eap_proxy_post_init(struct eap_proxy_sm * eap_proxy)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
eap_auth_end_eap_session(qmi_client_type qmi_auth_svc_client_ptr)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
eap_proxy_schedule_thread(void * eloop_ctx,void * timeout_ctx)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 *
eap_proxy_init(void * eapol_ctx,const struct eapol_callbacks * eapol_cb,void * msg_ctx)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
eap_proxy_qmi_deinit(struct eap_proxy_sm * eap_proxy)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
eap_proxy_deinit(struct eap_proxy_sm * eap_proxy)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 */
handle_qmi_eap_ind(qmi_client_type user_handle,unsigned int msg_id,void * ind_buf,unsigned int ind_buf_len,void * ind_cb_data)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 */
handle_qmi_eap_reply(qmi_client_type userHandle,unsigned int msg_id,void * resp_c_struct,unsigned int resp_c_struct_len,void * userData,qmi_client_error_type sysErrCode)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
eap_proxy_process(struct eap_proxy_sm * eap_proxy,u8 * eapReqData,int eapReqDataLen,struct eap_sm * eap_sm)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
eap_proxy_getKey(struct eap_proxy_sm * eap_proxy)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 */
eap_proxy_key_available(struct eap_proxy_sm * sm)1443 int eap_proxy_key_available(struct eap_proxy_sm *sm)
1444 {
1445 return sm ? sm->iskey_valid : 0;
1446 }
1447
1448
eap_proxy_is_state_changed(struct eap_proxy_sm * sm)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 */
eap_proxy_get_eapKeyData(struct eap_proxy_sm * sm,size_t * len)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 */
eap_proxy_get_eapRespData(struct eap_proxy_sm * eap_proxy)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
eap_proxy_qmi_response_wait(struct eap_proxy_sm * eap_proxy)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
eap_proxy_eapol_sm_set_bool(struct eap_proxy_sm * sm,enum eapol_bool_var var,Boolean value)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
eap_proxy_eapol_sm_get_bool(struct eap_proxy_sm * sm,enum eapol_bool_var var)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
eap_proxy_sm_step(struct eap_proxy_sm * sm,struct eap_sm * eap_sm)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
eap_proxy_packet_update(struct eap_proxy_sm * eap_proxy,u8 * eapReqData,int eapReqDataLen)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
eap_proxy_get_eap_session_id(struct eap_proxy_sm * sm,size_t * len)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
eap_proxy_get_emsk(struct eap_proxy_sm * sm,size_t * len)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
eap_proxy_sm_abort(struct eap_proxy_sm * sm)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
dump_buff(u8 * buff,int len)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 }
bin_to_hexchar(u8 ch)1649 static char bin_to_hexchar(u8 ch)
1650 {
1651 if (ch < 0x0a) {
1652 return ch + '0';
1653 }
1654 return ch + 'a' - 10;
1655 }
eap_proxy_build_identity(struct eap_proxy_sm * eap_proxy,u8 id,struct eap_sm * eap_sm)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 */
eap_proxy_sm_get_status(struct eap_proxy_sm * sm,char * buf,size_t buflen,int verbose)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
eap_proxy_sm_state_txt(int state)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 */
eap_proxy_get_imsi(struct eap_proxy_sm * eap_proxy,char * imsi_buf,size_t * imsi_len)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
eap_proxy_notify_config(struct eap_proxy_sm * eap_proxy,struct eap_peer_config * config)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
eap_proxy_allowed_method(struct eap_peer_config * config,int vendor,u32 method)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