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