2 * wpa_supplicant - WPA/RSN IE and KDE processing
3 * Copyright (c) 2003-2018, Jouni Malinen <j@w1.fi>
5 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
13 #include "pmksa_cache.h"
14 #include "common/ieee802_11_defs.h"
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
26 * Parse the contents of WPA or RSN IE and write the parsed data into data.
28 int wpa_parse_wpa_ie(const u8
*wpa_ie
, size_t wpa_ie_len
,
29 struct wpa_ie_data
*data
)
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
);
37 return wpa_parse_wpa_ie_wpa(wpa_ie
, wpa_ie_len
, data
);
41 static int wpa_gen_wpa_ie_wpa(u8
*wpa_ie
, size_t wpa_ie_len
,
42 int pairwise_cipher
, int group_cipher
,
46 struct wpa_ie_hdr
*hdr
;
49 if (wpa_ie_len
< sizeof(*hdr
) + WPA_SELECTOR_LEN
+
50 2 + WPA_SELECTOR_LEN
+ 2 + WPA_SELECTOR_LEN
)
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);
59 suite
= wpa_cipher_to_suite(WPA_PROTO_WPA
, group_cipher
);
61 wpa_printf(MSG_WARNING
, "Invalid group cipher (%d).",
65 RSN_SELECTOR_PUT(pos
, suite
);
66 pos
+= WPA_SELECTOR_LEN
;
70 suite
= wpa_cipher_to_suite(WPA_PROTO_WPA
, pairwise_cipher
);
72 (!wpa_cipher_valid_pairwise(pairwise_cipher
) &&
73 pairwise_cipher
!= WPA_CIPHER_NONE
)) {
74 wpa_printf(MSG_WARNING
, "Invalid pairwise cipher (%d).",
78 RSN_SELECTOR_PUT(pos
, suite
);
79 pos
+= WPA_SELECTOR_LEN
;
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
);
92 wpa_printf(MSG_WARNING
, "Invalid key management type (%d).",
96 pos
+= WPA_SELECTOR_LEN
;
98 /* WPA Capabilities; use defaults, so no need to include it */
100 hdr
->len
= (pos
- wpa_ie
) - 2;
102 WPA_ASSERT((size_t) (pos
- wpa_ie
) <= wpa_ie_len
);
108 static int wpa_gen_wpa_ie_rsn(u8
*rsn_ie
, size_t rsn_ie_len
,
109 int pairwise_cipher
, int group_cipher
,
110 int key_mgmt
, int mgmt_group_cipher
,
114 struct rsn_ie_hdr
*hdr
;
118 if (rsn_ie_len
< sizeof(*hdr
) + RSN_SELECTOR_LEN
+
119 2 + RSN_SELECTOR_LEN
+ 2 + RSN_SELECTOR_LEN
+ 2 +
120 (sm
->cur_pmksa
? 2 + PMKID_LEN
: 0)) {
121 wpa_printf(MSG_DEBUG
, "RSN: Too short IE buffer (%lu bytes)",
122 (unsigned long) rsn_ie_len
);
126 hdr
= (struct rsn_ie_hdr
*) rsn_ie
;
127 hdr
->elem_id
= WLAN_EID_RSN
;
128 WPA_PUT_LE16(hdr
->version
, RSN_VERSION
);
129 pos
= (u8
*) (hdr
+ 1);
131 suite
= wpa_cipher_to_suite(WPA_PROTO_RSN
, group_cipher
);
133 wpa_printf(MSG_WARNING
, "Invalid group cipher (%d).",
137 RSN_SELECTOR_PUT(pos
, suite
);
138 pos
+= RSN_SELECTOR_LEN
;
142 suite
= wpa_cipher_to_suite(WPA_PROTO_RSN
, pairwise_cipher
);
144 (!wpa_cipher_valid_pairwise(pairwise_cipher
) &&
145 pairwise_cipher
!= WPA_CIPHER_NONE
)) {
146 wpa_printf(MSG_WARNING
, "Invalid pairwise cipher (%d).",
150 RSN_SELECTOR_PUT(pos
, suite
);
151 pos
+= RSN_SELECTOR_LEN
;
155 if (key_mgmt
== WPA_KEY_MGMT_IEEE8021X
) {
156 RSN_SELECTOR_PUT(pos
, RSN_AUTH_KEY_MGMT_UNSPEC_802_1X
);
157 } else if (key_mgmt
== WPA_KEY_MGMT_PSK
) {
158 RSN_SELECTOR_PUT(pos
, RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X
);
159 } else if (key_mgmt
== WPA_KEY_MGMT_CCKM
) {
160 RSN_SELECTOR_PUT(pos
, RSN_AUTH_KEY_MGMT_CCKM
);
161 #ifdef CONFIG_IEEE80211R
162 } else if (key_mgmt
== WPA_KEY_MGMT_FT_IEEE8021X
) {
163 RSN_SELECTOR_PUT(pos
, RSN_AUTH_KEY_MGMT_FT_802_1X
);
165 } else if (key_mgmt
== WPA_KEY_MGMT_FT_IEEE8021X_SHA384
) {
166 RSN_SELECTOR_PUT(pos
, RSN_AUTH_KEY_MGMT_FT_802_1X_SHA384
);
167 #endif /* CONFIG_SHA384 */
168 } else if (key_mgmt
== WPA_KEY_MGMT_FT_PSK
) {
169 RSN_SELECTOR_PUT(pos
, RSN_AUTH_KEY_MGMT_FT_PSK
);
170 #endif /* CONFIG_IEEE80211R */
171 } else if (key_mgmt
== WPA_KEY_MGMT_IEEE8021X_SHA256
) {
172 RSN_SELECTOR_PUT(pos
, RSN_AUTH_KEY_MGMT_802_1X_SHA256
);
173 } else if (key_mgmt
== WPA_KEY_MGMT_PSK_SHA256
) {
174 RSN_SELECTOR_PUT(pos
, RSN_AUTH_KEY_MGMT_PSK_SHA256
);
176 } else if (key_mgmt
== WPA_KEY_MGMT_SAE
) {
177 RSN_SELECTOR_PUT(pos
, RSN_AUTH_KEY_MGMT_SAE
);
178 } else if (key_mgmt
== WPA_KEY_MGMT_FT_SAE
) {
179 RSN_SELECTOR_PUT(pos
, RSN_AUTH_KEY_MGMT_FT_SAE
);
180 #endif /* CONFIG_SAE */
181 } else if (key_mgmt
== WPA_KEY_MGMT_IEEE8021X_SUITE_B_192
) {
182 RSN_SELECTOR_PUT(pos
, RSN_AUTH_KEY_MGMT_802_1X_SUITE_B_192
);
183 } else if (key_mgmt
== WPA_KEY_MGMT_IEEE8021X_SUITE_B
) {
184 RSN_SELECTOR_PUT(pos
, RSN_AUTH_KEY_MGMT_802_1X_SUITE_B
);
186 } else if (key_mgmt
& WPA_KEY_MGMT_FILS_SHA256
) {
187 RSN_SELECTOR_PUT(pos
, RSN_AUTH_KEY_MGMT_FILS_SHA256
);
188 } else if (key_mgmt
& WPA_KEY_MGMT_FILS_SHA384
) {
189 RSN_SELECTOR_PUT(pos
, RSN_AUTH_KEY_MGMT_FILS_SHA384
);
190 #ifdef CONFIG_IEEE80211R
191 } else if (key_mgmt
& WPA_KEY_MGMT_FT_FILS_SHA256
) {
192 RSN_SELECTOR_PUT(pos
, RSN_AUTH_KEY_MGMT_FT_FILS_SHA256
);
193 } else if (key_mgmt
& WPA_KEY_MGMT_FT_FILS_SHA384
) {
194 RSN_SELECTOR_PUT(pos
, RSN_AUTH_KEY_MGMT_FT_FILS_SHA384
);
195 #endif /* CONFIG_IEEE80211R */
196 #endif /* CONFIG_FILS */
198 } else if (key_mgmt
& WPA_KEY_MGMT_OWE
) {
199 RSN_SELECTOR_PUT(pos
, RSN_AUTH_KEY_MGMT_OWE
);
200 #endif /* CONFIG_OWE */
202 } else if (key_mgmt
& WPA_KEY_MGMT_DPP
) {
203 RSN_SELECTOR_PUT(pos
, RSN_AUTH_KEY_MGMT_DPP
);
204 #endif /* CONFIG_DPP */
206 } else if (key_mgmt
& WPA_KEY_MGMT_OSEN
) {
207 RSN_SELECTOR_PUT(pos
, RSN_AUTH_KEY_MGMT_OSEN
);
208 #endif /* CONFIG_HS20 */
210 wpa_printf(MSG_WARNING
, "Invalid key management type (%d).",
214 pos
+= RSN_SELECTOR_LEN
;
216 /* RSN Capabilities */
219 capab
|= WPA_CAPABILITY_MFPC
;
221 capab
|= WPA_CAPABILITY_MFPR
;
223 capab
|= WPA_CAPABILITY_OCVC
;
225 capab
|= WPA_CAPABILITY_EXT_KEY_ID_FOR_UNICAST
;
226 WPA_PUT_LE16(pos
, capab
);
230 /* PMKID Count (2 octets, little endian) */
234 os_memcpy(pos
, sm
->cur_pmksa
->pmkid
, PMKID_LEN
);
238 if (wpa_cipher_valid_mgmt_group(mgmt_group_cipher
)) {
239 if (!sm
->cur_pmksa
) {
241 WPA_PUT_LE16(pos
, 0);
245 /* Management Group Cipher Suite */
246 RSN_SELECTOR_PUT(pos
, wpa_cipher_to_suite(WPA_PROTO_RSN
,
248 pos
+= RSN_SELECTOR_LEN
;
251 hdr
->len
= (pos
- rsn_ie
) - 2;
253 WPA_ASSERT((size_t) (pos
- rsn_ie
) <= rsn_ie_len
);
260 static int wpa_gen_wpa_ie_osen(u8
*wpa_ie
, size_t wpa_ie_len
,
261 int pairwise_cipher
, int group_cipher
,
267 if (wpa_ie_len
< 2 + 4 + RSN_SELECTOR_LEN
+
268 2 + RSN_SELECTOR_LEN
+ 2 + RSN_SELECTOR_LEN
)
272 *pos
++ = WLAN_EID_VENDOR_SPECIFIC
;
273 len
= pos
++; /* to be filled */
274 WPA_PUT_BE24(pos
, OUI_WFA
);
276 *pos
++ = HS20_OSEN_OUI_TYPE
;
278 /* Group Data Cipher Suite */
279 suite
= wpa_cipher_to_suite(WPA_PROTO_RSN
, group_cipher
);
281 wpa_printf(MSG_WARNING
, "Invalid group cipher (%d).",
285 RSN_SELECTOR_PUT(pos
, suite
);
286 pos
+= RSN_SELECTOR_LEN
;
288 /* Pairwise Cipher Suite Count and List */
289 WPA_PUT_LE16(pos
, 1);
291 suite
= wpa_cipher_to_suite(WPA_PROTO_RSN
, pairwise_cipher
);
293 (!wpa_cipher_valid_pairwise(pairwise_cipher
) &&
294 pairwise_cipher
!= WPA_CIPHER_NONE
)) {
295 wpa_printf(MSG_WARNING
, "Invalid pairwise cipher (%d).",
299 RSN_SELECTOR_PUT(pos
, suite
);
300 pos
+= RSN_SELECTOR_LEN
;
302 /* AKM Suite Count and List */
303 WPA_PUT_LE16(pos
, 1);
305 RSN_SELECTOR_PUT(pos
, RSN_AUTH_KEY_MGMT_OSEN
);
306 pos
+= RSN_SELECTOR_LEN
;
308 *len
= pos
- len
- 1;
310 WPA_ASSERT((size_t) (pos
- wpa_ie
) <= wpa_ie_len
);
314 #endif /* CONFIG_HS20 */
318 * wpa_gen_wpa_ie - Generate WPA/RSN IE based on current security policy
319 * @sm: Pointer to WPA state machine data from wpa_sm_init()
320 * @wpa_ie: Pointer to memory area for the generated WPA/RSN IE
321 * @wpa_ie_len: Maximum length of the generated WPA/RSN IE
322 * Returns: Length of the generated WPA/RSN IE or -1 on failure
324 int wpa_gen_wpa_ie(struct wpa_sm
*sm
, u8
*wpa_ie
, size_t wpa_ie_len
)
326 if (sm
->proto
== WPA_PROTO_RSN
)
327 return wpa_gen_wpa_ie_rsn(wpa_ie
, wpa_ie_len
,
330 sm
->key_mgmt
, sm
->mgmt_group_cipher
,
333 else if (sm
->proto
== WPA_PROTO_OSEN
)
334 return wpa_gen_wpa_ie_osen(wpa_ie
, wpa_ie_len
,
338 #endif /* CONFIG_HS20 */
340 return wpa_gen_wpa_ie_wpa(wpa_ie
, wpa_ie_len
,
347 int wpa_gen_rsnxe(struct wpa_sm
*sm
, u8
*rsnxe
, size_t rsnxe_len
)
351 if (!wpa_key_mgmt_sae(sm
->key_mgmt
))
352 return 0; /* SAE not in use */
353 if (sm
->sae_pwe
!= 1 && sm
->sae_pwe
!= 2)
354 return 0; /* no supported extended RSN capabilities */
359 *pos
++ = WLAN_EID_RSNX
;
361 /* bits 0-3 = 0 since only one octet of Extended RSN Capabilities is
363 *pos
++ = BIT(WLAN_RSNX_CAPAB_SAE_H2E
);