$search
00001 /* 00002 * wpa_supplicant - WPA/RSN IE and KDE processing 00003 * Copyright (c) 2003-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 "wpa.h" 00019 #include "pmksa_cache.h" 00020 #include "common/ieee802_11_defs.h" 00021 #include "wpa_i.h" 00022 #include "wpa_ie.h" 00023 00024 00025 static int wpa_selector_to_bitfield(const u8 *s) 00026 { 00027 if (RSN_SELECTOR_GET(s) == WPA_CIPHER_SUITE_NONE) 00028 return WPA_CIPHER_NONE; 00029 if (RSN_SELECTOR_GET(s) == WPA_CIPHER_SUITE_WEP40) 00030 return WPA_CIPHER_WEP40; 00031 if (RSN_SELECTOR_GET(s) == WPA_CIPHER_SUITE_TKIP) 00032 return WPA_CIPHER_TKIP; 00033 if (RSN_SELECTOR_GET(s) == WPA_CIPHER_SUITE_CCMP) 00034 return WPA_CIPHER_CCMP; 00035 if (RSN_SELECTOR_GET(s) == WPA_CIPHER_SUITE_WEP104) 00036 return WPA_CIPHER_WEP104; 00037 return 0; 00038 } 00039 00040 00041 static int wpa_key_mgmt_to_bitfield(const u8 *s) 00042 { 00043 if (RSN_SELECTOR_GET(s) == WPA_AUTH_KEY_MGMT_UNSPEC_802_1X) 00044 return WPA_KEY_MGMT_IEEE8021X; 00045 if (RSN_SELECTOR_GET(s) == WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X) 00046 return WPA_KEY_MGMT_PSK; 00047 if (RSN_SELECTOR_GET(s) == WPA_AUTH_KEY_MGMT_NONE) 00048 return WPA_KEY_MGMT_WPA_NONE; 00049 return 0; 00050 } 00051 00052 00053 static int wpa_parse_wpa_ie_wpa(const u8 *wpa_ie, size_t wpa_ie_len, 00054 struct wpa_ie_data *data) 00055 { 00056 const struct wpa_ie_hdr *hdr; 00057 const u8 *pos; 00058 int left; 00059 int i, count; 00060 00061 os_memset(data, 0, sizeof(*data)); 00062 data->proto = WPA_PROTO_WPA; 00063 data->pairwise_cipher = WPA_CIPHER_TKIP; 00064 data->group_cipher = WPA_CIPHER_TKIP; 00065 data->key_mgmt = WPA_KEY_MGMT_IEEE8021X; 00066 data->capabilities = 0; 00067 data->pmkid = NULL; 00068 data->num_pmkid = 0; 00069 data->mgmt_group_cipher = 0; 00070 00071 if (wpa_ie_len == 0) { 00072 /* No WPA IE - fail silently */ 00073 return -1; 00074 } 00075 00076 if (wpa_ie_len < sizeof(struct wpa_ie_hdr)) { 00077 wpa_printf(MSG_DEBUG, "%s: ie len too short %lu", 00078 __func__, (unsigned long) wpa_ie_len); 00079 return -1; 00080 } 00081 00082 hdr = (const struct wpa_ie_hdr *) wpa_ie; 00083 00084 if (hdr->elem_id != WLAN_EID_VENDOR_SPECIFIC || 00085 hdr->len != wpa_ie_len - 2 || 00086 RSN_SELECTOR_GET(hdr->oui) != WPA_OUI_TYPE || 00087 WPA_GET_LE16(hdr->version) != WPA_VERSION) { 00088 wpa_printf(MSG_DEBUG, "%s: malformed ie or unknown version", 00089 __func__); 00090 return -1; 00091 } 00092 00093 pos = (const u8 *) (hdr + 1); 00094 left = wpa_ie_len - sizeof(*hdr); 00095 00096 if (left >= WPA_SELECTOR_LEN) { 00097 data->group_cipher = wpa_selector_to_bitfield(pos); 00098 pos += WPA_SELECTOR_LEN; 00099 left -= WPA_SELECTOR_LEN; 00100 } else if (left > 0) { 00101 wpa_printf(MSG_DEBUG, "%s: ie length mismatch, %u too much", 00102 __func__, left); 00103 return -1; 00104 } 00105 00106 if (left >= 2) { 00107 data->pairwise_cipher = 0; 00108 count = WPA_GET_LE16(pos); 00109 pos += 2; 00110 left -= 2; 00111 if (count == 0 || left < count * WPA_SELECTOR_LEN) { 00112 wpa_printf(MSG_DEBUG, "%s: ie count botch (pairwise), " 00113 "count %u left %u", __func__, count, left); 00114 return -1; 00115 } 00116 for (i = 0; i < count; i++) { 00117 data->pairwise_cipher |= wpa_selector_to_bitfield(pos); 00118 pos += WPA_SELECTOR_LEN; 00119 left -= WPA_SELECTOR_LEN; 00120 } 00121 } else if (left == 1) { 00122 wpa_printf(MSG_DEBUG, "%s: ie too short (for key mgmt)", 00123 __func__); 00124 return -1; 00125 } 00126 00127 if (left >= 2) { 00128 data->key_mgmt = 0; 00129 count = WPA_GET_LE16(pos); 00130 pos += 2; 00131 left -= 2; 00132 if (count == 0 || left < count * WPA_SELECTOR_LEN) { 00133 wpa_printf(MSG_DEBUG, "%s: ie count botch (key mgmt), " 00134 "count %u left %u", __func__, count, left); 00135 return -1; 00136 } 00137 for (i = 0; i < count; i++) { 00138 data->key_mgmt |= wpa_key_mgmt_to_bitfield(pos); 00139 pos += WPA_SELECTOR_LEN; 00140 left -= WPA_SELECTOR_LEN; 00141 } 00142 } else if (left == 1) { 00143 wpa_printf(MSG_DEBUG, "%s: ie too short (for capabilities)", 00144 __func__); 00145 return -1; 00146 } 00147 00148 if (left >= 2) { 00149 data->capabilities = WPA_GET_LE16(pos); 00150 pos += 2; 00151 left -= 2; 00152 } 00153 00154 if (left > 0) { 00155 wpa_printf(MSG_DEBUG, "%s: ie has %u trailing bytes - ignored", 00156 __func__, left); 00157 } 00158 00159 return 0; 00160 } 00161 00162 00172 int wpa_parse_wpa_ie(const u8 *wpa_ie, size_t wpa_ie_len, 00173 struct wpa_ie_data *data) 00174 { 00175 if (wpa_ie_len >= 1 && wpa_ie[0] == WLAN_EID_RSN) 00176 return wpa_parse_wpa_ie_rsn(wpa_ie, wpa_ie_len, data); 00177 else 00178 return wpa_parse_wpa_ie_wpa(wpa_ie, wpa_ie_len, data); 00179 } 00180 00181 00182 static int wpa_gen_wpa_ie_wpa(u8 *wpa_ie, size_t wpa_ie_len, 00183 int pairwise_cipher, int group_cipher, 00184 int key_mgmt) 00185 { 00186 u8 *pos; 00187 struct wpa_ie_hdr *hdr; 00188 00189 if (wpa_ie_len < sizeof(*hdr) + WPA_SELECTOR_LEN + 00190 2 + WPA_SELECTOR_LEN + 2 + WPA_SELECTOR_LEN) 00191 return -1; 00192 00193 hdr = (struct wpa_ie_hdr *) wpa_ie; 00194 hdr->elem_id = WLAN_EID_VENDOR_SPECIFIC; 00195 RSN_SELECTOR_PUT(hdr->oui, WPA_OUI_TYPE); 00196 WPA_PUT_LE16(hdr->version, WPA_VERSION); 00197 pos = (u8 *) (hdr + 1); 00198 00199 if (group_cipher == WPA_CIPHER_CCMP) { 00200 RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_CCMP); 00201 } else if (group_cipher == WPA_CIPHER_TKIP) { 00202 RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_TKIP); 00203 } else if (group_cipher == WPA_CIPHER_WEP104) { 00204 RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_WEP104); 00205 } else if (group_cipher == WPA_CIPHER_WEP40) { 00206 RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_WEP40); 00207 } else { 00208 wpa_printf(MSG_WARNING, "Invalid group cipher (%d).", 00209 group_cipher); 00210 return -1; 00211 } 00212 pos += WPA_SELECTOR_LEN; 00213 00214 *pos++ = 1; 00215 *pos++ = 0; 00216 if (pairwise_cipher == WPA_CIPHER_CCMP) { 00217 RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_CCMP); 00218 } else if (pairwise_cipher == WPA_CIPHER_TKIP) { 00219 RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_TKIP); 00220 } else if (pairwise_cipher == WPA_CIPHER_NONE) { 00221 RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_NONE); 00222 } else { 00223 wpa_printf(MSG_WARNING, "Invalid pairwise cipher (%d).", 00224 pairwise_cipher); 00225 return -1; 00226 } 00227 pos += WPA_SELECTOR_LEN; 00228 00229 *pos++ = 1; 00230 *pos++ = 0; 00231 if (key_mgmt == WPA_KEY_MGMT_IEEE8021X) { 00232 RSN_SELECTOR_PUT(pos, WPA_AUTH_KEY_MGMT_UNSPEC_802_1X); 00233 } else if (key_mgmt == WPA_KEY_MGMT_PSK) { 00234 RSN_SELECTOR_PUT(pos, WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X); 00235 } else if (key_mgmt == WPA_KEY_MGMT_WPA_NONE) { 00236 RSN_SELECTOR_PUT(pos, WPA_AUTH_KEY_MGMT_NONE); 00237 } else { 00238 wpa_printf(MSG_WARNING, "Invalid key management type (%d).", 00239 key_mgmt); 00240 return -1; 00241 } 00242 pos += WPA_SELECTOR_LEN; 00243 00244 /* WPA Capabilities; use defaults, so no need to include it */ 00245 00246 hdr->len = (pos - wpa_ie) - 2; 00247 00248 WPA_ASSERT((size_t) (pos - wpa_ie) <= wpa_ie_len); 00249 00250 return pos - wpa_ie; 00251 } 00252 00253 00254 static int wpa_gen_wpa_ie_rsn(u8 *rsn_ie, size_t rsn_ie_len, 00255 int pairwise_cipher, int group_cipher, 00256 int key_mgmt, int mgmt_group_cipher, 00257 struct wpa_sm *sm) 00258 { 00259 #ifndef CONFIG_NO_WPA2 00260 u8 *pos; 00261 struct rsn_ie_hdr *hdr; 00262 u16 capab; 00263 00264 if (rsn_ie_len < sizeof(*hdr) + RSN_SELECTOR_LEN + 00265 2 + RSN_SELECTOR_LEN + 2 + RSN_SELECTOR_LEN + 2 + 00266 (sm->cur_pmksa ? 2 + PMKID_LEN : 0)) { 00267 wpa_printf(MSG_DEBUG, "RSN: Too short IE buffer (%lu bytes)", 00268 (unsigned long) rsn_ie_len); 00269 return -1; 00270 } 00271 00272 hdr = (struct rsn_ie_hdr *) rsn_ie; 00273 hdr->elem_id = WLAN_EID_RSN; 00274 WPA_PUT_LE16(hdr->version, RSN_VERSION); 00275 pos = (u8 *) (hdr + 1); 00276 00277 if (group_cipher == WPA_CIPHER_CCMP) { 00278 RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP); 00279 } else if (group_cipher == WPA_CIPHER_TKIP) { 00280 RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_TKIP); 00281 } else if (group_cipher == WPA_CIPHER_WEP104) { 00282 RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_WEP104); 00283 } else if (group_cipher == WPA_CIPHER_WEP40) { 00284 RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_WEP40); 00285 } else { 00286 wpa_printf(MSG_WARNING, "Invalid group cipher (%d).", 00287 group_cipher); 00288 return -1; 00289 } 00290 pos += RSN_SELECTOR_LEN; 00291 00292 *pos++ = 1; 00293 *pos++ = 0; 00294 if (pairwise_cipher == WPA_CIPHER_CCMP) { 00295 RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP); 00296 } else if (pairwise_cipher == WPA_CIPHER_TKIP) { 00297 RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_TKIP); 00298 } else if (pairwise_cipher == WPA_CIPHER_NONE) { 00299 RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_NONE); 00300 } else { 00301 wpa_printf(MSG_WARNING, "Invalid pairwise cipher (%d).", 00302 pairwise_cipher); 00303 return -1; 00304 } 00305 pos += RSN_SELECTOR_LEN; 00306 00307 *pos++ = 1; 00308 *pos++ = 0; 00309 if (key_mgmt == WPA_KEY_MGMT_IEEE8021X) { 00310 RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_UNSPEC_802_1X); 00311 } else if (key_mgmt == WPA_KEY_MGMT_PSK) { 00312 RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X); 00313 #ifdef CONFIG_IEEE80211R 00314 } else if (key_mgmt == WPA_KEY_MGMT_FT_IEEE8021X) { 00315 RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_802_1X); 00316 } else if (key_mgmt == WPA_KEY_MGMT_FT_PSK) { 00317 RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_PSK); 00318 #endif /* CONFIG_IEEE80211R */ 00319 #ifdef CONFIG_IEEE80211W 00320 } else if (key_mgmt == WPA_KEY_MGMT_IEEE8021X_SHA256) { 00321 RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_802_1X_SHA256); 00322 } else if (key_mgmt == WPA_KEY_MGMT_PSK_SHA256) { 00323 RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_PSK_SHA256); 00324 #endif /* CONFIG_IEEE80211W */ 00325 } else { 00326 wpa_printf(MSG_WARNING, "Invalid key management type (%d).", 00327 key_mgmt); 00328 return -1; 00329 } 00330 pos += RSN_SELECTOR_LEN; 00331 00332 /* RSN Capabilities */ 00333 capab = 0; 00334 #ifdef CONFIG_IEEE80211W 00335 if (sm->mfp) 00336 capab |= WPA_CAPABILITY_MFPC; 00337 if (sm->mfp == 2) 00338 capab |= WPA_CAPABILITY_MFPR; 00339 #endif /* CONFIG_IEEE80211W */ 00340 WPA_PUT_LE16(pos, capab); 00341 pos += 2; 00342 00343 if (sm->cur_pmksa) { 00344 /* PMKID Count (2 octets, little endian) */ 00345 *pos++ = 1; 00346 *pos++ = 0; 00347 /* PMKID */ 00348 os_memcpy(pos, sm->cur_pmksa->pmkid, PMKID_LEN); 00349 pos += PMKID_LEN; 00350 } 00351 00352 #ifdef CONFIG_IEEE80211W 00353 if (mgmt_group_cipher == WPA_CIPHER_AES_128_CMAC) { 00354 if (!sm->cur_pmksa) { 00355 /* PMKID Count */ 00356 WPA_PUT_LE16(pos, 0); 00357 pos += 2; 00358 } 00359 00360 /* Management Group Cipher Suite */ 00361 RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_AES_128_CMAC); 00362 pos += RSN_SELECTOR_LEN; 00363 } 00364 #endif /* CONFIG_IEEE80211W */ 00365 00366 hdr->len = (pos - rsn_ie) - 2; 00367 00368 WPA_ASSERT((size_t) (pos - rsn_ie) <= rsn_ie_len); 00369 00370 return pos - rsn_ie; 00371 #else /* CONFIG_NO_WPA2 */ 00372 return -1; 00373 #endif /* CONFIG_NO_WPA2 */ 00374 } 00375 00376 00384 int wpa_gen_wpa_ie(struct wpa_sm *sm, u8 *wpa_ie, size_t wpa_ie_len) 00385 { 00386 if (sm->proto == WPA_PROTO_RSN) 00387 return wpa_gen_wpa_ie_rsn(wpa_ie, wpa_ie_len, 00388 sm->pairwise_cipher, 00389 sm->group_cipher, 00390 sm->key_mgmt, sm->mgmt_group_cipher, 00391 sm); 00392 else 00393 return wpa_gen_wpa_ie_wpa(wpa_ie, wpa_ie_len, 00394 sm->pairwise_cipher, 00395 sm->group_cipher, 00396 sm->key_mgmt); 00397 } 00398 00399 00407 static int wpa_parse_generic(const u8 *pos, const u8 *end, 00408 struct wpa_eapol_ie_parse *ie) 00409 { 00410 if (pos[1] == 0) 00411 return 1; 00412 00413 if (pos[1] >= 6 && 00414 RSN_SELECTOR_GET(pos + 2) == WPA_OUI_TYPE && 00415 pos[2 + WPA_SELECTOR_LEN] == 1 && 00416 pos[2 + WPA_SELECTOR_LEN + 1] == 0) { 00417 ie->wpa_ie = pos; 00418 ie->wpa_ie_len = pos[1] + 2; 00419 wpa_hexdump(MSG_DEBUG, "WPA: WPA IE in EAPOL-Key", 00420 ie->wpa_ie, ie->wpa_ie_len); 00421 return 0; 00422 } 00423 00424 if (pos + 1 + RSN_SELECTOR_LEN < end && 00425 pos[1] >= RSN_SELECTOR_LEN + PMKID_LEN && 00426 RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_PMKID) { 00427 ie->pmkid = pos + 2 + RSN_SELECTOR_LEN; 00428 wpa_hexdump(MSG_DEBUG, "WPA: PMKID in EAPOL-Key", 00429 pos, pos[1] + 2); 00430 return 0; 00431 } 00432 00433 if (pos[1] > RSN_SELECTOR_LEN + 2 && 00434 RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_GROUPKEY) { 00435 ie->gtk = pos + 2 + RSN_SELECTOR_LEN; 00436 ie->gtk_len = pos[1] - RSN_SELECTOR_LEN; 00437 wpa_hexdump_key(MSG_DEBUG, "WPA: GTK in EAPOL-Key", 00438 pos, pos[1] + 2); 00439 return 0; 00440 } 00441 00442 if (pos[1] > RSN_SELECTOR_LEN + 2 && 00443 RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_MAC_ADDR) { 00444 ie->mac_addr = pos + 2 + RSN_SELECTOR_LEN; 00445 ie->mac_addr_len = pos[1] - RSN_SELECTOR_LEN; 00446 wpa_hexdump(MSG_DEBUG, "WPA: MAC Address in EAPOL-Key", 00447 pos, pos[1] + 2); 00448 return 0; 00449 } 00450 00451 #ifdef CONFIG_PEERKEY 00452 if (pos[1] > RSN_SELECTOR_LEN + 2 && 00453 RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_SMK) { 00454 ie->smk = pos + 2 + RSN_SELECTOR_LEN; 00455 ie->smk_len = pos[1] - RSN_SELECTOR_LEN; 00456 wpa_hexdump_key(MSG_DEBUG, "WPA: SMK in EAPOL-Key", 00457 pos, pos[1] + 2); 00458 return 0; 00459 } 00460 00461 if (pos[1] > RSN_SELECTOR_LEN + 2 && 00462 RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_NONCE) { 00463 ie->nonce = pos + 2 + RSN_SELECTOR_LEN; 00464 ie->nonce_len = pos[1] - RSN_SELECTOR_LEN; 00465 wpa_hexdump(MSG_DEBUG, "WPA: Nonce in EAPOL-Key", 00466 pos, pos[1] + 2); 00467 return 0; 00468 } 00469 00470 if (pos[1] > RSN_SELECTOR_LEN + 2 && 00471 RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_LIFETIME) { 00472 ie->lifetime = pos + 2 + RSN_SELECTOR_LEN; 00473 ie->lifetime_len = pos[1] - RSN_SELECTOR_LEN; 00474 wpa_hexdump(MSG_DEBUG, "WPA: Lifetime in EAPOL-Key", 00475 pos, pos[1] + 2); 00476 return 0; 00477 } 00478 00479 if (pos[1] > RSN_SELECTOR_LEN + 2 && 00480 RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_ERROR) { 00481 ie->error = pos + 2 + RSN_SELECTOR_LEN; 00482 ie->error_len = pos[1] - RSN_SELECTOR_LEN; 00483 wpa_hexdump(MSG_DEBUG, "WPA: Error in EAPOL-Key", 00484 pos, pos[1] + 2); 00485 return 0; 00486 } 00487 #endif /* CONFIG_PEERKEY */ 00488 00489 #ifdef CONFIG_IEEE80211W 00490 if (pos[1] > RSN_SELECTOR_LEN + 2 && 00491 RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_IGTK) { 00492 ie->igtk = pos + 2 + RSN_SELECTOR_LEN; 00493 ie->igtk_len = pos[1] - RSN_SELECTOR_LEN; 00494 wpa_hexdump_key(MSG_DEBUG, "WPA: IGTK in EAPOL-Key", 00495 pos, pos[1] + 2); 00496 return 0; 00497 } 00498 #endif /* CONFIG_IEEE80211W */ 00499 00500 return 0; 00501 } 00502 00503 00511 int wpa_supplicant_parse_ies(const u8 *buf, size_t len, 00512 struct wpa_eapol_ie_parse *ie) 00513 { 00514 const u8 *pos, *end; 00515 int ret = 0; 00516 00517 os_memset(ie, 0, sizeof(*ie)); 00518 for (pos = buf, end = pos + len; pos + 1 < end; pos += 2 + pos[1]) { 00519 if (pos[0] == 0xdd && 00520 ((pos == buf + len - 1) || pos[1] == 0)) { 00521 /* Ignore padding */ 00522 break; 00523 } 00524 if (pos + 2 + pos[1] > end) { 00525 wpa_printf(MSG_DEBUG, "WPA: EAPOL-Key Key Data " 00526 "underflow (ie=%d len=%d pos=%d)", 00527 pos[0], pos[1], (int) (pos - buf)); 00528 wpa_hexdump_key(MSG_DEBUG, "WPA: Key Data", 00529 buf, len); 00530 ret = -1; 00531 break; 00532 } 00533 if (*pos == WLAN_EID_RSN) { 00534 ie->rsn_ie = pos; 00535 ie->rsn_ie_len = pos[1] + 2; 00536 wpa_hexdump(MSG_DEBUG, "WPA: RSN IE in EAPOL-Key", 00537 ie->rsn_ie, ie->rsn_ie_len); 00538 #ifdef CONFIG_IEEE80211R 00539 } else if (*pos == WLAN_EID_MOBILITY_DOMAIN) { 00540 ie->mdie = pos; 00541 ie->mdie_len = pos[1] + 2; 00542 wpa_hexdump(MSG_DEBUG, "WPA: MDIE in EAPOL-Key", 00543 ie->mdie, ie->mdie_len); 00544 } else if (*pos == WLAN_EID_FAST_BSS_TRANSITION) { 00545 ie->ftie = pos; 00546 ie->ftie_len = pos[1] + 2; 00547 wpa_hexdump(MSG_DEBUG, "WPA: FTIE in EAPOL-Key", 00548 ie->ftie, ie->ftie_len); 00549 } else if (*pos == WLAN_EID_TIMEOUT_INTERVAL && pos[1] >= 5) { 00550 if (pos[2] == WLAN_TIMEOUT_REASSOC_DEADLINE) { 00551 ie->reassoc_deadline = pos; 00552 wpa_hexdump(MSG_DEBUG, "WPA: Reassoc Deadline " 00553 "in EAPOL-Key", 00554 ie->reassoc_deadline, pos[1] + 2); 00555 } else if (pos[2] == WLAN_TIMEOUT_KEY_LIFETIME) { 00556 ie->key_lifetime = pos; 00557 wpa_hexdump(MSG_DEBUG, "WPA: KeyLifetime " 00558 "in EAPOL-Key", 00559 ie->key_lifetime, pos[1] + 2); 00560 } else { 00561 wpa_hexdump(MSG_DEBUG, "WPA: Unrecognized " 00562 "EAPOL-Key Key Data IE", 00563 pos, 2 + pos[1]); 00564 } 00565 #endif /* CONFIG_IEEE80211R */ 00566 } else if (*pos == WLAN_EID_VENDOR_SPECIFIC) { 00567 ret = wpa_parse_generic(pos, end, ie); 00568 if (ret < 0) 00569 break; 00570 if (ret > 0) { 00571 ret = 0; 00572 break; 00573 } 00574 } else { 00575 wpa_hexdump(MSG_DEBUG, "WPA: Unrecognized EAPOL-Key " 00576 "Key Data IE", pos, 2 + pos[1]); 00577 } 00578 } 00579 00580 return ret; 00581 }