source: rtems-libbsd/freebsd/contrib/wpa/src/rsn_supp/wpa_ie.c @ 9c9d11b

55-freebsd-126-freebsd-12
Last change on this file since 9c9d11b was 9c9d11b, checked in by Sichen Zhao <1473996754@…>, on 08/01/17 at 12:43:41

Import wpa from FreeBSD

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