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