18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* 204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * hostapd / EAP-AKA (RFC 4187) and EAP-AKA' (RFC 5448) 304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * Copyright (c) 2005-2012, Jouni Malinen <j@w1.fi> 48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 5c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * This software may be distributed under the terms of the BSD license. 6c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * See README for more details. 78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "includes.h" 108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common.h" 128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/sha256.h" 138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/crypto.h" 148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/random.h" 158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eap_common/eap_sim_common.h" 168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eap_server/eap_i.h" 178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eap_server/eap_sim_db.h" 188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct eap_aka_data { 218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 mk[EAP_SIM_MK_LEN]; 228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 nonce_s[EAP_SIM_NONCE_S_LEN]; 238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 k_aut[EAP_AKA_PRIME_K_AUT_LEN]; 248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 k_encr[EAP_SIM_K_ENCR_LEN]; 258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 k_re[EAP_AKA_PRIME_K_RE_LEN]; /* EAP-AKA' only */ 268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 msk[EAP_SIM_KEYING_DATA_LEN]; 278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 emsk[EAP_EMSK_LEN]; 288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 rand[EAP_AKA_RAND_LEN]; 298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 autn[EAP_AKA_AUTN_LEN]; 308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 ck[EAP_AKA_CK_LEN]; 318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 ik[EAP_AKA_IK_LEN]; 328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 res[EAP_AKA_RES_MAX_LEN]; 338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t res_len; 348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt enum { 358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt IDENTITY, CHALLENGE, REAUTH, NOTIFICATION, SUCCESS, FAILURE 368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } state; 378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *next_pseudonym; 388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *next_reauth_id; 398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 counter; 408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_reauth *reauth; 418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int auts_reported; /* whether the current AUTS has been reported to the 428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_sim_db */ 438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 notification; 448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int use_result_ind; 458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *id_msgs; 478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int pending_id; 488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 eap_method; 498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *network_name; 508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t network_name_len; 518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 kdf; 524530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt int identity_round; 534530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt char permanent[20]; /* Permanent username */ 548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}; 558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 574530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtstatic void eap_aka_fullauth(struct eap_sm *sm, struct eap_aka_data *data); 588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const char * eap_aka_state_txt(int state) 618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (state) { 638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case IDENTITY: 648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "IDENTITY"; 658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case CHALLENGE: 668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "CHALLENGE"; 678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case REAUTH: 688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "REAUTH"; 698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case SUCCESS: 708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "SUCCESS"; 718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case FAILURE: 728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "FAILURE"; 738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case NOTIFICATION: 748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "NOTIFICATION"; 758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "Unknown?!"; 778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_aka_state(struct eap_aka_data *data, int state) 828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-AKA: %s -> %s", 848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_aka_state_txt(data->state), 858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_aka_state_txt(state)); 868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->state = state; 878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 904530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtstatic int eap_aka_check_identity_reauth(struct eap_sm *sm, 914530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt struct eap_aka_data *data, 924530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt const char *username) 934530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt{ 944530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (data->eap_method == EAP_TYPE_AKA_PRIME && 954530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt username[0] != EAP_AKA_PRIME_REAUTH_ID_PREFIX) 964530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt return 0; 974530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (data->eap_method == EAP_TYPE_AKA && 984530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt username[0] != EAP_AKA_REAUTH_ID_PREFIX) 994530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt return 0; 1004530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 1014530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-AKA: Reauth username '%s'", username); 1024530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt data->reauth = eap_sim_db_get_reauth_entry(sm->eap_sim_db_priv, 1034530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt username); 1044530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (data->reauth == NULL) { 1054530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-AKA: Unknown reauth identity - " 1064530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt "request full auth identity"); 1074530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt /* Remain in IDENTITY state for another round */ 1084530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt return 0; 1094530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt } 1104530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 1114530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-AKA: Using fast re-authentication"); 1124530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt os_strlcpy(data->permanent, data->reauth->permanent, 1134530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt sizeof(data->permanent)); 1144530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt data->counter = data->reauth->counter; 1154530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (data->eap_method == EAP_TYPE_AKA_PRIME) { 1164530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt os_memcpy(data->k_encr, data->reauth->k_encr, 1174530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt EAP_SIM_K_ENCR_LEN); 1184530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt os_memcpy(data->k_aut, data->reauth->k_aut, 1194530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt EAP_AKA_PRIME_K_AUT_LEN); 1204530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt os_memcpy(data->k_re, data->reauth->k_re, 1214530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt EAP_AKA_PRIME_K_RE_LEN); 1224530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt } else { 1234530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt os_memcpy(data->mk, data->reauth->mk, EAP_SIM_MK_LEN); 1244530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt } 1254530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 1264530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt eap_aka_state(data, REAUTH); 1274530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt return 1; 1284530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt} 1294530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 1304530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 1314530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtstatic void eap_aka_check_identity(struct eap_sm *sm, 1324530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt struct eap_aka_data *data) 1334530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt{ 1344530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt char *username; 1354530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 1364530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt /* Check if we already know the identity from EAP-Response/Identity */ 1374530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 1384530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt username = sim_get_username(sm->identity, sm->identity_len); 1394530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (username == NULL) 1404530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt return; 1414530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 1424530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (eap_aka_check_identity_reauth(sm, data, username) > 0) { 1434530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt os_free(username); 1444530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt /* 1454530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt * Since re-auth username was recognized, skip AKA/Identity 1464530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt * exchange. 1474530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt */ 1484530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt return; 1494530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt } 1504530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 1514530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if ((data->eap_method == EAP_TYPE_AKA_PRIME && 1524530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt username[0] == EAP_AKA_PRIME_PSEUDONYM_PREFIX) || 1534530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt (data->eap_method == EAP_TYPE_AKA && 1544530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt username[0] == EAP_AKA_PSEUDONYM_PREFIX)) { 1554530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt const char *permanent; 1564530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-AKA: Pseudonym username '%s'", 1574530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt username); 1584530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt permanent = eap_sim_db_get_permanent( 1594530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt sm->eap_sim_db_priv, username); 1604530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (permanent == NULL) { 1614530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt os_free(username); 1624530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-AKA: Unknown pseudonym " 1634530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt "identity - request permanent identity"); 1644530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt /* Remain in IDENTITY state for another round */ 1654530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt return; 1664530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt } 1674530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt os_strlcpy(data->permanent, permanent, 1684530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt sizeof(data->permanent)); 1694530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt /* 1704530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt * Since pseudonym username was recognized, skip AKA/Identity 1714530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt * exchange. 1724530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt */ 1734530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt eap_aka_fullauth(sm, data); 1744530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt } 1754530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 1764530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt os_free(username); 1774530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt} 1784530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 1794530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void * eap_aka_init(struct eap_sm *sm) 1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_aka_data *data; 1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->eap_sim_db_priv == NULL) { 1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "EAP-AKA: eap_sim_db not configured"); 1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data = os_zalloc(sizeof(*data)); 1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data == NULL) 1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->eap_method = EAP_TYPE_AKA; 1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->state = IDENTITY; 1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->pending_id = -1; 1974530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt eap_aka_check_identity(sm, data); 1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return data; 2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef EAP_SERVER_AKA_PRIME 2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void * eap_aka_prime_init(struct eap_sm *sm) 2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_aka_data *data; 2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: make ANID configurable; see 3GPP TS 24.302 */ 2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *network_name = "WLAN"; 2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->eap_sim_db_priv == NULL) { 2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "EAP-AKA: eap_sim_db not configured"); 2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data = os_zalloc(sizeof(*data)); 2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data == NULL) 2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->eap_method = EAP_TYPE_AKA_PRIME; 2201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt data->network_name = (u8 *) os_strdup(network_name); 2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->network_name == NULL) { 2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data); 2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->network_name_len = os_strlen(network_name); 2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->state = IDENTITY; 2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->pending_id = -1; 2304530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt eap_aka_check_identity(sm, data); 2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return data; 2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* EAP_SERVER_AKA_PRIME */ 2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_aka_reset(struct eap_sm *sm, void *priv) 2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_aka_data *data = priv; 2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data->next_pseudonym); 2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data->next_reauth_id); 2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(data->id_msgs); 2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data->network_name); 244c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt bin_clear_free(data, sizeof(*data)); 2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_aka_add_id_msg(struct eap_aka_data *data, 2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpabuf *msg) 2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (msg == NULL) 2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->id_msgs == NULL) { 2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->id_msgs = wpabuf_dup(msg); 2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return data->id_msgs == NULL ? -1 : 0; 2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpabuf_resize(&data->id_msgs, wpabuf_len(msg)) < 0) 2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_buf(data->id_msgs, msg); 2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_aka_add_checkcode(struct eap_aka_data *data, 2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_msg *msg) 2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *addr; 2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len; 2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 hash[SHA256_MAC_LEN]; 2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " AT_CHECKCODE"); 2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->id_msgs == NULL) { 2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * No EAP-AKA/Identity packets were exchanged - send empty 2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * checkcode. 2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_add(msg, EAP_SIM_AT_CHECKCODE, 0, NULL, 0); 2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Checkcode is SHA1 hash over all EAP-AKA/Identity packets. */ 2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr = wpabuf_head(data->id_msgs); 2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len = wpabuf_len(data->id_msgs); 2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "EAP-AKA: AT_CHECKCODE data", addr, len); 2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->eap_method == EAP_TYPE_AKA_PRIME) 2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sha256_vector(1, &addr, &len, hash); 2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sha1_vector(1, &addr, &len, hash); 2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_add(msg, EAP_SIM_AT_CHECKCODE, 0, hash, 2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->eap_method == EAP_TYPE_AKA_PRIME ? 2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_AKA_PRIME_CHECKCODE_LEN : EAP_AKA_CHECKCODE_LEN); 2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_aka_verify_checkcode(struct eap_aka_data *data, 3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *checkcode, size_t checkcode_len) 3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *addr; 3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len; 3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 hash[SHA256_MAC_LEN]; 3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t hash_len; 3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (checkcode == NULL) 3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->id_msgs == NULL) { 3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (checkcode_len != 0) { 3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-AKA: Checkcode from peer " 3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "indicates that AKA/Identity messages were " 3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "used, but they were not"); 3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hash_len = data->eap_method == EAP_TYPE_AKA_PRIME ? 3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_AKA_PRIME_CHECKCODE_LEN : EAP_AKA_CHECKCODE_LEN; 3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (checkcode_len != hash_len) { 3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-AKA: Checkcode from peer indicates " 3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "that AKA/Identity message were not used, but they " 3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "were"); 3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Checkcode is SHA1 hash over all EAP-AKA/Identity packets. */ 3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr = wpabuf_head(data->id_msgs); 3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len = wpabuf_len(data->id_msgs); 3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->eap_method == EAP_TYPE_AKA_PRIME) 3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sha256_vector(1, &addr, &len, hash); 3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sha1_vector(1, &addr, &len, hash); 3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 339c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt if (os_memcmp_const(hash, checkcode, hash_len) != 0) { 3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-AKA: Mismatch in AT_CHECKCODE"); 3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_aka_build_identity(struct eap_sm *sm, 3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_aka_data *data, u8 id) 3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_msg *msg; 3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *buf; 3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-AKA: Generating Identity"); 3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = eap_sim_msg_init(EAP_CODE_REQUEST, id, data->eap_method, 3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_AKA_SUBTYPE_IDENTITY); 3574530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt data->identity_round++; 3584530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (data->identity_round == 1) { 3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * RFC 4187, Chap. 4.1.4 recommends that identity from EAP is 3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * ignored and the AKA/Identity is used to request the 3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * identity. 3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " AT_ANY_ID_REQ"); 3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_add(msg, EAP_SIM_AT_ANY_ID_REQ, 0, NULL, 0); 3664530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt } else if (data->identity_round > 3) { 3674530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt /* Cannot use more than three rounds of Identity messages */ 368d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt eap_sim_msg_free(msg); 3694530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt return NULL; 3704530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt } else if (sm->identity && sm->identity_len > 0 && 3714530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt (sm->identity[0] == EAP_AKA_REAUTH_ID_PREFIX || 3724530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt sm->identity[0] == EAP_AKA_PRIME_REAUTH_ID_PREFIX)) { 3734530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt /* Reauth id may have expired - try fullauth */ 3744530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt wpa_printf(MSG_DEBUG, " AT_FULLAUTH_ID_REQ"); 3754530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt eap_sim_msg_add(msg, EAP_SIM_AT_FULLAUTH_ID_REQ, 0, NULL, 0); 3764530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt } else { 3774530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt wpa_printf(MSG_DEBUG, " AT_PERMANENT_ID_REQ"); 3784530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt eap_sim_msg_add(msg, EAP_SIM_AT_PERMANENT_ID_REQ, 0, NULL, 0); 3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 380c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt buf = eap_sim_msg_finish(msg, data->eap_method, NULL, NULL, 0); 3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_aka_add_id_msg(data, buf) < 0) { 3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(buf); 3838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->pending_id = id; 3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return buf; 3878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_aka_build_encr(struct eap_sm *sm, struct eap_aka_data *data, 3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_msg *msg, u16 counter, 3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *nonce_s) 3938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data->next_pseudonym); 39504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (nonce_s == NULL) { 39604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt data->next_pseudonym = 39704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt eap_sim_db_get_next_pseudonym( 39804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt sm->eap_sim_db_priv, 39904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt data->eap_method == EAP_TYPE_AKA_PRIME ? 40004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt EAP_SIM_DB_AKA_PRIME : EAP_SIM_DB_AKA); 40104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } else { 40204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt /* Do not update pseudonym during re-authentication */ 40304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt data->next_pseudonym = NULL; 40404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 4058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data->next_reauth_id); 4068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->counter <= EAP_AKA_MAX_FAST_REAUTHS) { 4078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->next_reauth_id = 40804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt eap_sim_db_get_next_reauth_id( 40904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt sm->eap_sim_db_priv, 41004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt data->eap_method == EAP_TYPE_AKA_PRIME ? 41104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt EAP_SIM_DB_AKA_PRIME : EAP_SIM_DB_AKA); 4128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 4138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-AKA: Max fast re-authentication " 4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "count exceeded - force full authentication"); 4158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->next_reauth_id = NULL; 4168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->next_pseudonym == NULL && data->next_reauth_id == NULL && 4198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt counter == 0 && nonce_s == NULL) 4208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 4218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " AT_IV"); 4238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " AT_ENCR_DATA"); 4248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_add_encr_start(msg, EAP_SIM_AT_IV, EAP_SIM_AT_ENCR_DATA); 4258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (counter > 0) { 4278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " *AT_COUNTER (%u)", counter); 4288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_add(msg, EAP_SIM_AT_COUNTER, counter, NULL, 0); 4298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (nonce_s) { 4328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " *AT_NONCE_S"); 4338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_add(msg, EAP_SIM_AT_NONCE_S, 0, nonce_s, 4348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_SIM_NONCE_S_LEN); 4358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->next_pseudonym) { 4388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " *AT_NEXT_PSEUDONYM (%s)", 4398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->next_pseudonym); 4408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_add(msg, EAP_SIM_AT_NEXT_PSEUDONYM, 4418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_strlen(data->next_pseudonym), 4428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (u8 *) data->next_pseudonym, 4438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_strlen(data->next_pseudonym)); 4448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->next_reauth_id) { 4478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " *AT_NEXT_REAUTH_ID (%s)", 4488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->next_reauth_id); 4498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_add(msg, EAP_SIM_AT_NEXT_REAUTH_ID, 4508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_strlen(data->next_reauth_id), 4518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (u8 *) data->next_reauth_id, 4528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_strlen(data->next_reauth_id)); 4538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_sim_msg_add_encr_end(msg, data->k_encr, EAP_SIM_AT_PADDING)) { 4568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "EAP-AKA: Failed to encrypt " 4578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "AT_ENCR_DATA"); 4588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 4628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_aka_build_challenge(struct eap_sm *sm, 4668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_aka_data *data, 4678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 id) 4688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_msg *msg; 4708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-AKA: Generating Challenge"); 4728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = eap_sim_msg_init(EAP_CODE_REQUEST, id, data->eap_method, 4738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_AKA_SUBTYPE_CHALLENGE); 4748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " AT_RAND"); 4758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_add(msg, EAP_SIM_AT_RAND, 0, data->rand, EAP_AKA_RAND_LEN); 4768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " AT_AUTN"); 4778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_add(msg, EAP_SIM_AT_AUTN, 0, data->autn, EAP_AKA_AUTN_LEN); 4788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->eap_method == EAP_TYPE_AKA_PRIME) { 4798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->kdf) { 4808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Add the selected KDF into the beginning */ 4818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " AT_KDF"); 4828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_add(msg, EAP_SIM_AT_KDF, data->kdf, 4838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NULL, 0); 4848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " AT_KDF"); 4868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_add(msg, EAP_SIM_AT_KDF, EAP_AKA_PRIME_KDF, 4878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NULL, 0); 4888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " AT_KDF_INPUT"); 4898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_add(msg, EAP_SIM_AT_KDF_INPUT, 4908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->network_name_len, 4918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->network_name, data->network_name_len); 4928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_aka_build_encr(sm, data, msg, 0, NULL)) { 4958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_free(msg); 4968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_aka_add_checkcode(data, msg); 5008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->eap_sim_aka_result_ind) { 5028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " AT_RESULT_IND"); 5038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_add(msg, EAP_SIM_AT_RESULT_IND, 0, NULL, 0); 5048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef EAP_SERVER_AKA_PRIME 5078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->eap_method == EAP_TYPE_AKA) { 5088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 flags = 0; 5098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int i; 5108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int aka_prime_preferred = 0; 5118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt i = 0; 5138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (sm->user && i < EAP_MAX_METHODS && 5148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (sm->user->methods[i].vendor != EAP_VENDOR_IETF || 5158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->user->methods[i].method != EAP_TYPE_NONE)) { 5168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->user->methods[i].vendor == EAP_VENDOR_IETF) { 5178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->user->methods[i].method == 5188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_TYPE_AKA) 5198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 5208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->user->methods[i].method == 5218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_TYPE_AKA_PRIME) { 5228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt aka_prime_preferred = 1; 5238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 5248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt i++; 5278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (aka_prime_preferred) 5308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt flags |= EAP_AKA_BIDDING_FLAG_D; 5318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_add(msg, EAP_SIM_AT_BIDDING, flags, NULL, 0); 5328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* EAP_SERVER_AKA_PRIME */ 5348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " AT_MAC"); 5368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC); 537c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt return eap_sim_msg_finish(msg, data->eap_method, data->k_aut, NULL, 0); 5388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_aka_build_reauth(struct eap_sm *sm, 5428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_aka_data *data, u8 id) 5438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_msg *msg; 5458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-AKA: Generating Re-authentication"); 5478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (random_get_bytes(data->nonce_s, EAP_SIM_NONCE_S_LEN)) 5498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 5508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_MSGDUMP, "EAP-AKA: NONCE_S", 5518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->nonce_s, EAP_SIM_NONCE_S_LEN); 5528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->eap_method == EAP_TYPE_AKA_PRIME) { 5548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_aka_prime_derive_keys_reauth(data->k_re, data->counter, 5558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->identity, 5568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->identity_len, 5578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->nonce_s, 5588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->msk, data->emsk); 5598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 5608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_derive_keys(data->mk, data->k_encr, data->k_aut, 5618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->msk, data->emsk); 5628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_derive_keys_reauth(data->counter, sm->identity, 5638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->identity_len, data->nonce_s, 5648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->mk, data->msk, data->emsk); 5658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = eap_sim_msg_init(EAP_CODE_REQUEST, id, data->eap_method, 5688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_AKA_SUBTYPE_REAUTHENTICATION); 5698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_aka_build_encr(sm, data, msg, data->counter, data->nonce_s)) { 5718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_free(msg); 5728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 5738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_aka_add_checkcode(data, msg); 5768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->eap_sim_aka_result_ind) { 5788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " AT_RESULT_IND"); 5798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_add(msg, EAP_SIM_AT_RESULT_IND, 0, NULL, 0); 5808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " AT_MAC"); 5838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC); 584c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt return eap_sim_msg_finish(msg, data->eap_method, data->k_aut, NULL, 0); 5858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_aka_build_notification(struct eap_sm *sm, 5898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_aka_data *data, 5908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 id) 5918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_msg *msg; 5938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-AKA: Generating Notification"); 5958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = eap_sim_msg_init(EAP_CODE_REQUEST, id, data->eap_method, 5968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_AKA_SUBTYPE_NOTIFICATION); 5978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " AT_NOTIFICATION (%d)", data->notification); 5988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_add(msg, EAP_SIM_AT_NOTIFICATION, data->notification, 5998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NULL, 0); 6008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->use_result_ind) { 6018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->reauth) { 6028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " AT_IV"); 6038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " AT_ENCR_DATA"); 6048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_add_encr_start(msg, EAP_SIM_AT_IV, 6058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_SIM_AT_ENCR_DATA); 6068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " *AT_COUNTER (%u)", 6078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->counter); 6088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_add(msg, EAP_SIM_AT_COUNTER, data->counter, 6098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NULL, 0); 6108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_sim_msg_add_encr_end(msg, data->k_encr, 6128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_SIM_AT_PADDING)) { 6138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "EAP-AKA: Failed to " 6148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "encrypt AT_ENCR_DATA"); 6158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_free(msg); 6168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 6178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " AT_MAC"); 6218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC); 6228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 623c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt return eap_sim_msg_finish(msg, data->eap_method, data->k_aut, NULL, 0); 6248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_aka_buildReq(struct eap_sm *sm, void *priv, u8 id) 6288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_aka_data *data = priv; 6308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->auts_reported = 0; 6328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (data->state) { 6338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case IDENTITY: 6348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return eap_aka_build_identity(sm, data, id); 6358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case CHALLENGE: 6368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return eap_aka_build_challenge(sm, data, id); 6378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case REAUTH: 6388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return eap_aka_build_reauth(sm, data, id); 6398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case NOTIFICATION: 6408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return eap_aka_build_notification(sm, data, id); 6418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 6428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-AKA: Unknown state %d in " 6438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "buildReq", data->state); 6448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 6458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 6478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic Boolean eap_aka_check(struct eap_sm *sm, void *priv, 6518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *respData) 6528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_aka_data *data = priv; 6548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos; 6558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len; 6568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = eap_hdr_validate(EAP_VENDOR_IETF, data->eap_method, respData, 6588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &len); 6598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos == NULL || len < 3) { 6608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-AKA: Invalid frame"); 6618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return TRUE; 6628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return FALSE; 6658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic Boolean eap_aka_subtype_ok(struct eap_aka_data *data, u8 subtype) 6698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (subtype == EAP_AKA_SUBTYPE_CLIENT_ERROR || 6718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt subtype == EAP_AKA_SUBTYPE_AUTHENTICATION_REJECT) 6728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return FALSE; 6738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (data->state) { 6758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case IDENTITY: 6768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (subtype != EAP_AKA_SUBTYPE_IDENTITY) { 6778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-AKA: Unexpected response " 6788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "subtype %d", subtype); 6798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return TRUE; 6808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 6828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case CHALLENGE: 6838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (subtype != EAP_AKA_SUBTYPE_CHALLENGE && 6848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt subtype != EAP_AKA_SUBTYPE_SYNCHRONIZATION_FAILURE) { 6858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-AKA: Unexpected response " 6868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "subtype %d", subtype); 6878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return TRUE; 6888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 6908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case REAUTH: 6918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (subtype != EAP_AKA_SUBTYPE_REAUTHENTICATION) { 6928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-AKA: Unexpected response " 6938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "subtype %d", subtype); 6948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return TRUE; 6958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 6978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case NOTIFICATION: 6988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (subtype != EAP_AKA_SUBTYPE_NOTIFICATION) { 6998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-AKA: Unexpected response " 7008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "subtype %d", subtype); 7018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return TRUE; 7028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 7048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 7058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-AKA: Unexpected state (%d) for " 7068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "processing a response", data->state); 7078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return TRUE; 7088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return FALSE; 7118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_aka_determine_identity(struct eap_sm *sm, 7154530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt struct eap_aka_data *data) 7168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7174530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt char *username; 7188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7194530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, "EAP-AKA: Identity", 7204530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt sm->identity, sm->identity_len); 7218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7224530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt username = sim_get_username(sm->identity, sm->identity_len); 7234530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (username == NULL) { 7244530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH; 7254530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt eap_aka_state(data, NOTIFICATION); 7264530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt return; 7274530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt } 7284530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 7294530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (eap_aka_check_identity_reauth(sm, data, username) > 0) { 7304530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt os_free(username); 7314530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt return; 7328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 734a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (((data->eap_method == EAP_TYPE_AKA_PRIME && 735a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt username[0] == EAP_AKA_PRIME_REAUTH_ID_PREFIX) || 736a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt (data->eap_method == EAP_TYPE_AKA && 737a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt username[0] == EAP_AKA_REAUTH_ID_PREFIX)) && 738a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt data->identity_round == 1) { 739a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt /* Remain in IDENTITY state for another round to request full 740a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * auth identity since we did not recognize reauth id */ 741a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt os_free(username); 742a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt return; 743a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt } 744a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 7454530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if ((data->eap_method == EAP_TYPE_AKA_PRIME && 7464530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt username[0] == EAP_AKA_PRIME_PSEUDONYM_PREFIX) || 7474530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt (data->eap_method == EAP_TYPE_AKA && 7484530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt username[0] == EAP_AKA_PSEUDONYM_PREFIX)) { 7494530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt const char *permanent; 7504530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-AKA: Pseudonym username '%s'", 7514530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt username); 7524530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt permanent = eap_sim_db_get_permanent( 7534530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt sm->eap_sim_db_priv, username); 7544530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt os_free(username); 7554530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (permanent == NULL) { 7564530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-AKA: Unknown pseudonym " 7574530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt "identity - request permanent identity"); 7584530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt /* Remain in IDENTITY state for another round */ 7598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 7608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7614530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt os_strlcpy(data->permanent, permanent, 7624530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt sizeof(data->permanent)); 7634530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt } else if ((data->eap_method == EAP_TYPE_AKA_PRIME && 7644530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt username[0] == EAP_AKA_PRIME_PERMANENT_PREFIX) || 7654530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt (data->eap_method == EAP_TYPE_AKA && 7664530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt username[0] == EAP_AKA_PERMANENT_PREFIX)) { 7674530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-AKA: Permanent username '%s'", 7684530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt username); 7694530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt os_strlcpy(data->permanent, username, sizeof(data->permanent)); 7704530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt os_free(username); 7714530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt } else { 7724530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-AKA: Unrecognized username '%s'", 7734530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt username); 7744530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt os_free(username); 7754530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH; 7764530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt eap_aka_state(data, NOTIFICATION); 7774530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt return; 7788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7804530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt eap_aka_fullauth(sm, data); 7814530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt} 7828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7844530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtstatic void eap_aka_fullauth(struct eap_sm *sm, struct eap_aka_data *data) 7854530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt{ 7864530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt size_t identity_len; 7874530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt int res; 7884530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 7894530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt res = eap_sim_db_get_aka_auth(sm->eap_sim_db_priv, data->permanent, 7904530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt data->rand, data->autn, data->ik, 7914530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt data->ck, data->res, &data->res_len, sm); 7928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res == EAP_SIM_DB_PENDING) { 7938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-AKA: AKA authentication data " 7948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "not yet available - pending request"); 7958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->method_pending = METHOD_PENDING_WAIT; 7968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 7978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef EAP_SERVER_AKA_PRIME 8008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->eap_method == EAP_TYPE_AKA_PRIME) { 8018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Note: AUTN = (SQN ^ AK) || AMF || MAC which gives us the 8028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * needed 6-octet SQN ^AK for CK',IK' derivation */ 8038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_aka_prime_derive_ck_ik_prime(data->ck, data->ik, 8048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->autn, 8058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->network_name, 8068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->network_name_len); 8078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* EAP_SERVER_AKA_PRIME */ 8098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->reauth = NULL; 8118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->counter = 0; /* reset re-auth counter since this is full auth */ 8128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res != 0) { 8148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-AKA: Failed to get AKA " 8158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "authentication data for the peer"); 8168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH; 8178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_aka_state(data, NOTIFICATION); 8188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 8198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->method_pending == METHOD_PENDING_WAIT) { 8218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-AKA: AKA authentication data " 8228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "available - abort pending wait"); 8238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->method_pending = METHOD_PENDING_NONE; 8248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt identity_len = sm->identity_len; 8278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (identity_len > 0 && sm->identity[identity_len - 1] == '\0') { 8288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-AKA: Workaround - drop last null " 8298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "character from identity"); 8308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt identity_len--; 8318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, "EAP-AKA: Identity for MK derivation", 8338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->identity, identity_len); 8348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->eap_method == EAP_TYPE_AKA_PRIME) { 83604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt eap_aka_prime_derive_keys(sm->identity, identity_len, data->ik, 8378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->ck, data->k_encr, data->k_aut, 8388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->k_re, data->msk, data->emsk); 8398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 8408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_aka_derive_mk(sm->identity, identity_len, data->ik, 8418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->ck, data->mk); 8428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_derive_keys(data->mk, data->k_encr, data->k_aut, 8438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->msk, data->emsk); 8448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_aka_state(data, CHALLENGE); 8478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 8488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_aka_process_identity(struct eap_sm *sm, 8518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_aka_data *data, 8528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *respData, 8538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_attrs *attr) 8548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 8554530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt u8 *new_identity; 8564530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 8578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-AKA: Processing Identity"); 8588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (attr->mac || attr->iv || attr->encr_data) { 8608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "EAP-AKA: Unexpected attribute " 8618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "received in EAP-Response/AKA-Identity"); 8628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH; 8638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_aka_state(data, NOTIFICATION); 8648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 8658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8674530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt /* 8684530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt * We always request identity with AKA/Identity, so the peer is 8694530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt * required to have replied with one. 8704530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt */ 8714530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (!attr->identity || attr->identity_len == 0) { 8724530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-AKA: Peer did not provide any " 8734530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt "identity"); 8744530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH; 8754530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt eap_aka_state(data, NOTIFICATION); 8764530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt return; 8778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8794530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt new_identity = os_malloc(attr->identity_len); 8804530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (new_identity == NULL) { 8814530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH; 8824530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt eap_aka_state(data, NOTIFICATION); 8834530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt return; 8844530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt } 8854530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt os_free(sm->identity); 8864530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt sm->identity = new_identity; 8874530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt os_memcpy(sm->identity, attr->identity, attr->identity_len); 8884530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt sm->identity_len = attr->identity_len; 8894530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 8904530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt eap_aka_determine_identity(sm, data); 8918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_get_id(respData) == data->pending_id) { 8928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->pending_id = -1; 8938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_aka_add_id_msg(data, respData); 8948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 8968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_aka_verify_mac(struct eap_aka_data *data, 8998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpabuf *req, 9008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *mac, const u8 *extra, 9018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t extra_len) 9028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 9038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->eap_method == EAP_TYPE_AKA_PRIME) 9048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return eap_sim_verify_mac_sha256(data->k_aut, req, mac, extra, 9058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt extra_len); 9068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return eap_sim_verify_mac(data->k_aut, req, mac, extra, extra_len); 9078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 9088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_aka_process_challenge(struct eap_sm *sm, 9118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_aka_data *data, 9128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *respData, 9138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_attrs *attr) 9148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 9158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-AKA: Processing Challenge"); 9168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef EAP_SERVER_AKA_PRIME 9188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#if 0 9198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* KDF negotiation; to be enabled only after more than one KDF is 9208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * supported */ 9218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->eap_method == EAP_TYPE_AKA_PRIME && 9228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt attr->kdf_count == 1 && attr->mac == NULL) { 9238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (attr->kdf[0] != EAP_AKA_PRIME_KDF) { 9248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "EAP-AKA': Peer selected " 9258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "unknown KDF"); 9268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->notification = 9278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH; 9288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_aka_state(data, NOTIFICATION); 9298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 9308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->kdf = attr->kdf[0]; 9338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Allow negotiation to continue with the selected KDF by 9358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * sending another Challenge message */ 9368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-AKA': KDF %d selected", data->kdf); 9378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 9388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif 9408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* EAP_SERVER_AKA_PRIME */ 9418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (attr->checkcode && 9438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_aka_verify_checkcode(data, attr->checkcode, 9448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt attr->checkcode_len)) { 9458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "EAP-AKA: Invalid AT_CHECKCODE in the " 9468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "message"); 9478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH; 9488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_aka_state(data, NOTIFICATION); 9498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 9508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (attr->mac == NULL || 9528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_aka_verify_mac(data, respData, attr->mac, NULL, 0)) { 9538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "EAP-AKA: Challenge message " 9548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "did not include valid AT_MAC"); 9558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH; 9568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_aka_state(data, NOTIFICATION); 9578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 9588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 9618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * AT_RES is padded, so verify that there is enough room for RES and 9628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * that the RES length in bits matches with the expected RES. 9638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 9648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (attr->res == NULL || attr->res_len < data->res_len || 9658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt attr->res_len_bits != data->res_len * 8 || 966c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt os_memcmp_const(attr->res, data->res, data->res_len) != 0) { 9678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "EAP-AKA: Challenge message did not " 9688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "include valid AT_RES (attr len=%lu, res len=%lu " 9698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "bits, expected %lu bits)", 9708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) attr->res_len, 9718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) attr->res_len_bits, 9728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) data->res_len * 8); 9738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH; 9748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_aka_state(data, NOTIFICATION); 9758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 9768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-AKA: Challenge response includes the " 9798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "correct AT_MAC"); 9808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->eap_sim_aka_result_ind && attr->result_ind) { 9818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->use_result_ind = 1; 9828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->notification = EAP_SIM_SUCCESS; 9838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_aka_state(data, NOTIFICATION); 9848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else 9858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_aka_state(data, SUCCESS); 9868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->next_pseudonym) { 9884530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt eap_sim_db_add_pseudonym(sm->eap_sim_db_priv, data->permanent, 9898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->next_pseudonym); 9908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->next_pseudonym = NULL; 9918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->next_reauth_id) { 9938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->eap_method == EAP_TYPE_AKA_PRIME) { 9948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef EAP_SERVER_AKA_PRIME 9958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_db_add_reauth_prime(sm->eap_sim_db_priv, 9964530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt data->permanent, 9978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->next_reauth_id, 9988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->counter + 1, 9998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->k_encr, data->k_aut, 10008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->k_re); 10018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* EAP_SERVER_AKA_PRIME */ 10028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 10034530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt eap_sim_db_add_reauth(sm->eap_sim_db_priv, 10044530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt data->permanent, 10058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->next_reauth_id, 10068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->counter + 1, 10078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->mk); 10088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->next_reauth_id = NULL; 10108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 10128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_aka_process_sync_failure(struct eap_sm *sm, 10158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_aka_data *data, 10168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *respData, 10178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_attrs *attr) 10188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 10198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-AKA: Processing Synchronization-Failure"); 10208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (attr->auts == NULL) { 10228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "EAP-AKA: Synchronization-Failure " 10238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "message did not include valid AT_AUTS"); 10248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH; 10258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_aka_state(data, NOTIFICATION); 10268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 10278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Avoid re-reporting AUTS when processing pending EAP packet by 10308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * maintaining a local flag stating whether this AUTS has already been 10318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * reported. */ 10328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!data->auts_reported && 10334530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt eap_sim_db_resynchronize(sm->eap_sim_db_priv, data->permanent, 10344530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt attr->auts, data->rand)) { 10358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "EAP-AKA: Resynchronization failed"); 10368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH; 10378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_aka_state(data, NOTIFICATION); 10388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 10398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->auts_reported = 1; 10418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10424530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt /* Remain in CHALLENGE state to re-try after resynchronization */ 10435605286c30e1701491bd3af974ae423727750eddDmitry Shmidt eap_aka_fullauth(sm, data); 10448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 10458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_aka_process_reauth(struct eap_sm *sm, 10488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_aka_data *data, 10498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *respData, 10508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_attrs *attr) 10518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 10528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_attrs eattr; 10538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *decrypted = NULL; 10548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-AKA: Processing Reauthentication"); 10568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (attr->mac == NULL || 10588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_aka_verify_mac(data, respData, attr->mac, data->nonce_s, 10598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_SIM_NONCE_S_LEN)) { 10608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "EAP-AKA: Re-authentication message " 10618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "did not include valid AT_MAC"); 10628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 10638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (attr->encr_data == NULL || attr->iv == NULL) { 10668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "EAP-AKA: Reauthentication " 10678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "message did not include encrypted data"); 10688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 10698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt decrypted = eap_sim_parse_encr(data->k_encr, attr->encr_data, 10728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt attr->encr_data_len, attr->iv, &eattr, 10738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0); 10748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (decrypted == NULL) { 10758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "EAP-AKA: Failed to parse encrypted " 10768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "data from reauthentication message"); 10778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 10788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eattr.counter != data->counter) { 10818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "EAP-AKA: Re-authentication message " 10828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "used incorrect counter %u, expected %u", 10838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eattr.counter, data->counter); 10848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 10858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(decrypted); 10878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt decrypted = NULL; 10888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-AKA: Re-authentication response includes " 10908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "the correct AT_MAC"); 10918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eattr.counter_too_small) { 10938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-AKA: Re-authentication response " 10948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "included AT_COUNTER_TOO_SMALL - starting full " 10958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "authentication"); 10964530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt eap_aka_fullauth(sm, data); 10978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 10988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->eap_sim_aka_result_ind && attr->result_ind) { 11018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->use_result_ind = 1; 11028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->notification = EAP_SIM_SUCCESS; 11038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_aka_state(data, NOTIFICATION); 11048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else 11058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_aka_state(data, SUCCESS); 11068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->next_reauth_id) { 11088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->eap_method == EAP_TYPE_AKA_PRIME) { 11098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef EAP_SERVER_AKA_PRIME 11108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_db_add_reauth_prime(sm->eap_sim_db_priv, 11114530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt data->permanent, 11128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->next_reauth_id, 11138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->counter + 1, 11148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->k_encr, data->k_aut, 11158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->k_re); 11168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* EAP_SERVER_AKA_PRIME */ 11178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 11184530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt eap_sim_db_add_reauth(sm->eap_sim_db_priv, 11194530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt data->permanent, 11208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->next_reauth_id, 11218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->counter + 1, 11228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->mk); 11238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->next_reauth_id = NULL; 11258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 11268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_db_remove_reauth(sm->eap_sim_db_priv, data->reauth); 11278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->reauth = NULL; 11288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 11318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtfail: 11338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH; 11348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_aka_state(data, NOTIFICATION); 11358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_db_remove_reauth(sm->eap_sim_db_priv, data->reauth); 11368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->reauth = NULL; 11378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(decrypted); 11388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 11398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_aka_process_client_error(struct eap_sm *sm, 11428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_aka_data *data, 11438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *respData, 11448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_attrs *attr) 11458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 11468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-AKA: Client reported error %d", 11478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt attr->client_error_code); 11488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->notification == EAP_SIM_SUCCESS && data->use_result_ind) 11498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_aka_state(data, SUCCESS); 11508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 11518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_aka_state(data, FAILURE); 11528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 11538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_aka_process_authentication_reject( 11568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sm *sm, struct eap_aka_data *data, 11578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *respData, struct eap_sim_attrs *attr) 11588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 11598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-AKA: Client rejected authentication"); 11608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_aka_state(data, FAILURE); 11618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 11628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_aka_process_notification(struct eap_sm *sm, 11658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_aka_data *data, 11668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *respData, 11678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_attrs *attr) 11688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 11698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-AKA: Client replied to notification"); 11708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->notification == EAP_SIM_SUCCESS && data->use_result_ind) 11718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_aka_state(data, SUCCESS); 11728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 11738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_aka_state(data, FAILURE); 11748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 11758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_aka_process(struct eap_sm *sm, void *priv, 11788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *respData) 11798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 11808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_aka_data *data = priv; 11818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos, *end; 11828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 subtype; 11838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len; 11848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_attrs attr; 11858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = eap_hdr_validate(EAP_VENDOR_IETF, data->eap_method, respData, 11878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &len); 11888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos == NULL || len < 3) 11898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 11908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt end = pos + len; 11928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt subtype = *pos; 11938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 3; 11948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_aka_subtype_ok(data, subtype)) { 11968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-AKA: Unrecognized or unexpected " 11978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "EAP-AKA Subtype in EAP Response"); 11988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH; 11998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_aka_state(data, NOTIFICATION); 12008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 12018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_sim_parse_attr(pos, end, &attr, 12048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->eap_method == EAP_TYPE_AKA_PRIME ? 2 : 1, 12058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0)) { 12068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-AKA: Failed to parse attributes"); 12078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH; 12088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_aka_state(data, NOTIFICATION); 12098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 12108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (subtype == EAP_AKA_SUBTYPE_CLIENT_ERROR) { 12138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_aka_process_client_error(sm, data, respData, &attr); 12148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 12158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (subtype == EAP_AKA_SUBTYPE_AUTHENTICATION_REJECT) { 12188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_aka_process_authentication_reject(sm, data, respData, 12198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &attr); 12208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 12218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (data->state) { 12248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case IDENTITY: 12258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_aka_process_identity(sm, data, respData, &attr); 12268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 12278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case CHALLENGE: 12288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (subtype == EAP_AKA_SUBTYPE_SYNCHRONIZATION_FAILURE) { 12298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_aka_process_sync_failure(sm, data, respData, 12308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &attr); 12318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 12328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_aka_process_challenge(sm, data, respData, &attr); 12338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 12358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case REAUTH: 12368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_aka_process_reauth(sm, data, respData, &attr); 12378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 12388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case NOTIFICATION: 12398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_aka_process_notification(sm, data, respData, &attr); 12408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 12418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 12428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-AKA: Unknown state %d in " 12438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "process", data->state); 12448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 12458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 12478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic Boolean eap_aka_isDone(struct eap_sm *sm, void *priv) 12508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 12518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_aka_data *data = priv; 12528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return data->state == SUCCESS || data->state == FAILURE; 12538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 12548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic u8 * eap_aka_getKey(struct eap_sm *sm, void *priv, size_t *len) 12578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 12588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_aka_data *data = priv; 12598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *key; 12608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->state != SUCCESS) 12628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 12638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key = os_malloc(EAP_SIM_KEYING_DATA_LEN); 12658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (key == NULL) 12668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 12678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(key, data->msk, EAP_SIM_KEYING_DATA_LEN); 12688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *len = EAP_SIM_KEYING_DATA_LEN; 12698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return key; 12708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 12718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic u8 * eap_aka_get_emsk(struct eap_sm *sm, void *priv, size_t *len) 12748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 12758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_aka_data *data = priv; 12768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *key; 12778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->state != SUCCESS) 12798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 12808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key = os_malloc(EAP_EMSK_LEN); 12828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (key == NULL) 12838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 12848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(key, data->emsk, EAP_EMSK_LEN); 12858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *len = EAP_EMSK_LEN; 12868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return key; 12878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 12888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic Boolean eap_aka_isSuccess(struct eap_sm *sm, void *priv) 12918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 12928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_aka_data *data = priv; 12938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return data->state == SUCCESS; 12948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 12958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint eap_server_aka_register(void) 12988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 12998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_method *eap; 13008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret; 13018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION, 13038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_VENDOR_IETF, EAP_TYPE_AKA, "AKA"); 13048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap == NULL) 13058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 13068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->init = eap_aka_init; 13088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->reset = eap_aka_reset; 13098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->buildReq = eap_aka_buildReq; 13108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->check = eap_aka_check; 13118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->process = eap_aka_process; 13128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->isDone = eap_aka_isDone; 13138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->getKey = eap_aka_getKey; 13148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->isSuccess = eap_aka_isSuccess; 13158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->get_emsk = eap_aka_get_emsk; 13168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = eap_server_method_register(eap); 13188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret) 13198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_server_method_free(eap); 13208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 13218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 13228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef EAP_SERVER_AKA_PRIME 13258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint eap_server_aka_prime_register(void) 13268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 13278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_method *eap; 13288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret; 13298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION, 13318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_VENDOR_IETF, EAP_TYPE_AKA_PRIME, 13328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "AKA'"); 13338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap == NULL) 13348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 13358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->init = eap_aka_prime_init; 13378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->reset = eap_aka_reset; 13388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->buildReq = eap_aka_buildReq; 13398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->check = eap_aka_check; 13408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->process = eap_aka_process; 13418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->isDone = eap_aka_isDone; 13428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->getKey = eap_aka_getKey; 13438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->isSuccess = eap_aka_isSuccess; 13448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->get_emsk = eap_aka_get_emsk; 13458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = eap_server_method_register(eap); 13478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret) 13488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_server_method_free(eap); 13498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 13518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 13528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* EAP_SERVER_AKA_PRIME */ 1353