1*8dbcf02cSchristos /* 2*8dbcf02cSchristos * EAP peer method: EAP-AKA (RFC 4187) and EAP-AKA' (draft-arkko-eap-aka-kdf) 3*8dbcf02cSchristos * Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi> 4*8dbcf02cSchristos * 5*8dbcf02cSchristos * This program is free software; you can redistribute it and/or modify 6*8dbcf02cSchristos * it under the terms of the GNU General Public License version 2 as 7*8dbcf02cSchristos * published by the Free Software Foundation. 8*8dbcf02cSchristos * 9*8dbcf02cSchristos * Alternatively, this software may be distributed under the terms of BSD 10*8dbcf02cSchristos * license. 11*8dbcf02cSchristos * 12*8dbcf02cSchristos * See README and COPYING for more details. 13*8dbcf02cSchristos */ 14*8dbcf02cSchristos 15*8dbcf02cSchristos #include "includes.h" 16*8dbcf02cSchristos 17*8dbcf02cSchristos #include "common.h" 18*8dbcf02cSchristos #include "pcsc_funcs.h" 19*8dbcf02cSchristos #include "crypto/crypto.h" 20*8dbcf02cSchristos #include "crypto/sha1.h" 21*8dbcf02cSchristos #include "crypto/sha256.h" 22*8dbcf02cSchristos #include "crypto/milenage.h" 23*8dbcf02cSchristos #include "eap_common/eap_sim_common.h" 24*8dbcf02cSchristos #include "eap_config.h" 25*8dbcf02cSchristos #include "eap_i.h" 26*8dbcf02cSchristos 27*8dbcf02cSchristos 28*8dbcf02cSchristos struct eap_aka_data { 29*8dbcf02cSchristos u8 ik[EAP_AKA_IK_LEN], ck[EAP_AKA_CK_LEN], res[EAP_AKA_RES_MAX_LEN]; 30*8dbcf02cSchristos size_t res_len; 31*8dbcf02cSchristos u8 nonce_s[EAP_SIM_NONCE_S_LEN]; 32*8dbcf02cSchristos u8 mk[EAP_SIM_MK_LEN]; 33*8dbcf02cSchristos u8 k_aut[EAP_AKA_PRIME_K_AUT_LEN]; 34*8dbcf02cSchristos u8 k_encr[EAP_SIM_K_ENCR_LEN]; 35*8dbcf02cSchristos u8 k_re[EAP_AKA_PRIME_K_RE_LEN]; /* EAP-AKA' only */ 36*8dbcf02cSchristos u8 msk[EAP_SIM_KEYING_DATA_LEN]; 37*8dbcf02cSchristos u8 emsk[EAP_EMSK_LEN]; 38*8dbcf02cSchristos u8 rand[EAP_AKA_RAND_LEN], autn[EAP_AKA_AUTN_LEN]; 39*8dbcf02cSchristos u8 auts[EAP_AKA_AUTS_LEN]; 40*8dbcf02cSchristos 41*8dbcf02cSchristos int num_id_req, num_notification; 42*8dbcf02cSchristos u8 *pseudonym; 43*8dbcf02cSchristos size_t pseudonym_len; 44*8dbcf02cSchristos u8 *reauth_id; 45*8dbcf02cSchristos size_t reauth_id_len; 46*8dbcf02cSchristos int reauth; 47*8dbcf02cSchristos unsigned int counter, counter_too_small; 48*8dbcf02cSchristos u8 *last_eap_identity; 49*8dbcf02cSchristos size_t last_eap_identity_len; 50*8dbcf02cSchristos enum { 51*8dbcf02cSchristos CONTINUE, RESULT_SUCCESS, RESULT_FAILURE, SUCCESS, FAILURE 52*8dbcf02cSchristos } state; 53*8dbcf02cSchristos 54*8dbcf02cSchristos struct wpabuf *id_msgs; 55*8dbcf02cSchristos int prev_id; 56*8dbcf02cSchristos int result_ind, use_result_ind; 57*8dbcf02cSchristos u8 eap_method; 58*8dbcf02cSchristos u8 *network_name; 59*8dbcf02cSchristos size_t network_name_len; 60*8dbcf02cSchristos u16 kdf; 61*8dbcf02cSchristos int kdf_negotiation; 62*8dbcf02cSchristos }; 63*8dbcf02cSchristos 64*8dbcf02cSchristos 65*8dbcf02cSchristos #ifndef CONFIG_NO_STDOUT_DEBUG 66*8dbcf02cSchristos static const char * eap_aka_state_txt(int state) 67*8dbcf02cSchristos { 68*8dbcf02cSchristos switch (state) { 69*8dbcf02cSchristos case CONTINUE: 70*8dbcf02cSchristos return "CONTINUE"; 71*8dbcf02cSchristos case RESULT_SUCCESS: 72*8dbcf02cSchristos return "RESULT_SUCCESS"; 73*8dbcf02cSchristos case RESULT_FAILURE: 74*8dbcf02cSchristos return "RESULT_FAILURE"; 75*8dbcf02cSchristos case SUCCESS: 76*8dbcf02cSchristos return "SUCCESS"; 77*8dbcf02cSchristos case FAILURE: 78*8dbcf02cSchristos return "FAILURE"; 79*8dbcf02cSchristos default: 80*8dbcf02cSchristos return "?"; 81*8dbcf02cSchristos } 82*8dbcf02cSchristos } 83*8dbcf02cSchristos #endif /* CONFIG_NO_STDOUT_DEBUG */ 84*8dbcf02cSchristos 85*8dbcf02cSchristos 86*8dbcf02cSchristos static void eap_aka_state(struct eap_aka_data *data, int state) 87*8dbcf02cSchristos { 88*8dbcf02cSchristos wpa_printf(MSG_DEBUG, "EAP-AKA: %s -> %s", 89*8dbcf02cSchristos eap_aka_state_txt(data->state), 90*8dbcf02cSchristos eap_aka_state_txt(state)); 91*8dbcf02cSchristos data->state = state; 92*8dbcf02cSchristos } 93*8dbcf02cSchristos 94*8dbcf02cSchristos 95*8dbcf02cSchristos static void * eap_aka_init(struct eap_sm *sm) 96*8dbcf02cSchristos { 97*8dbcf02cSchristos struct eap_aka_data *data; 98*8dbcf02cSchristos const char *phase1 = eap_get_config_phase1(sm); 99*8dbcf02cSchristos 100*8dbcf02cSchristos data = os_zalloc(sizeof(*data)); 101*8dbcf02cSchristos if (data == NULL) 102*8dbcf02cSchristos return NULL; 103*8dbcf02cSchristos 104*8dbcf02cSchristos data->eap_method = EAP_TYPE_AKA; 105*8dbcf02cSchristos 106*8dbcf02cSchristos eap_aka_state(data, CONTINUE); 107*8dbcf02cSchristos data->prev_id = -1; 108*8dbcf02cSchristos 109*8dbcf02cSchristos data->result_ind = phase1 && os_strstr(phase1, "result_ind=1") != NULL; 110*8dbcf02cSchristos 111*8dbcf02cSchristos return data; 112*8dbcf02cSchristos } 113*8dbcf02cSchristos 114*8dbcf02cSchristos 115*8dbcf02cSchristos #ifdef EAP_AKA_PRIME 116*8dbcf02cSchristos static void * eap_aka_prime_init(struct eap_sm *sm) 117*8dbcf02cSchristos { 118*8dbcf02cSchristos struct eap_aka_data *data = eap_aka_init(sm); 119*8dbcf02cSchristos if (data == NULL) 120*8dbcf02cSchristos return NULL; 121*8dbcf02cSchristos data->eap_method = EAP_TYPE_AKA_PRIME; 122*8dbcf02cSchristos return data; 123*8dbcf02cSchristos } 124*8dbcf02cSchristos #endif /* EAP_AKA_PRIME */ 125*8dbcf02cSchristos 126*8dbcf02cSchristos 127*8dbcf02cSchristos static void eap_aka_deinit(struct eap_sm *sm, void *priv) 128*8dbcf02cSchristos { 129*8dbcf02cSchristos struct eap_aka_data *data = priv; 130*8dbcf02cSchristos if (data) { 131*8dbcf02cSchristos os_free(data->pseudonym); 132*8dbcf02cSchristos os_free(data->reauth_id); 133*8dbcf02cSchristos os_free(data->last_eap_identity); 134*8dbcf02cSchristos wpabuf_free(data->id_msgs); 135*8dbcf02cSchristos os_free(data->network_name); 136*8dbcf02cSchristos os_free(data); 137*8dbcf02cSchristos } 138*8dbcf02cSchristos } 139*8dbcf02cSchristos 140*8dbcf02cSchristos 141*8dbcf02cSchristos static int eap_aka_umts_auth(struct eap_sm *sm, struct eap_aka_data *data) 142*8dbcf02cSchristos { 143*8dbcf02cSchristos struct eap_peer_config *conf; 144*8dbcf02cSchristos 145*8dbcf02cSchristos wpa_printf(MSG_DEBUG, "EAP-AKA: UMTS authentication algorithm"); 146*8dbcf02cSchristos 147*8dbcf02cSchristos conf = eap_get_config(sm); 148*8dbcf02cSchristos if (conf == NULL) 149*8dbcf02cSchristos return -1; 150*8dbcf02cSchristos if (conf->pcsc) { 151*8dbcf02cSchristos return scard_umts_auth(sm->scard_ctx, data->rand, 152*8dbcf02cSchristos data->autn, data->res, &data->res_len, 153*8dbcf02cSchristos data->ik, data->ck, data->auts); 154*8dbcf02cSchristos } 155*8dbcf02cSchristos 156*8dbcf02cSchristos #ifdef CONFIG_USIM_SIMULATOR 157*8dbcf02cSchristos if (conf->password) { 158*8dbcf02cSchristos u8 opc[16], k[16], sqn[6]; 159*8dbcf02cSchristos const char *pos; 160*8dbcf02cSchristos wpa_printf(MSG_DEBUG, "EAP-AKA: Use internal Milenage " 161*8dbcf02cSchristos "implementation for UMTS authentication"); 162*8dbcf02cSchristos if (conf->password_len < 78) { 163*8dbcf02cSchristos wpa_printf(MSG_DEBUG, "EAP-AKA: invalid Milenage " 164*8dbcf02cSchristos "password"); 165*8dbcf02cSchristos return -1; 166*8dbcf02cSchristos } 167*8dbcf02cSchristos pos = (const char *) conf->password; 168*8dbcf02cSchristos if (hexstr2bin(pos, k, 16)) 169*8dbcf02cSchristos return -1; 170*8dbcf02cSchristos pos += 32; 171*8dbcf02cSchristos if (*pos != ':') 172*8dbcf02cSchristos return -1; 173*8dbcf02cSchristos pos++; 174*8dbcf02cSchristos 175*8dbcf02cSchristos if (hexstr2bin(pos, opc, 16)) 176*8dbcf02cSchristos return -1; 177*8dbcf02cSchristos pos += 32; 178*8dbcf02cSchristos if (*pos != ':') 179*8dbcf02cSchristos return -1; 180*8dbcf02cSchristos pos++; 181*8dbcf02cSchristos 182*8dbcf02cSchristos if (hexstr2bin(pos, sqn, 6)) 183*8dbcf02cSchristos return -1; 184*8dbcf02cSchristos 185*8dbcf02cSchristos return milenage_check(opc, k, sqn, data->rand, data->autn, 186*8dbcf02cSchristos data->ik, data->ck, 187*8dbcf02cSchristos data->res, &data->res_len, data->auts); 188*8dbcf02cSchristos } 189*8dbcf02cSchristos #endif /* CONFIG_USIM_SIMULATOR */ 190*8dbcf02cSchristos 191*8dbcf02cSchristos #ifdef CONFIG_USIM_HARDCODED 192*8dbcf02cSchristos wpa_printf(MSG_DEBUG, "EAP-AKA: Use hardcoded Kc and SRES values for " 193*8dbcf02cSchristos "testing"); 194*8dbcf02cSchristos 195*8dbcf02cSchristos /* These hardcoded Kc and SRES values are used for testing. 196*8dbcf02cSchristos * Could consider making them configurable. */ 197*8dbcf02cSchristos os_memset(data->res, '2', EAP_AKA_RES_MAX_LEN); 198*8dbcf02cSchristos data->res_len = EAP_AKA_RES_MAX_LEN; 199*8dbcf02cSchristos os_memset(data->ik, '3', EAP_AKA_IK_LEN); 200*8dbcf02cSchristos os_memset(data->ck, '4', EAP_AKA_CK_LEN); 201*8dbcf02cSchristos { 202*8dbcf02cSchristos u8 autn[EAP_AKA_AUTN_LEN]; 203*8dbcf02cSchristos os_memset(autn, '1', EAP_AKA_AUTN_LEN); 204*8dbcf02cSchristos if (os_memcmp(autn, data->autn, EAP_AKA_AUTN_LEN) != 0) { 205*8dbcf02cSchristos wpa_printf(MSG_WARNING, "EAP-AKA: AUTN did not match " 206*8dbcf02cSchristos "with expected value"); 207*8dbcf02cSchristos return -1; 208*8dbcf02cSchristos } 209*8dbcf02cSchristos } 210*8dbcf02cSchristos #if 0 211*8dbcf02cSchristos { 212*8dbcf02cSchristos static int test_resync = 1; 213*8dbcf02cSchristos if (test_resync) { 214*8dbcf02cSchristos /* Test Resynchronization */ 215*8dbcf02cSchristos test_resync = 0; 216*8dbcf02cSchristos return -2; 217*8dbcf02cSchristos } 218*8dbcf02cSchristos } 219*8dbcf02cSchristos #endif 220*8dbcf02cSchristos return 0; 221*8dbcf02cSchristos 222*8dbcf02cSchristos #else /* CONFIG_USIM_HARDCODED */ 223*8dbcf02cSchristos 224*8dbcf02cSchristos wpa_printf(MSG_DEBUG, "EAP-AKA: No UMTS authentication algorith " 225*8dbcf02cSchristos "enabled"); 226*8dbcf02cSchristos return -1; 227*8dbcf02cSchristos 228*8dbcf02cSchristos #endif /* CONFIG_USIM_HARDCODED */ 229*8dbcf02cSchristos } 230*8dbcf02cSchristos 231*8dbcf02cSchristos 232*8dbcf02cSchristos #define CLEAR_PSEUDONYM 0x01 233*8dbcf02cSchristos #define CLEAR_REAUTH_ID 0x02 234*8dbcf02cSchristos #define CLEAR_EAP_ID 0x04 235*8dbcf02cSchristos 236*8dbcf02cSchristos static void eap_aka_clear_identities(struct eap_aka_data *data, int id) 237*8dbcf02cSchristos { 238*8dbcf02cSchristos wpa_printf(MSG_DEBUG, "EAP-AKA: forgetting old%s%s%s", 239*8dbcf02cSchristos id & CLEAR_PSEUDONYM ? " pseudonym" : "", 240*8dbcf02cSchristos id & CLEAR_REAUTH_ID ? " reauth_id" : "", 241*8dbcf02cSchristos id & CLEAR_EAP_ID ? " eap_id" : ""); 242*8dbcf02cSchristos if (id & CLEAR_PSEUDONYM) { 243*8dbcf02cSchristos os_free(data->pseudonym); 244*8dbcf02cSchristos data->pseudonym = NULL; 245*8dbcf02cSchristos data->pseudonym_len = 0; 246*8dbcf02cSchristos } 247*8dbcf02cSchristos if (id & CLEAR_REAUTH_ID) { 248*8dbcf02cSchristos os_free(data->reauth_id); 249*8dbcf02cSchristos data->reauth_id = NULL; 250*8dbcf02cSchristos data->reauth_id_len = 0; 251*8dbcf02cSchristos } 252*8dbcf02cSchristos if (id & CLEAR_EAP_ID) { 253*8dbcf02cSchristos os_free(data->last_eap_identity); 254*8dbcf02cSchristos data->last_eap_identity = NULL; 255*8dbcf02cSchristos data->last_eap_identity_len = 0; 256*8dbcf02cSchristos } 257*8dbcf02cSchristos } 258*8dbcf02cSchristos 259*8dbcf02cSchristos 260*8dbcf02cSchristos static int eap_aka_learn_ids(struct eap_aka_data *data, 261*8dbcf02cSchristos struct eap_sim_attrs *attr) 262*8dbcf02cSchristos { 263*8dbcf02cSchristos if (attr->next_pseudonym) { 264*8dbcf02cSchristos os_free(data->pseudonym); 265*8dbcf02cSchristos data->pseudonym = os_malloc(attr->next_pseudonym_len); 266*8dbcf02cSchristos if (data->pseudonym == NULL) { 267*8dbcf02cSchristos wpa_printf(MSG_INFO, "EAP-AKA: (encr) No memory for " 268*8dbcf02cSchristos "next pseudonym"); 269*8dbcf02cSchristos return -1; 270*8dbcf02cSchristos } 271*8dbcf02cSchristos os_memcpy(data->pseudonym, attr->next_pseudonym, 272*8dbcf02cSchristos attr->next_pseudonym_len); 273*8dbcf02cSchristos data->pseudonym_len = attr->next_pseudonym_len; 274*8dbcf02cSchristos wpa_hexdump_ascii(MSG_DEBUG, 275*8dbcf02cSchristos "EAP-AKA: (encr) AT_NEXT_PSEUDONYM", 276*8dbcf02cSchristos data->pseudonym, 277*8dbcf02cSchristos data->pseudonym_len); 278*8dbcf02cSchristos } 279*8dbcf02cSchristos 280*8dbcf02cSchristos if (attr->next_reauth_id) { 281*8dbcf02cSchristos os_free(data->reauth_id); 282*8dbcf02cSchristos data->reauth_id = os_malloc(attr->next_reauth_id_len); 283*8dbcf02cSchristos if (data->reauth_id == NULL) { 284*8dbcf02cSchristos wpa_printf(MSG_INFO, "EAP-AKA: (encr) No memory for " 285*8dbcf02cSchristos "next reauth_id"); 286*8dbcf02cSchristos return -1; 287*8dbcf02cSchristos } 288*8dbcf02cSchristos os_memcpy(data->reauth_id, attr->next_reauth_id, 289*8dbcf02cSchristos attr->next_reauth_id_len); 290*8dbcf02cSchristos data->reauth_id_len = attr->next_reauth_id_len; 291*8dbcf02cSchristos wpa_hexdump_ascii(MSG_DEBUG, 292*8dbcf02cSchristos "EAP-AKA: (encr) AT_NEXT_REAUTH_ID", 293*8dbcf02cSchristos data->reauth_id, 294*8dbcf02cSchristos data->reauth_id_len); 295*8dbcf02cSchristos } 296*8dbcf02cSchristos 297*8dbcf02cSchristos return 0; 298*8dbcf02cSchristos } 299*8dbcf02cSchristos 300*8dbcf02cSchristos 301*8dbcf02cSchristos static int eap_aka_add_id_msg(struct eap_aka_data *data, 302*8dbcf02cSchristos const struct wpabuf *msg) 303*8dbcf02cSchristos { 304*8dbcf02cSchristos if (msg == NULL) 305*8dbcf02cSchristos return -1; 306*8dbcf02cSchristos 307*8dbcf02cSchristos if (data->id_msgs == NULL) { 308*8dbcf02cSchristos data->id_msgs = wpabuf_dup(msg); 309*8dbcf02cSchristos return data->id_msgs == NULL ? -1 : 0; 310*8dbcf02cSchristos } 311*8dbcf02cSchristos 312*8dbcf02cSchristos if (wpabuf_resize(&data->id_msgs, wpabuf_len(msg)) < 0) 313*8dbcf02cSchristos return -1; 314*8dbcf02cSchristos wpabuf_put_buf(data->id_msgs, msg); 315*8dbcf02cSchristos 316*8dbcf02cSchristos return 0; 317*8dbcf02cSchristos } 318*8dbcf02cSchristos 319*8dbcf02cSchristos 320*8dbcf02cSchristos static void eap_aka_add_checkcode(struct eap_aka_data *data, 321*8dbcf02cSchristos struct eap_sim_msg *msg) 322*8dbcf02cSchristos { 323*8dbcf02cSchristos const u8 *addr; 324*8dbcf02cSchristos size_t len; 325*8dbcf02cSchristos u8 hash[SHA256_MAC_LEN]; 326*8dbcf02cSchristos 327*8dbcf02cSchristos wpa_printf(MSG_DEBUG, " AT_CHECKCODE"); 328*8dbcf02cSchristos 329*8dbcf02cSchristos if (data->id_msgs == NULL) { 330*8dbcf02cSchristos /* 331*8dbcf02cSchristos * No EAP-AKA/Identity packets were exchanged - send empty 332*8dbcf02cSchristos * checkcode. 333*8dbcf02cSchristos */ 334*8dbcf02cSchristos eap_sim_msg_add(msg, EAP_SIM_AT_CHECKCODE, 0, NULL, 0); 335*8dbcf02cSchristos return; 336*8dbcf02cSchristos } 337*8dbcf02cSchristos 338*8dbcf02cSchristos /* Checkcode is SHA1/SHA256 hash over all EAP-AKA/Identity packets. */ 339*8dbcf02cSchristos addr = wpabuf_head(data->id_msgs); 340*8dbcf02cSchristos len = wpabuf_len(data->id_msgs); 341*8dbcf02cSchristos wpa_hexdump(MSG_MSGDUMP, "EAP-AKA: AT_CHECKCODE data", addr, len); 342*8dbcf02cSchristos #ifdef EAP_AKA_PRIME 343*8dbcf02cSchristos if (data->eap_method == EAP_TYPE_AKA_PRIME) 344*8dbcf02cSchristos sha256_vector(1, &addr, &len, hash); 345*8dbcf02cSchristos else 346*8dbcf02cSchristos #endif /* EAP_AKA_PRIME */ 347*8dbcf02cSchristos sha1_vector(1, &addr, &len, hash); 348*8dbcf02cSchristos 349*8dbcf02cSchristos eap_sim_msg_add(msg, EAP_SIM_AT_CHECKCODE, 0, hash, 350*8dbcf02cSchristos data->eap_method == EAP_TYPE_AKA_PRIME ? 351*8dbcf02cSchristos EAP_AKA_PRIME_CHECKCODE_LEN : EAP_AKA_CHECKCODE_LEN); 352*8dbcf02cSchristos } 353*8dbcf02cSchristos 354*8dbcf02cSchristos 355*8dbcf02cSchristos static int eap_aka_verify_checkcode(struct eap_aka_data *data, 356*8dbcf02cSchristos const u8 *checkcode, size_t checkcode_len) 357*8dbcf02cSchristos { 358*8dbcf02cSchristos const u8 *addr; 359*8dbcf02cSchristos size_t len; 360*8dbcf02cSchristos u8 hash[SHA256_MAC_LEN]; 361*8dbcf02cSchristos size_t hash_len; 362*8dbcf02cSchristos 363*8dbcf02cSchristos if (checkcode == NULL) 364*8dbcf02cSchristos return -1; 365*8dbcf02cSchristos 366*8dbcf02cSchristos if (data->id_msgs == NULL) { 367*8dbcf02cSchristos if (checkcode_len != 0) { 368*8dbcf02cSchristos wpa_printf(MSG_DEBUG, "EAP-AKA: Checkcode from server " 369*8dbcf02cSchristos "indicates that AKA/Identity messages were " 370*8dbcf02cSchristos "used, but they were not"); 371*8dbcf02cSchristos return -1; 372*8dbcf02cSchristos } 373*8dbcf02cSchristos return 0; 374*8dbcf02cSchristos } 375*8dbcf02cSchristos 376*8dbcf02cSchristos hash_len = data->eap_method == EAP_TYPE_AKA_PRIME ? 377*8dbcf02cSchristos EAP_AKA_PRIME_CHECKCODE_LEN : EAP_AKA_CHECKCODE_LEN; 378*8dbcf02cSchristos 379*8dbcf02cSchristos if (checkcode_len != hash_len) { 380*8dbcf02cSchristos wpa_printf(MSG_DEBUG, "EAP-AKA: Checkcode from server " 381*8dbcf02cSchristos "indicates that AKA/Identity message were not " 382*8dbcf02cSchristos "used, but they were"); 383*8dbcf02cSchristos return -1; 384*8dbcf02cSchristos } 385*8dbcf02cSchristos 386*8dbcf02cSchristos /* Checkcode is SHA1/SHA256 hash over all EAP-AKA/Identity packets. */ 387*8dbcf02cSchristos addr = wpabuf_head(data->id_msgs); 388*8dbcf02cSchristos len = wpabuf_len(data->id_msgs); 389*8dbcf02cSchristos #ifdef EAP_AKA_PRIME 390*8dbcf02cSchristos if (data->eap_method == EAP_TYPE_AKA_PRIME) 391*8dbcf02cSchristos sha256_vector(1, &addr, &len, hash); 392*8dbcf02cSchristos else 393*8dbcf02cSchristos #endif /* EAP_AKA_PRIME */ 394*8dbcf02cSchristos sha1_vector(1, &addr, &len, hash); 395*8dbcf02cSchristos 396*8dbcf02cSchristos if (os_memcmp(hash, checkcode, hash_len) != 0) { 397*8dbcf02cSchristos wpa_printf(MSG_DEBUG, "EAP-AKA: Mismatch in AT_CHECKCODE"); 398*8dbcf02cSchristos return -1; 399*8dbcf02cSchristos } 400*8dbcf02cSchristos 401*8dbcf02cSchristos return 0; 402*8dbcf02cSchristos } 403*8dbcf02cSchristos 404*8dbcf02cSchristos 405*8dbcf02cSchristos static struct wpabuf * eap_aka_client_error(struct eap_aka_data *data, u8 id, 406*8dbcf02cSchristos int err) 407*8dbcf02cSchristos { 408*8dbcf02cSchristos struct eap_sim_msg *msg; 409*8dbcf02cSchristos 410*8dbcf02cSchristos eap_aka_state(data, FAILURE); 411*8dbcf02cSchristos data->num_id_req = 0; 412*8dbcf02cSchristos data->num_notification = 0; 413*8dbcf02cSchristos 414*8dbcf02cSchristos msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, data->eap_method, 415*8dbcf02cSchristos EAP_AKA_SUBTYPE_CLIENT_ERROR); 416*8dbcf02cSchristos eap_sim_msg_add(msg, EAP_SIM_AT_CLIENT_ERROR_CODE, err, NULL, 0); 417*8dbcf02cSchristos return eap_sim_msg_finish(msg, NULL, NULL, 0); 418*8dbcf02cSchristos } 419*8dbcf02cSchristos 420*8dbcf02cSchristos 421*8dbcf02cSchristos static struct wpabuf * eap_aka_authentication_reject(struct eap_aka_data *data, 422*8dbcf02cSchristos u8 id) 423*8dbcf02cSchristos { 424*8dbcf02cSchristos struct eap_sim_msg *msg; 425*8dbcf02cSchristos 426*8dbcf02cSchristos eap_aka_state(data, FAILURE); 427*8dbcf02cSchristos data->num_id_req = 0; 428*8dbcf02cSchristos data->num_notification = 0; 429*8dbcf02cSchristos 430*8dbcf02cSchristos wpa_printf(MSG_DEBUG, "Generating EAP-AKA Authentication-Reject " 431*8dbcf02cSchristos "(id=%d)", id); 432*8dbcf02cSchristos msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, data->eap_method, 433*8dbcf02cSchristos EAP_AKA_SUBTYPE_AUTHENTICATION_REJECT); 434*8dbcf02cSchristos return eap_sim_msg_finish(msg, NULL, NULL, 0); 435*8dbcf02cSchristos } 436*8dbcf02cSchristos 437*8dbcf02cSchristos 438*8dbcf02cSchristos static struct wpabuf * eap_aka_synchronization_failure( 439*8dbcf02cSchristos struct eap_aka_data *data, u8 id) 440*8dbcf02cSchristos { 441*8dbcf02cSchristos struct eap_sim_msg *msg; 442*8dbcf02cSchristos 443*8dbcf02cSchristos data->num_id_req = 0; 444*8dbcf02cSchristos data->num_notification = 0; 445*8dbcf02cSchristos 446*8dbcf02cSchristos wpa_printf(MSG_DEBUG, "Generating EAP-AKA Synchronization-Failure " 447*8dbcf02cSchristos "(id=%d)", id); 448*8dbcf02cSchristos msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, data->eap_method, 449*8dbcf02cSchristos EAP_AKA_SUBTYPE_SYNCHRONIZATION_FAILURE); 450*8dbcf02cSchristos wpa_printf(MSG_DEBUG, " AT_AUTS"); 451*8dbcf02cSchristos eap_sim_msg_add_full(msg, EAP_SIM_AT_AUTS, data->auts, 452*8dbcf02cSchristos EAP_AKA_AUTS_LEN); 453*8dbcf02cSchristos return eap_sim_msg_finish(msg, NULL, NULL, 0); 454*8dbcf02cSchristos } 455*8dbcf02cSchristos 456*8dbcf02cSchristos 457*8dbcf02cSchristos static struct wpabuf * eap_aka_response_identity(struct eap_sm *sm, 458*8dbcf02cSchristos struct eap_aka_data *data, 459*8dbcf02cSchristos u8 id, 460*8dbcf02cSchristos enum eap_sim_id_req id_req) 461*8dbcf02cSchristos { 462*8dbcf02cSchristos const u8 *identity = NULL; 463*8dbcf02cSchristos size_t identity_len = 0; 464*8dbcf02cSchristos struct eap_sim_msg *msg; 465*8dbcf02cSchristos 466*8dbcf02cSchristos data->reauth = 0; 467*8dbcf02cSchristos if (id_req == ANY_ID && data->reauth_id) { 468*8dbcf02cSchristos identity = data->reauth_id; 469*8dbcf02cSchristos identity_len = data->reauth_id_len; 470*8dbcf02cSchristos data->reauth = 1; 471*8dbcf02cSchristos } else if ((id_req == ANY_ID || id_req == FULLAUTH_ID) && 472*8dbcf02cSchristos data->pseudonym) { 473*8dbcf02cSchristos identity = data->pseudonym; 474*8dbcf02cSchristos identity_len = data->pseudonym_len; 475*8dbcf02cSchristos eap_aka_clear_identities(data, CLEAR_REAUTH_ID); 476*8dbcf02cSchristos } else if (id_req != NO_ID_REQ) { 477*8dbcf02cSchristos identity = eap_get_config_identity(sm, &identity_len); 478*8dbcf02cSchristos if (identity) { 479*8dbcf02cSchristos eap_aka_clear_identities(data, CLEAR_PSEUDONYM | 480*8dbcf02cSchristos CLEAR_REAUTH_ID); 481*8dbcf02cSchristos } 482*8dbcf02cSchristos } 483*8dbcf02cSchristos if (id_req != NO_ID_REQ) 484*8dbcf02cSchristos eap_aka_clear_identities(data, CLEAR_EAP_ID); 485*8dbcf02cSchristos 486*8dbcf02cSchristos wpa_printf(MSG_DEBUG, "Generating EAP-AKA Identity (id=%d)", id); 487*8dbcf02cSchristos msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, data->eap_method, 488*8dbcf02cSchristos EAP_AKA_SUBTYPE_IDENTITY); 489*8dbcf02cSchristos 490*8dbcf02cSchristos if (identity) { 491*8dbcf02cSchristos wpa_hexdump_ascii(MSG_DEBUG, " AT_IDENTITY", 492*8dbcf02cSchristos identity, identity_len); 493*8dbcf02cSchristos eap_sim_msg_add(msg, EAP_SIM_AT_IDENTITY, identity_len, 494*8dbcf02cSchristos identity, identity_len); 495*8dbcf02cSchristos } 496*8dbcf02cSchristos 497*8dbcf02cSchristos return eap_sim_msg_finish(msg, NULL, NULL, 0); 498*8dbcf02cSchristos } 499*8dbcf02cSchristos 500*8dbcf02cSchristos 501*8dbcf02cSchristos static struct wpabuf * eap_aka_response_challenge(struct eap_aka_data *data, 502*8dbcf02cSchristos u8 id) 503*8dbcf02cSchristos { 504*8dbcf02cSchristos struct eap_sim_msg *msg; 505*8dbcf02cSchristos 506*8dbcf02cSchristos wpa_printf(MSG_DEBUG, "Generating EAP-AKA Challenge (id=%d)", id); 507*8dbcf02cSchristos msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, data->eap_method, 508*8dbcf02cSchristos EAP_AKA_SUBTYPE_CHALLENGE); 509*8dbcf02cSchristos wpa_printf(MSG_DEBUG, " AT_RES"); 510*8dbcf02cSchristos eap_sim_msg_add(msg, EAP_SIM_AT_RES, data->res_len * 8, 511*8dbcf02cSchristos data->res, data->res_len); 512*8dbcf02cSchristos eap_aka_add_checkcode(data, msg); 513*8dbcf02cSchristos if (data->use_result_ind) { 514*8dbcf02cSchristos wpa_printf(MSG_DEBUG, " AT_RESULT_IND"); 515*8dbcf02cSchristos eap_sim_msg_add(msg, EAP_SIM_AT_RESULT_IND, 0, NULL, 0); 516*8dbcf02cSchristos } 517*8dbcf02cSchristos wpa_printf(MSG_DEBUG, " AT_MAC"); 518*8dbcf02cSchristos eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC); 519*8dbcf02cSchristos return eap_sim_msg_finish(msg, data->k_aut, (u8 *) "", 0); 520*8dbcf02cSchristos } 521*8dbcf02cSchristos 522*8dbcf02cSchristos 523*8dbcf02cSchristos static struct wpabuf * eap_aka_response_reauth(struct eap_aka_data *data, 524*8dbcf02cSchristos u8 id, int counter_too_small, 525*8dbcf02cSchristos const u8 *nonce_s) 526*8dbcf02cSchristos { 527*8dbcf02cSchristos struct eap_sim_msg *msg; 528*8dbcf02cSchristos unsigned int counter; 529*8dbcf02cSchristos 530*8dbcf02cSchristos wpa_printf(MSG_DEBUG, "Generating EAP-AKA Reauthentication (id=%d)", 531*8dbcf02cSchristos id); 532*8dbcf02cSchristos msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, data->eap_method, 533*8dbcf02cSchristos EAP_AKA_SUBTYPE_REAUTHENTICATION); 534*8dbcf02cSchristos wpa_printf(MSG_DEBUG, " AT_IV"); 535*8dbcf02cSchristos wpa_printf(MSG_DEBUG, " AT_ENCR_DATA"); 536*8dbcf02cSchristos eap_sim_msg_add_encr_start(msg, EAP_SIM_AT_IV, EAP_SIM_AT_ENCR_DATA); 537*8dbcf02cSchristos 538*8dbcf02cSchristos if (counter_too_small) { 539*8dbcf02cSchristos wpa_printf(MSG_DEBUG, " *AT_COUNTER_TOO_SMALL"); 540*8dbcf02cSchristos eap_sim_msg_add(msg, EAP_SIM_AT_COUNTER_TOO_SMALL, 0, NULL, 0); 541*8dbcf02cSchristos counter = data->counter_too_small; 542*8dbcf02cSchristos } else 543*8dbcf02cSchristos counter = data->counter; 544*8dbcf02cSchristos 545*8dbcf02cSchristos wpa_printf(MSG_DEBUG, " *AT_COUNTER %d", counter); 546*8dbcf02cSchristos eap_sim_msg_add(msg, EAP_SIM_AT_COUNTER, counter, NULL, 0); 547*8dbcf02cSchristos 548*8dbcf02cSchristos if (eap_sim_msg_add_encr_end(msg, data->k_encr, EAP_SIM_AT_PADDING)) { 549*8dbcf02cSchristos wpa_printf(MSG_WARNING, "EAP-AKA: Failed to encrypt " 550*8dbcf02cSchristos "AT_ENCR_DATA"); 551*8dbcf02cSchristos eap_sim_msg_free(msg); 552*8dbcf02cSchristos return NULL; 553*8dbcf02cSchristos } 554*8dbcf02cSchristos eap_aka_add_checkcode(data, msg); 555*8dbcf02cSchristos if (data->use_result_ind) { 556*8dbcf02cSchristos wpa_printf(MSG_DEBUG, " AT_RESULT_IND"); 557*8dbcf02cSchristos eap_sim_msg_add(msg, EAP_SIM_AT_RESULT_IND, 0, NULL, 0); 558*8dbcf02cSchristos } 559*8dbcf02cSchristos wpa_printf(MSG_DEBUG, " AT_MAC"); 560*8dbcf02cSchristos eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC); 561*8dbcf02cSchristos return eap_sim_msg_finish(msg, data->k_aut, nonce_s, 562*8dbcf02cSchristos EAP_SIM_NONCE_S_LEN); 563*8dbcf02cSchristos } 564*8dbcf02cSchristos 565*8dbcf02cSchristos 566*8dbcf02cSchristos static struct wpabuf * eap_aka_response_notification(struct eap_aka_data *data, 567*8dbcf02cSchristos u8 id, u16 notification) 568*8dbcf02cSchristos { 569*8dbcf02cSchristos struct eap_sim_msg *msg; 570*8dbcf02cSchristos u8 *k_aut = (notification & 0x4000) == 0 ? data->k_aut : NULL; 571*8dbcf02cSchristos 572*8dbcf02cSchristos wpa_printf(MSG_DEBUG, "Generating EAP-AKA Notification (id=%d)", id); 573*8dbcf02cSchristos msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, data->eap_method, 574*8dbcf02cSchristos EAP_AKA_SUBTYPE_NOTIFICATION); 575*8dbcf02cSchristos if (k_aut && data->reauth) { 576*8dbcf02cSchristos wpa_printf(MSG_DEBUG, " AT_IV"); 577*8dbcf02cSchristos wpa_printf(MSG_DEBUG, " AT_ENCR_DATA"); 578*8dbcf02cSchristos eap_sim_msg_add_encr_start(msg, EAP_SIM_AT_IV, 579*8dbcf02cSchristos EAP_SIM_AT_ENCR_DATA); 580*8dbcf02cSchristos wpa_printf(MSG_DEBUG, " *AT_COUNTER %d", data->counter); 581*8dbcf02cSchristos eap_sim_msg_add(msg, EAP_SIM_AT_COUNTER, data->counter, 582*8dbcf02cSchristos NULL, 0); 583*8dbcf02cSchristos if (eap_sim_msg_add_encr_end(msg, data->k_encr, 584*8dbcf02cSchristos EAP_SIM_AT_PADDING)) { 585*8dbcf02cSchristos wpa_printf(MSG_WARNING, "EAP-AKA: Failed to encrypt " 586*8dbcf02cSchristos "AT_ENCR_DATA"); 587*8dbcf02cSchristos eap_sim_msg_free(msg); 588*8dbcf02cSchristos return NULL; 589*8dbcf02cSchristos } 590*8dbcf02cSchristos } 591*8dbcf02cSchristos if (k_aut) { 592*8dbcf02cSchristos wpa_printf(MSG_DEBUG, " AT_MAC"); 593*8dbcf02cSchristos eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC); 594*8dbcf02cSchristos } 595*8dbcf02cSchristos return eap_sim_msg_finish(msg, k_aut, (u8 *) "", 0); 596*8dbcf02cSchristos } 597*8dbcf02cSchristos 598*8dbcf02cSchristos 599*8dbcf02cSchristos static struct wpabuf * eap_aka_process_identity(struct eap_sm *sm, 600*8dbcf02cSchristos struct eap_aka_data *data, 601*8dbcf02cSchristos u8 id, 602*8dbcf02cSchristos const struct wpabuf *reqData, 603*8dbcf02cSchristos struct eap_sim_attrs *attr) 604*8dbcf02cSchristos { 605*8dbcf02cSchristos int id_error; 606*8dbcf02cSchristos struct wpabuf *buf; 607*8dbcf02cSchristos 608*8dbcf02cSchristos wpa_printf(MSG_DEBUG, "EAP-AKA: subtype Identity"); 609*8dbcf02cSchristos 610*8dbcf02cSchristos id_error = 0; 611*8dbcf02cSchristos switch (attr->id_req) { 612*8dbcf02cSchristos case NO_ID_REQ: 613*8dbcf02cSchristos break; 614*8dbcf02cSchristos case ANY_ID: 615*8dbcf02cSchristos if (data->num_id_req > 0) 616*8dbcf02cSchristos id_error++; 617*8dbcf02cSchristos data->num_id_req++; 618*8dbcf02cSchristos break; 619*8dbcf02cSchristos case FULLAUTH_ID: 620*8dbcf02cSchristos if (data->num_id_req > 1) 621*8dbcf02cSchristos id_error++; 622*8dbcf02cSchristos data->num_id_req++; 623*8dbcf02cSchristos break; 624*8dbcf02cSchristos case PERMANENT_ID: 625*8dbcf02cSchristos if (data->num_id_req > 2) 626*8dbcf02cSchristos id_error++; 627*8dbcf02cSchristos data->num_id_req++; 628*8dbcf02cSchristos break; 629*8dbcf02cSchristos } 630*8dbcf02cSchristos if (id_error) { 631*8dbcf02cSchristos wpa_printf(MSG_INFO, "EAP-AKA: Too many ID requests " 632*8dbcf02cSchristos "used within one authentication"); 633*8dbcf02cSchristos return eap_aka_client_error(data, id, 634*8dbcf02cSchristos EAP_AKA_UNABLE_TO_PROCESS_PACKET); 635*8dbcf02cSchristos } 636*8dbcf02cSchristos 637*8dbcf02cSchristos buf = eap_aka_response_identity(sm, data, id, attr->id_req); 638*8dbcf02cSchristos 639*8dbcf02cSchristos if (data->prev_id != id) { 640*8dbcf02cSchristos eap_aka_add_id_msg(data, reqData); 641*8dbcf02cSchristos eap_aka_add_id_msg(data, buf); 642*8dbcf02cSchristos data->prev_id = id; 643*8dbcf02cSchristos } 644*8dbcf02cSchristos 645*8dbcf02cSchristos return buf; 646*8dbcf02cSchristos } 647*8dbcf02cSchristos 648*8dbcf02cSchristos 649*8dbcf02cSchristos static int eap_aka_verify_mac(struct eap_aka_data *data, 650*8dbcf02cSchristos const struct wpabuf *req, 651*8dbcf02cSchristos const u8 *mac, const u8 *extra, 652*8dbcf02cSchristos size_t extra_len) 653*8dbcf02cSchristos { 654*8dbcf02cSchristos if (data->eap_method == EAP_TYPE_AKA_PRIME) 655*8dbcf02cSchristos return eap_sim_verify_mac_sha256(data->k_aut, req, mac, extra, 656*8dbcf02cSchristos extra_len); 657*8dbcf02cSchristos return eap_sim_verify_mac(data->k_aut, req, mac, extra, extra_len); 658*8dbcf02cSchristos } 659*8dbcf02cSchristos 660*8dbcf02cSchristos 661*8dbcf02cSchristos #ifdef EAP_AKA_PRIME 662*8dbcf02cSchristos static struct wpabuf * eap_aka_prime_kdf_select(struct eap_aka_data *data, 663*8dbcf02cSchristos u8 id, u16 kdf) 664*8dbcf02cSchristos { 665*8dbcf02cSchristos struct eap_sim_msg *msg; 666*8dbcf02cSchristos 667*8dbcf02cSchristos data->kdf_negotiation = 1; 668*8dbcf02cSchristos data->kdf = kdf; 669*8dbcf02cSchristos wpa_printf(MSG_DEBUG, "Generating EAP-AKA Challenge (id=%d) (KDF " 670*8dbcf02cSchristos "select)", id); 671*8dbcf02cSchristos msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, data->eap_method, 672*8dbcf02cSchristos EAP_AKA_SUBTYPE_CHALLENGE); 673*8dbcf02cSchristos wpa_printf(MSG_DEBUG, " AT_KDF"); 674*8dbcf02cSchristos eap_sim_msg_add(msg, EAP_SIM_AT_KDF, kdf, NULL, 0); 675*8dbcf02cSchristos return eap_sim_msg_finish(msg, NULL, NULL, 0); 676*8dbcf02cSchristos } 677*8dbcf02cSchristos 678*8dbcf02cSchristos 679*8dbcf02cSchristos static struct wpabuf * eap_aka_prime_kdf_neg(struct eap_aka_data *data, 680*8dbcf02cSchristos u8 id, struct eap_sim_attrs *attr) 681*8dbcf02cSchristos { 682*8dbcf02cSchristos size_t i; 683*8dbcf02cSchristos 684*8dbcf02cSchristos for (i = 0; i < attr->kdf_count; i++) { 685*8dbcf02cSchristos if (attr->kdf[i] == EAP_AKA_PRIME_KDF) 686*8dbcf02cSchristos return eap_aka_prime_kdf_select(data, id, 687*8dbcf02cSchristos EAP_AKA_PRIME_KDF); 688*8dbcf02cSchristos } 689*8dbcf02cSchristos 690*8dbcf02cSchristos /* No matching KDF found - fail authentication as if AUTN had been 691*8dbcf02cSchristos * incorrect */ 692*8dbcf02cSchristos return eap_aka_authentication_reject(data, id); 693*8dbcf02cSchristos } 694*8dbcf02cSchristos 695*8dbcf02cSchristos 696*8dbcf02cSchristos static int eap_aka_prime_kdf_valid(struct eap_aka_data *data, 697*8dbcf02cSchristos struct eap_sim_attrs *attr) 698*8dbcf02cSchristos { 699*8dbcf02cSchristos size_t i, j; 700*8dbcf02cSchristos 701*8dbcf02cSchristos if (attr->kdf_count == 0) 702*8dbcf02cSchristos return 0; 703*8dbcf02cSchristos 704*8dbcf02cSchristos /* The only allowed (and required) duplication of a KDF is the addition 705*8dbcf02cSchristos * of the selected KDF into the beginning of the list. */ 706*8dbcf02cSchristos 707*8dbcf02cSchristos if (data->kdf_negotiation) { 708*8dbcf02cSchristos if (attr->kdf[0] != data->kdf) { 709*8dbcf02cSchristos wpa_printf(MSG_WARNING, "EAP-AKA': The server did not " 710*8dbcf02cSchristos "accept the selected KDF"); 711*8dbcf02cSchristos return 0; 712*8dbcf02cSchristos } 713*8dbcf02cSchristos 714*8dbcf02cSchristos for (i = 1; i < attr->kdf_count; i++) { 715*8dbcf02cSchristos if (attr->kdf[i] == data->kdf) 716*8dbcf02cSchristos break; 717*8dbcf02cSchristos } 718*8dbcf02cSchristos if (i == attr->kdf_count && 719*8dbcf02cSchristos attr->kdf_count < EAP_AKA_PRIME_KDF_MAX) { 720*8dbcf02cSchristos wpa_printf(MSG_WARNING, "EAP-AKA': The server did not " 721*8dbcf02cSchristos "duplicate the selected KDF"); 722*8dbcf02cSchristos return 0; 723*8dbcf02cSchristos } 724*8dbcf02cSchristos 725*8dbcf02cSchristos /* TODO: should check that the list is identical to the one 726*8dbcf02cSchristos * used in the previous Challenge message apart from the added 727*8dbcf02cSchristos * entry in the beginning. */ 728*8dbcf02cSchristos } 729*8dbcf02cSchristos 730*8dbcf02cSchristos for (i = data->kdf ? 1 : 0; i < attr->kdf_count; i++) { 731*8dbcf02cSchristos for (j = i + 1; j < attr->kdf_count; j++) { 732*8dbcf02cSchristos if (attr->kdf[i] == attr->kdf[j]) { 733*8dbcf02cSchristos wpa_printf(MSG_WARNING, "EAP-AKA': The server " 734*8dbcf02cSchristos "included a duplicated KDF"); 735*8dbcf02cSchristos return 0; 736*8dbcf02cSchristos } 737*8dbcf02cSchristos } 738*8dbcf02cSchristos } 739*8dbcf02cSchristos 740*8dbcf02cSchristos return 1; 741*8dbcf02cSchristos } 742*8dbcf02cSchristos #endif /* EAP_AKA_PRIME */ 743*8dbcf02cSchristos 744*8dbcf02cSchristos 745*8dbcf02cSchristos static struct wpabuf * eap_aka_process_challenge(struct eap_sm *sm, 746*8dbcf02cSchristos struct eap_aka_data *data, 747*8dbcf02cSchristos u8 id, 748*8dbcf02cSchristos const struct wpabuf *reqData, 749*8dbcf02cSchristos struct eap_sim_attrs *attr) 750*8dbcf02cSchristos { 751*8dbcf02cSchristos const u8 *identity; 752*8dbcf02cSchristos size_t identity_len; 753*8dbcf02cSchristos int res; 754*8dbcf02cSchristos struct eap_sim_attrs eattr; 755*8dbcf02cSchristos 756*8dbcf02cSchristos wpa_printf(MSG_DEBUG, "EAP-AKA: subtype Challenge"); 757*8dbcf02cSchristos 758*8dbcf02cSchristos if (attr->checkcode && 759*8dbcf02cSchristos eap_aka_verify_checkcode(data, attr->checkcode, 760*8dbcf02cSchristos attr->checkcode_len)) { 761*8dbcf02cSchristos wpa_printf(MSG_WARNING, "EAP-AKA: Invalid AT_CHECKCODE in the " 762*8dbcf02cSchristos "message"); 763*8dbcf02cSchristos return eap_aka_client_error(data, id, 764*8dbcf02cSchristos EAP_AKA_UNABLE_TO_PROCESS_PACKET); 765*8dbcf02cSchristos } 766*8dbcf02cSchristos 767*8dbcf02cSchristos #ifdef EAP_AKA_PRIME 768*8dbcf02cSchristos if (data->eap_method == EAP_TYPE_AKA_PRIME) { 769*8dbcf02cSchristos if (!attr->kdf_input || attr->kdf_input_len == 0) { 770*8dbcf02cSchristos wpa_printf(MSG_WARNING, "EAP-AKA': Challenge message " 771*8dbcf02cSchristos "did not include non-empty AT_KDF_INPUT"); 772*8dbcf02cSchristos /* Fail authentication as if AUTN had been incorrect */ 773*8dbcf02cSchristos return eap_aka_authentication_reject(data, id); 774*8dbcf02cSchristos } 775*8dbcf02cSchristos os_free(data->network_name); 776*8dbcf02cSchristos data->network_name = os_malloc(attr->kdf_input_len); 777*8dbcf02cSchristos if (data->network_name == NULL) { 778*8dbcf02cSchristos wpa_printf(MSG_WARNING, "EAP-AKA': No memory for " 779*8dbcf02cSchristos "storing Network Name"); 780*8dbcf02cSchristos return eap_aka_authentication_reject(data, id); 781*8dbcf02cSchristos } 782*8dbcf02cSchristos os_memcpy(data->network_name, attr->kdf_input, 783*8dbcf02cSchristos attr->kdf_input_len); 784*8dbcf02cSchristos data->network_name_len = attr->kdf_input_len; 785*8dbcf02cSchristos wpa_hexdump_ascii(MSG_DEBUG, "EAP-AKA': Network Name " 786*8dbcf02cSchristos "(AT_KDF_INPUT)", 787*8dbcf02cSchristos data->network_name, data->network_name_len); 788*8dbcf02cSchristos /* TODO: check Network Name per 3GPP.33.402 */ 789*8dbcf02cSchristos 790*8dbcf02cSchristos if (!eap_aka_prime_kdf_valid(data, attr)) 791*8dbcf02cSchristos return eap_aka_authentication_reject(data, id); 792*8dbcf02cSchristos 793*8dbcf02cSchristos if (attr->kdf[0] != EAP_AKA_PRIME_KDF) 794*8dbcf02cSchristos return eap_aka_prime_kdf_neg(data, id, attr); 795*8dbcf02cSchristos 796*8dbcf02cSchristos data->kdf = EAP_AKA_PRIME_KDF; 797*8dbcf02cSchristos wpa_printf(MSG_DEBUG, "EAP-AKA': KDF %d selected", data->kdf); 798*8dbcf02cSchristos } 799*8dbcf02cSchristos 800*8dbcf02cSchristos if (data->eap_method == EAP_TYPE_AKA && attr->bidding) { 801*8dbcf02cSchristos u16 flags = WPA_GET_BE16(attr->bidding); 802*8dbcf02cSchristos if ((flags & EAP_AKA_BIDDING_FLAG_D) && 803*8dbcf02cSchristos eap_allowed_method(sm, EAP_VENDOR_IETF, 804*8dbcf02cSchristos EAP_TYPE_AKA_PRIME)) { 805*8dbcf02cSchristos wpa_printf(MSG_WARNING, "EAP-AKA: Bidding down from " 806*8dbcf02cSchristos "AKA' to AKA detected"); 807*8dbcf02cSchristos /* Fail authentication as if AUTN had been incorrect */ 808*8dbcf02cSchristos return eap_aka_authentication_reject(data, id); 809*8dbcf02cSchristos } 810*8dbcf02cSchristos } 811*8dbcf02cSchristos #endif /* EAP_AKA_PRIME */ 812*8dbcf02cSchristos 813*8dbcf02cSchristos data->reauth = 0; 814*8dbcf02cSchristos if (!attr->mac || !attr->rand || !attr->autn) { 815*8dbcf02cSchristos wpa_printf(MSG_WARNING, "EAP-AKA: Challenge message " 816*8dbcf02cSchristos "did not include%s%s%s", 817*8dbcf02cSchristos !attr->mac ? " AT_MAC" : "", 818*8dbcf02cSchristos !attr->rand ? " AT_RAND" : "", 819*8dbcf02cSchristos !attr->autn ? " AT_AUTN" : ""); 820*8dbcf02cSchristos return eap_aka_client_error(data, id, 821*8dbcf02cSchristos EAP_AKA_UNABLE_TO_PROCESS_PACKET); 822*8dbcf02cSchristos } 823*8dbcf02cSchristos os_memcpy(data->rand, attr->rand, EAP_AKA_RAND_LEN); 824*8dbcf02cSchristos os_memcpy(data->autn, attr->autn, EAP_AKA_AUTN_LEN); 825*8dbcf02cSchristos 826*8dbcf02cSchristos res = eap_aka_umts_auth(sm, data); 827*8dbcf02cSchristos if (res == -1) { 828*8dbcf02cSchristos wpa_printf(MSG_WARNING, "EAP-AKA: UMTS authentication " 829*8dbcf02cSchristos "failed (AUTN)"); 830*8dbcf02cSchristos return eap_aka_authentication_reject(data, id); 831*8dbcf02cSchristos } else if (res == -2) { 832*8dbcf02cSchristos wpa_printf(MSG_WARNING, "EAP-AKA: UMTS authentication " 833*8dbcf02cSchristos "failed (AUTN seq# -> AUTS)"); 834*8dbcf02cSchristos return eap_aka_synchronization_failure(data, id); 835*8dbcf02cSchristos } else if (res) { 836*8dbcf02cSchristos wpa_printf(MSG_WARNING, "EAP-AKA: UMTS authentication failed"); 837*8dbcf02cSchristos return eap_aka_client_error(data, id, 838*8dbcf02cSchristos EAP_AKA_UNABLE_TO_PROCESS_PACKET); 839*8dbcf02cSchristos } 840*8dbcf02cSchristos #ifdef EAP_AKA_PRIME 841*8dbcf02cSchristos if (data->eap_method == EAP_TYPE_AKA_PRIME) { 842*8dbcf02cSchristos /* Note: AUTN = (SQN ^ AK) || AMF || MAC which gives us the 843*8dbcf02cSchristos * needed 6-octet SQN ^ AK for CK',IK' derivation */ 844*8dbcf02cSchristos u16 amf = WPA_GET_BE16(data->autn + 6); 845*8dbcf02cSchristos if (!(amf & 0x8000)) { 846*8dbcf02cSchristos wpa_printf(MSG_WARNING, "EAP-AKA': AMF separation bit " 847*8dbcf02cSchristos "not set (AMF=0x%4x)", amf); 848*8dbcf02cSchristos return eap_aka_authentication_reject(data, id); 849*8dbcf02cSchristos } 850*8dbcf02cSchristos eap_aka_prime_derive_ck_ik_prime(data->ck, data->ik, 851*8dbcf02cSchristos data->autn, 852*8dbcf02cSchristos data->network_name, 853*8dbcf02cSchristos data->network_name_len); 854*8dbcf02cSchristos } 855*8dbcf02cSchristos #endif /* EAP_AKA_PRIME */ 856*8dbcf02cSchristos if (data->last_eap_identity) { 857*8dbcf02cSchristos identity = data->last_eap_identity; 858*8dbcf02cSchristos identity_len = data->last_eap_identity_len; 859*8dbcf02cSchristos } else if (data->pseudonym) { 860*8dbcf02cSchristos identity = data->pseudonym; 861*8dbcf02cSchristos identity_len = data->pseudonym_len; 862*8dbcf02cSchristos } else 863*8dbcf02cSchristos identity = eap_get_config_identity(sm, &identity_len); 864*8dbcf02cSchristos wpa_hexdump_ascii(MSG_DEBUG, "EAP-AKA: Selected identity for MK " 865*8dbcf02cSchristos "derivation", identity, identity_len); 866*8dbcf02cSchristos if (data->eap_method == EAP_TYPE_AKA_PRIME) { 867*8dbcf02cSchristos eap_aka_prime_derive_keys(identity, identity_len, data->ik, 868*8dbcf02cSchristos data->ck, data->k_encr, data->k_aut, 869*8dbcf02cSchristos data->k_re, data->msk, data->emsk); 870*8dbcf02cSchristos } else { 871*8dbcf02cSchristos eap_aka_derive_mk(identity, identity_len, data->ik, data->ck, 872*8dbcf02cSchristos data->mk); 873*8dbcf02cSchristos eap_sim_derive_keys(data->mk, data->k_encr, data->k_aut, 874*8dbcf02cSchristos data->msk, data->emsk); 875*8dbcf02cSchristos } 876*8dbcf02cSchristos if (eap_aka_verify_mac(data, reqData, attr->mac, (u8 *) "", 0)) { 877*8dbcf02cSchristos wpa_printf(MSG_WARNING, "EAP-AKA: Challenge message " 878*8dbcf02cSchristos "used invalid AT_MAC"); 879*8dbcf02cSchristos return eap_aka_client_error(data, id, 880*8dbcf02cSchristos EAP_AKA_UNABLE_TO_PROCESS_PACKET); 881*8dbcf02cSchristos } 882*8dbcf02cSchristos 883*8dbcf02cSchristos /* Old reauthentication and pseudonym identities must not be used 884*8dbcf02cSchristos * anymore. In other words, if no new identities are received, full 885*8dbcf02cSchristos * authentication will be used on next reauthentication. */ 886*8dbcf02cSchristos eap_aka_clear_identities(data, CLEAR_PSEUDONYM | CLEAR_REAUTH_ID | 887*8dbcf02cSchristos CLEAR_EAP_ID); 888*8dbcf02cSchristos 889*8dbcf02cSchristos if (attr->encr_data) { 890*8dbcf02cSchristos u8 *decrypted; 891*8dbcf02cSchristos decrypted = eap_sim_parse_encr(data->k_encr, attr->encr_data, 892*8dbcf02cSchristos attr->encr_data_len, attr->iv, 893*8dbcf02cSchristos &eattr, 0); 894*8dbcf02cSchristos if (decrypted == NULL) { 895*8dbcf02cSchristos return eap_aka_client_error( 896*8dbcf02cSchristos data, id, EAP_AKA_UNABLE_TO_PROCESS_PACKET); 897*8dbcf02cSchristos } 898*8dbcf02cSchristos eap_aka_learn_ids(data, &eattr); 899*8dbcf02cSchristos os_free(decrypted); 900*8dbcf02cSchristos } 901*8dbcf02cSchristos 902*8dbcf02cSchristos if (data->result_ind && attr->result_ind) 903*8dbcf02cSchristos data->use_result_ind = 1; 904*8dbcf02cSchristos 905*8dbcf02cSchristos if (data->state != FAILURE && data->state != RESULT_FAILURE) { 906*8dbcf02cSchristos eap_aka_state(data, data->use_result_ind ? 907*8dbcf02cSchristos RESULT_SUCCESS : SUCCESS); 908*8dbcf02cSchristos } 909*8dbcf02cSchristos 910*8dbcf02cSchristos data->num_id_req = 0; 911*8dbcf02cSchristos data->num_notification = 0; 912*8dbcf02cSchristos /* RFC 4187 specifies that counter is initialized to one after 913*8dbcf02cSchristos * fullauth, but initializing it to zero makes it easier to implement 914*8dbcf02cSchristos * reauth verification. */ 915*8dbcf02cSchristos data->counter = 0; 916*8dbcf02cSchristos return eap_aka_response_challenge(data, id); 917*8dbcf02cSchristos } 918*8dbcf02cSchristos 919*8dbcf02cSchristos 920*8dbcf02cSchristos static int eap_aka_process_notification_reauth(struct eap_aka_data *data, 921*8dbcf02cSchristos struct eap_sim_attrs *attr) 922*8dbcf02cSchristos { 923*8dbcf02cSchristos struct eap_sim_attrs eattr; 924*8dbcf02cSchristos u8 *decrypted; 925*8dbcf02cSchristos 926*8dbcf02cSchristos if (attr->encr_data == NULL || attr->iv == NULL) { 927*8dbcf02cSchristos wpa_printf(MSG_WARNING, "EAP-AKA: Notification message after " 928*8dbcf02cSchristos "reauth did not include encrypted data"); 929*8dbcf02cSchristos return -1; 930*8dbcf02cSchristos } 931*8dbcf02cSchristos 932*8dbcf02cSchristos decrypted = eap_sim_parse_encr(data->k_encr, attr->encr_data, 933*8dbcf02cSchristos attr->encr_data_len, attr->iv, &eattr, 934*8dbcf02cSchristos 0); 935*8dbcf02cSchristos if (decrypted == NULL) { 936*8dbcf02cSchristos wpa_printf(MSG_WARNING, "EAP-AKA: Failed to parse encrypted " 937*8dbcf02cSchristos "data from notification message"); 938*8dbcf02cSchristos return -1; 939*8dbcf02cSchristos } 940*8dbcf02cSchristos 941*8dbcf02cSchristos if (eattr.counter < 0 || (size_t) eattr.counter != data->counter) { 942*8dbcf02cSchristos wpa_printf(MSG_WARNING, "EAP-AKA: Counter in notification " 943*8dbcf02cSchristos "message does not match with counter in reauth " 944*8dbcf02cSchristos "message"); 945*8dbcf02cSchristos os_free(decrypted); 946*8dbcf02cSchristos return -1; 947*8dbcf02cSchristos } 948*8dbcf02cSchristos 949*8dbcf02cSchristos os_free(decrypted); 950*8dbcf02cSchristos return 0; 951*8dbcf02cSchristos } 952*8dbcf02cSchristos 953*8dbcf02cSchristos 954*8dbcf02cSchristos static int eap_aka_process_notification_auth(struct eap_aka_data *data, 955*8dbcf02cSchristos const struct wpabuf *reqData, 956*8dbcf02cSchristos struct eap_sim_attrs *attr) 957*8dbcf02cSchristos { 958*8dbcf02cSchristos if (attr->mac == NULL) { 959*8dbcf02cSchristos wpa_printf(MSG_INFO, "EAP-AKA: no AT_MAC in after_auth " 960*8dbcf02cSchristos "Notification message"); 961*8dbcf02cSchristos return -1; 962*8dbcf02cSchristos } 963*8dbcf02cSchristos 964*8dbcf02cSchristos if (eap_aka_verify_mac(data, reqData, attr->mac, (u8 *) "", 0)) { 965*8dbcf02cSchristos wpa_printf(MSG_WARNING, "EAP-AKA: Notification message " 966*8dbcf02cSchristos "used invalid AT_MAC"); 967*8dbcf02cSchristos return -1; 968*8dbcf02cSchristos } 969*8dbcf02cSchristos 970*8dbcf02cSchristos if (data->reauth && 971*8dbcf02cSchristos eap_aka_process_notification_reauth(data, attr)) { 972*8dbcf02cSchristos wpa_printf(MSG_WARNING, "EAP-AKA: Invalid notification " 973*8dbcf02cSchristos "message after reauth"); 974*8dbcf02cSchristos return -1; 975*8dbcf02cSchristos } 976*8dbcf02cSchristos 977*8dbcf02cSchristos return 0; 978*8dbcf02cSchristos } 979*8dbcf02cSchristos 980*8dbcf02cSchristos 981*8dbcf02cSchristos static struct wpabuf * eap_aka_process_notification( 982*8dbcf02cSchristos struct eap_sm *sm, struct eap_aka_data *data, u8 id, 983*8dbcf02cSchristos const struct wpabuf *reqData, struct eap_sim_attrs *attr) 984*8dbcf02cSchristos { 985*8dbcf02cSchristos wpa_printf(MSG_DEBUG, "EAP-AKA: subtype Notification"); 986*8dbcf02cSchristos if (data->num_notification > 0) { 987*8dbcf02cSchristos wpa_printf(MSG_INFO, "EAP-AKA: too many notification " 988*8dbcf02cSchristos "rounds (only one allowed)"); 989*8dbcf02cSchristos return eap_aka_client_error(data, id, 990*8dbcf02cSchristos EAP_AKA_UNABLE_TO_PROCESS_PACKET); 991*8dbcf02cSchristos } 992*8dbcf02cSchristos data->num_notification++; 993*8dbcf02cSchristos if (attr->notification == -1) { 994*8dbcf02cSchristos wpa_printf(MSG_INFO, "EAP-AKA: no AT_NOTIFICATION in " 995*8dbcf02cSchristos "Notification message"); 996*8dbcf02cSchristos return eap_aka_client_error(data, id, 997*8dbcf02cSchristos EAP_AKA_UNABLE_TO_PROCESS_PACKET); 998*8dbcf02cSchristos } 999*8dbcf02cSchristos 1000*8dbcf02cSchristos if ((attr->notification & 0x4000) == 0 && 1001*8dbcf02cSchristos eap_aka_process_notification_auth(data, reqData, attr)) { 1002*8dbcf02cSchristos return eap_aka_client_error(data, id, 1003*8dbcf02cSchristos EAP_AKA_UNABLE_TO_PROCESS_PACKET); 1004*8dbcf02cSchristos } 1005*8dbcf02cSchristos 1006*8dbcf02cSchristos eap_sim_report_notification(sm->msg_ctx, attr->notification, 1); 1007*8dbcf02cSchristos if (attr->notification >= 0 && attr->notification < 32768) { 1008*8dbcf02cSchristos eap_aka_state(data, FAILURE); 1009*8dbcf02cSchristos } else if (attr->notification == EAP_SIM_SUCCESS && 1010*8dbcf02cSchristos data->state == RESULT_SUCCESS) 1011*8dbcf02cSchristos eap_aka_state(data, SUCCESS); 1012*8dbcf02cSchristos return eap_aka_response_notification(data, id, attr->notification); 1013*8dbcf02cSchristos } 1014*8dbcf02cSchristos 1015*8dbcf02cSchristos 1016*8dbcf02cSchristos static struct wpabuf * eap_aka_process_reauthentication( 1017*8dbcf02cSchristos struct eap_sm *sm, struct eap_aka_data *data, u8 id, 1018*8dbcf02cSchristos const struct wpabuf *reqData, struct eap_sim_attrs *attr) 1019*8dbcf02cSchristos { 1020*8dbcf02cSchristos struct eap_sim_attrs eattr; 1021*8dbcf02cSchristos u8 *decrypted; 1022*8dbcf02cSchristos 1023*8dbcf02cSchristos wpa_printf(MSG_DEBUG, "EAP-AKA: subtype Reauthentication"); 1024*8dbcf02cSchristos 1025*8dbcf02cSchristos if (attr->checkcode && 1026*8dbcf02cSchristos eap_aka_verify_checkcode(data, attr->checkcode, 1027*8dbcf02cSchristos attr->checkcode_len)) { 1028*8dbcf02cSchristos wpa_printf(MSG_WARNING, "EAP-AKA: Invalid AT_CHECKCODE in the " 1029*8dbcf02cSchristos "message"); 1030*8dbcf02cSchristos return eap_aka_client_error(data, id, 1031*8dbcf02cSchristos EAP_AKA_UNABLE_TO_PROCESS_PACKET); 1032*8dbcf02cSchristos } 1033*8dbcf02cSchristos 1034*8dbcf02cSchristos if (data->reauth_id == NULL) { 1035*8dbcf02cSchristos wpa_printf(MSG_WARNING, "EAP-AKA: Server is trying " 1036*8dbcf02cSchristos "reauthentication, but no reauth_id available"); 1037*8dbcf02cSchristos return eap_aka_client_error(data, id, 1038*8dbcf02cSchristos EAP_AKA_UNABLE_TO_PROCESS_PACKET); 1039*8dbcf02cSchristos } 1040*8dbcf02cSchristos 1041*8dbcf02cSchristos data->reauth = 1; 1042*8dbcf02cSchristos if (eap_aka_verify_mac(data, reqData, attr->mac, (u8 *) "", 0)) { 1043*8dbcf02cSchristos wpa_printf(MSG_WARNING, "EAP-AKA: Reauthentication " 1044*8dbcf02cSchristos "did not have valid AT_MAC"); 1045*8dbcf02cSchristos return eap_aka_client_error(data, id, 1046*8dbcf02cSchristos EAP_AKA_UNABLE_TO_PROCESS_PACKET); 1047*8dbcf02cSchristos } 1048*8dbcf02cSchristos 1049*8dbcf02cSchristos if (attr->encr_data == NULL || attr->iv == NULL) { 1050*8dbcf02cSchristos wpa_printf(MSG_WARNING, "EAP-AKA: Reauthentication " 1051*8dbcf02cSchristos "message did not include encrypted data"); 1052*8dbcf02cSchristos return eap_aka_client_error(data, id, 1053*8dbcf02cSchristos EAP_AKA_UNABLE_TO_PROCESS_PACKET); 1054*8dbcf02cSchristos } 1055*8dbcf02cSchristos 1056*8dbcf02cSchristos decrypted = eap_sim_parse_encr(data->k_encr, attr->encr_data, 1057*8dbcf02cSchristos attr->encr_data_len, attr->iv, &eattr, 1058*8dbcf02cSchristos 0); 1059*8dbcf02cSchristos if (decrypted == NULL) { 1060*8dbcf02cSchristos wpa_printf(MSG_WARNING, "EAP-AKA: Failed to parse encrypted " 1061*8dbcf02cSchristos "data from reauthentication message"); 1062*8dbcf02cSchristos return eap_aka_client_error(data, id, 1063*8dbcf02cSchristos EAP_AKA_UNABLE_TO_PROCESS_PACKET); 1064*8dbcf02cSchristos } 1065*8dbcf02cSchristos 1066*8dbcf02cSchristos if (eattr.nonce_s == NULL || eattr.counter < 0) { 1067*8dbcf02cSchristos wpa_printf(MSG_INFO, "EAP-AKA: (encr) No%s%s in reauth packet", 1068*8dbcf02cSchristos !eattr.nonce_s ? " AT_NONCE_S" : "", 1069*8dbcf02cSchristos eattr.counter < 0 ? " AT_COUNTER" : ""); 1070*8dbcf02cSchristos os_free(decrypted); 1071*8dbcf02cSchristos return eap_aka_client_error(data, id, 1072*8dbcf02cSchristos EAP_AKA_UNABLE_TO_PROCESS_PACKET); 1073*8dbcf02cSchristos } 1074*8dbcf02cSchristos 1075*8dbcf02cSchristos if (eattr.counter < 0 || (size_t) eattr.counter <= data->counter) { 1076*8dbcf02cSchristos struct wpabuf *res; 1077*8dbcf02cSchristos wpa_printf(MSG_INFO, "EAP-AKA: (encr) Invalid counter " 1078*8dbcf02cSchristos "(%d <= %d)", eattr.counter, data->counter); 1079*8dbcf02cSchristos data->counter_too_small = eattr.counter; 1080*8dbcf02cSchristos 1081*8dbcf02cSchristos /* Reply using Re-auth w/ AT_COUNTER_TOO_SMALL. The current 1082*8dbcf02cSchristos * reauth_id must not be used to start a new reauthentication. 1083*8dbcf02cSchristos * However, since it was used in the last EAP-Response-Identity 1084*8dbcf02cSchristos * packet, it has to saved for the following fullauth to be 1085*8dbcf02cSchristos * used in MK derivation. */ 1086*8dbcf02cSchristos os_free(data->last_eap_identity); 1087*8dbcf02cSchristos data->last_eap_identity = data->reauth_id; 1088*8dbcf02cSchristos data->last_eap_identity_len = data->reauth_id_len; 1089*8dbcf02cSchristos data->reauth_id = NULL; 1090*8dbcf02cSchristos data->reauth_id_len = 0; 1091*8dbcf02cSchristos 1092*8dbcf02cSchristos res = eap_aka_response_reauth(data, id, 1, eattr.nonce_s); 1093*8dbcf02cSchristos os_free(decrypted); 1094*8dbcf02cSchristos 1095*8dbcf02cSchristos return res; 1096*8dbcf02cSchristos } 1097*8dbcf02cSchristos data->counter = eattr.counter; 1098*8dbcf02cSchristos 1099*8dbcf02cSchristos os_memcpy(data->nonce_s, eattr.nonce_s, EAP_SIM_NONCE_S_LEN); 1100*8dbcf02cSchristos wpa_hexdump(MSG_DEBUG, "EAP-AKA: (encr) AT_NONCE_S", 1101*8dbcf02cSchristos data->nonce_s, EAP_SIM_NONCE_S_LEN); 1102*8dbcf02cSchristos 1103*8dbcf02cSchristos if (data->eap_method == EAP_TYPE_AKA_PRIME) { 1104*8dbcf02cSchristos eap_aka_prime_derive_keys_reauth(data->k_re, data->counter, 1105*8dbcf02cSchristos data->reauth_id, 1106*8dbcf02cSchristos data->reauth_id_len, 1107*8dbcf02cSchristos data->nonce_s, 1108*8dbcf02cSchristos data->msk, data->emsk); 1109*8dbcf02cSchristos } else { 1110*8dbcf02cSchristos eap_sim_derive_keys_reauth(data->counter, data->reauth_id, 1111*8dbcf02cSchristos data->reauth_id_len, 1112*8dbcf02cSchristos data->nonce_s, data->mk, 1113*8dbcf02cSchristos data->msk, data->emsk); 1114*8dbcf02cSchristos } 1115*8dbcf02cSchristos eap_aka_clear_identities(data, CLEAR_REAUTH_ID | CLEAR_EAP_ID); 1116*8dbcf02cSchristos eap_aka_learn_ids(data, &eattr); 1117*8dbcf02cSchristos 1118*8dbcf02cSchristos if (data->result_ind && attr->result_ind) 1119*8dbcf02cSchristos data->use_result_ind = 1; 1120*8dbcf02cSchristos 1121*8dbcf02cSchristos if (data->state != FAILURE && data->state != RESULT_FAILURE) { 1122*8dbcf02cSchristos eap_aka_state(data, data->use_result_ind ? 1123*8dbcf02cSchristos RESULT_SUCCESS : SUCCESS); 1124*8dbcf02cSchristos } 1125*8dbcf02cSchristos 1126*8dbcf02cSchristos data->num_id_req = 0; 1127*8dbcf02cSchristos data->num_notification = 0; 1128*8dbcf02cSchristos if (data->counter > EAP_AKA_MAX_FAST_REAUTHS) { 1129*8dbcf02cSchristos wpa_printf(MSG_DEBUG, "EAP-AKA: Maximum number of " 1130*8dbcf02cSchristos "fast reauths performed - force fullauth"); 1131*8dbcf02cSchristos eap_aka_clear_identities(data, CLEAR_REAUTH_ID | CLEAR_EAP_ID); 1132*8dbcf02cSchristos } 1133*8dbcf02cSchristos os_free(decrypted); 1134*8dbcf02cSchristos return eap_aka_response_reauth(data, id, 0, data->nonce_s); 1135*8dbcf02cSchristos } 1136*8dbcf02cSchristos 1137*8dbcf02cSchristos 1138*8dbcf02cSchristos static struct wpabuf * eap_aka_process(struct eap_sm *sm, void *priv, 1139*8dbcf02cSchristos struct eap_method_ret *ret, 1140*8dbcf02cSchristos const struct wpabuf *reqData) 1141*8dbcf02cSchristos { 1142*8dbcf02cSchristos struct eap_aka_data *data = priv; 1143*8dbcf02cSchristos const struct eap_hdr *req; 1144*8dbcf02cSchristos u8 subtype, id; 1145*8dbcf02cSchristos struct wpabuf *res; 1146*8dbcf02cSchristos const u8 *pos; 1147*8dbcf02cSchristos struct eap_sim_attrs attr; 1148*8dbcf02cSchristos size_t len; 1149*8dbcf02cSchristos 1150*8dbcf02cSchristos wpa_hexdump_buf(MSG_DEBUG, "EAP-AKA: EAP data", reqData); 1151*8dbcf02cSchristos if (eap_get_config_identity(sm, &len) == NULL) { 1152*8dbcf02cSchristos wpa_printf(MSG_INFO, "EAP-AKA: Identity not configured"); 1153*8dbcf02cSchristos eap_sm_request_identity(sm); 1154*8dbcf02cSchristos ret->ignore = TRUE; 1155*8dbcf02cSchristos return NULL; 1156*8dbcf02cSchristos } 1157*8dbcf02cSchristos 1158*8dbcf02cSchristos pos = eap_hdr_validate(EAP_VENDOR_IETF, data->eap_method, reqData, 1159*8dbcf02cSchristos &len); 1160*8dbcf02cSchristos if (pos == NULL || len < 1) { 1161*8dbcf02cSchristos ret->ignore = TRUE; 1162*8dbcf02cSchristos return NULL; 1163*8dbcf02cSchristos } 1164*8dbcf02cSchristos req = wpabuf_head(reqData); 1165*8dbcf02cSchristos id = req->identifier; 1166*8dbcf02cSchristos len = be_to_host16(req->length); 1167*8dbcf02cSchristos 1168*8dbcf02cSchristos ret->ignore = FALSE; 1169*8dbcf02cSchristos ret->methodState = METHOD_MAY_CONT; 1170*8dbcf02cSchristos ret->decision = DECISION_FAIL; 1171*8dbcf02cSchristos ret->allowNotifications = TRUE; 1172*8dbcf02cSchristos 1173*8dbcf02cSchristos subtype = *pos++; 1174*8dbcf02cSchristos wpa_printf(MSG_DEBUG, "EAP-AKA: Subtype=%d", subtype); 1175*8dbcf02cSchristos pos += 2; /* Reserved */ 1176*8dbcf02cSchristos 1177*8dbcf02cSchristos if (eap_sim_parse_attr(pos, wpabuf_head_u8(reqData) + len, &attr, 1178*8dbcf02cSchristos data->eap_method == EAP_TYPE_AKA_PRIME ? 2 : 1, 1179*8dbcf02cSchristos 0)) { 1180*8dbcf02cSchristos res = eap_aka_client_error(data, id, 1181*8dbcf02cSchristos EAP_AKA_UNABLE_TO_PROCESS_PACKET); 1182*8dbcf02cSchristos goto done; 1183*8dbcf02cSchristos } 1184*8dbcf02cSchristos 1185*8dbcf02cSchristos switch (subtype) { 1186*8dbcf02cSchristos case EAP_AKA_SUBTYPE_IDENTITY: 1187*8dbcf02cSchristos res = eap_aka_process_identity(sm, data, id, reqData, &attr); 1188*8dbcf02cSchristos break; 1189*8dbcf02cSchristos case EAP_AKA_SUBTYPE_CHALLENGE: 1190*8dbcf02cSchristos res = eap_aka_process_challenge(sm, data, id, reqData, &attr); 1191*8dbcf02cSchristos break; 1192*8dbcf02cSchristos case EAP_AKA_SUBTYPE_NOTIFICATION: 1193*8dbcf02cSchristos res = eap_aka_process_notification(sm, data, id, reqData, 1194*8dbcf02cSchristos &attr); 1195*8dbcf02cSchristos break; 1196*8dbcf02cSchristos case EAP_AKA_SUBTYPE_REAUTHENTICATION: 1197*8dbcf02cSchristos res = eap_aka_process_reauthentication(sm, data, id, reqData, 1198*8dbcf02cSchristos &attr); 1199*8dbcf02cSchristos break; 1200*8dbcf02cSchristos case EAP_AKA_SUBTYPE_CLIENT_ERROR: 1201*8dbcf02cSchristos wpa_printf(MSG_DEBUG, "EAP-AKA: subtype Client-Error"); 1202*8dbcf02cSchristos res = eap_aka_client_error(data, id, 1203*8dbcf02cSchristos EAP_AKA_UNABLE_TO_PROCESS_PACKET); 1204*8dbcf02cSchristos break; 1205*8dbcf02cSchristos default: 1206*8dbcf02cSchristos wpa_printf(MSG_DEBUG, "EAP-AKA: Unknown subtype=%d", subtype); 1207*8dbcf02cSchristos res = eap_aka_client_error(data, id, 1208*8dbcf02cSchristos EAP_AKA_UNABLE_TO_PROCESS_PACKET); 1209*8dbcf02cSchristos break; 1210*8dbcf02cSchristos } 1211*8dbcf02cSchristos 1212*8dbcf02cSchristos done: 1213*8dbcf02cSchristos if (data->state == FAILURE) { 1214*8dbcf02cSchristos ret->decision = DECISION_FAIL; 1215*8dbcf02cSchristos ret->methodState = METHOD_DONE; 1216*8dbcf02cSchristos } else if (data->state == SUCCESS) { 1217*8dbcf02cSchristos ret->decision = data->use_result_ind ? 1218*8dbcf02cSchristos DECISION_UNCOND_SUCC : DECISION_COND_SUCC; 1219*8dbcf02cSchristos /* 1220*8dbcf02cSchristos * It is possible for the server to reply with AKA 1221*8dbcf02cSchristos * Notification, so we must allow the method to continue and 1222*8dbcf02cSchristos * not only accept EAP-Success at this point. 1223*8dbcf02cSchristos */ 1224*8dbcf02cSchristos ret->methodState = data->use_result_ind ? 1225*8dbcf02cSchristos METHOD_DONE : METHOD_MAY_CONT; 1226*8dbcf02cSchristos } else if (data->state == RESULT_FAILURE) 1227*8dbcf02cSchristos ret->methodState = METHOD_CONT; 1228*8dbcf02cSchristos else if (data->state == RESULT_SUCCESS) 1229*8dbcf02cSchristos ret->methodState = METHOD_CONT; 1230*8dbcf02cSchristos 1231*8dbcf02cSchristos if (ret->methodState == METHOD_DONE) { 1232*8dbcf02cSchristos ret->allowNotifications = FALSE; 1233*8dbcf02cSchristos } 1234*8dbcf02cSchristos 1235*8dbcf02cSchristos return res; 1236*8dbcf02cSchristos } 1237*8dbcf02cSchristos 1238*8dbcf02cSchristos 1239*8dbcf02cSchristos static Boolean eap_aka_has_reauth_data(struct eap_sm *sm, void *priv) 1240*8dbcf02cSchristos { 1241*8dbcf02cSchristos struct eap_aka_data *data = priv; 1242*8dbcf02cSchristos return data->pseudonym || data->reauth_id; 1243*8dbcf02cSchristos } 1244*8dbcf02cSchristos 1245*8dbcf02cSchristos 1246*8dbcf02cSchristos static void eap_aka_deinit_for_reauth(struct eap_sm *sm, void *priv) 1247*8dbcf02cSchristos { 1248*8dbcf02cSchristos struct eap_aka_data *data = priv; 1249*8dbcf02cSchristos eap_aka_clear_identities(data, CLEAR_EAP_ID); 1250*8dbcf02cSchristos data->prev_id = -1; 1251*8dbcf02cSchristos wpabuf_free(data->id_msgs); 1252*8dbcf02cSchristos data->id_msgs = NULL; 1253*8dbcf02cSchristos data->use_result_ind = 0; 1254*8dbcf02cSchristos data->kdf_negotiation = 0; 1255*8dbcf02cSchristos } 1256*8dbcf02cSchristos 1257*8dbcf02cSchristos 1258*8dbcf02cSchristos static void * eap_aka_init_for_reauth(struct eap_sm *sm, void *priv) 1259*8dbcf02cSchristos { 1260*8dbcf02cSchristos struct eap_aka_data *data = priv; 1261*8dbcf02cSchristos data->num_id_req = 0; 1262*8dbcf02cSchristos data->num_notification = 0; 1263*8dbcf02cSchristos eap_aka_state(data, CONTINUE); 1264*8dbcf02cSchristos return priv; 1265*8dbcf02cSchristos } 1266*8dbcf02cSchristos 1267*8dbcf02cSchristos 1268*8dbcf02cSchristos static const u8 * eap_aka_get_identity(struct eap_sm *sm, void *priv, 1269*8dbcf02cSchristos size_t *len) 1270*8dbcf02cSchristos { 1271*8dbcf02cSchristos struct eap_aka_data *data = priv; 1272*8dbcf02cSchristos 1273*8dbcf02cSchristos if (data->reauth_id) { 1274*8dbcf02cSchristos *len = data->reauth_id_len; 1275*8dbcf02cSchristos return data->reauth_id; 1276*8dbcf02cSchristos } 1277*8dbcf02cSchristos 1278*8dbcf02cSchristos if (data->pseudonym) { 1279*8dbcf02cSchristos *len = data->pseudonym_len; 1280*8dbcf02cSchristos return data->pseudonym; 1281*8dbcf02cSchristos } 1282*8dbcf02cSchristos 1283*8dbcf02cSchristos return NULL; 1284*8dbcf02cSchristos } 1285*8dbcf02cSchristos 1286*8dbcf02cSchristos 1287*8dbcf02cSchristos static Boolean eap_aka_isKeyAvailable(struct eap_sm *sm, void *priv) 1288*8dbcf02cSchristos { 1289*8dbcf02cSchristos struct eap_aka_data *data = priv; 1290*8dbcf02cSchristos return data->state == SUCCESS; 1291*8dbcf02cSchristos } 1292*8dbcf02cSchristos 1293*8dbcf02cSchristos 1294*8dbcf02cSchristos static u8 * eap_aka_getKey(struct eap_sm *sm, void *priv, size_t *len) 1295*8dbcf02cSchristos { 1296*8dbcf02cSchristos struct eap_aka_data *data = priv; 1297*8dbcf02cSchristos u8 *key; 1298*8dbcf02cSchristos 1299*8dbcf02cSchristos if (data->state != SUCCESS) 1300*8dbcf02cSchristos return NULL; 1301*8dbcf02cSchristos 1302*8dbcf02cSchristos key = os_malloc(EAP_SIM_KEYING_DATA_LEN); 1303*8dbcf02cSchristos if (key == NULL) 1304*8dbcf02cSchristos return NULL; 1305*8dbcf02cSchristos 1306*8dbcf02cSchristos *len = EAP_SIM_KEYING_DATA_LEN; 1307*8dbcf02cSchristos os_memcpy(key, data->msk, EAP_SIM_KEYING_DATA_LEN); 1308*8dbcf02cSchristos 1309*8dbcf02cSchristos return key; 1310*8dbcf02cSchristos } 1311*8dbcf02cSchristos 1312*8dbcf02cSchristos 1313*8dbcf02cSchristos static u8 * eap_aka_get_emsk(struct eap_sm *sm, void *priv, size_t *len) 1314*8dbcf02cSchristos { 1315*8dbcf02cSchristos struct eap_aka_data *data = priv; 1316*8dbcf02cSchristos u8 *key; 1317*8dbcf02cSchristos 1318*8dbcf02cSchristos if (data->state != SUCCESS) 1319*8dbcf02cSchristos return NULL; 1320*8dbcf02cSchristos 1321*8dbcf02cSchristos key = os_malloc(EAP_EMSK_LEN); 1322*8dbcf02cSchristos if (key == NULL) 1323*8dbcf02cSchristos return NULL; 1324*8dbcf02cSchristos 1325*8dbcf02cSchristos *len = EAP_EMSK_LEN; 1326*8dbcf02cSchristos os_memcpy(key, data->emsk, EAP_EMSK_LEN); 1327*8dbcf02cSchristos 1328*8dbcf02cSchristos return key; 1329*8dbcf02cSchristos } 1330*8dbcf02cSchristos 1331*8dbcf02cSchristos 1332*8dbcf02cSchristos int eap_peer_aka_register(void) 1333*8dbcf02cSchristos { 1334*8dbcf02cSchristos struct eap_method *eap; 1335*8dbcf02cSchristos int ret; 1336*8dbcf02cSchristos 1337*8dbcf02cSchristos eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, 1338*8dbcf02cSchristos EAP_VENDOR_IETF, EAP_TYPE_AKA, "AKA"); 1339*8dbcf02cSchristos if (eap == NULL) 1340*8dbcf02cSchristos return -1; 1341*8dbcf02cSchristos 1342*8dbcf02cSchristos eap->init = eap_aka_init; 1343*8dbcf02cSchristos eap->deinit = eap_aka_deinit; 1344*8dbcf02cSchristos eap->process = eap_aka_process; 1345*8dbcf02cSchristos eap->isKeyAvailable = eap_aka_isKeyAvailable; 1346*8dbcf02cSchristos eap->getKey = eap_aka_getKey; 1347*8dbcf02cSchristos eap->has_reauth_data = eap_aka_has_reauth_data; 1348*8dbcf02cSchristos eap->deinit_for_reauth = eap_aka_deinit_for_reauth; 1349*8dbcf02cSchristos eap->init_for_reauth = eap_aka_init_for_reauth; 1350*8dbcf02cSchristos eap->get_identity = eap_aka_get_identity; 1351*8dbcf02cSchristos eap->get_emsk = eap_aka_get_emsk; 1352*8dbcf02cSchristos 1353*8dbcf02cSchristos ret = eap_peer_method_register(eap); 1354*8dbcf02cSchristos if (ret) 1355*8dbcf02cSchristos eap_peer_method_free(eap); 1356*8dbcf02cSchristos return ret; 1357*8dbcf02cSchristos } 1358*8dbcf02cSchristos 1359*8dbcf02cSchristos 1360*8dbcf02cSchristos #ifdef EAP_AKA_PRIME 1361*8dbcf02cSchristos int eap_peer_aka_prime_register(void) 1362*8dbcf02cSchristos { 1363*8dbcf02cSchristos struct eap_method *eap; 1364*8dbcf02cSchristos int ret; 1365*8dbcf02cSchristos 1366*8dbcf02cSchristos eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, 1367*8dbcf02cSchristos EAP_VENDOR_IETF, EAP_TYPE_AKA_PRIME, 1368*8dbcf02cSchristos "AKA'"); 1369*8dbcf02cSchristos if (eap == NULL) 1370*8dbcf02cSchristos return -1; 1371*8dbcf02cSchristos 1372*8dbcf02cSchristos eap->init = eap_aka_prime_init; 1373*8dbcf02cSchristos eap->deinit = eap_aka_deinit; 1374*8dbcf02cSchristos eap->process = eap_aka_process; 1375*8dbcf02cSchristos eap->isKeyAvailable = eap_aka_isKeyAvailable; 1376*8dbcf02cSchristos eap->getKey = eap_aka_getKey; 1377*8dbcf02cSchristos eap->has_reauth_data = eap_aka_has_reauth_data; 1378*8dbcf02cSchristos eap->deinit_for_reauth = eap_aka_deinit_for_reauth; 1379*8dbcf02cSchristos eap->init_for_reauth = eap_aka_init_for_reauth; 1380*8dbcf02cSchristos eap->get_identity = eap_aka_get_identity; 1381*8dbcf02cSchristos eap->get_emsk = eap_aka_get_emsk; 1382*8dbcf02cSchristos 1383*8dbcf02cSchristos ret = eap_peer_method_register(eap); 1384*8dbcf02cSchristos if (ret) 1385*8dbcf02cSchristos eap_peer_method_free(eap); 1386*8dbcf02cSchristos 1387*8dbcf02cSchristos return ret; 1388*8dbcf02cSchristos } 1389*8dbcf02cSchristos #endif /* EAP_AKA_PRIME */ 1390