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, 0); 143 } else { 144 /* Do not update pseudonym during re-authentication */ 145 data->next_pseudonym = NULL; 146 } 147 os_free(data->next_reauth_id); 148 if (data->counter <= EAP_SIM_MAX_FAST_REAUTHS) { 149 data->next_reauth_id = 150 eap_sim_db_get_next_reauth_id(sm->eap_sim_db_priv, 0); 151 } else { 152 wpa_printf(MSG_DEBUG, "EAP-SIM: Max fast re-authentication " 153 "count exceeded - force full authentication"); 154 data->next_reauth_id = NULL; 155 } 156 157 if (data->next_pseudonym == NULL && data->next_reauth_id == NULL && 158 counter == 0 && nonce_s == NULL) 159 return 0; 160 161 wpa_printf(MSG_DEBUG, " AT_IV"); 162 wpa_printf(MSG_DEBUG, " AT_ENCR_DATA"); 163 eap_sim_msg_add_encr_start(msg, EAP_SIM_AT_IV, EAP_SIM_AT_ENCR_DATA); 164 165 if (counter > 0) { 166 wpa_printf(MSG_DEBUG, " *AT_COUNTER (%u)", counter); 167 eap_sim_msg_add(msg, EAP_SIM_AT_COUNTER, counter, NULL, 0); 168 } 169 170 if (nonce_s) { 171 wpa_printf(MSG_DEBUG, " *AT_NONCE_S"); 172 eap_sim_msg_add(msg, EAP_SIM_AT_NONCE_S, 0, nonce_s, 173 EAP_SIM_NONCE_S_LEN); 174 } 175 176 if (data->next_pseudonym) { 177 wpa_printf(MSG_DEBUG, " *AT_NEXT_PSEUDONYM (%s)", 178 data->next_pseudonym); 179 eap_sim_msg_add(msg, EAP_SIM_AT_NEXT_PSEUDONYM, 180 os_strlen(data->next_pseudonym), 181 (u8 *) data->next_pseudonym, 182 os_strlen(data->next_pseudonym)); 183 } 184 185 if (data->next_reauth_id) { 186 wpa_printf(MSG_DEBUG, " *AT_NEXT_REAUTH_ID (%s)", 187 data->next_reauth_id); 188 eap_sim_msg_add(msg, EAP_SIM_AT_NEXT_REAUTH_ID, 189 os_strlen(data->next_reauth_id), 190 (u8 *) data->next_reauth_id, 191 os_strlen(data->next_reauth_id)); 192 } 193 194 if (eap_sim_msg_add_encr_end(msg, data->k_encr, EAP_SIM_AT_PADDING)) { 195 wpa_printf(MSG_WARNING, "EAP-SIM: Failed to encrypt " 196 "AT_ENCR_DATA"); 197 return -1; 198 } 199 200 return 0; 201 } 202 203 204 static struct wpabuf * eap_sim_build_challenge(struct eap_sm *sm, 205 struct eap_sim_data *data, 206 u8 id) 207 { 208 struct eap_sim_msg *msg; 209 210 wpa_printf(MSG_DEBUG, "EAP-SIM: Generating Challenge"); 211 msg = eap_sim_msg_init(EAP_CODE_REQUEST, id, EAP_TYPE_SIM, 212 EAP_SIM_SUBTYPE_CHALLENGE); 213 wpa_printf(MSG_DEBUG, " AT_RAND"); 214 eap_sim_msg_add(msg, EAP_SIM_AT_RAND, 0, (u8 *) data->rand, 215 data->num_chal * GSM_RAND_LEN); 216 217 if (eap_sim_build_encr(sm, data, msg, 0, NULL)) { 218 eap_sim_msg_free(msg); 219 return NULL; 220 } 221 222 if (sm->eap_sim_aka_result_ind) { 223 wpa_printf(MSG_DEBUG, " AT_RESULT_IND"); 224 eap_sim_msg_add(msg, EAP_SIM_AT_RESULT_IND, 0, NULL, 0); 225 } 226 227 wpa_printf(MSG_DEBUG, " AT_MAC"); 228 eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC); 229 return eap_sim_msg_finish(msg, data->k_aut, data->nonce_mt, 230 EAP_SIM_NONCE_MT_LEN); 231 } 232 233 234 static struct wpabuf * eap_sim_build_reauth(struct eap_sm *sm, 235 struct eap_sim_data *data, u8 id) 236 { 237 struct eap_sim_msg *msg; 238 239 wpa_printf(MSG_DEBUG, "EAP-SIM: Generating Re-authentication"); 240 241 if (random_get_bytes(data->nonce_s, EAP_SIM_NONCE_S_LEN)) 242 return NULL; 243 wpa_hexdump_key(MSG_MSGDUMP, "EAP-SIM: NONCE_S", 244 data->nonce_s, EAP_SIM_NONCE_S_LEN); 245 246 eap_sim_derive_keys(data->mk, data->k_encr, data->k_aut, data->msk, 247 data->emsk); 248 eap_sim_derive_keys_reauth(data->counter, sm->identity, 249 sm->identity_len, data->nonce_s, data->mk, 250 data->msk, data->emsk); 251 252 msg = eap_sim_msg_init(EAP_CODE_REQUEST, id, EAP_TYPE_SIM, 253 EAP_SIM_SUBTYPE_REAUTHENTICATION); 254 255 if (eap_sim_build_encr(sm, data, msg, data->counter, data->nonce_s)) { 256 eap_sim_msg_free(msg); 257 return NULL; 258 } 259 260 if (sm->eap_sim_aka_result_ind) { 261 wpa_printf(MSG_DEBUG, " AT_RESULT_IND"); 262 eap_sim_msg_add(msg, EAP_SIM_AT_RESULT_IND, 0, NULL, 0); 263 } 264 265 wpa_printf(MSG_DEBUG, " AT_MAC"); 266 eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC); 267 return eap_sim_msg_finish(msg, data->k_aut, NULL, 0); 268 } 269 270 271 static struct wpabuf * eap_sim_build_notification(struct eap_sm *sm, 272 struct eap_sim_data *data, 273 u8 id) 274 { 275 struct eap_sim_msg *msg; 276 277 wpa_printf(MSG_DEBUG, "EAP-SIM: Generating Notification"); 278 msg = eap_sim_msg_init(EAP_CODE_REQUEST, id, EAP_TYPE_SIM, 279 EAP_SIM_SUBTYPE_NOTIFICATION); 280 wpa_printf(MSG_DEBUG, " AT_NOTIFICATION (%d)", data->notification); 281 eap_sim_msg_add(msg, EAP_SIM_AT_NOTIFICATION, data->notification, 282 NULL, 0); 283 if (data->use_result_ind) { 284 if (data->reauth) { 285 wpa_printf(MSG_DEBUG, " AT_IV"); 286 wpa_printf(MSG_DEBUG, " AT_ENCR_DATA"); 287 eap_sim_msg_add_encr_start(msg, EAP_SIM_AT_IV, 288 EAP_SIM_AT_ENCR_DATA); 289 wpa_printf(MSG_DEBUG, " *AT_COUNTER (%u)", 290 data->counter); 291 eap_sim_msg_add(msg, EAP_SIM_AT_COUNTER, data->counter, 292 NULL, 0); 293 294 if (eap_sim_msg_add_encr_end(msg, data->k_encr, 295 EAP_SIM_AT_PADDING)) { 296 wpa_printf(MSG_WARNING, "EAP-SIM: Failed to " 297 "encrypt AT_ENCR_DATA"); 298 eap_sim_msg_free(msg); 299 return NULL; 300 } 301 } 302 303 wpa_printf(MSG_DEBUG, " AT_MAC"); 304 eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC); 305 } 306 return eap_sim_msg_finish(msg, data->k_aut, NULL, 0); 307 } 308 309 310 static struct wpabuf * eap_sim_buildReq(struct eap_sm *sm, void *priv, u8 id) 311 { 312 struct eap_sim_data *data = priv; 313 314 switch (data->state) { 315 case START: 316 return eap_sim_build_start(sm, data, id); 317 case CHALLENGE: 318 return eap_sim_build_challenge(sm, data, id); 319 case REAUTH: 320 return eap_sim_build_reauth(sm, data, id); 321 case NOTIFICATION: 322 return eap_sim_build_notification(sm, data, id); 323 default: 324 wpa_printf(MSG_DEBUG, "EAP-SIM: Unknown state %d in " 325 "buildReq", data->state); 326 break; 327 } 328 return NULL; 329 } 330 331 332 static Boolean eap_sim_check(struct eap_sm *sm, void *priv, 333 struct wpabuf *respData) 334 { 335 struct eap_sim_data *data = priv; 336 const u8 *pos; 337 size_t len; 338 u8 subtype; 339 340 pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_SIM, respData, &len); 341 if (pos == NULL || len < 3) { 342 wpa_printf(MSG_INFO, "EAP-SIM: Invalid frame"); 343 return TRUE; 344 } 345 subtype = *pos; 346 347 if (subtype == EAP_SIM_SUBTYPE_CLIENT_ERROR) 348 return FALSE; 349 350 switch (data->state) { 351 case START: 352 if (subtype != EAP_SIM_SUBTYPE_START) { 353 wpa_printf(MSG_INFO, "EAP-SIM: Unexpected response " 354 "subtype %d", subtype); 355 return TRUE; 356 } 357 break; 358 case CHALLENGE: 359 if (subtype != EAP_SIM_SUBTYPE_CHALLENGE) { 360 wpa_printf(MSG_INFO, "EAP-SIM: Unexpected response " 361 "subtype %d", subtype); 362 return TRUE; 363 } 364 break; 365 case REAUTH: 366 if (subtype != EAP_SIM_SUBTYPE_REAUTHENTICATION) { 367 wpa_printf(MSG_INFO, "EAP-SIM: Unexpected response " 368 "subtype %d", subtype); 369 return TRUE; 370 } 371 break; 372 case NOTIFICATION: 373 if (subtype != EAP_SIM_SUBTYPE_NOTIFICATION) { 374 wpa_printf(MSG_INFO, "EAP-SIM: Unexpected response " 375 "subtype %d", subtype); 376 return TRUE; 377 } 378 break; 379 default: 380 wpa_printf(MSG_INFO, "EAP-SIM: Unexpected state (%d) for " 381 "processing a response", data->state); 382 return TRUE; 383 } 384 385 return FALSE; 386 } 387 388 389 static int eap_sim_supported_ver(struct eap_sim_data *data, int version) 390 { 391 return version == EAP_SIM_VERSION; 392 } 393 394 395 static void eap_sim_process_start(struct eap_sm *sm, 396 struct eap_sim_data *data, 397 struct wpabuf *respData, 398 struct eap_sim_attrs *attr) 399 { 400 const u8 *identity; 401 size_t identity_len; 402 u8 ver_list[2]; 403 404 wpa_printf(MSG_DEBUG, "EAP-SIM: Receive start response"); 405 406 if (attr->identity) { 407 os_free(sm->identity); 408 sm->identity = os_malloc(attr->identity_len); 409 if (sm->identity) { 410 os_memcpy(sm->identity, attr->identity, 411 attr->identity_len); 412 sm->identity_len = attr->identity_len; 413 } 414 } 415 416 identity = NULL; 417 identity_len = 0; 418 419 if (sm->identity && sm->identity_len > 0 && 420 sm->identity[0] == EAP_SIM_PERMANENT_PREFIX) { 421 identity = sm->identity; 422 identity_len = sm->identity_len; 423 } else { 424 identity = eap_sim_db_get_permanent(sm->eap_sim_db_priv, 425 sm->identity, 426 sm->identity_len, 427 &identity_len); 428 if (identity == NULL) { 429 data->reauth = eap_sim_db_get_reauth_entry( 430 sm->eap_sim_db_priv, sm->identity, 431 sm->identity_len); 432 if (data->reauth) { 433 wpa_printf(MSG_DEBUG, "EAP-SIM: Using fast " 434 "re-authentication"); 435 identity = data->reauth->identity; 436 identity_len = data->reauth->identity_len; 437 data->counter = data->reauth->counter; 438 os_memcpy(data->mk, data->reauth->mk, 439 EAP_SIM_MK_LEN); 440 } 441 } 442 } 443 444 if (identity == NULL) { 445 wpa_printf(MSG_DEBUG, "EAP-SIM: Could not get proper permanent" 446 " user name"); 447 eap_sim_state(data, FAILURE); 448 return; 449 } 450 451 wpa_hexdump_ascii(MSG_DEBUG, "EAP-SIM: Identity", 452 identity, identity_len); 453 454 if (data->reauth) { 455 eap_sim_state(data, REAUTH); 456 return; 457 } 458 459 if (attr->nonce_mt == NULL || attr->selected_version < 0) { 460 wpa_printf(MSG_DEBUG, "EAP-SIM: Start/Response missing " 461 "required attributes"); 462 eap_sim_state(data, FAILURE); 463 return; 464 } 465 466 if (!eap_sim_supported_ver(data, attr->selected_version)) { 467 wpa_printf(MSG_DEBUG, "EAP-SIM: Peer selected unsupported " 468 "version %d", attr->selected_version); 469 eap_sim_state(data, FAILURE); 470 return; 471 } 472 473 data->counter = 0; /* reset re-auth counter since this is full auth */ 474 data->reauth = NULL; 475 476 data->num_chal = eap_sim_db_get_gsm_triplets( 477 sm->eap_sim_db_priv, identity, identity_len, 478 EAP_SIM_MAX_CHAL, 479 (u8 *) data->rand, (u8 *) data->kc, (u8 *) data->sres, sm); 480 if (data->num_chal == EAP_SIM_DB_PENDING) { 481 wpa_printf(MSG_DEBUG, "EAP-SIM: GSM authentication triplets " 482 "not yet available - pending request"); 483 sm->method_pending = METHOD_PENDING_WAIT; 484 return; 485 } 486 if (data->num_chal < 2) { 487 wpa_printf(MSG_INFO, "EAP-SIM: Failed to get GSM " 488 "authentication triplets for the peer"); 489 eap_sim_state(data, FAILURE); 490 return; 491 } 492 493 identity_len = sm->identity_len; 494 while (identity_len > 0 && sm->identity[identity_len - 1] == '\0') { 495 wpa_printf(MSG_DEBUG, "EAP-SIM: Workaround - drop last null " 496 "character from identity"); 497 identity_len--; 498 } 499 wpa_hexdump_ascii(MSG_DEBUG, "EAP-SIM: Identity for MK derivation", 500 sm->identity, identity_len); 501 502 os_memcpy(data->nonce_mt, attr->nonce_mt, EAP_SIM_NONCE_MT_LEN); 503 WPA_PUT_BE16(ver_list, EAP_SIM_VERSION); 504 eap_sim_derive_mk(sm->identity, identity_len, attr->nonce_mt, 505 attr->selected_version, ver_list, sizeof(ver_list), 506 data->num_chal, (const u8 *) data->kc, data->mk); 507 eap_sim_derive_keys(data->mk, data->k_encr, data->k_aut, data->msk, 508 data->emsk); 509 510 eap_sim_state(data, CHALLENGE); 511 } 512 513 514 static void eap_sim_process_challenge(struct eap_sm *sm, 515 struct eap_sim_data *data, 516 struct wpabuf *respData, 517 struct eap_sim_attrs *attr) 518 { 519 const u8 *identity; 520 size_t identity_len; 521 522 if (attr->mac == NULL || 523 eap_sim_verify_mac(data->k_aut, respData, attr->mac, 524 (u8 *) data->sres, 525 data->num_chal * EAP_SIM_SRES_LEN)) { 526 wpa_printf(MSG_WARNING, "EAP-SIM: Challenge message " 527 "did not include valid AT_MAC"); 528 eap_sim_state(data, FAILURE); 529 return; 530 } 531 532 wpa_printf(MSG_DEBUG, "EAP-SIM: Challenge response includes the " 533 "correct AT_MAC"); 534 if (sm->eap_sim_aka_result_ind && attr->result_ind) { 535 data->use_result_ind = 1; 536 data->notification = EAP_SIM_SUCCESS; 537 eap_sim_state(data, NOTIFICATION); 538 } else 539 eap_sim_state(data, SUCCESS); 540 541 identity = eap_sim_db_get_permanent(sm->eap_sim_db_priv, sm->identity, 542 sm->identity_len, &identity_len); 543 if (identity == NULL) { 544 identity = sm->identity; 545 identity_len = sm->identity_len; 546 } 547 548 if (data->next_pseudonym) { 549 eap_sim_db_add_pseudonym(sm->eap_sim_db_priv, identity, 550 identity_len, 551 data->next_pseudonym); 552 data->next_pseudonym = NULL; 553 } 554 if (data->next_reauth_id) { 555 eap_sim_db_add_reauth(sm->eap_sim_db_priv, identity, 556 identity_len, 557 data->next_reauth_id, data->counter + 1, 558 data->mk); 559 data->next_reauth_id = NULL; 560 } 561 } 562 563 564 static void eap_sim_process_reauth(struct eap_sm *sm, 565 struct eap_sim_data *data, 566 struct wpabuf *respData, 567 struct eap_sim_attrs *attr) 568 { 569 struct eap_sim_attrs eattr; 570 u8 *decrypted = NULL; 571 const u8 *identity, *id2; 572 size_t identity_len, id2_len; 573 574 if (attr->mac == NULL || 575 eap_sim_verify_mac(data->k_aut, respData, attr->mac, data->nonce_s, 576 EAP_SIM_NONCE_S_LEN)) { 577 wpa_printf(MSG_WARNING, "EAP-SIM: Re-authentication message " 578 "did not include valid AT_MAC"); 579 goto fail; 580 } 581 582 if (attr->encr_data == NULL || attr->iv == NULL) { 583 wpa_printf(MSG_WARNING, "EAP-SIM: Reauthentication " 584 "message did not include encrypted data"); 585 goto fail; 586 } 587 588 decrypted = eap_sim_parse_encr(data->k_encr, attr->encr_data, 589 attr->encr_data_len, attr->iv, &eattr, 590 0); 591 if (decrypted == NULL) { 592 wpa_printf(MSG_WARNING, "EAP-SIM: Failed to parse encrypted " 593 "data from reauthentication message"); 594 goto fail; 595 } 596 597 if (eattr.counter != data->counter) { 598 wpa_printf(MSG_WARNING, "EAP-SIM: Re-authentication message " 599 "used incorrect counter %u, expected %u", 600 eattr.counter, data->counter); 601 goto fail; 602 } 603 os_free(decrypted); 604 decrypted = NULL; 605 606 wpa_printf(MSG_DEBUG, "EAP-SIM: Re-authentication response includes " 607 "the correct AT_MAC"); 608 if (sm->eap_sim_aka_result_ind && attr->result_ind) { 609 data->use_result_ind = 1; 610 data->notification = EAP_SIM_SUCCESS; 611 eap_sim_state(data, NOTIFICATION); 612 } else 613 eap_sim_state(data, SUCCESS); 614 615 if (data->reauth) { 616 identity = data->reauth->identity; 617 identity_len = data->reauth->identity_len; 618 } else { 619 identity = sm->identity; 620 identity_len = sm->identity_len; 621 } 622 623 id2 = eap_sim_db_get_permanent(sm->eap_sim_db_priv, identity, 624 identity_len, &id2_len); 625 if (id2) { 626 identity = id2; 627 identity_len = id2_len; 628 } 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