1 /*
2  * wpa_supplicant - WPA/RSN IE and KDE processing
3  * Copyright (c) 2003-2008, Jouni Malinen <j@w1.fi>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation.
8  *
9  * Alternatively, this software may be distributed under the terms of BSD
10  * license.
11  *
12  * See README and COPYING for more details.
13  */
14  #ifdef ESP_SUPPLICANT
15 
16 #include "utils/includes.h"
17 
18 #include "utils/common.h"
19 #include "rsn_supp/wpa.h"
20 #include "common/ieee802_11_defs.h"
21 #include "rsn_supp/wpa_ie.h"
22 #include "rsn_supp/pmksa_cache.h"
23 
24 /**
25  * wpa_parse_wpa_ie - Parse WPA/RSN IE
26  * @wpa_ie: Pointer to WPA or RSN IE
27  * @wpa_ie_len: Length of the WPA/RSN IE
28  * @data: Pointer to data area for parsing results
29  * Returns: 0 on success, -1 on failure
30  *
31  * Parse the contents of WPA or RSN IE and write the parsed data into data.
32  */
wpa_parse_wpa_ie(const u8 * wpa_ie,size_t wpa_ie_len,struct wpa_ie_data * data)33 int  wpa_parse_wpa_ie(const u8 *wpa_ie, size_t wpa_ie_len,
34 		     struct wpa_ie_data *data)
35 {
36     if (wpa_ie_len >= 1 && wpa_ie[0] == WLAN_EID_RSN) {
37         return wpa_parse_wpa_ie_rsn(wpa_ie, wpa_ie_len, data);
38     } else if (wpa_ie_len >=1 && wpa_ie[0] == WLAN_EID_RSNX){
39         return wpa_parse_wpa_ie_rsnxe(wpa_ie, wpa_ie_len, data);
40     } else if (wpa_ie[0] == WLAN_EID_WAPI) {
41         return 0;
42     }
43 
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 {
97         wpa_printf(MSG_DEBUG, "Invalid key management type (%d).",
98                key_mgmt);
99         return -1;
100     }
101     pos += WPA_SELECTOR_LEN;
102 
103     /* WPA Capabilities; use defaults, so no need to include it */
104 
105     hdr->len = (pos - wpa_ie) - 2;
106 
107     WPA_ASSERT((size_t) (pos - wpa_ie) <= wpa_ie_len);
108 
109     return pos - wpa_ie;
110 }
111 
112 
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)113 static int wpa_gen_wpa_ie_rsn(u8 *rsn_ie, size_t rsn_ie_len,
114                   int pairwise_cipher, int group_cipher,
115                   int key_mgmt, int mgmt_group_cipher,
116                   struct wpa_sm *sm)
117 {
118     u8 *pos;
119     struct rsn_ie_hdr *hdr;
120     u16 capab;
121     u8 min_len = 0;
122     u32 suite;
123 
124     if (rsn_ie_len < sizeof(*hdr) + RSN_SELECTOR_LEN +
125             2 + RSN_SELECTOR_LEN + 2 + RSN_SELECTOR_LEN + 2 +
126             (sm->cur_pmksa ? 2 + PMKID_LEN : 0)) {
127         wpa_printf(MSG_DEBUG, "RSN: Too short IE buffer (%lu bytes)",
128                 (unsigned long) rsn_ie_len);
129         return -1;
130     }
131 
132     if ( (sm->ap_notify_completed_rsne == true) || (key_mgmt == WPA_KEY_MGMT_IEEE8021X) ) {
133         min_len = sizeof(*hdr) + RSN_SELECTOR_LEN + 2 + RSN_SELECTOR_LEN + 2 + RSN_SELECTOR_LEN + 2;
134     } else {
135         min_len = sizeof(*hdr) + RSN_SELECTOR_LEN;
136     }
137 
138     if (rsn_ie_len < min_len) {
139         wpa_printf(MSG_DEBUG, "RSN: Too short IE buffer (%lu bytes)", (unsigned long) rsn_ie_len);
140     }
141 
142     hdr = (struct rsn_ie_hdr *) rsn_ie;
143     hdr->elem_id = WLAN_EID_RSN;
144     WPA_PUT_LE16(hdr->version, RSN_VERSION);
145     pos = (u8 *) (hdr + 1);
146 
147     suite = wpa_cipher_to_suite(WPA_PROTO_RSN, group_cipher);
148     if (suite == 0) {
149             wpa_printf(MSG_WARNING, "Invalid group cipher (%d).",
150                        group_cipher);
151             return -1;
152     }
153     RSN_SELECTOR_PUT(pos, suite);
154     pos += RSN_SELECTOR_LEN;
155 
156     if ( (sm->ap_notify_completed_rsne == false) && (key_mgmt != WPA_KEY_MGMT_IEEE8021X) ) {
157         hdr->len = (pos - rsn_ie) - 2;
158         return (pos - rsn_ie);
159     }
160 
161     *pos++ = 1;
162     *pos++ = 0;
163     suite = wpa_cipher_to_suite(WPA_PROTO_RSN, pairwise_cipher);
164     if (suite == 0 ||
165          (pairwise_cipher == WPA_CIPHER_NONE)) {
166             wpa_printf(MSG_WARNING, "Invalid pairwise cipher (%d).",
167                        pairwise_cipher);
168             return -1;
169     }
170     RSN_SELECTOR_PUT(pos, suite);
171     pos += RSN_SELECTOR_LEN;
172 
173     *pos++ = 1;
174     *pos++ = 0;
175 
176     if (key_mgmt == WPA_KEY_MGMT_IEEE8021X) {
177         RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_UNSPEC_802_1X);
178     } else if (key_mgmt == WPA_KEY_MGMT_PSK) {
179         RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X);
180 #ifdef CONFIG_IEEE80211R
181     } else if (key_mgmt == WPA_KEY_MGMT_FT_IEEE8021X) {
182         RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_802_1X);
183     } else if (key_mgmt == WPA_KEY_MGMT_FT_PSK) {
184         RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_PSK);
185 #endif /* CONFIG_IEEE80211R */
186 #ifdef CONFIG_IEEE80211W
187     } else if (key_mgmt == WPA_KEY_MGMT_IEEE8021X_SHA256) {
188         RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_802_1X_SHA256);
189     } else if (key_mgmt == WPA_KEY_MGMT_PSK_SHA256) {
190         RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_PSK_SHA256);
191 #ifdef CONFIG_WPA3_SAE
192     } else if (key_mgmt == WPA_KEY_MGMT_SAE) {
193         RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_SAE);
194 #endif /* CONFIG_WPA3_SAE */
195 #ifdef CONFIG_OWE_STA
196     } else if (key_mgmt == WPA_KEY_MGMT_OWE) {
197         RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_OWE);
198 #endif /* CONFIG_OWE_STA */
199 #endif /* CONFIG_IEEE80211W */
200     } else if (key_mgmt == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) {
201         RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_802_1X_SUITE_B_192);
202     } else if (key_mgmt == WPA_KEY_MGMT_IEEE8021X_SUITE_B) {
203         RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_802_1X_SUITE_B);
204     } else {
205         wpa_printf(MSG_DEBUG, "Invalid key management type (%d).",
206                key_mgmt);
207         return -1;
208     }
209     pos += RSN_SELECTOR_LEN;
210 
211     /* RSN Capabilities */
212     capab = 0;
213 #ifdef CONFIG_IEEE80211W
214     if (sm->pmf_cfg.capable) {
215         capab |= WPA_CAPABILITY_MFPC;
216         if (sm->pmf_cfg.required || key_mgmt == WPA_KEY_MGMT_SAE || key_mgmt == WPA_KEY_MGMT_OWE) {
217             capab |= WPA_CAPABILITY_MFPR;
218         }
219     }
220 #endif /* CONFIG_IEEE80211W */
221 
222     if (sm->spp_sup.capable) {
223         capab |= WPA_CAPABILITY_SPP_CAPABLE;
224     }
225 
226     if (sm->spp_sup.require) {
227         capab |= WPA_CAPABILITY_SPP_REQUIRED;
228     }
229 
230     WPA_PUT_LE16(pos, capab);
231     pos += 2;
232 
233     if (sm->cur_pmksa) {
234         /* PMKID Count (2 octets, little endian) */
235         *pos++ = 1;
236         *pos++ = 0;
237         /* PMKID */
238         os_memcpy(pos, sm->cur_pmksa->pmkid, PMKID_LEN);
239         pos += PMKID_LEN;
240     }
241 
242 #ifdef CONFIG_IEEE80211W
243     if (wpa_cipher_valid_mgmt_group(mgmt_group_cipher)) {
244         if (!sm->cur_pmksa) {
245             /* 0 PMKID Count */
246             WPA_PUT_LE16(pos, 0);
247             pos += 2;
248         }
249 
250         /* Management Group Cipher Suite */
251         RSN_SELECTOR_PUT(pos, wpa_cipher_to_suite(WPA_PROTO_RSN,
252                                                   mgmt_group_cipher));;
253         pos += RSN_SELECTOR_LEN;
254     }
255 #endif /* CONFIG_IEEE80211W */
256 
257     hdr->len = (pos - rsn_ie) - 2;
258 
259     WPA_ASSERT((size_t) (pos - rsn_ie) <= rsn_ie_len);
260 
261     return pos - rsn_ie;
262 }
263 
264 
265 /**
266  * wpa_gen_wpa_ie - Generate WPA/RSN IE based on current security policy
267  * @sm: Pointer to WPA state machine data from wpa_sm_init()
268  * @wpa_ie: Pointer to memory area for the generated WPA/RSN IE
269  * @wpa_ie_len: Maximum length of the generated WPA/RSN IE
270  * Returns: Length of the generated WPA/RSN IE or -1 on failure
271  */
wpa_gen_wpa_ie(struct wpa_sm * sm,u8 * wpa_ie,size_t wpa_ie_len)272 int  wpa_gen_wpa_ie(struct wpa_sm *sm, u8 *wpa_ie, size_t wpa_ie_len)
273 {
274     if (sm->proto == WPA_PROTO_RSN) {
275         return wpa_gen_wpa_ie_rsn(wpa_ie, wpa_ie_len,
276                       sm->pairwise_cipher,
277                       sm->group_cipher,
278                       sm->key_mgmt, sm->mgmt_group_cipher,
279                       sm);
280     } else if (sm->proto == WPA_PROTO_WAPI) {
281         return 0;
282     }
283 
284     return wpa_gen_wpa_ie_wpa(wpa_ie, wpa_ie_len,
285                     sm->pairwise_cipher,
286                     sm->group_cipher,
287                     sm->key_mgmt);
288 }
289 
290 
wpa_gen_rsnxe(struct wpa_sm * sm,u8 * rsnxe,size_t rsnxe_len)291 int wpa_gen_rsnxe(struct wpa_sm *sm, u8 *rsnxe, size_t rsnxe_len)
292 {
293     u8 *pos = rsnxe;
294     u16 capab = 0;
295     size_t flen;
296 
297     if (wpa_key_mgmt_sae(sm->key_mgmt) &&
298         (sm->sae_pwe == SAE_PWE_HASH_TO_ELEMENT ||
299          sm->sae_pwe == SAE_PWE_BOTH)) {
300         capab |= BIT(WLAN_RSNX_CAPAB_SAE_H2E);
301 #ifdef CONFIG_SAE_PK
302         if (sm->sae_pk) {
303             capab |= BIT(WLAN_RSNX_CAPAB_SAE_PK);
304         }
305 #endif /* CONFIG_SAE_PK */
306     }
307 
308     flen = (capab & 0xff00) ? 2 : 1;
309     if (!capab)
310         return 0; /* no supported extended RSN capabilities */
311     if (rsnxe_len < 2 + flen)
312         return -1;
313     capab |= flen - 1; /* bit 0-3 = Field length (n - 1) */
314 
315     *pos++ = WLAN_EID_RSNX;
316     *pos++ = flen;
317     *pos++ = capab & 0x00ff;
318     capab >>= 8;
319     if (capab)
320         *pos++ = capab;
321 
322     return pos - rsnxe;
323 }
324 
325 /**
326  * wpa_parse_generic - Parse EAPOL-Key Key Data Generic IEs
327  * @pos: Pointer to the IE header
328  * @end: Pointer to the end of the Key Data buffer
329  * @ie: Pointer to parsed IE data
330  * Returns: 0 on success, 1 if end mark is found, -1 on failure
331  */
wpa_parse_generic(const u8 * pos,const u8 * end,struct wpa_eapol_ie_parse * ie)332 static int  wpa_parse_generic(const u8 *pos, const u8 *end,
333 			     struct wpa_eapol_ie_parse *ie)
334 {
335 	if (pos[1] == 0)
336 		return 1;
337 
338 	if (pos[1] >= 6 &&
339 	    RSN_SELECTOR_GET(pos + 2) == WPA_OUI_TYPE &&
340 	    pos[2 + WPA_SELECTOR_LEN] == 1 &&
341 	    pos[2 + WPA_SELECTOR_LEN + 1] == 0) {
342 		ie->wpa_ie = pos;
343 		ie->wpa_ie_len = pos[1] + 2;
344 		wpa_hexdump(MSG_DEBUG, "WPA: WPA IE in EAPOL-Key",
345 			    ie->wpa_ie, ie->wpa_ie_len);
346 		return 0;
347 	}
348 
349 	if (pos + 1 + RSN_SELECTOR_LEN < end &&
350 	    pos[1] >= RSN_SELECTOR_LEN + PMKID_LEN &&
351 	    RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_PMKID) {
352 		ie->pmkid = pos + 2 + RSN_SELECTOR_LEN;
353 		wpa_hexdump(MSG_DEBUG, "WPA: PMKID in EAPOL-Key",
354 			    pos, pos[1] + 2);
355 		return 0;
356 	}
357 
358 	if (pos[1] > RSN_SELECTOR_LEN + 2 &&
359 	    RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_GROUPKEY) {
360 		ie->gtk = pos + 2 + RSN_SELECTOR_LEN;
361 		ie->gtk_len = pos[1] - RSN_SELECTOR_LEN;
362 		wpa_hexdump(MSG_DEBUG, "WPA: GTK in EAPOL-Key",
363 				pos, pos[1] + 2);
364 		return 0;
365 	}
366 
367 	if (pos[1] > RSN_SELECTOR_LEN + 2 &&
368 	    RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_MAC_ADDR) {
369 		ie->mac_addr = pos + 2 + RSN_SELECTOR_LEN;
370 		ie->mac_addr_len = pos[1] - RSN_SELECTOR_LEN;
371 		wpa_hexdump(MSG_DEBUG, "WPA: MAC Address in EAPOL-Key",
372 			    pos, pos[1] + 2);
373 		return 0;
374 	}
375 #ifdef CONFIG_IEEE80211W
376 	if (pos[1] > RSN_SELECTOR_LEN + 2 &&
377 	    RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_IGTK) {
378 		ie->igtk = pos + 2 + RSN_SELECTOR_LEN;
379 		ie->igtk_len = pos[1] - RSN_SELECTOR_LEN;
380 		wpa_hexdump(MSG_DEBUG, "WPA: IGTK in EAPOL-Key",
381 				pos, pos[1] + 2);
382 		return 0;
383 	}
384 #endif
385 	if (pos[1] >= RSN_SELECTOR_LEN + 1 &&
386 		RSN_SELECTOR_GET(pos + 2) == WFA_KEY_DATA_TRANSITION_DISABLE) {
387 		ie->transition_disable = pos + 2 + RSN_SELECTOR_LEN;
388 		ie->transition_disable_len = pos[1] - RSN_SELECTOR_LEN;
389 		wpa_hexdump(MSG_DEBUG,
390 				"WPA: Transition Disable KDE in EAPOL-Key",
391 				pos, pos[1] + 2);
392 		return 0;
393 	}
394 	return 0;
395 }
396 
397 
398 /**
399  * wpa_supplicant_parse_ies - Parse EAPOL-Key Key Data IEs
400  * @buf: Pointer to the Key Data buffer
401  * @len: Key Data Length
402  * @ie: Pointer to parsed IE data
403  * Returns: 0 on success, -1 on failure
404  */
wpa_supplicant_parse_ies(const u8 * buf,size_t len,struct wpa_eapol_ie_parse * ie)405 int  wpa_supplicant_parse_ies(const u8 *buf, size_t len,
406 			     struct wpa_eapol_ie_parse *ie)
407 {
408 	const u8 *pos, *end;
409 	int ret = 0;
410 
411 	memset(ie, 0, sizeof(*ie));
412 	for (pos = buf, end = pos + len; pos + 1 < end; pos += 2 + pos[1]) {
413 		if (pos[0] == 0xdd &&
414 		    ((pos == buf + len - 1) || pos[1] == 0)) {
415 			/* Ignore padding */
416 			break;
417 		}
418 		if (pos + 2 + pos[1] > end) {
419 			wpa_printf(MSG_DEBUG, "WPA: EAPOL-Key Key Data "
420 				   "underflow (ie=%d len=%d pos=%d)",
421 				   pos[0], pos[1], (int) (pos - buf));
422 			wpa_hexdump(MSG_DEBUG, "WPA: Key Data",
423 					buf, len);
424 			ret = -1;
425 			break;
426 		}
427 		if (*pos == WLAN_EID_RSN) {
428 			ie->rsn_ie = pos;
429 			ie->rsn_ie_len = pos[1] + 2;
430 			wpa_hexdump(MSG_DEBUG, "WPA: RSN IE in EAPOL-Key",
431 				    ie->rsn_ie, ie->rsn_ie_len);
432 		} else if (*pos == WLAN_EID_RSNX) {
433 			ie->rsnxe = pos;
434 			ie->rsnxe_len = pos[1] + 2;
435 			wpa_hexdump(MSG_DEBUG, "WPA: RSNXE in EAPOL-Key",
436 			ie->rsnxe, ie->rsnxe_len);
437 		} else if (*pos == WLAN_EID_VENDOR_SPECIFIC) {
438 			ret = wpa_parse_generic(pos, end, ie);
439 			if (ret < 0)
440 				break;
441 			if (ret > 0) {
442 				ret = 0;
443 				break;
444 			}
445 		} else {
446 			wpa_hexdump(MSG_DEBUG, "WPA: Unrecognized EAPOL-Key "
447 				    "Key Data IE", pos, 2 + pos[1]);
448 		}
449 	}
450 
451 	return ret;
452 }
453 
454 
455 #endif // ESP_SUPPLICANT
456