18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* 204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * EAP peer method: EAP-AKA (RFC 4187) and EAP-AKA' (RFC 5448) 304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * Copyright (c) 2004-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 "pcsc_funcs.h" 138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/crypto.h" 148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/sha1.h" 158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/sha256.h" 168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/milenage.h" 178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eap_common/eap_sim_common.h" 188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eap_config.h" 198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eap_i.h" 208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct eap_aka_data { 238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 ik[EAP_AKA_IK_LEN], ck[EAP_AKA_CK_LEN], res[EAP_AKA_RES_MAX_LEN]; 248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t res_len; 258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 nonce_s[EAP_SIM_NONCE_S_LEN]; 268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 mk[EAP_SIM_MK_LEN]; 278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 k_aut[EAP_AKA_PRIME_K_AUT_LEN]; 288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 k_encr[EAP_SIM_K_ENCR_LEN]; 298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 k_re[EAP_AKA_PRIME_K_RE_LEN]; /* EAP-AKA' only */ 308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 msk[EAP_SIM_KEYING_DATA_LEN]; 318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 emsk[EAP_EMSK_LEN]; 328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 rand[EAP_AKA_RAND_LEN], autn[EAP_AKA_AUTN_LEN]; 338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 auts[EAP_AKA_AUTS_LEN]; 348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int num_id_req, num_notification; 368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *pseudonym; 378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t pseudonym_len; 388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *reauth_id; 398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t reauth_id_len; 408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int reauth; 418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt unsigned int counter, counter_too_small; 428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *last_eap_identity; 438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t last_eap_identity_len; 448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt enum { 452271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt CONTINUE, RESULT_SUCCESS, SUCCESS, FAILURE 468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } state; 478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *id_msgs; 498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int prev_id; 508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int result_ind, use_result_ind; 518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 eap_method; 528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *network_name; 538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t network_name_len; 548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 kdf; 558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int kdf_negotiation; 568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}; 578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef CONFIG_NO_STDOUT_DEBUG 608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const char * eap_aka_state_txt(int state) 618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (state) { 638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case CONTINUE: 648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "CONTINUE"; 658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case RESULT_SUCCESS: 668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "RESULT_SUCCESS"; 678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case SUCCESS: 688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "SUCCESS"; 698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case FAILURE: 708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "FAILURE"; 718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "?"; 738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_NO_STDOUT_DEBUG */ 768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_aka_state(struct eap_aka_data *data, int state) 798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-AKA: %s -> %s", 818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_aka_state_txt(data->state), 828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_aka_state_txt(state)); 838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->state = state; 848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void * eap_aka_init(struct eap_sm *sm) 888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_aka_data *data; 908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const char *phase1 = eap_get_config_phase1(sm); 914530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt struct eap_peer_config *config = eap_get_config(sm); 928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data = os_zalloc(sizeof(*data)); 948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data == NULL) 958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->eap_method = EAP_TYPE_AKA; 988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_aka_state(data, CONTINUE); 1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->prev_id = -1; 1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->result_ind = phase1 && os_strstr(phase1, "result_ind=1") != NULL; 1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1044530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (config && config->anonymous_identity) { 1054530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt data->pseudonym = os_malloc(config->anonymous_identity_len); 1064530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (data->pseudonym) { 1074530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt os_memcpy(data->pseudonym, config->anonymous_identity, 1084530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt config->anonymous_identity_len); 1094530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt data->pseudonym_len = config->anonymous_identity_len; 1104530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt } 1114530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt } 1124530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return data; 1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef EAP_AKA_PRIME 1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void * eap_aka_prime_init(struct eap_sm *sm) 1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_aka_data *data = eap_aka_init(sm); 1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data == NULL) 1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->eap_method = EAP_TYPE_AKA_PRIME; 1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return data; 1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* EAP_AKA_PRIME */ 1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 129c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidtstatic void eap_aka_clear_keys(struct eap_aka_data *data, int reauth) 130c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt{ 131c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt if (!reauth) { 132c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt os_memset(data->mk, 0, EAP_SIM_MK_LEN); 133c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt os_memset(data->k_aut, 0, EAP_AKA_PRIME_K_AUT_LEN); 134c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt os_memset(data->k_encr, 0, EAP_SIM_K_ENCR_LEN); 135c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt os_memset(data->k_re, 0, EAP_AKA_PRIME_K_RE_LEN); 136c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt } 137c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt os_memset(data->msk, 0, EAP_SIM_KEYING_DATA_LEN); 138c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt os_memset(data->emsk, 0, EAP_EMSK_LEN); 139c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt os_memset(data->autn, 0, EAP_AKA_AUTN_LEN); 140c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt os_memset(data->auts, 0, EAP_AKA_AUTS_LEN); 141c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt} 142c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt 143c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt 1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_aka_deinit(struct eap_sm *sm, void *priv) 1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_aka_data *data = priv; 1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data) { 1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data->pseudonym); 1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data->reauth_id); 1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data->last_eap_identity); 1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(data->id_msgs); 1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data->network_name); 153c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt eap_aka_clear_keys(data, 0); 1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data); 1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 159051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidtstatic int eap_aka_ext_sim_req(struct eap_sm *sm, struct eap_aka_data *data) 160051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt{ 161051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt char req[200], *pos, *end; 162051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 163051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-AKA: Use external USIM processing"); 164051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt pos = req; 165051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt end = pos + sizeof(req); 166051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt pos += os_snprintf(pos, end - pos, "UMTS-AUTH"); 167051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt pos += os_snprintf(pos, end - pos, ":"); 168051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt pos += wpa_snprintf_hex(pos, end - pos, data->rand, EAP_AKA_RAND_LEN); 169051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt pos += os_snprintf(pos, end - pos, ":"); 170c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt wpa_snprintf_hex(pos, end - pos, data->autn, EAP_AKA_AUTN_LEN); 171051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 172051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt eap_sm_request_sim(sm, req); 173051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt return 1; 174051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt} 175051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 176051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 177051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidtstatic int eap_aka_ext_sim_result(struct eap_sm *sm, struct eap_aka_data *data, 178051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt struct eap_peer_config *conf) 179051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt{ 180051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt char *resp, *pos; 181051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 182051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt wpa_printf(MSG_DEBUG, 183051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt "EAP-AKA: Use result from external USIM processing"); 184051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 185051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt resp = conf->external_sim_resp; 186051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt conf->external_sim_resp = NULL; 187051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 188051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt if (os_strncmp(resp, "UMTS-AUTS:", 10) == 0) { 189051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt pos = resp + 10; 190051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt if (hexstr2bin(pos, data->auts, EAP_AKA_AUTS_LEN) < 0) 191051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt goto invalid; 192051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "EAP-AKA: AUTS", data->auts, 193051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt EAP_AKA_AUTS_LEN); 194051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt os_free(resp); 195051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt return -2; 196051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt } 197051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 198051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt if (os_strncmp(resp, "UMTS-AUTH:", 10) != 0) { 199051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-AKA: Unrecognized external USIM processing response"); 200051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt os_free(resp); 201051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt return -1; 202051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt } 203051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 204051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt pos = resp + 10; 205051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "EAP-AKA: RAND", data->rand, EAP_AKA_RAND_LEN); 206051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 207051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt if (hexstr2bin(pos, data->ik, EAP_AKA_IK_LEN) < 0) 208051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt goto invalid; 209051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "EAP-AKA: IK", data->ik, EAP_AKA_IK_LEN); 210051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt pos += EAP_AKA_IK_LEN * 2; 211051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt if (*pos != ':') 212051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt goto invalid; 213051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt pos++; 214051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 215051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt if (hexstr2bin(pos, data->ck, EAP_AKA_CK_LEN) < 0) 216051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt goto invalid; 217051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "EAP-AKA: CK", data->ck, EAP_AKA_CK_LEN); 218051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt pos += EAP_AKA_CK_LEN * 2; 219051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt if (*pos != ':') 220051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt goto invalid; 221051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt pos++; 222051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 223051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt data->res_len = os_strlen(pos) / 2; 224051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt if (data->res_len > EAP_AKA_RES_MAX_LEN) { 225051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt data->res_len = 0; 226051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt goto invalid; 227051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt } 228051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt if (hexstr2bin(pos, data->res, data->res_len) < 0) 229051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt goto invalid; 230051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "EAP-AKA: RES", data->res, data->res_len); 231051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 232051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt os_free(resp); 233051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt return 0; 234051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 235051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidtinvalid: 236051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-AKA: Invalid external USIM processing UMTS-AUTH response"); 237051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt os_free(resp); 238051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt return -1; 239051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt} 240051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 241051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_aka_umts_auth(struct eap_sm *sm, struct eap_aka_data *data) 2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_peer_config *conf; 2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-AKA: UMTS authentication algorithm"); 2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conf = eap_get_config(sm); 2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (conf == NULL) 2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 251051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 252051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt if (sm->external_sim) { 253051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt if (conf->external_sim_resp) 254051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt return eap_aka_ext_sim_result(sm, data, conf); 255051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt else 256051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt return eap_aka_ext_sim_req(sm, data); 257051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt } 258051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (conf->pcsc) { 2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return scard_umts_auth(sm->scard_ctx, data->rand, 2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->autn, data->res, &data->res_len, 2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->ik, data->ck, data->auts); 2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_USIM_SIMULATOR 2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (conf->password) { 2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 opc[16], k[16], sqn[6]; 2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const char *pos; 2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-AKA: Use internal Milenage " 2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "implementation for UMTS authentication"); 2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (conf->password_len < 78) { 2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-AKA: invalid Milenage " 2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "password"); 2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = (const char *) conf->password; 2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hexstr2bin(pos, k, 16)) 2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 32; 2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (*pos != ':') 2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos++; 2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hexstr2bin(pos, opc, 16)) 2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 32; 2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (*pos != ':') 2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos++; 2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hexstr2bin(pos, sqn, 6)) 2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return milenage_check(opc, k, sqn, data->rand, data->autn, 2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->ik, data->ck, 2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->res, &data->res_len, data->auts); 2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_USIM_SIMULATOR */ 2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_USIM_HARDCODED 3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-AKA: Use hardcoded Kc and SRES values for " 3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "testing"); 3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* These hardcoded Kc and SRES values are used for testing. 3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Could consider making them configurable. */ 3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(data->res, '2', EAP_AKA_RES_MAX_LEN); 3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->res_len = EAP_AKA_RES_MAX_LEN; 3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(data->ik, '3', EAP_AKA_IK_LEN); 3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(data->ck, '4', EAP_AKA_CK_LEN); 3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt { 3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 autn[EAP_AKA_AUTN_LEN]; 3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(autn, '1', EAP_AKA_AUTN_LEN); 313c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt if (os_memcmp_const(autn, data->autn, EAP_AKA_AUTN_LEN) != 0) { 3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "EAP-AKA: AUTN did not match " 3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "with expected value"); 3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#if 0 3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt { 3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt static int test_resync = 1; 3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (test_resync) { 3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Test Resynchronization */ 3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt test_resync = 0; 3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -2; 3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif 3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* CONFIG_USIM_HARDCODED */ 3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 333f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-AKA: No UMTS authentication algorithm " 3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "enabled"); 3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_USIM_HARDCODED */ 3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define CLEAR_PSEUDONYM 0x01 3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define CLEAR_REAUTH_ID 0x02 3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define CLEAR_EAP_ID 0x04 3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3454530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtstatic void eap_aka_clear_identities(struct eap_sm *sm, 3464530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt struct eap_aka_data *data, int id) 3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 34804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if ((id & CLEAR_PSEUDONYM) && data->pseudonym) { 3491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-AKA: forgetting old pseudonym"); 3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data->pseudonym); 3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->pseudonym = NULL; 3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->pseudonym_len = 0; 3534530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt eap_set_anon_id(sm, NULL, 0); 3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 35504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if ((id & CLEAR_REAUTH_ID) && data->reauth_id) { 3561f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-AKA: forgetting old reauth_id"); 3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data->reauth_id); 3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->reauth_id = NULL; 3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->reauth_id_len = 0; 3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 36104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if ((id & CLEAR_EAP_ID) && data->last_eap_identity) { 3621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-AKA: forgetting old eap_id"); 3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data->last_eap_identity); 3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->last_eap_identity = NULL; 3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->last_eap_identity_len = 0; 3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 370c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidtstatic int eap_aka_learn_ids(struct eap_sm *sm, struct eap_aka_data *data, 3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_attrs *attr) 3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (attr->next_pseudonym) { 374c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt const u8 *identity = NULL; 375c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt size_t identity_len = 0; 376c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt const u8 *realm = NULL; 377c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt size_t realm_len = 0; 378c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt 379c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, 380c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt "EAP-AKA: (encr) AT_NEXT_PSEUDONYM", 381c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt attr->next_pseudonym, 382c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt attr->next_pseudonym_len); 3838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data->pseudonym); 384c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt /* Look for the realm of the permanent identity */ 385c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt identity = eap_get_config_identity(sm, &identity_len); 386c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt if (identity) { 387c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt for (realm = identity, realm_len = identity_len; 388c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt realm_len > 0; realm_len--, realm++) { 389c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt if (*realm == '@') 390c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt break; 391c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt } 392c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt } 393c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt data->pseudonym = os_malloc(attr->next_pseudonym_len + 394c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt realm_len); 3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->pseudonym == NULL) { 3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-AKA: (encr) No memory for " 3978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "next pseudonym"); 398c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt data->pseudonym_len = 0; 3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(data->pseudonym, attr->next_pseudonym, 4028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt attr->next_pseudonym_len); 403c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt if (realm_len) { 404c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt os_memcpy(data->pseudonym + attr->next_pseudonym_len, 405c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt realm, realm_len); 406c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt } 407c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt data->pseudonym_len = attr->next_pseudonym_len + realm_len; 4084530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt eap_set_anon_id(sm, data->pseudonym, data->pseudonym_len); 4098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (attr->next_reauth_id) { 4128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data->reauth_id); 4138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->reauth_id = os_malloc(attr->next_reauth_id_len); 4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->reauth_id == NULL) { 4158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-AKA: (encr) No memory for " 4168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "next reauth_id"); 417c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt data->reauth_id_len = 0; 4188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(data->reauth_id, attr->next_reauth_id, 4218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt attr->next_reauth_id_len); 4228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->reauth_id_len = attr->next_reauth_id_len; 4238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, 4248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "EAP-AKA: (encr) AT_NEXT_REAUTH_ID", 4258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->reauth_id, 4268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->reauth_id_len); 4278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 4308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_aka_add_id_msg(struct eap_aka_data *data, 4348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpabuf *msg) 4358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (msg == NULL) 4378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->id_msgs == NULL) { 4408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->id_msgs = wpabuf_dup(msg); 4418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return data->id_msgs == NULL ? -1 : 0; 4428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpabuf_resize(&data->id_msgs, wpabuf_len(msg)) < 0) 4458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_buf(data->id_msgs, msg); 4478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 4498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_aka_add_checkcode(struct eap_aka_data *data, 4538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_msg *msg) 4548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *addr; 4568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len; 4578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 hash[SHA256_MAC_LEN]; 4588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " AT_CHECKCODE"); 4608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->id_msgs == NULL) { 4628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 4638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * No EAP-AKA/Identity packets were exchanged - send empty 4648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * checkcode. 4658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 4668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_add(msg, EAP_SIM_AT_CHECKCODE, 0, NULL, 0); 4678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 4688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Checkcode is SHA1/SHA256 hash over all EAP-AKA/Identity packets. */ 4718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr = wpabuf_head(data->id_msgs); 4728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len = wpabuf_len(data->id_msgs); 4738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "EAP-AKA: AT_CHECKCODE data", addr, len); 4748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef EAP_AKA_PRIME 4758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->eap_method == EAP_TYPE_AKA_PRIME) 4768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sha256_vector(1, &addr, &len, hash); 4778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 4788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* EAP_AKA_PRIME */ 4798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sha1_vector(1, &addr, &len, hash); 4808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_add(msg, EAP_SIM_AT_CHECKCODE, 0, hash, 4828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->eap_method == EAP_TYPE_AKA_PRIME ? 4838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_AKA_PRIME_CHECKCODE_LEN : EAP_AKA_CHECKCODE_LEN); 4848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_aka_verify_checkcode(struct eap_aka_data *data, 4888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *checkcode, size_t checkcode_len) 4898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *addr; 4918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len; 4928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 hash[SHA256_MAC_LEN]; 4938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t hash_len; 4948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (checkcode == NULL) 4968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->id_msgs == NULL) { 4998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (checkcode_len != 0) { 5008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-AKA: Checkcode from server " 5018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "indicates that AKA/Identity messages were " 5028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "used, but they were not"); 5038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 5068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hash_len = data->eap_method == EAP_TYPE_AKA_PRIME ? 5098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_AKA_PRIME_CHECKCODE_LEN : EAP_AKA_CHECKCODE_LEN; 5108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (checkcode_len != hash_len) { 5128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-AKA: Checkcode from server " 5138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "indicates that AKA/Identity message were not " 5148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "used, but they were"); 5158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Checkcode is SHA1/SHA256 hash over all EAP-AKA/Identity packets. */ 5198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr = wpabuf_head(data->id_msgs); 5208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len = wpabuf_len(data->id_msgs); 5218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef EAP_AKA_PRIME 5228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->eap_method == EAP_TYPE_AKA_PRIME) 5238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sha256_vector(1, &addr, &len, hash); 5248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 5258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* EAP_AKA_PRIME */ 5268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sha1_vector(1, &addr, &len, hash); 5278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 528c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt if (os_memcmp_const(hash, checkcode, hash_len) != 0) { 5298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-AKA: Mismatch in AT_CHECKCODE"); 5308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 5348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_aka_client_error(struct eap_aka_data *data, u8 id, 5388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int err) 5398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_msg *msg; 5418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_aka_state(data, FAILURE); 5438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->num_id_req = 0; 5448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->num_notification = 0; 5458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5464530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-AKA: Send Client-Error (error code %d)", 5474530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt err); 5488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, data->eap_method, 5498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_AKA_SUBTYPE_CLIENT_ERROR); 5508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_add(msg, EAP_SIM_AT_CLIENT_ERROR_CODE, err, NULL, 0); 551c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt return eap_sim_msg_finish(msg, data->eap_method, NULL, NULL, 0); 5528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_aka_authentication_reject(struct eap_aka_data *data, 5568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 id) 5578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_msg *msg; 5598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_aka_state(data, FAILURE); 5618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->num_id_req = 0; 5628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->num_notification = 0; 5638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "Generating EAP-AKA Authentication-Reject " 5658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(id=%d)", id); 5668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, data->eap_method, 5678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_AKA_SUBTYPE_AUTHENTICATION_REJECT); 568c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt return eap_sim_msg_finish(msg, data->eap_method, NULL, NULL, 0); 5698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_aka_synchronization_failure( 5738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_aka_data *data, u8 id) 5748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_msg *msg; 5768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->num_id_req = 0; 5788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->num_notification = 0; 5798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "Generating EAP-AKA Synchronization-Failure " 5818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(id=%d)", id); 5828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, data->eap_method, 5838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_AKA_SUBTYPE_SYNCHRONIZATION_FAILURE); 5848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " AT_AUTS"); 5858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_add_full(msg, EAP_SIM_AT_AUTS, data->auts, 5868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_AKA_AUTS_LEN); 587c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt return eap_sim_msg_finish(msg, data->eap_method, NULL, NULL, 0); 5888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_aka_response_identity(struct eap_sm *sm, 5928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_aka_data *data, 5938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 id, 5948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt enum eap_sim_id_req id_req) 5958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *identity = NULL; 5978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t identity_len = 0; 5988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_msg *msg; 5998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->reauth = 0; 6018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (id_req == ANY_ID && data->reauth_id) { 6028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt identity = data->reauth_id; 6038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt identity_len = data->reauth_id_len; 6048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->reauth = 1; 6058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if ((id_req == ANY_ID || id_req == FULLAUTH_ID) && 6068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->pseudonym) { 6078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt identity = data->pseudonym; 6088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt identity_len = data->pseudonym_len; 6094530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt eap_aka_clear_identities(sm, data, CLEAR_REAUTH_ID); 6108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (id_req != NO_ID_REQ) { 6118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt identity = eap_get_config_identity(sm, &identity_len); 6128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (identity) { 6134530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt eap_aka_clear_identities(sm, data, CLEAR_PSEUDONYM | 6148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt CLEAR_REAUTH_ID); 6158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (id_req != NO_ID_REQ) 6184530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt eap_aka_clear_identities(sm, data, CLEAR_EAP_ID); 6198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "Generating EAP-AKA Identity (id=%d)", id); 6218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, data->eap_method, 6228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_AKA_SUBTYPE_IDENTITY); 6238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (identity) { 6258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, " AT_IDENTITY", 6268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt identity, identity_len); 6278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_add(msg, EAP_SIM_AT_IDENTITY, identity_len, 6288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt identity, identity_len); 6298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 631c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt return eap_sim_msg_finish(msg, data->eap_method, NULL, NULL, 0); 6328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_aka_response_challenge(struct eap_aka_data *data, 6368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 id) 6378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_msg *msg; 6398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "Generating EAP-AKA Challenge (id=%d)", id); 6418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, data->eap_method, 6428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_AKA_SUBTYPE_CHALLENGE); 6438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " AT_RES"); 6448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_add(msg, EAP_SIM_AT_RES, data->res_len * 8, 6458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->res, data->res_len); 6468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_aka_add_checkcode(data, msg); 6478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->use_result_ind) { 6488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " AT_RESULT_IND"); 6498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_add(msg, EAP_SIM_AT_RESULT_IND, 0, NULL, 0); 6508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " AT_MAC"); 6528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC); 653c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt return eap_sim_msg_finish(msg, data->eap_method, data->k_aut, (u8 *) "", 654c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt 0); 6558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_aka_response_reauth(struct eap_aka_data *data, 6598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 id, int counter_too_small, 6608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *nonce_s) 6618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_msg *msg; 6638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt unsigned int counter; 6648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "Generating EAP-AKA Reauthentication (id=%d)", 6668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt id); 6678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, data->eap_method, 6688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_AKA_SUBTYPE_REAUTHENTICATION); 6698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " AT_IV"); 6708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " AT_ENCR_DATA"); 6718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_add_encr_start(msg, EAP_SIM_AT_IV, EAP_SIM_AT_ENCR_DATA); 6728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (counter_too_small) { 6748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " *AT_COUNTER_TOO_SMALL"); 6758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_add(msg, EAP_SIM_AT_COUNTER_TOO_SMALL, 0, NULL, 0); 6768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt counter = data->counter_too_small; 6778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else 6788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt counter = data->counter; 6798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " *AT_COUNTER %d", counter); 6818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_add(msg, EAP_SIM_AT_COUNTER, counter, NULL, 0); 6828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_sim_msg_add_encr_end(msg, data->k_encr, EAP_SIM_AT_PADDING)) { 6848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "EAP-AKA: Failed to encrypt " 6858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "AT_ENCR_DATA"); 6868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_free(msg); 6878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 6888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_aka_add_checkcode(data, msg); 6908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->use_result_ind) { 6918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " AT_RESULT_IND"); 6928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_add(msg, EAP_SIM_AT_RESULT_IND, 0, NULL, 0); 6938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " AT_MAC"); 6958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC); 696c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt return eap_sim_msg_finish(msg, data->eap_method, data->k_aut, nonce_s, 6978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_SIM_NONCE_S_LEN); 6988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_aka_response_notification(struct eap_aka_data *data, 7028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 id, u16 notification) 7038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_msg *msg; 7058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *k_aut = (notification & 0x4000) == 0 ? data->k_aut : NULL; 7068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "Generating EAP-AKA Notification (id=%d)", id); 7088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, data->eap_method, 7098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_AKA_SUBTYPE_NOTIFICATION); 7108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (k_aut && data->reauth) { 7118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " AT_IV"); 7128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " AT_ENCR_DATA"); 7138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_add_encr_start(msg, EAP_SIM_AT_IV, 7148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_SIM_AT_ENCR_DATA); 7158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " *AT_COUNTER %d", data->counter); 7168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_add(msg, EAP_SIM_AT_COUNTER, data->counter, 7178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NULL, 0); 7188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_sim_msg_add_encr_end(msg, data->k_encr, 7198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_SIM_AT_PADDING)) { 7208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "EAP-AKA: Failed to encrypt " 7218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "AT_ENCR_DATA"); 7228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_free(msg); 7238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 7248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (k_aut) { 7278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " AT_MAC"); 7288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC); 7298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 730c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt return eap_sim_msg_finish(msg, data->eap_method, k_aut, (u8 *) "", 0); 7318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_aka_process_identity(struct eap_sm *sm, 7358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_aka_data *data, 7368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 id, 7378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpabuf *reqData, 7388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_attrs *attr) 7398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int id_error; 7418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *buf; 7428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-AKA: subtype Identity"); 7448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt id_error = 0; 7468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (attr->id_req) { 7478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case NO_ID_REQ: 7488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 7498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case ANY_ID: 7508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->num_id_req > 0) 7518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt id_error++; 7528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->num_id_req++; 7538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 7548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case FULLAUTH_ID: 7558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->num_id_req > 1) 7568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt id_error++; 7578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->num_id_req++; 7588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 7598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case PERMANENT_ID: 7608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->num_id_req > 2) 7618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt id_error++; 7628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->num_id_req++; 7638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 7648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (id_error) { 7668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-AKA: Too many ID requests " 7678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "used within one authentication"); 7688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return eap_aka_client_error(data, id, 7698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_AKA_UNABLE_TO_PROCESS_PACKET); 7708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf = eap_aka_response_identity(sm, data, id, attr->id_req); 7738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->prev_id != id) { 7758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_aka_add_id_msg(data, reqData); 7768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_aka_add_id_msg(data, buf); 7778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->prev_id = id; 7788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return buf; 7818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_aka_verify_mac(struct eap_aka_data *data, 7858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpabuf *req, 7868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *mac, const u8 *extra, 7878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t extra_len) 7888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->eap_method == EAP_TYPE_AKA_PRIME) 7908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return eap_sim_verify_mac_sha256(data->k_aut, req, mac, extra, 7918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt extra_len); 7928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return eap_sim_verify_mac(data->k_aut, req, mac, extra, extra_len); 7938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef EAP_AKA_PRIME 7978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_aka_prime_kdf_select(struct eap_aka_data *data, 7988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 id, u16 kdf) 7998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 8008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_msg *msg; 8018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->kdf_negotiation = 1; 8038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->kdf = kdf; 8048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "Generating EAP-AKA Challenge (id=%d) (KDF " 8058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "select)", id); 8068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, data->eap_method, 8078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_AKA_SUBTYPE_CHALLENGE); 8088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " AT_KDF"); 8098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_msg_add(msg, EAP_SIM_AT_KDF, kdf, NULL, 0); 810c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt return eap_sim_msg_finish(msg, data->eap_method, NULL, NULL, 0); 8118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 8128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_aka_prime_kdf_neg(struct eap_aka_data *data, 8158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 id, struct eap_sim_attrs *attr) 8168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 8178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t i; 8188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; i < attr->kdf_count; i++) { 8208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (attr->kdf[i] == EAP_AKA_PRIME_KDF) 8218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return eap_aka_prime_kdf_select(data, id, 8228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_AKA_PRIME_KDF); 8238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* No matching KDF found - fail authentication as if AUTN had been 8268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * incorrect */ 8278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return eap_aka_authentication_reject(data, id); 8288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 8298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_aka_prime_kdf_valid(struct eap_aka_data *data, 8328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_attrs *attr) 8338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 8348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t i, j; 8358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (attr->kdf_count == 0) 8378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 8388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* The only allowed (and required) duplication of a KDF is the addition 8408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * of the selected KDF into the beginning of the list. */ 8418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->kdf_negotiation) { 8438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (attr->kdf[0] != data->kdf) { 8448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "EAP-AKA': The server did not " 8458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "accept the selected KDF"); 8468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 8478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 1; i < attr->kdf_count; i++) { 8508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (attr->kdf[i] == data->kdf) 8518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 8528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (i == attr->kdf_count && 8548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt attr->kdf_count < EAP_AKA_PRIME_KDF_MAX) { 8558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "EAP-AKA': The server did not " 8568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "duplicate the selected KDF"); 8578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 8588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: should check that the list is identical to the one 8618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * used in the previous Challenge message apart from the added 8628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * entry in the beginning. */ 8638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = data->kdf ? 1 : 0; i < attr->kdf_count; i++) { 8668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (j = i + 1; j < attr->kdf_count; j++) { 8678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (attr->kdf[i] == attr->kdf[j]) { 8688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "EAP-AKA': The server " 8698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "included a duplicated KDF"); 8708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 8718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 1; 8768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 8778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* EAP_AKA_PRIME */ 8788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_aka_process_challenge(struct eap_sm *sm, 8818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_aka_data *data, 8828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 id, 8838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpabuf *reqData, 8848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_attrs *attr) 8858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 8868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *identity; 8878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t identity_len; 8888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int res; 8898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_attrs eattr; 8908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-AKA: subtype Challenge"); 8928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (attr->checkcode && 8948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_aka_verify_checkcode(data, attr->checkcode, 8958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt attr->checkcode_len)) { 8968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "EAP-AKA: Invalid AT_CHECKCODE in the " 8978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "message"); 8988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return eap_aka_client_error(data, id, 8998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_AKA_UNABLE_TO_PROCESS_PACKET); 9008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef EAP_AKA_PRIME 9038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->eap_method == EAP_TYPE_AKA_PRIME) { 9048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!attr->kdf_input || attr->kdf_input_len == 0) { 9058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "EAP-AKA': Challenge message " 9068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "did not include non-empty AT_KDF_INPUT"); 9078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Fail authentication as if AUTN had been incorrect */ 9088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return eap_aka_authentication_reject(data, id); 9098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data->network_name); 9118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->network_name = os_malloc(attr->kdf_input_len); 9128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->network_name == NULL) { 9138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "EAP-AKA': No memory for " 9148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "storing Network Name"); 9158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return eap_aka_authentication_reject(data, id); 9168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(data->network_name, attr->kdf_input, 9188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt attr->kdf_input_len); 9198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->network_name_len = attr->kdf_input_len; 9208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, "EAP-AKA': Network Name " 9218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(AT_KDF_INPUT)", 9228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->network_name, data->network_name_len); 9238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: check Network Name per 3GPP.33.402 */ 9248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!eap_aka_prime_kdf_valid(data, attr)) 9268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return eap_aka_authentication_reject(data, id); 9278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (attr->kdf[0] != EAP_AKA_PRIME_KDF) 9298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return eap_aka_prime_kdf_neg(data, id, attr); 9308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->kdf = EAP_AKA_PRIME_KDF; 9328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-AKA': KDF %d selected", data->kdf); 9338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->eap_method == EAP_TYPE_AKA && attr->bidding) { 9368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 flags = WPA_GET_BE16(attr->bidding); 9378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if ((flags & EAP_AKA_BIDDING_FLAG_D) && 9388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_allowed_method(sm, EAP_VENDOR_IETF, 9398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_TYPE_AKA_PRIME)) { 9408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "EAP-AKA: Bidding down from " 9418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "AKA' to AKA detected"); 9428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Fail authentication as if AUTN had been incorrect */ 9438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return eap_aka_authentication_reject(data, id); 9448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* EAP_AKA_PRIME */ 9478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->reauth = 0; 9498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!attr->mac || !attr->rand || !attr->autn) { 9508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "EAP-AKA: Challenge message " 9518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "did not include%s%s%s", 9528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt !attr->mac ? " AT_MAC" : "", 9538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt !attr->rand ? " AT_RAND" : "", 9548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt !attr->autn ? " AT_AUTN" : ""); 9558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return eap_aka_client_error(data, id, 9568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_AKA_UNABLE_TO_PROCESS_PACKET); 9578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(data->rand, attr->rand, EAP_AKA_RAND_LEN); 9598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(data->autn, attr->autn, EAP_AKA_AUTN_LEN); 9608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = eap_aka_umts_auth(sm, data); 9628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res == -1) { 9638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "EAP-AKA: UMTS authentication " 9648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "failed (AUTN)"); 9658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return eap_aka_authentication_reject(data, id); 9668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (res == -2) { 9678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "EAP-AKA: UMTS authentication " 9688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "failed (AUTN seq# -> AUTS)"); 9698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return eap_aka_synchronization_failure(data, id); 970051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt } else if (res > 0) { 971051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-AKA: Wait for external USIM processing"); 972051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt return NULL; 9738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (res) { 9748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "EAP-AKA: UMTS authentication failed"); 9758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return eap_aka_client_error(data, id, 9768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_AKA_UNABLE_TO_PROCESS_PACKET); 9778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef EAP_AKA_PRIME 9798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->eap_method == EAP_TYPE_AKA_PRIME) { 9808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Note: AUTN = (SQN ^ AK) || AMF || MAC which gives us the 9818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * needed 6-octet SQN ^ AK for CK',IK' derivation */ 9828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 amf = WPA_GET_BE16(data->autn + 6); 9838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!(amf & 0x8000)) { 9848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "EAP-AKA': AMF separation bit " 9858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "not set (AMF=0x%4x)", amf); 9868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return eap_aka_authentication_reject(data, id); 9878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_aka_prime_derive_ck_ik_prime(data->ck, data->ik, 9898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->autn, 9908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->network_name, 9918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->network_name_len); 9928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* EAP_AKA_PRIME */ 9948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->last_eap_identity) { 9958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt identity = data->last_eap_identity; 9968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt identity_len = data->last_eap_identity_len; 9978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (data->pseudonym) { 9988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt identity = data->pseudonym; 9998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt identity_len = data->pseudonym_len; 10008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else 10018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt identity = eap_get_config_identity(sm, &identity_len); 10028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, "EAP-AKA: Selected identity for MK " 10038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "derivation", identity, identity_len); 10048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->eap_method == EAP_TYPE_AKA_PRIME) { 10058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_aka_prime_derive_keys(identity, identity_len, data->ik, 10068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->ck, data->k_encr, data->k_aut, 10078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->k_re, data->msk, data->emsk); 10088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 10098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_aka_derive_mk(identity, identity_len, data->ik, data->ck, 10108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->mk); 10118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_derive_keys(data->mk, data->k_encr, data->k_aut, 10128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->msk, data->emsk); 10138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_aka_verify_mac(data, reqData, attr->mac, (u8 *) "", 0)) { 10158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "EAP-AKA: Challenge message " 10168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "used invalid AT_MAC"); 10178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return eap_aka_client_error(data, id, 10188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_AKA_UNABLE_TO_PROCESS_PACKET); 10198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt /* Old reauthentication identity must not be used anymore. In 10221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * other words, if no new identities are received, full 10231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * authentication will be used on next reauthentication (using 10241f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * pseudonym identity or permanent identity). */ 10254530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt eap_aka_clear_identities(sm, data, CLEAR_REAUTH_ID | CLEAR_EAP_ID); 10268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (attr->encr_data) { 10288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *decrypted; 10298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt decrypted = eap_sim_parse_encr(data->k_encr, attr->encr_data, 10308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt attr->encr_data_len, attr->iv, 10318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &eattr, 0); 10328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (decrypted == NULL) { 10338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return eap_aka_client_error( 10348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data, id, EAP_AKA_UNABLE_TO_PROCESS_PACKET); 10358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1036c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt eap_aka_learn_ids(sm, data, &eattr); 10378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(decrypted); 10388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->result_ind && attr->result_ind) 10418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->use_result_ind = 1; 10428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10432271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt if (data->state != FAILURE) { 10448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_aka_state(data, data->use_result_ind ? 10458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RESULT_SUCCESS : SUCCESS); 10468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->num_id_req = 0; 10498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->num_notification = 0; 10508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* RFC 4187 specifies that counter is initialized to one after 10518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * fullauth, but initializing it to zero makes it easier to implement 10528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * reauth verification. */ 10538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->counter = 0; 10548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return eap_aka_response_challenge(data, id); 10558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 10568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_aka_process_notification_reauth(struct eap_aka_data *data, 10598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_attrs *attr) 10608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 10618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_attrs eattr; 10628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *decrypted; 10638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (attr->encr_data == NULL || attr->iv == NULL) { 10658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "EAP-AKA: Notification message after " 10668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "reauth did not include encrypted data"); 10678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 10688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt decrypted = eap_sim_parse_encr(data->k_encr, attr->encr_data, 10718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt attr->encr_data_len, attr->iv, &eattr, 10728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0); 10738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (decrypted == NULL) { 10748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "EAP-AKA: Failed to parse encrypted " 10758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "data from notification message"); 10768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 10778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eattr.counter < 0 || (size_t) eattr.counter != data->counter) { 10808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "EAP-AKA: Counter in notification " 10818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "message does not match with counter in reauth " 10828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "message"); 10838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(decrypted); 10848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 10858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(decrypted); 10888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 10898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 10908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_aka_process_notification_auth(struct eap_aka_data *data, 10938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpabuf *reqData, 10948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_attrs *attr) 10958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 10968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (attr->mac == NULL) { 10978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-AKA: no AT_MAC in after_auth " 10988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Notification message"); 10998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 11008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_aka_verify_mac(data, reqData, attr->mac, (u8 *) "", 0)) { 11038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "EAP-AKA: Notification message " 11048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "used invalid AT_MAC"); 11058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 11068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->reauth && 11098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_aka_process_notification_reauth(data, attr)) { 11108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "EAP-AKA: Invalid notification " 11118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "message after reauth"); 11128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 11138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 11168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 11178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_aka_process_notification( 11208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sm *sm, struct eap_aka_data *data, u8 id, 11218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpabuf *reqData, struct eap_sim_attrs *attr) 11228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 11238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-AKA: subtype Notification"); 11248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->num_notification > 0) { 11258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-AKA: too many notification " 11268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "rounds (only one allowed)"); 11278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return eap_aka_client_error(data, id, 11288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_AKA_UNABLE_TO_PROCESS_PACKET); 11298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->num_notification++; 11318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (attr->notification == -1) { 11328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-AKA: no AT_NOTIFICATION in " 11338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Notification message"); 11348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return eap_aka_client_error(data, id, 11358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_AKA_UNABLE_TO_PROCESS_PACKET); 11368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if ((attr->notification & 0x4000) == 0 && 11398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_aka_process_notification_auth(data, reqData, attr)) { 11408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return eap_aka_client_error(data, id, 11418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_AKA_UNABLE_TO_PROCESS_PACKET); 11428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_report_notification(sm->msg_ctx, attr->notification, 1); 11458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (attr->notification >= 0 && attr->notification < 32768) { 11468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_aka_state(data, FAILURE); 11478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (attr->notification == EAP_SIM_SUCCESS && 11488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->state == RESULT_SUCCESS) 11498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_aka_state(data, SUCCESS); 11508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return eap_aka_response_notification(data, id, attr->notification); 11518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 11528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_aka_process_reauthentication( 11558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sm *sm, struct eap_aka_data *data, u8 id, 11568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpabuf *reqData, struct eap_sim_attrs *attr) 11578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 11588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_attrs eattr; 11598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *decrypted; 11608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-AKA: subtype Reauthentication"); 11628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (attr->checkcode && 11648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_aka_verify_checkcode(data, attr->checkcode, 11658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt attr->checkcode_len)) { 11668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "EAP-AKA: Invalid AT_CHECKCODE in the " 11678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "message"); 11688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return eap_aka_client_error(data, id, 11698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_AKA_UNABLE_TO_PROCESS_PACKET); 11708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->reauth_id == NULL) { 11738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "EAP-AKA: Server is trying " 11748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "reauthentication, but no reauth_id available"); 11758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return eap_aka_client_error(data, id, 11768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_AKA_UNABLE_TO_PROCESS_PACKET); 11778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->reauth = 1; 11808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_aka_verify_mac(data, reqData, attr->mac, (u8 *) "", 0)) { 11818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "EAP-AKA: Reauthentication " 11828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "did not have valid AT_MAC"); 11838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return eap_aka_client_error(data, id, 11848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_AKA_UNABLE_TO_PROCESS_PACKET); 11858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (attr->encr_data == NULL || attr->iv == NULL) { 11888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "EAP-AKA: Reauthentication " 11898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "message did not include encrypted data"); 11908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return eap_aka_client_error(data, id, 11918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_AKA_UNABLE_TO_PROCESS_PACKET); 11928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt decrypted = eap_sim_parse_encr(data->k_encr, attr->encr_data, 11958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt attr->encr_data_len, attr->iv, &eattr, 11968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0); 11978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (decrypted == NULL) { 11988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "EAP-AKA: Failed to parse encrypted " 11998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "data from reauthentication message"); 12008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return eap_aka_client_error(data, id, 12018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_AKA_UNABLE_TO_PROCESS_PACKET); 12028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eattr.nonce_s == NULL || eattr.counter < 0) { 12058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-AKA: (encr) No%s%s in reauth packet", 12068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt !eattr.nonce_s ? " AT_NONCE_S" : "", 12078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eattr.counter < 0 ? " AT_COUNTER" : ""); 12088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(decrypted); 12098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return eap_aka_client_error(data, id, 12108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_AKA_UNABLE_TO_PROCESS_PACKET); 12118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eattr.counter < 0 || (size_t) eattr.counter <= data->counter) { 12148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *res; 12158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-AKA: (encr) Invalid counter " 12168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(%d <= %d)", eattr.counter, data->counter); 12178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->counter_too_small = eattr.counter; 12188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Reply using Re-auth w/ AT_COUNTER_TOO_SMALL. The current 12208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * reauth_id must not be used to start a new reauthentication. 12218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * However, since it was used in the last EAP-Response-Identity 12228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * packet, it has to saved for the following fullauth to be 12238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * used in MK derivation. */ 12248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data->last_eap_identity); 12258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->last_eap_identity = data->reauth_id; 12268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->last_eap_identity_len = data->reauth_id_len; 12278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->reauth_id = NULL; 12288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->reauth_id_len = 0; 12298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = eap_aka_response_reauth(data, id, 1, eattr.nonce_s); 12318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(decrypted); 12328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return res; 12348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->counter = eattr.counter; 12368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(data->nonce_s, eattr.nonce_s, EAP_SIM_NONCE_S_LEN); 12388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "EAP-AKA: (encr) AT_NONCE_S", 12398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->nonce_s, EAP_SIM_NONCE_S_LEN); 12408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->eap_method == EAP_TYPE_AKA_PRIME) { 12428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_aka_prime_derive_keys_reauth(data->k_re, data->counter, 12438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->reauth_id, 12448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->reauth_id_len, 12458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->nonce_s, 12468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->msk, data->emsk); 12478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 12488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sim_derive_keys_reauth(data->counter, data->reauth_id, 12498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->reauth_id_len, 12508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->nonce_s, data->mk, 12518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->msk, data->emsk); 12528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12534530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt eap_aka_clear_identities(sm, data, CLEAR_REAUTH_ID | CLEAR_EAP_ID); 1254c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt eap_aka_learn_ids(sm, data, &eattr); 12558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->result_ind && attr->result_ind) 12578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->use_result_ind = 1; 12588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12592271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt if (data->state != FAILURE) { 12608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_aka_state(data, data->use_result_ind ? 12618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RESULT_SUCCESS : SUCCESS); 12628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->num_id_req = 0; 12658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->num_notification = 0; 12668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->counter > EAP_AKA_MAX_FAST_REAUTHS) { 12678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-AKA: Maximum number of " 12688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "fast reauths performed - force fullauth"); 12694530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt eap_aka_clear_identities(sm, data, 12704530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt CLEAR_REAUTH_ID | CLEAR_EAP_ID); 12718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(decrypted); 12738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return eap_aka_response_reauth(data, id, 0, data->nonce_s); 12748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 12758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_aka_process(struct eap_sm *sm, void *priv, 12788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_method_ret *ret, 12798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpabuf *reqData) 12808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 12818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_aka_data *data = priv; 12828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct eap_hdr *req; 12838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 subtype, id; 12848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *res; 12858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos; 12868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sim_attrs attr; 12878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len; 12888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_buf(MSG_DEBUG, "EAP-AKA: EAP data", reqData); 12908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_get_config_identity(sm, &len) == NULL) { 12918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-AKA: Identity not configured"); 12928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sm_request_identity(sm); 12938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->ignore = TRUE; 12948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 12958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = eap_hdr_validate(EAP_VENDOR_IETF, data->eap_method, reqData, 12988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &len); 12998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos == NULL || len < 1) { 13008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->ignore = TRUE; 13018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 13028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 13038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt req = wpabuf_head(reqData); 13048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt id = req->identifier; 13058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len = be_to_host16(req->length); 13068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->ignore = FALSE; 13088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->methodState = METHOD_MAY_CONT; 13098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->decision = DECISION_FAIL; 13108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->allowNotifications = TRUE; 13118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt subtype = *pos++; 13138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-AKA: Subtype=%d", subtype); 13148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2; /* Reserved */ 13158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_sim_parse_attr(pos, wpabuf_head_u8(reqData) + len, &attr, 13178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->eap_method == EAP_TYPE_AKA_PRIME ? 2 : 1, 13188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0)) { 13198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = eap_aka_client_error(data, id, 13208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_AKA_UNABLE_TO_PROCESS_PACKET); 13218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto done; 13228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 13238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (subtype) { 13258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case EAP_AKA_SUBTYPE_IDENTITY: 13268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = eap_aka_process_identity(sm, data, id, reqData, &attr); 13278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 13288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case EAP_AKA_SUBTYPE_CHALLENGE: 13298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = eap_aka_process_challenge(sm, data, id, reqData, &attr); 13308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 13318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case EAP_AKA_SUBTYPE_NOTIFICATION: 13328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = eap_aka_process_notification(sm, data, id, reqData, 13338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &attr); 13348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 13358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case EAP_AKA_SUBTYPE_REAUTHENTICATION: 13368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = eap_aka_process_reauthentication(sm, data, id, reqData, 13378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &attr); 13388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 13398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case EAP_AKA_SUBTYPE_CLIENT_ERROR: 13408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-AKA: subtype Client-Error"); 13418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = eap_aka_client_error(data, id, 13428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_AKA_UNABLE_TO_PROCESS_PACKET); 13438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 13448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 13458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-AKA: Unknown subtype=%d", subtype); 13468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = eap_aka_client_error(data, id, 13478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_AKA_UNABLE_TO_PROCESS_PACKET); 13488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 13498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 13508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtdone: 13528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->state == FAILURE) { 13538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->decision = DECISION_FAIL; 13548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->methodState = METHOD_DONE; 13558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (data->state == SUCCESS) { 13568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->decision = data->use_result_ind ? 13578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt DECISION_UNCOND_SUCC : DECISION_COND_SUCC; 13588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 13598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * It is possible for the server to reply with AKA 13608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Notification, so we must allow the method to continue and 13618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * not only accept EAP-Success at this point. 13628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 13638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->methodState = data->use_result_ind ? 13648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt METHOD_DONE : METHOD_MAY_CONT; 13652271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt } else if (data->state == RESULT_SUCCESS) 13668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->methodState = METHOD_CONT; 13678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret->methodState == METHOD_DONE) { 13698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->allowNotifications = FALSE; 13708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 13718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return res; 13738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 13748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic Boolean eap_aka_has_reauth_data(struct eap_sm *sm, void *priv) 13778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 13788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_aka_data *data = priv; 13798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return data->pseudonym || data->reauth_id; 13808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 13818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_aka_deinit_for_reauth(struct eap_sm *sm, void *priv) 13848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 13858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_aka_data *data = priv; 13864530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt eap_aka_clear_identities(sm, data, CLEAR_EAP_ID); 13878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->prev_id = -1; 13888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(data->id_msgs); 13898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->id_msgs = NULL; 13908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->use_result_ind = 0; 13918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->kdf_negotiation = 0; 1392c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt eap_aka_clear_keys(data, 1); 13938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 13948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void * eap_aka_init_for_reauth(struct eap_sm *sm, void *priv) 13978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 13988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_aka_data *data = priv; 13998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->num_id_req = 0; 14008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->num_notification = 0; 14018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_aka_state(data, CONTINUE); 14028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return priv; 14038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 14048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const u8 * eap_aka_get_identity(struct eap_sm *sm, void *priv, 14078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t *len) 14088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 14098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_aka_data *data = priv; 14108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->reauth_id) { 14128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *len = data->reauth_id_len; 14138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return data->reauth_id; 14148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 14158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->pseudonym) { 14178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *len = data->pseudonym_len; 14188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return data->pseudonym; 14198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 14208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 14228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 14238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic Boolean eap_aka_isKeyAvailable(struct eap_sm *sm, void *priv) 14268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 14278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_aka_data *data = priv; 14288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return data->state == SUCCESS; 14298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 14308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic u8 * eap_aka_getKey(struct eap_sm *sm, void *priv, size_t *len) 14338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 14348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_aka_data *data = priv; 14358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *key; 14368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->state != SUCCESS) 14388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 14398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key = os_malloc(EAP_SIM_KEYING_DATA_LEN); 14418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (key == NULL) 14428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 14438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *len = EAP_SIM_KEYING_DATA_LEN; 14458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(key, data->msk, EAP_SIM_KEYING_DATA_LEN); 14468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return key; 14488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 14498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1451f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidtstatic u8 * eap_aka_get_session_id(struct eap_sm *sm, void *priv, size_t *len) 1452f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt{ 1453f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt struct eap_aka_data *data = priv; 1454f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt u8 *id; 1455f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 1456f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt if (data->state != SUCCESS) 1457f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt return NULL; 1458f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 1459f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt *len = 1 + EAP_AKA_RAND_LEN + EAP_AKA_AUTN_LEN; 1460f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt id = os_malloc(*len); 1461f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt if (id == NULL) 1462f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt return NULL; 1463f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 1464f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt id[0] = data->eap_method; 1465f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt os_memcpy(id + 1, data->rand, EAP_AKA_RAND_LEN); 1466f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt os_memcpy(id + 1 + EAP_AKA_RAND_LEN, data->autn, EAP_AKA_AUTN_LEN); 1467f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "EAP-AKA: Derived Session-Id", id, *len); 1468f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 1469f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt return id; 1470f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt} 1471f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 1472f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 14738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic u8 * eap_aka_get_emsk(struct eap_sm *sm, void *priv, size_t *len) 14748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 14758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_aka_data *data = priv; 14768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *key; 14778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->state != SUCCESS) 14798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 14808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key = os_malloc(EAP_EMSK_LEN); 14828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (key == NULL) 14838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 14848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *len = EAP_EMSK_LEN; 14868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(key, data->emsk, EAP_EMSK_LEN); 14878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return key; 14898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 14908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint eap_peer_aka_register(void) 14938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 14948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_method *eap; 14958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret; 14968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, 14988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_VENDOR_IETF, EAP_TYPE_AKA, "AKA"); 14998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap == NULL) 15008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 15018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->init = eap_aka_init; 15038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->deinit = eap_aka_deinit; 15048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->process = eap_aka_process; 15058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->isKeyAvailable = eap_aka_isKeyAvailable; 15068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->getKey = eap_aka_getKey; 1507f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt eap->getSessionId = eap_aka_get_session_id; 15088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->has_reauth_data = eap_aka_has_reauth_data; 15098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->deinit_for_reauth = eap_aka_deinit_for_reauth; 15108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->init_for_reauth = eap_aka_init_for_reauth; 15118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->get_identity = eap_aka_get_identity; 15128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->get_emsk = eap_aka_get_emsk; 15138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = eap_peer_method_register(eap); 15158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret) 15168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_peer_method_free(eap); 15178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 15188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 15198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef EAP_AKA_PRIME 15228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint eap_peer_aka_prime_register(void) 15238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 15248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_method *eap; 15258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret; 15268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, 15288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_VENDOR_IETF, EAP_TYPE_AKA_PRIME, 15298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "AKA'"); 15308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap == NULL) 15318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 15328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->init = eap_aka_prime_init; 15348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->deinit = eap_aka_deinit; 15358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->process = eap_aka_process; 15368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->isKeyAvailable = eap_aka_isKeyAvailable; 15378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->getKey = eap_aka_getKey; 1538f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt eap->getSessionId = eap_aka_get_session_id; 15398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->has_reauth_data = eap_aka_has_reauth_data; 15408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->deinit_for_reauth = eap_aka_deinit_for_reauth; 15418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->init_for_reauth = eap_aka_init_for_reauth; 15428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->get_identity = eap_aka_get_identity; 15438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->get_emsk = eap_aka_get_emsk; 15448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = eap_peer_method_register(eap); 15468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret) 15478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_peer_method_free(eap); 15488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 15508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 15518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* EAP_AKA_PRIME */ 1552