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