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