eap_server_sim.c
Go to the documentation of this file.
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 }


wpa_supplicant
Author(s): Package maintained by Blaise Gassend
autogenerated on Thu Apr 24 2014 15:34:35