2 * wpa_supplicant - WPA/RSN IE and KDE processing
3 * Copyright (c) 2003-2018, Jouni Malinen <j@w1.fi>
5 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
13 #include "pmksa_cache.h"
14 #include "common/ieee802_11_defs.h"
20 * wpa_parse_wpa_ie - Parse WPA/RSN IE
21 * @wpa_ie: Pointer to WPA or RSN IE
22 * @wpa_ie_len: Length of the WPA/RSN IE
23 * @data: Pointer to data area for parsing results
24 * Returns: 0 on success, -1 on failure
26 * Parse the contents of WPA or RSN IE and write the parsed data into data.
28 int wpa_parse_wpa_ie(const u8
*wpa_ie
, size_t wpa_ie_len
,
29 struct wpa_ie_data
*data
)
31 if (wpa_ie_len
>= 1 && wpa_ie
[0] == WLAN_EID_RSN
)
32 return wpa_parse_wpa_ie_rsn(wpa_ie
, wpa_ie_len
, data
);
33 if (wpa_ie_len
>= 6 && wpa_ie
[0] == WLAN_EID_VENDOR_SPECIFIC
&&
34 wpa_ie
[1] >= 4 && WPA_GET_BE32(&wpa_ie
[2]) == OSEN_IE_VENDOR_TYPE
)
35 return wpa_parse_wpa_ie_rsn(wpa_ie
, wpa_ie_len
, data
);
37 return wpa_parse_wpa_ie_wpa(wpa_ie
, wpa_ie_len
, data
);
41 static int wpa_gen_wpa_ie_wpa(u8
*wpa_ie
, size_t wpa_ie_len
,
42 int pairwise_cipher
, int group_cipher
,
46 struct wpa_ie_hdr
*hdr
;
49 if (wpa_ie_len
< sizeof(*hdr
) + WPA_SELECTOR_LEN
+
50 2 + WPA_SELECTOR_LEN
+ 2 + WPA_SELECTOR_LEN
)
53 hdr
= (struct wpa_ie_hdr
*) wpa_ie
;
54 hdr
->elem_id
= WLAN_EID_VENDOR_SPECIFIC
;
55 RSN_SELECTOR_PUT(hdr
->oui
, WPA_OUI_TYPE
);
56 WPA_PUT_LE16(hdr
->version
, WPA_VERSION
);
57 pos
= (u8
*) (hdr
+ 1);
59 suite
= wpa_cipher_to_suite(WPA_PROTO_WPA
, group_cipher
);
61 wpa_printf(MSG_WARNING
, "Invalid group cipher (%d).",
65 RSN_SELECTOR_PUT(pos
, suite
);
66 pos
+= WPA_SELECTOR_LEN
;
70 suite
= wpa_cipher_to_suite(WPA_PROTO_WPA
, pairwise_cipher
);
72 (!wpa_cipher_valid_pairwise(pairwise_cipher
) &&
73 pairwise_cipher
!= WPA_CIPHER_NONE
)) {
74 wpa_printf(MSG_WARNING
, "Invalid pairwise cipher (%d).",
78 RSN_SELECTOR_PUT(pos
, suite
);
79 pos
+= WPA_SELECTOR_LEN
;
83 if (key_mgmt
== WPA_KEY_MGMT_IEEE8021X
) {
84 RSN_SELECTOR_PUT(pos
, WPA_AUTH_KEY_MGMT_UNSPEC_802_1X
);
85 } else if (key_mgmt
== WPA_KEY_MGMT_PSK
) {
86 RSN_SELECTOR_PUT(pos
, WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X
);
87 } else if (key_mgmt
== WPA_KEY_MGMT_WPA_NONE
) {
88 RSN_SELECTOR_PUT(pos
, WPA_AUTH_KEY_MGMT_NONE
);
89 } else if (key_mgmt
== WPA_KEY_MGMT_CCKM
) {
90 RSN_SELECTOR_PUT(pos
, WPA_AUTH_KEY_MGMT_CCKM
);
92 wpa_printf(MSG_WARNING
, "Invalid key management type (%d).",
96 pos
+= WPA_SELECTOR_LEN
;
98 /* WPA Capabilities; use defaults, so no need to include it */
100 hdr
->len
= (pos
- wpa_ie
) - 2;
102 WPA_ASSERT((size_t) (pos
- wpa_ie
) <= wpa_ie_len
);
108 static int wpa_gen_wpa_ie_rsn(u8
*rsn_ie
, size_t rsn_ie_len
,
109 int pairwise_cipher
, int group_cipher
,
110 int key_mgmt
, int mgmt_group_cipher
,
114 struct rsn_ie_hdr
*hdr
;
118 if (rsn_ie_len
< sizeof(*hdr
) + RSN_SELECTOR_LEN
+
119 2 + RSN_SELECTOR_LEN
+ 2 + RSN_SELECTOR_LEN
+ 2 +
120 (sm
->cur_pmksa
? 2 + PMKID_LEN
: 0)) {
121 wpa_printf(MSG_DEBUG
, "RSN: Too short IE buffer (%lu bytes)",
122 (unsigned long) rsn_ie_len
);
126 hdr
= (struct rsn_ie_hdr
*) rsn_ie
;
127 hdr
->elem_id
= WLAN_EID_RSN
;
128 WPA_PUT_LE16(hdr
->version
, RSN_VERSION
);
129 pos
= (u8
*) (hdr
+ 1);
131 suite
= wpa_cipher_to_suite(WPA_PROTO_RSN
, group_cipher
);
133 wpa_printf(MSG_WARNING
, "Invalid group cipher (%d).",
137 RSN_SELECTOR_PUT(pos
, suite
);
138 pos
+= RSN_SELECTOR_LEN
;
142 suite
= wpa_cipher_to_suite(WPA_PROTO_RSN
, pairwise_cipher
);
144 (!wpa_cipher_valid_pairwise(pairwise_cipher
) &&
145 pairwise_cipher
!= WPA_CIPHER_NONE
)) {
146 wpa_printf(MSG_WARNING
, "Invalid pairwise cipher (%d).",
150 RSN_SELECTOR_PUT(pos
, suite
);
151 pos
+= RSN_SELECTOR_LEN
;
155 if (key_mgmt
== WPA_KEY_MGMT_IEEE8021X
) {
156 RSN_SELECTOR_PUT(pos
, RSN_AUTH_KEY_MGMT_UNSPEC_802_1X
);
157 } else if (key_mgmt
== WPA_KEY_MGMT_PSK
) {
158 RSN_SELECTOR_PUT(pos
, RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X
);
159 } else if (key_mgmt
== WPA_KEY_MGMT_CCKM
) {
160 RSN_SELECTOR_PUT(pos
, RSN_AUTH_KEY_MGMT_CCKM
);
161 #ifdef CONFIG_IEEE80211R
162 } else if (key_mgmt
== WPA_KEY_MGMT_FT_IEEE8021X
) {
163 RSN_SELECTOR_PUT(pos
, RSN_AUTH_KEY_MGMT_FT_802_1X
);
165 } else if (key_mgmt
== WPA_KEY_MGMT_FT_IEEE8021X_SHA384
) {
166 RSN_SELECTOR_PUT(pos
, RSN_AUTH_KEY_MGMT_FT_802_1X_SHA384
);
167 #endif /* CONFIG_SHA384 */
168 } else if (key_mgmt
== WPA_KEY_MGMT_FT_PSK
) {
169 RSN_SELECTOR_PUT(pos
, RSN_AUTH_KEY_MGMT_FT_PSK
);
170 #endif /* CONFIG_IEEE80211R */
171 #ifdef CONFIG_IEEE80211W
172 } else if (key_mgmt
== WPA_KEY_MGMT_IEEE8021X_SHA256
) {
173 RSN_SELECTOR_PUT(pos
, RSN_AUTH_KEY_MGMT_802_1X_SHA256
);
174 } else if (key_mgmt
== WPA_KEY_MGMT_PSK_SHA256
) {
175 RSN_SELECTOR_PUT(pos
, RSN_AUTH_KEY_MGMT_PSK_SHA256
);
176 #endif /* CONFIG_IEEE80211W */
178 } else if (key_mgmt
== WPA_KEY_MGMT_SAE
) {
179 RSN_SELECTOR_PUT(pos
, RSN_AUTH_KEY_MGMT_SAE
);
180 } else if (key_mgmt
== WPA_KEY_MGMT_FT_SAE
) {
181 RSN_SELECTOR_PUT(pos
, RSN_AUTH_KEY_MGMT_FT_SAE
);
182 #endif /* CONFIG_SAE */
183 } else if (key_mgmt
== WPA_KEY_MGMT_IEEE8021X_SUITE_B_192
) {
184 RSN_SELECTOR_PUT(pos
, RSN_AUTH_KEY_MGMT_802_1X_SUITE_B_192
);
185 } else if (key_mgmt
== WPA_KEY_MGMT_IEEE8021X_SUITE_B
) {
186 RSN_SELECTOR_PUT(pos
, RSN_AUTH_KEY_MGMT_802_1X_SUITE_B
);
188 } else if (key_mgmt
& WPA_KEY_MGMT_FILS_SHA256
) {
189 RSN_SELECTOR_PUT(pos
, RSN_AUTH_KEY_MGMT_FILS_SHA256
);
190 } else if (key_mgmt
& WPA_KEY_MGMT_FILS_SHA384
) {
191 RSN_SELECTOR_PUT(pos
, RSN_AUTH_KEY_MGMT_FILS_SHA384
);
192 #ifdef CONFIG_IEEE80211R
193 } else if (key_mgmt
& WPA_KEY_MGMT_FT_FILS_SHA256
) {
194 RSN_SELECTOR_PUT(pos
, RSN_AUTH_KEY_MGMT_FT_FILS_SHA256
);
195 } else if (key_mgmt
& WPA_KEY_MGMT_FT_FILS_SHA384
) {
196 RSN_SELECTOR_PUT(pos
, RSN_AUTH_KEY_MGMT_FT_FILS_SHA384
);
197 #endif /* CONFIG_IEEE80211R */
198 #endif /* CONFIG_FILS */
200 } else if (key_mgmt
& WPA_KEY_MGMT_OWE
) {
201 RSN_SELECTOR_PUT(pos
, RSN_AUTH_KEY_MGMT_OWE
);
202 #endif /* CONFIG_OWE */
204 } else if (key_mgmt
& WPA_KEY_MGMT_DPP
) {
205 RSN_SELECTOR_PUT(pos
, RSN_AUTH_KEY_MGMT_DPP
);
206 #endif /* CONFIG_DPP */
208 } else if (key_mgmt
& WPA_KEY_MGMT_OSEN
) {
209 RSN_SELECTOR_PUT(pos
, RSN_AUTH_KEY_MGMT_OSEN
);
210 #endif /* CONFIG_HS20 */
212 wpa_printf(MSG_WARNING
, "Invalid key management type (%d).",
216 pos
+= RSN_SELECTOR_LEN
;
218 /* RSN Capabilities */
220 #ifdef CONFIG_IEEE80211W
222 capab
|= WPA_CAPABILITY_MFPC
;
224 capab
|= WPA_CAPABILITY_MFPR
;
225 #endif /* CONFIG_IEEE80211W */
227 capab
|= WPA_CAPABILITY_OCVC
;
228 WPA_PUT_LE16(pos
, capab
);
232 /* PMKID Count (2 octets, little endian) */
236 os_memcpy(pos
, sm
->cur_pmksa
->pmkid
, PMKID_LEN
);
240 #ifdef CONFIG_IEEE80211W
241 if (wpa_cipher_valid_mgmt_group(mgmt_group_cipher
)) {
242 if (!sm
->cur_pmksa
) {
244 WPA_PUT_LE16(pos
, 0);
248 /* Management Group Cipher Suite */
249 RSN_SELECTOR_PUT(pos
, wpa_cipher_to_suite(WPA_PROTO_RSN
,
251 pos
+= RSN_SELECTOR_LEN
;
253 #endif /* CONFIG_IEEE80211W */
255 hdr
->len
= (pos
- rsn_ie
) - 2;
257 WPA_ASSERT((size_t) (pos
- rsn_ie
) <= rsn_ie_len
);
264 static int wpa_gen_wpa_ie_osen(u8
*wpa_ie
, size_t wpa_ie_len
,
265 int pairwise_cipher
, int group_cipher
,
271 if (wpa_ie_len
< 2 + 4 + RSN_SELECTOR_LEN
+
272 2 + RSN_SELECTOR_LEN
+ 2 + RSN_SELECTOR_LEN
)
276 *pos
++ = WLAN_EID_VENDOR_SPECIFIC
;
277 len
= pos
++; /* to be filled */
278 WPA_PUT_BE24(pos
, OUI_WFA
);
280 *pos
++ = HS20_OSEN_OUI_TYPE
;
282 /* Group Data Cipher Suite */
283 suite
= wpa_cipher_to_suite(WPA_PROTO_RSN
, group_cipher
);
285 wpa_printf(MSG_WARNING
, "Invalid group cipher (%d).",
289 RSN_SELECTOR_PUT(pos
, suite
);
290 pos
+= RSN_SELECTOR_LEN
;
292 /* Pairwise Cipher Suite Count and List */
293 WPA_PUT_LE16(pos
, 1);
295 suite
= wpa_cipher_to_suite(WPA_PROTO_RSN
, pairwise_cipher
);
297 (!wpa_cipher_valid_pairwise(pairwise_cipher
) &&
298 pairwise_cipher
!= WPA_CIPHER_NONE
)) {
299 wpa_printf(MSG_WARNING
, "Invalid pairwise cipher (%d).",
303 RSN_SELECTOR_PUT(pos
, suite
);
304 pos
+= RSN_SELECTOR_LEN
;
306 /* AKM Suite Count and List */
307 WPA_PUT_LE16(pos
, 1);
309 RSN_SELECTOR_PUT(pos
, RSN_AUTH_KEY_MGMT_OSEN
);
310 pos
+= RSN_SELECTOR_LEN
;
312 *len
= pos
- len
- 1;
314 WPA_ASSERT((size_t) (pos
- wpa_ie
) <= wpa_ie_len
);
318 #endif /* CONFIG_HS20 */
322 * wpa_gen_wpa_ie - Generate WPA/RSN IE based on current security policy
323 * @sm: Pointer to WPA state machine data from wpa_sm_init()
324 * @wpa_ie: Pointer to memory area for the generated WPA/RSN IE
325 * @wpa_ie_len: Maximum length of the generated WPA/RSN IE
326 * Returns: Length of the generated WPA/RSN IE or -1 on failure
328 int wpa_gen_wpa_ie(struct wpa_sm
*sm
, u8
*wpa_ie
, size_t wpa_ie_len
)
330 if (sm
->proto
== WPA_PROTO_RSN
)
331 return wpa_gen_wpa_ie_rsn(wpa_ie
, wpa_ie_len
,
334 sm
->key_mgmt
, sm
->mgmt_group_cipher
,
337 else if (sm
->proto
== WPA_PROTO_OSEN
)
338 return wpa_gen_wpa_ie_osen(wpa_ie
, wpa_ie_len
,
342 #endif /* CONFIG_HS20 */
344 return wpa_gen_wpa_ie_wpa(wpa_ie
, wpa_ie_len
,
352 * wpa_parse_vendor_specific - Parse Vendor Specific IEs
353 * @pos: Pointer to the IE header
354 * @end: Pointer to the end of the Key Data buffer
355 * @ie: Pointer to parsed IE data
356 * Returns: 0 on success, 1 if end mark is found, -1 on failure
358 static int wpa_parse_vendor_specific(const u8
*pos
, const u8
*end
,
359 struct wpa_eapol_ie_parse
*ie
)
364 wpa_printf(MSG_MSGDUMP
, "Too short vendor specific IE ignored (len=%u)",
369 oui
= WPA_GET_BE24(&pos
[2]);
370 if (oui
== OUI_MICROSOFT
&& pos
[5] == WMM_OUI_TYPE
&& pos
[1] > 4) {
371 if (pos
[6] == WMM_OUI_SUBTYPE_INFORMATION_ELEMENT
) {
373 ie
->wmm_len
= pos
[1];
374 wpa_hexdump(MSG_DEBUG
, "WPA: WMM IE",
375 ie
->wmm
, ie
->wmm_len
);
376 } else if (pos
[6] == WMM_OUI_SUBTYPE_PARAMETER_ELEMENT
) {
378 ie
->wmm_len
= pos
[1];
379 wpa_hexdump(MSG_DEBUG
, "WPA: WMM Parameter Element",
380 ie
->wmm
, ie
->wmm_len
);
388 * wpa_parse_generic - Parse EAPOL-Key Key Data Generic IEs
389 * @pos: Pointer to the IE header
390 * @end: Pointer to the end of the Key Data buffer
391 * @ie: Pointer to parsed IE data
392 * Returns: 0 on success, 1 if end mark is found, -1 on failure
394 static int wpa_parse_generic(const u8
*pos
, const u8
*end
,
395 struct wpa_eapol_ie_parse
*ie
)
401 RSN_SELECTOR_GET(pos
+ 2) == WPA_OUI_TYPE
&&
402 pos
[2 + WPA_SELECTOR_LEN
] == 1 &&
403 pos
[2 + WPA_SELECTOR_LEN
+ 1] == 0) {
405 ie
->wpa_ie_len
= pos
[1] + 2;
406 wpa_hexdump(MSG_DEBUG
, "WPA: WPA IE in EAPOL-Key",
407 ie
->wpa_ie
, ie
->wpa_ie_len
);
411 if (1 + RSN_SELECTOR_LEN
< end
- pos
&&
412 pos
[1] >= RSN_SELECTOR_LEN
+ PMKID_LEN
&&
413 RSN_SELECTOR_GET(pos
+ 2) == RSN_KEY_DATA_PMKID
) {
414 ie
->pmkid
= pos
+ 2 + RSN_SELECTOR_LEN
;
415 wpa_hexdump(MSG_DEBUG
, "WPA: PMKID in EAPOL-Key",
420 if (pos
[1] > RSN_SELECTOR_LEN
+ 2 &&
421 RSN_SELECTOR_GET(pos
+ 2) == RSN_KEY_DATA_GROUPKEY
) {
422 ie
->gtk
= pos
+ 2 + RSN_SELECTOR_LEN
;
423 ie
->gtk_len
= pos
[1] - RSN_SELECTOR_LEN
;
424 wpa_hexdump_key(MSG_DEBUG
, "WPA: GTK in EAPOL-Key",
429 if (pos
[1] > RSN_SELECTOR_LEN
+ 2 &&
430 RSN_SELECTOR_GET(pos
+ 2) == RSN_KEY_DATA_MAC_ADDR
) {
431 ie
->mac_addr
= pos
+ 2 + RSN_SELECTOR_LEN
;
432 ie
->mac_addr_len
= pos
[1] - RSN_SELECTOR_LEN
;
433 wpa_hexdump(MSG_DEBUG
, "WPA: MAC Address in EAPOL-Key",
438 #ifdef CONFIG_IEEE80211W
439 if (pos
[1] > RSN_SELECTOR_LEN
+ 2 &&
440 RSN_SELECTOR_GET(pos
+ 2) == RSN_KEY_DATA_IGTK
) {
441 ie
->igtk
= pos
+ 2 + RSN_SELECTOR_LEN
;
442 ie
->igtk_len
= pos
[1] - RSN_SELECTOR_LEN
;
443 wpa_hexdump_key(MSG_DEBUG
, "WPA: IGTK in EAPOL-Key",
447 #endif /* CONFIG_IEEE80211W */
450 if (pos
[1] >= RSN_SELECTOR_LEN
+ 1 &&
451 RSN_SELECTOR_GET(pos
+ 2) == WFA_KEY_DATA_IP_ADDR_REQ
) {
452 ie
->ip_addr_req
= pos
+ 2 + RSN_SELECTOR_LEN
;
453 wpa_hexdump(MSG_DEBUG
, "WPA: IP Address Request in EAPOL-Key",
454 ie
->ip_addr_req
, pos
[1] - RSN_SELECTOR_LEN
);
458 if (pos
[1] >= RSN_SELECTOR_LEN
+ 3 * 4 &&
459 RSN_SELECTOR_GET(pos
+ 2) == WFA_KEY_DATA_IP_ADDR_ALLOC
) {
460 ie
->ip_addr_alloc
= pos
+ 2 + RSN_SELECTOR_LEN
;
461 wpa_hexdump(MSG_DEBUG
,
462 "WPA: IP Address Allocation in EAPOL-Key",
463 ie
->ip_addr_alloc
, pos
[1] - RSN_SELECTOR_LEN
);
466 #endif /* CONFIG_P2P */
469 if (pos
[1] >= RSN_SELECTOR_LEN
+ 1 &&
470 RSN_SELECTOR_GET(pos
+ 2) == RSN_KEY_DATA_OCI
) {
471 ie
->oci
= pos
+ 2 + RSN_SELECTOR_LEN
;
472 ie
->oci_len
= pos
[1] - RSN_SELECTOR_LEN
;
473 wpa_hexdump(MSG_DEBUG
, "WPA: OCI KDE in EAPOL-Key",
477 #endif /* CONFIG_OCV */
484 * wpa_supplicant_parse_ies - Parse EAPOL-Key Key Data IEs
485 * @buf: Pointer to the Key Data buffer
486 * @len: Key Data Length
487 * @ie: Pointer to parsed IE data
488 * Returns: 0 on success, -1 on failure
490 int wpa_supplicant_parse_ies(const u8
*buf
, size_t len
,
491 struct wpa_eapol_ie_parse
*ie
)
496 os_memset(ie
, 0, sizeof(*ie
));
497 for (pos
= buf
, end
= pos
+ len
; end
- pos
> 1; pos
+= 2 + pos
[1]) {
498 if (pos
[0] == 0xdd &&
499 ((pos
== buf
+ len
- 1) || pos
[1] == 0)) {
503 if (2 + pos
[1] > end
- pos
) {
504 wpa_printf(MSG_DEBUG
, "WPA: EAPOL-Key Key Data "
505 "underflow (ie=%d len=%d pos=%d)",
506 pos
[0], pos
[1], (int) (pos
- buf
));
507 wpa_hexdump_key(MSG_DEBUG
, "WPA: Key Data",
512 if (*pos
== WLAN_EID_RSN
) {
514 ie
->rsn_ie_len
= pos
[1] + 2;
515 wpa_hexdump(MSG_DEBUG
, "WPA: RSN IE in EAPOL-Key",
516 ie
->rsn_ie
, ie
->rsn_ie_len
);
517 } else if (*pos
== WLAN_EID_MOBILITY_DOMAIN
&&
518 pos
[1] >= sizeof(struct rsn_mdie
)) {
520 ie
->mdie_len
= pos
[1] + 2;
521 wpa_hexdump(MSG_DEBUG
, "WPA: MDIE in EAPOL-Key",
522 ie
->mdie
, ie
->mdie_len
);
523 } else if (*pos
== WLAN_EID_FAST_BSS_TRANSITION
&&
524 pos
[1] >= sizeof(struct rsn_ftie
)) {
526 ie
->ftie_len
= pos
[1] + 2;
527 wpa_hexdump(MSG_DEBUG
, "WPA: FTIE in EAPOL-Key",
528 ie
->ftie
, ie
->ftie_len
);
529 } else if (*pos
== WLAN_EID_TIMEOUT_INTERVAL
&& pos
[1] >= 5) {
530 if (pos
[2] == WLAN_TIMEOUT_REASSOC_DEADLINE
) {
531 ie
->reassoc_deadline
= pos
;
532 wpa_hexdump(MSG_DEBUG
, "WPA: Reassoc Deadline "
534 ie
->reassoc_deadline
, pos
[1] + 2);
535 } else if (pos
[2] == WLAN_TIMEOUT_KEY_LIFETIME
) {
536 ie
->key_lifetime
= pos
;
537 wpa_hexdump(MSG_DEBUG
, "WPA: KeyLifetime "
539 ie
->key_lifetime
, pos
[1] + 2);
541 wpa_hexdump(MSG_DEBUG
, "WPA: Unrecognized "
542 "EAPOL-Key Key Data IE",
545 } else if (*pos
== WLAN_EID_LINK_ID
) {
548 ie
->lnkid_len
= pos
[1] + 2;
550 } else if (*pos
== WLAN_EID_EXT_CAPAB
) {
552 ie
->ext_capab_len
= pos
[1] + 2;
553 } else if (*pos
== WLAN_EID_SUPP_RATES
) {
554 ie
->supp_rates
= pos
;
555 ie
->supp_rates_len
= pos
[1] + 2;
556 } else if (*pos
== WLAN_EID_EXT_SUPP_RATES
) {
557 ie
->ext_supp_rates
= pos
;
558 ie
->ext_supp_rates_len
= pos
[1] + 2;
559 } else if (*pos
== WLAN_EID_HT_CAP
&&
560 pos
[1] >= sizeof(struct ieee80211_ht_capabilities
)) {
561 ie
->ht_capabilities
= pos
+ 2;
562 } else if (*pos
== WLAN_EID_VHT_AID
) {
564 ie
->aid
= WPA_GET_LE16(pos
+ 2) & 0x3fff;
565 } else if (*pos
== WLAN_EID_VHT_CAP
&&
566 pos
[1] >= sizeof(struct ieee80211_vht_capabilities
))
568 ie
->vht_capabilities
= pos
+ 2;
569 } else if (*pos
== WLAN_EID_QOS
&& pos
[1] >= 1) {
570 ie
->qosinfo
= pos
[2];
571 } else if (*pos
== WLAN_EID_SUPPORTED_CHANNELS
) {
572 ie
->supp_channels
= pos
+ 2;
573 ie
->supp_channels_len
= pos
[1];
574 } else if (*pos
== WLAN_EID_SUPPORTED_OPERATING_CLASSES
) {
576 * The value of the Length field of the Supported
577 * Operating Classes element is between 2 and 253.
578 * Silently skip invalid elements to avoid interop
579 * issues when trying to use the value.
581 if (pos
[1] >= 2 && pos
[1] <= 253) {
582 ie
->supp_oper_classes
= pos
+ 2;
583 ie
->supp_oper_classes_len
= pos
[1];
585 } else if (*pos
== WLAN_EID_VENDOR_SPECIFIC
) {
586 ret
= wpa_parse_generic(pos
, end
, ie
);
594 ret
= wpa_parse_vendor_specific(pos
, end
, ie
);
602 wpa_hexdump(MSG_DEBUG
, "WPA: Unrecognized EAPOL-Key "
603 "Key Data IE", pos
, 2 + pos
[1]);