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