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