1 /* 2 * wpa_supplicant - WPA/RSN IE and KDE processing 3 * Copyright (c) 2003-2008, Jouni Malinen <j@w1.fi> 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License version 2 as 7 * published by the Free Software Foundation. 8 * 9 * Alternatively, this software may be distributed under the terms of BSD 10 * license. 11 * 12 * See README and COPYING for more details. 13 */ 14 15 #include "includes.h" 16 17 #include "common.h" 18 #include "wpa.h" 19 #include "pmksa_cache.h" 20 #include "common/ieee802_11_defs.h" 21 #include "wpa_i.h" 22 #include "wpa_ie.h" 23 24 25 static int wpa_selector_to_bitfield(const u8 *s) 26 { 27 if (RSN_SELECTOR_GET(s) == WPA_CIPHER_SUITE_NONE) 28 return WPA_CIPHER_NONE; 29 if (RSN_SELECTOR_GET(s) == WPA_CIPHER_SUITE_WEP40) 30 return WPA_CIPHER_WEP40; 31 if (RSN_SELECTOR_GET(s) == WPA_CIPHER_SUITE_TKIP) 32 return WPA_CIPHER_TKIP; 33 if (RSN_SELECTOR_GET(s) == WPA_CIPHER_SUITE_CCMP) 34 return WPA_CIPHER_CCMP; 35 if (RSN_SELECTOR_GET(s) == WPA_CIPHER_SUITE_WEP104) 36 return WPA_CIPHER_WEP104; 37 return 0; 38 } 39 40 41 static int wpa_key_mgmt_to_bitfield(const u8 *s) 42 { 43 if (RSN_SELECTOR_GET(s) == WPA_AUTH_KEY_MGMT_UNSPEC_802_1X) 44 return WPA_KEY_MGMT_IEEE8021X; 45 if (RSN_SELECTOR_GET(s) == WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X) 46 return WPA_KEY_MGMT_PSK; 47 if (RSN_SELECTOR_GET(s) == WPA_AUTH_KEY_MGMT_NONE) 48 return WPA_KEY_MGMT_WPA_NONE; 49 return 0; 50 } 51 52 53 static int wpa_parse_wpa_ie_wpa(const u8 *wpa_ie, size_t wpa_ie_len, 54 struct wpa_ie_data *data) 55 { 56 const struct wpa_ie_hdr *hdr; 57 const u8 *pos; 58 int left; 59 int i, count; 60 61 os_memset(data, 0, sizeof(*data)); 62 data->proto = WPA_PROTO_WPA; 63 data->pairwise_cipher = WPA_CIPHER_TKIP; 64 data->group_cipher = WPA_CIPHER_TKIP; 65 data->key_mgmt = WPA_KEY_MGMT_IEEE8021X; 66 data->capabilities = 0; 67 data->pmkid = NULL; 68 data->num_pmkid = 0; 69 data->mgmt_group_cipher = 0; 70 71 if (wpa_ie_len == 0) { 72 /* No WPA IE - fail silently */ 73 return -1; 74 } 75 76 if (wpa_ie_len < sizeof(struct wpa_ie_hdr)) { 77 wpa_printf(MSG_DEBUG, "%s: ie len too short %lu", 78 __func__, (unsigned long) wpa_ie_len); 79 return -1; 80 } 81 82 hdr = (const struct wpa_ie_hdr *) wpa_ie; 83 84 if (hdr->elem_id != WLAN_EID_VENDOR_SPECIFIC || 85 hdr->len != wpa_ie_len - 2 || 86 RSN_SELECTOR_GET(hdr->oui) != WPA_OUI_TYPE || 87 WPA_GET_LE16(hdr->version) != WPA_VERSION) { 88 wpa_printf(MSG_DEBUG, "%s: malformed ie or unknown version", 89 __func__); 90 return -1; 91 } 92 93 pos = (const u8 *) (hdr + 1); 94 left = wpa_ie_len - sizeof(*hdr); 95 96 if (left >= WPA_SELECTOR_LEN) { 97 data->group_cipher = wpa_selector_to_bitfield(pos); 98 pos += WPA_SELECTOR_LEN; 99 left -= WPA_SELECTOR_LEN; 100 } else if (left > 0) { 101 wpa_printf(MSG_DEBUG, "%s: ie length mismatch, %u too much", 102 __func__, left); 103 return -1; 104 } 105 106 if (left >= 2) { 107 data->pairwise_cipher = 0; 108 count = WPA_GET_LE16(pos); 109 pos += 2; 110 left -= 2; 111 if (count == 0 || left < count * WPA_SELECTOR_LEN) { 112 wpa_printf(MSG_DEBUG, "%s: ie count botch (pairwise), " 113 "count %u left %u", __func__, count, left); 114 return -1; 115 } 116 for (i = 0; i < count; i++) { 117 data->pairwise_cipher |= wpa_selector_to_bitfield(pos); 118 pos += WPA_SELECTOR_LEN; 119 left -= WPA_SELECTOR_LEN; 120 } 121 } else if (left == 1) { 122 wpa_printf(MSG_DEBUG, "%s: ie too short (for key mgmt)", 123 __func__); 124 return -1; 125 } 126 127 if (left >= 2) { 128 data->key_mgmt = 0; 129 count = WPA_GET_LE16(pos); 130 pos += 2; 131 left -= 2; 132 if (count == 0 || left < count * WPA_SELECTOR_LEN) { 133 wpa_printf(MSG_DEBUG, "%s: ie count botch (key mgmt), " 134 "count %u left %u", __func__, count, left); 135 return -1; 136 } 137 for (i = 0; i < count; i++) { 138 data->key_mgmt |= wpa_key_mgmt_to_bitfield(pos); 139 pos += WPA_SELECTOR_LEN; 140 left -= WPA_SELECTOR_LEN; 141 } 142 } else if (left == 1) { 143 wpa_printf(MSG_DEBUG, "%s: ie too short (for capabilities)", 144 __func__); 145 return -1; 146 } 147 148 if (left >= 2) { 149 data->capabilities = WPA_GET_LE16(pos); 150 pos += 2; 151 left -= 2; 152 } 153 154 if (left > 0) { 155 wpa_printf(MSG_DEBUG, "%s: ie has %u trailing bytes - ignored", 156 __func__, left); 157 } 158 159 return 0; 160 } 161 162 163 /** 164 * wpa_parse_wpa_ie - Parse WPA/RSN IE 165 * @wpa_ie: Pointer to WPA or RSN IE 166 * @wpa_ie_len: Length of the WPA/RSN IE 167 * @data: Pointer to data area for parsing results 168 * Returns: 0 on success, -1 on failure 169 * 170 * Parse the contents of WPA or RSN IE and write the parsed data into data. 171 */ 172 int wpa_parse_wpa_ie(const u8 *wpa_ie, size_t wpa_ie_len, 173 struct wpa_ie_data *data) 174 { 175 if (wpa_ie_len >= 1 && wpa_ie[0] == WLAN_EID_RSN) 176 return wpa_parse_wpa_ie_rsn(wpa_ie, wpa_ie_len, data); 177 else 178 return wpa_parse_wpa_ie_wpa(wpa_ie, wpa_ie_len, data); 179 } 180 181 182 static int wpa_gen_wpa_ie_wpa(u8 *wpa_ie, size_t wpa_ie_len, 183 int pairwise_cipher, int group_cipher, 184 int key_mgmt) 185 { 186 u8 *pos; 187 struct wpa_ie_hdr *hdr; 188 189 if (wpa_ie_len < sizeof(*hdr) + WPA_SELECTOR_LEN + 190 2 + WPA_SELECTOR_LEN + 2 + WPA_SELECTOR_LEN) 191 return -1; 192 193 hdr = (struct wpa_ie_hdr *) wpa_ie; 194 hdr->elem_id = WLAN_EID_VENDOR_SPECIFIC; 195 RSN_SELECTOR_PUT(hdr->oui, WPA_OUI_TYPE); 196 WPA_PUT_LE16(hdr->version, WPA_VERSION); 197 pos = (u8 *) (hdr + 1); 198 199 if (group_cipher == WPA_CIPHER_CCMP) { 200 RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_CCMP); 201 } else if (group_cipher == WPA_CIPHER_TKIP) { 202 RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_TKIP); 203 } else if (group_cipher == WPA_CIPHER_WEP104) { 204 RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_WEP104); 205 } else if (group_cipher == WPA_CIPHER_WEP40) { 206 RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_WEP40); 207 } else { 208 wpa_printf(MSG_WARNING, "Invalid group cipher (%d).", 209 group_cipher); 210 return -1; 211 } 212 pos += WPA_SELECTOR_LEN; 213 214 *pos++ = 1; 215 *pos++ = 0; 216 if (pairwise_cipher == WPA_CIPHER_CCMP) { 217 RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_CCMP); 218 } else if (pairwise_cipher == WPA_CIPHER_TKIP) { 219 RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_TKIP); 220 } else if (pairwise_cipher == WPA_CIPHER_NONE) { 221 RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_NONE); 222 } else { 223 wpa_printf(MSG_WARNING, "Invalid pairwise cipher (%d).", 224 pairwise_cipher); 225 return -1; 226 } 227 pos += WPA_SELECTOR_LEN; 228 229 *pos++ = 1; 230 *pos++ = 0; 231 if (key_mgmt == WPA_KEY_MGMT_IEEE8021X) { 232 RSN_SELECTOR_PUT(pos, WPA_AUTH_KEY_MGMT_UNSPEC_802_1X); 233 } else if (key_mgmt == WPA_KEY_MGMT_PSK) { 234 RSN_SELECTOR_PUT(pos, WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X); 235 } else if (key_mgmt == WPA_KEY_MGMT_WPA_NONE) { 236 RSN_SELECTOR_PUT(pos, WPA_AUTH_KEY_MGMT_NONE); 237 } else { 238 wpa_printf(MSG_WARNING, "Invalid key management type (%d).", 239 key_mgmt); 240 return -1; 241 } 242 pos += WPA_SELECTOR_LEN; 243 244 /* WPA Capabilities; use defaults, so no need to include it */ 245 246 hdr->len = (pos - wpa_ie) - 2; 247 248 WPA_ASSERT((size_t) (pos - wpa_ie) <= wpa_ie_len); 249 250 return pos - wpa_ie; 251 } 252 253 254 static int wpa_gen_wpa_ie_rsn(u8 *rsn_ie, size_t rsn_ie_len, 255 int pairwise_cipher, int group_cipher, 256 int key_mgmt, int mgmt_group_cipher, 257 struct wpa_sm *sm) 258 { 259 #ifndef CONFIG_NO_WPA2 260 u8 *pos; 261 struct rsn_ie_hdr *hdr; 262 u16 capab; 263 264 if (rsn_ie_len < sizeof(*hdr) + RSN_SELECTOR_LEN + 265 2 + RSN_SELECTOR_LEN + 2 + RSN_SELECTOR_LEN + 2 + 266 (sm->cur_pmksa ? 2 + PMKID_LEN : 0)) { 267 wpa_printf(MSG_DEBUG, "RSN: Too short IE buffer (%lu bytes)", 268 (unsigned long) rsn_ie_len); 269 return -1; 270 } 271 272 hdr = (struct rsn_ie_hdr *) rsn_ie; 273 hdr->elem_id = WLAN_EID_RSN; 274 WPA_PUT_LE16(hdr->version, RSN_VERSION); 275 pos = (u8 *) (hdr + 1); 276 277 if (group_cipher == WPA_CIPHER_CCMP) { 278 RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP); 279 } else if (group_cipher == WPA_CIPHER_TKIP) { 280 RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_TKIP); 281 } else if (group_cipher == WPA_CIPHER_WEP104) { 282 RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_WEP104); 283 } else if (group_cipher == WPA_CIPHER_WEP40) { 284 RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_WEP40); 285 } else { 286 wpa_printf(MSG_WARNING, "Invalid group cipher (%d).", 287 group_cipher); 288 return -1; 289 } 290 pos += RSN_SELECTOR_LEN; 291 292 *pos++ = 1; 293 *pos++ = 0; 294 if (pairwise_cipher == WPA_CIPHER_CCMP) { 295 RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP); 296 } else if (pairwise_cipher == WPA_CIPHER_TKIP) { 297 RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_TKIP); 298 } else if (pairwise_cipher == WPA_CIPHER_NONE) { 299 RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_NONE); 300 } else { 301 wpa_printf(MSG_WARNING, "Invalid pairwise cipher (%d).", 302 pairwise_cipher); 303 return -1; 304 } 305 pos += RSN_SELECTOR_LEN; 306 307 *pos++ = 1; 308 *pos++ = 0; 309 if (key_mgmt == WPA_KEY_MGMT_IEEE8021X) { 310 RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_UNSPEC_802_1X); 311 } else if (key_mgmt == WPA_KEY_MGMT_PSK) { 312 RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X); 313 #ifdef CONFIG_IEEE80211R 314 } else if (key_mgmt == WPA_KEY_MGMT_FT_IEEE8021X) { 315 RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_802_1X); 316 } else if (key_mgmt == WPA_KEY_MGMT_FT_PSK) { 317 RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_PSK); 318 #endif /* CONFIG_IEEE80211R */ 319 #ifdef CONFIG_IEEE80211W 320 } else if (key_mgmt == WPA_KEY_MGMT_IEEE8021X_SHA256) { 321 RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_802_1X_SHA256); 322 } else if (key_mgmt == WPA_KEY_MGMT_PSK_SHA256) { 323 RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_PSK_SHA256); 324 #endif /* CONFIG_IEEE80211W */ 325 } else { 326 wpa_printf(MSG_WARNING, "Invalid key management type (%d).", 327 key_mgmt); 328 return -1; 329 } 330 pos += RSN_SELECTOR_LEN; 331 332 /* RSN Capabilities */ 333 capab = 0; 334 #ifdef CONFIG_IEEE80211W 335 if (sm->mfp) 336 capab |= WPA_CAPABILITY_MFPC; 337 if (sm->mfp == 2) 338 capab |= WPA_CAPABILITY_MFPR; 339 #endif /* CONFIG_IEEE80211W */ 340 WPA_PUT_LE16(pos, capab); 341 pos += 2; 342 343 if (sm->cur_pmksa) { 344 /* PMKID Count (2 octets, little endian) */ 345 *pos++ = 1; 346 *pos++ = 0; 347 /* PMKID */ 348 os_memcpy(pos, sm->cur_pmksa->pmkid, PMKID_LEN); 349 pos += PMKID_LEN; 350 } 351 352 #ifdef CONFIG_IEEE80211W 353 if (mgmt_group_cipher == WPA_CIPHER_AES_128_CMAC) { 354 if (!sm->cur_pmksa) { 355 /* PMKID Count */ 356 WPA_PUT_LE16(pos, 0); 357 pos += 2; 358 } 359 360 /* Management Group Cipher Suite */ 361 RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_AES_128_CMAC); 362 pos += RSN_SELECTOR_LEN; 363 } 364 #endif /* CONFIG_IEEE80211W */ 365 366 hdr->len = (pos - rsn_ie) - 2; 367 368 WPA_ASSERT((size_t) (pos - rsn_ie) <= rsn_ie_len); 369 370 return pos - rsn_ie; 371 #else /* CONFIG_NO_WPA2 */ 372 return -1; 373 #endif /* CONFIG_NO_WPA2 */ 374 } 375 376 377 /** 378 * wpa_gen_wpa_ie - Generate WPA/RSN IE based on current security policy 379 * @sm: Pointer to WPA state machine data from wpa_sm_init() 380 * @wpa_ie: Pointer to memory area for the generated WPA/RSN IE 381 * @wpa_ie_len: Maximum length of the generated WPA/RSN IE 382 * Returns: Length of the generated WPA/RSN IE or -1 on failure 383 */ 384 int wpa_gen_wpa_ie(struct wpa_sm *sm, u8 *wpa_ie, size_t wpa_ie_len) 385 { 386 if (sm->proto == WPA_PROTO_RSN) 387 return wpa_gen_wpa_ie_rsn(wpa_ie, wpa_ie_len, 388 sm->pairwise_cipher, 389 sm->group_cipher, 390 sm->key_mgmt, sm->mgmt_group_cipher, 391 sm); 392 else 393 return wpa_gen_wpa_ie_wpa(wpa_ie, wpa_ie_len, 394 sm->pairwise_cipher, 395 sm->group_cipher, 396 sm->key_mgmt); 397 } 398 399 400 /** 401 * wpa_parse_generic - Parse EAPOL-Key Key Data Generic IEs 402 * @pos: Pointer to the IE header 403 * @end: Pointer to the end of the Key Data buffer 404 * @ie: Pointer to parsed IE data 405 * Returns: 0 on success, 1 if end mark is found, -1 on failure 406 */ 407 static int wpa_parse_generic(const u8 *pos, const u8 *end, 408 struct wpa_eapol_ie_parse *ie) 409 { 410 if (pos[1] == 0) 411 return 1; 412 413 if (pos[1] >= 6 && 414 RSN_SELECTOR_GET(pos + 2) == WPA_OUI_TYPE && 415 pos[2 + WPA_SELECTOR_LEN] == 1 && 416 pos[2 + WPA_SELECTOR_LEN + 1] == 0) { 417 ie->wpa_ie = pos; 418 ie->wpa_ie_len = pos[1] + 2; 419 wpa_hexdump(MSG_DEBUG, "WPA: WPA IE in EAPOL-Key", 420 ie->wpa_ie, ie->wpa_ie_len); 421 return 0; 422 } 423 424 if (pos + 1 + RSN_SELECTOR_LEN < end && 425 pos[1] >= RSN_SELECTOR_LEN + PMKID_LEN && 426 RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_PMKID) { 427 ie->pmkid = pos + 2 + RSN_SELECTOR_LEN; 428 wpa_hexdump(MSG_DEBUG, "WPA: PMKID in EAPOL-Key", 429 pos, pos[1] + 2); 430 return 0; 431 } 432 433 if (pos[1] > RSN_SELECTOR_LEN + 2 && 434 RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_GROUPKEY) { 435 ie->gtk = pos + 2 + RSN_SELECTOR_LEN; 436 ie->gtk_len = pos[1] - RSN_SELECTOR_LEN; 437 wpa_hexdump_key(MSG_DEBUG, "WPA: GTK in EAPOL-Key", 438 pos, pos[1] + 2); 439 return 0; 440 } 441 442 if (pos[1] > RSN_SELECTOR_LEN + 2 && 443 RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_MAC_ADDR) { 444 ie->mac_addr = pos + 2 + RSN_SELECTOR_LEN; 445 ie->mac_addr_len = pos[1] - RSN_SELECTOR_LEN; 446 wpa_hexdump(MSG_DEBUG, "WPA: MAC Address in EAPOL-Key", 447 pos, pos[1] + 2); 448 return 0; 449 } 450 451 #ifdef CONFIG_PEERKEY 452 if (pos[1] > RSN_SELECTOR_LEN + 2 && 453 RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_SMK) { 454 ie->smk = pos + 2 + RSN_SELECTOR_LEN; 455 ie->smk_len = pos[1] - RSN_SELECTOR_LEN; 456 wpa_hexdump_key(MSG_DEBUG, "WPA: SMK in EAPOL-Key", 457 pos, pos[1] + 2); 458 return 0; 459 } 460 461 if (pos[1] > RSN_SELECTOR_LEN + 2 && 462 RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_NONCE) { 463 ie->nonce = pos + 2 + RSN_SELECTOR_LEN; 464 ie->nonce_len = pos[1] - RSN_SELECTOR_LEN; 465 wpa_hexdump(MSG_DEBUG, "WPA: Nonce in EAPOL-Key", 466 pos, pos[1] + 2); 467 return 0; 468 } 469 470 if (pos[1] > RSN_SELECTOR_LEN + 2 && 471 RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_LIFETIME) { 472 ie->lifetime = pos + 2 + RSN_SELECTOR_LEN; 473 ie->lifetime_len = pos[1] - RSN_SELECTOR_LEN; 474 wpa_hexdump(MSG_DEBUG, "WPA: Lifetime in EAPOL-Key", 475 pos, pos[1] + 2); 476 return 0; 477 } 478 479 if (pos[1] > RSN_SELECTOR_LEN + 2 && 480 RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_ERROR) { 481 ie->error = pos + 2 + RSN_SELECTOR_LEN; 482 ie->error_len = pos[1] - RSN_SELECTOR_LEN; 483 wpa_hexdump(MSG_DEBUG, "WPA: Error in EAPOL-Key", 484 pos, pos[1] + 2); 485 return 0; 486 } 487 #endif /* CONFIG_PEERKEY */ 488 489 #ifdef CONFIG_IEEE80211W 490 if (pos[1] > RSN_SELECTOR_LEN + 2 && 491 RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_IGTK) { 492 ie->igtk = pos + 2 + RSN_SELECTOR_LEN; 493 ie->igtk_len = pos[1] - RSN_SELECTOR_LEN; 494 wpa_hexdump_key(MSG_DEBUG, "WPA: IGTK in EAPOL-Key", 495 pos, pos[1] + 2); 496 return 0; 497 } 498 #endif /* CONFIG_IEEE80211W */ 499 500 return 0; 501 } 502 503 504 /** 505 * wpa_supplicant_parse_ies - Parse EAPOL-Key Key Data IEs 506 * @buf: Pointer to the Key Data buffer 507 * @len: Key Data Length 508 * @ie: Pointer to parsed IE data 509 * Returns: 0 on success, -1 on failure 510 */ 511 int wpa_supplicant_parse_ies(const u8 *buf, size_t len, 512 struct wpa_eapol_ie_parse *ie) 513 { 514 const u8 *pos, *end; 515 int ret = 0; 516 517 os_memset(ie, 0, sizeof(*ie)); 518 for (pos = buf, end = pos + len; pos + 1 < end; pos += 2 + pos[1]) { 519 if (pos[0] == 0xdd && 520 ((pos == buf + len - 1) || pos[1] == 0)) { 521 /* Ignore padding */ 522 break; 523 } 524 if (pos + 2 + pos[1] > end) { 525 wpa_printf(MSG_DEBUG, "WPA: EAPOL-Key Key Data " 526 "underflow (ie=%d len=%d pos=%d)", 527 pos[0], pos[1], (int) (pos - buf)); 528 wpa_hexdump_key(MSG_DEBUG, "WPA: Key Data", 529 buf, len); 530 ret = -1; 531 break; 532 } 533 if (*pos == WLAN_EID_RSN) { 534 ie->rsn_ie = pos; 535 ie->rsn_ie_len = pos[1] + 2; 536 wpa_hexdump(MSG_DEBUG, "WPA: RSN IE in EAPOL-Key", 537 ie->rsn_ie, ie->rsn_ie_len); 538 #ifdef CONFIG_IEEE80211R 539 } else if (*pos == WLAN_EID_MOBILITY_DOMAIN) { 540 ie->mdie = pos; 541 ie->mdie_len = pos[1] + 2; 542 wpa_hexdump(MSG_DEBUG, "WPA: MDIE in EAPOL-Key", 543 ie->mdie, ie->mdie_len); 544 } else if (*pos == WLAN_EID_FAST_BSS_TRANSITION) { 545 ie->ftie = pos; 546 ie->ftie_len = pos[1] + 2; 547 wpa_hexdump(MSG_DEBUG, "WPA: FTIE in EAPOL-Key", 548 ie->ftie, ie->ftie_len); 549 } else if (*pos == WLAN_EID_TIMEOUT_INTERVAL && pos[1] >= 5) { 550 if (pos[2] == WLAN_TIMEOUT_REASSOC_DEADLINE) { 551 ie->reassoc_deadline = pos; 552 wpa_hexdump(MSG_DEBUG, "WPA: Reassoc Deadline " 553 "in EAPOL-Key", 554 ie->reassoc_deadline, pos[1] + 2); 555 } else if (pos[2] == WLAN_TIMEOUT_KEY_LIFETIME) { 556 ie->key_lifetime = pos; 557 wpa_hexdump(MSG_DEBUG, "WPA: KeyLifetime " 558 "in EAPOL-Key", 559 ie->key_lifetime, pos[1] + 2); 560 } else { 561 wpa_hexdump(MSG_DEBUG, "WPA: Unrecognized " 562 "EAPOL-Key Key Data IE", 563 pos, 2 + pos[1]); 564 } 565 #endif /* CONFIG_IEEE80211R */ 566 } else if (*pos == WLAN_EID_VENDOR_SPECIFIC) { 567 ret = wpa_parse_generic(pos, end, ie); 568 if (ret < 0) 569 break; 570 if (ret > 0) { 571 ret = 0; 572 break; 573 } 574 } else { 575 wpa_hexdump(MSG_DEBUG, "WPA: Unrecognized EAPOL-Key " 576 "Key Data IE", pos, 2 + pos[1]); 577 } 578 } 579 580 return ret; 581 } 582