• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * wpa_supplicant - WPA/RSN IE and KDE processing
3  * Copyright (c) 2003-2018, 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 #ifdef CONFIG_WAPI
92 	} else if (key_mgmt == WPA_KEY_MGMT_WAPI_PSK) {
93 		RSN_SELECTOR_PUT(pos, WPA_KEY_MGMT_WAPI_PSK);
94 	} else if (key_mgmt == WPA_KEY_MGMT_WAPI_CERT) {
95 		RSN_SELECTOR_PUT(pos, WPA_KEY_MGMT_WAPI_CERT);
96 #endif
97 	} else {
98 		wpa_printf(MSG_WARNING, "Invalid key management type (%d).",
99 			   key_mgmt);
100 		return -1;
101 	}
102 	pos += WPA_SELECTOR_LEN;
103 
104 	/* WPA Capabilities; use defaults, so no need to include it */
105 
106 	hdr->len = (pos - wpa_ie) - 2;
107 
108 	WPA_ASSERT((size_t) (pos - wpa_ie) <= wpa_ie_len);
109 
110 	return pos - wpa_ie;
111 }
112 
113 
rsn_supp_capab(struct wpa_sm * sm)114 u16 rsn_supp_capab(struct wpa_sm *sm)
115 {
116 	u16 capab = 0;
117 
118 	if (sm->wmm_enabled) {
119 		/* Advertise 16 PTKSA replay counters when using WMM */
120 		capab |= RSN_NUM_REPLAY_COUNTERS_16 << 2;
121 	}
122 	if (sm->mfp)
123 		capab |= WPA_CAPABILITY_MFPC;
124 	if (sm->mfp == 2)
125 		capab |= WPA_CAPABILITY_MFPR;
126 	if (sm->ocv)
127 		capab |= WPA_CAPABILITY_OCVC;
128 	if (sm->ext_key_id)
129 		capab |= WPA_CAPABILITY_EXT_KEY_ID_FOR_UNICAST;
130 
131 	return capab;
132 }
133 
134 
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)135 static int wpa_gen_wpa_ie_rsn(u8 *rsn_ie, size_t rsn_ie_len,
136 			      int pairwise_cipher, int group_cipher,
137 			      int key_mgmt, int mgmt_group_cipher,
138 			      struct wpa_sm *sm)
139 {
140 	u8 *pos;
141 	struct rsn_ie_hdr *hdr;
142 	u32 suite;
143 
144 	if (rsn_ie_len < sizeof(*hdr) + RSN_SELECTOR_LEN +
145 	    2 + RSN_SELECTOR_LEN + 2 + RSN_SELECTOR_LEN + 2 +
146 	    (sm->cur_pmksa ? 2 + PMKID_LEN : 0)) {
147 		wpa_printf(MSG_DEBUG, "RSN: Too short IE buffer (%lu bytes)",
148 			   (unsigned long) rsn_ie_len);
149 		return -1;
150 	}
151 
152 	hdr = (struct rsn_ie_hdr *) rsn_ie;
153 	hdr->elem_id = WLAN_EID_RSN;
154 	WPA_PUT_LE16(hdr->version, RSN_VERSION);
155 	pos = (u8 *) (hdr + 1);
156 
157 	suite = wpa_cipher_to_suite(WPA_PROTO_RSN, group_cipher);
158 	if (suite == 0) {
159 		wpa_printf(MSG_WARNING, "Invalid group cipher (%d).",
160 			   group_cipher);
161 		return -1;
162 	}
163 	RSN_SELECTOR_PUT(pos, suite);
164 	pos += RSN_SELECTOR_LEN;
165 
166 	*pos++ = 1;
167 	*pos++ = 0;
168 	suite = wpa_cipher_to_suite(WPA_PROTO_RSN, pairwise_cipher);
169 	if (suite == 0 ||
170 	    (!wpa_cipher_valid_pairwise(pairwise_cipher) &&
171 	     pairwise_cipher != WPA_CIPHER_NONE)) {
172 		wpa_printf(MSG_WARNING, "Invalid pairwise cipher (%d).",
173 			   pairwise_cipher);
174 		return -1;
175 	}
176 	RSN_SELECTOR_PUT(pos, suite);
177 	pos += RSN_SELECTOR_LEN;
178 
179 	*pos++ = 1;
180 	*pos++ = 0;
181 	if (key_mgmt == WPA_KEY_MGMT_IEEE8021X) {
182 		RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_UNSPEC_802_1X);
183 	} else if (key_mgmt == WPA_KEY_MGMT_PSK) {
184 		RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X);
185 	} else if (key_mgmt == WPA_KEY_MGMT_CCKM) {
186 		RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_CCKM);
187 #ifdef CONFIG_IEEE80211R
188 	} else if (key_mgmt == WPA_KEY_MGMT_FT_IEEE8021X) {
189 		RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_802_1X);
190 #ifdef CONFIG_SHA384
191 	} else if (key_mgmt == WPA_KEY_MGMT_FT_IEEE8021X_SHA384) {
192 		RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_802_1X_SHA384);
193 #endif /* CONFIG_SHA384 */
194 	} else if (key_mgmt == WPA_KEY_MGMT_FT_PSK) {
195 		RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_PSK);
196 #endif /* CONFIG_IEEE80211R */
197 	} else if (key_mgmt == WPA_KEY_MGMT_IEEE8021X_SHA256) {
198 		RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_802_1X_SHA256);
199 	} else if (key_mgmt == WPA_KEY_MGMT_PSK_SHA256) {
200 		RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_PSK_SHA256);
201 #ifdef CONFIG_SAE
202 	} else if (key_mgmt == WPA_KEY_MGMT_SAE) {
203 		RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_SAE);
204 	} else if (key_mgmt == WPA_KEY_MGMT_SAE_EXT_KEY) {
205 		RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_SAE_EXT_KEY);
206 	} else if (key_mgmt == WPA_KEY_MGMT_FT_SAE) {
207 		RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_SAE);
208 	} else if (key_mgmt == WPA_KEY_MGMT_FT_SAE_EXT_KEY) {
209 		RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_SAE_EXT_KEY);
210 #endif /* CONFIG_SAE */
211 	} else if (key_mgmt == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) {
212 		RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_802_1X_SUITE_B_192);
213 	} else if (key_mgmt == WPA_KEY_MGMT_IEEE8021X_SUITE_B) {
214 		RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_802_1X_SUITE_B);
215 #ifdef CONFIG_FILS
216 	} else if (key_mgmt & WPA_KEY_MGMT_FILS_SHA256) {
217 		RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FILS_SHA256);
218 	} else if (key_mgmt & WPA_KEY_MGMT_FILS_SHA384) {
219 		RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FILS_SHA384);
220 #ifdef CONFIG_IEEE80211R
221 	} else if (key_mgmt & WPA_KEY_MGMT_FT_FILS_SHA256) {
222 		RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_FILS_SHA256);
223 	} else if (key_mgmt & WPA_KEY_MGMT_FT_FILS_SHA384) {
224 		RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_FILS_SHA384);
225 #endif /* CONFIG_IEEE80211R */
226 #endif /* CONFIG_FILS */
227 #ifdef CONFIG_OWE
228 	} else if (key_mgmt & WPA_KEY_MGMT_OWE) {
229 		RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_OWE);
230 #endif /* CONFIG_OWE */
231 #ifdef CONFIG_DPP
232 	} else if (key_mgmt & WPA_KEY_MGMT_DPP) {
233 		RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_DPP);
234 #endif /* CONFIG_DPP */
235 #ifdef CONFIG_HS20
236 	} else if (key_mgmt & WPA_KEY_MGMT_OSEN) {
237 		RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_OSEN);
238 #endif /* CONFIG_HS20 */
239 #ifdef CONFIG_SHA384
240 	} else if (key_mgmt == WPA_KEY_MGMT_IEEE8021X_SHA384) {
241 		RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_802_1X_SHA384);
242 #endif /* CONFIG_SHA384 */
243 	} else {
244 		wpa_printf(MSG_WARNING, "Invalid key management type (%d).",
245 			   key_mgmt);
246 		return -1;
247 	}
248 	pos += RSN_SELECTOR_LEN;
249 
250 	/* RSN Capabilities */
251 	WPA_PUT_LE16(pos, rsn_supp_capab(sm));
252 	pos += 2;
253 
254 	if (sm->cur_pmksa) {
255 		/* PMKID Count (2 octets, little endian) */
256 		*pos++ = 1;
257 		*pos++ = 0;
258 		/* PMKID */
259 		os_memcpy(pos, sm->cur_pmksa->pmkid, PMKID_LEN);
260 		pos += PMKID_LEN;
261 	}
262 
263 	if (wpa_cipher_valid_mgmt_group(mgmt_group_cipher)) {
264 		if (!sm->cur_pmksa) {
265 			/* PMKID Count */
266 			WPA_PUT_LE16(pos, 0);
267 			pos += 2;
268 		}
269 
270 		/* Management Group Cipher Suite */
271 		RSN_SELECTOR_PUT(pos, wpa_cipher_to_suite(WPA_PROTO_RSN,
272 							  mgmt_group_cipher));
273 		pos += RSN_SELECTOR_LEN;
274 	}
275 
276 	hdr->len = (pos - rsn_ie) - 2;
277 
278 	WPA_ASSERT((size_t) (pos - rsn_ie) <= rsn_ie_len);
279 
280 	return pos - rsn_ie;
281 }
282 
283 
284 #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)285 static int wpa_gen_wpa_ie_osen(u8 *wpa_ie, size_t wpa_ie_len,
286 			       int pairwise_cipher, int group_cipher,
287 			       int key_mgmt)
288 {
289 	u8 *pos, *len;
290 	u32 suite;
291 
292 	if (wpa_ie_len < 2 + 4 + RSN_SELECTOR_LEN +
293 	    2 + RSN_SELECTOR_LEN + 2 + RSN_SELECTOR_LEN)
294 		return -1;
295 
296 	pos = wpa_ie;
297 	*pos++ = WLAN_EID_VENDOR_SPECIFIC;
298 	len = pos++; /* to be filled */
299 	WPA_PUT_BE24(pos, OUI_WFA);
300 	pos += 3;
301 	*pos++ = HS20_OSEN_OUI_TYPE;
302 
303 	/* Group Data Cipher Suite */
304 	suite = wpa_cipher_to_suite(WPA_PROTO_RSN, group_cipher);
305 	if (suite == 0) {
306 		wpa_printf(MSG_WARNING, "Invalid group cipher (%d).",
307 			   group_cipher);
308 		return -1;
309 	}
310 	RSN_SELECTOR_PUT(pos, suite);
311 	pos += RSN_SELECTOR_LEN;
312 
313 	/* Pairwise Cipher Suite Count and List */
314 	WPA_PUT_LE16(pos, 1);
315 	pos += 2;
316 	suite = wpa_cipher_to_suite(WPA_PROTO_RSN, pairwise_cipher);
317 	if (suite == 0 ||
318 	    (!wpa_cipher_valid_pairwise(pairwise_cipher) &&
319 	     pairwise_cipher != WPA_CIPHER_NONE)) {
320 		wpa_printf(MSG_WARNING, "Invalid pairwise cipher (%d).",
321 			   pairwise_cipher);
322 		return -1;
323 	}
324 	RSN_SELECTOR_PUT(pos, suite);
325 	pos += RSN_SELECTOR_LEN;
326 
327 	/* AKM Suite Count and List */
328 	WPA_PUT_LE16(pos, 1);
329 	pos += 2;
330 	RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_OSEN);
331 	pos += RSN_SELECTOR_LEN;
332 
333 	*len = pos - len - 1;
334 
335 	WPA_ASSERT((size_t) (pos - wpa_ie) <= wpa_ie_len);
336 
337 	return pos - wpa_ie;
338 }
339 #endif /* CONFIG_HS20 */
340 
341 
342 /**
343  * wpa_gen_wpa_ie - Generate WPA/RSN IE based on current security policy
344  * @sm: Pointer to WPA state machine data from wpa_sm_init()
345  * @wpa_ie: Pointer to memory area for the generated WPA/RSN IE
346  * @wpa_ie_len: Maximum length of the generated WPA/RSN IE
347  * Returns: Length of the generated WPA/RSN IE or -1 on failure
348  */
wpa_gen_wpa_ie(struct wpa_sm * sm,u8 * wpa_ie,size_t wpa_ie_len)349 int wpa_gen_wpa_ie(struct wpa_sm *sm, u8 *wpa_ie, size_t wpa_ie_len)
350 {
351 	if (sm->proto == WPA_PROTO_RSN)
352 		return wpa_gen_wpa_ie_rsn(wpa_ie, wpa_ie_len,
353 					  sm->pairwise_cipher,
354 					  sm->group_cipher,
355 					  sm->key_mgmt, sm->mgmt_group_cipher,
356 					  sm);
357 #ifdef CONFIG_HS20
358 	else if (sm->proto == WPA_PROTO_OSEN)
359 		return wpa_gen_wpa_ie_osen(wpa_ie, wpa_ie_len,
360 					   sm->pairwise_cipher,
361 					   sm->group_cipher,
362 					   sm->key_mgmt);
363 #endif /* CONFIG_HS20 */
364 	else
365 		return wpa_gen_wpa_ie_wpa(wpa_ie, wpa_ie_len,
366 					  sm->pairwise_cipher,
367 					  sm->group_cipher,
368 					  sm->key_mgmt);
369 }
370 
371 
wpa_gen_rsnxe(struct wpa_sm * sm,u8 * rsnxe,size_t rsnxe_len)372 int wpa_gen_rsnxe(struct wpa_sm *sm, u8 *rsnxe, size_t rsnxe_len)
373 {
374 	u8 *pos = rsnxe;
375 	u32 capab = 0, tmp;
376 	size_t flen;
377 
378 	if (wpa_key_mgmt_sae(sm->key_mgmt) &&
379 	    (sm->sae_pwe == SAE_PWE_HASH_TO_ELEMENT ||
380 	     sm->sae_pwe == SAE_PWE_BOTH || sm->sae_pk)) {
381 		capab |= BIT(WLAN_RSNX_CAPAB_SAE_H2E);
382 #ifdef CONFIG_SAE_PK
383 		if (sm->sae_pk)
384 			capab |= BIT(WLAN_RSNX_CAPAB_SAE_PK);
385 #endif /* CONFIG_SAE_PK */
386 	}
387 
388 	if (sm->secure_ltf)
389 		capab |= BIT(WLAN_RSNX_CAPAB_SECURE_LTF);
390 	if (sm->secure_rtt)
391 		capab |= BIT(WLAN_RSNX_CAPAB_SECURE_RTT);
392 	if (sm->prot_range_neg)
393 		capab |= BIT(WLAN_RSNX_CAPAB_URNM_MFPR);
394 	if (sm->ssid_protection)
395 		capab |= BIT(WLAN_RSNX_CAPAB_SSID_PROTECTION);
396 
397 	if (!capab)
398 		return 0; /* no supported extended RSN capabilities */
399 	tmp = capab;
400 	flen = 0;
401 	while (tmp) {
402 		flen++;
403 		tmp >>= 8;
404 	}
405 	if (rsnxe_len < 2 + flen)
406 		return -1;
407 	capab |= flen - 1; /* bit 0-3 = Field length (n - 1) */
408 
409 	*pos++ = WLAN_EID_RSNX;
410 	*pos++ = flen;
411 	while (capab) {
412 		*pos++ = capab & 0xff;
413 		capab >>= 8;
414 	}
415 
416 	return pos - rsnxe;
417 }
418