1 /* 2 * hostapd / EAP-SIM (RFC 4186) 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/random.h" 19 #include "eap_server/eap_i.h" 20 #include "eap_common/eap_sim_common.h" 21 #include "eap_server/eap_sim_db.h" 22 23 24 struct eap_sim_data { 25 u8 mk[EAP_SIM_MK_LEN]; 26 u8 nonce_mt[EAP_SIM_NONCE_MT_LEN]; 27 u8 nonce_s[EAP_SIM_NONCE_S_LEN]; 28 u8 k_aut[EAP_SIM_K_AUT_LEN]; 29 u8 k_encr[EAP_SIM_K_ENCR_LEN]; 30 u8 msk[EAP_SIM_KEYING_DATA_LEN]; 31 u8 emsk[EAP_EMSK_LEN]; 32 u8 kc[EAP_SIM_MAX_CHAL][EAP_SIM_KC_LEN]; 33 u8 sres[EAP_SIM_MAX_CHAL][EAP_SIM_SRES_LEN]; 34 u8 rand[EAP_SIM_MAX_CHAL][GSM_RAND_LEN]; 35 int num_chal; 36 enum { 37 START, 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 u16 notification; 44 int use_result_ind; 45 }; 46 47 48 static const char * eap_sim_state_txt(int state) 49 { 50 switch (state) { 51 case START: 52 return "START"; 53 case CHALLENGE: 54 return "CHALLENGE"; 55 case REAUTH: 56 return "REAUTH"; 57 case SUCCESS: 58 return "SUCCESS"; 59 case FAILURE: 60 return "FAILURE"; 61 case NOTIFICATION: 62 return "NOTIFICATION"; 63 default: 64 return "Unknown?!"; 65 } 66 } 67 68 69 static void eap_sim_state(struct eap_sim_data *data, int state) 70 { 71 wpa_printf(MSG_DEBUG, "EAP-SIM: %s -> %s", 72 eap_sim_state_txt(data->state), 73 eap_sim_state_txt(state)); 74 data->state = state; 75 } 76 77 78 static void * eap_sim_init(struct eap_sm *sm) 79 { 80 struct eap_sim_data *data; 81 82 if (sm->eap_sim_db_priv == NULL) { 83 wpa_printf(MSG_WARNING, "EAP-SIM: eap_sim_db not configured"); 84 return NULL; 85 } 86 87 data = os_zalloc(sizeof(*data)); 88 if (data == NULL) 89 return NULL; 90 data->state = START; 91 92 return data; 93 } 94 95 96 static void eap_sim_reset(struct eap_sm *sm, void *priv) 97 { 98 struct eap_sim_data *data = priv; 99 os_free(data->next_pseudonym); 100 os_free(data->next_reauth_id); 101 os_free(data); 102 } 103 104 105 static struct wpabuf * eap_sim_build_start(struct eap_sm *sm, 106 struct eap_sim_data *data, u8 id) 107 { 108 struct eap_sim_msg *msg; 109 u8 ver[2]; 110 111 wpa_printf(MSG_DEBUG, "EAP-SIM: Generating Start"); 112 msg = eap_sim_msg_init(EAP_CODE_REQUEST, id, EAP_TYPE_SIM, 113 EAP_SIM_SUBTYPE_START); 114 if (eap_sim_db_identity_known(sm->eap_sim_db_priv, sm->identity, 115 sm->identity_len)) { 116 wpa_printf(MSG_DEBUG, " AT_PERMANENT_ID_REQ"); 117 eap_sim_msg_add(msg, EAP_SIM_AT_PERMANENT_ID_REQ, 0, NULL, 0); 118 } else { 119 /* 120 * RFC 4186, Chap. 4.2.4 recommends that identity from EAP is 121 * ignored and the SIM/Start is used to request the identity. 122 */ 123 wpa_printf(MSG_DEBUG, " AT_ANY_ID_REQ"); 124 eap_sim_msg_add(msg, EAP_SIM_AT_ANY_ID_REQ, 0, NULL, 0); 125 } 126 wpa_printf(MSG_DEBUG, " AT_VERSION_LIST"); 127 ver[0] = 0; 128 ver[1] = EAP_SIM_VERSION; 129 eap_sim_msg_add(msg, EAP_SIM_AT_VERSION_LIST, sizeof(ver), 130 ver, sizeof(ver)); 131 return eap_sim_msg_finish(msg, NULL, NULL, 0); 132 } 133 134 135 static int eap_sim_build_encr(struct eap_sm *sm, struct eap_sim_data *data, 136 struct eap_sim_msg *msg, u16 counter, 137 const u8 *nonce_s) 138 { 139 os_free(data->next_pseudonym); 140 if (nonce_s == NULL) { 141 data->next_pseudonym = 142 eap_sim_db_get_next_pseudonym(sm->eap_sim_db_priv, 143 EAP_SIM_DB_SIM); 144 } else { 145 /* Do not update pseudonym during re-authentication */ 146 data->next_pseudonym = NULL; 147 } 148 os_free(data->next_reauth_id); 149 if (data->counter <= EAP_SIM_MAX_FAST_REAUTHS) { 150 data->next_reauth_id = 151 eap_sim_db_get_next_reauth_id(sm->eap_sim_db_priv, 152 EAP_SIM_DB_SIM); 153 } else { 154 wpa_printf(MSG_DEBUG, "EAP-SIM: Max fast re-authentication " 155 "count exceeded - force full authentication"); 156 data->next_reauth_id = NULL; 157 } 158 159 if (data->next_pseudonym == NULL && data->next_reauth_id == NULL && 160 counter == 0 && nonce_s == NULL) 161 return 0; 162 163 wpa_printf(MSG_DEBUG, " AT_IV"); 164 wpa_printf(MSG_DEBUG, " AT_ENCR_DATA"); 165 eap_sim_msg_add_encr_start(msg, EAP_SIM_AT_IV, EAP_SIM_AT_ENCR_DATA); 166 167 if (counter > 0) { 168 wpa_printf(MSG_DEBUG, " *AT_COUNTER (%u)", counter); 169 eap_sim_msg_add(msg, EAP_SIM_AT_COUNTER, counter, NULL, 0); 170 } 171 172 if (nonce_s) { 173 wpa_printf(MSG_DEBUG, " *AT_NONCE_S"); 174 eap_sim_msg_add(msg, EAP_SIM_AT_NONCE_S, 0, nonce_s, 175 EAP_SIM_NONCE_S_LEN); 176 } 177 178 if (data->next_pseudonym) { 179 wpa_printf(MSG_DEBUG, " *AT_NEXT_PSEUDONYM (%s)", 180 data->next_pseudonym); 181 eap_sim_msg_add(msg, EAP_SIM_AT_NEXT_PSEUDONYM, 182 os_strlen(data->next_pseudonym), 183 (u8 *) data->next_pseudonym, 184 os_strlen(data->next_pseudonym)); 185 } 186 187 if (data->next_reauth_id) { 188 wpa_printf(MSG_DEBUG, " *AT_NEXT_REAUTH_ID (%s)", 189 data->next_reauth_id); 190 eap_sim_msg_add(msg, EAP_SIM_AT_NEXT_REAUTH_ID, 191 os_strlen(data->next_reauth_id), 192 (u8 *) data->next_reauth_id, 193 os_strlen(data->next_reauth_id)); 194 } 195 196 if (eap_sim_msg_add_encr_end(msg, data->k_encr, EAP_SIM_AT_PADDING)) { 197 wpa_printf(MSG_WARNING, "EAP-SIM: Failed to encrypt " 198 "AT_ENCR_DATA"); 199 return -1; 200 } 201 202 return 0; 203 } 204 205 206 static struct wpabuf * eap_sim_build_challenge(struct eap_sm *sm, 207 struct eap_sim_data *data, 208 u8 id) 209 { 210 struct eap_sim_msg *msg; 211 212 wpa_printf(MSG_DEBUG, "EAP-SIM: Generating Challenge"); 213 msg = eap_sim_msg_init(EAP_CODE_REQUEST, id, EAP_TYPE_SIM, 214 EAP_SIM_SUBTYPE_CHALLENGE); 215 wpa_printf(MSG_DEBUG, " AT_RAND"); 216 eap_sim_msg_add(msg, EAP_SIM_AT_RAND, 0, (u8 *) data->rand, 217 data->num_chal * GSM_RAND_LEN); 218 219 if (eap_sim_build_encr(sm, data, msg, 0, NULL)) { 220 eap_sim_msg_free(msg); 221 return NULL; 222 } 223 224 if (sm->eap_sim_aka_result_ind) { 225 wpa_printf(MSG_DEBUG, " AT_RESULT_IND"); 226 eap_sim_msg_add(msg, EAP_SIM_AT_RESULT_IND, 0, NULL, 0); 227 } 228 229 wpa_printf(MSG_DEBUG, " AT_MAC"); 230 eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC); 231 return eap_sim_msg_finish(msg, data->k_aut, data->nonce_mt, 232 EAP_SIM_NONCE_MT_LEN); 233 } 234 235 236 static struct wpabuf * eap_sim_build_reauth(struct eap_sm *sm, 237 struct eap_sim_data *data, u8 id) 238 { 239 struct eap_sim_msg *msg; 240 241 wpa_printf(MSG_DEBUG, "EAP-SIM: Generating Re-authentication"); 242 243 if (random_get_bytes(data->nonce_s, EAP_SIM_NONCE_S_LEN)) 244 return NULL; 245 wpa_hexdump_key(MSG_MSGDUMP, "EAP-SIM: NONCE_S", 246 data->nonce_s, EAP_SIM_NONCE_S_LEN); 247 248 eap_sim_derive_keys(data->mk, data->k_encr, data->k_aut, data->msk, 249 data->emsk); 250 eap_sim_derive_keys_reauth(data->counter, sm->identity, 251 sm->identity_len, data->nonce_s, data->mk, 252 data->msk, data->emsk); 253 254 msg = eap_sim_msg_init(EAP_CODE_REQUEST, id, EAP_TYPE_SIM, 255 EAP_SIM_SUBTYPE_REAUTHENTICATION); 256 257 if (eap_sim_build_encr(sm, data, msg, data->counter, data->nonce_s)) { 258 eap_sim_msg_free(msg); 259 return NULL; 260 } 261 262 if (sm->eap_sim_aka_result_ind) { 263 wpa_printf(MSG_DEBUG, " AT_RESULT_IND"); 264 eap_sim_msg_add(msg, EAP_SIM_AT_RESULT_IND, 0, NULL, 0); 265 } 266 267 wpa_printf(MSG_DEBUG, " AT_MAC"); 268 eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC); 269 return eap_sim_msg_finish(msg, data->k_aut, NULL, 0); 270 } 271 272 273 static struct wpabuf * eap_sim_build_notification(struct eap_sm *sm, 274 struct eap_sim_data *data, 275 u8 id) 276 { 277 struct eap_sim_msg *msg; 278 279 wpa_printf(MSG_DEBUG, "EAP-SIM: Generating Notification"); 280 msg = eap_sim_msg_init(EAP_CODE_REQUEST, id, EAP_TYPE_SIM, 281 EAP_SIM_SUBTYPE_NOTIFICATION); 282 wpa_printf(MSG_DEBUG, " AT_NOTIFICATION (%d)", data->notification); 283 eap_sim_msg_add(msg, EAP_SIM_AT_NOTIFICATION, data->notification, 284 NULL, 0); 285 if (data->use_result_ind) { 286 if (data->reauth) { 287 wpa_printf(MSG_DEBUG, " AT_IV"); 288 wpa_printf(MSG_DEBUG, " AT_ENCR_DATA"); 289 eap_sim_msg_add_encr_start(msg, EAP_SIM_AT_IV, 290 EAP_SIM_AT_ENCR_DATA); 291 wpa_printf(MSG_DEBUG, " *AT_COUNTER (%u)", 292 data->counter); 293 eap_sim_msg_add(msg, EAP_SIM_AT_COUNTER, data->counter, 294 NULL, 0); 295 296 if (eap_sim_msg_add_encr_end(msg, data->k_encr, 297 EAP_SIM_AT_PADDING)) { 298 wpa_printf(MSG_WARNING, "EAP-SIM: Failed to " 299 "encrypt AT_ENCR_DATA"); 300 eap_sim_msg_free(msg); 301 return NULL; 302 } 303 } 304 305 wpa_printf(MSG_DEBUG, " AT_MAC"); 306 eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC); 307 } 308 return eap_sim_msg_finish(msg, data->k_aut, NULL, 0); 309 } 310 311 312 static struct wpabuf * eap_sim_buildReq(struct eap_sm *sm, void *priv, u8 id) 313 { 314 struct eap_sim_data *data = priv; 315 316 switch (data->state) { 317 case START: 318 return eap_sim_build_start(sm, data, id); 319 case CHALLENGE: 320 return eap_sim_build_challenge(sm, data, id); 321 case REAUTH: 322 return eap_sim_build_reauth(sm, data, id); 323 case NOTIFICATION: 324 return eap_sim_build_notification(sm, data, id); 325 default: 326 wpa_printf(MSG_DEBUG, "EAP-SIM: Unknown state %d in " 327 "buildReq", data->state); 328 break; 329 } 330 return NULL; 331 } 332 333 334 static Boolean eap_sim_check(struct eap_sm *sm, void *priv, 335 struct wpabuf *respData) 336 { 337 struct eap_sim_data *data = priv; 338 const u8 *pos; 339 size_t len; 340 u8 subtype; 341 342 pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_SIM, respData, &len); 343 if (pos == NULL || len < 3) { 344 wpa_printf(MSG_INFO, "EAP-SIM: Invalid frame"); 345 return TRUE; 346 } 347 subtype = *pos; 348 349 if (subtype == EAP_SIM_SUBTYPE_CLIENT_ERROR) 350 return FALSE; 351 352 switch (data->state) { 353 case START: 354 if (subtype != EAP_SIM_SUBTYPE_START) { 355 wpa_printf(MSG_INFO, "EAP-SIM: Unexpected response " 356 "subtype %d", subtype); 357 return TRUE; 358 } 359 break; 360 case CHALLENGE: 361 if (subtype != EAP_SIM_SUBTYPE_CHALLENGE) { 362 wpa_printf(MSG_INFO, "EAP-SIM: Unexpected response " 363 "subtype %d", subtype); 364 return TRUE; 365 } 366 break; 367 case REAUTH: 368 if (subtype != EAP_SIM_SUBTYPE_REAUTHENTICATION) { 369 wpa_printf(MSG_INFO, "EAP-SIM: Unexpected response " 370 "subtype %d", subtype); 371 return TRUE; 372 } 373 break; 374 case NOTIFICATION: 375 if (subtype != EAP_SIM_SUBTYPE_NOTIFICATION) { 376 wpa_printf(MSG_INFO, "EAP-SIM: Unexpected response " 377 "subtype %d", subtype); 378 return TRUE; 379 } 380 break; 381 default: 382 wpa_printf(MSG_INFO, "EAP-SIM: Unexpected state (%d) for " 383 "processing a response", data->state); 384 return TRUE; 385 } 386 387 return FALSE; 388 } 389 390 391 static int eap_sim_supported_ver(struct eap_sim_data *data, int version) 392 { 393 return version == EAP_SIM_VERSION; 394 } 395 396 397 static void eap_sim_process_start(struct eap_sm *sm, 398 struct eap_sim_data *data, 399 struct wpabuf *respData, 400 struct eap_sim_attrs *attr) 401 { 402 const u8 *identity; 403 size_t identity_len; 404 u8 ver_list[2]; 405 406 wpa_printf(MSG_DEBUG, "EAP-SIM: Receive start response"); 407 408 if (attr->identity) { 409 os_free(sm->identity); 410 sm->identity = os_malloc(attr->identity_len); 411 if (sm->identity) { 412 os_memcpy(sm->identity, attr->identity, 413 attr->identity_len); 414 sm->identity_len = attr->identity_len; 415 } 416 } 417 418 identity = NULL; 419 identity_len = 0; 420 421 if (sm->identity && sm->identity_len > 0 && 422 sm->identity[0] == EAP_SIM_PERMANENT_PREFIX) { 423 identity = sm->identity; 424 identity_len = sm->identity_len; 425 } else { 426 identity = eap_sim_db_get_permanent(sm->eap_sim_db_priv, 427 sm->identity, 428 sm->identity_len, 429 &identity_len); 430 if (identity == NULL) { 431 data->reauth = eap_sim_db_get_reauth_entry( 432 sm->eap_sim_db_priv, sm->identity, 433 sm->identity_len); 434 if (data->reauth) { 435 wpa_printf(MSG_DEBUG, "EAP-SIM: Using fast " 436 "re-authentication"); 437 identity = data->reauth->identity; 438 identity_len = data->reauth->identity_len; 439 data->counter = data->reauth->counter; 440 os_memcpy(data->mk, data->reauth->mk, 441 EAP_SIM_MK_LEN); 442 } 443 } 444 } 445 446 if (identity == NULL) { 447 wpa_printf(MSG_DEBUG, "EAP-SIM: Could not get proper permanent" 448 " user name"); 449 eap_sim_state(data, FAILURE); 450 return; 451 } 452 453 wpa_hexdump_ascii(MSG_DEBUG, "EAP-SIM: Identity", 454 identity, identity_len); 455 456 if (data->reauth) { 457 eap_sim_state(data, REAUTH); 458 return; 459 } 460 461 if (attr->nonce_mt == NULL || attr->selected_version < 0) { 462 wpa_printf(MSG_DEBUG, "EAP-SIM: Start/Response missing " 463 "required attributes"); 464 eap_sim_state(data, FAILURE); 465 return; 466 } 467 468 if (!eap_sim_supported_ver(data, attr->selected_version)) { 469 wpa_printf(MSG_DEBUG, "EAP-SIM: Peer selected unsupported " 470 "version %d", attr->selected_version); 471 eap_sim_state(data, FAILURE); 472 return; 473 } 474 475 data->counter = 0; /* reset re-auth counter since this is full auth */ 476 data->reauth = NULL; 477 478 data->num_chal = eap_sim_db_get_gsm_triplets( 479 sm->eap_sim_db_priv, identity, identity_len, 480 EAP_SIM_MAX_CHAL, 481 (u8 *) data->rand, (u8 *) data->kc, (u8 *) data->sres, sm); 482 if (data->num_chal == EAP_SIM_DB_PENDING) { 483 wpa_printf(MSG_DEBUG, "EAP-SIM: GSM authentication triplets " 484 "not yet available - pending request"); 485 sm->method_pending = METHOD_PENDING_WAIT; 486 return; 487 } 488 if (data->num_chal < 2) { 489 wpa_printf(MSG_INFO, "EAP-SIM: Failed to get GSM " 490 "authentication triplets for the peer"); 491 eap_sim_state(data, FAILURE); 492 return; 493 } 494 495 identity_len = sm->identity_len; 496 while (identity_len > 0 && sm->identity[identity_len - 1] == '\0') { 497 wpa_printf(MSG_DEBUG, "EAP-SIM: Workaround - drop last null " 498 "character from identity"); 499 identity_len--; 500 } 501 wpa_hexdump_ascii(MSG_DEBUG, "EAP-SIM: Identity for MK derivation", 502 sm->identity, identity_len); 503 504 os_memcpy(data->nonce_mt, attr->nonce_mt, EAP_SIM_NONCE_MT_LEN); 505 WPA_PUT_BE16(ver_list, EAP_SIM_VERSION); 506 eap_sim_derive_mk(sm->identity, identity_len, attr->nonce_mt, 507 attr->selected_version, ver_list, sizeof(ver_list), 508 data->num_chal, (const u8 *) data->kc, data->mk); 509 eap_sim_derive_keys(data->mk, data->k_encr, data->k_aut, data->msk, 510 data->emsk); 511 512 eap_sim_state(data, CHALLENGE); 513 } 514 515 516 static void eap_sim_process_challenge(struct eap_sm *sm, 517 struct eap_sim_data *data, 518 struct wpabuf *respData, 519 struct eap_sim_attrs *attr) 520 { 521 const u8 *identity; 522 size_t identity_len; 523 524 if (attr->mac == NULL || 525 eap_sim_verify_mac(data->k_aut, respData, attr->mac, 526 (u8 *) data->sres, 527 data->num_chal * EAP_SIM_SRES_LEN)) { 528 wpa_printf(MSG_WARNING, "EAP-SIM: Challenge message " 529 "did not include valid AT_MAC"); 530 eap_sim_state(data, FAILURE); 531 return; 532 } 533 534 wpa_printf(MSG_DEBUG, "EAP-SIM: Challenge response includes the " 535 "correct AT_MAC"); 536 if (sm->eap_sim_aka_result_ind && attr->result_ind) { 537 data->use_result_ind = 1; 538 data->notification = EAP_SIM_SUCCESS; 539 eap_sim_state(data, NOTIFICATION); 540 } else 541 eap_sim_state(data, SUCCESS); 542 543 identity = eap_sim_db_get_permanent(sm->eap_sim_db_priv, sm->identity, 544 sm->identity_len, &identity_len); 545 if (identity == NULL) { 546 identity = sm->identity; 547 identity_len = sm->identity_len; 548 } 549 550 if (data->next_pseudonym) { 551 eap_sim_db_add_pseudonym(sm->eap_sim_db_priv, identity, 552 identity_len, 553 data->next_pseudonym); 554 data->next_pseudonym = NULL; 555 } 556 if (data->next_reauth_id) { 557 eap_sim_db_add_reauth(sm->eap_sim_db_priv, identity, 558 identity_len, 559 data->next_reauth_id, data->counter + 1, 560 data->mk); 561 data->next_reauth_id = NULL; 562 } 563 } 564 565 566 static void eap_sim_process_reauth(struct eap_sm *sm, 567 struct eap_sim_data *data, 568 struct wpabuf *respData, 569 struct eap_sim_attrs *attr) 570 { 571 struct eap_sim_attrs eattr; 572 u8 *decrypted = NULL; 573 const u8 *identity, *id2; 574 size_t identity_len, id2_len; 575 576 if (attr->mac == NULL || 577 eap_sim_verify_mac(data->k_aut, respData, attr->mac, data->nonce_s, 578 EAP_SIM_NONCE_S_LEN)) { 579 wpa_printf(MSG_WARNING, "EAP-SIM: Re-authentication message " 580 "did not include valid AT_MAC"); 581 goto fail; 582 } 583 584 if (attr->encr_data == NULL || attr->iv == NULL) { 585 wpa_printf(MSG_WARNING, "EAP-SIM: Reauthentication " 586 "message did not include encrypted data"); 587 goto fail; 588 } 589 590 decrypted = eap_sim_parse_encr(data->k_encr, attr->encr_data, 591 attr->encr_data_len, attr->iv, &eattr, 592 0); 593 if (decrypted == NULL) { 594 wpa_printf(MSG_WARNING, "EAP-SIM: Failed to parse encrypted " 595 "data from reauthentication message"); 596 goto fail; 597 } 598 599 if (eattr.counter != data->counter) { 600 wpa_printf(MSG_WARNING, "EAP-SIM: Re-authentication message " 601 "used incorrect counter %u, expected %u", 602 eattr.counter, data->counter); 603 goto fail; 604 } 605 os_free(decrypted); 606 decrypted = NULL; 607 608 wpa_printf(MSG_DEBUG, "EAP-SIM: Re-authentication response includes " 609 "the correct AT_MAC"); 610 if (sm->eap_sim_aka_result_ind && attr->result_ind) { 611 data->use_result_ind = 1; 612 data->notification = EAP_SIM_SUCCESS; 613 eap_sim_state(data, NOTIFICATION); 614 } else 615 eap_sim_state(data, SUCCESS); 616 617 if (data->reauth) { 618 identity = data->reauth->identity; 619 identity_len = data->reauth->identity_len; 620 } else { 621 identity = sm->identity; 622 identity_len = sm->identity_len; 623 } 624 625 id2 = eap_sim_db_get_permanent(sm->eap_sim_db_priv, identity, 626 identity_len, &id2_len); 627 if (id2) { 628 identity = id2; 629 identity_len = id2_len; 630 } 631 632 if (data->next_reauth_id) { 633 eap_sim_db_add_reauth(sm->eap_sim_db_priv, identity, 634 identity_len, data->next_reauth_id, 635 data->counter + 1, data->mk); 636 data->next_reauth_id = NULL; 637 } else { 638 eap_sim_db_remove_reauth(sm->eap_sim_db_priv, data->reauth); 639 data->reauth = NULL; 640 } 641 642 return; 643 644 fail: 645 eap_sim_state(data, FAILURE); 646 eap_sim_db_remove_reauth(sm->eap_sim_db_priv, data->reauth); 647 data->reauth = NULL; 648 os_free(decrypted); 649 } 650 651 652 static void eap_sim_process_client_error(struct eap_sm *sm, 653 struct eap_sim_data *data, 654 struct wpabuf *respData, 655 struct eap_sim_attrs *attr) 656 { 657 wpa_printf(MSG_DEBUG, "EAP-SIM: Client reported error %d", 658 attr->client_error_code); 659 if (data->notification == EAP_SIM_SUCCESS && data->use_result_ind) 660 eap_sim_state(data, SUCCESS); 661 else 662 eap_sim_state(data, FAILURE); 663 } 664 665 666 static void eap_sim_process_notification(struct eap_sm *sm, 667 struct eap_sim_data *data, 668 struct wpabuf *respData, 669 struct eap_sim_attrs *attr) 670 { 671 wpa_printf(MSG_DEBUG, "EAP-SIM: Client replied to notification"); 672 if (data->notification == EAP_SIM_SUCCESS && data->use_result_ind) 673 eap_sim_state(data, SUCCESS); 674 else 675 eap_sim_state(data, FAILURE); 676 } 677 678 679 static void eap_sim_process(struct eap_sm *sm, void *priv, 680 struct wpabuf *respData) 681 { 682 struct eap_sim_data *data = priv; 683 const u8 *pos, *end; 684 u8 subtype; 685 size_t len; 686 struct eap_sim_attrs attr; 687 688 pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_SIM, respData, &len); 689 if (pos == NULL || len < 3) 690 return; 691 692 end = pos + len; 693 subtype = *pos; 694 pos += 3; 695 696 if (eap_sim_parse_attr(pos, end, &attr, 0, 0)) { 697 wpa_printf(MSG_DEBUG, "EAP-SIM: Failed to parse attributes"); 698 eap_sim_state(data, FAILURE); 699 return; 700 } 701 702 if (subtype == EAP_SIM_SUBTYPE_CLIENT_ERROR) { 703 eap_sim_process_client_error(sm, data, respData, &attr); 704 return; 705 } 706 707 switch (data->state) { 708 case START: 709 eap_sim_process_start(sm, data, respData, &attr); 710 break; 711 case CHALLENGE: 712 eap_sim_process_challenge(sm, data, respData, &attr); 713 break; 714 case REAUTH: 715 eap_sim_process_reauth(sm, data, respData, &attr); 716 break; 717 case NOTIFICATION: 718 eap_sim_process_notification(sm, data, respData, &attr); 719 break; 720 default: 721 wpa_printf(MSG_DEBUG, "EAP-SIM: Unknown state %d in " 722 "process", data->state); 723 break; 724 } 725 } 726 727 728 static Boolean eap_sim_isDone(struct eap_sm *sm, void *priv) 729 { 730 struct eap_sim_data *data = priv; 731 return data->state == SUCCESS || data->state == FAILURE; 732 } 733 734 735 static u8 * eap_sim_getKey(struct eap_sm *sm, void *priv, size_t *len) 736 { 737 struct eap_sim_data *data = priv; 738 u8 *key; 739 740 if (data->state != SUCCESS) 741 return NULL; 742 743 key = os_malloc(EAP_SIM_KEYING_DATA_LEN); 744 if (key == NULL) 745 return NULL; 746 os_memcpy(key, data->msk, EAP_SIM_KEYING_DATA_LEN); 747 *len = EAP_SIM_KEYING_DATA_LEN; 748 return key; 749 } 750 751 752 static u8 * eap_sim_get_emsk(struct eap_sm *sm, void *priv, size_t *len) 753 { 754 struct eap_sim_data *data = priv; 755 u8 *key; 756 757 if (data->state != SUCCESS) 758 return NULL; 759 760 key = os_malloc(EAP_EMSK_LEN); 761 if (key == NULL) 762 return NULL; 763 os_memcpy(key, data->emsk, EAP_EMSK_LEN); 764 *len = EAP_EMSK_LEN; 765 return key; 766 } 767 768 769 static Boolean eap_sim_isSuccess(struct eap_sm *sm, void *priv) 770 { 771 struct eap_sim_data *data = priv; 772 return data->state == SUCCESS; 773 } 774 775 776 int eap_server_sim_register(void) 777 { 778 struct eap_method *eap; 779 int ret; 780 781 eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION, 782 EAP_VENDOR_IETF, EAP_TYPE_SIM, "SIM"); 783 if (eap == NULL) 784 return -1; 785 786 eap->init = eap_sim_init; 787 eap->reset = eap_sim_reset; 788 eap->buildReq = eap_sim_buildReq; 789 eap->check = eap_sim_check; 790 eap->process = eap_sim_process; 791 eap->isDone = eap_sim_isDone; 792 eap->getKey = eap_sim_getKey; 793 eap->isSuccess = eap_sim_isSuccess; 794 eap->get_emsk = eap_sim_get_emsk; 795 796 ret = eap_server_method_register(eap); 797 if (ret) 798 eap_server_method_free(eap); 799 return ret; 800 } 801