eap_aka.c

Go to the documentation of this file.
00001 
00016 #include "includes.h"
00017 
00018 #include "common.h"
00019 #include "eap_server/eap_i.h"
00020 #include "eap_common/eap_sim_common.h"
00021 #include "eap_server/eap_sim_db.h"
00022 #include "sha1.h"
00023 #include "sha256.h"
00024 #include "crypto.h"
00025 
00026 
00027 struct eap_aka_data {
00028         u8 mk[EAP_SIM_MK_LEN];
00029         u8 nonce_s[EAP_SIM_NONCE_S_LEN];
00030         u8 k_aut[EAP_AKA_PRIME_K_AUT_LEN];
00031         u8 k_encr[EAP_SIM_K_ENCR_LEN];
00032         u8 k_re[EAP_AKA_PRIME_K_RE_LEN]; /* EAP-AKA' only */
00033         u8 msk[EAP_SIM_KEYING_DATA_LEN];
00034         u8 emsk[EAP_EMSK_LEN];
00035         u8 rand[EAP_AKA_RAND_LEN];
00036         u8 autn[EAP_AKA_AUTN_LEN];
00037         u8 ck[EAP_AKA_CK_LEN];
00038         u8 ik[EAP_AKA_IK_LEN];
00039         u8 res[EAP_AKA_RES_MAX_LEN];
00040         size_t res_len;
00041         enum {
00042                 IDENTITY, CHALLENGE, REAUTH, NOTIFICATION, SUCCESS, FAILURE
00043         } state;
00044         char *next_pseudonym;
00045         char *next_reauth_id;
00046         u16 counter;
00047         struct eap_sim_reauth *reauth;
00048         int auts_reported; /* whether the current AUTS has been reported to the
00049                             * eap_sim_db */
00050         u16 notification;
00051         int use_result_ind;
00052 
00053         struct wpabuf *id_msgs;
00054         int pending_id;
00055         u8 eap_method;
00056         u8 *network_name;
00057         size_t network_name_len;
00058         u16 kdf;
00059 };
00060 
00061 
00062 static void eap_aka_determine_identity(struct eap_sm *sm,
00063                                        struct eap_aka_data *data,
00064                                        int before_identity, int after_reauth);
00065 
00066 
00067 static const char * eap_aka_state_txt(int state)
00068 {
00069         switch (state) {
00070         case IDENTITY:
00071                 return "IDENTITY";
00072         case CHALLENGE:
00073                 return "CHALLENGE";
00074         case REAUTH:
00075                 return "REAUTH";
00076         case SUCCESS:
00077                 return "SUCCESS";
00078         case FAILURE:
00079                 return "FAILURE";
00080         case NOTIFICATION:
00081                 return "NOTIFICATION";
00082         default:
00083                 return "Unknown?!";
00084         }
00085 }
00086 
00087 
00088 static void eap_aka_state(struct eap_aka_data *data, int state)
00089 {
00090         wpa_printf(MSG_DEBUG, "EAP-AKA: %s -> %s",
00091                    eap_aka_state_txt(data->state),
00092                    eap_aka_state_txt(state));
00093         data->state = state;
00094 }
00095 
00096 
00097 static void * eap_aka_init(struct eap_sm *sm)
00098 {
00099         struct eap_aka_data *data;
00100 
00101         if (sm->eap_sim_db_priv == NULL) {
00102                 wpa_printf(MSG_WARNING, "EAP-AKA: eap_sim_db not configured");
00103                 return NULL;
00104         }
00105 
00106         data = os_zalloc(sizeof(*data));
00107         if (data == NULL)
00108                 return NULL;
00109 
00110         data->eap_method = EAP_TYPE_AKA;
00111 
00112         data->state = IDENTITY;
00113         eap_aka_determine_identity(sm, data, 1, 0);
00114         data->pending_id = -1;
00115 
00116         return data;
00117 }
00118 
00119 
00120 #ifdef EAP_SERVER_AKA_PRIME
00121 static void * eap_aka_prime_init(struct eap_sm *sm)
00122 {
00123         struct eap_aka_data *data;
00124         /* TODO: make ANID configurable; see 3GPP TS 24.302 */
00125         char *network_name = "WLAN";
00126 
00127         if (sm->eap_sim_db_priv == NULL) {
00128                 wpa_printf(MSG_WARNING, "EAP-AKA: eap_sim_db not configured");
00129                 return NULL;
00130         }
00131 
00132         data = os_zalloc(sizeof(*data));
00133         if (data == NULL)
00134                 return NULL;
00135 
00136         data->eap_method = EAP_TYPE_AKA_PRIME;
00137         data->network_name = os_malloc(os_strlen(network_name));
00138         if (data->network_name == NULL) {
00139                 os_free(data);
00140                 return NULL;
00141         }
00142 
00143         data->network_name_len = os_strlen(network_name);
00144         os_memcpy(data->network_name, network_name, data->network_name_len);
00145 
00146         data->state = IDENTITY;
00147         eap_aka_determine_identity(sm, data, 1, 0);
00148         data->pending_id = -1;
00149 
00150         return data;
00151 }
00152 #endif /* EAP_SERVER_AKA_PRIME */
00153 
00154 
00155 static void eap_aka_reset(struct eap_sm *sm, void *priv)
00156 {
00157         struct eap_aka_data *data = priv;
00158         os_free(data->next_pseudonym);
00159         os_free(data->next_reauth_id);
00160         wpabuf_free(data->id_msgs);
00161         os_free(data->network_name);
00162         os_free(data);
00163 }
00164 
00165 
00166 static int eap_aka_add_id_msg(struct eap_aka_data *data,
00167                               const struct wpabuf *msg)
00168 {
00169         if (msg == NULL)
00170                 return -1;
00171 
00172         if (data->id_msgs == NULL) {
00173                 data->id_msgs = wpabuf_dup(msg);
00174                 return data->id_msgs == NULL ? -1 : 0;
00175         }
00176 
00177         if (wpabuf_resize(&data->id_msgs, wpabuf_len(msg)) < 0)
00178                 return -1;
00179         wpabuf_put_buf(data->id_msgs, msg);
00180 
00181         return 0;
00182 }
00183 
00184 
00185 static void eap_aka_add_checkcode(struct eap_aka_data *data,
00186                                   struct eap_sim_msg *msg)
00187 {
00188         const u8 *addr;
00189         size_t len;
00190         u8 hash[SHA256_MAC_LEN];
00191 
00192         wpa_printf(MSG_DEBUG, "   AT_CHECKCODE");
00193 
00194         if (data->id_msgs == NULL) {
00195                 /*
00196                  * No EAP-AKA/Identity packets were exchanged - send empty
00197                  * checkcode.
00198                  */
00199                 eap_sim_msg_add(msg, EAP_SIM_AT_CHECKCODE, 0, NULL, 0);
00200                 return;
00201         }
00202 
00203         /* Checkcode is SHA1 hash over all EAP-AKA/Identity packets. */
00204         addr = wpabuf_head(data->id_msgs);
00205         len = wpabuf_len(data->id_msgs);
00206         wpa_hexdump(MSG_MSGDUMP, "EAP-AKA: AT_CHECKCODE data", addr, len);
00207         if (data->eap_method == EAP_TYPE_AKA_PRIME)
00208                 sha256_vector(1, &addr, &len, hash);
00209         else
00210                 sha1_vector(1, &addr, &len, hash);
00211 
00212         eap_sim_msg_add(msg, EAP_SIM_AT_CHECKCODE, 0, hash,
00213                         data->eap_method == EAP_TYPE_AKA_PRIME ?
00214                         EAP_AKA_PRIME_CHECKCODE_LEN : EAP_AKA_CHECKCODE_LEN);
00215 }
00216 
00217 
00218 static int eap_aka_verify_checkcode(struct eap_aka_data *data,
00219                                     const u8 *checkcode, size_t checkcode_len)
00220 {
00221         const u8 *addr;
00222         size_t len;
00223         u8 hash[SHA256_MAC_LEN];
00224         size_t hash_len;
00225 
00226         if (checkcode == NULL)
00227                 return -1;
00228 
00229         if (data->id_msgs == NULL) {
00230                 if (checkcode_len != 0) {
00231                         wpa_printf(MSG_DEBUG, "EAP-AKA: Checkcode from peer "
00232                                    "indicates that AKA/Identity messages were "
00233                                    "used, but they were not");
00234                         return -1;
00235                 }
00236                 return 0;
00237         }
00238 
00239         hash_len = data->eap_method == EAP_TYPE_AKA_PRIME ?
00240                 EAP_AKA_PRIME_CHECKCODE_LEN : EAP_AKA_CHECKCODE_LEN;
00241 
00242         if (checkcode_len != hash_len) {
00243                 wpa_printf(MSG_DEBUG, "EAP-AKA: Checkcode from peer indicates "
00244                            "that AKA/Identity message were not used, but they "
00245                            "were");
00246                 return -1;
00247         }
00248 
00249         /* Checkcode is SHA1 hash over all EAP-AKA/Identity packets. */
00250         addr = wpabuf_head(data->id_msgs);
00251         len = wpabuf_len(data->id_msgs);
00252         if (data->eap_method == EAP_TYPE_AKA_PRIME)
00253                 sha256_vector(1, &addr, &len, hash);
00254         else
00255                 sha1_vector(1, &addr, &len, hash);
00256 
00257         if (os_memcmp(hash, checkcode, hash_len) != 0) {
00258                 wpa_printf(MSG_DEBUG, "EAP-AKA: Mismatch in AT_CHECKCODE");
00259                 return -1;
00260         }
00261 
00262         return 0;
00263 }
00264 
00265 
00266 static struct wpabuf * eap_aka_build_identity(struct eap_sm *sm,
00267                                               struct eap_aka_data *data, u8 id)
00268 {
00269         struct eap_sim_msg *msg;
00270         struct wpabuf *buf;
00271 
00272         wpa_printf(MSG_DEBUG, "EAP-AKA: Generating Identity");
00273         msg = eap_sim_msg_init(EAP_CODE_REQUEST, id, data->eap_method,
00274                                EAP_AKA_SUBTYPE_IDENTITY);
00275         if (eap_sim_db_identity_known(sm->eap_sim_db_priv, sm->identity,
00276                                       sm->identity_len)) {
00277                 wpa_printf(MSG_DEBUG, "   AT_PERMANENT_ID_REQ");
00278                 eap_sim_msg_add(msg, EAP_SIM_AT_PERMANENT_ID_REQ, 0, NULL, 0);
00279         } else {
00280                 /*
00281                  * RFC 4187, Chap. 4.1.4 recommends that identity from EAP is
00282                  * ignored and the AKA/Identity is used to request the
00283                  * identity.
00284                  */
00285                 wpa_printf(MSG_DEBUG, "   AT_ANY_ID_REQ");
00286                 eap_sim_msg_add(msg, EAP_SIM_AT_ANY_ID_REQ, 0, NULL, 0);
00287         }
00288         buf = eap_sim_msg_finish(msg, NULL, NULL, 0);
00289         if (eap_aka_add_id_msg(data, buf) < 0) {
00290                 wpabuf_free(buf);
00291                 return NULL;
00292         }
00293         data->pending_id = id;
00294         return buf;
00295 }
00296 
00297 
00298 static int eap_aka_build_encr(struct eap_sm *sm, struct eap_aka_data *data,
00299                               struct eap_sim_msg *msg, u16 counter,
00300                               const u8 *nonce_s)
00301 {
00302         os_free(data->next_pseudonym);
00303         data->next_pseudonym =
00304                 eap_sim_db_get_next_pseudonym(sm->eap_sim_db_priv, 1);
00305         os_free(data->next_reauth_id);
00306         if (data->counter <= EAP_AKA_MAX_FAST_REAUTHS) {
00307                 data->next_reauth_id =
00308                         eap_sim_db_get_next_reauth_id(sm->eap_sim_db_priv, 1);
00309         } else {
00310                 wpa_printf(MSG_DEBUG, "EAP-AKA: Max fast re-authentication "
00311                            "count exceeded - force full authentication");
00312                 data->next_reauth_id = NULL;
00313         }
00314 
00315         if (data->next_pseudonym == NULL && data->next_reauth_id == NULL &&
00316             counter == 0 && nonce_s == NULL)
00317                 return 0;
00318 
00319         wpa_printf(MSG_DEBUG, "   AT_IV");
00320         wpa_printf(MSG_DEBUG, "   AT_ENCR_DATA");
00321         eap_sim_msg_add_encr_start(msg, EAP_SIM_AT_IV, EAP_SIM_AT_ENCR_DATA);
00322 
00323         if (counter > 0) {
00324                 wpa_printf(MSG_DEBUG, "   *AT_COUNTER (%u)", counter);
00325                 eap_sim_msg_add(msg, EAP_SIM_AT_COUNTER, counter, NULL, 0);
00326         }
00327 
00328         if (nonce_s) {
00329                 wpa_printf(MSG_DEBUG, "   *AT_NONCE_S");
00330                 eap_sim_msg_add(msg, EAP_SIM_AT_NONCE_S, 0, nonce_s,
00331                                 EAP_SIM_NONCE_S_LEN);
00332         }
00333 
00334         if (data->next_pseudonym) {
00335                 wpa_printf(MSG_DEBUG, "   *AT_NEXT_PSEUDONYM (%s)",
00336                            data->next_pseudonym);
00337                 eap_sim_msg_add(msg, EAP_SIM_AT_NEXT_PSEUDONYM,
00338                                 os_strlen(data->next_pseudonym),
00339                                 (u8 *) data->next_pseudonym,
00340                                 os_strlen(data->next_pseudonym));
00341         }
00342 
00343         if (data->next_reauth_id) {
00344                 wpa_printf(MSG_DEBUG, "   *AT_NEXT_REAUTH_ID (%s)",
00345                            data->next_reauth_id);
00346                 eap_sim_msg_add(msg, EAP_SIM_AT_NEXT_REAUTH_ID,
00347                                 os_strlen(data->next_reauth_id),
00348                                 (u8 *) data->next_reauth_id,
00349                                 os_strlen(data->next_reauth_id));
00350         }
00351 
00352         if (eap_sim_msg_add_encr_end(msg, data->k_encr, EAP_SIM_AT_PADDING)) {
00353                 wpa_printf(MSG_WARNING, "EAP-AKA: Failed to encrypt "
00354                            "AT_ENCR_DATA");
00355                 return -1;
00356         }
00357 
00358         return 0;
00359 }
00360 
00361 
00362 static struct wpabuf * eap_aka_build_challenge(struct eap_sm *sm,
00363                                                struct eap_aka_data *data,
00364                                                u8 id)
00365 {
00366         struct eap_sim_msg *msg;
00367 
00368         wpa_printf(MSG_DEBUG, "EAP-AKA: Generating Challenge");
00369         msg = eap_sim_msg_init(EAP_CODE_REQUEST, id, data->eap_method,
00370                                EAP_AKA_SUBTYPE_CHALLENGE);
00371         wpa_printf(MSG_DEBUG, "   AT_RAND");
00372         eap_sim_msg_add(msg, EAP_SIM_AT_RAND, 0, data->rand, EAP_AKA_RAND_LEN);
00373         wpa_printf(MSG_DEBUG, "   AT_AUTN");
00374         eap_sim_msg_add(msg, EAP_SIM_AT_AUTN, 0, data->autn, EAP_AKA_AUTN_LEN);
00375         if (data->eap_method == EAP_TYPE_AKA_PRIME) {
00376                 if (data->kdf) {
00377                         /* Add the selected KDF into the beginning */
00378                         wpa_printf(MSG_DEBUG, "   AT_KDF");
00379                         eap_sim_msg_add(msg, EAP_SIM_AT_KDF, data->kdf,
00380                                         NULL, 0);
00381                 }
00382                 wpa_printf(MSG_DEBUG, "   AT_KDF");
00383                 eap_sim_msg_add(msg, EAP_SIM_AT_KDF, EAP_AKA_PRIME_KDF,
00384                                 NULL, 0);
00385                 wpa_printf(MSG_DEBUG, "   AT_KDF_INPUT");
00386                 eap_sim_msg_add(msg, EAP_SIM_AT_KDF_INPUT,
00387                                 data->network_name_len,
00388                                 data->network_name, data->network_name_len);
00389         }
00390 
00391         if (eap_aka_build_encr(sm, data, msg, 0, NULL)) {
00392                 eap_sim_msg_free(msg);
00393                 return NULL;
00394         }
00395 
00396         eap_aka_add_checkcode(data, msg);
00397 
00398         if (sm->eap_sim_aka_result_ind) {
00399                 wpa_printf(MSG_DEBUG, "   AT_RESULT_IND");
00400                 eap_sim_msg_add(msg, EAP_SIM_AT_RESULT_IND, 0, NULL, 0);
00401         }
00402 
00403 #ifdef EAP_SERVER_AKA_PRIME
00404         if (data->eap_method == EAP_TYPE_AKA) {
00405                 u16 flags = 0;
00406                 int i;
00407                 int aka_prime_preferred = 0;
00408 
00409                 i = 0;
00410                 while (sm->user && i < EAP_MAX_METHODS &&
00411                        (sm->user->methods[i].vendor != EAP_VENDOR_IETF ||
00412                         sm->user->methods[i].method != EAP_TYPE_NONE)) {
00413                         if (sm->user->methods[i].vendor == EAP_VENDOR_IETF) {
00414                                 if (sm->user->methods[i].method ==
00415                                     EAP_TYPE_AKA)
00416                                         break;
00417                                 if (sm->user->methods[i].method ==
00418                                     EAP_TYPE_AKA_PRIME) {
00419                                         aka_prime_preferred = 1;
00420                                         break;
00421                                 }
00422                         }
00423                         i++;
00424                 }
00425 
00426                 if (aka_prime_preferred)
00427                         flags |= EAP_AKA_BIDDING_FLAG_D;
00428                 eap_sim_msg_add(msg, EAP_SIM_AT_BIDDING, flags, NULL, 0);
00429         }
00430 #endif /* EAP_SERVER_AKA_PRIME */
00431 
00432         wpa_printf(MSG_DEBUG, "   AT_MAC");
00433         eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC);
00434         return eap_sim_msg_finish(msg, data->k_aut, NULL, 0);
00435 }
00436 
00437 
00438 static struct wpabuf * eap_aka_build_reauth(struct eap_sm *sm,
00439                                             struct eap_aka_data *data, u8 id)
00440 {
00441         struct eap_sim_msg *msg;
00442 
00443         wpa_printf(MSG_DEBUG, "EAP-AKA: Generating Re-authentication");
00444 
00445         if (os_get_random(data->nonce_s, EAP_SIM_NONCE_S_LEN))
00446                 return NULL;
00447         wpa_hexdump_key(MSG_MSGDUMP, "EAP-AKA: NONCE_S",
00448                         data->nonce_s, EAP_SIM_NONCE_S_LEN);
00449 
00450         if (data->eap_method == EAP_TYPE_AKA_PRIME) {
00451                 eap_aka_prime_derive_keys_reauth(data->k_re, data->counter,
00452                                                  sm->identity,
00453                                                  sm->identity_len,
00454                                                  data->nonce_s,
00455                                                  data->msk, data->emsk);
00456         } else {
00457                 eap_sim_derive_keys(data->mk, data->k_encr, data->k_aut,
00458                                     data->msk, data->emsk);
00459                 eap_sim_derive_keys_reauth(data->counter, sm->identity,
00460                                            sm->identity_len, data->nonce_s,
00461                                            data->mk, data->msk, data->emsk);
00462         }
00463 
00464         msg = eap_sim_msg_init(EAP_CODE_REQUEST, id, data->eap_method,
00465                                EAP_AKA_SUBTYPE_REAUTHENTICATION);
00466 
00467         if (eap_aka_build_encr(sm, data, msg, data->counter, data->nonce_s)) {
00468                 eap_sim_msg_free(msg);
00469                 return NULL;
00470         }
00471 
00472         eap_aka_add_checkcode(data, msg);
00473 
00474         if (sm->eap_sim_aka_result_ind) {
00475                 wpa_printf(MSG_DEBUG, "   AT_RESULT_IND");
00476                 eap_sim_msg_add(msg, EAP_SIM_AT_RESULT_IND, 0, NULL, 0);
00477         }
00478 
00479         wpa_printf(MSG_DEBUG, "   AT_MAC");
00480         eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC);
00481         return eap_sim_msg_finish(msg, data->k_aut, NULL, 0);
00482 }
00483 
00484 
00485 static struct wpabuf * eap_aka_build_notification(struct eap_sm *sm,
00486                                                   struct eap_aka_data *data,
00487                                                   u8 id)
00488 {
00489         struct eap_sim_msg *msg;
00490 
00491         wpa_printf(MSG_DEBUG, "EAP-AKA: Generating Notification");
00492         msg = eap_sim_msg_init(EAP_CODE_REQUEST, id, data->eap_method,
00493                                EAP_AKA_SUBTYPE_NOTIFICATION);
00494         wpa_printf(MSG_DEBUG, "   AT_NOTIFICATION (%d)", data->notification);
00495         eap_sim_msg_add(msg, EAP_SIM_AT_NOTIFICATION, data->notification,
00496                         NULL, 0);
00497         if (data->use_result_ind) {
00498                 if (data->reauth) {
00499                         wpa_printf(MSG_DEBUG, "   AT_IV");
00500                         wpa_printf(MSG_DEBUG, "   AT_ENCR_DATA");
00501                         eap_sim_msg_add_encr_start(msg, EAP_SIM_AT_IV,
00502                                                    EAP_SIM_AT_ENCR_DATA);
00503                         wpa_printf(MSG_DEBUG, "   *AT_COUNTER (%u)",
00504                                    data->counter);
00505                         eap_sim_msg_add(msg, EAP_SIM_AT_COUNTER, data->counter,
00506                                         NULL, 0);
00507 
00508                         if (eap_sim_msg_add_encr_end(msg, data->k_encr,
00509                                                      EAP_SIM_AT_PADDING)) {
00510                                 wpa_printf(MSG_WARNING, "EAP-AKA: Failed to "
00511                                            "encrypt AT_ENCR_DATA");
00512                                 eap_sim_msg_free(msg);
00513                                 return NULL;
00514                         }
00515                 }
00516 
00517                 wpa_printf(MSG_DEBUG, "   AT_MAC");
00518                 eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC);
00519         }
00520         return eap_sim_msg_finish(msg, data->k_aut, NULL, 0);
00521 }
00522 
00523 
00524 static struct wpabuf * eap_aka_buildReq(struct eap_sm *sm, void *priv, u8 id)
00525 {
00526         struct eap_aka_data *data = priv;
00527 
00528         data->auts_reported = 0;
00529         switch (data->state) {
00530         case IDENTITY:
00531                 return eap_aka_build_identity(sm, data, id);
00532         case CHALLENGE:
00533                 return eap_aka_build_challenge(sm, data, id);
00534         case REAUTH:
00535                 return eap_aka_build_reauth(sm, data, id);
00536         case NOTIFICATION:
00537                 return eap_aka_build_notification(sm, data, id);
00538         default:
00539                 wpa_printf(MSG_DEBUG, "EAP-AKA: Unknown state %d in "
00540                            "buildReq", data->state);
00541                 break;
00542         }
00543         return NULL;
00544 }
00545 
00546 
00547 static Boolean eap_aka_check(struct eap_sm *sm, void *priv,
00548                              struct wpabuf *respData)
00549 {
00550         struct eap_aka_data *data = priv;
00551         const u8 *pos;
00552         size_t len;
00553 
00554         pos = eap_hdr_validate(EAP_VENDOR_IETF, data->eap_method, respData,
00555                                &len);
00556         if (pos == NULL || len < 3) {
00557                 wpa_printf(MSG_INFO, "EAP-AKA: Invalid frame");
00558                 return TRUE;
00559         }
00560 
00561         return FALSE;
00562 }
00563 
00564 
00565 static Boolean eap_aka_subtype_ok(struct eap_aka_data *data, u8 subtype)
00566 {
00567         if (subtype == EAP_AKA_SUBTYPE_CLIENT_ERROR ||
00568             subtype == EAP_AKA_SUBTYPE_AUTHENTICATION_REJECT)
00569                 return FALSE;
00570 
00571         switch (data->state) {
00572         case IDENTITY:
00573                 if (subtype != EAP_AKA_SUBTYPE_IDENTITY) {
00574                         wpa_printf(MSG_INFO, "EAP-AKA: Unexpected response "
00575                                    "subtype %d", subtype);
00576                         return TRUE;
00577                 }
00578                 break;
00579         case CHALLENGE:
00580                 if (subtype != EAP_AKA_SUBTYPE_CHALLENGE &&
00581                     subtype != EAP_AKA_SUBTYPE_SYNCHRONIZATION_FAILURE) {
00582                         wpa_printf(MSG_INFO, "EAP-AKA: Unexpected response "
00583                                    "subtype %d", subtype);
00584                         return TRUE;
00585                 }
00586                 break;
00587         case REAUTH:
00588                 if (subtype != EAP_AKA_SUBTYPE_REAUTHENTICATION) {
00589                         wpa_printf(MSG_INFO, "EAP-AKA: Unexpected response "
00590                                    "subtype %d", subtype);
00591                         return TRUE;
00592                 }
00593                 break;
00594         case NOTIFICATION:
00595                 if (subtype != EAP_AKA_SUBTYPE_NOTIFICATION) {
00596                         wpa_printf(MSG_INFO, "EAP-AKA: Unexpected response "
00597                                    "subtype %d", subtype);
00598                         return TRUE;
00599                 }
00600                 break;
00601         default:
00602                 wpa_printf(MSG_INFO, "EAP-AKA: Unexpected state (%d) for "
00603                            "processing a response", data->state);
00604                 return TRUE;
00605         }
00606 
00607         return FALSE;
00608 }
00609 
00610 
00611 static void eap_aka_determine_identity(struct eap_sm *sm,
00612                                        struct eap_aka_data *data,
00613                                        int before_identity, int after_reauth)
00614 {
00615         const u8 *identity;
00616         size_t identity_len;
00617         int res;
00618 
00619         identity = NULL;
00620         identity_len = 0;
00621 
00622         if (after_reauth && data->reauth) {
00623                 identity = data->reauth->identity;
00624                 identity_len = data->reauth->identity_len;
00625         } else if (sm->identity && sm->identity_len > 0 &&
00626                    sm->identity[0] == EAP_AKA_PERMANENT_PREFIX) {
00627                 identity = sm->identity;
00628                 identity_len = sm->identity_len;
00629         } else {
00630                 identity = eap_sim_db_get_permanent(sm->eap_sim_db_priv,
00631                                                     sm->identity,
00632                                                     sm->identity_len,
00633                                                     &identity_len);
00634                 if (identity == NULL) {
00635                         data->reauth = eap_sim_db_get_reauth_entry(
00636                                 sm->eap_sim_db_priv, sm->identity,
00637                                 sm->identity_len);
00638                         if (data->reauth &&
00639                             data->reauth->aka_prime !=
00640                             (data->eap_method == EAP_TYPE_AKA_PRIME)) {
00641                                 wpa_printf(MSG_DEBUG, "EAP-AKA: Reauth data "
00642                                            "was for different AKA version");
00643                                 data->reauth = NULL;
00644                         }
00645                         if (data->reauth) {
00646                                 wpa_printf(MSG_DEBUG, "EAP-AKA: Using fast "
00647                                            "re-authentication");
00648                                 identity = data->reauth->identity;
00649                                 identity_len = data->reauth->identity_len;
00650                                 data->counter = data->reauth->counter;
00651                                 if (data->eap_method == EAP_TYPE_AKA_PRIME) {
00652                                         os_memcpy(data->k_encr,
00653                                                   data->reauth->k_encr,
00654                                                   EAP_SIM_K_ENCR_LEN);
00655                                         os_memcpy(data->k_aut,
00656                                                   data->reauth->k_aut,
00657                                                   EAP_AKA_PRIME_K_AUT_LEN);
00658                                         os_memcpy(data->k_re,
00659                                                   data->reauth->k_re,
00660                                                   EAP_AKA_PRIME_K_RE_LEN);
00661                                 } else {
00662                                         os_memcpy(data->mk, data->reauth->mk,
00663                                                   EAP_SIM_MK_LEN);
00664                                 }
00665                         }
00666                 }
00667         }
00668 
00669         if (identity == NULL ||
00670             eap_sim_db_identity_known(sm->eap_sim_db_priv, sm->identity,
00671                                       sm->identity_len) < 0) {
00672                 if (before_identity) {
00673                         wpa_printf(MSG_DEBUG, "EAP-AKA: Permanent user name "
00674                                    "not known - send AKA-Identity request");
00675                         eap_aka_state(data, IDENTITY);
00676                         return;
00677                 } else {
00678                         wpa_printf(MSG_DEBUG, "EAP-AKA: Unknown whether the "
00679                                    "permanent user name is known; try to use "
00680                                    "it");
00681                         /* eap_sim_db_get_aka_auth() will report failure, if
00682                          * this identity is not known. */
00683                 }
00684         }
00685 
00686         wpa_hexdump_ascii(MSG_DEBUG, "EAP-AKA: Identity",
00687                           identity, identity_len);
00688 
00689         if (!after_reauth && data->reauth) {
00690                 eap_aka_state(data, REAUTH);
00691                 return;
00692         }
00693 
00694         res = eap_sim_db_get_aka_auth(sm->eap_sim_db_priv, identity,
00695                                       identity_len, data->rand, data->autn,
00696                                       data->ik, data->ck, data->res,
00697                                       &data->res_len, sm);
00698         if (res == EAP_SIM_DB_PENDING) {
00699                 wpa_printf(MSG_DEBUG, "EAP-AKA: AKA authentication data "
00700                            "not yet available - pending request");
00701                 sm->method_pending = METHOD_PENDING_WAIT;
00702                 return;
00703         }
00704 
00705 #ifdef EAP_SERVER_AKA_PRIME
00706         if (data->eap_method == EAP_TYPE_AKA_PRIME) {
00707                 /* Note: AUTN = (SQN ^ AK) || AMF || MAC which gives us the
00708                  * needed 6-octet SQN ^AK for CK',IK' derivation */
00709                 eap_aka_prime_derive_ck_ik_prime(data->ck, data->ik,
00710                                                  data->autn,
00711                                                  data->network_name,
00712                                                  data->network_name_len);
00713         }
00714 #endif /* EAP_SERVER_AKA_PRIME */
00715 
00716         data->reauth = NULL;
00717         data->counter = 0; /* reset re-auth counter since this is full auth */
00718 
00719         if (res != 0) {
00720                 wpa_printf(MSG_INFO, "EAP-AKA: Failed to get AKA "
00721                            "authentication data for the peer");
00722                 data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
00723                 eap_aka_state(data, NOTIFICATION);
00724                 return;
00725         }
00726         if (sm->method_pending == METHOD_PENDING_WAIT) {
00727                 wpa_printf(MSG_DEBUG, "EAP-AKA: AKA authentication data "
00728                            "available - abort pending wait");
00729                 sm->method_pending = METHOD_PENDING_NONE;
00730         }
00731 
00732         identity_len = sm->identity_len;
00733         while (identity_len > 0 && sm->identity[identity_len - 1] == '\0') {
00734                 wpa_printf(MSG_DEBUG, "EAP-AKA: Workaround - drop last null "
00735                            "character from identity");
00736                 identity_len--;
00737         }
00738         wpa_hexdump_ascii(MSG_DEBUG, "EAP-AKA: Identity for MK derivation",
00739                           sm->identity, identity_len);
00740 
00741         if (data->eap_method == EAP_TYPE_AKA_PRIME) {
00742                 eap_aka_prime_derive_keys(identity, identity_len, data->ik,
00743                                           data->ck, data->k_encr, data->k_aut,
00744                                           data->k_re, data->msk, data->emsk);
00745         } else {
00746                 eap_aka_derive_mk(sm->identity, identity_len, data->ik,
00747                                   data->ck, data->mk);
00748                 eap_sim_derive_keys(data->mk, data->k_encr, data->k_aut,
00749                                     data->msk, data->emsk);
00750         }
00751 
00752         eap_aka_state(data, CHALLENGE);
00753 }
00754 
00755 
00756 static void eap_aka_process_identity(struct eap_sm *sm,
00757                                      struct eap_aka_data *data,
00758                                      struct wpabuf *respData,
00759                                      struct eap_sim_attrs *attr)
00760 {
00761         wpa_printf(MSG_DEBUG, "EAP-AKA: Processing Identity");
00762 
00763         if (attr->mac || attr->iv || attr->encr_data) {
00764                 wpa_printf(MSG_WARNING, "EAP-AKA: Unexpected attribute "
00765                            "received in EAP-Response/AKA-Identity");
00766                 data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
00767                 eap_aka_state(data, NOTIFICATION);
00768                 return;
00769         }
00770 
00771         if (attr->identity) {
00772                 os_free(sm->identity);
00773                 sm->identity = os_malloc(attr->identity_len);
00774                 if (sm->identity) {
00775                         os_memcpy(sm->identity, attr->identity,
00776                                   attr->identity_len);
00777                         sm->identity_len = attr->identity_len;
00778                 }
00779         }
00780 
00781         eap_aka_determine_identity(sm, data, 0, 0);
00782         if (eap_get_id(respData) == data->pending_id) {
00783                 data->pending_id = -1;
00784                 eap_aka_add_id_msg(data, respData);
00785         }
00786 }
00787 
00788 
00789 static int eap_aka_verify_mac(struct eap_aka_data *data,
00790                               const struct wpabuf *req,
00791                               const u8 *mac, const u8 *extra,
00792                               size_t extra_len)
00793 {
00794         if (data->eap_method == EAP_TYPE_AKA_PRIME)
00795                 return eap_sim_verify_mac_sha256(data->k_aut, req, mac, extra,
00796                                                  extra_len);
00797         return eap_sim_verify_mac(data->k_aut, req, mac, extra, extra_len);
00798 }
00799 
00800 
00801 static void eap_aka_process_challenge(struct eap_sm *sm,
00802                                       struct eap_aka_data *data,
00803                                       struct wpabuf *respData,
00804                                       struct eap_sim_attrs *attr)
00805 {
00806         const u8 *identity;
00807         size_t identity_len;
00808 
00809         wpa_printf(MSG_DEBUG, "EAP-AKA: Processing Challenge");
00810 
00811 #ifdef EAP_SERVER_AKA_PRIME
00812 #if 0
00813         /* KDF negotiation; to be enabled only after more than one KDF is
00814          * supported */
00815         if (data->eap_method == EAP_TYPE_AKA_PRIME &&
00816             attr->kdf_count == 1 && attr->mac == NULL) {
00817                 if (attr->kdf[0] != EAP_AKA_PRIME_KDF) {
00818                         wpa_printf(MSG_WARNING, "EAP-AKA': Peer selected "
00819                                    "unknown KDF");
00820                         data->notification =
00821                                 EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
00822                         eap_aka_state(data, NOTIFICATION);
00823                         return;
00824                 }
00825 
00826                 data->kdf = attr->kdf[0];
00827 
00828                 /* Allow negotiation to continue with the selected KDF by
00829                  * sending another Challenge message */
00830                 wpa_printf(MSG_DEBUG, "EAP-AKA': KDF %d selected", data->kdf);
00831                 return;
00832         }
00833 #endif
00834 #endif /* EAP_SERVER_AKA_PRIME */
00835 
00836         if (attr->checkcode &&
00837             eap_aka_verify_checkcode(data, attr->checkcode,
00838                                      attr->checkcode_len)) {
00839                 wpa_printf(MSG_WARNING, "EAP-AKA: Invalid AT_CHECKCODE in the "
00840                            "message");
00841                 data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
00842                 eap_aka_state(data, NOTIFICATION);
00843                 return;
00844         }
00845         if (attr->mac == NULL ||
00846             eap_aka_verify_mac(data, respData, attr->mac, NULL, 0)) {
00847                 wpa_printf(MSG_WARNING, "EAP-AKA: Challenge message "
00848                            "did not include valid AT_MAC");
00849                 data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
00850                 eap_aka_state(data, NOTIFICATION);
00851                 return;
00852         }
00853 
00854         /*
00855          * AT_RES is padded, so verify that there is enough room for RES and
00856          * that the RES length in bits matches with the expected RES.
00857          */
00858         if (attr->res == NULL || attr->res_len < data->res_len ||
00859             attr->res_len_bits != data->res_len * 8 ||
00860             os_memcmp(attr->res, data->res, data->res_len) != 0) {
00861                 wpa_printf(MSG_WARNING, "EAP-AKA: Challenge message did not "
00862                            "include valid AT_RES (attr len=%lu, res len=%lu "
00863                            "bits, expected %lu bits)",
00864                            (unsigned long) attr->res_len,
00865                            (unsigned long) attr->res_len_bits,
00866                            (unsigned long) data->res_len * 8);
00867                 data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
00868                 eap_aka_state(data, NOTIFICATION);
00869                 return;
00870         }
00871 
00872         wpa_printf(MSG_DEBUG, "EAP-AKA: Challenge response includes the "
00873                    "correct AT_MAC");
00874         if (sm->eap_sim_aka_result_ind && attr->result_ind) {
00875                 data->use_result_ind = 1;
00876                 data->notification = EAP_SIM_SUCCESS;
00877                 eap_aka_state(data, NOTIFICATION);
00878         } else
00879                 eap_aka_state(data, SUCCESS);
00880 
00881         identity = eap_sim_db_get_permanent(sm->eap_sim_db_priv, sm->identity,
00882                                             sm->identity_len, &identity_len);
00883         if (identity == NULL) {
00884                 identity = sm->identity;
00885                 identity_len = sm->identity_len;
00886         }
00887 
00888         if (data->next_pseudonym) {
00889                 eap_sim_db_add_pseudonym(sm->eap_sim_db_priv, identity,
00890                                          identity_len,
00891                                          data->next_pseudonym);
00892                 data->next_pseudonym = NULL;
00893         }
00894         if (data->next_reauth_id) {
00895                 if (data->eap_method == EAP_TYPE_AKA_PRIME) {
00896 #ifdef EAP_SERVER_AKA_PRIME
00897                         eap_sim_db_add_reauth_prime(sm->eap_sim_db_priv,
00898                                                     identity,
00899                                                     identity_len,
00900                                                     data->next_reauth_id,
00901                                                     data->counter + 1,
00902                                                     data->k_encr, data->k_aut,
00903                                                     data->k_re);
00904 #endif /* EAP_SERVER_AKA_PRIME */
00905                 } else {
00906                         eap_sim_db_add_reauth(sm->eap_sim_db_priv, identity,
00907                                               identity_len,
00908                                               data->next_reauth_id,
00909                                               data->counter + 1,
00910                                               data->mk);
00911                 }
00912                 data->next_reauth_id = NULL;
00913         }
00914 }
00915 
00916 
00917 static void eap_aka_process_sync_failure(struct eap_sm *sm,
00918                                          struct eap_aka_data *data,
00919                                          struct wpabuf *respData,
00920                                          struct eap_sim_attrs *attr)
00921 {
00922         wpa_printf(MSG_DEBUG, "EAP-AKA: Processing Synchronization-Failure");
00923 
00924         if (attr->auts == NULL) {
00925                 wpa_printf(MSG_WARNING, "EAP-AKA: Synchronization-Failure "
00926                            "message did not include valid AT_AUTS");
00927                 data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
00928                 eap_aka_state(data, NOTIFICATION);
00929                 return;
00930         }
00931 
00932         /* Avoid re-reporting AUTS when processing pending EAP packet by
00933          * maintaining a local flag stating whether this AUTS has already been
00934          * reported. */
00935         if (!data->auts_reported &&
00936             eap_sim_db_resynchronize(sm->eap_sim_db_priv, sm->identity,
00937                                      sm->identity_len, attr->auts,
00938                                      data->rand)) {
00939                 wpa_printf(MSG_WARNING, "EAP-AKA: Resynchronization failed");
00940                 data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
00941                 eap_aka_state(data, NOTIFICATION);
00942                 return;
00943         }
00944         data->auts_reported = 1;
00945 
00946         /* Try again after resynchronization */
00947         eap_aka_determine_identity(sm, data, 0, 0);
00948 }
00949 
00950 
00951 static void eap_aka_process_reauth(struct eap_sm *sm,
00952                                    struct eap_aka_data *data,
00953                                    struct wpabuf *respData,
00954                                    struct eap_sim_attrs *attr)
00955 {
00956         struct eap_sim_attrs eattr;
00957         u8 *decrypted = NULL;
00958         const u8 *identity, *id2;
00959         size_t identity_len, id2_len;
00960 
00961         wpa_printf(MSG_DEBUG, "EAP-AKA: Processing Reauthentication");
00962 
00963         if (attr->mac == NULL ||
00964             eap_aka_verify_mac(data, respData, attr->mac, data->nonce_s,
00965                                EAP_SIM_NONCE_S_LEN)) {
00966                 wpa_printf(MSG_WARNING, "EAP-AKA: Re-authentication message "
00967                            "did not include valid AT_MAC");
00968                 goto fail;
00969         }
00970 
00971         if (attr->encr_data == NULL || attr->iv == NULL) {
00972                 wpa_printf(MSG_WARNING, "EAP-AKA: Reauthentication "
00973                            "message did not include encrypted data");
00974                 goto fail;
00975         }
00976 
00977         decrypted = eap_sim_parse_encr(data->k_encr, attr->encr_data,
00978                                        attr->encr_data_len, attr->iv, &eattr,
00979                                        0);
00980         if (decrypted == NULL) {
00981                 wpa_printf(MSG_WARNING, "EAP-AKA: Failed to parse encrypted "
00982                            "data from reauthentication message");
00983                 goto fail;
00984         }
00985 
00986         if (eattr.counter != data->counter) {
00987                 wpa_printf(MSG_WARNING, "EAP-AKA: Re-authentication message "
00988                            "used incorrect counter %u, expected %u",
00989                            eattr.counter, data->counter);
00990                 goto fail;
00991         }
00992         os_free(decrypted);
00993         decrypted = NULL;
00994 
00995         wpa_printf(MSG_DEBUG, "EAP-AKA: Re-authentication response includes "
00996                    "the correct AT_MAC");
00997 
00998         if (eattr.counter_too_small) {
00999                 wpa_printf(MSG_DEBUG, "EAP-AKA: Re-authentication response "
01000                            "included AT_COUNTER_TOO_SMALL - starting full "
01001                            "authentication");
01002                 eap_aka_determine_identity(sm, data, 0, 1);
01003                 return;
01004         }
01005 
01006         if (sm->eap_sim_aka_result_ind && attr->result_ind) {
01007                 data->use_result_ind = 1;
01008                 data->notification = EAP_SIM_SUCCESS;
01009                 eap_aka_state(data, NOTIFICATION);
01010         } else
01011                 eap_aka_state(data, SUCCESS);
01012 
01013         if (data->reauth) {
01014                 identity = data->reauth->identity;
01015                 identity_len = data->reauth->identity_len;
01016         } else {
01017                 identity = sm->identity;
01018                 identity_len = sm->identity_len;
01019         }
01020 
01021         id2 = eap_sim_db_get_permanent(sm->eap_sim_db_priv, identity,
01022                                        identity_len, &id2_len);
01023         if (id2) {
01024                 identity = id2;
01025                 identity_len = id2_len;
01026         }
01027 
01028         if (data->next_pseudonym) {
01029                 eap_sim_db_add_pseudonym(sm->eap_sim_db_priv, identity,
01030                                          identity_len, data->next_pseudonym);
01031                 data->next_pseudonym = NULL;
01032         }
01033         if (data->next_reauth_id) {
01034                 if (data->eap_method == EAP_TYPE_AKA_PRIME) {
01035 #ifdef EAP_SERVER_AKA_PRIME
01036                         eap_sim_db_add_reauth_prime(sm->eap_sim_db_priv,
01037                                                     identity,
01038                                                     identity_len,
01039                                                     data->next_reauth_id,
01040                                                     data->counter + 1,
01041                                                     data->k_encr, data->k_aut,
01042                                                     data->k_re);
01043 #endif /* EAP_SERVER_AKA_PRIME */
01044                 } else {
01045                         eap_sim_db_add_reauth(sm->eap_sim_db_priv, identity,
01046                                               identity_len,
01047                                               data->next_reauth_id,
01048                                               data->counter + 1,
01049                                               data->mk);
01050                 }
01051                 data->next_reauth_id = NULL;
01052         } else {
01053                 eap_sim_db_remove_reauth(sm->eap_sim_db_priv, data->reauth);
01054                 data->reauth = NULL;
01055         }
01056 
01057         return;
01058 
01059 fail:
01060         data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
01061         eap_aka_state(data, NOTIFICATION);
01062         eap_sim_db_remove_reauth(sm->eap_sim_db_priv, data->reauth);
01063         data->reauth = NULL;
01064         os_free(decrypted);
01065 }
01066 
01067 
01068 static void eap_aka_process_client_error(struct eap_sm *sm,
01069                                          struct eap_aka_data *data,
01070                                          struct wpabuf *respData,
01071                                          struct eap_sim_attrs *attr)
01072 {
01073         wpa_printf(MSG_DEBUG, "EAP-AKA: Client reported error %d",
01074                    attr->client_error_code);
01075         if (data->notification == EAP_SIM_SUCCESS && data->use_result_ind)
01076                 eap_aka_state(data, SUCCESS);
01077         else
01078                 eap_aka_state(data, FAILURE);
01079 }
01080 
01081 
01082 static void eap_aka_process_authentication_reject(
01083         struct eap_sm *sm, struct eap_aka_data *data,
01084         struct wpabuf *respData, struct eap_sim_attrs *attr)
01085 {
01086         wpa_printf(MSG_DEBUG, "EAP-AKA: Client rejected authentication");
01087         eap_aka_state(data, FAILURE);
01088 }
01089 
01090 
01091 static void eap_aka_process_notification(struct eap_sm *sm,
01092                                          struct eap_aka_data *data,
01093                                          struct wpabuf *respData,
01094                                          struct eap_sim_attrs *attr)
01095 {
01096         wpa_printf(MSG_DEBUG, "EAP-AKA: Client replied to notification");
01097         if (data->notification == EAP_SIM_SUCCESS && data->use_result_ind)
01098                 eap_aka_state(data, SUCCESS);
01099         else
01100                 eap_aka_state(data, FAILURE);
01101 }
01102 
01103 
01104 static void eap_aka_process(struct eap_sm *sm, void *priv,
01105                             struct wpabuf *respData)
01106 {
01107         struct eap_aka_data *data = priv;
01108         const u8 *pos, *end;
01109         u8 subtype;
01110         size_t len;
01111         struct eap_sim_attrs attr;
01112 
01113         pos = eap_hdr_validate(EAP_VENDOR_IETF, data->eap_method, respData,
01114                                &len);
01115         if (pos == NULL || len < 3)
01116                 return;
01117 
01118         end = pos + len;
01119         subtype = *pos;
01120         pos += 3;
01121 
01122         if (eap_aka_subtype_ok(data, subtype)) {
01123                 wpa_printf(MSG_DEBUG, "EAP-AKA: Unrecognized or unexpected "
01124                            "EAP-AKA Subtype in EAP Response");
01125                 data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
01126                 eap_aka_state(data, NOTIFICATION);
01127                 return;
01128         }
01129 
01130         if (eap_sim_parse_attr(pos, end, &attr,
01131                                data->eap_method == EAP_TYPE_AKA_PRIME ? 2 : 1,
01132                                0)) {
01133                 wpa_printf(MSG_DEBUG, "EAP-AKA: Failed to parse attributes");
01134                 data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
01135                 eap_aka_state(data, NOTIFICATION);
01136                 return;
01137         }
01138 
01139         if (subtype == EAP_AKA_SUBTYPE_CLIENT_ERROR) {
01140                 eap_aka_process_client_error(sm, data, respData, &attr);
01141                 return;
01142         }
01143 
01144         if (subtype == EAP_AKA_SUBTYPE_AUTHENTICATION_REJECT) {
01145                 eap_aka_process_authentication_reject(sm, data, respData,
01146                                                       &attr);
01147                 return;
01148         }
01149 
01150         switch (data->state) {
01151         case IDENTITY:
01152                 eap_aka_process_identity(sm, data, respData, &attr);
01153                 break;
01154         case CHALLENGE:
01155                 if (subtype == EAP_AKA_SUBTYPE_SYNCHRONIZATION_FAILURE) {
01156                         eap_aka_process_sync_failure(sm, data, respData,
01157                                                      &attr);
01158                 } else {
01159                         eap_aka_process_challenge(sm, data, respData, &attr);
01160                 }
01161                 break;
01162         case REAUTH:
01163                 eap_aka_process_reauth(sm, data, respData, &attr);
01164                 break;
01165         case NOTIFICATION:
01166                 eap_aka_process_notification(sm, data, respData, &attr);
01167                 break;
01168         default:
01169                 wpa_printf(MSG_DEBUG, "EAP-AKA: Unknown state %d in "
01170                            "process", data->state);
01171                 break;
01172         }
01173 }
01174 
01175 
01176 static Boolean eap_aka_isDone(struct eap_sm *sm, void *priv)
01177 {
01178         struct eap_aka_data *data = priv;
01179         return data->state == SUCCESS || data->state == FAILURE;
01180 }
01181 
01182 
01183 static u8 * eap_aka_getKey(struct eap_sm *sm, void *priv, size_t *len)
01184 {
01185         struct eap_aka_data *data = priv;
01186         u8 *key;
01187 
01188         if (data->state != SUCCESS)
01189                 return NULL;
01190 
01191         key = os_malloc(EAP_SIM_KEYING_DATA_LEN);
01192         if (key == NULL)
01193                 return NULL;
01194         os_memcpy(key, data->msk, EAP_SIM_KEYING_DATA_LEN);
01195         *len = EAP_SIM_KEYING_DATA_LEN;
01196         return key;
01197 }
01198 
01199 
01200 static u8 * eap_aka_get_emsk(struct eap_sm *sm, void *priv, size_t *len)
01201 {
01202         struct eap_aka_data *data = priv;
01203         u8 *key;
01204 
01205         if (data->state != SUCCESS)
01206                 return NULL;
01207 
01208         key = os_malloc(EAP_EMSK_LEN);
01209         if (key == NULL)
01210                 return NULL;
01211         os_memcpy(key, data->emsk, EAP_EMSK_LEN);
01212         *len = EAP_EMSK_LEN;
01213         return key;
01214 }
01215 
01216 
01217 static Boolean eap_aka_isSuccess(struct eap_sm *sm, void *priv)
01218 {
01219         struct eap_aka_data *data = priv;
01220         return data->state == SUCCESS;
01221 }
01222 
01223 
01224 int eap_server_aka_register(void)
01225 {
01226         struct eap_method *eap;
01227         int ret;
01228 
01229         eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION,
01230                                       EAP_VENDOR_IETF, EAP_TYPE_AKA, "AKA");
01231         if (eap == NULL)
01232                 return -1;
01233 
01234         eap->init = eap_aka_init;
01235         eap->reset = eap_aka_reset;
01236         eap->buildReq = eap_aka_buildReq;
01237         eap->check = eap_aka_check;
01238         eap->process = eap_aka_process;
01239         eap->isDone = eap_aka_isDone;
01240         eap->getKey = eap_aka_getKey;
01241         eap->isSuccess = eap_aka_isSuccess;
01242         eap->get_emsk = eap_aka_get_emsk;
01243 
01244         ret = eap_server_method_register(eap);
01245         if (ret)
01246                 eap_server_method_free(eap);
01247         return ret;
01248 }
01249 
01250 
01251 #ifdef EAP_SERVER_AKA_PRIME
01252 int eap_server_aka_prime_register(void)
01253 {
01254         struct eap_method *eap;
01255         int ret;
01256 
01257         eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION,
01258                                       EAP_VENDOR_IETF, EAP_TYPE_AKA_PRIME,
01259                                       "AKA'");
01260         if (eap == NULL)
01261                 return -1;
01262 
01263         eap->init = eap_aka_prime_init;
01264         eap->reset = eap_aka_reset;
01265         eap->buildReq = eap_aka_buildReq;
01266         eap->check = eap_aka_check;
01267         eap->process = eap_aka_process;
01268         eap->isDone = eap_aka_isDone;
01269         eap->getKey = eap_aka_getKey;
01270         eap->isSuccess = eap_aka_isSuccess;
01271         eap->get_emsk = eap_aka_get_emsk;
01272 
01273         ret = eap_server_method_register(eap);
01274         if (ret)
01275                 eap_server_method_free(eap);
01276 
01277         return ret;
01278 }
01279 #endif /* EAP_SERVER_AKA_PRIME */
01280 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines

Generated on Sat Nov 21 23:16:51 2009 for hostapd by  doxygen 1.6.1