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); 97c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt bin_clear_free(data, sizeof(*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 */ 120d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt eap_sim_msg_free(msg); 1214530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt return NULL; 1224530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt } else if (data->start_round == 0) { 1234530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt /* 1244530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt * This is a special case that is used to recover from 1254530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt * AT_COUNTER_TOO_SMALL during re-authentication. Since we 1264530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt * already know the identity of the peer, there is no need to 1274530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt * request any identity in this case. 1284530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt */ 1294530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt } else if (sm->identity && sm->identity_len > 0 && 1304530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt sm->identity[0] == EAP_SIM_REAUTH_ID_PREFIX) { 1314530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt /* Reauth id may have expired - try fullauth */ 1324530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt wpa_printf(MSG_DEBUG, " AT_FULLAUTH_ID_REQ"); 1334530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt eap_sim_msg_add(msg, EAP_SIM_AT_FULLAUTH_ID_REQ, 0, NULL, 0); 1344530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt } else { 1354530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt wpa_printf(MSG_DEBUG, " AT_PERMANENT_ID_REQ"); 1364530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt eap_sim_msg_add(msg, EAP_SIM_AT_PERMANENT_ID_REQ, 0, NULL, 0); 1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " AT_VERSION_LIST"); 1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ver[0] = 0; 1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ver[1] = EAP_SIM_VERSION; 1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_add(msg, EAP_SIM_AT_VERSION_LIST, sizeof(ver), 1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ver, sizeof(ver)); 143c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt return eap_sim_msg_finish(msg, EAP_TYPE_SIM, NULL, NULL, 0); 1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_sim_build_encr(struct eap_sm *sm, struct eap_sim_data *data, 1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_msg *msg, u16 counter, 1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *nonce_s) 1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data->next_pseudonym); 15204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (nonce_s == NULL) { 15304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt data->next_pseudonym = 15404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt eap_sim_db_get_next_pseudonym(sm->eap_sim_db_priv, 15504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt EAP_SIM_DB_SIM); 15604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } else { 15704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt /* Do not update pseudonym during re-authentication */ 15804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt data->next_pseudonym = NULL; 15904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data->next_reauth_id); 1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->counter <= EAP_SIM_MAX_FAST_REAUTHS) { 1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->next_reauth_id = 16304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt eap_sim_db_get_next_reauth_id(sm->eap_sim_db_priv, 16404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt EAP_SIM_DB_SIM); 1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-SIM: Max fast re-authentication " 1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "count exceeded - force full authentication"); 1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->next_reauth_id = NULL; 1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->next_pseudonym == NULL && data->next_reauth_id == NULL && 1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt counter == 0 && nonce_s == NULL) 1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " AT_IV"); 1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " AT_ENCR_DATA"); 1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_add_encr_start(msg, EAP_SIM_AT_IV, EAP_SIM_AT_ENCR_DATA); 1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (counter > 0) { 1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " *AT_COUNTER (%u)", counter); 1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_add(msg, EAP_SIM_AT_COUNTER, counter, NULL, 0); 1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (nonce_s) { 1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " *AT_NONCE_S"); 1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_add(msg, EAP_SIM_AT_NONCE_S, 0, nonce_s, 1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_SIM_NONCE_S_LEN); 1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->next_pseudonym) { 1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " *AT_NEXT_PSEUDONYM (%s)", 1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->next_pseudonym); 1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_add(msg, EAP_SIM_AT_NEXT_PSEUDONYM, 1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_strlen(data->next_pseudonym), 1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (u8 *) data->next_pseudonym, 1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_strlen(data->next_pseudonym)); 1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->next_reauth_id) { 2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " *AT_NEXT_REAUTH_ID (%s)", 2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->next_reauth_id); 2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_add(msg, EAP_SIM_AT_NEXT_REAUTH_ID, 2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_strlen(data->next_reauth_id), 2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (u8 *) data->next_reauth_id, 2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_strlen(data->next_reauth_id)); 2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_sim_msg_add_encr_end(msg, data->k_encr, EAP_SIM_AT_PADDING)) { 2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "EAP-SIM: Failed to encrypt " 2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "AT_ENCR_DATA"); 2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_sim_build_challenge(struct eap_sm *sm, 2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_data *data, 2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 id) 2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_msg *msg; 2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-SIM: Generating Challenge"); 2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = eap_sim_msg_init(EAP_CODE_REQUEST, id, EAP_TYPE_SIM, 2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_SIM_SUBTYPE_CHALLENGE); 2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " AT_RAND"); 2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_add(msg, EAP_SIM_AT_RAND, 0, (u8 *) data->rand, 2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->num_chal * GSM_RAND_LEN); 2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_sim_build_encr(sm, data, msg, 0, NULL)) { 2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_free(msg); 2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->eap_sim_aka_result_ind) { 2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " AT_RESULT_IND"); 2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_add(msg, EAP_SIM_AT_RESULT_IND, 0, NULL, 0); 2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " AT_MAC"); 2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC); 243c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt return eap_sim_msg_finish(msg, EAP_TYPE_SIM, data->k_aut, 244c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt data->nonce_mt, EAP_SIM_NONCE_MT_LEN); 2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_sim_build_reauth(struct eap_sm *sm, 2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_data *data, u8 id) 2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_msg *msg; 2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-SIM: Generating Re-authentication"); 2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (random_get_bytes(data->nonce_s, EAP_SIM_NONCE_S_LEN)) 2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_MSGDUMP, "EAP-SIM: NONCE_S", 2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->nonce_s, EAP_SIM_NONCE_S_LEN); 2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_derive_keys(data->mk, data->k_encr, data->k_aut, data->msk, 2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->emsk); 2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_derive_keys_reauth(data->counter, sm->identity, 2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->identity_len, data->nonce_s, data->mk, 2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->msk, data->emsk); 2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = eap_sim_msg_init(EAP_CODE_REQUEST, id, EAP_TYPE_SIM, 2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_SIM_SUBTYPE_REAUTHENTICATION); 2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_sim_build_encr(sm, data, msg, data->counter, data->nonce_s)) { 2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_free(msg); 2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->eap_sim_aka_result_ind) { 2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " AT_RESULT_IND"); 2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_add(msg, EAP_SIM_AT_RESULT_IND, 0, NULL, 0); 2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " AT_MAC"); 2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC); 281c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt return eap_sim_msg_finish(msg, EAP_TYPE_SIM, data->k_aut, NULL, 0); 2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_sim_build_notification(struct eap_sm *sm, 2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_data *data, 2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 id) 2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_msg *msg; 2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-SIM: Generating Notification"); 2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = eap_sim_msg_init(EAP_CODE_REQUEST, id, EAP_TYPE_SIM, 2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_SIM_SUBTYPE_NOTIFICATION); 2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " AT_NOTIFICATION (%d)", data->notification); 2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_add(msg, EAP_SIM_AT_NOTIFICATION, data->notification, 2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NULL, 0); 2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->use_result_ind) { 2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->reauth) { 2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " AT_IV"); 3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " AT_ENCR_DATA"); 3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_add_encr_start(msg, EAP_SIM_AT_IV, 3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_SIM_AT_ENCR_DATA); 3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " *AT_COUNTER (%u)", 3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->counter); 3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_add(msg, EAP_SIM_AT_COUNTER, data->counter, 3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NULL, 0); 3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_sim_msg_add_encr_end(msg, data->k_encr, 3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_SIM_AT_PADDING)) { 3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "EAP-SIM: Failed to " 3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "encrypt AT_ENCR_DATA"); 3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_free(msg); 3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " AT_MAC"); 3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC); 3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 320c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt return eap_sim_msg_finish(msg, EAP_TYPE_SIM, data->k_aut, NULL, 0); 3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_sim_buildReq(struct eap_sm *sm, void *priv, u8 id) 3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_data *data = priv; 3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (data->state) { 3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case START: 3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return eap_sim_build_start(sm, data, id); 3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case CHALLENGE: 3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return eap_sim_build_challenge(sm, data, id); 3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case REAUTH: 3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return eap_sim_build_reauth(sm, data, id); 3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case NOTIFICATION: 3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return eap_sim_build_notification(sm, data, id); 3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-SIM: Unknown state %d in " 3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "buildReq", data->state); 3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic Boolean eap_sim_check(struct eap_sm *sm, void *priv, 3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *respData) 3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos; 3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len; 3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_SIM, respData, &len); 3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos == NULL || len < 3) { 3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-SIM: Invalid frame"); 3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return TRUE; 3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3584530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt return FALSE; 3594530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt} 3604530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 3614530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 3624530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtstatic Boolean eap_sim_unexpected_subtype(struct eap_sim_data *data, 3634530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt u8 subtype) 3644530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt{ 3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (subtype == EAP_SIM_SUBTYPE_CLIENT_ERROR) 3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return FALSE; 3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (data->state) { 3698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case START: 3708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (subtype != EAP_SIM_SUBTYPE_START) { 3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-SIM: Unexpected response " 3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "subtype %d", subtype); 3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return TRUE; 3748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case CHALLENGE: 3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (subtype != EAP_SIM_SUBTYPE_CHALLENGE) { 3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-SIM: Unexpected response " 3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "subtype %d", subtype); 3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return TRUE; 3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 3838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case REAUTH: 3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (subtype != EAP_SIM_SUBTYPE_REAUTHENTICATION) { 3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-SIM: Unexpected response " 3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "subtype %d", subtype); 3878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return TRUE; 3888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case NOTIFICATION: 3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (subtype != EAP_SIM_SUBTYPE_NOTIFICATION) { 3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-SIM: Unexpected response " 3938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "subtype %d", subtype); 3948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return TRUE; 3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 3978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-SIM: Unexpected state (%d) for " 3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "processing a response", data->state); 4008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return TRUE; 4018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return FALSE; 4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_sim_supported_ver(struct eap_sim_data *data, int version) 4088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return version == EAP_SIM_VERSION; 4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_sim_process_start(struct eap_sm *sm, 4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_data *data, 4158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *respData, 4168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_attrs *attr) 4178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t identity_len; 4198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 ver_list[2]; 4204530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt u8 *new_identity; 4214530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt char *username; 4228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-SIM: Receive start response"); 4248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4254530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (data->start_round == 0) { 4264530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt /* 4274530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt * Special case for AT_COUNTER_TOO_SMALL recovery - no identity 4284530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt * was requested since we already know it. 4294530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt */ 4304530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt goto skip_id_update; 4318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4334530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt /* 4344530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt * We always request identity in SIM/Start, so the peer is required to 4354530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt * have replied with one. 4364530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt */ 4374530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (!attr->identity || attr->identity_len == 0) { 4384530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-SIM: Peer did not provide any " 4394530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt "identity"); 4404530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt goto failed; 4418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4434530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt new_identity = os_malloc(attr->identity_len); 4444530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (new_identity == NULL) 4454530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt goto failed; 4464530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt os_free(sm->identity); 4474530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt sm->identity = new_identity; 4484530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt os_memcpy(sm->identity, attr->identity, attr->identity_len); 4494530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt sm->identity_len = attr->identity_len; 4508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, "EAP-SIM: Identity", 4524530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt sm->identity, sm->identity_len); 4534530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt username = sim_get_username(sm->identity, sm->identity_len); 4544530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (username == NULL) 4554530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt goto failed; 4564530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 4574530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (username[0] == EAP_SIM_REAUTH_ID_PREFIX) { 4584530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-SIM: Reauth username '%s'", 4594530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt username); 4604530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt data->reauth = eap_sim_db_get_reauth_entry( 4614530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt sm->eap_sim_db_priv, username); 4624530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt os_free(username); 4634530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (data->reauth == NULL) { 4644530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-SIM: Unknown reauth " 4654530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt "identity - request full auth identity"); 4664530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt /* Remain in START state for another round */ 4674530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt return; 4684530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt } 4694530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-SIM: Using fast re-authentication"); 4704530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt os_strlcpy(data->permanent, data->reauth->permanent, 4714530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt sizeof(data->permanent)); 4724530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt data->counter = data->reauth->counter; 4734530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt os_memcpy(data->mk, data->reauth->mk, EAP_SIM_MK_LEN); 4748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_state(data, REAUTH); 4758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 4768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4784530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (username[0] == EAP_SIM_PSEUDONYM_PREFIX) { 4794530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt const char *permanent; 4804530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-SIM: Pseudonym username '%s'", 4814530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt username); 4824530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt permanent = eap_sim_db_get_permanent( 4834530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt sm->eap_sim_db_priv, username); 4844530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt os_free(username); 4854530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (permanent == NULL) { 4864530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-SIM: Unknown pseudonym " 4874530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt "identity - request permanent identity"); 4884530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt /* Remain in START state for another round */ 4894530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt return; 4904530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt } 4914530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt os_strlcpy(data->permanent, permanent, 4924530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt sizeof(data->permanent)); 4934530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt } else if (username[0] == EAP_SIM_PERMANENT_PREFIX) { 4944530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-SIM: Permanent username '%s'", 4954530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt username); 4964530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt os_strlcpy(data->permanent, username, sizeof(data->permanent)); 4974530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt os_free(username); 4984530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt } else { 4994530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-SIM: Unrecognized username '%s'", 5004530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt username); 5014530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt os_free(username); 5024530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt goto failed; 5034530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt } 5044530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 5054530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtskip_id_update: 5064530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt /* Full authentication */ 5074530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 5088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (attr->nonce_mt == NULL || attr->selected_version < 0) { 5098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-SIM: Start/Response missing " 5108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "required attributes"); 5114530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt goto failed; 5128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!eap_sim_supported_ver(data, attr->selected_version)) { 5158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-SIM: Peer selected unsupported " 5168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "version %d", attr->selected_version); 5174530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt goto failed; 5188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->counter = 0; /* reset re-auth counter since this is full auth */ 5218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->reauth = NULL; 5228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->num_chal = eap_sim_db_get_gsm_triplets( 5244530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt sm->eap_sim_db_priv, data->permanent, EAP_SIM_MAX_CHAL, 5258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (u8 *) data->rand, (u8 *) data->kc, (u8 *) data->sres, sm); 5268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->num_chal == EAP_SIM_DB_PENDING) { 5278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-SIM: GSM authentication triplets " 5288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "not yet available - pending request"); 5298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->method_pending = METHOD_PENDING_WAIT; 5308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 5318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->num_chal < 2) { 5338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-SIM: Failed to get GSM " 5348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "authentication triplets for the peer"); 5354530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt goto failed; 5368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt identity_len = sm->identity_len; 5398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (identity_len > 0 && sm->identity[identity_len - 1] == '\0') { 5408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-SIM: Workaround - drop last null " 5418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "character from identity"); 5428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt identity_len--; 5438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, "EAP-SIM: Identity for MK derivation", 5458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->identity, identity_len); 5468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(data->nonce_mt, attr->nonce_mt, EAP_SIM_NONCE_MT_LEN); 5488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(ver_list, EAP_SIM_VERSION); 5498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_derive_mk(sm->identity, identity_len, attr->nonce_mt, 5508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt attr->selected_version, ver_list, sizeof(ver_list), 5518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->num_chal, (const u8 *) data->kc, data->mk); 5528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_derive_keys(data->mk, data->k_encr, data->k_aut, data->msk, 5538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->emsk); 5548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_state(data, CHALLENGE); 5564530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt return; 5574530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 5584530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtfailed: 5594530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH; 5604530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt eap_sim_state(data, NOTIFICATION); 5618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_sim_process_challenge(struct eap_sm *sm, 5658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_data *data, 5668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *respData, 5678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_attrs *attr) 5688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (attr->mac == NULL || 5708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_verify_mac(data->k_aut, respData, attr->mac, 5718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (u8 *) data->sres, 5728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->num_chal * EAP_SIM_SRES_LEN)) { 5738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "EAP-SIM: Challenge message " 5748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "did not include valid AT_MAC"); 5754530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH; 5764530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt eap_sim_state(data, NOTIFICATION); 5778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 5788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-SIM: Challenge response includes the " 5818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "correct AT_MAC"); 5828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->eap_sim_aka_result_ind && attr->result_ind) { 5838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->use_result_ind = 1; 5848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->notification = EAP_SIM_SUCCESS; 5858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_state(data, NOTIFICATION); 5868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else 5878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_state(data, SUCCESS); 5888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->next_pseudonym) { 5904530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt eap_sim_db_add_pseudonym(sm->eap_sim_db_priv, data->permanent, 5918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->next_pseudonym); 5928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->next_pseudonym = NULL; 5938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->next_reauth_id) { 5954530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt eap_sim_db_add_reauth(sm->eap_sim_db_priv, data->permanent, 5968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->next_reauth_id, data->counter + 1, 5978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->mk); 5988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->next_reauth_id = NULL; 5998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_sim_process_reauth(struct eap_sm *sm, 6048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_data *data, 6058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *respData, 6068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_attrs *attr) 6078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_attrs eattr; 6098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *decrypted = NULL; 6108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (attr->mac == NULL || 6128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_verify_mac(data->k_aut, respData, attr->mac, data->nonce_s, 6138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_SIM_NONCE_S_LEN)) { 6148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "EAP-SIM: Re-authentication message " 6158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "did not include valid AT_MAC"); 6168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 6178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (attr->encr_data == NULL || attr->iv == NULL) { 6208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "EAP-SIM: Reauthentication " 6218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "message did not include encrypted data"); 6228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 6238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt decrypted = eap_sim_parse_encr(data->k_encr, attr->encr_data, 6268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt attr->encr_data_len, attr->iv, &eattr, 6278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0); 6288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (decrypted == NULL) { 6298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "EAP-SIM: Failed to parse encrypted " 6308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "data from reauthentication message"); 6318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 6328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eattr.counter != data->counter) { 6358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "EAP-SIM: Re-authentication message " 6368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "used incorrect counter %u, expected %u", 6378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eattr.counter, data->counter); 6388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 6398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(decrypted); 6418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt decrypted = NULL; 6428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-SIM: Re-authentication response includes " 6448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "the correct AT_MAC"); 6454530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 6464530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (eattr.counter_too_small) { 6474530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-AKA: Re-authentication response " 6484530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt "included AT_COUNTER_TOO_SMALL - starting full " 6494530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt "authentication"); 6504530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt data->start_round = -1; 6514530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt eap_sim_state(data, START); 6524530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt return; 6534530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt } 6544530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 6558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->eap_sim_aka_result_ind && attr->result_ind) { 6568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->use_result_ind = 1; 6578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->notification = EAP_SIM_SUCCESS; 6588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_state(data, NOTIFICATION); 6598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else 6608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_state(data, SUCCESS); 6618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->next_reauth_id) { 6634530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt eap_sim_db_add_reauth(sm->eap_sim_db_priv, data->permanent, 6644530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt data->next_reauth_id, 6658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->counter + 1, data->mk); 6668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->next_reauth_id = NULL; 6678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 6688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_db_remove_reauth(sm->eap_sim_db_priv, data->reauth); 6698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->reauth = NULL; 6708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 6738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtfail: 6754530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH; 6764530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt eap_sim_state(data, NOTIFICATION); 6778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_db_remove_reauth(sm->eap_sim_db_priv, data->reauth); 6788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->reauth = NULL; 6798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(decrypted); 6808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_sim_process_client_error(struct eap_sm *sm, 6848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_data *data, 6858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *respData, 6868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_attrs *attr) 6878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-SIM: Client reported error %d", 6898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt attr->client_error_code); 6908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->notification == EAP_SIM_SUCCESS && data->use_result_ind) 6918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_state(data, SUCCESS); 6928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 6938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_state(data, FAILURE); 6948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_sim_process_notification(struct eap_sm *sm, 6988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_data *data, 6998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *respData, 7008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_attrs *attr) 7018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-SIM: Client replied to notification"); 7038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->notification == EAP_SIM_SUCCESS && data->use_result_ind) 7048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_state(data, SUCCESS); 7058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 7068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_state(data, FAILURE); 7078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_sim_process(struct eap_sm *sm, void *priv, 7118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *respData) 7128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_data *data = priv; 7148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos, *end; 7158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 subtype; 7168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len; 7178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_attrs attr; 7188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_SIM, respData, &len); 7208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos == NULL || len < 3) 7218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 7228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt end = pos + len; 7248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt subtype = *pos; 7258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 3; 7268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7274530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (eap_sim_unexpected_subtype(data, subtype)) { 7284530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-SIM: Unrecognized or unexpected " 7294530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt "EAP-SIM Subtype in EAP Response"); 7304530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH; 7314530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt eap_sim_state(data, NOTIFICATION); 7324530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt return; 7334530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt } 7344530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 7358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_sim_parse_attr(pos, end, &attr, 0, 0)) { 7368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-SIM: Failed to parse attributes"); 7374530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (subtype != EAP_SIM_SUBTYPE_CLIENT_ERROR && 7384530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt (data->state == START || data->state == CHALLENGE || 7394530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt data->state == REAUTH)) { 7404530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt data->notification = 7414530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH; 7424530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt eap_sim_state(data, NOTIFICATION); 7434530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt return; 7444530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt } 7458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_state(data, FAILURE); 7468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 7478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (subtype == EAP_SIM_SUBTYPE_CLIENT_ERROR) { 7508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_process_client_error(sm, data, respData, &attr); 7518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 7528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (data->state) { 7558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case START: 7568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_process_start(sm, data, respData, &attr); 7578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 7588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case CHALLENGE: 7598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_process_challenge(sm, data, respData, &attr); 7608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 7618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case REAUTH: 7628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_process_reauth(sm, data, respData, &attr); 7638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 7648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case NOTIFICATION: 7658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_process_notification(sm, data, respData, &attr); 7668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 7678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 7688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-SIM: Unknown state %d in " 7698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "process", data->state); 7708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 7718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic Boolean eap_sim_isDone(struct eap_sm *sm, void *priv) 7768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_data *data = priv; 7788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return data->state == SUCCESS || data->state == FAILURE; 7798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic u8 * eap_sim_getKey(struct eap_sm *sm, void *priv, size_t *len) 7838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_data *data = priv; 7858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *key; 7868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->state != SUCCESS) 7888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 7898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key = os_malloc(EAP_SIM_KEYING_DATA_LEN); 7918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (key == NULL) 7928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 7938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(key, data->msk, EAP_SIM_KEYING_DATA_LEN); 7948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *len = EAP_SIM_KEYING_DATA_LEN; 7958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return key; 7968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic u8 * eap_sim_get_emsk(struct eap_sm *sm, void *priv, size_t *len) 8008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 8018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_data *data = priv; 8028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *key; 8038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->state != SUCCESS) 8058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 8068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key = os_malloc(EAP_EMSK_LEN); 8088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (key == NULL) 8098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 8108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(key, data->emsk, EAP_EMSK_LEN); 8118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *len = EAP_EMSK_LEN; 8128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return key; 8138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 8148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic Boolean eap_sim_isSuccess(struct eap_sm *sm, void *priv) 8178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 8188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_data *data = priv; 8198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return data->state == SUCCESS; 8208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 8218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 823fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidtstatic u8 * eap_sim_get_session_id(struct eap_sm *sm, void *priv, size_t *len) 824fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt{ 825fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt struct eap_sim_data *data = priv; 826fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt u8 *id; 827fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt 828fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt if (data->state != SUCCESS) 829fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt return NULL; 830fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt 831fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt *len = 1 + data->num_chal * GSM_RAND_LEN + EAP_SIM_NONCE_MT_LEN; 832fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt id = os_malloc(*len); 833fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt if (id == NULL) 834fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt return NULL; 835fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt 836fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt id[0] = EAP_TYPE_SIM; 837fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt os_memcpy(id + 1, data->rand, data->num_chal * GSM_RAND_LEN); 838fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt os_memcpy(id + 1 + data->num_chal * GSM_RAND_LEN, data->nonce_mt, 839fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt EAP_SIM_NONCE_MT_LEN); 840fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "EAP-SIM: Derived Session-Id", id, *len); 841fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt 842fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt return id; 843fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt} 844fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt 845fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt 8468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint eap_server_sim_register(void) 8478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 8488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_method *eap; 8498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret; 8508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION, 8528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_VENDOR_IETF, EAP_TYPE_SIM, "SIM"); 8538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap == NULL) 8548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 8558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->init = eap_sim_init; 8578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->reset = eap_sim_reset; 8588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->buildReq = eap_sim_buildReq; 8598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->check = eap_sim_check; 8608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->process = eap_sim_process; 8618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->isDone = eap_sim_isDone; 8628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->getKey = eap_sim_getKey; 8638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->isSuccess = eap_sim_isSuccess; 8648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->get_emsk = eap_sim_get_emsk; 865fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt eap->getSessionId = eap_sim_get_session_id; 8668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = eap_server_method_register(eap); 8688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret) 8698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_server_method_free(eap); 8708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 8718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 872