18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* 28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * hostapd / EAP-SIM (RFC 4186) 34530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt * Copyright (c) 2005-2012, 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; 394530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt int start_round; 404530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt char permanent[20]; /* Permanent username */ 418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}; 428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const char * eap_sim_state_txt(int state) 458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (state) { 478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case START: 488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "START"; 498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case CHALLENGE: 508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "CHALLENGE"; 518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case REAUTH: 528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "REAUTH"; 538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case SUCCESS: 548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "SUCCESS"; 558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case FAILURE: 568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "FAILURE"; 578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case NOTIFICATION: 588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "NOTIFICATION"; 598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "Unknown?!"; 618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_sim_state(struct eap_sim_data *data, int state) 668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-SIM: %s -> %s", 688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_state_txt(data->state), 698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_state_txt(state)); 708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->state = state; 718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void * eap_sim_init(struct eap_sm *sm) 758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_data *data; 778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->eap_sim_db_priv == NULL) { 798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "EAP-SIM: eap_sim_db not configured"); 808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data = os_zalloc(sizeof(*data)); 848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data == NULL) 858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->state = START; 878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return data; 898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_sim_reset(struct eap_sm *sm, void *priv) 938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_data *data = priv; 958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data->next_pseudonym); 968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data->next_reauth_id); 978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data); 988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_sim_build_start(struct eap_sm *sm, 1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_data *data, u8 id) 1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_msg *msg; 1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 ver[2]; 1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-SIM: Generating Start"); 1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = eap_sim_msg_init(EAP_CODE_REQUEST, id, EAP_TYPE_SIM, 1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_SIM_SUBTYPE_START); 1104530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt data->start_round++; 1114530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (data->start_round == 1) { 1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * RFC 4186, Chap. 4.2.4 recommends that identity from EAP is 1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * ignored and the SIM/Start is used to request the identity. 1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " AT_ANY_ID_REQ"); 1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_add(msg, EAP_SIM_AT_ANY_ID_REQ, 0, NULL, 0); 1184530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt } else if (data->start_round > 3) { 1194530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt /* Cannot use more than three rounds of Start messages */ 1204530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt return NULL; 1214530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt } else if (data->start_round == 0) { 1224530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt /* 1234530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt * This is a special case that is used to recover from 1244530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt * AT_COUNTER_TOO_SMALL during re-authentication. Since we 1254530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt * already know the identity of the peer, there is no need to 1264530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt * request any identity in this case. 1274530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt */ 1284530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt } else if (sm->identity && sm->identity_len > 0 && 1294530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt sm->identity[0] == EAP_SIM_REAUTH_ID_PREFIX) { 1304530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt /* Reauth id may have expired - try fullauth */ 1314530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt wpa_printf(MSG_DEBUG, " AT_FULLAUTH_ID_REQ"); 1324530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt eap_sim_msg_add(msg, EAP_SIM_AT_FULLAUTH_ID_REQ, 0, NULL, 0); 1334530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt } else { 1344530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt wpa_printf(MSG_DEBUG, " AT_PERMANENT_ID_REQ"); 1354530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt eap_sim_msg_add(msg, EAP_SIM_AT_PERMANENT_ID_REQ, 0, NULL, 0); 1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " AT_VERSION_LIST"); 1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ver[0] = 0; 1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ver[1] = EAP_SIM_VERSION; 1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_add(msg, EAP_SIM_AT_VERSION_LIST, sizeof(ver), 1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ver, sizeof(ver)); 1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return eap_sim_msg_finish(msg, NULL, NULL, 0); 1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_sim_build_encr(struct eap_sm *sm, struct eap_sim_data *data, 1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_msg *msg, u16 counter, 1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *nonce_s) 1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data->next_pseudonym); 15104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (nonce_s == NULL) { 15204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt data->next_pseudonym = 15304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt eap_sim_db_get_next_pseudonym(sm->eap_sim_db_priv, 15404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt EAP_SIM_DB_SIM); 15504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } else { 15604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt /* Do not update pseudonym during re-authentication */ 15704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt data->next_pseudonym = NULL; 15804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data->next_reauth_id); 1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->counter <= EAP_SIM_MAX_FAST_REAUTHS) { 1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->next_reauth_id = 16204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt eap_sim_db_get_next_reauth_id(sm->eap_sim_db_priv, 16304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt EAP_SIM_DB_SIM); 1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-SIM: Max fast re-authentication " 1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "count exceeded - force full authentication"); 1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->next_reauth_id = NULL; 1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->next_pseudonym == NULL && data->next_reauth_id == NULL && 1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt counter == 0 && nonce_s == NULL) 1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " AT_IV"); 1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " AT_ENCR_DATA"); 1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_add_encr_start(msg, EAP_SIM_AT_IV, EAP_SIM_AT_ENCR_DATA); 1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (counter > 0) { 1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " *AT_COUNTER (%u)", counter); 1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_add(msg, EAP_SIM_AT_COUNTER, counter, NULL, 0); 1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (nonce_s) { 1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " *AT_NONCE_S"); 1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_add(msg, EAP_SIM_AT_NONCE_S, 0, nonce_s, 1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_SIM_NONCE_S_LEN); 1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->next_pseudonym) { 1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " *AT_NEXT_PSEUDONYM (%s)", 1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->next_pseudonym); 1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_add(msg, EAP_SIM_AT_NEXT_PSEUDONYM, 1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_strlen(data->next_pseudonym), 1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (u8 *) data->next_pseudonym, 1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_strlen(data->next_pseudonym)); 1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->next_reauth_id) { 1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " *AT_NEXT_REAUTH_ID (%s)", 2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->next_reauth_id); 2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_add(msg, EAP_SIM_AT_NEXT_REAUTH_ID, 2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_strlen(data->next_reauth_id), 2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (u8 *) data->next_reauth_id, 2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_strlen(data->next_reauth_id)); 2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_sim_msg_add_encr_end(msg, data->k_encr, EAP_SIM_AT_PADDING)) { 2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "EAP-SIM: Failed to encrypt " 2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "AT_ENCR_DATA"); 2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_sim_build_challenge(struct eap_sm *sm, 2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_data *data, 2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 id) 2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_msg *msg; 2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-SIM: Generating Challenge"); 2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = eap_sim_msg_init(EAP_CODE_REQUEST, id, EAP_TYPE_SIM, 2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_SIM_SUBTYPE_CHALLENGE); 2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " AT_RAND"); 2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_add(msg, EAP_SIM_AT_RAND, 0, (u8 *) data->rand, 2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->num_chal * GSM_RAND_LEN); 2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_sim_build_encr(sm, data, msg, 0, NULL)) { 2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_free(msg); 2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->eap_sim_aka_result_ind) { 2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " AT_RESULT_IND"); 2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_add(msg, EAP_SIM_AT_RESULT_IND, 0, NULL, 0); 2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " AT_MAC"); 2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC); 2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return eap_sim_msg_finish(msg, data->k_aut, data->nonce_mt, 2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_SIM_NONCE_MT_LEN); 2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_sim_build_reauth(struct eap_sm *sm, 2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_data *data, u8 id) 2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_msg *msg; 2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-SIM: Generating Re-authentication"); 2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (random_get_bytes(data->nonce_s, EAP_SIM_NONCE_S_LEN)) 2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_MSGDUMP, "EAP-SIM: NONCE_S", 2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->nonce_s, EAP_SIM_NONCE_S_LEN); 2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_derive_keys(data->mk, data->k_encr, data->k_aut, data->msk, 2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->emsk); 2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_derive_keys_reauth(data->counter, sm->identity, 2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->identity_len, data->nonce_s, data->mk, 2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->msk, data->emsk); 2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = eap_sim_msg_init(EAP_CODE_REQUEST, id, EAP_TYPE_SIM, 2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_SIM_SUBTYPE_REAUTHENTICATION); 2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_sim_build_encr(sm, data, msg, data->counter, data->nonce_s)) { 2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_free(msg); 2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->eap_sim_aka_result_ind) { 2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " AT_RESULT_IND"); 2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_add(msg, EAP_SIM_AT_RESULT_IND, 0, NULL, 0); 2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " AT_MAC"); 2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC); 2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return eap_sim_msg_finish(msg, data->k_aut, NULL, 0); 2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_sim_build_notification(struct eap_sm *sm, 2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_data *data, 2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 id) 2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_msg *msg; 2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-SIM: Generating Notification"); 2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = eap_sim_msg_init(EAP_CODE_REQUEST, id, EAP_TYPE_SIM, 2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_SIM_SUBTYPE_NOTIFICATION); 2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " AT_NOTIFICATION (%d)", data->notification); 2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_add(msg, EAP_SIM_AT_NOTIFICATION, data->notification, 2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NULL, 0); 2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->use_result_ind) { 2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->reauth) { 2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " AT_IV"); 2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " AT_ENCR_DATA"); 3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_add_encr_start(msg, EAP_SIM_AT_IV, 3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_SIM_AT_ENCR_DATA); 3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " *AT_COUNTER (%u)", 3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->counter); 3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_add(msg, EAP_SIM_AT_COUNTER, data->counter, 3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NULL, 0); 3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_sim_msg_add_encr_end(msg, data->k_encr, 3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_SIM_AT_PADDING)) { 3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "EAP-SIM: Failed to " 3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "encrypt AT_ENCR_DATA"); 3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_free(msg); 3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " AT_MAC"); 3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC); 3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return eap_sim_msg_finish(msg, data->k_aut, NULL, 0); 3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_sim_buildReq(struct eap_sm *sm, void *priv, u8 id) 3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_data *data = priv; 3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (data->state) { 3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case START: 3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return eap_sim_build_start(sm, data, id); 3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case CHALLENGE: 3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return eap_sim_build_challenge(sm, data, id); 3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case REAUTH: 3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return eap_sim_build_reauth(sm, data, id); 3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case NOTIFICATION: 3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return eap_sim_build_notification(sm, data, id); 3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-SIM: Unknown state %d in " 3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "buildReq", data->state); 3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic Boolean eap_sim_check(struct eap_sm *sm, void *priv, 3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *respData) 3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos; 3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len; 3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_SIM, respData, &len); 3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos == NULL || len < 3) { 3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-SIM: Invalid frame"); 3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return TRUE; 3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3574530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt return FALSE; 3584530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt} 3594530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 3604530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 3614530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtstatic Boolean eap_sim_unexpected_subtype(struct eap_sim_data *data, 3624530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt u8 subtype) 3634530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt{ 3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (subtype == EAP_SIM_SUBTYPE_CLIENT_ERROR) 3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return FALSE; 3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (data->state) { 3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case START: 3698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (subtype != EAP_SIM_SUBTYPE_START) { 3708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-SIM: Unexpected response " 3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "subtype %d", subtype); 3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return TRUE; 3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case CHALLENGE: 3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (subtype != EAP_SIM_SUBTYPE_CHALLENGE) { 3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-SIM: Unexpected response " 3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "subtype %d", subtype); 3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return TRUE; 3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case REAUTH: 3838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (subtype != EAP_SIM_SUBTYPE_REAUTHENTICATION) { 3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-SIM: Unexpected response " 3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "subtype %d", subtype); 3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return TRUE; 3878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 3898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case NOTIFICATION: 3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (subtype != EAP_SIM_SUBTYPE_NOTIFICATION) { 3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-SIM: Unexpected response " 3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "subtype %d", subtype); 3938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return TRUE; 3948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 3978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-SIM: Unexpected state (%d) for " 3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "processing a response", data->state); 3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return TRUE; 4008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return FALSE; 4038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_sim_supported_ver(struct eap_sim_data *data, int version) 4078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return version == EAP_SIM_VERSION; 4098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_sim_process_start(struct eap_sm *sm, 4138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_data *data, 4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *respData, 4158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_attrs *attr) 4168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t identity_len; 4188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 ver_list[2]; 4194530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt u8 *new_identity; 4204530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt char *username; 4218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-SIM: Receive start response"); 4238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4244530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (data->start_round == 0) { 4254530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt /* 4264530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt * Special case for AT_COUNTER_TOO_SMALL recovery - no identity 4274530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt * was requested since we already know it. 4284530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt */ 4294530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt goto skip_id_update; 4308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4324530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt /* 4334530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt * We always request identity in SIM/Start, so the peer is required to 4344530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt * have replied with one. 4354530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt */ 4364530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (!attr->identity || attr->identity_len == 0) { 4374530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-SIM: Peer did not provide any " 4384530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt "identity"); 4394530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt goto failed; 4408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4424530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt new_identity = os_malloc(attr->identity_len); 4434530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (new_identity == NULL) 4444530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt goto failed; 4454530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt os_free(sm->identity); 4464530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt sm->identity = new_identity; 4474530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt os_memcpy(sm->identity, attr->identity, attr->identity_len); 4484530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt sm->identity_len = attr->identity_len; 4498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, "EAP-SIM: Identity", 4514530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt sm->identity, sm->identity_len); 4524530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt username = sim_get_username(sm->identity, sm->identity_len); 4534530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (username == NULL) 4544530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt goto failed; 4554530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 4564530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (username[0] == EAP_SIM_REAUTH_ID_PREFIX) { 4574530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-SIM: Reauth username '%s'", 4584530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt username); 4594530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt data->reauth = eap_sim_db_get_reauth_entry( 4604530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt sm->eap_sim_db_priv, username); 4614530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt os_free(username); 4624530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (data->reauth == NULL) { 4634530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-SIM: Unknown reauth " 4644530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt "identity - request full auth identity"); 4654530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt /* Remain in START state for another round */ 4664530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt return; 4674530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt } 4684530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-SIM: Using fast re-authentication"); 4694530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt os_strlcpy(data->permanent, data->reauth->permanent, 4704530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt sizeof(data->permanent)); 4714530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt data->counter = data->reauth->counter; 4724530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt os_memcpy(data->mk, data->reauth->mk, EAP_SIM_MK_LEN); 4738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_state(data, REAUTH); 4748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 4758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4774530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (username[0] == EAP_SIM_PSEUDONYM_PREFIX) { 4784530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt const char *permanent; 4794530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-SIM: Pseudonym username '%s'", 4804530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt username); 4814530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt permanent = eap_sim_db_get_permanent( 4824530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt sm->eap_sim_db_priv, username); 4834530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt os_free(username); 4844530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (permanent == NULL) { 4854530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-SIM: Unknown pseudonym " 4864530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt "identity - request permanent identity"); 4874530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt /* Remain in START state for another round */ 4884530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt return; 4894530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt } 4904530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt os_strlcpy(data->permanent, permanent, 4914530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt sizeof(data->permanent)); 4924530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt } else if (username[0] == EAP_SIM_PERMANENT_PREFIX) { 4934530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-SIM: Permanent username '%s'", 4944530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt username); 4954530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt os_strlcpy(data->permanent, username, sizeof(data->permanent)); 4964530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt os_free(username); 4974530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt } else { 4984530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-SIM: Unrecognized username '%s'", 4994530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt username); 5004530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt os_free(username); 5014530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt goto failed; 5024530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt } 5034530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 5044530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtskip_id_update: 5054530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt /* Full authentication */ 5064530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 5078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (attr->nonce_mt == NULL || attr->selected_version < 0) { 5088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-SIM: Start/Response missing " 5098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "required attributes"); 5104530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt goto failed; 5118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!eap_sim_supported_ver(data, attr->selected_version)) { 5148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-SIM: Peer selected unsupported " 5158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "version %d", attr->selected_version); 5164530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt goto failed; 5178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->counter = 0; /* reset re-auth counter since this is full auth */ 5208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->reauth = NULL; 5218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->num_chal = eap_sim_db_get_gsm_triplets( 5234530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt sm->eap_sim_db_priv, data->permanent, EAP_SIM_MAX_CHAL, 5248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (u8 *) data->rand, (u8 *) data->kc, (u8 *) data->sres, sm); 5258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->num_chal == EAP_SIM_DB_PENDING) { 5268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-SIM: GSM authentication triplets " 5278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "not yet available - pending request"); 5288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->method_pending = METHOD_PENDING_WAIT; 5298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 5308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->num_chal < 2) { 5328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-SIM: Failed to get GSM " 5338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "authentication triplets for the peer"); 5344530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt goto failed; 5358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt identity_len = sm->identity_len; 5388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (identity_len > 0 && sm->identity[identity_len - 1] == '\0') { 5398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-SIM: Workaround - drop last null " 5408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "character from identity"); 5418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt identity_len--; 5428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, "EAP-SIM: Identity for MK derivation", 5448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->identity, identity_len); 5458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(data->nonce_mt, attr->nonce_mt, EAP_SIM_NONCE_MT_LEN); 5478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(ver_list, EAP_SIM_VERSION); 5488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_derive_mk(sm->identity, identity_len, attr->nonce_mt, 5498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt attr->selected_version, ver_list, sizeof(ver_list), 5508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->num_chal, (const u8 *) data->kc, data->mk); 5518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_derive_keys(data->mk, data->k_encr, data->k_aut, data->msk, 5528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->emsk); 5538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_state(data, CHALLENGE); 5554530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt return; 5564530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 5574530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtfailed: 5584530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH; 5594530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt eap_sim_state(data, NOTIFICATION); 5608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_sim_process_challenge(struct eap_sm *sm, 5648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_data *data, 5658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *respData, 5668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_attrs *attr) 5678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (attr->mac == NULL || 5698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_verify_mac(data->k_aut, respData, attr->mac, 5708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (u8 *) data->sres, 5718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->num_chal * EAP_SIM_SRES_LEN)) { 5728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "EAP-SIM: Challenge message " 5738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "did not include valid AT_MAC"); 5744530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH; 5754530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt eap_sim_state(data, NOTIFICATION); 5768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 5778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-SIM: Challenge response includes the " 5808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "correct AT_MAC"); 5818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->eap_sim_aka_result_ind && attr->result_ind) { 5828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->use_result_ind = 1; 5838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->notification = EAP_SIM_SUCCESS; 5848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_state(data, NOTIFICATION); 5858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else 5868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_state(data, SUCCESS); 5878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->next_pseudonym) { 5894530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt eap_sim_db_add_pseudonym(sm->eap_sim_db_priv, data->permanent, 5908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->next_pseudonym); 5918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->next_pseudonym = NULL; 5928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->next_reauth_id) { 5944530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt eap_sim_db_add_reauth(sm->eap_sim_db_priv, data->permanent, 5958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->next_reauth_id, data->counter + 1, 5968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->mk); 5978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->next_reauth_id = NULL; 5988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_sim_process_reauth(struct eap_sm *sm, 6038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_data *data, 6048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *respData, 6058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_attrs *attr) 6068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_attrs eattr; 6088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *decrypted = NULL; 6098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (attr->mac == NULL || 6118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_verify_mac(data->k_aut, respData, attr->mac, data->nonce_s, 6128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_SIM_NONCE_S_LEN)) { 6138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "EAP-SIM: Re-authentication message " 6148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "did not include valid AT_MAC"); 6158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 6168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (attr->encr_data == NULL || attr->iv == NULL) { 6198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "EAP-SIM: Reauthentication " 6208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "message did not include encrypted data"); 6218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 6228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt decrypted = eap_sim_parse_encr(data->k_encr, attr->encr_data, 6258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt attr->encr_data_len, attr->iv, &eattr, 6268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0); 6278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (decrypted == NULL) { 6288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "EAP-SIM: Failed to parse encrypted " 6298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "data from reauthentication message"); 6308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 6318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eattr.counter != data->counter) { 6348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "EAP-SIM: Re-authentication message " 6358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "used incorrect counter %u, expected %u", 6368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eattr.counter, data->counter); 6378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 6388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(decrypted); 6408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt decrypted = NULL; 6418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-SIM: Re-authentication response includes " 6438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "the correct AT_MAC"); 6444530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 6454530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (eattr.counter_too_small) { 6464530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-AKA: Re-authentication response " 6474530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt "included AT_COUNTER_TOO_SMALL - starting full " 6484530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt "authentication"); 6494530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt data->start_round = -1; 6504530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt eap_sim_state(data, START); 6514530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt return; 6524530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt } 6534530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 6548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->eap_sim_aka_result_ind && attr->result_ind) { 6558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->use_result_ind = 1; 6568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->notification = EAP_SIM_SUCCESS; 6578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_state(data, NOTIFICATION); 6588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else 6598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_state(data, SUCCESS); 6608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->next_reauth_id) { 6624530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt eap_sim_db_add_reauth(sm->eap_sim_db_priv, data->permanent, 6634530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt data->next_reauth_id, 6648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->counter + 1, data->mk); 6658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->next_reauth_id = NULL; 6668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 6678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_db_remove_reauth(sm->eap_sim_db_priv, data->reauth); 6688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->reauth = NULL; 6698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 6728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtfail: 6744530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH; 6754530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt eap_sim_state(data, NOTIFICATION); 6768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_db_remove_reauth(sm->eap_sim_db_priv, data->reauth); 6778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->reauth = NULL; 6788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(decrypted); 6798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_sim_process_client_error(struct eap_sm *sm, 6838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_data *data, 6848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *respData, 6858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_attrs *attr) 6868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-SIM: Client reported error %d", 6888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt attr->client_error_code); 6898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->notification == EAP_SIM_SUCCESS && data->use_result_ind) 6908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_state(data, SUCCESS); 6918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 6928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_state(data, FAILURE); 6938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_sim_process_notification(struct eap_sm *sm, 6978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_data *data, 6988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *respData, 6998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_attrs *attr) 7008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-SIM: Client replied to notification"); 7028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->notification == EAP_SIM_SUCCESS && data->use_result_ind) 7038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_state(data, SUCCESS); 7048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 7058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_state(data, FAILURE); 7068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_sim_process(struct eap_sm *sm, void *priv, 7108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *respData) 7118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_data *data = priv; 7138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos, *end; 7148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 subtype; 7158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len; 7168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_attrs attr; 7178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_SIM, respData, &len); 7198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos == NULL || len < 3) 7208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 7218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt end = pos + len; 7238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt subtype = *pos; 7248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 3; 7258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7264530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (eap_sim_unexpected_subtype(data, subtype)) { 7274530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-SIM: Unrecognized or unexpected " 7284530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt "EAP-SIM Subtype in EAP Response"); 7294530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH; 7304530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt eap_sim_state(data, NOTIFICATION); 7314530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt return; 7324530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt } 7334530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 7348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_sim_parse_attr(pos, end, &attr, 0, 0)) { 7358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-SIM: Failed to parse attributes"); 7364530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (subtype != EAP_SIM_SUBTYPE_CLIENT_ERROR && 7374530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt (data->state == START || data->state == CHALLENGE || 7384530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt data->state == REAUTH)) { 7394530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt data->notification = 7404530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH; 7414530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt eap_sim_state(data, NOTIFICATION); 7424530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt return; 7434530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt } 7448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_state(data, FAILURE); 7458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 7468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (subtype == EAP_SIM_SUBTYPE_CLIENT_ERROR) { 7498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_process_client_error(sm, data, respData, &attr); 7508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 7518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (data->state) { 7548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case START: 7558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_process_start(sm, data, respData, &attr); 7568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 7578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case CHALLENGE: 7588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_process_challenge(sm, data, respData, &attr); 7598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 7608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case REAUTH: 7618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_process_reauth(sm, data, respData, &attr); 7628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 7638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case NOTIFICATION: 7648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_process_notification(sm, data, respData, &attr); 7658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 7668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 7678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-SIM: Unknown state %d in " 7688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "process", data->state); 7698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 7708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic Boolean eap_sim_isDone(struct eap_sm *sm, void *priv) 7758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_data *data = priv; 7778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return data->state == SUCCESS || data->state == FAILURE; 7788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic u8 * eap_sim_getKey(struct eap_sm *sm, void *priv, size_t *len) 7828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_data *data = priv; 7848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *key; 7858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->state != SUCCESS) 7878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 7888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key = os_malloc(EAP_SIM_KEYING_DATA_LEN); 7908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (key == NULL) 7918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 7928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(key, data->msk, EAP_SIM_KEYING_DATA_LEN); 7938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *len = EAP_SIM_KEYING_DATA_LEN; 7948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return key; 7958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic u8 * eap_sim_get_emsk(struct eap_sm *sm, void *priv, size_t *len) 7998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 8008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_data *data = priv; 8018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *key; 8028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->state != SUCCESS) 8048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 8058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key = os_malloc(EAP_EMSK_LEN); 8078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (key == NULL) 8088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 8098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(key, data->emsk, EAP_EMSK_LEN); 8108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *len = EAP_EMSK_LEN; 8118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return key; 8128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 8138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic Boolean eap_sim_isSuccess(struct eap_sm *sm, void *priv) 8168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 8178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_data *data = priv; 8188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return data->state == SUCCESS; 8198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 8208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint eap_server_sim_register(void) 8238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 8248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_method *eap; 8258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret; 8268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION, 8288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_VENDOR_IETF, EAP_TYPE_SIM, "SIM"); 8298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap == NULL) 8308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 8318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->init = eap_sim_init; 8338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->reset = eap_sim_reset; 8348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->buildReq = eap_sim_buildReq; 8358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->check = eap_sim_check; 8368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->process = eap_sim_process; 8378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->isDone = eap_sim_isDone; 8388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->getKey = eap_sim_getKey; 8398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->isSuccess = eap_sim_isSuccess; 8408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->get_emsk = eap_sim_get_emsk; 8418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = eap_server_method_register(eap); 8438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret) 8448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_server_method_free(eap); 8458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 8468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 847