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