eap_server_sim.c revision c5ec7f57ead87efa365800228aa0b09a12d9e6c4
18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* 28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * hostapd / EAP-SIM (RFC 4186) 38d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Copyright (c) 2005-2008, Jouni Malinen <j@w1.fi> 48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 5c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * This software may be distributed under the terms of the BSD license. 6c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * See README for more details. 78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "includes.h" 108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common.h" 128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/random.h" 138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eap_server/eap_i.h" 148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eap_common/eap_sim_common.h" 158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eap_server/eap_sim_db.h" 168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct eap_sim_data { 198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 mk[EAP_SIM_MK_LEN]; 208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 nonce_mt[EAP_SIM_NONCE_MT_LEN]; 218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 nonce_s[EAP_SIM_NONCE_S_LEN]; 228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 k_aut[EAP_SIM_K_AUT_LEN]; 238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 k_encr[EAP_SIM_K_ENCR_LEN]; 248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 msk[EAP_SIM_KEYING_DATA_LEN]; 258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 emsk[EAP_EMSK_LEN]; 268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 kc[EAP_SIM_MAX_CHAL][EAP_SIM_KC_LEN]; 278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 sres[EAP_SIM_MAX_CHAL][EAP_SIM_SRES_LEN]; 288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 rand[EAP_SIM_MAX_CHAL][GSM_RAND_LEN]; 298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int num_chal; 308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt enum { 318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt START, CHALLENGE, REAUTH, NOTIFICATION, SUCCESS, FAILURE 328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } state; 338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *next_pseudonym; 348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *next_reauth_id; 358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 counter; 368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_reauth *reauth; 378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 notification; 388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int use_result_ind; 398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}; 408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const char * eap_sim_state_txt(int state) 438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (state) { 458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case START: 468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "START"; 478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case CHALLENGE: 488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "CHALLENGE"; 498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case REAUTH: 508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "REAUTH"; 518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case SUCCESS: 528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "SUCCESS"; 538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case FAILURE: 548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "FAILURE"; 558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case NOTIFICATION: 568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "NOTIFICATION"; 578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "Unknown?!"; 598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_sim_state(struct eap_sim_data *data, int state) 648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-SIM: %s -> %s", 668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_state_txt(data->state), 678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_state_txt(state)); 688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->state = state; 698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void * eap_sim_init(struct eap_sm *sm) 738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_data *data; 758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->eap_sim_db_priv == NULL) { 778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "EAP-SIM: eap_sim_db not configured"); 788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data = os_zalloc(sizeof(*data)); 828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data == NULL) 838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->state = START; 858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return data; 878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_sim_reset(struct eap_sm *sm, void *priv) 918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_data *data = priv; 938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data->next_pseudonym); 948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data->next_reauth_id); 958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data); 968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_sim_build_start(struct eap_sm *sm, 1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_data *data, u8 id) 1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_msg *msg; 1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 ver[2]; 1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-SIM: Generating Start"); 1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = eap_sim_msg_init(EAP_CODE_REQUEST, id, EAP_TYPE_SIM, 1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_SIM_SUBTYPE_START); 1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_sim_db_identity_known(sm->eap_sim_db_priv, sm->identity, 1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->identity_len)) { 1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " AT_PERMANENT_ID_REQ"); 1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_add(msg, EAP_SIM_AT_PERMANENT_ID_REQ, 0, NULL, 0); 1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * RFC 4186, Chap. 4.2.4 recommends that identity from EAP is 1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * ignored and the SIM/Start is used to request the identity. 1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " AT_ANY_ID_REQ"); 1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_add(msg, EAP_SIM_AT_ANY_ID_REQ, 0, NULL, 0); 1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " AT_VERSION_LIST"); 1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ver[0] = 0; 1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ver[1] = EAP_SIM_VERSION; 1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_add(msg, EAP_SIM_AT_VERSION_LIST, sizeof(ver), 1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ver, sizeof(ver)); 1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return eap_sim_msg_finish(msg, NULL, NULL, 0); 1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_sim_build_encr(struct eap_sm *sm, struct eap_sim_data *data, 1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_msg *msg, u16 counter, 1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *nonce_s) 1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data->next_pseudonym); 1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->next_pseudonym = 1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_db_get_next_pseudonym(sm->eap_sim_db_priv, 0); 1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data->next_reauth_id); 1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->counter <= EAP_SIM_MAX_FAST_REAUTHS) { 1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->next_reauth_id = 1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_db_get_next_reauth_id(sm->eap_sim_db_priv, 0); 1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-SIM: Max fast re-authentication " 1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "count exceeded - force full authentication"); 1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->next_reauth_id = NULL; 1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->next_pseudonym == NULL && data->next_reauth_id == NULL && 1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt counter == 0 && nonce_s == NULL) 1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " AT_IV"); 1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " AT_ENCR_DATA"); 1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_add_encr_start(msg, EAP_SIM_AT_IV, EAP_SIM_AT_ENCR_DATA); 1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (counter > 0) { 1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " *AT_COUNTER (%u)", counter); 1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_add(msg, EAP_SIM_AT_COUNTER, counter, NULL, 0); 1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (nonce_s) { 1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " *AT_NONCE_S"); 1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_add(msg, EAP_SIM_AT_NONCE_S, 0, nonce_s, 1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_SIM_NONCE_S_LEN); 1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->next_pseudonym) { 1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " *AT_NEXT_PSEUDONYM (%s)", 1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->next_pseudonym); 1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_add(msg, EAP_SIM_AT_NEXT_PSEUDONYM, 1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_strlen(data->next_pseudonym), 1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (u8 *) data->next_pseudonym, 1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_strlen(data->next_pseudonym)); 1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->next_reauth_id) { 1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " *AT_NEXT_REAUTH_ID (%s)", 1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->next_reauth_id); 1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_add(msg, EAP_SIM_AT_NEXT_REAUTH_ID, 1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_strlen(data->next_reauth_id), 1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (u8 *) data->next_reauth_id, 1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_strlen(data->next_reauth_id)); 1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_sim_msg_add_encr_end(msg, data->k_encr, EAP_SIM_AT_PADDING)) { 1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "EAP-SIM: Failed to encrypt " 1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "AT_ENCR_DATA"); 1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_sim_build_challenge(struct eap_sm *sm, 1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_data *data, 1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 id) 1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_msg *msg; 1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-SIM: Generating Challenge"); 2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = eap_sim_msg_init(EAP_CODE_REQUEST, id, EAP_TYPE_SIM, 2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_SIM_SUBTYPE_CHALLENGE); 2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " AT_RAND"); 2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_add(msg, EAP_SIM_AT_RAND, 0, (u8 *) data->rand, 2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->num_chal * GSM_RAND_LEN); 2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_sim_build_encr(sm, data, msg, 0, NULL)) { 2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_free(msg); 2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->eap_sim_aka_result_ind) { 2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " AT_RESULT_IND"); 2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_add(msg, EAP_SIM_AT_RESULT_IND, 0, NULL, 0); 2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " AT_MAC"); 2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC); 2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return eap_sim_msg_finish(msg, data->k_aut, data->nonce_mt, 2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_SIM_NONCE_MT_LEN); 2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_sim_build_reauth(struct eap_sm *sm, 2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_data *data, u8 id) 2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_msg *msg; 2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-SIM: Generating Re-authentication"); 2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (random_get_bytes(data->nonce_s, EAP_SIM_NONCE_S_LEN)) 2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_MSGDUMP, "EAP-SIM: NONCE_S", 2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->nonce_s, EAP_SIM_NONCE_S_LEN); 2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_derive_keys(data->mk, data->k_encr, data->k_aut, data->msk, 2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->emsk); 2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_derive_keys_reauth(data->counter, sm->identity, 2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->identity_len, data->nonce_s, data->mk, 2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->msk, data->emsk); 2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = eap_sim_msg_init(EAP_CODE_REQUEST, id, EAP_TYPE_SIM, 2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_SIM_SUBTYPE_REAUTHENTICATION); 2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_sim_build_encr(sm, data, msg, data->counter, data->nonce_s)) { 2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_free(msg); 2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->eap_sim_aka_result_ind) { 2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " AT_RESULT_IND"); 2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_add(msg, EAP_SIM_AT_RESULT_IND, 0, NULL, 0); 2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " AT_MAC"); 2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC); 2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return eap_sim_msg_finish(msg, data->k_aut, NULL, 0); 2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_sim_build_notification(struct eap_sm *sm, 2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_data *data, 2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 id) 2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_msg *msg; 2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-SIM: Generating Notification"); 2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = eap_sim_msg_init(EAP_CODE_REQUEST, id, EAP_TYPE_SIM, 2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_SIM_SUBTYPE_NOTIFICATION); 2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " AT_NOTIFICATION (%d)", data->notification); 2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_add(msg, EAP_SIM_AT_NOTIFICATION, data->notification, 2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NULL, 0); 2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->use_result_ind) { 2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->reauth) { 2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " AT_IV"); 2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " AT_ENCR_DATA"); 2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_add_encr_start(msg, EAP_SIM_AT_IV, 2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_SIM_AT_ENCR_DATA); 2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " *AT_COUNTER (%u)", 2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->counter); 2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_add(msg, EAP_SIM_AT_COUNTER, data->counter, 2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NULL, 0); 2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_sim_msg_add_encr_end(msg, data->k_encr, 2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_SIM_AT_PADDING)) { 2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "EAP-SIM: Failed to " 2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "encrypt AT_ENCR_DATA"); 2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_free(msg); 2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " AT_MAC"); 2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC); 2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return eap_sim_msg_finish(msg, data->k_aut, NULL, 0); 2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_sim_buildReq(struct eap_sm *sm, void *priv, u8 id) 3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_data *data = priv; 3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (data->state) { 3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case START: 3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return eap_sim_build_start(sm, data, id); 3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case CHALLENGE: 3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return eap_sim_build_challenge(sm, data, id); 3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case REAUTH: 3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return eap_sim_build_reauth(sm, data, id); 3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case NOTIFICATION: 3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return eap_sim_build_notification(sm, data, id); 3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-SIM: Unknown state %d in " 3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "buildReq", data->state); 3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic Boolean eap_sim_check(struct eap_sm *sm, void *priv, 3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *respData) 3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_data *data = priv; 3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos; 3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len; 3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 subtype; 3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_SIM, respData, &len); 3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos == NULL || len < 3) { 3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-SIM: Invalid frame"); 3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return TRUE; 3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt subtype = *pos; 3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (subtype == EAP_SIM_SUBTYPE_CLIENT_ERROR) 3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return FALSE; 3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (data->state) { 3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case START: 3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (subtype != EAP_SIM_SUBTYPE_START) { 3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-SIM: Unexpected response " 3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "subtype %d", subtype); 3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return TRUE; 3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case CHALLENGE: 3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (subtype != EAP_SIM_SUBTYPE_CHALLENGE) { 3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-SIM: Unexpected response " 3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "subtype %d", subtype); 3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return TRUE; 3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case REAUTH: 3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (subtype != EAP_SIM_SUBTYPE_REAUTHENTICATION) { 3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-SIM: Unexpected response " 3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "subtype %d", subtype); 3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return TRUE; 3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case NOTIFICATION: 3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (subtype != EAP_SIM_SUBTYPE_NOTIFICATION) { 3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-SIM: Unexpected response " 3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "subtype %d", subtype); 3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return TRUE; 3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 3698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-SIM: Unexpected state (%d) for " 3708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "processing a response", data->state); 3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return TRUE; 3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return FALSE; 3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_sim_supported_ver(struct eap_sim_data *data, int version) 3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return version == EAP_SIM_VERSION; 3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_sim_process_start(struct eap_sm *sm, 3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_data *data, 3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *respData, 3878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_attrs *attr) 3888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *identity; 3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t identity_len; 3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 ver_list[2]; 3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-SIM: Receive start response"); 3948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (attr->identity) { 3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(sm->identity); 3978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->identity = os_malloc(attr->identity_len); 3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->identity) { 3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(sm->identity, attr->identity, 4008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt attr->identity_len); 4018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->identity_len = attr->identity_len; 4028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt identity = NULL; 4068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt identity_len = 0; 4078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->identity && sm->identity_len > 0 && 4098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->identity[0] == EAP_SIM_PERMANENT_PREFIX) { 4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt identity = sm->identity; 4118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt identity_len = sm->identity_len; 4128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 4138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt identity = eap_sim_db_get_permanent(sm->eap_sim_db_priv, 4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->identity, 4158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->identity_len, 4168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &identity_len); 4178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (identity == NULL) { 4188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->reauth = eap_sim_db_get_reauth_entry( 4198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->eap_sim_db_priv, sm->identity, 4208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->identity_len); 4218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->reauth) { 4228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-SIM: Using fast " 4238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "re-authentication"); 4248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt identity = data->reauth->identity; 4258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt identity_len = data->reauth->identity_len; 4268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->counter = data->reauth->counter; 4278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(data->mk, data->reauth->mk, 4288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_SIM_MK_LEN); 4298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (identity == NULL) { 4348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-SIM: Could not get proper permanent" 4358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " user name"); 4368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_state(data, FAILURE); 4378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 4388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, "EAP-SIM: Identity", 4418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt identity, identity_len); 4428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->reauth) { 4448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_state(data, REAUTH); 4458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 4468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (attr->nonce_mt == NULL || attr->selected_version < 0) { 4498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-SIM: Start/Response missing " 4508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "required attributes"); 4518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_state(data, FAILURE); 4528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 4538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!eap_sim_supported_ver(data, attr->selected_version)) { 4568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-SIM: Peer selected unsupported " 4578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "version %d", attr->selected_version); 4588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_state(data, FAILURE); 4598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 4608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->counter = 0; /* reset re-auth counter since this is full auth */ 4638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->reauth = NULL; 4648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->num_chal = eap_sim_db_get_gsm_triplets( 4668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->eap_sim_db_priv, identity, identity_len, 4678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_SIM_MAX_CHAL, 4688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (u8 *) data->rand, (u8 *) data->kc, (u8 *) data->sres, sm); 4698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->num_chal == EAP_SIM_DB_PENDING) { 4708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-SIM: GSM authentication triplets " 4718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "not yet available - pending request"); 4728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->method_pending = METHOD_PENDING_WAIT; 4738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 4748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->num_chal < 2) { 4768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-SIM: Failed to get GSM " 4778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "authentication triplets for the peer"); 4788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_state(data, FAILURE); 4798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 4808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt identity_len = sm->identity_len; 4838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (identity_len > 0 && sm->identity[identity_len - 1] == '\0') { 4848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-SIM: Workaround - drop last null " 4858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "character from identity"); 4868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt identity_len--; 4878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, "EAP-SIM: Identity for MK derivation", 4898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->identity, identity_len); 4908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(data->nonce_mt, attr->nonce_mt, EAP_SIM_NONCE_MT_LEN); 4928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(ver_list, EAP_SIM_VERSION); 4938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_derive_mk(sm->identity, identity_len, attr->nonce_mt, 4948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt attr->selected_version, ver_list, sizeof(ver_list), 4958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->num_chal, (const u8 *) data->kc, data->mk); 4968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_derive_keys(data->mk, data->k_encr, data->k_aut, data->msk, 4978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->emsk); 4988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_state(data, CHALLENGE); 5008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_sim_process_challenge(struct eap_sm *sm, 5048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_data *data, 5058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *respData, 5068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_attrs *attr) 5078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *identity; 5098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t identity_len; 5108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (attr->mac == NULL || 5128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_verify_mac(data->k_aut, respData, attr->mac, 5138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (u8 *) data->sres, 5148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->num_chal * EAP_SIM_SRES_LEN)) { 5158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "EAP-SIM: Challenge message " 5168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "did not include valid AT_MAC"); 5178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_state(data, FAILURE); 5188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 5198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-SIM: Challenge response includes the " 5228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "correct AT_MAC"); 5238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->eap_sim_aka_result_ind && attr->result_ind) { 5248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->use_result_ind = 1; 5258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->notification = EAP_SIM_SUCCESS; 5268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_state(data, NOTIFICATION); 5278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else 5288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_state(data, SUCCESS); 5298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt identity = eap_sim_db_get_permanent(sm->eap_sim_db_priv, sm->identity, 5318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->identity_len, &identity_len); 5328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (identity == NULL) { 5338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt identity = sm->identity; 5348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt identity_len = sm->identity_len; 5358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->next_pseudonym) { 5388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_db_add_pseudonym(sm->eap_sim_db_priv, identity, 5398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt identity_len, 5408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->next_pseudonym); 5418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->next_pseudonym = NULL; 5428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->next_reauth_id) { 5448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_db_add_reauth(sm->eap_sim_db_priv, identity, 5458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt identity_len, 5468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->next_reauth_id, data->counter + 1, 5478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->mk); 5488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->next_reauth_id = NULL; 5498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_sim_process_reauth(struct eap_sm *sm, 5548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_data *data, 5558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *respData, 5568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_attrs *attr) 5578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_attrs eattr; 5598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *decrypted = NULL; 5608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *identity, *id2; 5618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t identity_len, id2_len; 5628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (attr->mac == NULL || 5648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_verify_mac(data->k_aut, respData, attr->mac, data->nonce_s, 5658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_SIM_NONCE_S_LEN)) { 5668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "EAP-SIM: Re-authentication message " 5678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "did not include valid AT_MAC"); 5688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 5698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (attr->encr_data == NULL || attr->iv == NULL) { 5728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "EAP-SIM: Reauthentication " 5738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "message did not include encrypted data"); 5748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 5758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt decrypted = eap_sim_parse_encr(data->k_encr, attr->encr_data, 5788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt attr->encr_data_len, attr->iv, &eattr, 5798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0); 5808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (decrypted == NULL) { 5818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "EAP-SIM: Failed to parse encrypted " 5828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "data from reauthentication message"); 5838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 5848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eattr.counter != data->counter) { 5878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "EAP-SIM: Re-authentication message " 5888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "used incorrect counter %u, expected %u", 5898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eattr.counter, data->counter); 5908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 5918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(decrypted); 5938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt decrypted = NULL; 5948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-SIM: Re-authentication response includes " 5968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "the correct AT_MAC"); 5978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->eap_sim_aka_result_ind && attr->result_ind) { 5988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->use_result_ind = 1; 5998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->notification = EAP_SIM_SUCCESS; 6008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_state(data, NOTIFICATION); 6018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else 6028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_state(data, SUCCESS); 6038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->reauth) { 6058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt identity = data->reauth->identity; 6068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt identity_len = data->reauth->identity_len; 6078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 6088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt identity = sm->identity; 6098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt identity_len = sm->identity_len; 6108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt id2 = eap_sim_db_get_permanent(sm->eap_sim_db_priv, identity, 6138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt identity_len, &id2_len); 6148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (id2) { 6158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt identity = id2; 6168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt identity_len = id2_len; 6178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->next_pseudonym) { 6208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_db_add_pseudonym(sm->eap_sim_db_priv, identity, 6218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt identity_len, data->next_pseudonym); 6228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->next_pseudonym = NULL; 6238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->next_reauth_id) { 6258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_db_add_reauth(sm->eap_sim_db_priv, identity, 6268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt identity_len, data->next_reauth_id, 6278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->counter + 1, data->mk); 6288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->next_reauth_id = NULL; 6298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 6308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_db_remove_reauth(sm->eap_sim_db_priv, data->reauth); 6318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->reauth = NULL; 6328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 6358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtfail: 6378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_state(data, FAILURE); 6388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_db_remove_reauth(sm->eap_sim_db_priv, data->reauth); 6398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->reauth = NULL; 6408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(decrypted); 6418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_sim_process_client_error(struct eap_sm *sm, 6458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_data *data, 6468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *respData, 6478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_attrs *attr) 6488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-SIM: Client reported error %d", 6508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt attr->client_error_code); 6518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->notification == EAP_SIM_SUCCESS && data->use_result_ind) 6528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_state(data, SUCCESS); 6538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 6548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_state(data, FAILURE); 6558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_sim_process_notification(struct eap_sm *sm, 6598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_data *data, 6608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *respData, 6618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_attrs *attr) 6628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-SIM: Client replied to notification"); 6648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->notification == EAP_SIM_SUCCESS && data->use_result_ind) 6658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_state(data, SUCCESS); 6668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 6678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_state(data, FAILURE); 6688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_sim_process(struct eap_sm *sm, void *priv, 6728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *respData) 6738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_data *data = priv; 6758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos, *end; 6768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 subtype; 6778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len; 6788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_attrs attr; 6798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_SIM, respData, &len); 6818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos == NULL || len < 3) 6828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 6838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt end = pos + len; 6858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt subtype = *pos; 6868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 3; 6878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_sim_parse_attr(pos, end, &attr, 0, 0)) { 6898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-SIM: Failed to parse attributes"); 6908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_state(data, FAILURE); 6918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 6928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (subtype == EAP_SIM_SUBTYPE_CLIENT_ERROR) { 6958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_process_client_error(sm, data, respData, &attr); 6968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 6978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (data->state) { 7008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case START: 7018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_process_start(sm, data, respData, &attr); 7028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 7038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case CHALLENGE: 7048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_process_challenge(sm, data, respData, &attr); 7058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 7068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case REAUTH: 7078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_process_reauth(sm, data, respData, &attr); 7088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 7098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case NOTIFICATION: 7108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_process_notification(sm, data, respData, &attr); 7118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 7128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 7138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-SIM: Unknown state %d in " 7148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "process", data->state); 7158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 7168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic Boolean eap_sim_isDone(struct eap_sm *sm, void *priv) 7218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_data *data = priv; 7238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return data->state == SUCCESS || data->state == FAILURE; 7248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic u8 * eap_sim_getKey(struct eap_sm *sm, void *priv, size_t *len) 7288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_data *data = priv; 7308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *key; 7318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->state != SUCCESS) 7338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 7348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key = os_malloc(EAP_SIM_KEYING_DATA_LEN); 7368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (key == NULL) 7378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 7388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(key, data->msk, EAP_SIM_KEYING_DATA_LEN); 7398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *len = EAP_SIM_KEYING_DATA_LEN; 7408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return key; 7418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic u8 * eap_sim_get_emsk(struct eap_sm *sm, void *priv, size_t *len) 7458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_data *data = priv; 7478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *key; 7488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->state != SUCCESS) 7508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 7518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key = os_malloc(EAP_EMSK_LEN); 7538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (key == NULL) 7548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 7558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(key, data->emsk, EAP_EMSK_LEN); 7568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *len = EAP_EMSK_LEN; 7578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return key; 7588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic Boolean eap_sim_isSuccess(struct eap_sm *sm, void *priv) 7628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_data *data = priv; 7648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return data->state == SUCCESS; 7658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint eap_server_sim_register(void) 7698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_method *eap; 7718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret; 7728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION, 7748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_VENDOR_IETF, EAP_TYPE_SIM, "SIM"); 7758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap == NULL) 7768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 7778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->init = eap_sim_init; 7798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->reset = eap_sim_reset; 7808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->buildReq = eap_sim_buildReq; 7818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->check = eap_sim_check; 7828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->process = eap_sim_process; 7838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->isDone = eap_sim_isDone; 7848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->getKey = eap_sim_getKey; 7858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->isSuccess = eap_sim_isSuccess; 7868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->get_emsk = eap_sim_get_emsk; 7878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = eap_server_method_register(eap); 7898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret) 7908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_server_method_free(eap); 7918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 7928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 793