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