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