$search
00001 /* 00002 * hostapd / EAP-SIM (RFC 4186) 00003 * Copyright (c) 2005-2008, Jouni Malinen <j@w1.fi> 00004 * 00005 * This program is free software; you can redistribute it and/or modify 00006 * it under the terms of the GNU General Public License version 2 as 00007 * published by the Free Software Foundation. 00008 * 00009 * Alternatively, this software may be distributed under the terms of BSD 00010 * license. 00011 * 00012 * See README and COPYING for more details. 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 * RFC 4186, Chap. 4.2.4 recommends that identity from EAP is 00120 * ignored and the SIM/Start is used to request the identity. 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; /* reset re-auth counter since this is full auth */ 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 }