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