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