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