eap_server_aka.c revision 1f69aa52ea2e0a73ac502565df8c666ee49cab6a
18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* 28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * hostapd / EAP-AKA (RFC 4187) and EAP-AKA' (draft-arkko-eap-aka-kdf) 38d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Copyright (c) 2005-2008, Jouni Malinen <j@w1.fi> 48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 58d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This program is free software; you can redistribute it and/or modify 68d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * it under the terms of the GNU General Public License version 2 as 78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * published by the Free Software Foundation. 88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Alternatively, this software may be distributed under the terms of BSD 108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * license. 118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * See README and COPYING for more details. 138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "includes.h" 168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common.h" 188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/sha256.h" 198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/crypto.h" 208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/random.h" 218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eap_common/eap_sim_common.h" 228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eap_server/eap_i.h" 238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eap_server/eap_sim_db.h" 248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct eap_aka_data { 278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 mk[EAP_SIM_MK_LEN]; 288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 nonce_s[EAP_SIM_NONCE_S_LEN]; 298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 k_aut[EAP_AKA_PRIME_K_AUT_LEN]; 308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 k_encr[EAP_SIM_K_ENCR_LEN]; 318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 k_re[EAP_AKA_PRIME_K_RE_LEN]; /* EAP-AKA' only */ 328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 msk[EAP_SIM_KEYING_DATA_LEN]; 338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 emsk[EAP_EMSK_LEN]; 348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 rand[EAP_AKA_RAND_LEN]; 358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 autn[EAP_AKA_AUTN_LEN]; 368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 ck[EAP_AKA_CK_LEN]; 378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 ik[EAP_AKA_IK_LEN]; 388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 res[EAP_AKA_RES_MAX_LEN]; 398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t res_len; 408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt enum { 418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt IDENTITY, CHALLENGE, REAUTH, NOTIFICATION, SUCCESS, FAILURE 428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } state; 438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *next_pseudonym; 448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *next_reauth_id; 458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 counter; 468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_reauth *reauth; 478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int auts_reported; /* whether the current AUTS has been reported to the 488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_sim_db */ 498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 notification; 508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int use_result_ind; 518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *id_msgs; 538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int pending_id; 548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 eap_method; 558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *network_name; 568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t network_name_len; 578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 kdf; 588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}; 598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_aka_determine_identity(struct eap_sm *sm, 628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_aka_data *data, 638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int before_identity, int after_reauth); 648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const char * eap_aka_state_txt(int state) 678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (state) { 698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case IDENTITY: 708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "IDENTITY"; 718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case CHALLENGE: 728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "CHALLENGE"; 738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case REAUTH: 748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "REAUTH"; 758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case SUCCESS: 768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "SUCCESS"; 778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case FAILURE: 788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "FAILURE"; 798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case NOTIFICATION: 808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "NOTIFICATION"; 818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "Unknown?!"; 838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_aka_state(struct eap_aka_data *data, int state) 888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-AKA: %s -> %s", 908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_aka_state_txt(data->state), 918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_aka_state_txt(state)); 928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->state = state; 938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void * eap_aka_init(struct eap_sm *sm) 978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_aka_data *data; 998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->eap_sim_db_priv == NULL) { 1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "EAP-AKA: eap_sim_db not configured"); 1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data = os_zalloc(sizeof(*data)); 1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data == NULL) 1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->eap_method = EAP_TYPE_AKA; 1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->state = IDENTITY; 1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_aka_determine_identity(sm, data, 1, 0); 1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->pending_id = -1; 1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return data; 1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef EAP_SERVER_AKA_PRIME 1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void * eap_aka_prime_init(struct eap_sm *sm) 1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_aka_data *data; 1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: make ANID configurable; see 3GPP TS 24.302 */ 1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *network_name = "WLAN"; 1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->eap_sim_db_priv == NULL) { 1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "EAP-AKA: eap_sim_db not configured"); 1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data = os_zalloc(sizeof(*data)); 1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data == NULL) 1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->eap_method = EAP_TYPE_AKA_PRIME; 1361f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt data->network_name = (u8 *) os_strdup(network_name); 1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->network_name == NULL) { 1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data); 1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->network_name_len = os_strlen(network_name); 1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->state = IDENTITY; 1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_aka_determine_identity(sm, data, 1, 0); 1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->pending_id = -1; 1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return data; 1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* EAP_SERVER_AKA_PRIME */ 1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_aka_reset(struct eap_sm *sm, void *priv) 1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_aka_data *data = priv; 1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data->next_pseudonym); 1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data->next_reauth_id); 1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(data->id_msgs); 1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data->network_name); 1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data); 1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_aka_add_id_msg(struct eap_aka_data *data, 1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpabuf *msg) 1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (msg == NULL) 1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->id_msgs == NULL) { 1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->id_msgs = wpabuf_dup(msg); 1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return data->id_msgs == NULL ? -1 : 0; 1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpabuf_resize(&data->id_msgs, wpabuf_len(msg)) < 0) 1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_buf(data->id_msgs, msg); 1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_aka_add_checkcode(struct eap_aka_data *data, 1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_msg *msg) 1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *addr; 1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len; 1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 hash[SHA256_MAC_LEN]; 1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " AT_CHECKCODE"); 1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->id_msgs == NULL) { 1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * No EAP-AKA/Identity packets were exchanged - send empty 1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * checkcode. 1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_add(msg, EAP_SIM_AT_CHECKCODE, 0, NULL, 0); 1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Checkcode is SHA1 hash over all EAP-AKA/Identity packets. */ 2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr = wpabuf_head(data->id_msgs); 2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len = wpabuf_len(data->id_msgs); 2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "EAP-AKA: AT_CHECKCODE data", addr, len); 2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->eap_method == EAP_TYPE_AKA_PRIME) 2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sha256_vector(1, &addr, &len, hash); 2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sha1_vector(1, &addr, &len, hash); 2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_add(msg, EAP_SIM_AT_CHECKCODE, 0, hash, 2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->eap_method == EAP_TYPE_AKA_PRIME ? 2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_AKA_PRIME_CHECKCODE_LEN : EAP_AKA_CHECKCODE_LEN); 2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_aka_verify_checkcode(struct eap_aka_data *data, 2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *checkcode, size_t checkcode_len) 2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *addr; 2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len; 2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 hash[SHA256_MAC_LEN]; 2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t hash_len; 2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (checkcode == NULL) 2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->id_msgs == NULL) { 2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (checkcode_len != 0) { 2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-AKA: Checkcode from peer " 2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "indicates that AKA/Identity messages were " 2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "used, but they were not"); 2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hash_len = data->eap_method == EAP_TYPE_AKA_PRIME ? 2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_AKA_PRIME_CHECKCODE_LEN : EAP_AKA_CHECKCODE_LEN; 2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (checkcode_len != hash_len) { 2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-AKA: Checkcode from peer indicates " 2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "that AKA/Identity message were not used, but they " 2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "were"); 2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Checkcode is SHA1 hash over all EAP-AKA/Identity packets. */ 2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr = wpabuf_head(data->id_msgs); 2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len = wpabuf_len(data->id_msgs); 2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->eap_method == EAP_TYPE_AKA_PRIME) 2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sha256_vector(1, &addr, &len, hash); 2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sha1_vector(1, &addr, &len, hash); 2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(hash, checkcode, hash_len) != 0) { 2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-AKA: Mismatch in AT_CHECKCODE"); 2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_aka_build_identity(struct eap_sm *sm, 2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_aka_data *data, u8 id) 2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_msg *msg; 2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *buf; 2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-AKA: Generating Identity"); 2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = eap_sim_msg_init(EAP_CODE_REQUEST, id, data->eap_method, 2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_AKA_SUBTYPE_IDENTITY); 2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_sim_db_identity_known(sm->eap_sim_db_priv, sm->identity, 2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->identity_len)) { 2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " AT_PERMANENT_ID_REQ"); 2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_add(msg, EAP_SIM_AT_PERMANENT_ID_REQ, 0, NULL, 0); 2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * RFC 4187, Chap. 4.1.4 recommends that identity from EAP is 2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * ignored and the AKA/Identity is used to request the 2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * identity. 2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " AT_ANY_ID_REQ"); 2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_add(msg, EAP_SIM_AT_ANY_ID_REQ, 0, NULL, 0); 2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf = eap_sim_msg_finish(msg, NULL, NULL, 0); 2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_aka_add_id_msg(data, buf) < 0) { 2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(buf); 2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->pending_id = id; 2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return buf; 2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_aka_build_encr(struct eap_sm *sm, struct eap_aka_data *data, 2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_msg *msg, u16 counter, 2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *nonce_s) 2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data->next_pseudonym); 3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->next_pseudonym = 3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_db_get_next_pseudonym(sm->eap_sim_db_priv, 1); 3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data->next_reauth_id); 3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->counter <= EAP_AKA_MAX_FAST_REAUTHS) { 3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->next_reauth_id = 3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_db_get_next_reauth_id(sm->eap_sim_db_priv, 1); 3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-AKA: Max fast re-authentication " 3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "count exceeded - force full authentication"); 3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->next_reauth_id = NULL; 3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->next_pseudonym == NULL && data->next_reauth_id == NULL && 3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt counter == 0 && nonce_s == NULL) 3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " AT_IV"); 3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " AT_ENCR_DATA"); 3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_add_encr_start(msg, EAP_SIM_AT_IV, EAP_SIM_AT_ENCR_DATA); 3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (counter > 0) { 3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " *AT_COUNTER (%u)", counter); 3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_add(msg, EAP_SIM_AT_COUNTER, counter, NULL, 0); 3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (nonce_s) { 3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " *AT_NONCE_S"); 3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_add(msg, EAP_SIM_AT_NONCE_S, 0, nonce_s, 3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_SIM_NONCE_S_LEN); 3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->next_pseudonym) { 3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " *AT_NEXT_PSEUDONYM (%s)", 3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->next_pseudonym); 3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_add(msg, EAP_SIM_AT_NEXT_PSEUDONYM, 3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_strlen(data->next_pseudonym), 3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (u8 *) data->next_pseudonym, 3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_strlen(data->next_pseudonym)); 3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->next_reauth_id) { 3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " *AT_NEXT_REAUTH_ID (%s)", 3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->next_reauth_id); 3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_add(msg, EAP_SIM_AT_NEXT_REAUTH_ID, 3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_strlen(data->next_reauth_id), 3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (u8 *) data->next_reauth_id, 3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_strlen(data->next_reauth_id)); 3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_sim_msg_add_encr_end(msg, data->k_encr, EAP_SIM_AT_PADDING)) { 3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "EAP-AKA: Failed to encrypt " 3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "AT_ENCR_DATA"); 3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_aka_build_challenge(struct eap_sm *sm, 3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_aka_data *data, 3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 id) 3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_msg *msg; 3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-AKA: Generating Challenge"); 3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = eap_sim_msg_init(EAP_CODE_REQUEST, id, data->eap_method, 3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_AKA_SUBTYPE_CHALLENGE); 3698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " AT_RAND"); 3708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_add(msg, EAP_SIM_AT_RAND, 0, data->rand, EAP_AKA_RAND_LEN); 3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " AT_AUTN"); 3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_add(msg, EAP_SIM_AT_AUTN, 0, data->autn, EAP_AKA_AUTN_LEN); 3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->eap_method == EAP_TYPE_AKA_PRIME) { 3748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->kdf) { 3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Add the selected KDF into the beginning */ 3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " AT_KDF"); 3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_add(msg, EAP_SIM_AT_KDF, data->kdf, 3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NULL, 0); 3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " AT_KDF"); 3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_add(msg, EAP_SIM_AT_KDF, EAP_AKA_PRIME_KDF, 3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NULL, 0); 3838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " AT_KDF_INPUT"); 3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_add(msg, EAP_SIM_AT_KDF_INPUT, 3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->network_name_len, 3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->network_name, data->network_name_len); 3878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_aka_build_encr(sm, data, msg, 0, NULL)) { 3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_free(msg); 3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_aka_add_checkcode(data, msg); 3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->eap_sim_aka_result_ind) { 3978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " AT_RESULT_IND"); 3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_add(msg, EAP_SIM_AT_RESULT_IND, 0, NULL, 0); 3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef EAP_SERVER_AKA_PRIME 4028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->eap_method == EAP_TYPE_AKA) { 4038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 flags = 0; 4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int i; 4058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int aka_prime_preferred = 0; 4068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt i = 0; 4088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (sm->user && i < EAP_MAX_METHODS && 4098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (sm->user->methods[i].vendor != EAP_VENDOR_IETF || 4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->user->methods[i].method != EAP_TYPE_NONE)) { 4118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->user->methods[i].vendor == EAP_VENDOR_IETF) { 4128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->user->methods[i].method == 4138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_TYPE_AKA) 4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 4158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->user->methods[i].method == 4168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_TYPE_AKA_PRIME) { 4178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt aka_prime_preferred = 1; 4188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 4198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt i++; 4228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (aka_prime_preferred) 4258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt flags |= EAP_AKA_BIDDING_FLAG_D; 4268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_add(msg, EAP_SIM_AT_BIDDING, flags, NULL, 0); 4278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* EAP_SERVER_AKA_PRIME */ 4298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " AT_MAC"); 4318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC); 4328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return eap_sim_msg_finish(msg, data->k_aut, NULL, 0); 4338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_aka_build_reauth(struct eap_sm *sm, 4378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_aka_data *data, u8 id) 4388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_msg *msg; 4408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-AKA: Generating Re-authentication"); 4428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (random_get_bytes(data->nonce_s, EAP_SIM_NONCE_S_LEN)) 4448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_MSGDUMP, "EAP-AKA: NONCE_S", 4468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->nonce_s, EAP_SIM_NONCE_S_LEN); 4478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->eap_method == EAP_TYPE_AKA_PRIME) { 4498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_aka_prime_derive_keys_reauth(data->k_re, data->counter, 4508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->identity, 4518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->identity_len, 4528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->nonce_s, 4538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->msk, data->emsk); 4548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 4558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_derive_keys(data->mk, data->k_encr, data->k_aut, 4568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->msk, data->emsk); 4578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_derive_keys_reauth(data->counter, sm->identity, 4588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->identity_len, data->nonce_s, 4598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->mk, data->msk, data->emsk); 4608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = eap_sim_msg_init(EAP_CODE_REQUEST, id, data->eap_method, 4638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_AKA_SUBTYPE_REAUTHENTICATION); 4648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_aka_build_encr(sm, data, msg, data->counter, data->nonce_s)) { 4668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_free(msg); 4678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_aka_add_checkcode(data, msg); 4718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->eap_sim_aka_result_ind) { 4738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " AT_RESULT_IND"); 4748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_add(msg, EAP_SIM_AT_RESULT_IND, 0, NULL, 0); 4758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " AT_MAC"); 4788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC); 4798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return eap_sim_msg_finish(msg, data->k_aut, NULL, 0); 4808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_aka_build_notification(struct eap_sm *sm, 4848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_aka_data *data, 4858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 id) 4868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_msg *msg; 4888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-AKA: Generating Notification"); 4908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = eap_sim_msg_init(EAP_CODE_REQUEST, id, data->eap_method, 4918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_AKA_SUBTYPE_NOTIFICATION); 4928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " AT_NOTIFICATION (%d)", data->notification); 4938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_add(msg, EAP_SIM_AT_NOTIFICATION, data->notification, 4948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NULL, 0); 4958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->use_result_ind) { 4968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->reauth) { 4978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " AT_IV"); 4988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " AT_ENCR_DATA"); 4998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_add_encr_start(msg, EAP_SIM_AT_IV, 5008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_SIM_AT_ENCR_DATA); 5018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " *AT_COUNTER (%u)", 5028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->counter); 5038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_add(msg, EAP_SIM_AT_COUNTER, data->counter, 5048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NULL, 0); 5058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_sim_msg_add_encr_end(msg, data->k_encr, 5078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_SIM_AT_PADDING)) { 5088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "EAP-AKA: Failed to " 5098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "encrypt AT_ENCR_DATA"); 5108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_free(msg); 5118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 5128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " AT_MAC"); 5168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC); 5178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return eap_sim_msg_finish(msg, data->k_aut, NULL, 0); 5198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_aka_buildReq(struct eap_sm *sm, void *priv, u8 id) 5238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_aka_data *data = priv; 5258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->auts_reported = 0; 5278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (data->state) { 5288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case IDENTITY: 5298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return eap_aka_build_identity(sm, data, id); 5308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case CHALLENGE: 5318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return eap_aka_build_challenge(sm, data, id); 5328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case REAUTH: 5338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return eap_aka_build_reauth(sm, data, id); 5348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case NOTIFICATION: 5358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return eap_aka_build_notification(sm, data, id); 5368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 5378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-AKA: Unknown state %d in " 5388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "buildReq", data->state); 5398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 5408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 5428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic Boolean eap_aka_check(struct eap_sm *sm, void *priv, 5468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *respData) 5478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_aka_data *data = priv; 5498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos; 5508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len; 5518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = eap_hdr_validate(EAP_VENDOR_IETF, data->eap_method, respData, 5538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &len); 5548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos == NULL || len < 3) { 5558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-AKA: Invalid frame"); 5568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return TRUE; 5578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return FALSE; 5608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic Boolean eap_aka_subtype_ok(struct eap_aka_data *data, u8 subtype) 5648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (subtype == EAP_AKA_SUBTYPE_CLIENT_ERROR || 5668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt subtype == EAP_AKA_SUBTYPE_AUTHENTICATION_REJECT) 5678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return FALSE; 5688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (data->state) { 5708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case IDENTITY: 5718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (subtype != EAP_AKA_SUBTYPE_IDENTITY) { 5728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-AKA: Unexpected response " 5738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "subtype %d", subtype); 5748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return TRUE; 5758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 5778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case CHALLENGE: 5788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (subtype != EAP_AKA_SUBTYPE_CHALLENGE && 5798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt subtype != EAP_AKA_SUBTYPE_SYNCHRONIZATION_FAILURE) { 5808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-AKA: Unexpected response " 5818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "subtype %d", subtype); 5828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return TRUE; 5838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 5858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case REAUTH: 5868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (subtype != EAP_AKA_SUBTYPE_REAUTHENTICATION) { 5878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-AKA: Unexpected response " 5888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "subtype %d", subtype); 5898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return TRUE; 5908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 5928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case NOTIFICATION: 5938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (subtype != EAP_AKA_SUBTYPE_NOTIFICATION) { 5948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-AKA: Unexpected response " 5958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "subtype %d", subtype); 5968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return TRUE; 5978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 5998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 6008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-AKA: Unexpected state (%d) for " 6018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "processing a response", data->state); 6028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return TRUE; 6038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return FALSE; 6068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_aka_determine_identity(struct eap_sm *sm, 6108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_aka_data *data, 6118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int before_identity, int after_reauth) 6128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *identity; 6148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t identity_len; 6158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int res; 6168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt identity = NULL; 6188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt identity_len = 0; 6198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (after_reauth && data->reauth) { 6218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt identity = data->reauth->identity; 6228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt identity_len = data->reauth->identity_len; 6238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (sm->identity && sm->identity_len > 0 && 6248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->identity[0] == EAP_AKA_PERMANENT_PREFIX) { 6258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt identity = sm->identity; 6268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt identity_len = sm->identity_len; 6278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 6288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt identity = eap_sim_db_get_permanent(sm->eap_sim_db_priv, 6298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->identity, 6308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->identity_len, 6318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &identity_len); 6328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (identity == NULL) { 6338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->reauth = eap_sim_db_get_reauth_entry( 6348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->eap_sim_db_priv, sm->identity, 6358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->identity_len); 6368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->reauth && 6378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->reauth->aka_prime != 6388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (data->eap_method == EAP_TYPE_AKA_PRIME)) { 6398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-AKA: Reauth data " 6408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "was for different AKA version"); 6418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->reauth = NULL; 6428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->reauth) { 6448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-AKA: Using fast " 6458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "re-authentication"); 6468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt identity = data->reauth->identity; 6478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt identity_len = data->reauth->identity_len; 6488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->counter = data->reauth->counter; 6498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->eap_method == EAP_TYPE_AKA_PRIME) { 6508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(data->k_encr, 6518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->reauth->k_encr, 6528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_SIM_K_ENCR_LEN); 6538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(data->k_aut, 6548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->reauth->k_aut, 6558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_AKA_PRIME_K_AUT_LEN); 6568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(data->k_re, 6578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->reauth->k_re, 6588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_AKA_PRIME_K_RE_LEN); 6598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 6608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(data->mk, data->reauth->mk, 6618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_SIM_MK_LEN); 6628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (identity == NULL || 6688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_db_identity_known(sm->eap_sim_db_priv, sm->identity, 6698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->identity_len) < 0) { 6708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (before_identity) { 6718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-AKA: Permanent user name " 6728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "not known - send AKA-Identity request"); 6738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_aka_state(data, IDENTITY); 6748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 6758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 6768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-AKA: Unknown whether the " 6778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "permanent user name is known; try to use " 6788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "it"); 6798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* eap_sim_db_get_aka_auth() will report failure, if 6808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * this identity is not known. */ 6818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, "EAP-AKA: Identity", 6858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt identity, identity_len); 6868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!after_reauth && data->reauth) { 6888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_aka_state(data, REAUTH); 6898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 6908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = eap_sim_db_get_aka_auth(sm->eap_sim_db_priv, identity, 6938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt identity_len, data->rand, data->autn, 6948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->ik, data->ck, data->res, 6958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &data->res_len, sm); 6968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res == EAP_SIM_DB_PENDING) { 6978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-AKA: AKA authentication data " 6988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "not yet available - pending request"); 6998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->method_pending = METHOD_PENDING_WAIT; 7008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 7018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef EAP_SERVER_AKA_PRIME 7048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->eap_method == EAP_TYPE_AKA_PRIME) { 7058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Note: AUTN = (SQN ^ AK) || AMF || MAC which gives us the 7068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * needed 6-octet SQN ^AK for CK',IK' derivation */ 7078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_aka_prime_derive_ck_ik_prime(data->ck, data->ik, 7088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->autn, 7098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->network_name, 7108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->network_name_len); 7118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* EAP_SERVER_AKA_PRIME */ 7138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->reauth = NULL; 7158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->counter = 0; /* reset re-auth counter since this is full auth */ 7168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res != 0) { 7188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-AKA: Failed to get AKA " 7198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "authentication data for the peer"); 7208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH; 7218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_aka_state(data, NOTIFICATION); 7228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 7238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->method_pending == METHOD_PENDING_WAIT) { 7258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-AKA: AKA authentication data " 7268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "available - abort pending wait"); 7278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->method_pending = METHOD_PENDING_NONE; 7288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt identity_len = sm->identity_len; 7318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (identity_len > 0 && sm->identity[identity_len - 1] == '\0') { 7328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-AKA: Workaround - drop last null " 7338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "character from identity"); 7348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt identity_len--; 7358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, "EAP-AKA: Identity for MK derivation", 7378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->identity, identity_len); 7388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->eap_method == EAP_TYPE_AKA_PRIME) { 7408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_aka_prime_derive_keys(identity, identity_len, data->ik, 7418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->ck, data->k_encr, data->k_aut, 7428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->k_re, data->msk, data->emsk); 7438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 7448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_aka_derive_mk(sm->identity, identity_len, data->ik, 7458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->ck, data->mk); 7468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_derive_keys(data->mk, data->k_encr, data->k_aut, 7478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->msk, data->emsk); 7488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_aka_state(data, CHALLENGE); 7518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_aka_process_identity(struct eap_sm *sm, 7558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_aka_data *data, 7568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *respData, 7578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_attrs *attr) 7588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-AKA: Processing Identity"); 7608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (attr->mac || attr->iv || attr->encr_data) { 7628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "EAP-AKA: Unexpected attribute " 7638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "received in EAP-Response/AKA-Identity"); 7648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH; 7658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_aka_state(data, NOTIFICATION); 7668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 7678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (attr->identity) { 7708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(sm->identity); 7718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->identity = os_malloc(attr->identity_len); 7728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->identity) { 7738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(sm->identity, attr->identity, 7748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt attr->identity_len); 7758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->identity_len = attr->identity_len; 7768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_aka_determine_identity(sm, data, 0, 0); 7808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_get_id(respData) == data->pending_id) { 7818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->pending_id = -1; 7828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_aka_add_id_msg(data, respData); 7838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_aka_verify_mac(struct eap_aka_data *data, 7888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpabuf *req, 7898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *mac, const u8 *extra, 7908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t extra_len) 7918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->eap_method == EAP_TYPE_AKA_PRIME) 7938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return eap_sim_verify_mac_sha256(data->k_aut, req, mac, extra, 7948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt extra_len); 7958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return eap_sim_verify_mac(data->k_aut, req, mac, extra, extra_len); 7968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_aka_process_challenge(struct eap_sm *sm, 8008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_aka_data *data, 8018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *respData, 8028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_attrs *attr) 8038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 8048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *identity; 8058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t identity_len; 8068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-AKA: Processing Challenge"); 8088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef EAP_SERVER_AKA_PRIME 8108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#if 0 8118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* KDF negotiation; to be enabled only after more than one KDF is 8128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * supported */ 8138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->eap_method == EAP_TYPE_AKA_PRIME && 8148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt attr->kdf_count == 1 && attr->mac == NULL) { 8158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (attr->kdf[0] != EAP_AKA_PRIME_KDF) { 8168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "EAP-AKA': Peer selected " 8178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "unknown KDF"); 8188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->notification = 8198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH; 8208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_aka_state(data, NOTIFICATION); 8218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 8228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->kdf = attr->kdf[0]; 8258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Allow negotiation to continue with the selected KDF by 8278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * sending another Challenge message */ 8288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-AKA': KDF %d selected", data->kdf); 8298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 8308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif 8328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* EAP_SERVER_AKA_PRIME */ 8338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (attr->checkcode && 8358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_aka_verify_checkcode(data, attr->checkcode, 8368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt attr->checkcode_len)) { 8378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "EAP-AKA: Invalid AT_CHECKCODE in the " 8388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "message"); 8398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH; 8408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_aka_state(data, NOTIFICATION); 8418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 8428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (attr->mac == NULL || 8448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_aka_verify_mac(data, respData, attr->mac, NULL, 0)) { 8458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "EAP-AKA: Challenge message " 8468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "did not include valid AT_MAC"); 8478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH; 8488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_aka_state(data, NOTIFICATION); 8498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 8508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 8538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * AT_RES is padded, so verify that there is enough room for RES and 8548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * that the RES length in bits matches with the expected RES. 8558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 8568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (attr->res == NULL || attr->res_len < data->res_len || 8578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt attr->res_len_bits != data->res_len * 8 || 8588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcmp(attr->res, data->res, data->res_len) != 0) { 8598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "EAP-AKA: Challenge message did not " 8608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "include valid AT_RES (attr len=%lu, res len=%lu " 8618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "bits, expected %lu bits)", 8628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) attr->res_len, 8638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) attr->res_len_bits, 8648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) data->res_len * 8); 8658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH; 8668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_aka_state(data, NOTIFICATION); 8678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 8688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-AKA: Challenge response includes the " 8718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "correct AT_MAC"); 8728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->eap_sim_aka_result_ind && attr->result_ind) { 8738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->use_result_ind = 1; 8748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->notification = EAP_SIM_SUCCESS; 8758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_aka_state(data, NOTIFICATION); 8768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else 8778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_aka_state(data, SUCCESS); 8788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt identity = eap_sim_db_get_permanent(sm->eap_sim_db_priv, sm->identity, 8808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->identity_len, &identity_len); 8818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (identity == NULL) { 8828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt identity = sm->identity; 8838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt identity_len = sm->identity_len; 8848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->next_pseudonym) { 8878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_db_add_pseudonym(sm->eap_sim_db_priv, identity, 8888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt identity_len, 8898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->next_pseudonym); 8908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->next_pseudonym = NULL; 8918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->next_reauth_id) { 8938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->eap_method == EAP_TYPE_AKA_PRIME) { 8948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef EAP_SERVER_AKA_PRIME 8958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_db_add_reauth_prime(sm->eap_sim_db_priv, 8968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt identity, 8978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt identity_len, 8988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->next_reauth_id, 8998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->counter + 1, 9008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->k_encr, data->k_aut, 9018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->k_re); 9028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* EAP_SERVER_AKA_PRIME */ 9038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 9048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_db_add_reauth(sm->eap_sim_db_priv, identity, 9058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt identity_len, 9068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->next_reauth_id, 9078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->counter + 1, 9088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->mk); 9098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->next_reauth_id = NULL; 9118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 9138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_aka_process_sync_failure(struct eap_sm *sm, 9168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_aka_data *data, 9178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *respData, 9188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_attrs *attr) 9198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 9208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-AKA: Processing Synchronization-Failure"); 9218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (attr->auts == NULL) { 9238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "EAP-AKA: Synchronization-Failure " 9248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "message did not include valid AT_AUTS"); 9258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH; 9268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_aka_state(data, NOTIFICATION); 9278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 9288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Avoid re-reporting AUTS when processing pending EAP packet by 9318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * maintaining a local flag stating whether this AUTS has already been 9328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * reported. */ 9338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!data->auts_reported && 9348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_db_resynchronize(sm->eap_sim_db_priv, sm->identity, 9358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->identity_len, attr->auts, 9368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->rand)) { 9378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "EAP-AKA: Resynchronization failed"); 9388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH; 9398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_aka_state(data, NOTIFICATION); 9408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 9418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->auts_reported = 1; 9438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Try again after resynchronization */ 9458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_aka_determine_identity(sm, data, 0, 0); 9468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 9478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_aka_process_reauth(struct eap_sm *sm, 9508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_aka_data *data, 9518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *respData, 9528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_attrs *attr) 9538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 9548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_attrs eattr; 9558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *decrypted = NULL; 9568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *identity, *id2; 9578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t identity_len, id2_len; 9588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-AKA: Processing Reauthentication"); 9608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (attr->mac == NULL || 9628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_aka_verify_mac(data, respData, attr->mac, data->nonce_s, 9638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_SIM_NONCE_S_LEN)) { 9648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "EAP-AKA: Re-authentication message " 9658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "did not include valid AT_MAC"); 9668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 9678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (attr->encr_data == NULL || attr->iv == NULL) { 9708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "EAP-AKA: Reauthentication " 9718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "message did not include encrypted data"); 9728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 9738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt decrypted = eap_sim_parse_encr(data->k_encr, attr->encr_data, 9768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt attr->encr_data_len, attr->iv, &eattr, 9778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0); 9788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (decrypted == NULL) { 9798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "EAP-AKA: Failed to parse encrypted " 9808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "data from reauthentication message"); 9818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 9828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eattr.counter != data->counter) { 9858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "EAP-AKA: Re-authentication message " 9868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "used incorrect counter %u, expected %u", 9878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eattr.counter, data->counter); 9888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 9898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(decrypted); 9918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt decrypted = NULL; 9928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-AKA: Re-authentication response includes " 9948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "the correct AT_MAC"); 9958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eattr.counter_too_small) { 9978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-AKA: Re-authentication response " 9988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "included AT_COUNTER_TOO_SMALL - starting full " 9998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "authentication"); 10008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_aka_determine_identity(sm, data, 0, 1); 10018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 10028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->eap_sim_aka_result_ind && attr->result_ind) { 10058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->use_result_ind = 1; 10068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->notification = EAP_SIM_SUCCESS; 10078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_aka_state(data, NOTIFICATION); 10088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else 10098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_aka_state(data, SUCCESS); 10108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->reauth) { 10128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt identity = data->reauth->identity; 10138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt identity_len = data->reauth->identity_len; 10148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 10158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt identity = sm->identity; 10168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt identity_len = sm->identity_len; 10178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt id2 = eap_sim_db_get_permanent(sm->eap_sim_db_priv, identity, 10208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt identity_len, &id2_len); 10218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (id2) { 10228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt identity = id2; 10238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt identity_len = id2_len; 10248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->next_pseudonym) { 10278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_db_add_pseudonym(sm->eap_sim_db_priv, identity, 10288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt identity_len, data->next_pseudonym); 10298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->next_pseudonym = NULL; 10308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->next_reauth_id) { 10328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->eap_method == EAP_TYPE_AKA_PRIME) { 10338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef EAP_SERVER_AKA_PRIME 10348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_db_add_reauth_prime(sm->eap_sim_db_priv, 10358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt identity, 10368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt identity_len, 10378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->next_reauth_id, 10388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->counter + 1, 10398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->k_encr, data->k_aut, 10408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->k_re); 10418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* EAP_SERVER_AKA_PRIME */ 10428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 10438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_db_add_reauth(sm->eap_sim_db_priv, identity, 10448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt identity_len, 10458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->next_reauth_id, 10468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->counter + 1, 10478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->mk); 10488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->next_reauth_id = NULL; 10508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 10518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_db_remove_reauth(sm->eap_sim_db_priv, data->reauth); 10528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->reauth = NULL; 10538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 10568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtfail: 10588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH; 10598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_aka_state(data, NOTIFICATION); 10608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_db_remove_reauth(sm->eap_sim_db_priv, data->reauth); 10618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->reauth = NULL; 10628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(decrypted); 10638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 10648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_aka_process_client_error(struct eap_sm *sm, 10678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_aka_data *data, 10688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *respData, 10698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_attrs *attr) 10708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 10718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-AKA: Client reported error %d", 10728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt attr->client_error_code); 10738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->notification == EAP_SIM_SUCCESS && data->use_result_ind) 10748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_aka_state(data, SUCCESS); 10758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 10768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_aka_state(data, FAILURE); 10778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 10788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_aka_process_authentication_reject( 10818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sm *sm, struct eap_aka_data *data, 10828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *respData, struct eap_sim_attrs *attr) 10838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 10848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-AKA: Client rejected authentication"); 10858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_aka_state(data, FAILURE); 10868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 10878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_aka_process_notification(struct eap_sm *sm, 10908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_aka_data *data, 10918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *respData, 10928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_attrs *attr) 10938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 10948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-AKA: Client replied to notification"); 10958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->notification == EAP_SIM_SUCCESS && data->use_result_ind) 10968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_aka_state(data, SUCCESS); 10978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 10988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_aka_state(data, FAILURE); 10998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 11008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_aka_process(struct eap_sm *sm, void *priv, 11038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *respData) 11048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 11058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_aka_data *data = priv; 11068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos, *end; 11078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 subtype; 11088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len; 11098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_attrs attr; 11108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = eap_hdr_validate(EAP_VENDOR_IETF, data->eap_method, respData, 11128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &len); 11138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos == NULL || len < 3) 11148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 11158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt end = pos + len; 11178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt subtype = *pos; 11188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 3; 11198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_aka_subtype_ok(data, subtype)) { 11218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-AKA: Unrecognized or unexpected " 11228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "EAP-AKA Subtype in EAP Response"); 11238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH; 11248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_aka_state(data, NOTIFICATION); 11258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 11268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_sim_parse_attr(pos, end, &attr, 11298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->eap_method == EAP_TYPE_AKA_PRIME ? 2 : 1, 11308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0)) { 11318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-AKA: Failed to parse attributes"); 11328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH; 11338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_aka_state(data, NOTIFICATION); 11348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 11358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (subtype == EAP_AKA_SUBTYPE_CLIENT_ERROR) { 11388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_aka_process_client_error(sm, data, respData, &attr); 11398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 11408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (subtype == EAP_AKA_SUBTYPE_AUTHENTICATION_REJECT) { 11438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_aka_process_authentication_reject(sm, data, respData, 11448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &attr); 11458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 11468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (data->state) { 11498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case IDENTITY: 11508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_aka_process_identity(sm, data, respData, &attr); 11518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 11528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case CHALLENGE: 11538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (subtype == EAP_AKA_SUBTYPE_SYNCHRONIZATION_FAILURE) { 11548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_aka_process_sync_failure(sm, data, respData, 11558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &attr); 11568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 11578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_aka_process_challenge(sm, data, respData, &attr); 11588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 11608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case REAUTH: 11618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_aka_process_reauth(sm, data, respData, &attr); 11628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 11638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case NOTIFICATION: 11648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_aka_process_notification(sm, data, respData, &attr); 11658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 11668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 11678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-AKA: Unknown state %d in " 11688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "process", data->state); 11698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 11708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 11728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic Boolean eap_aka_isDone(struct eap_sm *sm, void *priv) 11758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 11768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_aka_data *data = priv; 11778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return data->state == SUCCESS || data->state == FAILURE; 11788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 11798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic u8 * eap_aka_getKey(struct eap_sm *sm, void *priv, size_t *len) 11828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 11838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_aka_data *data = priv; 11848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *key; 11858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->state != SUCCESS) 11878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 11888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key = os_malloc(EAP_SIM_KEYING_DATA_LEN); 11908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (key == NULL) 11918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 11928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(key, data->msk, EAP_SIM_KEYING_DATA_LEN); 11938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *len = EAP_SIM_KEYING_DATA_LEN; 11948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return key; 11958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 11968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic u8 * eap_aka_get_emsk(struct eap_sm *sm, void *priv, size_t *len) 11998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 12008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_aka_data *data = priv; 12018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *key; 12028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->state != SUCCESS) 12048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 12058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key = os_malloc(EAP_EMSK_LEN); 12078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (key == NULL) 12088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 12098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(key, data->emsk, EAP_EMSK_LEN); 12108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *len = EAP_EMSK_LEN; 12118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return key; 12128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 12138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic Boolean eap_aka_isSuccess(struct eap_sm *sm, void *priv) 12168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 12178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_aka_data *data = priv; 12188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return data->state == SUCCESS; 12198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 12208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint eap_server_aka_register(void) 12238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 12248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_method *eap; 12258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret; 12268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION, 12288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_VENDOR_IETF, EAP_TYPE_AKA, "AKA"); 12298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap == NULL) 12308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 12318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->init = eap_aka_init; 12338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->reset = eap_aka_reset; 12348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->buildReq = eap_aka_buildReq; 12358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->check = eap_aka_check; 12368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->process = eap_aka_process; 12378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->isDone = eap_aka_isDone; 12388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->getKey = eap_aka_getKey; 12398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->isSuccess = eap_aka_isSuccess; 12408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->get_emsk = eap_aka_get_emsk; 12418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = eap_server_method_register(eap); 12438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret) 12448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_server_method_free(eap); 12458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 12468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 12478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef EAP_SERVER_AKA_PRIME 12508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint eap_server_aka_prime_register(void) 12518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 12528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_method *eap; 12538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret; 12548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION, 12568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_VENDOR_IETF, EAP_TYPE_AKA_PRIME, 12578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "AKA'"); 12588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap == NULL) 12598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 12608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->init = eap_aka_prime_init; 12628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->reset = eap_aka_reset; 12638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->buildReq = eap_aka_buildReq; 12648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->check = eap_aka_check; 12658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->process = eap_aka_process; 12668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->isDone = eap_aka_isDone; 12678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->getKey = eap_aka_getKey; 12688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->isSuccess = eap_aka_isSuccess; 12698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->get_emsk = eap_aka_get_emsk; 12708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = eap_server_method_register(eap); 12728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret) 12738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_server_method_free(eap); 12748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 12768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 12778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* EAP_SERVER_AKA_PRIME */ 1278