1 /* 2 * hostapd / EAP-AKA (RFC 4187) and EAP-AKA' (draft-arkko-eap-aka-kdf) 3 * Copyright (c) 2005-2008, Jouni Malinen <j (at) 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 "crypto/sha256.h" 19 #include "crypto/crypto.h" 20 #include "crypto/random.h" 21 #include "eap_common/eap_sim_common.h" 22 #include "eap_server/eap_i.h" 23 #include "eap_server/eap_sim_db.h" 24 25 26 struct eap_aka_data { 27 u8 mk[EAP_SIM_MK_LEN]; 28 u8 nonce_s[EAP_SIM_NONCE_S_LEN]; 29 u8 k_aut[EAP_AKA_PRIME_K_AUT_LEN]; 30 u8 k_encr[EAP_SIM_K_ENCR_LEN]; 31 u8 k_re[EAP_AKA_PRIME_K_RE_LEN]; /* EAP-AKA' only */ 32 u8 msk[EAP_SIM_KEYING_DATA_LEN]; 33 u8 emsk[EAP_EMSK_LEN]; 34 u8 rand[EAP_AKA_RAND_LEN]; 35 u8 autn[EAP_AKA_AUTN_LEN]; 36 u8 ck[EAP_AKA_CK_LEN]; 37 u8 ik[EAP_AKA_IK_LEN]; 38 u8 res[EAP_AKA_RES_MAX_LEN]; 39 size_t res_len; 40 enum { 41 IDENTITY, CHALLENGE, REAUTH, NOTIFICATION, SUCCESS, FAILURE 42 } state; 43 char *next_pseudonym; 44 char *next_reauth_id; 45 u16 counter; 46 struct eap_sim_reauth *reauth; 47 int auts_reported; /* whether the current AUTS has been reported to the 48 * eap_sim_db */ 49 u16 notification; 50 int use_result_ind; 51 52 struct wpabuf *id_msgs; 53 int pending_id; 54 u8 eap_method; 55 u8 *network_name; 56 size_t network_name_len; 57 u16 kdf; 58 }; 59 60 61 static void eap_aka_determine_identity(struct eap_sm *sm, 62 struct eap_aka_data *data, 63 int before_identity, int after_reauth); 64 65 66 static const char * eap_aka_state_txt(int state) 67 { 68 switch (state) { 69 case IDENTITY: 70 return "IDENTITY"; 71 case CHALLENGE: 72 return "CHALLENGE"; 73 case REAUTH: 74 return "REAUTH"; 75 case SUCCESS: 76 return "SUCCESS"; 77 case FAILURE: 78 return "FAILURE"; 79 case NOTIFICATION: 80 return "NOTIFICATION"; 81 default: 82 return "Unknown?!"; 83 } 84 } 85 86 87 static void eap_aka_state(struct eap_aka_data *data, int state) 88 { 89 wpa_printf(MSG_DEBUG, "EAP-AKA: %s -> %s", 90 eap_aka_state_txt(data->state), 91 eap_aka_state_txt(state)); 92 data->state = state; 93 } 94 95 96 static void * eap_aka_init(struct eap_sm *sm) 97 { 98 struct eap_aka_data *data; 99 100 if (sm->eap_sim_db_priv == NULL) { 101 wpa_printf(MSG_WARNING, "EAP-AKA: eap_sim_db not configured"); 102 return NULL; 103 } 104 105 data = os_zalloc(sizeof(*data)); 106 if (data == NULL) 107 return NULL; 108 109 data->eap_method = EAP_TYPE_AKA; 110 111 data->state = IDENTITY; 112 eap_aka_determine_identity(sm, data, 1, 0); 113 data->pending_id = -1; 114 115 return data; 116 } 117 118 119 #ifdef EAP_SERVER_AKA_PRIME 120 static void * eap_aka_prime_init(struct eap_sm *sm) 121 { 122 struct eap_aka_data *data; 123 /* TODO: make ANID configurable; see 3GPP TS 24.302 */ 124 char *network_name = "WLAN"; 125 126 if (sm->eap_sim_db_priv == NULL) { 127 wpa_printf(MSG_WARNING, "EAP-AKA: eap_sim_db not configured"); 128 return NULL; 129 } 130 131 data = os_zalloc(sizeof(*data)); 132 if (data == NULL) 133 return NULL; 134 135 data->eap_method = EAP_TYPE_AKA_PRIME; 136 data->network_name = os_malloc(os_strlen(network_name)); 137 if (data->network_name == NULL) { 138 os_free(data); 139 return NULL; 140 } 141 142 data->network_name_len = os_strlen(network_name); 143 os_memcpy(data->network_name, network_name, data->network_name_len); 144 145 data->state = IDENTITY; 146 eap_aka_determine_identity(sm, data, 1, 0); 147 data->pending_id = -1; 148 149 return data; 150 } 151 #endif /* EAP_SERVER_AKA_PRIME */ 152 153 154 static void eap_aka_reset(struct eap_sm *sm, void *priv) 155 { 156 struct eap_aka_data *data = priv; 157 os_free(data->next_pseudonym); 158 os_free(data->next_reauth_id); 159 wpabuf_free(data->id_msgs); 160 os_free(data->network_name); 161 os_free(data); 162 } 163 164 165 static int eap_aka_add_id_msg(struct eap_aka_data *data, 166 const struct wpabuf *msg) 167 { 168 if (msg == NULL) 169 return -1; 170 171 if (data->id_msgs == NULL) { 172 data->id_msgs = wpabuf_dup(msg); 173 return data->id_msgs == NULL ? -1 : 0; 174 } 175 176 if (wpabuf_resize(&data->id_msgs, wpabuf_len(msg)) < 0) 177 return -1; 178 wpabuf_put_buf(data->id_msgs, msg); 179 180 return 0; 181 } 182 183 184 static void eap_aka_add_checkcode(struct eap_aka_data *data, 185 struct eap_sim_msg *msg) 186 { 187 const u8 *addr; 188 size_t len; 189 u8 hash[SHA256_MAC_LEN]; 190 191 wpa_printf(MSG_DEBUG, " AT_CHECKCODE"); 192 193 if (data->id_msgs == NULL) { 194 /* 195 * No EAP-AKA/Identity packets were exchanged - send empty 196 * checkcode. 197 */ 198 eap_sim_msg_add(msg, EAP_SIM_AT_CHECKCODE, 0, NULL, 0); 199 return; 200 } 201 202 /* Checkcode is SHA1 hash over all EAP-AKA/Identity packets. */ 203 addr = wpabuf_head(data->id_msgs); 204 len = wpabuf_len(data->id_msgs); 205 wpa_hexdump(MSG_MSGDUMP, "EAP-AKA: AT_CHECKCODE data", addr, len); 206 if (data->eap_method == EAP_TYPE_AKA_PRIME) 207 sha256_vector(1, &addr, &len, hash); 208 else 209 sha1_vector(1, &addr, &len, hash); 210 211 eap_sim_msg_add(msg, EAP_SIM_AT_CHECKCODE, 0, hash, 212 data->eap_method == EAP_TYPE_AKA_PRIME ? 213 EAP_AKA_PRIME_CHECKCODE_LEN : EAP_AKA_CHECKCODE_LEN); 214 } 215 216 217 static int eap_aka_verify_checkcode(struct eap_aka_data *data, 218 const u8 *checkcode, size_t checkcode_len) 219 { 220 const u8 *addr; 221 size_t len; 222 u8 hash[SHA256_MAC_LEN]; 223 size_t hash_len; 224 225 if (checkcode == NULL) 226 return -1; 227 228 if (data->id_msgs == NULL) { 229 if (checkcode_len != 0) { 230 wpa_printf(MSG_DEBUG, "EAP-AKA: Checkcode from peer " 231 "indicates that AKA/Identity messages were " 232 "used, but they were not"); 233 return -1; 234 } 235 return 0; 236 } 237 238 hash_len = data->eap_method == EAP_TYPE_AKA_PRIME ? 239 EAP_AKA_PRIME_CHECKCODE_LEN : EAP_AKA_CHECKCODE_LEN; 240 241 if (checkcode_len != hash_len) { 242 wpa_printf(MSG_DEBUG, "EAP-AKA: Checkcode from peer indicates " 243 "that AKA/Identity message were not used, but they " 244 "were"); 245 return -1; 246 } 247 248 /* Checkcode is SHA1 hash over all EAP-AKA/Identity packets. */ 249 addr = wpabuf_head(data->id_msgs); 250 len = wpabuf_len(data->id_msgs); 251 if (data->eap_method == EAP_TYPE_AKA_PRIME) 252 sha256_vector(1, &addr, &len, hash); 253 else 254 sha1_vector(1, &addr, &len, hash); 255 256 if (os_memcmp(hash, checkcode, hash_len) != 0) { 257 wpa_printf(MSG_DEBUG, "EAP-AKA: Mismatch in AT_CHECKCODE"); 258 return -1; 259 } 260 261 return 0; 262 } 263 264 265 static struct wpabuf * eap_aka_build_identity(struct eap_sm *sm, 266 struct eap_aka_data *data, u8 id) 267 { 268 struct eap_sim_msg *msg; 269 struct wpabuf *buf; 270 271 wpa_printf(MSG_DEBUG, "EAP-AKA: Generating Identity"); 272 msg = eap_sim_msg_init(EAP_CODE_REQUEST, id, data->eap_method, 273 EAP_AKA_SUBTYPE_IDENTITY); 274 if (eap_sim_db_identity_known(sm->eap_sim_db_priv, sm->identity, 275 sm->identity_len)) { 276 wpa_printf(MSG_DEBUG, " AT_PERMANENT_ID_REQ"); 277 eap_sim_msg_add(msg, EAP_SIM_AT_PERMANENT_ID_REQ, 0, NULL, 0); 278 } else { 279 /* 280 * RFC 4187, Chap. 4.1.4 recommends that identity from EAP is 281 * ignored and the AKA/Identity is used to request the 282 * identity. 283 */ 284 wpa_printf(MSG_DEBUG, " AT_ANY_ID_REQ"); 285 eap_sim_msg_add(msg, EAP_SIM_AT_ANY_ID_REQ, 0, NULL, 0); 286 } 287 buf = eap_sim_msg_finish(msg, NULL, NULL, 0); 288 if (eap_aka_add_id_msg(data, buf) < 0) { 289 wpabuf_free(buf); 290 return NULL; 291 } 292 data->pending_id = id; 293 return buf; 294 } 295 296 297 static int eap_aka_build_encr(struct eap_sm *sm, struct eap_aka_data *data, 298 struct eap_sim_msg *msg, u16 counter, 299 const u8 *nonce_s) 300 { 301 os_free(data->next_pseudonym); 302 data->next_pseudonym = 303 eap_sim_db_get_next_pseudonym(sm->eap_sim_db_priv, 1); 304 os_free(data->next_reauth_id); 305 if (data->counter <= EAP_AKA_MAX_FAST_REAUTHS) { 306 data->next_reauth_id = 307 eap_sim_db_get_next_reauth_id(sm->eap_sim_db_priv, 1); 308 } else { 309 wpa_printf(MSG_DEBUG, "EAP-AKA: Max fast re-authentication " 310 "count exceeded - force full authentication"); 311 data->next_reauth_id = NULL; 312 } 313 314 if (data->next_pseudonym == NULL && data->next_reauth_id == NULL && 315 counter == 0 && nonce_s == NULL) 316 return 0; 317 318 wpa_printf(MSG_DEBUG, " AT_IV"); 319 wpa_printf(MSG_DEBUG, " AT_ENCR_DATA"); 320 eap_sim_msg_add_encr_start(msg, EAP_SIM_AT_IV, EAP_SIM_AT_ENCR_DATA); 321 322 if (counter > 0) { 323 wpa_printf(MSG_DEBUG, " *AT_COUNTER (%u)", counter); 324 eap_sim_msg_add(msg, EAP_SIM_AT_COUNTER, counter, NULL, 0); 325 } 326 327 if (nonce_s) { 328 wpa_printf(MSG_DEBUG, " *AT_NONCE_S"); 329 eap_sim_msg_add(msg, EAP_SIM_AT_NONCE_S, 0, nonce_s, 330 EAP_SIM_NONCE_S_LEN); 331 } 332 333 if (data->next_pseudonym) { 334 wpa_printf(MSG_DEBUG, " *AT_NEXT_PSEUDONYM (%s)", 335 data->next_pseudonym); 336 eap_sim_msg_add(msg, EAP_SIM_AT_NEXT_PSEUDONYM, 337 os_strlen(data->next_pseudonym), 338 (u8 *) data->next_pseudonym, 339 os_strlen(data->next_pseudonym)); 340 } 341 342 if (data->next_reauth_id) { 343 wpa_printf(MSG_DEBUG, " *AT_NEXT_REAUTH_ID (%s)", 344 data->next_reauth_id); 345 eap_sim_msg_add(msg, EAP_SIM_AT_NEXT_REAUTH_ID, 346 os_strlen(data->next_reauth_id), 347 (u8 *) data->next_reauth_id, 348 os_strlen(data->next_reauth_id)); 349 } 350 351 if (eap_sim_msg_add_encr_end(msg, data->k_encr, EAP_SIM_AT_PADDING)) { 352 wpa_printf(MSG_WARNING, "EAP-AKA: Failed to encrypt " 353 "AT_ENCR_DATA"); 354 return -1; 355 } 356 357 return 0; 358 } 359 360 361 static struct wpabuf * eap_aka_build_challenge(struct eap_sm *sm, 362 struct eap_aka_data *data, 363 u8 id) 364 { 365 struct eap_sim_msg *msg; 366 367 wpa_printf(MSG_DEBUG, "EAP-AKA: Generating Challenge"); 368 msg = eap_sim_msg_init(EAP_CODE_REQUEST, id, data->eap_method, 369 EAP_AKA_SUBTYPE_CHALLENGE); 370 wpa_printf(MSG_DEBUG, " AT_RAND"); 371 eap_sim_msg_add(msg, EAP_SIM_AT_RAND, 0, data->rand, EAP_AKA_RAND_LEN); 372 wpa_printf(MSG_DEBUG, " AT_AUTN"); 373 eap_sim_msg_add(msg, EAP_SIM_AT_AUTN, 0, data->autn, EAP_AKA_AUTN_LEN); 374 if (data->eap_method == EAP_TYPE_AKA_PRIME) { 375 if (data->kdf) { 376 /* Add the selected KDF into the beginning */ 377 wpa_printf(MSG_DEBUG, " AT_KDF"); 378 eap_sim_msg_add(msg, EAP_SIM_AT_KDF, data->kdf, 379 NULL, 0); 380 } 381 wpa_printf(MSG_DEBUG, " AT_KDF"); 382 eap_sim_msg_add(msg, EAP_SIM_AT_KDF, EAP_AKA_PRIME_KDF, 383 NULL, 0); 384 wpa_printf(MSG_DEBUG, " AT_KDF_INPUT"); 385 eap_sim_msg_add(msg, EAP_SIM_AT_KDF_INPUT, 386 data->network_name_len, 387 data->network_name, data->network_name_len); 388 } 389 390 if (eap_aka_build_encr(sm, data, msg, 0, NULL)) { 391 eap_sim_msg_free(msg); 392 return NULL; 393 } 394 395 eap_aka_add_checkcode(data, msg); 396 397 if (sm->eap_sim_aka_result_ind) { 398 wpa_printf(MSG_DEBUG, " AT_RESULT_IND"); 399 eap_sim_msg_add(msg, EAP_SIM_AT_RESULT_IND, 0, NULL, 0); 400 } 401 402 #ifdef EAP_SERVER_AKA_PRIME 403 if (data->eap_method == EAP_TYPE_AKA) { 404 u16 flags = 0; 405 int i; 406 int aka_prime_preferred = 0; 407 408 i = 0; 409 while (sm->user && i < EAP_MAX_METHODS && 410 (sm->user->methods[i].vendor != EAP_VENDOR_IETF || 411 sm->user->methods[i].method != EAP_TYPE_NONE)) { 412 if (sm->user->methods[i].vendor == EAP_VENDOR_IETF) { 413 if (sm->user->methods[i].method == 414 EAP_TYPE_AKA) 415 break; 416 if (sm->user->methods[i].method == 417 EAP_TYPE_AKA_PRIME) { 418 aka_prime_preferred = 1; 419 break; 420 } 421 } 422 i++; 423 } 424 425 if (aka_prime_preferred) 426 flags |= EAP_AKA_BIDDING_FLAG_D; 427 eap_sim_msg_add(msg, EAP_SIM_AT_BIDDING, flags, NULL, 0); 428 } 429 #endif /* EAP_SERVER_AKA_PRIME */ 430 431 wpa_printf(MSG_DEBUG, " AT_MAC"); 432 eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC); 433 return eap_sim_msg_finish(msg, data->k_aut, NULL, 0); 434 } 435 436 437 static struct wpabuf * eap_aka_build_reauth(struct eap_sm *sm, 438 struct eap_aka_data *data, u8 id) 439 { 440 struct eap_sim_msg *msg; 441 442 wpa_printf(MSG_DEBUG, "EAP-AKA: Generating Re-authentication"); 443 444 if (random_get_bytes(data->nonce_s, EAP_SIM_NONCE_S_LEN)) 445 return NULL; 446 wpa_hexdump_key(MSG_MSGDUMP, "EAP-AKA: NONCE_S", 447 data->nonce_s, EAP_SIM_NONCE_S_LEN); 448 449 if (data->eap_method == EAP_TYPE_AKA_PRIME) { 450 eap_aka_prime_derive_keys_reauth(data->k_re, data->counter, 451 sm->identity, 452 sm->identity_len, 453 data->nonce_s, 454 data->msk, data->emsk); 455 } else { 456 eap_sim_derive_keys(data->mk, data->k_encr, data->k_aut, 457 data->msk, data->emsk); 458 eap_sim_derive_keys_reauth(data->counter, sm->identity, 459 sm->identity_len, data->nonce_s, 460 data->mk, data->msk, data->emsk); 461 } 462 463 msg = eap_sim_msg_init(EAP_CODE_REQUEST, id, data->eap_method, 464 EAP_AKA_SUBTYPE_REAUTHENTICATION); 465 466 if (eap_aka_build_encr(sm, data, msg, data->counter, data->nonce_s)) { 467 eap_sim_msg_free(msg); 468 return NULL; 469 } 470 471 eap_aka_add_checkcode(data, msg); 472 473 if (sm->eap_sim_aka_result_ind) { 474 wpa_printf(MSG_DEBUG, " AT_RESULT_IND"); 475 eap_sim_msg_add(msg, EAP_SIM_AT_RESULT_IND, 0, NULL, 0); 476 } 477 478 wpa_printf(MSG_DEBUG, " AT_MAC"); 479 eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC); 480 return eap_sim_msg_finish(msg, data->k_aut, NULL, 0); 481 } 482 483 484 static struct wpabuf * eap_aka_build_notification(struct eap_sm *sm, 485 struct eap_aka_data *data, 486 u8 id) 487 { 488 struct eap_sim_msg *msg; 489 490 wpa_printf(MSG_DEBUG, "EAP-AKA: Generating Notification"); 491 msg = eap_sim_msg_init(EAP_CODE_REQUEST, id, data->eap_method, 492 EAP_AKA_SUBTYPE_NOTIFICATION); 493 wpa_printf(MSG_DEBUG, " AT_NOTIFICATION (%d)", data->notification); 494 eap_sim_msg_add(msg, EAP_SIM_AT_NOTIFICATION, data->notification, 495 NULL, 0); 496 if (data->use_result_ind) { 497 if (data->reauth) { 498 wpa_printf(MSG_DEBUG, " AT_IV"); 499 wpa_printf(MSG_DEBUG, " AT_ENCR_DATA"); 500 eap_sim_msg_add_encr_start(msg, EAP_SIM_AT_IV, 501 EAP_SIM_AT_ENCR_DATA); 502 wpa_printf(MSG_DEBUG, " *AT_COUNTER (%u)", 503 data->counter); 504 eap_sim_msg_add(msg, EAP_SIM_AT_COUNTER, data->counter, 505 NULL, 0); 506 507 if (eap_sim_msg_add_encr_end(msg, data->k_encr, 508 EAP_SIM_AT_PADDING)) { 509 wpa_printf(MSG_WARNING, "EAP-AKA: Failed to " 510 "encrypt AT_ENCR_DATA"); 511 eap_sim_msg_free(msg); 512 return NULL; 513 } 514 } 515 516 wpa_printf(MSG_DEBUG, " AT_MAC"); 517 eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC); 518 } 519 return eap_sim_msg_finish(msg, data->k_aut, NULL, 0); 520 } 521 522 523 static struct wpabuf * eap_aka_buildReq(struct eap_sm *sm, void *priv, u8 id) 524 { 525 struct eap_aka_data *data = priv; 526 527 data->auts_reported = 0; 528 switch (data->state) { 529 case IDENTITY: 530 return eap_aka_build_identity(sm, data, id); 531 case CHALLENGE: 532 return eap_aka_build_challenge(sm, data, id); 533 case REAUTH: 534 return eap_aka_build_reauth(sm, data, id); 535 case NOTIFICATION: 536 return eap_aka_build_notification(sm, data, id); 537 default: 538 wpa_printf(MSG_DEBUG, "EAP-AKA: Unknown state %d in " 539 "buildReq", data->state); 540 break; 541 } 542 return NULL; 543 } 544 545 546 static Boolean eap_aka_check(struct eap_sm *sm, void *priv, 547 struct wpabuf *respData) 548 { 549 struct eap_aka_data *data = priv; 550 const u8 *pos; 551 size_t len; 552 553 pos = eap_hdr_validate(EAP_VENDOR_IETF, data->eap_method, respData, 554 &len); 555 if (pos == NULL || len < 3) { 556 wpa_printf(MSG_INFO, "EAP-AKA: Invalid frame"); 557 return TRUE; 558 } 559 560 return FALSE; 561 } 562 563 564 static Boolean eap_aka_subtype_ok(struct eap_aka_data *data, u8 subtype) 565 { 566 if (subtype == EAP_AKA_SUBTYPE_CLIENT_ERROR || 567 subtype == EAP_AKA_SUBTYPE_AUTHENTICATION_REJECT) 568 return FALSE; 569 570 switch (data->state) { 571 case IDENTITY: 572 if (subtype != EAP_AKA_SUBTYPE_IDENTITY) { 573 wpa_printf(MSG_INFO, "EAP-AKA: Unexpected response " 574 "subtype %d", subtype); 575 return TRUE; 576 } 577 break; 578 case CHALLENGE: 579 if (subtype != EAP_AKA_SUBTYPE_CHALLENGE && 580 subtype != EAP_AKA_SUBTYPE_SYNCHRONIZATION_FAILURE) { 581 wpa_printf(MSG_INFO, "EAP-AKA: Unexpected response " 582 "subtype %d", subtype); 583 return TRUE; 584 } 585 break; 586 case REAUTH: 587 if (subtype != EAP_AKA_SUBTYPE_REAUTHENTICATION) { 588 wpa_printf(MSG_INFO, "EAP-AKA: Unexpected response " 589 "subtype %d", subtype); 590 return TRUE; 591 } 592 break; 593 case NOTIFICATION: 594 if (subtype != EAP_AKA_SUBTYPE_NOTIFICATION) { 595 wpa_printf(MSG_INFO, "EAP-AKA: Unexpected response " 596 "subtype %d", subtype); 597 return TRUE; 598 } 599 break; 600 default: 601 wpa_printf(MSG_INFO, "EAP-AKA: Unexpected state (%d) for " 602 "processing a response", data->state); 603 return TRUE; 604 } 605 606 return FALSE; 607 } 608 609 610 static void eap_aka_determine_identity(struct eap_sm *sm, 611 struct eap_aka_data *data, 612 int before_identity, int after_reauth) 613 { 614 const u8 *identity; 615 size_t identity_len; 616 int res; 617 618 identity = NULL; 619 identity_len = 0; 620 621 if (after_reauth && data->reauth) { 622 identity = data->reauth->identity; 623 identity_len = data->reauth->identity_len; 624 } else if (sm->identity && sm->identity_len > 0 && 625 sm->identity[0] == EAP_AKA_PERMANENT_PREFIX) { 626 identity = sm->identity; 627 identity_len = sm->identity_len; 628 } else { 629 identity = eap_sim_db_get_permanent(sm->eap_sim_db_priv, 630 sm->identity, 631 sm->identity_len, 632 &identity_len); 633 if (identity == NULL) { 634 data->reauth = eap_sim_db_get_reauth_entry( 635 sm->eap_sim_db_priv, sm->identity, 636 sm->identity_len); 637 if (data->reauth && 638 data->reauth->aka_prime != 639 (data->eap_method == EAP_TYPE_AKA_PRIME)) { 640 wpa_printf(MSG_DEBUG, "EAP-AKA: Reauth data " 641 "was for different AKA version"); 642 data->reauth = NULL; 643 } 644 if (data->reauth) { 645 wpa_printf(MSG_DEBUG, "EAP-AKA: Using fast " 646 "re-authentication"); 647 identity = data->reauth->identity; 648 identity_len = data->reauth->identity_len; 649 data->counter = data->reauth->counter; 650 if (data->eap_method == EAP_TYPE_AKA_PRIME) { 651 os_memcpy(data->k_encr, 652 data->reauth->k_encr, 653 EAP_SIM_K_ENCR_LEN); 654 os_memcpy(data->k_aut, 655 data->reauth->k_aut, 656 EAP_AKA_PRIME_K_AUT_LEN); 657 os_memcpy(data->k_re, 658 data->reauth->k_re, 659 EAP_AKA_PRIME_K_RE_LEN); 660 } else { 661 os_memcpy(data->mk, data->reauth->mk, 662 EAP_SIM_MK_LEN); 663 } 664 } 665 } 666 } 667 668 if (identity == NULL || 669 eap_sim_db_identity_known(sm->eap_sim_db_priv, sm->identity, 670 sm->identity_len) < 0) { 671 if (before_identity) { 672 wpa_printf(MSG_DEBUG, "EAP-AKA: Permanent user name " 673 "not known - send AKA-Identity request"); 674 eap_aka_state(data, IDENTITY); 675 return; 676 } else { 677 wpa_printf(MSG_DEBUG, "EAP-AKA: Unknown whether the " 678 "permanent user name is known; try to use " 679 "it"); 680 /* eap_sim_db_get_aka_auth() will report failure, if 681 * this identity is not known. */ 682 } 683 } 684 685 wpa_hexdump_ascii(MSG_DEBUG, "EAP-AKA: Identity", 686 identity, identity_len); 687 688 if (!after_reauth && data->reauth) { 689 eap_aka_state(data, REAUTH); 690 return; 691 } 692 693 res = eap_sim_db_get_aka_auth(sm->eap_sim_db_priv, identity, 694 identity_len, data->rand, data->autn, 695 data->ik, data->ck, data->res, 696 &data->res_len, sm); 697 if (res == EAP_SIM_DB_PENDING) { 698 wpa_printf(MSG_DEBUG, "EAP-AKA: AKA authentication data " 699 "not yet available - pending request"); 700 sm->method_pending = METHOD_PENDING_WAIT; 701 return; 702 } 703 704 #ifdef EAP_SERVER_AKA_PRIME 705 if (data->eap_method == EAP_TYPE_AKA_PRIME) { 706 /* Note: AUTN = (SQN ^ AK) || AMF || MAC which gives us the 707 * needed 6-octet SQN ^AK for CK',IK' derivation */ 708 eap_aka_prime_derive_ck_ik_prime(data->ck, data->ik, 709 data->autn, 710 data->network_name, 711 data->network_name_len); 712 } 713 #endif /* EAP_SERVER_AKA_PRIME */ 714 715 data->reauth = NULL; 716 data->counter = 0; /* reset re-auth counter since this is full auth */ 717 718 if (res != 0) { 719 wpa_printf(MSG_INFO, "EAP-AKA: Failed to get AKA " 720 "authentication data for the peer"); 721 data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH; 722 eap_aka_state(data, NOTIFICATION); 723 return; 724 } 725 if (sm->method_pending == METHOD_PENDING_WAIT) { 726 wpa_printf(MSG_DEBUG, "EAP-AKA: AKA authentication data " 727 "available - abort pending wait"); 728 sm->method_pending = METHOD_PENDING_NONE; 729 } 730 731 identity_len = sm->identity_len; 732 while (identity_len > 0 && sm->identity[identity_len - 1] == '\0') { 733 wpa_printf(MSG_DEBUG, "EAP-AKA: Workaround - drop last null " 734 "character from identity"); 735 identity_len--; 736 } 737 wpa_hexdump_ascii(MSG_DEBUG, "EAP-AKA: Identity for MK derivation", 738 sm->identity, identity_len); 739 740 if (data->eap_method == EAP_TYPE_AKA_PRIME) { 741 eap_aka_prime_derive_keys(identity, identity_len, data->ik, 742 data->ck, data->k_encr, data->k_aut, 743 data->k_re, data->msk, data->emsk); 744 } else { 745 eap_aka_derive_mk(sm->identity, identity_len, data->ik, 746 data->ck, data->mk); 747 eap_sim_derive_keys(data->mk, data->k_encr, data->k_aut, 748 data->msk, data->emsk); 749 } 750 751 eap_aka_state(data, CHALLENGE); 752 } 753 754 755 static void eap_aka_process_identity(struct eap_sm *sm, 756 struct eap_aka_data *data, 757 struct wpabuf *respData, 758 struct eap_sim_attrs *attr) 759 { 760 wpa_printf(MSG_DEBUG, "EAP-AKA: Processing Identity"); 761 762 if (attr->mac || attr->iv || attr->encr_data) { 763 wpa_printf(MSG_WARNING, "EAP-AKA: Unexpected attribute " 764 "received in EAP-Response/AKA-Identity"); 765 data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH; 766 eap_aka_state(data, NOTIFICATION); 767 return; 768 } 769 770 if (attr->identity) { 771 os_free(sm->identity); 772 sm->identity = os_malloc(attr->identity_len); 773 if (sm->identity) { 774 os_memcpy(sm->identity, attr->identity, 775 attr->identity_len); 776 sm->identity_len = attr->identity_len; 777 } 778 } 779 780 eap_aka_determine_identity(sm, data, 0, 0); 781 if (eap_get_id(respData) == data->pending_id) { 782 data->pending_id = -1; 783 eap_aka_add_id_msg(data, respData); 784 } 785 } 786 787 788 static int eap_aka_verify_mac(struct eap_aka_data *data, 789 const struct wpabuf *req, 790 const u8 *mac, const u8 *extra, 791 size_t extra_len) 792 { 793 if (data->eap_method == EAP_TYPE_AKA_PRIME) 794 return eap_sim_verify_mac_sha256(data->k_aut, req, mac, extra, 795 extra_len); 796 return eap_sim_verify_mac(data->k_aut, req, mac, extra, extra_len); 797 } 798 799 800 static void eap_aka_process_challenge(struct eap_sm *sm, 801 struct eap_aka_data *data, 802 struct wpabuf *respData, 803 struct eap_sim_attrs *attr) 804 { 805 const u8 *identity; 806 size_t identity_len; 807 808 wpa_printf(MSG_DEBUG, "EAP-AKA: Processing Challenge"); 809 810 #ifdef EAP_SERVER_AKA_PRIME 811 #if 0 812 /* KDF negotiation; to be enabled only after more than one KDF is 813 * supported */ 814 if (data->eap_method == EAP_TYPE_AKA_PRIME && 815 attr->kdf_count == 1 && attr->mac == NULL) { 816 if (attr->kdf[0] != EAP_AKA_PRIME_KDF) { 817 wpa_printf(MSG_WARNING, "EAP-AKA': Peer selected " 818 "unknown KDF"); 819 data->notification = 820 EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH; 821 eap_aka_state(data, NOTIFICATION); 822 return; 823 } 824 825 data->kdf = attr->kdf[0]; 826 827 /* Allow negotiation to continue with the selected KDF by 828 * sending another Challenge message */ 829 wpa_printf(MSG_DEBUG, "EAP-AKA': KDF %d selected", data->kdf); 830 return; 831 } 832 #endif 833 #endif /* EAP_SERVER_AKA_PRIME */ 834 835 if (attr->checkcode && 836 eap_aka_verify_checkcode(data, attr->checkcode, 837 attr->checkcode_len)) { 838 wpa_printf(MSG_WARNING, "EAP-AKA: Invalid AT_CHECKCODE in the " 839 "message"); 840 data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH; 841 eap_aka_state(data, NOTIFICATION); 842 return; 843 } 844 if (attr->mac == NULL || 845 eap_aka_verify_mac(data, respData, attr->mac, NULL, 0)) { 846 wpa_printf(MSG_WARNING, "EAP-AKA: Challenge message " 847 "did not include valid AT_MAC"); 848 data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH; 849 eap_aka_state(data, NOTIFICATION); 850 return; 851 } 852 853 /* 854 * AT_RES is padded, so verify that there is enough room for RES and 855 * that the RES length in bits matches with the expected RES. 856 */ 857 if (attr->res == NULL || attr->res_len < data->res_len || 858 attr->res_len_bits != data->res_len * 8 || 859 os_memcmp(attr->res, data->res, data->res_len) != 0) { 860 wpa_printf(MSG_WARNING, "EAP-AKA: Challenge message did not " 861 "include valid AT_RES (attr len=%lu, res len=%lu " 862 "bits, expected %lu bits)", 863 (unsigned long) attr->res_len, 864 (unsigned long) attr->res_len_bits, 865 (unsigned long) data->res_len * 8); 866 data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH; 867 eap_aka_state(data, NOTIFICATION); 868 return; 869 } 870 871 wpa_printf(MSG_DEBUG, "EAP-AKA: Challenge response includes the " 872 "correct AT_MAC"); 873 if (sm->eap_sim_aka_result_ind && attr->result_ind) { 874 data->use_result_ind = 1; 875 data->notification = EAP_SIM_SUCCESS; 876 eap_aka_state(data, NOTIFICATION); 877 } else 878 eap_aka_state(data, SUCCESS); 879 880 identity = eap_sim_db_get_permanent(sm->eap_sim_db_priv, sm->identity, 881 sm->identity_len, &identity_len); 882 if (identity == NULL) { 883 identity = sm->identity; 884 identity_len = sm->identity_len; 885 } 886 887 if (data->next_pseudonym) { 888 eap_sim_db_add_pseudonym(sm->eap_sim_db_priv, identity, 889 identity_len, 890 data->next_pseudonym); 891 data->next_pseudonym = NULL; 892 } 893 if (data->next_reauth_id) { 894 if (data->eap_method == EAP_TYPE_AKA_PRIME) { 895 #ifdef EAP_SERVER_AKA_PRIME 896 eap_sim_db_add_reauth_prime(sm->eap_sim_db_priv, 897 identity, 898 identity_len, 899 data->next_reauth_id, 900 data->counter + 1, 901 data->k_encr, data->k_aut, 902 data->k_re); 903 #endif /* EAP_SERVER_AKA_PRIME */ 904 } else { 905 eap_sim_db_add_reauth(sm->eap_sim_db_priv, identity, 906 identity_len, 907 data->next_reauth_id, 908 data->counter + 1, 909 data->mk); 910 } 911 data->next_reauth_id = NULL; 912 } 913 } 914 915 916 static void eap_aka_process_sync_failure(struct eap_sm *sm, 917 struct eap_aka_data *data, 918 struct wpabuf *respData, 919 struct eap_sim_attrs *attr) 920 { 921 wpa_printf(MSG_DEBUG, "EAP-AKA: Processing Synchronization-Failure"); 922 923 if (attr->auts == NULL) { 924 wpa_printf(MSG_WARNING, "EAP-AKA: Synchronization-Failure " 925 "message did not include valid AT_AUTS"); 926 data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH; 927 eap_aka_state(data, NOTIFICATION); 928 return; 929 } 930 931 /* Avoid re-reporting AUTS when processing pending EAP packet by 932 * maintaining a local flag stating whether this AUTS has already been 933 * reported. */ 934 if (!data->auts_reported && 935 eap_sim_db_resynchronize(sm->eap_sim_db_priv, sm->identity, 936 sm->identity_len, attr->auts, 937 data->rand)) { 938 wpa_printf(MSG_WARNING, "EAP-AKA: Resynchronization failed"); 939 data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH; 940 eap_aka_state(data, NOTIFICATION); 941 return; 942 } 943 data->auts_reported = 1; 944 945 /* Try again after resynchronization */ 946 eap_aka_determine_identity(sm, data, 0, 0); 947 } 948 949 950 static void eap_aka_process_reauth(struct eap_sm *sm, 951 struct eap_aka_data *data, 952 struct wpabuf *respData, 953 struct eap_sim_attrs *attr) 954 { 955 struct eap_sim_attrs eattr; 956 u8 *decrypted = NULL; 957 const u8 *identity, *id2; 958 size_t identity_len, id2_len; 959 960 wpa_printf(MSG_DEBUG, "EAP-AKA: Processing Reauthentication"); 961 962 if (attr->mac == NULL || 963 eap_aka_verify_mac(data, respData, attr->mac, data->nonce_s, 964 EAP_SIM_NONCE_S_LEN)) { 965 wpa_printf(MSG_WARNING, "EAP-AKA: Re-authentication message " 966 "did not include valid AT_MAC"); 967 goto fail; 968 } 969 970 if (attr->encr_data == NULL || attr->iv == NULL) { 971 wpa_printf(MSG_WARNING, "EAP-AKA: Reauthentication " 972 "message did not include encrypted data"); 973 goto fail; 974 } 975 976 decrypted = eap_sim_parse_encr(data->k_encr, attr->encr_data, 977 attr->encr_data_len, attr->iv, &eattr, 978 0); 979 if (decrypted == NULL) { 980 wpa_printf(MSG_WARNING, "EAP-AKA: Failed to parse encrypted " 981 "data from reauthentication message"); 982 goto fail; 983 } 984 985 if (eattr.counter != data->counter) { 986 wpa_printf(MSG_WARNING, "EAP-AKA: Re-authentication message " 987 "used incorrect counter %u, expected %u", 988 eattr.counter, data->counter); 989 goto fail; 990 } 991 os_free(decrypted); 992 decrypted = NULL; 993 994 wpa_printf(MSG_DEBUG, "EAP-AKA: Re-authentication response includes " 995 "the correct AT_MAC"); 996 997 if (eattr.counter_too_small) { 998 wpa_printf(MSG_DEBUG, "EAP-AKA: Re-authentication response " 999 "included AT_COUNTER_TOO_SMALL - starting full " 1000 "authentication"); 1001 eap_aka_determine_identity(sm, data, 0, 1); 1002 return; 1003 } 1004 1005 if (sm->eap_sim_aka_result_ind && attr->result_ind) { 1006 data->use_result_ind = 1; 1007 data->notification = EAP_SIM_SUCCESS; 1008 eap_aka_state(data, NOTIFICATION); 1009 } else 1010 eap_aka_state(data, SUCCESS); 1011 1012 if (data->reauth) { 1013 identity = data->reauth->identity; 1014 identity_len = data->reauth->identity_len; 1015 } else { 1016 identity = sm->identity; 1017 identity_len = sm->identity_len; 1018 } 1019 1020 id2 = eap_sim_db_get_permanent(sm->eap_sim_db_priv, identity, 1021 identity_len, &id2_len); 1022 if (id2) { 1023 identity = id2; 1024 identity_len = id2_len; 1025 } 1026 1027 if (data->next_pseudonym) { 1028 eap_sim_db_add_pseudonym(sm->eap_sim_db_priv, identity, 1029 identity_len, data->next_pseudonym); 1030 data->next_pseudonym = NULL; 1031 } 1032 if (data->next_reauth_id) { 1033 if (data->eap_method == EAP_TYPE_AKA_PRIME) { 1034 #ifdef EAP_SERVER_AKA_PRIME 1035 eap_sim_db_add_reauth_prime(sm->eap_sim_db_priv, 1036 identity, 1037 identity_len, 1038 data->next_reauth_id, 1039 data->counter + 1, 1040 data->k_encr, data->k_aut, 1041 data->k_re); 1042 #endif /* EAP_SERVER_AKA_PRIME */ 1043 } else { 1044 eap_sim_db_add_reauth(sm->eap_sim_db_priv, identity, 1045 identity_len, 1046 data->next_reauth_id, 1047 data->counter + 1, 1048 data->mk); 1049 } 1050 data->next_reauth_id = NULL; 1051 } else { 1052 eap_sim_db_remove_reauth(sm->eap_sim_db_priv, data->reauth); 1053 data->reauth = NULL; 1054 } 1055 1056 return; 1057 1058 fail: 1059 data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH; 1060 eap_aka_state(data, NOTIFICATION); 1061 eap_sim_db_remove_reauth(sm->eap_sim_db_priv, data->reauth); 1062 data->reauth = NULL; 1063 os_free(decrypted); 1064 } 1065 1066 1067 static void eap_aka_process_client_error(struct eap_sm *sm, 1068 struct eap_aka_data *data, 1069 struct wpabuf *respData, 1070 struct eap_sim_attrs *attr) 1071 { 1072 wpa_printf(MSG_DEBUG, "EAP-AKA: Client reported error %d", 1073 attr->client_error_code); 1074 if (data->notification == EAP_SIM_SUCCESS && data->use_result_ind) 1075 eap_aka_state(data, SUCCESS); 1076 else 1077 eap_aka_state(data, FAILURE); 1078 } 1079 1080 1081 static void eap_aka_process_authentication_reject( 1082 struct eap_sm *sm, struct eap_aka_data *data, 1083 struct wpabuf *respData, struct eap_sim_attrs *attr) 1084 { 1085 wpa_printf(MSG_DEBUG, "EAP-AKA: Client rejected authentication"); 1086 eap_aka_state(data, FAILURE); 1087 } 1088 1089 1090 static void eap_aka_process_notification(struct eap_sm *sm, 1091 struct eap_aka_data *data, 1092 struct wpabuf *respData, 1093 struct eap_sim_attrs *attr) 1094 { 1095 wpa_printf(MSG_DEBUG, "EAP-AKA: Client replied to notification"); 1096 if (data->notification == EAP_SIM_SUCCESS && data->use_result_ind) 1097 eap_aka_state(data, SUCCESS); 1098 else 1099 eap_aka_state(data, FAILURE); 1100 } 1101 1102 1103 static void eap_aka_process(struct eap_sm *sm, void *priv, 1104 struct wpabuf *respData) 1105 { 1106 struct eap_aka_data *data = priv; 1107 const u8 *pos, *end; 1108 u8 subtype; 1109 size_t len; 1110 struct eap_sim_attrs attr; 1111 1112 pos = eap_hdr_validate(EAP_VENDOR_IETF, data->eap_method, respData, 1113 &len); 1114 if (pos == NULL || len < 3) 1115 return; 1116 1117 end = pos + len; 1118 subtype = *pos; 1119 pos += 3; 1120 1121 if (eap_aka_subtype_ok(data, subtype)) { 1122 wpa_printf(MSG_DEBUG, "EAP-AKA: Unrecognized or unexpected " 1123 "EAP-AKA Subtype in EAP Response"); 1124 data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH; 1125 eap_aka_state(data, NOTIFICATION); 1126 return; 1127 } 1128 1129 if (eap_sim_parse_attr(pos, end, &attr, 1130 data->eap_method == EAP_TYPE_AKA_PRIME ? 2 : 1, 1131 0)) { 1132 wpa_printf(MSG_DEBUG, "EAP-AKA: Failed to parse attributes"); 1133 data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH; 1134 eap_aka_state(data, NOTIFICATION); 1135 return; 1136 } 1137 1138 if (subtype == EAP_AKA_SUBTYPE_CLIENT_ERROR) { 1139 eap_aka_process_client_error(sm, data, respData, &attr); 1140 return; 1141 } 1142 1143 if (subtype == EAP_AKA_SUBTYPE_AUTHENTICATION_REJECT) { 1144 eap_aka_process_authentication_reject(sm, data, respData, 1145 &attr); 1146 return; 1147 } 1148 1149 switch (data->state) { 1150 case IDENTITY: 1151 eap_aka_process_identity(sm, data, respData, &attr); 1152 break; 1153 case CHALLENGE: 1154 if (subtype == EAP_AKA_SUBTYPE_SYNCHRONIZATION_FAILURE) { 1155 eap_aka_process_sync_failure(sm, data, respData, 1156 &attr); 1157 } else { 1158 eap_aka_process_challenge(sm, data, respData, &attr); 1159 } 1160 break; 1161 case REAUTH: 1162 eap_aka_process_reauth(sm, data, respData, &attr); 1163 break; 1164 case NOTIFICATION: 1165 eap_aka_process_notification(sm, data, respData, &attr); 1166 break; 1167 default: 1168 wpa_printf(MSG_DEBUG, "EAP-AKA: Unknown state %d in " 1169 "process", data->state); 1170 break; 1171 } 1172 } 1173 1174 1175 static Boolean eap_aka_isDone(struct eap_sm *sm, void *priv) 1176 { 1177 struct eap_aka_data *data = priv; 1178 return data->state == SUCCESS || data->state == FAILURE; 1179 } 1180 1181 1182 static u8 * eap_aka_getKey(struct eap_sm *sm, void *priv, size_t *len) 1183 { 1184 struct eap_aka_data *data = priv; 1185 u8 *key; 1186 1187 if (data->state != SUCCESS) 1188 return NULL; 1189 1190 key = os_malloc(EAP_SIM_KEYING_DATA_LEN); 1191 if (key == NULL) 1192 return NULL; 1193 os_memcpy(key, data->msk, EAP_SIM_KEYING_DATA_LEN); 1194 *len = EAP_SIM_KEYING_DATA_LEN; 1195 return key; 1196 } 1197 1198 1199 static u8 * eap_aka_get_emsk(struct eap_sm *sm, void *priv, size_t *len) 1200 { 1201 struct eap_aka_data *data = priv; 1202 u8 *key; 1203 1204 if (data->state != SUCCESS) 1205 return NULL; 1206 1207 key = os_malloc(EAP_EMSK_LEN); 1208 if (key == NULL) 1209 return NULL; 1210 os_memcpy(key, data->emsk, EAP_EMSK_LEN); 1211 *len = EAP_EMSK_LEN; 1212 return key; 1213 } 1214 1215 1216 static Boolean eap_aka_isSuccess(struct eap_sm *sm, void *priv) 1217 { 1218 struct eap_aka_data *data = priv; 1219 return data->state == SUCCESS; 1220 } 1221 1222 1223 int eap_server_aka_register(void) 1224 { 1225 struct eap_method *eap; 1226 int ret; 1227 1228 eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION, 1229 EAP_VENDOR_IETF, EAP_TYPE_AKA, "AKA"); 1230 if (eap == NULL) 1231 return -1; 1232 1233 eap->init = eap_aka_init; 1234 eap->reset = eap_aka_reset; 1235 eap->buildReq = eap_aka_buildReq; 1236 eap->check = eap_aka_check; 1237 eap->process = eap_aka_process; 1238 eap->isDone = eap_aka_isDone; 1239 eap->getKey = eap_aka_getKey; 1240 eap->isSuccess = eap_aka_isSuccess; 1241 eap->get_emsk = eap_aka_get_emsk; 1242 1243 ret = eap_server_method_register(eap); 1244 if (ret) 1245 eap_server_method_free(eap); 1246 return ret; 1247 } 1248 1249 1250 #ifdef EAP_SERVER_AKA_PRIME 1251 int eap_server_aka_prime_register(void) 1252 { 1253 struct eap_method *eap; 1254 int ret; 1255 1256 eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION, 1257 EAP_VENDOR_IETF, EAP_TYPE_AKA_PRIME, 1258 "AKA'"); 1259 if (eap == NULL) 1260 return -1; 1261 1262 eap->init = eap_aka_prime_init; 1263 eap->reset = eap_aka_reset; 1264 eap->buildReq = eap_aka_buildReq; 1265 eap->check = eap_aka_check; 1266 eap->process = eap_aka_process; 1267 eap->isDone = eap_aka_isDone; 1268 eap->getKey = eap_aka_getKey; 1269 eap->isSuccess = eap_aka_isSuccess; 1270 eap->get_emsk = eap_aka_get_emsk; 1271 1272 ret = eap_server_method_register(eap); 1273 if (ret) 1274 eap_server_method_free(eap); 1275 1276 return ret; 1277 } 1278 #endif /* EAP_SERVER_AKA_PRIME */ 1279