Branch data Line data Source code
1 : : /*
2 : : * hostapd - WPA/RSN IE and KDE definitions
3 : : * Copyright (c) 2004-2008, 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 "utils/includes.h"
10 : :
11 : : #include "utils/common.h"
12 : : #include "common/ieee802_11_defs.h"
13 : : #include "eapol_auth/eapol_auth_sm.h"
14 : : #include "ap_config.h"
15 : : #include "ieee802_11.h"
16 : : #include "wpa_auth.h"
17 : : #include "pmksa_cache_auth.h"
18 : : #include "wpa_auth_ie.h"
19 : : #include "wpa_auth_i.h"
20 : :
21 : :
22 : : #ifdef CONFIG_RSN_TESTING
23 : : int rsn_testing = 0;
24 : : #endif /* CONFIG_RSN_TESTING */
25 : :
26 : :
27 : 16 : static int wpa_write_wpa_ie(struct wpa_auth_config *conf, u8 *buf, size_t len)
28 : : {
29 : : struct wpa_ie_hdr *hdr;
30 : : int num_suites;
31 : : u8 *pos, *count;
32 : : u32 suite;
33 : :
34 : 16 : hdr = (struct wpa_ie_hdr *) buf;
35 : 16 : hdr->elem_id = WLAN_EID_VENDOR_SPECIFIC;
36 : 16 : RSN_SELECTOR_PUT(hdr->oui, WPA_OUI_TYPE);
37 : 16 : WPA_PUT_LE16(hdr->version, WPA_VERSION);
38 : 16 : pos = (u8 *) (hdr + 1);
39 : :
40 : 16 : suite = wpa_cipher_to_suite(WPA_PROTO_WPA, conf->wpa_group);
41 [ - + ]: 16 : if (suite == 0) {
42 : 0 : wpa_printf(MSG_DEBUG, "Invalid group cipher (%d).",
43 : : conf->wpa_group);
44 : 0 : return -1;
45 : : }
46 : 16 : RSN_SELECTOR_PUT(pos, suite);
47 : 16 : pos += WPA_SELECTOR_LEN;
48 : :
49 : 16 : count = pos;
50 : 16 : pos += 2;
51 : :
52 : 16 : num_suites = wpa_cipher_put_suites(pos, conf->wpa_pairwise);
53 [ - + ]: 16 : if (num_suites == 0) {
54 : 0 : wpa_printf(MSG_DEBUG, "Invalid pairwise cipher (%d).",
55 : : conf->wpa_pairwise);
56 : 0 : return -1;
57 : : }
58 : 16 : pos += num_suites * WPA_SELECTOR_LEN;
59 : 16 : WPA_PUT_LE16(count, num_suites);
60 : :
61 : 16 : num_suites = 0;
62 : 16 : count = pos;
63 : 16 : pos += 2;
64 : :
65 [ + + ]: 16 : if (conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X) {
66 : 1 : RSN_SELECTOR_PUT(pos, WPA_AUTH_KEY_MGMT_UNSPEC_802_1X);
67 : 1 : pos += WPA_SELECTOR_LEN;
68 : 1 : num_suites++;
69 : : }
70 [ + + ]: 16 : if (conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK) {
71 : 15 : RSN_SELECTOR_PUT(pos, WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X);
72 : 15 : pos += WPA_SELECTOR_LEN;
73 : 15 : num_suites++;
74 : : }
75 : :
76 [ - + ]: 16 : if (num_suites == 0) {
77 : 0 : wpa_printf(MSG_DEBUG, "Invalid key management type (%d).",
78 : : conf->wpa_key_mgmt);
79 : 0 : return -1;
80 : : }
81 : 16 : WPA_PUT_LE16(count, num_suites);
82 : :
83 : : /* WPA Capabilities; use defaults, so no need to include it */
84 : :
85 : 16 : hdr->len = (pos - buf) - 2;
86 : :
87 : 16 : return pos - buf;
88 : : }
89 : :
90 : :
91 : 190 : int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len,
92 : : const u8 *pmkid)
93 : : {
94 : : struct rsn_ie_hdr *hdr;
95 : : int num_suites, res;
96 : : u8 *pos, *count;
97 : : u16 capab;
98 : : u32 suite;
99 : :
100 : 190 : hdr = (struct rsn_ie_hdr *) buf;
101 : 190 : hdr->elem_id = WLAN_EID_RSN;
102 : 190 : WPA_PUT_LE16(hdr->version, RSN_VERSION);
103 : 190 : pos = (u8 *) (hdr + 1);
104 : :
105 : 190 : suite = wpa_cipher_to_suite(WPA_PROTO_RSN, conf->wpa_group);
106 [ - + ]: 190 : if (suite == 0) {
107 : 0 : wpa_printf(MSG_DEBUG, "Invalid group cipher (%d).",
108 : : conf->wpa_group);
109 : 0 : return -1;
110 : : }
111 : 190 : RSN_SELECTOR_PUT(pos, suite);
112 : 190 : pos += RSN_SELECTOR_LEN;
113 : :
114 : 190 : num_suites = 0;
115 : 190 : count = pos;
116 : 190 : pos += 2;
117 : :
118 : : #ifdef CONFIG_RSN_TESTING
119 : : if (rsn_testing) {
120 : : RSN_SELECTOR_PUT(pos, RSN_SELECTOR(0x12, 0x34, 0x56, 1));
121 : : pos += RSN_SELECTOR_LEN;
122 : : num_suites++;
123 : : }
124 : : #endif /* CONFIG_RSN_TESTING */
125 : :
126 : 190 : res = rsn_cipher_put_suites(pos, conf->rsn_pairwise);
127 : 190 : num_suites += res;
128 : 190 : pos += res * RSN_SELECTOR_LEN;
129 : :
130 : : #ifdef CONFIG_RSN_TESTING
131 : : if (rsn_testing) {
132 : : RSN_SELECTOR_PUT(pos, RSN_SELECTOR(0x12, 0x34, 0x56, 2));
133 : : pos += RSN_SELECTOR_LEN;
134 : : num_suites++;
135 : : }
136 : : #endif /* CONFIG_RSN_TESTING */
137 : :
138 [ - + ]: 190 : if (num_suites == 0) {
139 : 0 : wpa_printf(MSG_DEBUG, "Invalid pairwise cipher (%d).",
140 : : conf->rsn_pairwise);
141 : 0 : return -1;
142 : : }
143 : 190 : WPA_PUT_LE16(count, num_suites);
144 : :
145 : 190 : num_suites = 0;
146 : 190 : count = pos;
147 : 190 : pos += 2;
148 : :
149 : : #ifdef CONFIG_RSN_TESTING
150 : : if (rsn_testing) {
151 : : RSN_SELECTOR_PUT(pos, RSN_SELECTOR(0x12, 0x34, 0x56, 1));
152 : : pos += RSN_SELECTOR_LEN;
153 : : num_suites++;
154 : : }
155 : : #endif /* CONFIG_RSN_TESTING */
156 : :
157 [ + + ]: 190 : if (conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X) {
158 : 71 : RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_UNSPEC_802_1X);
159 : 71 : pos += RSN_SELECTOR_LEN;
160 : 71 : num_suites++;
161 : : }
162 [ + + ]: 190 : if (conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK) {
163 : 69 : RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X);
164 : 69 : pos += RSN_SELECTOR_LEN;
165 : 69 : num_suites++;
166 : : }
167 : : #ifdef CONFIG_IEEE80211R
168 [ + + ]: 190 : if (conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) {
169 : 6 : RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_802_1X);
170 : 6 : pos += RSN_SELECTOR_LEN;
171 : 6 : num_suites++;
172 : : }
173 [ + + ]: 190 : if (conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_PSK) {
174 : 30 : RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_PSK);
175 : 30 : pos += RSN_SELECTOR_LEN;
176 : 30 : num_suites++;
177 : : }
178 : : #endif /* CONFIG_IEEE80211R */
179 : : #ifdef CONFIG_IEEE80211W
180 [ + + ]: 190 : if (conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) {
181 : 1 : RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_802_1X_SHA256);
182 : 1 : pos += RSN_SELECTOR_LEN;
183 : 1 : num_suites++;
184 : : }
185 [ + + ]: 190 : if (conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK_SHA256) {
186 : 4 : RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_PSK_SHA256);
187 : 4 : pos += RSN_SELECTOR_LEN;
188 : 4 : num_suites++;
189 : : }
190 : : #endif /* CONFIG_IEEE80211W */
191 : : #ifdef CONFIG_SAE
192 [ + + ]: 190 : if (conf->wpa_key_mgmt & WPA_KEY_MGMT_SAE) {
193 : 4 : RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_SAE);
194 : 4 : pos += RSN_SELECTOR_LEN;
195 : 4 : num_suites++;
196 : : }
197 [ + + ]: 190 : if (conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_SAE) {
198 : 12 : RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_SAE);
199 : 12 : pos += RSN_SELECTOR_LEN;
200 : 12 : num_suites++;
201 : : }
202 : : #endif /* CONFIG_SAE */
203 : :
204 : : #ifdef CONFIG_RSN_TESTING
205 : : if (rsn_testing) {
206 : : RSN_SELECTOR_PUT(pos, RSN_SELECTOR(0x12, 0x34, 0x56, 2));
207 : : pos += RSN_SELECTOR_LEN;
208 : : num_suites++;
209 : : }
210 : : #endif /* CONFIG_RSN_TESTING */
211 : :
212 [ - + ]: 190 : if (num_suites == 0) {
213 : 0 : wpa_printf(MSG_DEBUG, "Invalid key management type (%d).",
214 : : conf->wpa_key_mgmt);
215 : 0 : return -1;
216 : : }
217 : 190 : WPA_PUT_LE16(count, num_suites);
218 : :
219 : : /* RSN Capabilities */
220 : 190 : capab = 0;
221 [ - + ]: 190 : if (conf->rsn_preauth)
222 : 0 : capab |= WPA_CAPABILITY_PREAUTH;
223 [ + + ]: 190 : if (conf->peerkey)
224 : 1 : capab |= WPA_CAPABILITY_PEERKEY_ENABLED;
225 [ + - ]: 190 : if (conf->wmm_enabled) {
226 : : /* 4 PTKSA replay counters when using WMM */
227 : 190 : capab |= (RSN_NUM_REPLAY_COUNTERS_16 << 2);
228 : : }
229 : : #ifdef CONFIG_IEEE80211W
230 [ + + ]: 190 : if (conf->ieee80211w != NO_MGMT_FRAME_PROTECTION) {
231 : 59 : capab |= WPA_CAPABILITY_MFPC;
232 [ + + ]: 59 : if (conf->ieee80211w == MGMT_FRAME_PROTECTION_REQUIRED)
233 : 16 : capab |= WPA_CAPABILITY_MFPR;
234 : : }
235 : : #endif /* CONFIG_IEEE80211W */
236 : : #ifdef CONFIG_RSN_TESTING
237 : : if (rsn_testing)
238 : : capab |= BIT(8) | BIT(14) | BIT(15);
239 : : #endif /* CONFIG_RSN_TESTING */
240 : 190 : WPA_PUT_LE16(pos, capab);
241 : 190 : pos += 2;
242 : :
243 [ + + ]: 190 : if (pmkid) {
244 [ - + ]: 32 : if (pos + 2 + PMKID_LEN > buf + len)
245 : 0 : return -1;
246 : : /* PMKID Count */
247 : 32 : WPA_PUT_LE16(pos, 1);
248 : 32 : pos += 2;
249 : 32 : os_memcpy(pos, pmkid, PMKID_LEN);
250 : 32 : pos += PMKID_LEN;
251 : : }
252 : :
253 : : #ifdef CONFIG_IEEE80211W
254 [ + + ]: 190 : if (conf->ieee80211w != NO_MGMT_FRAME_PROTECTION) {
255 [ - + ]: 59 : if (pos + 2 + 4 > buf + len)
256 : 0 : return -1;
257 [ + + ]: 59 : if (pmkid == NULL) {
258 : : /* PMKID Count */
259 : 51 : WPA_PUT_LE16(pos, 0);
260 : 51 : pos += 2;
261 : : }
262 : :
263 : : /* Management Group Cipher Suite */
264 : 59 : RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_AES_128_CMAC);
265 : 59 : pos += RSN_SELECTOR_LEN;
266 : : }
267 : : #endif /* CONFIG_IEEE80211W */
268 : :
269 : : #ifdef CONFIG_RSN_TESTING
270 : : if (rsn_testing) {
271 : : /*
272 : : * Fill in any defined fields and add extra data to the end of
273 : : * the element.
274 : : */
275 : : int pmkid_count_set = pmkid != NULL;
276 : : if (conf->ieee80211w != NO_MGMT_FRAME_PROTECTION)
277 : : pmkid_count_set = 1;
278 : : /* PMKID Count */
279 : : WPA_PUT_LE16(pos, 0);
280 : : pos += 2;
281 : : if (conf->ieee80211w == NO_MGMT_FRAME_PROTECTION) {
282 : : /* Management Group Cipher Suite */
283 : : RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_AES_128_CMAC);
284 : : pos += RSN_SELECTOR_LEN;
285 : : }
286 : :
287 : : os_memset(pos, 0x12, 17);
288 : : pos += 17;
289 : : }
290 : : #endif /* CONFIG_RSN_TESTING */
291 : :
292 : 190 : hdr->len = (pos - buf) - 2;
293 : :
294 : 190 : return pos - buf;
295 : : }
296 : :
297 : :
298 : 161 : int wpa_auth_gen_wpa_ie(struct wpa_authenticator *wpa_auth)
299 : : {
300 : : u8 *pos, buf[128];
301 : : int res;
302 : :
303 : 161 : pos = buf;
304 : :
305 [ + + ]: 161 : if (wpa_auth->conf.wpa & WPA_PROTO_RSN) {
306 : 158 : res = wpa_write_rsn_ie(&wpa_auth->conf,
307 : 158 : pos, buf + sizeof(buf) - pos, NULL);
308 [ - + ]: 158 : if (res < 0)
309 : 0 : return res;
310 : 158 : pos += res;
311 : : }
312 : : #ifdef CONFIG_IEEE80211R
313 [ + + ]: 161 : if (wpa_key_mgmt_ft(wpa_auth->conf.wpa_key_mgmt)) {
314 : 16 : res = wpa_write_mdie(&wpa_auth->conf, pos,
315 : 16 : buf + sizeof(buf) - pos);
316 [ - + ]: 16 : if (res < 0)
317 : 0 : return res;
318 : 16 : pos += res;
319 : : }
320 : : #endif /* CONFIG_IEEE80211R */
321 [ + + ]: 161 : if (wpa_auth->conf.wpa & WPA_PROTO_WPA) {
322 : 16 : res = wpa_write_wpa_ie(&wpa_auth->conf,
323 : 16 : pos, buf + sizeof(buf) - pos);
324 [ - + ]: 16 : if (res < 0)
325 : 0 : return res;
326 : 16 : pos += res;
327 : : }
328 : :
329 : 161 : os_free(wpa_auth->wpa_ie);
330 : 161 : wpa_auth->wpa_ie = os_malloc(pos - buf);
331 [ - + ]: 161 : if (wpa_auth->wpa_ie == NULL)
332 : 0 : return -1;
333 : 161 : os_memcpy(wpa_auth->wpa_ie, buf, pos - buf);
334 : 161 : wpa_auth->wpa_ie_len = pos - buf;
335 : :
336 : 161 : return 0;
337 : : }
338 : :
339 : :
340 : 204 : u8 * wpa_add_kde(u8 *pos, u32 kde, const u8 *data, size_t data_len,
341 : : const u8 *data2, size_t data2_len)
342 : : {
343 : 204 : *pos++ = WLAN_EID_VENDOR_SPECIFIC;
344 : 204 : *pos++ = RSN_SELECTOR_LEN + data_len + data2_len;
345 : 204 : RSN_SELECTOR_PUT(pos, kde);
346 : 204 : pos += RSN_SELECTOR_LEN;
347 : 204 : os_memcpy(pos, data, data_len);
348 : 204 : pos += data_len;
349 [ + + ]: 204 : if (data2) {
350 : 185 : os_memcpy(pos, data2, data2_len);
351 : 185 : pos += data2_len;
352 : : }
353 : 204 : return pos;
354 : : }
355 : :
356 : :
357 : : struct wpa_auth_okc_iter_data {
358 : : struct rsn_pmksa_cache_entry *pmksa;
359 : : const u8 *aa;
360 : : const u8 *spa;
361 : : const u8 *pmkid;
362 : : };
363 : :
364 : :
365 : 1 : static int wpa_auth_okc_iter(struct wpa_authenticator *a, void *ctx)
366 : : {
367 : 1 : struct wpa_auth_okc_iter_data *data = ctx;
368 : 1 : data->pmksa = pmksa_cache_get_okc(a->pmksa, data->aa, data->spa,
369 : : data->pmkid);
370 [ + - ]: 1 : if (data->pmksa)
371 : 1 : return 1;
372 : 1 : return 0;
373 : : }
374 : :
375 : :
376 : 189 : int wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth,
377 : : struct wpa_state_machine *sm,
378 : : const u8 *wpa_ie, size_t wpa_ie_len,
379 : : const u8 *mdie, size_t mdie_len)
380 : : {
381 : : struct wpa_ie_data data;
382 : : int ciphers, key_mgmt, res, version;
383 : : u32 selector;
384 : : size_t i;
385 : 189 : const u8 *pmkid = NULL;
386 : :
387 [ + - ][ - + ]: 189 : if (wpa_auth == NULL || sm == NULL)
388 : 0 : return WPA_NOT_ENABLED;
389 : :
390 [ + - ][ - + ]: 189 : if (wpa_ie == NULL || wpa_ie_len < 1)
391 : 0 : return WPA_INVALID_IE;
392 : :
393 [ + + ]: 189 : if (wpa_ie[0] == WLAN_EID_RSN)
394 : 182 : version = WPA_PROTO_RSN;
395 : : else
396 : 7 : version = WPA_PROTO_WPA;
397 : :
398 [ - + ]: 189 : if (!(wpa_auth->conf.wpa & version)) {
399 : 0 : wpa_printf(MSG_DEBUG, "Invalid WPA proto (%d) from " MACSTR,
400 : 0 : version, MAC2STR(sm->addr));
401 : 0 : return WPA_INVALID_PROTO;
402 : : }
403 : :
404 [ + + ]: 189 : if (version == WPA_PROTO_RSN) {
405 : 182 : res = wpa_parse_wpa_ie_rsn(wpa_ie, wpa_ie_len, &data);
406 : :
407 : 182 : selector = RSN_AUTH_KEY_MGMT_UNSPEC_802_1X;
408 : : if (0) {
409 : : }
410 : : #ifdef CONFIG_IEEE80211R
411 [ + + ]: 182 : else if (data.key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X)
412 : 3 : selector = RSN_AUTH_KEY_MGMT_FT_802_1X;
413 [ + + ]: 179 : else if (data.key_mgmt & WPA_KEY_MGMT_FT_PSK)
414 : 15 : selector = RSN_AUTH_KEY_MGMT_FT_PSK;
415 : : #endif /* CONFIG_IEEE80211R */
416 : : #ifdef CONFIG_IEEE80211W
417 [ + + ]: 164 : else if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256)
418 : 1 : selector = RSN_AUTH_KEY_MGMT_802_1X_SHA256;
419 [ + + ]: 163 : else if (data.key_mgmt & WPA_KEY_MGMT_PSK_SHA256)
420 : 6 : selector = RSN_AUTH_KEY_MGMT_PSK_SHA256;
421 : : #endif /* CONFIG_IEEE80211W */
422 : : #ifdef CONFIG_SAE
423 [ + + ]: 157 : else if (data.key_mgmt & WPA_KEY_MGMT_SAE)
424 : 14 : selector = RSN_AUTH_KEY_MGMT_SAE;
425 [ + + ]: 143 : else if (data.key_mgmt & WPA_KEY_MGMT_FT_SAE)
426 : 6 : selector = RSN_AUTH_KEY_MGMT_FT_SAE;
427 : : #endif /* CONFIG_SAE */
428 [ + + ]: 137 : else if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X)
429 : 67 : selector = RSN_AUTH_KEY_MGMT_UNSPEC_802_1X;
430 [ + - ]: 70 : else if (data.key_mgmt & WPA_KEY_MGMT_PSK)
431 : 70 : selector = RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X;
432 : 182 : wpa_auth->dot11RSNAAuthenticationSuiteSelected = selector;
433 : :
434 : 182 : selector = wpa_cipher_to_suite(WPA_PROTO_RSN,
435 : : data.pairwise_cipher);
436 [ - + ]: 182 : if (!selector)
437 : 0 : selector = RSN_CIPHER_SUITE_CCMP;
438 : 182 : wpa_auth->dot11RSNAPairwiseCipherSelected = selector;
439 : :
440 : 182 : selector = wpa_cipher_to_suite(WPA_PROTO_RSN,
441 : : data.group_cipher);
442 [ - + ]: 182 : if (!selector)
443 : 0 : selector = RSN_CIPHER_SUITE_CCMP;
444 : 182 : wpa_auth->dot11RSNAGroupCipherSelected = selector;
445 : : } else {
446 : 7 : res = wpa_parse_wpa_ie_wpa(wpa_ie, wpa_ie_len, &data);
447 : :
448 : 7 : selector = WPA_AUTH_KEY_MGMT_UNSPEC_802_1X;
449 [ + + ]: 7 : if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X)
450 : 1 : selector = WPA_AUTH_KEY_MGMT_UNSPEC_802_1X;
451 [ + - ]: 6 : else if (data.key_mgmt & WPA_KEY_MGMT_PSK)
452 : 6 : selector = WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X;
453 : 7 : wpa_auth->dot11RSNAAuthenticationSuiteSelected = selector;
454 : :
455 : 7 : selector = wpa_cipher_to_suite(WPA_PROTO_WPA,
456 : : data.pairwise_cipher);
457 [ - + ]: 7 : if (!selector)
458 : 0 : selector = RSN_CIPHER_SUITE_TKIP;
459 : 7 : wpa_auth->dot11RSNAPairwiseCipherSelected = selector;
460 : :
461 : 7 : selector = wpa_cipher_to_suite(WPA_PROTO_WPA,
462 : : data.group_cipher);
463 [ - + ]: 7 : if (!selector)
464 : 0 : selector = WPA_CIPHER_SUITE_TKIP;
465 : 7 : wpa_auth->dot11RSNAGroupCipherSelected = selector;
466 : : }
467 [ - + ]: 189 : if (res) {
468 : 0 : wpa_printf(MSG_DEBUG, "Failed to parse WPA/RSN IE from "
469 : 0 : MACSTR " (res=%d)", MAC2STR(sm->addr), res);
470 : 0 : wpa_hexdump(MSG_DEBUG, "WPA/RSN IE", wpa_ie, wpa_ie_len);
471 : 0 : return WPA_INVALID_IE;
472 : : }
473 : :
474 [ - + ]: 189 : if (data.group_cipher != wpa_auth->conf.wpa_group) {
475 : 0 : wpa_printf(MSG_DEBUG, "Invalid WPA group cipher (0x%x) from "
476 : 0 : MACSTR, data.group_cipher, MAC2STR(sm->addr));
477 : 0 : return WPA_INVALID_GROUP;
478 : : }
479 : :
480 : 189 : key_mgmt = data.key_mgmt & wpa_auth->conf.wpa_key_mgmt;
481 [ - + ]: 189 : if (!key_mgmt) {
482 : 0 : wpa_printf(MSG_DEBUG, "Invalid WPA key mgmt (0x%x) from "
483 : 0 : MACSTR, data.key_mgmt, MAC2STR(sm->addr));
484 : 0 : return WPA_INVALID_AKMP;
485 : : }
486 : : if (0) {
487 : : }
488 : : #ifdef CONFIG_IEEE80211R
489 [ + + ]: 189 : else if (key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X)
490 : 3 : sm->wpa_key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X;
491 [ + + ]: 186 : else if (key_mgmt & WPA_KEY_MGMT_FT_PSK)
492 : 15 : sm->wpa_key_mgmt = WPA_KEY_MGMT_FT_PSK;
493 : : #endif /* CONFIG_IEEE80211R */
494 : : #ifdef CONFIG_IEEE80211W
495 [ + + ]: 171 : else if (key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256)
496 : 1 : sm->wpa_key_mgmt = WPA_KEY_MGMT_IEEE8021X_SHA256;
497 [ + + ]: 170 : else if (key_mgmt & WPA_KEY_MGMT_PSK_SHA256)
498 : 6 : sm->wpa_key_mgmt = WPA_KEY_MGMT_PSK_SHA256;
499 : : #endif /* CONFIG_IEEE80211W */
500 : : #ifdef CONFIG_SAE
501 [ + + ]: 164 : else if (key_mgmt & WPA_KEY_MGMT_SAE)
502 : 14 : sm->wpa_key_mgmt = WPA_KEY_MGMT_SAE;
503 [ + + ]: 150 : else if (key_mgmt & WPA_KEY_MGMT_FT_SAE)
504 : 6 : sm->wpa_key_mgmt = WPA_KEY_MGMT_FT_SAE;
505 : : #endif /* CONFIG_SAE */
506 [ + + ]: 144 : else if (key_mgmt & WPA_KEY_MGMT_IEEE8021X)
507 : 68 : sm->wpa_key_mgmt = WPA_KEY_MGMT_IEEE8021X;
508 : : else
509 : 76 : sm->wpa_key_mgmt = WPA_KEY_MGMT_PSK;
510 : :
511 [ + + ]: 189 : if (version == WPA_PROTO_RSN)
512 : 182 : ciphers = data.pairwise_cipher & wpa_auth->conf.rsn_pairwise;
513 : : else
514 : 7 : ciphers = data.pairwise_cipher & wpa_auth->conf.wpa_pairwise;
515 [ - + ]: 189 : if (!ciphers) {
516 [ # # ]: 0 : wpa_printf(MSG_DEBUG, "Invalid %s pairwise cipher (0x%x) "
517 : : "from " MACSTR,
518 : : version == WPA_PROTO_RSN ? "RSN" : "WPA",
519 : 0 : data.pairwise_cipher, MAC2STR(sm->addr));
520 : 0 : return WPA_INVALID_PAIRWISE;
521 : : }
522 : :
523 : : #ifdef CONFIG_IEEE80211W
524 [ + + ]: 189 : if (wpa_auth->conf.ieee80211w == MGMT_FRAME_PROTECTION_REQUIRED) {
525 [ - + ]: 11 : if (!(data.capabilities & WPA_CAPABILITY_MFPC)) {
526 : 0 : wpa_printf(MSG_DEBUG, "Management frame protection "
527 : : "required, but client did not enable it");
528 : 0 : return WPA_MGMT_FRAME_PROTECTION_VIOLATION;
529 : : }
530 : :
531 [ - + ]: 11 : if (ciphers & WPA_CIPHER_TKIP) {
532 : 0 : wpa_printf(MSG_DEBUG, "Management frame protection "
533 : : "cannot use TKIP");
534 : 0 : return WPA_MGMT_FRAME_PROTECTION_VIOLATION;
535 : : }
536 : :
537 [ - + ]: 11 : if (data.mgmt_group_cipher != WPA_CIPHER_AES_128_CMAC) {
538 : 0 : wpa_printf(MSG_DEBUG, "Unsupported management group "
539 : : "cipher %d", data.mgmt_group_cipher);
540 : 0 : return WPA_INVALID_MGMT_GROUP_CIPHER;
541 : : }
542 : : }
543 : :
544 [ + + ][ + + ]: 189 : if (wpa_auth->conf.ieee80211w == NO_MGMT_FRAME_PROTECTION ||
545 : 44 : !(data.capabilities & WPA_CAPABILITY_MFPC))
546 : 174 : sm->mgmt_frame_prot = 0;
547 : : else
548 : 15 : sm->mgmt_frame_prot = 1;
549 : : #endif /* CONFIG_IEEE80211W */
550 : :
551 : : #ifdef CONFIG_IEEE80211R
552 [ + + ]: 189 : if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) {
553 [ + - ][ - + ]: 24 : if (mdie == NULL || mdie_len < MOBILITY_DOMAIN_ID_LEN + 1) {
554 : 0 : wpa_printf(MSG_DEBUG, "RSN: Trying to use FT, but "
555 : : "MDIE not included");
556 : 0 : return WPA_INVALID_MDIE;
557 : : }
558 [ - + ]: 24 : if (os_memcmp(mdie, wpa_auth->conf.mobility_domain,
559 : : MOBILITY_DOMAIN_ID_LEN) != 0) {
560 : 0 : wpa_hexdump(MSG_DEBUG, "RSN: Attempted to use unknown "
561 : : "MDIE", mdie, MOBILITY_DOMAIN_ID_LEN);
562 : 0 : return WPA_INVALID_MDIE;
563 : : }
564 : : }
565 : : #endif /* CONFIG_IEEE80211R */
566 : :
567 : 189 : sm->pairwise = wpa_pick_pairwise_cipher(ciphers, 0);
568 [ - + ]: 189 : if (sm->pairwise < 0)
569 : 0 : return WPA_INVALID_PAIRWISE;
570 : :
571 : : /* TODO: clear WPA/WPA2 state if STA changes from one to another */
572 [ + + ]: 189 : if (wpa_ie[0] == WLAN_EID_RSN)
573 : 182 : sm->wpa = WPA_VERSION_WPA2;
574 : : else
575 : 7 : sm->wpa = WPA_VERSION_WPA;
576 : :
577 : 189 : sm->pmksa = NULL;
578 [ + + ]: 207 : for (i = 0; i < data.num_pmkid; i++) {
579 : 22 : wpa_hexdump(MSG_DEBUG, "RSN IE: STA PMKID",
580 : 22 : &data.pmkid[i * PMKID_LEN], PMKID_LEN);
581 : 22 : sm->pmksa = pmksa_cache_auth_get(wpa_auth->pmksa, sm->addr,
582 : 22 : &data.pmkid[i * PMKID_LEN]);
583 [ + + ]: 22 : if (sm->pmksa) {
584 : 4 : pmkid = sm->pmksa->pmkid;
585 : 4 : break;
586 : : }
587 : : }
588 [ + + ][ + + ]: 189 : for (i = 0; sm->pmksa == NULL && wpa_auth->conf.okc &&
[ + + ]
589 : 0 : i < data.num_pmkid; i++) {
590 : : struct wpa_auth_okc_iter_data idata;
591 : 1 : idata.pmksa = NULL;
592 : 1 : idata.aa = wpa_auth->addr;
593 : 1 : idata.spa = sm->addr;
594 : 1 : idata.pmkid = &data.pmkid[i * PMKID_LEN];
595 : 1 : wpa_auth_for_each_auth(wpa_auth, wpa_auth_okc_iter, &idata);
596 [ + - ]: 1 : if (idata.pmksa) {
597 : 1 : wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG,
598 : : "OKC match for PMKID");
599 : 1 : sm->pmksa = pmksa_cache_add_okc(wpa_auth->pmksa,
600 : 1 : idata.pmksa,
601 : 1 : wpa_auth->addr,
602 : : idata.pmkid);
603 : 1 : pmkid = idata.pmkid;
604 : 1 : break;
605 : : }
606 : : }
607 [ + + ]: 189 : if (sm->pmksa) {
608 : 5 : wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG,
609 : : "PMKID found from PMKSA cache "
610 : : "eap_type=%d vlan_id=%d",
611 : 5 : sm->pmksa->eap_type_authsrv,
612 : 5 : sm->pmksa->vlan_id);
613 : 5 : os_memcpy(wpa_auth->dot11RSNAPMKIDUsed, pmkid, PMKID_LEN);
614 : : }
615 : :
616 [ + + ][ + + ]: 189 : if (sm->wpa_ie == NULL || sm->wpa_ie_len < wpa_ie_len) {
617 : 187 : os_free(sm->wpa_ie);
618 : 187 : sm->wpa_ie = os_malloc(wpa_ie_len);
619 [ - + ]: 187 : if (sm->wpa_ie == NULL)
620 : 0 : return WPA_ALLOC_FAIL;
621 : : }
622 : 189 : os_memcpy(sm->wpa_ie, wpa_ie, wpa_ie_len);
623 : 189 : sm->wpa_ie_len = wpa_ie_len;
624 : :
625 : 189 : return WPA_IE_OK;
626 : : }
627 : :
628 : :
629 : : /**
630 : : * wpa_parse_generic - Parse EAPOL-Key Key Data Generic IEs
631 : : * @pos: Pointer to the IE header
632 : : * @end: Pointer to the end of the Key Data buffer
633 : : * @ie: Pointer to parsed IE data
634 : : * Returns: 0 on success, 1 if end mark is found, -1 on failure
635 : : */
636 : 11 : static int wpa_parse_generic(const u8 *pos, const u8 *end,
637 : : struct wpa_eapol_ie_parse *ie)
638 : : {
639 [ - + ]: 11 : if (pos[1] == 0)
640 : 0 : return 1;
641 : :
642 [ + - + + ]: 22 : if (pos[1] >= 6 &&
643 [ + - ]: 19 : RSN_SELECTOR_GET(pos + 2) == WPA_OUI_TYPE &&
644 [ + - ]: 8 : pos[2 + WPA_SELECTOR_LEN] == 1 &&
645 : 8 : pos[2 + WPA_SELECTOR_LEN + 1] == 0) {
646 : 8 : ie->wpa_ie = pos;
647 : 8 : ie->wpa_ie_len = pos[1] + 2;
648 : 8 : return 0;
649 : : }
650 : :
651 [ + - ][ + + ]: 3 : if (pos + 1 + RSN_SELECTOR_LEN < end &&
652 [ - + ]: 1 : pos[1] >= RSN_SELECTOR_LEN + PMKID_LEN &&
653 : 1 : RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_PMKID) {
654 : 0 : ie->pmkid = pos + 2 + RSN_SELECTOR_LEN;
655 : 0 : return 0;
656 : : }
657 : :
658 [ + - - + ]: 6 : if (pos[1] > RSN_SELECTOR_LEN + 2 &&
659 : 3 : RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_GROUPKEY) {
660 : 0 : ie->gtk = pos + 2 + RSN_SELECTOR_LEN;
661 : 0 : ie->gtk_len = pos[1] - RSN_SELECTOR_LEN;
662 : 0 : return 0;
663 : : }
664 : :
665 [ + - + + ]: 6 : if (pos[1] > RSN_SELECTOR_LEN + 2 &&
666 : 3 : RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_MAC_ADDR) {
667 : 2 : ie->mac_addr = pos + 2 + RSN_SELECTOR_LEN;
668 : 2 : ie->mac_addr_len = pos[1] - RSN_SELECTOR_LEN;
669 : 2 : return 0;
670 : : }
671 : :
672 : : #ifdef CONFIG_PEERKEY
673 [ + - - + ]: 2 : if (pos[1] > RSN_SELECTOR_LEN + 2 &&
674 : 1 : RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_SMK) {
675 : 0 : ie->smk = pos + 2 + RSN_SELECTOR_LEN;
676 : 0 : ie->smk_len = pos[1] - RSN_SELECTOR_LEN;
677 : 0 : return 0;
678 : : }
679 : :
680 [ + - + - ]: 2 : if (pos[1] > RSN_SELECTOR_LEN + 2 &&
681 : 1 : RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_NONCE) {
682 : 1 : ie->nonce = pos + 2 + RSN_SELECTOR_LEN;
683 : 1 : ie->nonce_len = pos[1] - RSN_SELECTOR_LEN;
684 : 1 : return 0;
685 : : }
686 : :
687 [ # # # # ]: 0 : if (pos[1] > RSN_SELECTOR_LEN + 2 &&
688 : 0 : RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_LIFETIME) {
689 : 0 : ie->lifetime = pos + 2 + RSN_SELECTOR_LEN;
690 : 0 : ie->lifetime_len = pos[1] - RSN_SELECTOR_LEN;
691 : 0 : return 0;
692 : : }
693 : :
694 [ # # # # ]: 0 : if (pos[1] > RSN_SELECTOR_LEN + 2 &&
695 : 0 : RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_ERROR) {
696 : 0 : ie->error = pos + 2 + RSN_SELECTOR_LEN;
697 : 0 : ie->error_len = pos[1] - RSN_SELECTOR_LEN;
698 : 0 : return 0;
699 : : }
700 : : #endif /* CONFIG_PEERKEY */
701 : :
702 : : #ifdef CONFIG_IEEE80211W
703 [ # # # # ]: 0 : if (pos[1] > RSN_SELECTOR_LEN + 2 &&
704 : 0 : RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_IGTK) {
705 : 0 : ie->igtk = pos + 2 + RSN_SELECTOR_LEN;
706 : 0 : ie->igtk_len = pos[1] - RSN_SELECTOR_LEN;
707 : 0 : return 0;
708 : : }
709 : : #endif /* CONFIG_IEEE80211W */
710 : :
711 : 11 : return 0;
712 : : }
713 : :
714 : :
715 : : /**
716 : : * wpa_parse_kde_ies - Parse EAPOL-Key Key Data IEs
717 : : * @buf: Pointer to the Key Data buffer
718 : : * @len: Key Data Length
719 : : * @ie: Pointer to parsed IE data
720 : : * Returns: 0 on success, -1 on failure
721 : : */
722 : 196 : int wpa_parse_kde_ies(const u8 *buf, size_t len, struct wpa_eapol_ie_parse *ie)
723 : : {
724 : : const u8 *pos, *end;
725 : 196 : int ret = 0;
726 : :
727 : 196 : os_memset(ie, 0, sizeof(*ie));
728 [ + + ]: 411 : for (pos = buf, end = pos + len; pos + 1 < end; pos += 2 + pos[1]) {
729 [ + + ][ + - ]: 215 : if (pos[0] == 0xdd &&
730 [ + - ]: 11 : ((pos == buf + len - 1) || pos[1] == 0)) {
731 : : /* Ignore padding */
732 : : break;
733 : : }
734 [ - + ]: 215 : if (pos + 2 + pos[1] > end) {
735 : 0 : wpa_printf(MSG_DEBUG, "WPA: EAPOL-Key Key Data "
736 : : "underflow (ie=%d len=%d pos=%d)",
737 : 0 : pos[0], pos[1], (int) (pos - buf));
738 : 0 : wpa_hexdump_key(MSG_DEBUG, "WPA: Key Data",
739 : : buf, len);
740 : 0 : ret = -1;
741 : 0 : break;
742 : : }
743 [ + + ]: 215 : if (*pos == WLAN_EID_RSN) {
744 : 188 : ie->rsn_ie = pos;
745 : 188 : ie->rsn_ie_len = pos[1] + 2;
746 : : #ifdef CONFIG_IEEE80211R
747 [ + + ]: 27 : } else if (*pos == WLAN_EID_MOBILITY_DOMAIN) {
748 : 8 : ie->mdie = pos;
749 : 8 : ie->mdie_len = pos[1] + 2;
750 [ + + ]: 19 : } else if (*pos == WLAN_EID_FAST_BSS_TRANSITION) {
751 : 8 : ie->ftie = pos;
752 : 8 : ie->ftie_len = pos[1] + 2;
753 : : #endif /* CONFIG_IEEE80211R */
754 [ + - ]: 11 : } else if (*pos == WLAN_EID_VENDOR_SPECIFIC) {
755 : 11 : ret = wpa_parse_generic(pos, end, ie);
756 [ - + ]: 11 : if (ret < 0)
757 : 0 : break;
758 [ - + ]: 11 : if (ret > 0) {
759 : 0 : ret = 0;
760 : 0 : break;
761 : : }
762 : : } else {
763 : 0 : wpa_hexdump(MSG_DEBUG, "WPA: Unrecognized EAPOL-Key "
764 : 0 : "Key Data IE", pos, 2 + pos[1]);
765 : : }
766 : : }
767 : :
768 : 196 : return ret;
769 : : }
770 : :
771 : :
772 : 198 : int wpa_auth_uses_mfp(struct wpa_state_machine *sm)
773 : : {
774 [ + + ]: 198 : return sm ? sm->mgmt_frame_prot : 0;
775 : : }
|