00001
00016 #include "includes.h"
00017
00018 #include "common.h"
00019 #include "eap_server/eap_i.h"
00020 #include "eap_common/eap_sim_common.h"
00021 #include "eap_server/eap_sim_db.h"
00022
00023
00024 struct eap_sim_data {
00025 u8 mk[EAP_SIM_MK_LEN];
00026 u8 nonce_mt[EAP_SIM_NONCE_MT_LEN];
00027 u8 nonce_s[EAP_SIM_NONCE_S_LEN];
00028 u8 k_aut[EAP_SIM_K_AUT_LEN];
00029 u8 k_encr[EAP_SIM_K_ENCR_LEN];
00030 u8 msk[EAP_SIM_KEYING_DATA_LEN];
00031 u8 emsk[EAP_EMSK_LEN];
00032 u8 kc[EAP_SIM_MAX_CHAL][EAP_SIM_KC_LEN];
00033 u8 sres[EAP_SIM_MAX_CHAL][EAP_SIM_SRES_LEN];
00034 u8 rand[EAP_SIM_MAX_CHAL][GSM_RAND_LEN];
00035 int num_chal;
00036 enum {
00037 START, CHALLENGE, REAUTH, NOTIFICATION, SUCCESS, FAILURE
00038 } state;
00039 char *next_pseudonym;
00040 char *next_reauth_id;
00041 u16 counter;
00042 struct eap_sim_reauth *reauth;
00043 u16 notification;
00044 int use_result_ind;
00045 };
00046
00047
00048 static const char * eap_sim_state_txt(int state)
00049 {
00050 switch (state) {
00051 case START:
00052 return "START";
00053 case CHALLENGE:
00054 return "CHALLENGE";
00055 case REAUTH:
00056 return "REAUTH";
00057 case SUCCESS:
00058 return "SUCCESS";
00059 case FAILURE:
00060 return "FAILURE";
00061 case NOTIFICATION:
00062 return "NOTIFICATION";
00063 default:
00064 return "Unknown?!";
00065 }
00066 }
00067
00068
00069 static void eap_sim_state(struct eap_sim_data *data, int state)
00070 {
00071 wpa_printf(MSG_DEBUG, "EAP-SIM: %s -> %s",
00072 eap_sim_state_txt(data->state),
00073 eap_sim_state_txt(state));
00074 data->state = state;
00075 }
00076
00077
00078 static void * eap_sim_init(struct eap_sm *sm)
00079 {
00080 struct eap_sim_data *data;
00081
00082 if (sm->eap_sim_db_priv == NULL) {
00083 wpa_printf(MSG_WARNING, "EAP-SIM: eap_sim_db not configured");
00084 return NULL;
00085 }
00086
00087 data = os_zalloc(sizeof(*data));
00088 if (data == NULL)
00089 return NULL;
00090 data->state = START;
00091
00092 return data;
00093 }
00094
00095
00096 static void eap_sim_reset(struct eap_sm *sm, void *priv)
00097 {
00098 struct eap_sim_data *data = priv;
00099 os_free(data->next_pseudonym);
00100 os_free(data->next_reauth_id);
00101 os_free(data);
00102 }
00103
00104
00105 static struct wpabuf * eap_sim_build_start(struct eap_sm *sm,
00106 struct eap_sim_data *data, u8 id)
00107 {
00108 struct eap_sim_msg *msg;
00109 u8 ver[2];
00110
00111 wpa_printf(MSG_DEBUG, "EAP-SIM: Generating Start");
00112 msg = eap_sim_msg_init(EAP_CODE_REQUEST, id, EAP_TYPE_SIM,
00113 EAP_SIM_SUBTYPE_START);
00114 if (eap_sim_db_identity_known(sm->eap_sim_db_priv, sm->identity,
00115 sm->identity_len)) {
00116 wpa_printf(MSG_DEBUG, " AT_PERMANENT_ID_REQ");
00117 eap_sim_msg_add(msg, EAP_SIM_AT_PERMANENT_ID_REQ, 0, NULL, 0);
00118 } else {
00119
00120
00121
00122
00123 wpa_printf(MSG_DEBUG, " AT_ANY_ID_REQ");
00124 eap_sim_msg_add(msg, EAP_SIM_AT_ANY_ID_REQ, 0, NULL, 0);
00125 }
00126 wpa_printf(MSG_DEBUG, " AT_VERSION_LIST");
00127 ver[0] = 0;
00128 ver[1] = EAP_SIM_VERSION;
00129 eap_sim_msg_add(msg, EAP_SIM_AT_VERSION_LIST, sizeof(ver),
00130 ver, sizeof(ver));
00131 return eap_sim_msg_finish(msg, NULL, NULL, 0);
00132 }
00133
00134
00135 static int eap_sim_build_encr(struct eap_sm *sm, struct eap_sim_data *data,
00136 struct eap_sim_msg *msg, u16 counter,
00137 const u8 *nonce_s)
00138 {
00139 os_free(data->next_pseudonym);
00140 data->next_pseudonym =
00141 eap_sim_db_get_next_pseudonym(sm->eap_sim_db_priv, 0);
00142 os_free(data->next_reauth_id);
00143 if (data->counter <= EAP_SIM_MAX_FAST_REAUTHS) {
00144 data->next_reauth_id =
00145 eap_sim_db_get_next_reauth_id(sm->eap_sim_db_priv, 0);
00146 } else {
00147 wpa_printf(MSG_DEBUG, "EAP-SIM: Max fast re-authentication "
00148 "count exceeded - force full authentication");
00149 data->next_reauth_id = NULL;
00150 }
00151
00152 if (data->next_pseudonym == NULL && data->next_reauth_id == NULL &&
00153 counter == 0 && nonce_s == NULL)
00154 return 0;
00155
00156 wpa_printf(MSG_DEBUG, " AT_IV");
00157 wpa_printf(MSG_DEBUG, " AT_ENCR_DATA");
00158 eap_sim_msg_add_encr_start(msg, EAP_SIM_AT_IV, EAP_SIM_AT_ENCR_DATA);
00159
00160 if (counter > 0) {
00161 wpa_printf(MSG_DEBUG, " *AT_COUNTER (%u)", counter);
00162 eap_sim_msg_add(msg, EAP_SIM_AT_COUNTER, counter, NULL, 0);
00163 }
00164
00165 if (nonce_s) {
00166 wpa_printf(MSG_DEBUG, " *AT_NONCE_S");
00167 eap_sim_msg_add(msg, EAP_SIM_AT_NONCE_S, 0, nonce_s,
00168 EAP_SIM_NONCE_S_LEN);
00169 }
00170
00171 if (data->next_pseudonym) {
00172 wpa_printf(MSG_DEBUG, " *AT_NEXT_PSEUDONYM (%s)",
00173 data->next_pseudonym);
00174 eap_sim_msg_add(msg, EAP_SIM_AT_NEXT_PSEUDONYM,
00175 os_strlen(data->next_pseudonym),
00176 (u8 *) data->next_pseudonym,
00177 os_strlen(data->next_pseudonym));
00178 }
00179
00180 if (data->next_reauth_id) {
00181 wpa_printf(MSG_DEBUG, " *AT_NEXT_REAUTH_ID (%s)",
00182 data->next_reauth_id);
00183 eap_sim_msg_add(msg, EAP_SIM_AT_NEXT_REAUTH_ID,
00184 os_strlen(data->next_reauth_id),
00185 (u8 *) data->next_reauth_id,
00186 os_strlen(data->next_reauth_id));
00187 }
00188
00189 if (eap_sim_msg_add_encr_end(msg, data->k_encr, EAP_SIM_AT_PADDING)) {
00190 wpa_printf(MSG_WARNING, "EAP-SIM: Failed to encrypt "
00191 "AT_ENCR_DATA");
00192 return -1;
00193 }
00194
00195 return 0;
00196 }
00197
00198
00199 static struct wpabuf * eap_sim_build_challenge(struct eap_sm *sm,
00200 struct eap_sim_data *data,
00201 u8 id)
00202 {
00203 struct eap_sim_msg *msg;
00204
00205 wpa_printf(MSG_DEBUG, "EAP-SIM: Generating Challenge");
00206 msg = eap_sim_msg_init(EAP_CODE_REQUEST, id, EAP_TYPE_SIM,
00207 EAP_SIM_SUBTYPE_CHALLENGE);
00208 wpa_printf(MSG_DEBUG, " AT_RAND");
00209 eap_sim_msg_add(msg, EAP_SIM_AT_RAND, 0, (u8 *) data->rand,
00210 data->num_chal * GSM_RAND_LEN);
00211
00212 if (eap_sim_build_encr(sm, data, msg, 0, NULL)) {
00213 eap_sim_msg_free(msg);
00214 return NULL;
00215 }
00216
00217 if (sm->eap_sim_aka_result_ind) {
00218 wpa_printf(MSG_DEBUG, " AT_RESULT_IND");
00219 eap_sim_msg_add(msg, EAP_SIM_AT_RESULT_IND, 0, NULL, 0);
00220 }
00221
00222 wpa_printf(MSG_DEBUG, " AT_MAC");
00223 eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC);
00224 return eap_sim_msg_finish(msg, data->k_aut, data->nonce_mt,
00225 EAP_SIM_NONCE_MT_LEN);
00226 }
00227
00228
00229 static struct wpabuf * eap_sim_build_reauth(struct eap_sm *sm,
00230 struct eap_sim_data *data, u8 id)
00231 {
00232 struct eap_sim_msg *msg;
00233
00234 wpa_printf(MSG_DEBUG, "EAP-SIM: Generating Re-authentication");
00235
00236 if (os_get_random(data->nonce_s, EAP_SIM_NONCE_S_LEN))
00237 return NULL;
00238 wpa_hexdump_key(MSG_MSGDUMP, "EAP-SIM: NONCE_S",
00239 data->nonce_s, EAP_SIM_NONCE_S_LEN);
00240
00241 eap_sim_derive_keys(data->mk, data->k_encr, data->k_aut, data->msk,
00242 data->emsk);
00243 eap_sim_derive_keys_reauth(data->counter, sm->identity,
00244 sm->identity_len, data->nonce_s, data->mk,
00245 data->msk, data->emsk);
00246
00247 msg = eap_sim_msg_init(EAP_CODE_REQUEST, id, EAP_TYPE_SIM,
00248 EAP_SIM_SUBTYPE_REAUTHENTICATION);
00249
00250 if (eap_sim_build_encr(sm, data, msg, data->counter, data->nonce_s)) {
00251 eap_sim_msg_free(msg);
00252 return NULL;
00253 }
00254
00255 if (sm->eap_sim_aka_result_ind) {
00256 wpa_printf(MSG_DEBUG, " AT_RESULT_IND");
00257 eap_sim_msg_add(msg, EAP_SIM_AT_RESULT_IND, 0, NULL, 0);
00258 }
00259
00260 wpa_printf(MSG_DEBUG, " AT_MAC");
00261 eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC);
00262 return eap_sim_msg_finish(msg, data->k_aut, NULL, 0);
00263 }
00264
00265
00266 static struct wpabuf * eap_sim_build_notification(struct eap_sm *sm,
00267 struct eap_sim_data *data,
00268 u8 id)
00269 {
00270 struct eap_sim_msg *msg;
00271
00272 wpa_printf(MSG_DEBUG, "EAP-SIM: Generating Notification");
00273 msg = eap_sim_msg_init(EAP_CODE_REQUEST, id, EAP_TYPE_SIM,
00274 EAP_SIM_SUBTYPE_NOTIFICATION);
00275 wpa_printf(MSG_DEBUG, " AT_NOTIFICATION (%d)", data->notification);
00276 eap_sim_msg_add(msg, EAP_SIM_AT_NOTIFICATION, data->notification,
00277 NULL, 0);
00278 if (data->use_result_ind) {
00279 if (data->reauth) {
00280 wpa_printf(MSG_DEBUG, " AT_IV");
00281 wpa_printf(MSG_DEBUG, " AT_ENCR_DATA");
00282 eap_sim_msg_add_encr_start(msg, EAP_SIM_AT_IV,
00283 EAP_SIM_AT_ENCR_DATA);
00284 wpa_printf(MSG_DEBUG, " *AT_COUNTER (%u)",
00285 data->counter);
00286 eap_sim_msg_add(msg, EAP_SIM_AT_COUNTER, data->counter,
00287 NULL, 0);
00288
00289 if (eap_sim_msg_add_encr_end(msg, data->k_encr,
00290 EAP_SIM_AT_PADDING)) {
00291 wpa_printf(MSG_WARNING, "EAP-SIM: Failed to "
00292 "encrypt AT_ENCR_DATA");
00293 eap_sim_msg_free(msg);
00294 return NULL;
00295 }
00296 }
00297
00298 wpa_printf(MSG_DEBUG, " AT_MAC");
00299 eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC);
00300 }
00301 return eap_sim_msg_finish(msg, data->k_aut, NULL, 0);
00302 }
00303
00304
00305 static struct wpabuf * eap_sim_buildReq(struct eap_sm *sm, void *priv, u8 id)
00306 {
00307 struct eap_sim_data *data = priv;
00308
00309 switch (data->state) {
00310 case START:
00311 return eap_sim_build_start(sm, data, id);
00312 case CHALLENGE:
00313 return eap_sim_build_challenge(sm, data, id);
00314 case REAUTH:
00315 return eap_sim_build_reauth(sm, data, id);
00316 case NOTIFICATION:
00317 return eap_sim_build_notification(sm, data, id);
00318 default:
00319 wpa_printf(MSG_DEBUG, "EAP-SIM: Unknown state %d in "
00320 "buildReq", data->state);
00321 break;
00322 }
00323 return NULL;
00324 }
00325
00326
00327 static Boolean eap_sim_check(struct eap_sm *sm, void *priv,
00328 struct wpabuf *respData)
00329 {
00330 struct eap_sim_data *data = priv;
00331 const u8 *pos;
00332 size_t len;
00333 u8 subtype;
00334
00335 pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_SIM, respData, &len);
00336 if (pos == NULL || len < 3) {
00337 wpa_printf(MSG_INFO, "EAP-SIM: Invalid frame");
00338 return TRUE;
00339 }
00340 subtype = *pos;
00341
00342 if (subtype == EAP_SIM_SUBTYPE_CLIENT_ERROR)
00343 return FALSE;
00344
00345 switch (data->state) {
00346 case START:
00347 if (subtype != EAP_SIM_SUBTYPE_START) {
00348 wpa_printf(MSG_INFO, "EAP-SIM: Unexpected response "
00349 "subtype %d", subtype);
00350 return TRUE;
00351 }
00352 break;
00353 case CHALLENGE:
00354 if (subtype != EAP_SIM_SUBTYPE_CHALLENGE) {
00355 wpa_printf(MSG_INFO, "EAP-SIM: Unexpected response "
00356 "subtype %d", subtype);
00357 return TRUE;
00358 }
00359 break;
00360 case REAUTH:
00361 if (subtype != EAP_SIM_SUBTYPE_REAUTHENTICATION) {
00362 wpa_printf(MSG_INFO, "EAP-SIM: Unexpected response "
00363 "subtype %d", subtype);
00364 return TRUE;
00365 }
00366 break;
00367 case NOTIFICATION:
00368 if (subtype != EAP_SIM_SUBTYPE_NOTIFICATION) {
00369 wpa_printf(MSG_INFO, "EAP-SIM: Unexpected response "
00370 "subtype %d", subtype);
00371 return TRUE;
00372 }
00373 break;
00374 default:
00375 wpa_printf(MSG_INFO, "EAP-SIM: Unexpected state (%d) for "
00376 "processing a response", data->state);
00377 return TRUE;
00378 }
00379
00380 return FALSE;
00381 }
00382
00383
00384 static int eap_sim_supported_ver(struct eap_sim_data *data, int version)
00385 {
00386 return version == EAP_SIM_VERSION;
00387 }
00388
00389
00390 static void eap_sim_process_start(struct eap_sm *sm,
00391 struct eap_sim_data *data,
00392 struct wpabuf *respData,
00393 struct eap_sim_attrs *attr)
00394 {
00395 const u8 *identity;
00396 size_t identity_len;
00397 u8 ver_list[2];
00398
00399 wpa_printf(MSG_DEBUG, "EAP-SIM: Receive start response");
00400
00401 if (attr->identity) {
00402 os_free(sm->identity);
00403 sm->identity = os_malloc(attr->identity_len);
00404 if (sm->identity) {
00405 os_memcpy(sm->identity, attr->identity,
00406 attr->identity_len);
00407 sm->identity_len = attr->identity_len;
00408 }
00409 }
00410
00411 identity = NULL;
00412 identity_len = 0;
00413
00414 if (sm->identity && sm->identity_len > 0 &&
00415 sm->identity[0] == EAP_SIM_PERMANENT_PREFIX) {
00416 identity = sm->identity;
00417 identity_len = sm->identity_len;
00418 } else {
00419 identity = eap_sim_db_get_permanent(sm->eap_sim_db_priv,
00420 sm->identity,
00421 sm->identity_len,
00422 &identity_len);
00423 if (identity == NULL) {
00424 data->reauth = eap_sim_db_get_reauth_entry(
00425 sm->eap_sim_db_priv, sm->identity,
00426 sm->identity_len);
00427 if (data->reauth) {
00428 wpa_printf(MSG_DEBUG, "EAP-SIM: Using fast "
00429 "re-authentication");
00430 identity = data->reauth->identity;
00431 identity_len = data->reauth->identity_len;
00432 data->counter = data->reauth->counter;
00433 os_memcpy(data->mk, data->reauth->mk,
00434 EAP_SIM_MK_LEN);
00435 }
00436 }
00437 }
00438
00439 if (identity == NULL) {
00440 wpa_printf(MSG_DEBUG, "EAP-SIM: Could not get proper permanent"
00441 " user name");
00442 eap_sim_state(data, FAILURE);
00443 return;
00444 }
00445
00446 wpa_hexdump_ascii(MSG_DEBUG, "EAP-SIM: Identity",
00447 identity, identity_len);
00448
00449 if (data->reauth) {
00450 eap_sim_state(data, REAUTH);
00451 return;
00452 }
00453
00454 if (attr->nonce_mt == NULL || attr->selected_version < 0) {
00455 wpa_printf(MSG_DEBUG, "EAP-SIM: Start/Response missing "
00456 "required attributes");
00457 eap_sim_state(data, FAILURE);
00458 return;
00459 }
00460
00461 if (!eap_sim_supported_ver(data, attr->selected_version)) {
00462 wpa_printf(MSG_DEBUG, "EAP-SIM: Peer selected unsupported "
00463 "version %d", attr->selected_version);
00464 eap_sim_state(data, FAILURE);
00465 return;
00466 }
00467
00468 data->counter = 0;
00469 data->reauth = NULL;
00470
00471 data->num_chal = eap_sim_db_get_gsm_triplets(
00472 sm->eap_sim_db_priv, identity, identity_len,
00473 EAP_SIM_MAX_CHAL,
00474 (u8 *) data->rand, (u8 *) data->kc, (u8 *) data->sres, sm);
00475 if (data->num_chal == EAP_SIM_DB_PENDING) {
00476 wpa_printf(MSG_DEBUG, "EAP-SIM: GSM authentication triplets "
00477 "not yet available - pending request");
00478 sm->method_pending = METHOD_PENDING_WAIT;
00479 return;
00480 }
00481 if (data->num_chal < 2) {
00482 wpa_printf(MSG_INFO, "EAP-SIM: Failed to get GSM "
00483 "authentication triplets for the peer");
00484 eap_sim_state(data, FAILURE);
00485 return;
00486 }
00487
00488 identity_len = sm->identity_len;
00489 while (identity_len > 0 && sm->identity[identity_len - 1] == '\0') {
00490 wpa_printf(MSG_DEBUG, "EAP-SIM: Workaround - drop last null "
00491 "character from identity");
00492 identity_len--;
00493 }
00494 wpa_hexdump_ascii(MSG_DEBUG, "EAP-SIM: Identity for MK derivation",
00495 sm->identity, identity_len);
00496
00497 os_memcpy(data->nonce_mt, attr->nonce_mt, EAP_SIM_NONCE_MT_LEN);
00498 WPA_PUT_BE16(ver_list, EAP_SIM_VERSION);
00499 eap_sim_derive_mk(sm->identity, identity_len, attr->nonce_mt,
00500 attr->selected_version, ver_list, sizeof(ver_list),
00501 data->num_chal, (const u8 *) data->kc, data->mk);
00502 eap_sim_derive_keys(data->mk, data->k_encr, data->k_aut, data->msk,
00503 data->emsk);
00504
00505 eap_sim_state(data, CHALLENGE);
00506 }
00507
00508
00509 static void eap_sim_process_challenge(struct eap_sm *sm,
00510 struct eap_sim_data *data,
00511 struct wpabuf *respData,
00512 struct eap_sim_attrs *attr)
00513 {
00514 const u8 *identity;
00515 size_t identity_len;
00516
00517 if (attr->mac == NULL ||
00518 eap_sim_verify_mac(data->k_aut, respData, attr->mac,
00519 (u8 *) data->sres,
00520 data->num_chal * EAP_SIM_SRES_LEN)) {
00521 wpa_printf(MSG_WARNING, "EAP-SIM: Challenge message "
00522 "did not include valid AT_MAC");
00523 eap_sim_state(data, FAILURE);
00524 return;
00525 }
00526
00527 wpa_printf(MSG_DEBUG, "EAP-SIM: Challenge response includes the "
00528 "correct AT_MAC");
00529 if (sm->eap_sim_aka_result_ind && attr->result_ind) {
00530 data->use_result_ind = 1;
00531 data->notification = EAP_SIM_SUCCESS;
00532 eap_sim_state(data, NOTIFICATION);
00533 } else
00534 eap_sim_state(data, SUCCESS);
00535
00536 identity = eap_sim_db_get_permanent(sm->eap_sim_db_priv, sm->identity,
00537 sm->identity_len, &identity_len);
00538 if (identity == NULL) {
00539 identity = sm->identity;
00540 identity_len = sm->identity_len;
00541 }
00542
00543 if (data->next_pseudonym) {
00544 eap_sim_db_add_pseudonym(sm->eap_sim_db_priv, identity,
00545 identity_len,
00546 data->next_pseudonym);
00547 data->next_pseudonym = NULL;
00548 }
00549 if (data->next_reauth_id) {
00550 eap_sim_db_add_reauth(sm->eap_sim_db_priv, identity,
00551 identity_len,
00552 data->next_reauth_id, data->counter + 1,
00553 data->mk);
00554 data->next_reauth_id = NULL;
00555 }
00556 }
00557
00558
00559 static void eap_sim_process_reauth(struct eap_sm *sm,
00560 struct eap_sim_data *data,
00561 struct wpabuf *respData,
00562 struct eap_sim_attrs *attr)
00563 {
00564 struct eap_sim_attrs eattr;
00565 u8 *decrypted = NULL;
00566 const u8 *identity, *id2;
00567 size_t identity_len, id2_len;
00568
00569 if (attr->mac == NULL ||
00570 eap_sim_verify_mac(data->k_aut, respData, attr->mac, data->nonce_s,
00571 EAP_SIM_NONCE_S_LEN)) {
00572 wpa_printf(MSG_WARNING, "EAP-SIM: Re-authentication message "
00573 "did not include valid AT_MAC");
00574 goto fail;
00575 }
00576
00577 if (attr->encr_data == NULL || attr->iv == NULL) {
00578 wpa_printf(MSG_WARNING, "EAP-SIM: Reauthentication "
00579 "message did not include encrypted data");
00580 goto fail;
00581 }
00582
00583 decrypted = eap_sim_parse_encr(data->k_encr, attr->encr_data,
00584 attr->encr_data_len, attr->iv, &eattr,
00585 0);
00586 if (decrypted == NULL) {
00587 wpa_printf(MSG_WARNING, "EAP-SIM: Failed to parse encrypted "
00588 "data from reauthentication message");
00589 goto fail;
00590 }
00591
00592 if (eattr.counter != data->counter) {
00593 wpa_printf(MSG_WARNING, "EAP-SIM: Re-authentication message "
00594 "used incorrect counter %u, expected %u",
00595 eattr.counter, data->counter);
00596 goto fail;
00597 }
00598 os_free(decrypted);
00599 decrypted = NULL;
00600
00601 wpa_printf(MSG_DEBUG, "EAP-SIM: Re-authentication response includes "
00602 "the correct AT_MAC");
00603 if (sm->eap_sim_aka_result_ind && attr->result_ind) {
00604 data->use_result_ind = 1;
00605 data->notification = EAP_SIM_SUCCESS;
00606 eap_sim_state(data, NOTIFICATION);
00607 } else
00608 eap_sim_state(data, SUCCESS);
00609
00610 if (data->reauth) {
00611 identity = data->reauth->identity;
00612 identity_len = data->reauth->identity_len;
00613 } else {
00614 identity = sm->identity;
00615 identity_len = sm->identity_len;
00616 }
00617
00618 id2 = eap_sim_db_get_permanent(sm->eap_sim_db_priv, identity,
00619 identity_len, &id2_len);
00620 if (id2) {
00621 identity = id2;
00622 identity_len = id2_len;
00623 }
00624
00625 if (data->next_pseudonym) {
00626 eap_sim_db_add_pseudonym(sm->eap_sim_db_priv, identity,
00627 identity_len, data->next_pseudonym);
00628 data->next_pseudonym = NULL;
00629 }
00630 if (data->next_reauth_id) {
00631 eap_sim_db_add_reauth(sm->eap_sim_db_priv, identity,
00632 identity_len, data->next_reauth_id,
00633 data->counter + 1, data->mk);
00634 data->next_reauth_id = NULL;
00635 } else {
00636 eap_sim_db_remove_reauth(sm->eap_sim_db_priv, data->reauth);
00637 data->reauth = NULL;
00638 }
00639
00640 return;
00641
00642 fail:
00643 eap_sim_state(data, FAILURE);
00644 eap_sim_db_remove_reauth(sm->eap_sim_db_priv, data->reauth);
00645 data->reauth = NULL;
00646 os_free(decrypted);
00647 }
00648
00649
00650 static void eap_sim_process_client_error(struct eap_sm *sm,
00651 struct eap_sim_data *data,
00652 struct wpabuf *respData,
00653 struct eap_sim_attrs *attr)
00654 {
00655 wpa_printf(MSG_DEBUG, "EAP-SIM: Client reported error %d",
00656 attr->client_error_code);
00657 if (data->notification == EAP_SIM_SUCCESS && data->use_result_ind)
00658 eap_sim_state(data, SUCCESS);
00659 else
00660 eap_sim_state(data, FAILURE);
00661 }
00662
00663
00664 static void eap_sim_process_notification(struct eap_sm *sm,
00665 struct eap_sim_data *data,
00666 struct wpabuf *respData,
00667 struct eap_sim_attrs *attr)
00668 {
00669 wpa_printf(MSG_DEBUG, "EAP-SIM: Client replied to notification");
00670 if (data->notification == EAP_SIM_SUCCESS && data->use_result_ind)
00671 eap_sim_state(data, SUCCESS);
00672 else
00673 eap_sim_state(data, FAILURE);
00674 }
00675
00676
00677 static void eap_sim_process(struct eap_sm *sm, void *priv,
00678 struct wpabuf *respData)
00679 {
00680 struct eap_sim_data *data = priv;
00681 const u8 *pos, *end;
00682 u8 subtype;
00683 size_t len;
00684 struct eap_sim_attrs attr;
00685
00686 pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_SIM, respData, &len);
00687 if (pos == NULL || len < 3)
00688 return;
00689
00690 end = pos + len;
00691 subtype = *pos;
00692 pos += 3;
00693
00694 if (eap_sim_parse_attr(pos, end, &attr, 0, 0)) {
00695 wpa_printf(MSG_DEBUG, "EAP-SIM: Failed to parse attributes");
00696 eap_sim_state(data, FAILURE);
00697 return;
00698 }
00699
00700 if (subtype == EAP_SIM_SUBTYPE_CLIENT_ERROR) {
00701 eap_sim_process_client_error(sm, data, respData, &attr);
00702 return;
00703 }
00704
00705 switch (data->state) {
00706 case START:
00707 eap_sim_process_start(sm, data, respData, &attr);
00708 break;
00709 case CHALLENGE:
00710 eap_sim_process_challenge(sm, data, respData, &attr);
00711 break;
00712 case REAUTH:
00713 eap_sim_process_reauth(sm, data, respData, &attr);
00714 break;
00715 case NOTIFICATION:
00716 eap_sim_process_notification(sm, data, respData, &attr);
00717 break;
00718 default:
00719 wpa_printf(MSG_DEBUG, "EAP-SIM: Unknown state %d in "
00720 "process", data->state);
00721 break;
00722 }
00723 }
00724
00725
00726 static Boolean eap_sim_isDone(struct eap_sm *sm, void *priv)
00727 {
00728 struct eap_sim_data *data = priv;
00729 return data->state == SUCCESS || data->state == FAILURE;
00730 }
00731
00732
00733 static u8 * eap_sim_getKey(struct eap_sm *sm, void *priv, size_t *len)
00734 {
00735 struct eap_sim_data *data = priv;
00736 u8 *key;
00737
00738 if (data->state != SUCCESS)
00739 return NULL;
00740
00741 key = os_malloc(EAP_SIM_KEYING_DATA_LEN);
00742 if (key == NULL)
00743 return NULL;
00744 os_memcpy(key, data->msk, EAP_SIM_KEYING_DATA_LEN);
00745 *len = EAP_SIM_KEYING_DATA_LEN;
00746 return key;
00747 }
00748
00749
00750 static u8 * eap_sim_get_emsk(struct eap_sm *sm, void *priv, size_t *len)
00751 {
00752 struct eap_sim_data *data = priv;
00753 u8 *key;
00754
00755 if (data->state != SUCCESS)
00756 return NULL;
00757
00758 key = os_malloc(EAP_EMSK_LEN);
00759 if (key == NULL)
00760 return NULL;
00761 os_memcpy(key, data->emsk, EAP_EMSK_LEN);
00762 *len = EAP_EMSK_LEN;
00763 return key;
00764 }
00765
00766
00767 static Boolean eap_sim_isSuccess(struct eap_sm *sm, void *priv)
00768 {
00769 struct eap_sim_data *data = priv;
00770 return data->state == SUCCESS;
00771 }
00772
00773
00774 int eap_server_sim_register(void)
00775 {
00776 struct eap_method *eap;
00777 int ret;
00778
00779 eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION,
00780 EAP_VENDOR_IETF, EAP_TYPE_SIM, "SIM");
00781 if (eap == NULL)
00782 return -1;
00783
00784 eap->init = eap_sim_init;
00785 eap->reset = eap_sim_reset;
00786 eap->buildReq = eap_sim_buildReq;
00787 eap->check = eap_sim_check;
00788 eap->process = eap_sim_process;
00789 eap->isDone = eap_sim_isDone;
00790 eap->getKey = eap_sim_getKey;
00791 eap->isSuccess = eap_sim_isSuccess;
00792 eap->get_emsk = eap_sim_get_emsk;
00793
00794 ret = eap_server_method_register(eap);
00795 if (ret)
00796 eap_server_method_free(eap);
00797 return ret;
00798 }
00799