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 "pcsc_funcs.h"
00019 #include "crypto/milenage.h"
00020 #include "eap_peer/eap_i.h"
00021 #include "eap_config.h"
00022 #include "eap_common/eap_sim_common.h"
00023
00024
00025 struct eap_sim_data {
00026 u8 *ver_list;
00027 size_t ver_list_len;
00028 int selected_version;
00029 size_t min_num_chal, num_chal;
00030
00031 u8 kc[3][EAP_SIM_KC_LEN];
00032 u8 sres[3][EAP_SIM_SRES_LEN];
00033 u8 nonce_mt[EAP_SIM_NONCE_MT_LEN], nonce_s[EAP_SIM_NONCE_S_LEN];
00034 u8 mk[EAP_SIM_MK_LEN];
00035 u8 k_aut[EAP_SIM_K_AUT_LEN];
00036 u8 k_encr[EAP_SIM_K_ENCR_LEN];
00037 u8 msk[EAP_SIM_KEYING_DATA_LEN];
00038 u8 emsk[EAP_EMSK_LEN];
00039 u8 rand[3][GSM_RAND_LEN];
00040
00041 int num_id_req, num_notification;
00042 u8 *pseudonym;
00043 size_t pseudonym_len;
00044 u8 *reauth_id;
00045 size_t reauth_id_len;
00046 int reauth;
00047 unsigned int counter, counter_too_small;
00048 u8 *last_eap_identity;
00049 size_t last_eap_identity_len;
00050 enum {
00051 CONTINUE, RESULT_SUCCESS, RESULT_FAILURE, SUCCESS, FAILURE
00052 } state;
00053 int result_ind, use_result_ind;
00054 };
00055
00056
00057 #ifndef CONFIG_NO_STDOUT_DEBUG
00058 static const char * eap_sim_state_txt(int state)
00059 {
00060 switch (state) {
00061 case CONTINUE:
00062 return "CONTINUE";
00063 case RESULT_SUCCESS:
00064 return "RESULT_SUCCESS";
00065 case RESULT_FAILURE:
00066 return "RESULT_FAILURE";
00067 case SUCCESS:
00068 return "SUCCESS";
00069 case FAILURE:
00070 return "FAILURE";
00071 default:
00072 return "?";
00073 }
00074 }
00075 #endif
00076
00077
00078 static void eap_sim_state(struct eap_sim_data *data, int state)
00079 {
00080 wpa_printf(MSG_DEBUG, "EAP-SIM: %s -> %s",
00081 eap_sim_state_txt(data->state),
00082 eap_sim_state_txt(state));
00083 data->state = state;
00084 }
00085
00086
00087 static void * eap_sim_init(struct eap_sm *sm)
00088 {
00089 struct eap_sim_data *data;
00090 struct eap_peer_config *config = eap_get_config(sm);
00091
00092 data = os_zalloc(sizeof(*data));
00093 if (data == NULL)
00094 return NULL;
00095
00096 if (os_get_random(data->nonce_mt, EAP_SIM_NONCE_MT_LEN)) {
00097 wpa_printf(MSG_WARNING, "EAP-SIM: Failed to get random data "
00098 "for NONCE_MT");
00099 os_free(data);
00100 return NULL;
00101 }
00102
00103 data->min_num_chal = 2;
00104 if (config && config->phase1) {
00105 char *pos = os_strstr(config->phase1, "sim_min_num_chal=");
00106 if (pos) {
00107 data->min_num_chal = atoi(pos + 17);
00108 if (data->min_num_chal < 2 || data->min_num_chal > 3) {
00109 wpa_printf(MSG_WARNING, "EAP-SIM: Invalid "
00110 "sim_min_num_chal configuration "
00111 "(%lu, expected 2 or 3)",
00112 (unsigned long) data->min_num_chal);
00113 os_free(data);
00114 return NULL;
00115 }
00116 wpa_printf(MSG_DEBUG, "EAP-SIM: Set minimum number of "
00117 "challenges to %lu",
00118 (unsigned long) data->min_num_chal);
00119 }
00120
00121 data->result_ind = os_strstr(config->phase1, "result_ind=1") !=
00122 NULL;
00123 }
00124
00125 eap_sim_state(data, CONTINUE);
00126
00127 return data;
00128 }
00129
00130
00131 static void eap_sim_deinit(struct eap_sm *sm, void *priv)
00132 {
00133 struct eap_sim_data *data = priv;
00134 if (data) {
00135 os_free(data->ver_list);
00136 os_free(data->pseudonym);
00137 os_free(data->reauth_id);
00138 os_free(data->last_eap_identity);
00139 os_free(data);
00140 }
00141 }
00142
00143
00144 static int eap_sim_gsm_auth(struct eap_sm *sm, struct eap_sim_data *data)
00145 {
00146 struct eap_peer_config *conf;
00147
00148 wpa_printf(MSG_DEBUG, "EAP-SIM: GSM authentication algorithm");
00149
00150 conf = eap_get_config(sm);
00151 if (conf == NULL)
00152 return -1;
00153 if (conf->pcsc) {
00154 if (scard_gsm_auth(sm->scard_ctx, data->rand[0],
00155 data->sres[0], data->kc[0]) ||
00156 scard_gsm_auth(sm->scard_ctx, data->rand[1],
00157 data->sres[1], data->kc[1]) ||
00158 (data->num_chal > 2 &&
00159 scard_gsm_auth(sm->scard_ctx, data->rand[2],
00160 data->sres[2], data->kc[2]))) {
00161 wpa_printf(MSG_DEBUG, "EAP-SIM: GSM SIM "
00162 "authentication could not be completed");
00163 return -1;
00164 }
00165 return 0;
00166 }
00167
00168 #ifdef CONFIG_SIM_SIMULATOR
00169 if (conf->password) {
00170 u8 opc[16], k[16];
00171 const char *pos;
00172 size_t i;
00173 wpa_printf(MSG_DEBUG, "EAP-SIM: Use internal GSM-Milenage "
00174 "implementation for authentication");
00175 if (conf->password_len < 65) {
00176 wpa_printf(MSG_DEBUG, "EAP-SIM: invalid GSM-Milenage "
00177 "password");
00178 return -1;
00179 }
00180 pos = (const char *) conf->password;
00181 if (hexstr2bin(pos, k, 16))
00182 return -1;
00183 pos += 32;
00184 if (*pos != ':')
00185 return -1;
00186 pos++;
00187
00188 if (hexstr2bin(pos, opc, 16))
00189 return -1;
00190
00191 for (i = 0; i < data->num_chal; i++) {
00192 if (gsm_milenage(opc, k, data->rand[i],
00193 data->sres[i], data->kc[i])) {
00194 wpa_printf(MSG_DEBUG, "EAP-SIM: "
00195 "GSM-Milenage authentication "
00196 "could not be completed");
00197 return -1;
00198 }
00199 wpa_hexdump(MSG_DEBUG, "EAP-SIM: RAND",
00200 data->rand[i], GSM_RAND_LEN);
00201 wpa_hexdump_key(MSG_DEBUG, "EAP-SIM: SRES",
00202 data->sres[i], EAP_SIM_SRES_LEN);
00203 wpa_hexdump_key(MSG_DEBUG, "EAP-SIM: Kc",
00204 data->kc[i], EAP_SIM_KC_LEN);
00205 }
00206 return 0;
00207 }
00208 #endif
00209
00210 #ifdef CONFIG_SIM_HARDCODED
00211
00212
00213
00214
00215 {
00216 size_t i;
00217
00218 wpa_printf(MSG_DEBUG, "EAP-SIM: Use hardcoded Kc and SRES "
00219 "values for testing");
00220
00221 for (i = 0; i < data->num_chal; i++) {
00222 if (data->rand[i][0] == 0xaa) {
00223 os_memcpy(data->kc[i],
00224 "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7",
00225 EAP_SIM_KC_LEN);
00226 os_memcpy(data->sres[i], "\xd1\xd2\xd3\xd4",
00227 EAP_SIM_SRES_LEN);
00228 } else if (data->rand[i][0] == 0xbb) {
00229 os_memcpy(data->kc[i],
00230 "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7",
00231 EAP_SIM_KC_LEN);
00232 os_memcpy(data->sres[i], "\xe1\xe2\xe3\xe4",
00233 EAP_SIM_SRES_LEN);
00234 } else {
00235 os_memcpy(data->kc[i],
00236 "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7",
00237 EAP_SIM_KC_LEN);
00238 os_memcpy(data->sres[i], "\xf1\xf2\xf3\xf4",
00239 EAP_SIM_SRES_LEN);
00240 }
00241 }
00242 }
00243
00244 return 0;
00245
00246 #else
00247
00248 wpa_printf(MSG_DEBUG, "EAP-SIM: No GSM authentication algorithm "
00249 "enabled");
00250 return -1;
00251
00252 #endif
00253 }
00254
00255
00256 static int eap_sim_supported_ver(int version)
00257 {
00258 return version == EAP_SIM_VERSION;
00259 }
00260
00261
00262 #define CLEAR_PSEUDONYM 0x01
00263 #define CLEAR_REAUTH_ID 0x02
00264 #define CLEAR_EAP_ID 0x04
00265
00266 static void eap_sim_clear_identities(struct eap_sim_data *data, int id)
00267 {
00268 wpa_printf(MSG_DEBUG, "EAP-SIM: forgetting old%s%s%s",
00269 id & CLEAR_PSEUDONYM ? " pseudonym" : "",
00270 id & CLEAR_REAUTH_ID ? " reauth_id" : "",
00271 id & CLEAR_EAP_ID ? " eap_id" : "");
00272 if (id & CLEAR_PSEUDONYM) {
00273 os_free(data->pseudonym);
00274 data->pseudonym = NULL;
00275 data->pseudonym_len = 0;
00276 }
00277 if (id & CLEAR_REAUTH_ID) {
00278 os_free(data->reauth_id);
00279 data->reauth_id = NULL;
00280 data->reauth_id_len = 0;
00281 }
00282 if (id & CLEAR_EAP_ID) {
00283 os_free(data->last_eap_identity);
00284 data->last_eap_identity = NULL;
00285 data->last_eap_identity_len = 0;
00286 }
00287 }
00288
00289
00290 static int eap_sim_learn_ids(struct eap_sim_data *data,
00291 struct eap_sim_attrs *attr)
00292 {
00293 if (attr->next_pseudonym) {
00294 os_free(data->pseudonym);
00295 data->pseudonym = os_malloc(attr->next_pseudonym_len);
00296 if (data->pseudonym == NULL) {
00297 wpa_printf(MSG_INFO, "EAP-SIM: (encr) No memory for "
00298 "next pseudonym");
00299 return -1;
00300 }
00301 os_memcpy(data->pseudonym, attr->next_pseudonym,
00302 attr->next_pseudonym_len);
00303 data->pseudonym_len = attr->next_pseudonym_len;
00304 wpa_hexdump_ascii(MSG_DEBUG,
00305 "EAP-SIM: (encr) AT_NEXT_PSEUDONYM",
00306 data->pseudonym,
00307 data->pseudonym_len);
00308 }
00309
00310 if (attr->next_reauth_id) {
00311 os_free(data->reauth_id);
00312 data->reauth_id = os_malloc(attr->next_reauth_id_len);
00313 if (data->reauth_id == NULL) {
00314 wpa_printf(MSG_INFO, "EAP-SIM: (encr) No memory for "
00315 "next reauth_id");
00316 return -1;
00317 }
00318 os_memcpy(data->reauth_id, attr->next_reauth_id,
00319 attr->next_reauth_id_len);
00320 data->reauth_id_len = attr->next_reauth_id_len;
00321 wpa_hexdump_ascii(MSG_DEBUG,
00322 "EAP-SIM: (encr) AT_NEXT_REAUTH_ID",
00323 data->reauth_id,
00324 data->reauth_id_len);
00325 }
00326
00327 return 0;
00328 }
00329
00330
00331 static struct wpabuf * eap_sim_client_error(struct eap_sim_data *data, u8 id,
00332 int err)
00333 {
00334 struct eap_sim_msg *msg;
00335
00336 eap_sim_state(data, FAILURE);
00337 data->num_id_req = 0;
00338 data->num_notification = 0;
00339
00340 msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, EAP_TYPE_SIM,
00341 EAP_SIM_SUBTYPE_CLIENT_ERROR);
00342 eap_sim_msg_add(msg, EAP_SIM_AT_CLIENT_ERROR_CODE, err, NULL, 0);
00343 return eap_sim_msg_finish(msg, NULL, NULL, 0);
00344 }
00345
00346
00347 static struct wpabuf * eap_sim_response_start(struct eap_sm *sm,
00348 struct eap_sim_data *data, u8 id,
00349 enum eap_sim_id_req id_req)
00350 {
00351 const u8 *identity = NULL;
00352 size_t identity_len = 0;
00353 struct eap_sim_msg *msg;
00354
00355 data->reauth = 0;
00356 if (id_req == ANY_ID && data->reauth_id) {
00357 identity = data->reauth_id;
00358 identity_len = data->reauth_id_len;
00359 data->reauth = 1;
00360 } else if ((id_req == ANY_ID || id_req == FULLAUTH_ID) &&
00361 data->pseudonym) {
00362 identity = data->pseudonym;
00363 identity_len = data->pseudonym_len;
00364 eap_sim_clear_identities(data, CLEAR_REAUTH_ID);
00365 } else if (id_req != NO_ID_REQ) {
00366 identity = eap_get_config_identity(sm, &identity_len);
00367 if (identity) {
00368 eap_sim_clear_identities(data, CLEAR_PSEUDONYM |
00369 CLEAR_REAUTH_ID);
00370 }
00371 }
00372 if (id_req != NO_ID_REQ)
00373 eap_sim_clear_identities(data, CLEAR_EAP_ID);
00374
00375 wpa_printf(MSG_DEBUG, "Generating EAP-SIM Start (id=%d)", id);
00376 msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id,
00377 EAP_TYPE_SIM, EAP_SIM_SUBTYPE_START);
00378 if (!data->reauth) {
00379 wpa_hexdump(MSG_DEBUG, " AT_NONCE_MT",
00380 data->nonce_mt, EAP_SIM_NONCE_MT_LEN);
00381 eap_sim_msg_add(msg, EAP_SIM_AT_NONCE_MT, 0,
00382 data->nonce_mt, EAP_SIM_NONCE_MT_LEN);
00383 wpa_printf(MSG_DEBUG, " AT_SELECTED_VERSION %d",
00384 data->selected_version);
00385 eap_sim_msg_add(msg, EAP_SIM_AT_SELECTED_VERSION,
00386 data->selected_version, NULL, 0);
00387 }
00388
00389 if (identity) {
00390 wpa_hexdump_ascii(MSG_DEBUG, " AT_IDENTITY",
00391 identity, identity_len);
00392 eap_sim_msg_add(msg, EAP_SIM_AT_IDENTITY, identity_len,
00393 identity, identity_len);
00394 }
00395
00396 return eap_sim_msg_finish(msg, NULL, NULL, 0);
00397 }
00398
00399
00400 static struct wpabuf * eap_sim_response_challenge(struct eap_sim_data *data,
00401 u8 id)
00402 {
00403 struct eap_sim_msg *msg;
00404
00405 wpa_printf(MSG_DEBUG, "Generating EAP-SIM Challenge (id=%d)", id);
00406 msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, EAP_TYPE_SIM,
00407 EAP_SIM_SUBTYPE_CHALLENGE);
00408 if (data->use_result_ind) {
00409 wpa_printf(MSG_DEBUG, " AT_RESULT_IND");
00410 eap_sim_msg_add(msg, EAP_SIM_AT_RESULT_IND, 0, NULL, 0);
00411 }
00412 wpa_printf(MSG_DEBUG, " AT_MAC");
00413 eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC);
00414 return eap_sim_msg_finish(msg, data->k_aut, (u8 *) data->sres,
00415 data->num_chal * EAP_SIM_SRES_LEN);
00416 }
00417
00418
00419 static struct wpabuf * eap_sim_response_reauth(struct eap_sim_data *data,
00420 u8 id, int counter_too_small)
00421 {
00422 struct eap_sim_msg *msg;
00423 unsigned int counter;
00424
00425 wpa_printf(MSG_DEBUG, "Generating EAP-SIM Reauthentication (id=%d)",
00426 id);
00427 msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, EAP_TYPE_SIM,
00428 EAP_SIM_SUBTYPE_REAUTHENTICATION);
00429 wpa_printf(MSG_DEBUG, " AT_IV");
00430 wpa_printf(MSG_DEBUG, " AT_ENCR_DATA");
00431 eap_sim_msg_add_encr_start(msg, EAP_SIM_AT_IV, EAP_SIM_AT_ENCR_DATA);
00432
00433 if (counter_too_small) {
00434 wpa_printf(MSG_DEBUG, " *AT_COUNTER_TOO_SMALL");
00435 eap_sim_msg_add(msg, EAP_SIM_AT_COUNTER_TOO_SMALL, 0, NULL, 0);
00436 counter = data->counter_too_small;
00437 } else
00438 counter = data->counter;
00439
00440 wpa_printf(MSG_DEBUG, " *AT_COUNTER %d", counter);
00441 eap_sim_msg_add(msg, EAP_SIM_AT_COUNTER, counter, NULL, 0);
00442
00443 if (eap_sim_msg_add_encr_end(msg, data->k_encr, EAP_SIM_AT_PADDING)) {
00444 wpa_printf(MSG_WARNING, "EAP-SIM: Failed to encrypt "
00445 "AT_ENCR_DATA");
00446 eap_sim_msg_free(msg);
00447 return NULL;
00448 }
00449 if (data->use_result_ind) {
00450 wpa_printf(MSG_DEBUG, " AT_RESULT_IND");
00451 eap_sim_msg_add(msg, EAP_SIM_AT_RESULT_IND, 0, NULL, 0);
00452 }
00453 wpa_printf(MSG_DEBUG, " AT_MAC");
00454 eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC);
00455 return eap_sim_msg_finish(msg, data->k_aut, data->nonce_s,
00456 EAP_SIM_NONCE_S_LEN);
00457 }
00458
00459
00460 static struct wpabuf * eap_sim_response_notification(struct eap_sim_data *data,
00461 u8 id, u16 notification)
00462 {
00463 struct eap_sim_msg *msg;
00464 u8 *k_aut = (notification & 0x4000) == 0 ? data->k_aut : NULL;
00465
00466 wpa_printf(MSG_DEBUG, "Generating EAP-SIM Notification (id=%d)", id);
00467 msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id,
00468 EAP_TYPE_SIM, EAP_SIM_SUBTYPE_NOTIFICATION);
00469 if (k_aut && data->reauth) {
00470 wpa_printf(MSG_DEBUG, " AT_IV");
00471 wpa_printf(MSG_DEBUG, " AT_ENCR_DATA");
00472 eap_sim_msg_add_encr_start(msg, EAP_SIM_AT_IV,
00473 EAP_SIM_AT_ENCR_DATA);
00474 wpa_printf(MSG_DEBUG, " *AT_COUNTER %d", data->counter);
00475 eap_sim_msg_add(msg, EAP_SIM_AT_COUNTER, data->counter,
00476 NULL, 0);
00477 if (eap_sim_msg_add_encr_end(msg, data->k_encr,
00478 EAP_SIM_AT_PADDING)) {
00479 wpa_printf(MSG_WARNING, "EAP-SIM: Failed to encrypt "
00480 "AT_ENCR_DATA");
00481 eap_sim_msg_free(msg);
00482 return NULL;
00483 }
00484 }
00485 if (k_aut) {
00486 wpa_printf(MSG_DEBUG, " AT_MAC");
00487 eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC);
00488 }
00489 return eap_sim_msg_finish(msg, k_aut, (u8 *) "", 0);
00490 }
00491
00492
00493 static struct wpabuf * eap_sim_process_start(struct eap_sm *sm,
00494 struct eap_sim_data *data, u8 id,
00495 struct eap_sim_attrs *attr)
00496 {
00497 int selected_version = -1, id_error;
00498 size_t i;
00499 u8 *pos;
00500
00501 wpa_printf(MSG_DEBUG, "EAP-SIM: subtype Start");
00502 if (attr->version_list == NULL) {
00503 wpa_printf(MSG_INFO, "EAP-SIM: No AT_VERSION_LIST in "
00504 "SIM/Start");
00505 return eap_sim_client_error(data, id,
00506 EAP_SIM_UNSUPPORTED_VERSION);
00507 }
00508
00509 os_free(data->ver_list);
00510 data->ver_list = os_malloc(attr->version_list_len);
00511 if (data->ver_list == NULL) {
00512 wpa_printf(MSG_DEBUG, "EAP-SIM: Failed to allocate "
00513 "memory for version list");
00514 return eap_sim_client_error(data, id,
00515 EAP_SIM_UNABLE_TO_PROCESS_PACKET);
00516 }
00517 os_memcpy(data->ver_list, attr->version_list, attr->version_list_len);
00518 data->ver_list_len = attr->version_list_len;
00519 pos = data->ver_list;
00520 for (i = 0; i < data->ver_list_len / 2; i++) {
00521 int ver = pos[0] * 256 + pos[1];
00522 pos += 2;
00523 if (eap_sim_supported_ver(ver)) {
00524 selected_version = ver;
00525 break;
00526 }
00527 }
00528 if (selected_version < 0) {
00529 wpa_printf(MSG_INFO, "EAP-SIM: Could not find a supported "
00530 "version");
00531 return eap_sim_client_error(data, id,
00532 EAP_SIM_UNSUPPORTED_VERSION);
00533 }
00534 wpa_printf(MSG_DEBUG, "EAP-SIM: Selected Version %d",
00535 selected_version);
00536 data->selected_version = selected_version;
00537
00538 id_error = 0;
00539 switch (attr->id_req) {
00540 case NO_ID_REQ:
00541 break;
00542 case ANY_ID:
00543 if (data->num_id_req > 0)
00544 id_error++;
00545 data->num_id_req++;
00546 break;
00547 case FULLAUTH_ID:
00548 if (data->num_id_req > 1)
00549 id_error++;
00550 data->num_id_req++;
00551 break;
00552 case PERMANENT_ID:
00553 if (data->num_id_req > 2)
00554 id_error++;
00555 data->num_id_req++;
00556 break;
00557 }
00558 if (id_error) {
00559 wpa_printf(MSG_INFO, "EAP-SIM: Too many ID requests "
00560 "used within one authentication");
00561 return eap_sim_client_error(data, id,
00562 EAP_SIM_UNABLE_TO_PROCESS_PACKET);
00563 }
00564
00565 return eap_sim_response_start(sm, data, id, attr->id_req);
00566 }
00567
00568
00569 static struct wpabuf * eap_sim_process_challenge(struct eap_sm *sm,
00570 struct eap_sim_data *data,
00571 u8 id,
00572 const struct wpabuf *reqData,
00573 struct eap_sim_attrs *attr)
00574 {
00575 const u8 *identity;
00576 size_t identity_len;
00577 struct eap_sim_attrs eattr;
00578
00579 wpa_printf(MSG_DEBUG, "EAP-SIM: subtype Challenge");
00580 data->reauth = 0;
00581 if (!attr->mac || !attr->rand) {
00582 wpa_printf(MSG_WARNING, "EAP-SIM: Challenge message "
00583 "did not include%s%s",
00584 !attr->mac ? " AT_MAC" : "",
00585 !attr->rand ? " AT_RAND" : "");
00586 return eap_sim_client_error(data, id,
00587 EAP_SIM_UNABLE_TO_PROCESS_PACKET);
00588 }
00589
00590 wpa_printf(MSG_DEBUG, "EAP-SIM: %lu challenges",
00591 (unsigned long) attr->num_chal);
00592 if (attr->num_chal < data->min_num_chal) {
00593 wpa_printf(MSG_INFO, "EAP-SIM: Insufficient number of "
00594 "challenges (%lu)", (unsigned long) attr->num_chal);
00595 return eap_sim_client_error(data, id,
00596 EAP_SIM_INSUFFICIENT_NUM_OF_CHAL);
00597 }
00598 if (attr->num_chal > 3) {
00599 wpa_printf(MSG_INFO, "EAP-SIM: Too many challenges "
00600 "(%lu)", (unsigned long) attr->num_chal);
00601 return eap_sim_client_error(data, id,
00602 EAP_SIM_UNABLE_TO_PROCESS_PACKET);
00603 }
00604
00605
00606 if (os_memcmp(attr->rand, attr->rand + GSM_RAND_LEN,
00607 GSM_RAND_LEN) == 0 ||
00608 (attr->num_chal > 2 &&
00609 (os_memcmp(attr->rand, attr->rand + 2 * GSM_RAND_LEN,
00610 GSM_RAND_LEN) == 0 ||
00611 os_memcmp(attr->rand + GSM_RAND_LEN,
00612 attr->rand + 2 * GSM_RAND_LEN,
00613 GSM_RAND_LEN) == 0))) {
00614 wpa_printf(MSG_INFO, "EAP-SIM: Same RAND used multiple times");
00615 return eap_sim_client_error(data, id,
00616 EAP_SIM_RAND_NOT_FRESH);
00617 }
00618
00619 os_memcpy(data->rand, attr->rand, attr->num_chal * GSM_RAND_LEN);
00620 data->num_chal = attr->num_chal;
00621
00622 if (eap_sim_gsm_auth(sm, data)) {
00623 wpa_printf(MSG_WARNING, "EAP-SIM: GSM authentication failed");
00624 return eap_sim_client_error(data, id,
00625 EAP_SIM_UNABLE_TO_PROCESS_PACKET);
00626 }
00627 if (data->last_eap_identity) {
00628 identity = data->last_eap_identity;
00629 identity_len = data->last_eap_identity_len;
00630 } else if (data->pseudonym) {
00631 identity = data->pseudonym;
00632 identity_len = data->pseudonym_len;
00633 } else
00634 identity = eap_get_config_identity(sm, &identity_len);
00635 wpa_hexdump_ascii(MSG_DEBUG, "EAP-SIM: Selected identity for MK "
00636 "derivation", identity, identity_len);
00637 eap_sim_derive_mk(identity, identity_len, data->nonce_mt,
00638 data->selected_version, data->ver_list,
00639 data->ver_list_len, data->num_chal,
00640 (const u8 *) data->kc, data->mk);
00641 eap_sim_derive_keys(data->mk, data->k_encr, data->k_aut, data->msk,
00642 data->emsk);
00643 if (eap_sim_verify_mac(data->k_aut, reqData, attr->mac, data->nonce_mt,
00644 EAP_SIM_NONCE_MT_LEN)) {
00645 wpa_printf(MSG_WARNING, "EAP-SIM: Challenge message "
00646 "used invalid AT_MAC");
00647 return eap_sim_client_error(data, id,
00648 EAP_SIM_UNABLE_TO_PROCESS_PACKET);
00649 }
00650
00651
00652
00653
00654 eap_sim_clear_identities(data, CLEAR_PSEUDONYM | CLEAR_REAUTH_ID |
00655 CLEAR_EAP_ID);
00656
00657 if (attr->encr_data) {
00658 u8 *decrypted;
00659 decrypted = eap_sim_parse_encr(data->k_encr, attr->encr_data,
00660 attr->encr_data_len, attr->iv,
00661 &eattr, 0);
00662 if (decrypted == NULL) {
00663 return eap_sim_client_error(
00664 data, id, EAP_SIM_UNABLE_TO_PROCESS_PACKET);
00665 }
00666 eap_sim_learn_ids(data, &eattr);
00667 os_free(decrypted);
00668 }
00669
00670 if (data->result_ind && attr->result_ind)
00671 data->use_result_ind = 1;
00672
00673 if (data->state != FAILURE && data->state != RESULT_FAILURE) {
00674 eap_sim_state(data, data->use_result_ind ?
00675 RESULT_SUCCESS : SUCCESS);
00676 }
00677
00678 data->num_id_req = 0;
00679 data->num_notification = 0;
00680
00681
00682
00683 data->counter = 0;
00684 return eap_sim_response_challenge(data, id);
00685 }
00686
00687
00688 static int eap_sim_process_notification_reauth(struct eap_sim_data *data,
00689 struct eap_sim_attrs *attr)
00690 {
00691 struct eap_sim_attrs eattr;
00692 u8 *decrypted;
00693
00694 if (attr->encr_data == NULL || attr->iv == NULL) {
00695 wpa_printf(MSG_WARNING, "EAP-SIM: Notification message after "
00696 "reauth did not include encrypted data");
00697 return -1;
00698 }
00699
00700 decrypted = eap_sim_parse_encr(data->k_encr, attr->encr_data,
00701 attr->encr_data_len, attr->iv, &eattr,
00702 0);
00703 if (decrypted == NULL) {
00704 wpa_printf(MSG_WARNING, "EAP-SIM: Failed to parse encrypted "
00705 "data from notification message");
00706 return -1;
00707 }
00708
00709 if (eattr.counter < 0 || (size_t) eattr.counter != data->counter) {
00710 wpa_printf(MSG_WARNING, "EAP-SIM: Counter in notification "
00711 "message does not match with counter in reauth "
00712 "message");
00713 os_free(decrypted);
00714 return -1;
00715 }
00716
00717 os_free(decrypted);
00718 return 0;
00719 }
00720
00721
00722 static int eap_sim_process_notification_auth(struct eap_sim_data *data,
00723 const struct wpabuf *reqData,
00724 struct eap_sim_attrs *attr)
00725 {
00726 if (attr->mac == NULL) {
00727 wpa_printf(MSG_INFO, "EAP-SIM: no AT_MAC in after_auth "
00728 "Notification message");
00729 return -1;
00730 }
00731
00732 if (eap_sim_verify_mac(data->k_aut, reqData, attr->mac, (u8 *) "", 0))
00733 {
00734 wpa_printf(MSG_WARNING, "EAP-SIM: Notification message "
00735 "used invalid AT_MAC");
00736 return -1;
00737 }
00738
00739 if (data->reauth &&
00740 eap_sim_process_notification_reauth(data, attr)) {
00741 wpa_printf(MSG_WARNING, "EAP-SIM: Invalid notification "
00742 "message after reauth");
00743 return -1;
00744 }
00745
00746 return 0;
00747 }
00748
00749
00750 static struct wpabuf * eap_sim_process_notification(
00751 struct eap_sm *sm, struct eap_sim_data *data, u8 id,
00752 const struct wpabuf *reqData, struct eap_sim_attrs *attr)
00753 {
00754 wpa_printf(MSG_DEBUG, "EAP-SIM: subtype Notification");
00755 if (data->num_notification > 0) {
00756 wpa_printf(MSG_INFO, "EAP-SIM: too many notification "
00757 "rounds (only one allowed)");
00758 return eap_sim_client_error(data, id,
00759 EAP_SIM_UNABLE_TO_PROCESS_PACKET);
00760 }
00761 data->num_notification++;
00762 if (attr->notification == -1) {
00763 wpa_printf(MSG_INFO, "EAP-SIM: no AT_NOTIFICATION in "
00764 "Notification message");
00765 return eap_sim_client_error(data, id,
00766 EAP_SIM_UNABLE_TO_PROCESS_PACKET);
00767 }
00768
00769 if ((attr->notification & 0x4000) == 0 &&
00770 eap_sim_process_notification_auth(data, reqData, attr)) {
00771 return eap_sim_client_error(data, id,
00772 EAP_SIM_UNABLE_TO_PROCESS_PACKET);
00773 }
00774
00775 eap_sim_report_notification(sm->msg_ctx, attr->notification, 0);
00776 if (attr->notification >= 0 && attr->notification < 32768) {
00777 eap_sim_state(data, FAILURE);
00778 } else if (attr->notification == EAP_SIM_SUCCESS &&
00779 data->state == RESULT_SUCCESS)
00780 eap_sim_state(data, SUCCESS);
00781 return eap_sim_response_notification(data, id, attr->notification);
00782 }
00783
00784
00785 static struct wpabuf * eap_sim_process_reauthentication(
00786 struct eap_sm *sm, struct eap_sim_data *data, u8 id,
00787 const struct wpabuf *reqData, struct eap_sim_attrs *attr)
00788 {
00789 struct eap_sim_attrs eattr;
00790 u8 *decrypted;
00791
00792 wpa_printf(MSG_DEBUG, "EAP-SIM: subtype Reauthentication");
00793
00794 if (data->reauth_id == NULL) {
00795 wpa_printf(MSG_WARNING, "EAP-SIM: Server is trying "
00796 "reauthentication, but no reauth_id available");
00797 return eap_sim_client_error(data, id,
00798 EAP_SIM_UNABLE_TO_PROCESS_PACKET);
00799 }
00800
00801 data->reauth = 1;
00802 if (eap_sim_verify_mac(data->k_aut, reqData, attr->mac, (u8 *) "", 0))
00803 {
00804 wpa_printf(MSG_WARNING, "EAP-SIM: Reauthentication "
00805 "did not have valid AT_MAC");
00806 return eap_sim_client_error(data, id,
00807 EAP_SIM_UNABLE_TO_PROCESS_PACKET);
00808 }
00809
00810 if (attr->encr_data == NULL || attr->iv == NULL) {
00811 wpa_printf(MSG_WARNING, "EAP-SIM: Reauthentication "
00812 "message did not include encrypted data");
00813 return eap_sim_client_error(data, id,
00814 EAP_SIM_UNABLE_TO_PROCESS_PACKET);
00815 }
00816
00817 decrypted = eap_sim_parse_encr(data->k_encr, attr->encr_data,
00818 attr->encr_data_len, attr->iv, &eattr,
00819 0);
00820 if (decrypted == NULL) {
00821 wpa_printf(MSG_WARNING, "EAP-SIM: Failed to parse encrypted "
00822 "data from reauthentication message");
00823 return eap_sim_client_error(data, id,
00824 EAP_SIM_UNABLE_TO_PROCESS_PACKET);
00825 }
00826
00827 if (eattr.nonce_s == NULL || eattr.counter < 0) {
00828 wpa_printf(MSG_INFO, "EAP-SIM: (encr) No%s%s in reauth packet",
00829 !eattr.nonce_s ? " AT_NONCE_S" : "",
00830 eattr.counter < 0 ? " AT_COUNTER" : "");
00831 os_free(decrypted);
00832 return eap_sim_client_error(data, id,
00833 EAP_SIM_UNABLE_TO_PROCESS_PACKET);
00834 }
00835
00836 if (eattr.counter < 0 || (size_t) eattr.counter <= data->counter) {
00837 wpa_printf(MSG_INFO, "EAP-SIM: (encr) Invalid counter "
00838 "(%d <= %d)", eattr.counter, data->counter);
00839 data->counter_too_small = eattr.counter;
00840
00841
00842
00843
00844
00845 os_free(data->last_eap_identity);
00846 data->last_eap_identity = data->reauth_id;
00847 data->last_eap_identity_len = data->reauth_id_len;
00848 data->reauth_id = NULL;
00849 data->reauth_id_len = 0;
00850 os_free(decrypted);
00851 return eap_sim_response_reauth(data, id, 1);
00852 }
00853 data->counter = eattr.counter;
00854
00855 os_memcpy(data->nonce_s, eattr.nonce_s, EAP_SIM_NONCE_S_LEN);
00856 wpa_hexdump(MSG_DEBUG, "EAP-SIM: (encr) AT_NONCE_S",
00857 data->nonce_s, EAP_SIM_NONCE_S_LEN);
00858
00859 eap_sim_derive_keys_reauth(data->counter,
00860 data->reauth_id, data->reauth_id_len,
00861 data->nonce_s, data->mk, data->msk,
00862 data->emsk);
00863 eap_sim_clear_identities(data, CLEAR_REAUTH_ID | CLEAR_EAP_ID);
00864 eap_sim_learn_ids(data, &eattr);
00865
00866 if (data->result_ind && attr->result_ind)
00867 data->use_result_ind = 1;
00868
00869 if (data->state != FAILURE && data->state != RESULT_FAILURE) {
00870 eap_sim_state(data, data->use_result_ind ?
00871 RESULT_SUCCESS : SUCCESS);
00872 }
00873
00874 data->num_id_req = 0;
00875 data->num_notification = 0;
00876 if (data->counter > EAP_SIM_MAX_FAST_REAUTHS) {
00877 wpa_printf(MSG_DEBUG, "EAP-SIM: Maximum number of "
00878 "fast reauths performed - force fullauth");
00879 eap_sim_clear_identities(data, CLEAR_REAUTH_ID | CLEAR_EAP_ID);
00880 }
00881 os_free(decrypted);
00882 return eap_sim_response_reauth(data, id, 0);
00883 }
00884
00885
00886 static struct wpabuf * eap_sim_process(struct eap_sm *sm, void *priv,
00887 struct eap_method_ret *ret,
00888 const struct wpabuf *reqData)
00889 {
00890 struct eap_sim_data *data = priv;
00891 const struct eap_hdr *req;
00892 u8 subtype, id;
00893 struct wpabuf *res;
00894 const u8 *pos;
00895 struct eap_sim_attrs attr;
00896 size_t len;
00897
00898 wpa_hexdump_buf(MSG_DEBUG, "EAP-SIM: EAP data", reqData);
00899 if (eap_get_config_identity(sm, &len) == NULL) {
00900 wpa_printf(MSG_INFO, "EAP-SIM: Identity not configured");
00901 eap_sm_request_identity(sm);
00902 ret->ignore = TRUE;
00903 return NULL;
00904 }
00905
00906 pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_SIM, reqData, &len);
00907 if (pos == NULL || len < 1) {
00908 ret->ignore = TRUE;
00909 return NULL;
00910 }
00911 req = wpabuf_head(reqData);
00912 id = req->identifier;
00913 len = be_to_host16(req->length);
00914
00915 ret->ignore = FALSE;
00916 ret->methodState = METHOD_MAY_CONT;
00917 ret->decision = DECISION_FAIL;
00918 ret->allowNotifications = TRUE;
00919
00920 subtype = *pos++;
00921 wpa_printf(MSG_DEBUG, "EAP-SIM: Subtype=%d", subtype);
00922 pos += 2;
00923
00924 if (eap_sim_parse_attr(pos, wpabuf_head_u8(reqData) + len, &attr, 0,
00925 0)) {
00926 res = eap_sim_client_error(data, id,
00927 EAP_SIM_UNABLE_TO_PROCESS_PACKET);
00928 goto done;
00929 }
00930
00931 switch (subtype) {
00932 case EAP_SIM_SUBTYPE_START:
00933 res = eap_sim_process_start(sm, data, id, &attr);
00934 break;
00935 case EAP_SIM_SUBTYPE_CHALLENGE:
00936 res = eap_sim_process_challenge(sm, data, id, reqData, &attr);
00937 break;
00938 case EAP_SIM_SUBTYPE_NOTIFICATION:
00939 res = eap_sim_process_notification(sm, data, id, reqData,
00940 &attr);
00941 break;
00942 case EAP_SIM_SUBTYPE_REAUTHENTICATION:
00943 res = eap_sim_process_reauthentication(sm, data, id, reqData,
00944 &attr);
00945 break;
00946 case EAP_SIM_SUBTYPE_CLIENT_ERROR:
00947 wpa_printf(MSG_DEBUG, "EAP-SIM: subtype Client-Error");
00948 res = eap_sim_client_error(data, id,
00949 EAP_SIM_UNABLE_TO_PROCESS_PACKET);
00950 break;
00951 default:
00952 wpa_printf(MSG_DEBUG, "EAP-SIM: Unknown subtype=%d", subtype);
00953 res = eap_sim_client_error(data, id,
00954 EAP_SIM_UNABLE_TO_PROCESS_PACKET);
00955 break;
00956 }
00957
00958 done:
00959 if (data->state == FAILURE) {
00960 ret->decision = DECISION_FAIL;
00961 ret->methodState = METHOD_DONE;
00962 } else if (data->state == SUCCESS) {
00963 ret->decision = data->use_result_ind ?
00964 DECISION_UNCOND_SUCC : DECISION_COND_SUCC;
00965 ret->methodState = data->use_result_ind ?
00966 METHOD_DONE : METHOD_MAY_CONT;
00967 } else if (data->state == RESULT_FAILURE)
00968 ret->methodState = METHOD_CONT;
00969 else if (data->state == RESULT_SUCCESS)
00970 ret->methodState = METHOD_CONT;
00971
00972 if (ret->methodState == METHOD_DONE) {
00973 ret->allowNotifications = FALSE;
00974 }
00975
00976 return res;
00977 }
00978
00979
00980 static Boolean eap_sim_has_reauth_data(struct eap_sm *sm, void *priv)
00981 {
00982 struct eap_sim_data *data = priv;
00983 return data->pseudonym || data->reauth_id;
00984 }
00985
00986
00987 static void eap_sim_deinit_for_reauth(struct eap_sm *sm, void *priv)
00988 {
00989 struct eap_sim_data *data = priv;
00990 eap_sim_clear_identities(data, CLEAR_EAP_ID);
00991 data->use_result_ind = 0;
00992 }
00993
00994
00995 static void * eap_sim_init_for_reauth(struct eap_sm *sm, void *priv)
00996 {
00997 struct eap_sim_data *data = priv;
00998 if (os_get_random(data->nonce_mt, EAP_SIM_NONCE_MT_LEN)) {
00999 wpa_printf(MSG_WARNING, "EAP-SIM: Failed to get random data "
01000 "for NONCE_MT");
01001 os_free(data);
01002 return NULL;
01003 }
01004 data->num_id_req = 0;
01005 data->num_notification = 0;
01006 eap_sim_state(data, CONTINUE);
01007 return priv;
01008 }
01009
01010
01011 static const u8 * eap_sim_get_identity(struct eap_sm *sm, void *priv,
01012 size_t *len)
01013 {
01014 struct eap_sim_data *data = priv;
01015
01016 if (data->reauth_id) {
01017 *len = data->reauth_id_len;
01018 return data->reauth_id;
01019 }
01020
01021 if (data->pseudonym) {
01022 *len = data->pseudonym_len;
01023 return data->pseudonym;
01024 }
01025
01026 return NULL;
01027 }
01028
01029
01030 static Boolean eap_sim_isKeyAvailable(struct eap_sm *sm, void *priv)
01031 {
01032 struct eap_sim_data *data = priv;
01033 return data->state == SUCCESS;
01034 }
01035
01036
01037 static u8 * eap_sim_getKey(struct eap_sm *sm, void *priv, size_t *len)
01038 {
01039 struct eap_sim_data *data = priv;
01040 u8 *key;
01041
01042 if (data->state != SUCCESS)
01043 return NULL;
01044
01045 key = os_malloc(EAP_SIM_KEYING_DATA_LEN);
01046 if (key == NULL)
01047 return NULL;
01048
01049 *len = EAP_SIM_KEYING_DATA_LEN;
01050 os_memcpy(key, data->msk, EAP_SIM_KEYING_DATA_LEN);
01051
01052 return key;
01053 }
01054
01055
01056 static u8 * eap_sim_get_emsk(struct eap_sm *sm, void *priv, size_t *len)
01057 {
01058 struct eap_sim_data *data = priv;
01059 u8 *key;
01060
01061 if (data->state != SUCCESS)
01062 return NULL;
01063
01064 key = os_malloc(EAP_EMSK_LEN);
01065 if (key == NULL)
01066 return NULL;
01067
01068 *len = EAP_EMSK_LEN;
01069 os_memcpy(key, data->emsk, EAP_EMSK_LEN);
01070
01071 return key;
01072 }
01073
01074
01075 int eap_peer_sim_register(void)
01076 {
01077 struct eap_method *eap;
01078 int ret;
01079
01080 eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION,
01081 EAP_VENDOR_IETF, EAP_TYPE_SIM, "SIM");
01082 if (eap == NULL)
01083 return -1;
01084
01085 eap->init = eap_sim_init;
01086 eap->deinit = eap_sim_deinit;
01087 eap->process = eap_sim_process;
01088 eap->isKeyAvailable = eap_sim_isKeyAvailable;
01089 eap->getKey = eap_sim_getKey;
01090 eap->has_reauth_data = eap_sim_has_reauth_data;
01091 eap->deinit_for_reauth = eap_sim_deinit_for_reauth;
01092 eap->init_for_reauth = eap_sim_init_for_reauth;
01093 eap->get_identity = eap_sim_get_identity;
01094 eap->get_emsk = eap_sim_get_emsk;
01095
01096 ret = eap_peer_method_register(eap);
01097 if (ret)
01098 eap_peer_method_free(eap);
01099 return ret;
01100 }