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