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