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