Branch data Line data Source code
1 : : /*
2 : : * WPA/RSN - Shared functions for supplicant and authenticator
3 : : * Copyright (c) 2002-2013, 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 "crypto/md5.h"
13 : : #include "crypto/sha1.h"
14 : : #include "crypto/sha256.h"
15 : : #include "crypto/aes_wrap.h"
16 : : #include "crypto/crypto.h"
17 : : #include "ieee802_11_defs.h"
18 : : #include "defs.h"
19 : : #include "wpa_common.h"
20 : :
21 : :
22 : : /**
23 : : * wpa_eapol_key_mic - Calculate EAPOL-Key MIC
24 : : * @key: EAPOL-Key Key Confirmation Key (KCK)
25 : : * @ver: Key descriptor version (WPA_KEY_INFO_TYPE_*)
26 : : * @buf: Pointer to the beginning of the EAPOL header (version field)
27 : : * @len: Length of the EAPOL frame (from EAPOL header to the end of the frame)
28 : : * @mic: Pointer to the buffer to which the EAPOL-Key MIC is written
29 : : * Returns: 0 on success, -1 on failure
30 : : *
31 : : * Calculate EAPOL-Key MIC for an EAPOL-Key packet. The EAPOL-Key MIC field has
32 : : * to be cleared (all zeroes) when calling this function.
33 : : *
34 : : * Note: 'IEEE Std 802.11i-2004 - 8.5.2 EAPOL-Key frames' has an error in the
35 : : * description of the Key MIC calculation. It includes packet data from the
36 : : * beginning of the EAPOL-Key header, not EAPOL header. This incorrect change
37 : : * happened during final editing of the standard and the correct behavior is
38 : : * defined in the last draft (IEEE 802.11i/D10).
39 : : */
40 : 1063 : int wpa_eapol_key_mic(const u8 *key, int ver, const u8 *buf, size_t len,
41 : : u8 *mic)
42 : : {
43 : : u8 hash[SHA1_MAC_LEN];
44 : :
45 [ + + + - ]: 1063 : switch (ver) {
46 : : #ifndef CONFIG_FIPS
47 : : case WPA_KEY_INFO_TYPE_HMAC_MD5_RC4:
48 : 43 : return hmac_md5(key, 16, buf, len, mic);
49 : : #endif /* CONFIG_FIPS */
50 : : case WPA_KEY_INFO_TYPE_HMAC_SHA1_AES:
51 [ - + ]: 972 : if (hmac_sha1(key, 16, buf, len, hash))
52 : 0 : return -1;
53 : 972 : os_memcpy(mic, hash, MD5_MAC_LEN);
54 : 972 : break;
55 : : #if defined(CONFIG_IEEE80211R) || defined(CONFIG_IEEE80211W)
56 : : case WPA_KEY_INFO_TYPE_AES_128_CMAC:
57 : 48 : return omac1_aes_128(key, buf, len, mic);
58 : : #endif /* CONFIG_IEEE80211R || CONFIG_IEEE80211W */
59 : : default:
60 : 0 : return -1;
61 : : }
62 : :
63 : 1063 : return 0;
64 : : }
65 : :
66 : :
67 : : /**
68 : : * wpa_pmk_to_ptk - Calculate PTK from PMK, addresses, and nonces
69 : : * @pmk: Pairwise master key
70 : : * @pmk_len: Length of PMK
71 : : * @label: Label to use in derivation
72 : : * @addr1: AA or SA
73 : : * @addr2: SA or AA
74 : : * @nonce1: ANonce or SNonce
75 : : * @nonce2: SNonce or ANonce
76 : : * @ptk: Buffer for pairwise transient key
77 : : * @ptk_len: Length of PTK
78 : : * @use_sha256: Whether to use SHA256-based KDF
79 : : *
80 : : * IEEE Std 802.11i-2004 - 8.5.1.2 Pairwise key hierarchy
81 : : * PTK = PRF-X(PMK, "Pairwise key expansion",
82 : : * Min(AA, SA) || Max(AA, SA) ||
83 : : * Min(ANonce, SNonce) || Max(ANonce, SNonce))
84 : : *
85 : : * STK = PRF-X(SMK, "Peer key expansion",
86 : : * Min(MAC_I, MAC_P) || Max(MAC_I, MAC_P) ||
87 : : * Min(INonce, PNonce) || Max(INonce, PNonce))
88 : : */
89 : 368 : void wpa_pmk_to_ptk(const u8 *pmk, size_t pmk_len, const char *label,
90 : : const u8 *addr1, const u8 *addr2,
91 : : const u8 *nonce1, const u8 *nonce2,
92 : : u8 *ptk, size_t ptk_len, int use_sha256)
93 : : {
94 : : u8 data[2 * ETH_ALEN + 2 * WPA_NONCE_LEN];
95 : :
96 [ + + ]: 368 : if (os_memcmp(addr1, addr2, ETH_ALEN) < 0) {
97 : 275 : os_memcpy(data, addr1, ETH_ALEN);
98 : 275 : os_memcpy(data + ETH_ALEN, addr2, ETH_ALEN);
99 : : } else {
100 : 93 : os_memcpy(data, addr2, ETH_ALEN);
101 : 93 : os_memcpy(data + ETH_ALEN, addr1, ETH_ALEN);
102 : : }
103 : :
104 [ + + ]: 368 : if (os_memcmp(nonce1, nonce2, WPA_NONCE_LEN) < 0) {
105 : 192 : os_memcpy(data + 2 * ETH_ALEN, nonce1, WPA_NONCE_LEN);
106 : 192 : os_memcpy(data + 2 * ETH_ALEN + WPA_NONCE_LEN, nonce2,
107 : : WPA_NONCE_LEN);
108 : : } else {
109 : 176 : os_memcpy(data + 2 * ETH_ALEN, nonce2, WPA_NONCE_LEN);
110 : 176 : os_memcpy(data + 2 * ETH_ALEN + WPA_NONCE_LEN, nonce1,
111 : : WPA_NONCE_LEN);
112 : : }
113 : :
114 : : #ifdef CONFIG_IEEE80211W
115 [ + + ]: 368 : if (use_sha256)
116 : 8 : sha256_prf(pmk, pmk_len, label, data, sizeof(data),
117 : : ptk, ptk_len);
118 : : else
119 : : #endif /* CONFIG_IEEE80211W */
120 : 360 : sha1_prf(pmk, pmk_len, label, data, sizeof(data), ptk,
121 : : ptk_len);
122 : :
123 : 368 : wpa_printf(MSG_DEBUG, "WPA: PTK derivation - A1=" MACSTR " A2=" MACSTR,
124 : 4416 : MAC2STR(addr1), MAC2STR(addr2));
125 : 368 : wpa_hexdump(MSG_DEBUG, "WPA: Nonce1", nonce1, WPA_NONCE_LEN);
126 : 368 : wpa_hexdump(MSG_DEBUG, "WPA: Nonce2", nonce2, WPA_NONCE_LEN);
127 : 368 : wpa_hexdump_key(MSG_DEBUG, "WPA: PMK", pmk, pmk_len);
128 : 368 : wpa_hexdump_key(MSG_DEBUG, "WPA: PTK", ptk, ptk_len);
129 : 368 : }
130 : :
131 : :
132 : : #ifdef CONFIG_IEEE80211R
133 : 32 : int wpa_ft_mic(const u8 *kck, const u8 *sta_addr, const u8 *ap_addr,
134 : : u8 transaction_seqnum, const u8 *mdie, size_t mdie_len,
135 : : const u8 *ftie, size_t ftie_len,
136 : : const u8 *rsnie, size_t rsnie_len,
137 : : const u8 *ric, size_t ric_len, u8 *mic)
138 : : {
139 : : u8 *buf, *pos;
140 : : size_t buf_len;
141 : :
142 : 32 : buf_len = 2 * ETH_ALEN + 1 + mdie_len + ftie_len + rsnie_len + ric_len;
143 : 32 : buf = os_malloc(buf_len);
144 [ - + ]: 32 : if (buf == NULL)
145 : 0 : return -1;
146 : :
147 : 32 : pos = buf;
148 : 32 : os_memcpy(pos, sta_addr, ETH_ALEN);
149 : 32 : pos += ETH_ALEN;
150 : 32 : os_memcpy(pos, ap_addr, ETH_ALEN);
151 : 32 : pos += ETH_ALEN;
152 : 32 : *pos++ = transaction_seqnum;
153 [ + - ]: 32 : if (rsnie) {
154 : 32 : os_memcpy(pos, rsnie, rsnie_len);
155 : 32 : pos += rsnie_len;
156 : : }
157 [ + - ]: 32 : if (mdie) {
158 : 32 : os_memcpy(pos, mdie, mdie_len);
159 : 32 : pos += mdie_len;
160 : : }
161 [ + - ]: 32 : if (ftie) {
162 : : struct rsn_ftie *_ftie;
163 : 32 : os_memcpy(pos, ftie, ftie_len);
164 [ - + ]: 32 : if (ftie_len < 2 + sizeof(*_ftie)) {
165 : 0 : os_free(buf);
166 : 0 : return -1;
167 : : }
168 : 32 : _ftie = (struct rsn_ftie *) (pos + 2);
169 : 32 : os_memset(_ftie->mic, 0, sizeof(_ftie->mic));
170 : 32 : pos += ftie_len;
171 : : }
172 [ - + ]: 32 : if (ric) {
173 : 0 : os_memcpy(pos, ric, ric_len);
174 : 0 : pos += ric_len;
175 : : }
176 : :
177 : 32 : wpa_hexdump(MSG_MSGDUMP, "FT: MIC data", buf, pos - buf);
178 [ - + ]: 32 : if (omac1_aes_128(kck, buf, pos - buf, mic)) {
179 : 0 : os_free(buf);
180 : 0 : return -1;
181 : : }
182 : :
183 : 32 : os_free(buf);
184 : :
185 : 32 : return 0;
186 : : }
187 : :
188 : :
189 : 56 : static int wpa_ft_parse_ftie(const u8 *ie, size_t ie_len,
190 : : struct wpa_ft_ies *parse)
191 : : {
192 : : const u8 *end, *pos;
193 : :
194 : 56 : parse->ftie = ie;
195 : 56 : parse->ftie_len = ie_len;
196 : :
197 : 56 : pos = ie + sizeof(struct rsn_ftie);
198 : 56 : end = ie + ie_len;
199 : :
200 [ + + ][ + - ]: 208 : while (pos + 2 <= end && pos + 2 + pos[1] <= end) {
201 [ + + + + : 152 : switch (pos[0]) {
- ]
202 : : case FTIE_SUBELEM_R1KH_ID:
203 [ - + ]: 56 : if (pos[1] != FT_R1KH_ID_LEN) {
204 : 0 : wpa_printf(MSG_DEBUG, "FT: Invalid R1KH-ID "
205 : 0 : "length in FTIE: %d", pos[1]);
206 : 0 : return -1;
207 : : }
208 : 56 : parse->r1kh_id = pos + 2;
209 : 56 : break;
210 : : case FTIE_SUBELEM_GTK:
211 : 32 : parse->gtk = pos + 2;
212 : 32 : parse->gtk_len = pos[1];
213 : 32 : break;
214 : : case FTIE_SUBELEM_R0KH_ID:
215 [ + - ][ - + ]: 56 : if (pos[1] < 1 || pos[1] > FT_R0KH_ID_MAX_LEN) {
216 : 0 : wpa_printf(MSG_DEBUG, "FT: Invalid R0KH-ID "
217 : 0 : "length in FTIE: %d", pos[1]);
218 : 0 : return -1;
219 : : }
220 : 56 : parse->r0kh_id = pos + 2;
221 : 56 : parse->r0kh_id_len = pos[1];
222 : 56 : break;
223 : : #ifdef CONFIG_IEEE80211W
224 : : case FTIE_SUBELEM_IGTK:
225 : 8 : parse->igtk = pos + 2;
226 : 8 : parse->igtk_len = pos[1];
227 : 8 : break;
228 : : #endif /* CONFIG_IEEE80211W */
229 : : }
230 : :
231 : 152 : pos += 2 + pos[1];
232 : : }
233 : :
234 : 56 : return 0;
235 : : }
236 : :
237 : :
238 : 925 : int wpa_ft_parse_ies(const u8 *ies, size_t ies_len,
239 : : struct wpa_ft_ies *parse)
240 : : {
241 : : const u8 *end, *pos;
242 : : struct wpa_ie_data data;
243 : : int ret;
244 : : const struct rsn_ftie *ftie;
245 : 925 : int prot_ie_count = 0;
246 : :
247 : 925 : os_memset(parse, 0, sizeof(*parse));
248 [ + + ]: 925 : if (ies == NULL)
249 : 434 : return 0;
250 : :
251 : 491 : pos = ies;
252 : 491 : end = ies + ies_len;
253 [ + + ][ + - ]: 3601 : while (pos + 2 <= end && pos + 2 + pos[1] <= end) {
254 [ + + + - : 3110 : switch (pos[0]) {
- + ]
255 : : case WLAN_EID_RSN:
256 : 48 : parse->rsn = pos + 2;
257 : 48 : parse->rsn_len = pos[1];
258 : 48 : ret = wpa_parse_wpa_ie_rsn(parse->rsn - 2,
259 : 48 : parse->rsn_len + 2,
260 : : &data);
261 [ - + ]: 48 : if (ret < 0) {
262 : 0 : wpa_printf(MSG_DEBUG, "FT: Failed to parse "
263 : : "RSN IE: %d", ret);
264 : 0 : return -1;
265 : : }
266 [ + - ][ + - ]: 48 : if (data.num_pmkid == 1 && data.pmkid)
267 : 48 : parse->rsn_pmkid = data.pmkid;
268 : 48 : break;
269 : : case WLAN_EID_MOBILITY_DOMAIN:
270 : 76 : parse->mdie = pos + 2;
271 : 76 : parse->mdie_len = pos[1];
272 : 76 : break;
273 : : case WLAN_EID_FAST_BSS_TRANSITION:
274 [ - + ]: 56 : if (pos[1] < sizeof(*ftie))
275 : 0 : return -1;
276 : 56 : ftie = (const struct rsn_ftie *) (pos + 2);
277 : 56 : prot_ie_count = ftie->mic_control[1];
278 [ - + ]: 56 : if (wpa_ft_parse_ftie(pos + 2, pos[1], parse) < 0)
279 : 0 : return -1;
280 : 56 : break;
281 : : case WLAN_EID_TIMEOUT_INTERVAL:
282 : 0 : parse->tie = pos + 2;
283 : 0 : parse->tie_len = pos[1];
284 : 0 : break;
285 : : case WLAN_EID_RIC_DATA:
286 [ # # ]: 0 : if (parse->ric == NULL)
287 : 0 : parse->ric = pos;
288 : 0 : break;
289 : : }
290 : :
291 : 3110 : pos += 2 + pos[1];
292 : : }
293 : :
294 [ + + ]: 491 : if (prot_ie_count == 0)
295 : 459 : return 0; /* no MIC */
296 : :
297 : : /*
298 : : * Check that the protected IE count matches with IEs included in the
299 : : * frame.
300 : : */
301 [ + - ]: 32 : if (parse->rsn)
302 : 32 : prot_ie_count--;
303 [ + - ]: 32 : if (parse->mdie)
304 : 32 : prot_ie_count--;
305 [ + - ]: 32 : if (parse->ftie)
306 : 32 : prot_ie_count--;
307 [ - + ]: 32 : if (prot_ie_count < 0) {
308 : 0 : wpa_printf(MSG_DEBUG, "FT: Some required IEs not included in "
309 : : "the protected IE count");
310 : 0 : return -1;
311 : : }
312 : :
313 [ + - ][ - + ]: 32 : if (prot_ie_count == 0 && parse->ric) {
314 : 0 : wpa_printf(MSG_DEBUG, "FT: RIC IE(s) in the frame, but not "
315 : : "included in protected IE count");
316 : 0 : return -1;
317 : : }
318 : :
319 : : /* Determine the end of the RIC IE(s) */
320 : 32 : pos = parse->ric;
321 [ - + ][ # # ]: 32 : while (pos && pos + 2 <= end && pos + 2 + pos[1] <= end &&
[ # # ][ # # ]
322 : : prot_ie_count) {
323 : 0 : prot_ie_count--;
324 : 0 : pos += 2 + pos[1];
325 : : }
326 : 32 : parse->ric_len = pos - parse->ric;
327 [ - + ]: 32 : if (prot_ie_count) {
328 : 0 : wpa_printf(MSG_DEBUG, "FT: %d protected IEs missing from "
329 : : "frame", (int) prot_ie_count);
330 : 0 : return -1;
331 : : }
332 : :
333 : 925 : return 0;
334 : : }
335 : : #endif /* CONFIG_IEEE80211R */
336 : :
337 : :
338 : 2194 : static int rsn_selector_to_bitfield(const u8 *s)
339 : : {
340 [ - + ]: 2194 : if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_NONE)
341 : 0 : return WPA_CIPHER_NONE;
342 [ - + ]: 2194 : if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_WEP40)
343 : 0 : return WPA_CIPHER_WEP40;
344 [ + + ]: 2194 : if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_TKIP)
345 : 70 : return WPA_CIPHER_TKIP;
346 [ + + ]: 2124 : if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_CCMP)
347 : 1943 : return WPA_CIPHER_CCMP;
348 [ - + ]: 181 : if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_WEP104)
349 : 0 : return WPA_CIPHER_WEP104;
350 : : #ifdef CONFIG_IEEE80211W
351 [ + + ]: 181 : if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_AES_128_CMAC)
352 : 143 : return WPA_CIPHER_AES_128_CMAC;
353 : : #endif /* CONFIG_IEEE80211W */
354 [ - + ]: 38 : if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_GCMP)
355 : 0 : return WPA_CIPHER_GCMP;
356 [ - + ]: 38 : if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_CCMP_256)
357 : 0 : return WPA_CIPHER_CCMP_256;
358 [ - + ]: 38 : if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_GCMP_256)
359 : 0 : return WPA_CIPHER_GCMP_256;
360 [ - + ]: 38 : if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_BIP_GMAC_128)
361 : 0 : return WPA_CIPHER_BIP_GMAC_128;
362 [ - + ]: 38 : if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_BIP_GMAC_256)
363 : 0 : return WPA_CIPHER_BIP_GMAC_256;
364 [ - + ]: 38 : if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_BIP_CMAC_256)
365 : 0 : return WPA_CIPHER_BIP_CMAC_256;
366 : 2194 : return 0;
367 : : }
368 : :
369 : :
370 : 1044 : static int rsn_key_mgmt_to_bitfield(const u8 *s)
371 : : {
372 [ + + ]: 1044 : if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_UNSPEC_802_1X)
373 : 208 : return WPA_KEY_MGMT_IEEE8021X;
374 [ + + ]: 836 : if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X)
375 : 525 : return WPA_KEY_MGMT_PSK;
376 : : #ifdef CONFIG_IEEE80211R
377 [ + + ]: 311 : if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_FT_802_1X)
378 : 20 : return WPA_KEY_MGMT_FT_IEEE8021X;
379 [ + + ]: 291 : if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_FT_PSK)
380 : 92 : return WPA_KEY_MGMT_FT_PSK;
381 : : #endif /* CONFIG_IEEE80211R */
382 : : #ifdef CONFIG_IEEE80211W
383 [ + + ]: 199 : if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_802_1X_SHA256)
384 : 5 : return WPA_KEY_MGMT_IEEE8021X_SHA256;
385 [ + + ]: 194 : if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_PSK_SHA256)
386 : 32 : return WPA_KEY_MGMT_PSK_SHA256;
387 : : #endif /* CONFIG_IEEE80211W */
388 : : #ifdef CONFIG_SAE
389 [ + + ]: 162 : if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_SAE)
390 : 78 : return WPA_KEY_MGMT_SAE;
391 [ + + ]: 84 : if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_FT_SAE)
392 : 46 : return WPA_KEY_MGMT_FT_SAE;
393 : : #endif /* CONFIG_SAE */
394 : 1044 : return 0;
395 : : }
396 : :
397 : :
398 : : /**
399 : : * wpa_parse_wpa_ie_rsn - Parse RSN IE
400 : : * @rsn_ie: Buffer containing RSN IE
401 : : * @rsn_ie_len: RSN IE buffer length (including IE number and length octets)
402 : : * @data: Pointer to structure that will be filled in with parsed data
403 : : * Returns: 0 on success, <0 on failure
404 : : */
405 : 1016 : int wpa_parse_wpa_ie_rsn(const u8 *rsn_ie, size_t rsn_ie_len,
406 : : struct wpa_ie_data *data)
407 : : {
408 : : const struct rsn_ie_hdr *hdr;
409 : : const u8 *pos;
410 : : int left;
411 : : int i, count;
412 : :
413 : 1016 : os_memset(data, 0, sizeof(*data));
414 : 1016 : data->proto = WPA_PROTO_RSN;
415 : 1016 : data->pairwise_cipher = WPA_CIPHER_CCMP;
416 : 1016 : data->group_cipher = WPA_CIPHER_CCMP;
417 : 1016 : data->key_mgmt = WPA_KEY_MGMT_IEEE8021X;
418 : 1016 : data->capabilities = 0;
419 : 1016 : data->pmkid = NULL;
420 : 1016 : data->num_pmkid = 0;
421 : : #ifdef CONFIG_IEEE80211W
422 : 1016 : data->mgmt_group_cipher = WPA_CIPHER_AES_128_CMAC;
423 : : #else /* CONFIG_IEEE80211W */
424 : : data->mgmt_group_cipher = 0;
425 : : #endif /* CONFIG_IEEE80211W */
426 : :
427 [ - + ]: 1016 : if (rsn_ie_len == 0) {
428 : : /* No RSN IE - fail silently */
429 : 0 : return -1;
430 : : }
431 : :
432 [ - + ]: 1016 : if (rsn_ie_len < sizeof(struct rsn_ie_hdr)) {
433 : 0 : wpa_printf(MSG_DEBUG, "%s: ie len too short %lu",
434 : : __func__, (unsigned long) rsn_ie_len);
435 : 0 : return -1;
436 : : }
437 : :
438 : 1016 : hdr = (const struct rsn_ie_hdr *) rsn_ie;
439 : :
440 [ + - ][ + - ]: 1016 : if (hdr->elem_id != WLAN_EID_RSN ||
441 [ - + ]: 1016 : hdr->len != rsn_ie_len - 2 ||
442 : 1016 : WPA_GET_LE16(hdr->version) != RSN_VERSION) {
443 : 0 : wpa_printf(MSG_DEBUG, "%s: malformed ie or unknown version",
444 : : __func__);
445 : 0 : return -2;
446 : : }
447 : :
448 : 1016 : pos = (const u8 *) (hdr + 1);
449 : 1016 : left = rsn_ie_len - sizeof(*hdr);
450 : :
451 [ + - ]: 1016 : if (left >= RSN_SELECTOR_LEN) {
452 : 1016 : data->group_cipher = rsn_selector_to_bitfield(pos);
453 : : #ifdef CONFIG_IEEE80211W
454 [ - + ]: 1016 : if (data->group_cipher == WPA_CIPHER_AES_128_CMAC) {
455 : 0 : wpa_printf(MSG_DEBUG, "%s: AES-128-CMAC used as group "
456 : : "cipher", __func__);
457 : 0 : return -1;
458 : : }
459 : : #endif /* CONFIG_IEEE80211W */
460 : 1016 : pos += RSN_SELECTOR_LEN;
461 : 1016 : left -= RSN_SELECTOR_LEN;
462 [ # # ]: 0 : } else if (left > 0) {
463 : 0 : wpa_printf(MSG_DEBUG, "%s: ie length mismatch, %u too much",
464 : : __func__, left);
465 : 0 : return -3;
466 : : }
467 : :
468 [ + - ]: 1016 : if (left >= 2) {
469 : 1016 : data->pairwise_cipher = 0;
470 : 1016 : count = WPA_GET_LE16(pos);
471 : 1016 : pos += 2;
472 : 1016 : left -= 2;
473 [ + - ][ - + ]: 1016 : if (count == 0 || left < count * RSN_SELECTOR_LEN) {
474 : 0 : wpa_printf(MSG_DEBUG, "%s: ie count botch (pairwise), "
475 : : "count %u left %u", __func__, count, left);
476 : 0 : return -4;
477 : : }
478 [ + + ]: 2051 : for (i = 0; i < count; i++) {
479 : 1035 : data->pairwise_cipher |= rsn_selector_to_bitfield(pos);
480 : 1035 : pos += RSN_SELECTOR_LEN;
481 : 1035 : left -= RSN_SELECTOR_LEN;
482 : : }
483 : : #ifdef CONFIG_IEEE80211W
484 [ - + ]: 1016 : if (data->pairwise_cipher & WPA_CIPHER_AES_128_CMAC) {
485 : 0 : wpa_printf(MSG_DEBUG, "%s: AES-128-CMAC used as "
486 : : "pairwise cipher", __func__);
487 : 0 : return -1;
488 : : }
489 : : #endif /* CONFIG_IEEE80211W */
490 [ # # ]: 0 : } else if (left == 1) {
491 : 0 : wpa_printf(MSG_DEBUG, "%s: ie too short (for key mgmt)",
492 : : __func__);
493 : 0 : return -5;
494 : : }
495 : :
496 [ + + ]: 1016 : if (left >= 2) {
497 : 1014 : data->key_mgmt = 0;
498 : 1014 : count = WPA_GET_LE16(pos);
499 : 1014 : pos += 2;
500 : 1014 : left -= 2;
501 [ + - ][ - + ]: 1014 : if (count == 0 || left < count * RSN_SELECTOR_LEN) {
502 : 0 : wpa_printf(MSG_DEBUG, "%s: ie count botch (key mgmt), "
503 : : "count %u left %u", __func__, count, left);
504 : 0 : return -6;
505 : : }
506 [ + + ]: 2058 : for (i = 0; i < count; i++) {
507 : 1044 : data->key_mgmt |= rsn_key_mgmt_to_bitfield(pos);
508 : 1044 : pos += RSN_SELECTOR_LEN;
509 : 1044 : left -= RSN_SELECTOR_LEN;
510 : : }
511 [ - + ]: 2 : } else if (left == 1) {
512 : 0 : wpa_printf(MSG_DEBUG, "%s: ie too short (for capabilities)",
513 : : __func__);
514 : 0 : return -7;
515 : : }
516 : :
517 [ + + ]: 1016 : if (left >= 2) {
518 : 1014 : data->capabilities = WPA_GET_LE16(pos);
519 : 1014 : pos += 2;
520 : 1014 : left -= 2;
521 : : }
522 : :
523 [ + + ]: 1016 : if (left >= 2) {
524 : 193 : data->num_pmkid = WPA_GET_LE16(pos);
525 : 193 : pos += 2;
526 : 193 : left -= 2;
527 [ - + ]: 193 : if (left < (int) data->num_pmkid * PMKID_LEN) {
528 : 0 : wpa_printf(MSG_DEBUG, "%s: PMKID underflow "
529 : : "(num_pmkid=%lu left=%d)",
530 : : __func__, (unsigned long) data->num_pmkid,
531 : : left);
532 : 0 : data->num_pmkid = 0;
533 : 0 : return -9;
534 : : } else {
535 : 193 : data->pmkid = pos;
536 : 193 : pos += data->num_pmkid * PMKID_LEN;
537 : 193 : left -= data->num_pmkid * PMKID_LEN;
538 : : }
539 : : }
540 : :
541 : : #ifdef CONFIG_IEEE80211W
542 [ + + ]: 1016 : if (left >= 4) {
543 : 143 : data->mgmt_group_cipher = rsn_selector_to_bitfield(pos);
544 [ - + ]: 143 : if (data->mgmt_group_cipher != WPA_CIPHER_AES_128_CMAC) {
545 : 0 : wpa_printf(MSG_DEBUG, "%s: Unsupported management "
546 : : "group cipher 0x%x", __func__,
547 : : data->mgmt_group_cipher);
548 : 0 : return -10;
549 : : }
550 : 143 : pos += RSN_SELECTOR_LEN;
551 : 143 : left -= RSN_SELECTOR_LEN;
552 : : }
553 : : #endif /* CONFIG_IEEE80211W */
554 : :
555 [ - + ]: 1016 : if (left > 0) {
556 : 0 : wpa_printf(MSG_DEBUG, "%s: ie has %u trailing bytes - ignored",
557 : : __func__, left);
558 : : }
559 : :
560 : 1016 : return 0;
561 : : }
562 : :
563 : :
564 : 44 : static int wpa_selector_to_bitfield(const u8 *s)
565 : : {
566 [ - + ]: 44 : if (RSN_SELECTOR_GET(s) == WPA_CIPHER_SUITE_NONE)
567 : 0 : return WPA_CIPHER_NONE;
568 [ - + ]: 44 : if (RSN_SELECTOR_GET(s) == WPA_CIPHER_SUITE_WEP40)
569 : 0 : return WPA_CIPHER_WEP40;
570 [ + + ]: 44 : if (RSN_SELECTOR_GET(s) == WPA_CIPHER_SUITE_TKIP)
571 : 38 : return WPA_CIPHER_TKIP;
572 [ + - ]: 6 : if (RSN_SELECTOR_GET(s) == WPA_CIPHER_SUITE_CCMP)
573 : 6 : return WPA_CIPHER_CCMP;
574 [ # # ]: 0 : if (RSN_SELECTOR_GET(s) == WPA_CIPHER_SUITE_WEP104)
575 : 0 : return WPA_CIPHER_WEP104;
576 : 44 : return 0;
577 : : }
578 : :
579 : :
580 : 19 : static int wpa_key_mgmt_to_bitfield(const u8 *s)
581 : : {
582 [ + + ]: 19 : if (RSN_SELECTOR_GET(s) == WPA_AUTH_KEY_MGMT_UNSPEC_802_1X)
583 : 2 : return WPA_KEY_MGMT_IEEE8021X;
584 [ + - ]: 17 : if (RSN_SELECTOR_GET(s) == WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X)
585 : 17 : return WPA_KEY_MGMT_PSK;
586 [ # # ]: 0 : if (RSN_SELECTOR_GET(s) == WPA_AUTH_KEY_MGMT_NONE)
587 : 0 : return WPA_KEY_MGMT_WPA_NONE;
588 : 19 : return 0;
589 : : }
590 : :
591 : :
592 : 19 : int wpa_parse_wpa_ie_wpa(const u8 *wpa_ie, size_t wpa_ie_len,
593 : : struct wpa_ie_data *data)
594 : : {
595 : : const struct wpa_ie_hdr *hdr;
596 : : const u8 *pos;
597 : : int left;
598 : : int i, count;
599 : :
600 : 19 : os_memset(data, 0, sizeof(*data));
601 : 19 : data->proto = WPA_PROTO_WPA;
602 : 19 : data->pairwise_cipher = WPA_CIPHER_TKIP;
603 : 19 : data->group_cipher = WPA_CIPHER_TKIP;
604 : 19 : data->key_mgmt = WPA_KEY_MGMT_IEEE8021X;
605 : 19 : data->capabilities = 0;
606 : 19 : data->pmkid = NULL;
607 : 19 : data->num_pmkid = 0;
608 : 19 : data->mgmt_group_cipher = 0;
609 : :
610 [ - + ]: 19 : if (wpa_ie_len == 0) {
611 : : /* No WPA IE - fail silently */
612 : 0 : return -1;
613 : : }
614 : :
615 [ - + ]: 19 : if (wpa_ie_len < sizeof(struct wpa_ie_hdr)) {
616 : 0 : wpa_printf(MSG_DEBUG, "%s: ie len too short %lu",
617 : : __func__, (unsigned long) wpa_ie_len);
618 : 0 : return -1;
619 : : }
620 : :
621 : 19 : hdr = (const struct wpa_ie_hdr *) wpa_ie;
622 : :
623 [ + - ][ + - ]: 19 : if (hdr->elem_id != WLAN_EID_VENDOR_SPECIFIC ||
624 [ + - ]: 19 : hdr->len != wpa_ie_len - 2 ||
625 [ - + ]: 38 : RSN_SELECTOR_GET(hdr->oui) != WPA_OUI_TYPE ||
626 : 19 : WPA_GET_LE16(hdr->version) != WPA_VERSION) {
627 : 0 : wpa_printf(MSG_DEBUG, "%s: malformed ie or unknown version",
628 : : __func__);
629 : 0 : return -2;
630 : : }
631 : :
632 : 19 : pos = (const u8 *) (hdr + 1);
633 : 19 : left = wpa_ie_len - sizeof(*hdr);
634 : :
635 [ + - ]: 19 : if (left >= WPA_SELECTOR_LEN) {
636 : 19 : data->group_cipher = wpa_selector_to_bitfield(pos);
637 : 19 : pos += WPA_SELECTOR_LEN;
638 : 19 : left -= WPA_SELECTOR_LEN;
639 [ # # ]: 0 : } else if (left > 0) {
640 : 0 : wpa_printf(MSG_DEBUG, "%s: ie length mismatch, %u too much",
641 : : __func__, left);
642 : 0 : return -3;
643 : : }
644 : :
645 [ + - ]: 19 : if (left >= 2) {
646 : 19 : data->pairwise_cipher = 0;
647 : 19 : count = WPA_GET_LE16(pos);
648 : 19 : pos += 2;
649 : 19 : left -= 2;
650 [ + - ][ - + ]: 19 : if (count == 0 || left < count * WPA_SELECTOR_LEN) {
651 : 0 : wpa_printf(MSG_DEBUG, "%s: ie count botch (pairwise), "
652 : : "count %u left %u", __func__, count, left);
653 : 0 : return -4;
654 : : }
655 [ + + ]: 44 : for (i = 0; i < count; i++) {
656 : 25 : data->pairwise_cipher |= wpa_selector_to_bitfield(pos);
657 : 25 : pos += WPA_SELECTOR_LEN;
658 : 25 : left -= WPA_SELECTOR_LEN;
659 : : }
660 [ # # ]: 0 : } else if (left == 1) {
661 : 0 : wpa_printf(MSG_DEBUG, "%s: ie too short (for key mgmt)",
662 : : __func__);
663 : 0 : return -5;
664 : : }
665 : :
666 [ + - ]: 19 : if (left >= 2) {
667 : 19 : data->key_mgmt = 0;
668 : 19 : count = WPA_GET_LE16(pos);
669 : 19 : pos += 2;
670 : 19 : left -= 2;
671 [ + - ][ - + ]: 19 : if (count == 0 || left < count * WPA_SELECTOR_LEN) {
672 : 0 : wpa_printf(MSG_DEBUG, "%s: ie count botch (key mgmt), "
673 : : "count %u left %u", __func__, count, left);
674 : 0 : return -6;
675 : : }
676 [ + + ]: 38 : for (i = 0; i < count; i++) {
677 : 19 : data->key_mgmt |= wpa_key_mgmt_to_bitfield(pos);
678 : 19 : pos += WPA_SELECTOR_LEN;
679 : 19 : left -= WPA_SELECTOR_LEN;
680 : : }
681 [ # # ]: 0 : } else if (left == 1) {
682 : 0 : wpa_printf(MSG_DEBUG, "%s: ie too short (for capabilities)",
683 : : __func__);
684 : 0 : return -7;
685 : : }
686 : :
687 [ - + ]: 19 : if (left >= 2) {
688 : 0 : data->capabilities = WPA_GET_LE16(pos);
689 : 0 : pos += 2;
690 : 0 : left -= 2;
691 : : }
692 : :
693 [ - + ]: 19 : if (left > 0) {
694 : 0 : wpa_printf(MSG_DEBUG, "%s: ie has %u trailing bytes - ignored",
695 : : __func__, left);
696 : : }
697 : :
698 : 19 : return 0;
699 : : }
700 : :
701 : :
702 : : #ifdef CONFIG_IEEE80211R
703 : :
704 : : /**
705 : : * wpa_derive_pmk_r0 - Derive PMK-R0 and PMKR0Name
706 : : *
707 : : * IEEE Std 802.11r-2008 - 8.5.1.5.3
708 : : */
709 : 8 : void wpa_derive_pmk_r0(const u8 *xxkey, size_t xxkey_len,
710 : : const u8 *ssid, size_t ssid_len,
711 : : const u8 *mdid, const u8 *r0kh_id, size_t r0kh_id_len,
712 : : const u8 *s0kh_id, u8 *pmk_r0, u8 *pmk_r0_name)
713 : : {
714 : : u8 buf[1 + WPA_MAX_SSID_LEN + MOBILITY_DOMAIN_ID_LEN + 1 +
715 : : FT_R0KH_ID_MAX_LEN + ETH_ALEN];
716 : : u8 *pos, r0_key_data[48], hash[32];
717 : : const u8 *addr[2];
718 : : size_t len[2];
719 : :
720 : : /*
721 : : * R0-Key-Data = KDF-384(XXKey, "FT-R0",
722 : : * SSIDlength || SSID || MDID || R0KHlength ||
723 : : * R0KH-ID || S0KH-ID)
724 : : * XXKey is either the second 256 bits of MSK or PSK.
725 : : * PMK-R0 = L(R0-Key-Data, 0, 256)
726 : : * PMK-R0Name-Salt = L(R0-Key-Data, 256, 128)
727 : : */
728 [ + - ][ - + ]: 8 : if (ssid_len > WPA_MAX_SSID_LEN || r0kh_id_len > FT_R0KH_ID_MAX_LEN)
729 : 8 : return;
730 : 8 : pos = buf;
731 : 8 : *pos++ = ssid_len;
732 : 8 : os_memcpy(pos, ssid, ssid_len);
733 : 8 : pos += ssid_len;
734 : 8 : os_memcpy(pos, mdid, MOBILITY_DOMAIN_ID_LEN);
735 : 8 : pos += MOBILITY_DOMAIN_ID_LEN;
736 : 8 : *pos++ = r0kh_id_len;
737 : 8 : os_memcpy(pos, r0kh_id, r0kh_id_len);
738 : 8 : pos += r0kh_id_len;
739 : 8 : os_memcpy(pos, s0kh_id, ETH_ALEN);
740 : 8 : pos += ETH_ALEN;
741 : :
742 : 8 : sha256_prf(xxkey, xxkey_len, "FT-R0", buf, pos - buf,
743 : : r0_key_data, sizeof(r0_key_data));
744 : 8 : os_memcpy(pmk_r0, r0_key_data, PMK_LEN);
745 : :
746 : : /*
747 : : * PMKR0Name = Truncate-128(SHA-256("FT-R0N" || PMK-R0Name-Salt)
748 : : */
749 : 8 : addr[0] = (const u8 *) "FT-R0N";
750 : 8 : len[0] = 6;
751 : 8 : addr[1] = r0_key_data + PMK_LEN;
752 : 8 : len[1] = 16;
753 : :
754 : 8 : sha256_vector(2, addr, len, hash);
755 : 8 : os_memcpy(pmk_r0_name, hash, WPA_PMK_NAME_LEN);
756 : : }
757 : :
758 : :
759 : : /**
760 : : * wpa_derive_pmk_r1_name - Derive PMKR1Name
761 : : *
762 : : * IEEE Std 802.11r-2008 - 8.5.1.5.4
763 : : */
764 : 24 : void wpa_derive_pmk_r1_name(const u8 *pmk_r0_name, const u8 *r1kh_id,
765 : : const u8 *s1kh_id, u8 *pmk_r1_name)
766 : : {
767 : : u8 hash[32];
768 : : const u8 *addr[4];
769 : : size_t len[4];
770 : :
771 : : /*
772 : : * PMKR1Name = Truncate-128(SHA-256("FT-R1N" || PMKR0Name ||
773 : : * R1KH-ID || S1KH-ID))
774 : : */
775 : 24 : addr[0] = (const u8 *) "FT-R1N";
776 : 24 : len[0] = 6;
777 : 24 : addr[1] = pmk_r0_name;
778 : 24 : len[1] = WPA_PMK_NAME_LEN;
779 : 24 : addr[2] = r1kh_id;
780 : 24 : len[2] = FT_R1KH_ID_LEN;
781 : 24 : addr[3] = s1kh_id;
782 : 24 : len[3] = ETH_ALEN;
783 : :
784 : 24 : sha256_vector(4, addr, len, hash);
785 : 24 : os_memcpy(pmk_r1_name, hash, WPA_PMK_NAME_LEN);
786 : 24 : }
787 : :
788 : :
789 : : /**
790 : : * wpa_derive_pmk_r1 - Derive PMK-R1 and PMKR1Name from PMK-R0
791 : : *
792 : : * IEEE Std 802.11r-2008 - 8.5.1.5.4
793 : : */
794 : 24 : void wpa_derive_pmk_r1(const u8 *pmk_r0, const u8 *pmk_r0_name,
795 : : const u8 *r1kh_id, const u8 *s1kh_id,
796 : : u8 *pmk_r1, u8 *pmk_r1_name)
797 : : {
798 : : u8 buf[FT_R1KH_ID_LEN + ETH_ALEN];
799 : : u8 *pos;
800 : :
801 : : /* PMK-R1 = KDF-256(PMK-R0, "FT-R1", R1KH-ID || S1KH-ID) */
802 : 24 : pos = buf;
803 : 24 : os_memcpy(pos, r1kh_id, FT_R1KH_ID_LEN);
804 : 24 : pos += FT_R1KH_ID_LEN;
805 : 24 : os_memcpy(pos, s1kh_id, ETH_ALEN);
806 : 24 : pos += ETH_ALEN;
807 : :
808 : 24 : sha256_prf(pmk_r0, PMK_LEN, "FT-R1", buf, pos - buf, pmk_r1, PMK_LEN);
809 : :
810 : 24 : wpa_derive_pmk_r1_name(pmk_r0_name, r1kh_id, s1kh_id, pmk_r1_name);
811 : 24 : }
812 : :
813 : :
814 : : /**
815 : : * wpa_pmk_r1_to_ptk - Derive PTK and PTKName from PMK-R1
816 : : *
817 : : * IEEE Std 802.11r-2008 - 8.5.1.5.5
818 : : */
819 : 24 : void wpa_pmk_r1_to_ptk(const u8 *pmk_r1, const u8 *snonce, const u8 *anonce,
820 : : const u8 *sta_addr, const u8 *bssid,
821 : : const u8 *pmk_r1_name,
822 : : u8 *ptk, size_t ptk_len, u8 *ptk_name)
823 : : {
824 : : u8 buf[2 * WPA_NONCE_LEN + 2 * ETH_ALEN];
825 : : u8 *pos, hash[32];
826 : : const u8 *addr[6];
827 : : size_t len[6];
828 : :
829 : : /*
830 : : * PTK = KDF-PTKLen(PMK-R1, "FT-PTK", SNonce || ANonce ||
831 : : * BSSID || STA-ADDR)
832 : : */
833 : 24 : pos = buf;
834 : 24 : os_memcpy(pos, snonce, WPA_NONCE_LEN);
835 : 24 : pos += WPA_NONCE_LEN;
836 : 24 : os_memcpy(pos, anonce, WPA_NONCE_LEN);
837 : 24 : pos += WPA_NONCE_LEN;
838 : 24 : os_memcpy(pos, bssid, ETH_ALEN);
839 : 24 : pos += ETH_ALEN;
840 : 24 : os_memcpy(pos, sta_addr, ETH_ALEN);
841 : 24 : pos += ETH_ALEN;
842 : :
843 : 24 : sha256_prf(pmk_r1, PMK_LEN, "FT-PTK", buf, pos - buf, ptk, ptk_len);
844 : :
845 : : /*
846 : : * PTKName = Truncate-128(SHA-256(PMKR1Name || "FT-PTKN" || SNonce ||
847 : : * ANonce || BSSID || STA-ADDR))
848 : : */
849 : 24 : addr[0] = pmk_r1_name;
850 : 24 : len[0] = WPA_PMK_NAME_LEN;
851 : 24 : addr[1] = (const u8 *) "FT-PTKN";
852 : 24 : len[1] = 7;
853 : 24 : addr[2] = snonce;
854 : 24 : len[2] = WPA_NONCE_LEN;
855 : 24 : addr[3] = anonce;
856 : 24 : len[3] = WPA_NONCE_LEN;
857 : 24 : addr[4] = bssid;
858 : 24 : len[4] = ETH_ALEN;
859 : 24 : addr[5] = sta_addr;
860 : 24 : len[5] = ETH_ALEN;
861 : :
862 : 24 : sha256_vector(6, addr, len, hash);
863 : 24 : os_memcpy(ptk_name, hash, WPA_PMK_NAME_LEN);
864 : 24 : }
865 : :
866 : : #endif /* CONFIG_IEEE80211R */
867 : :
868 : :
869 : : /**
870 : : * rsn_pmkid - Calculate PMK identifier
871 : : * @pmk: Pairwise master key
872 : : * @pmk_len: Length of pmk in bytes
873 : : * @aa: Authenticator address
874 : : * @spa: Supplicant address
875 : : * @pmkid: Buffer for PMKID
876 : : * @use_sha256: Whether to use SHA256-based KDF
877 : : *
878 : : * IEEE Std 802.11i-2004 - 8.5.1.2 Pairwise key hierarchy
879 : : * PMKID = HMAC-SHA1-128(PMK, "PMK Name" || AA || SPA)
880 : : */
881 : 82 : void rsn_pmkid(const u8 *pmk, size_t pmk_len, const u8 *aa, const u8 *spa,
882 : : u8 *pmkid, int use_sha256)
883 : : {
884 : 82 : char *title = "PMK Name";
885 : : const u8 *addr[3];
886 : 82 : const size_t len[3] = { 8, ETH_ALEN, ETH_ALEN };
887 : : unsigned char hash[SHA256_MAC_LEN];
888 : :
889 : 82 : addr[0] = (u8 *) title;
890 : 82 : addr[1] = aa;
891 : 82 : addr[2] = spa;
892 : :
893 : : #ifdef CONFIG_IEEE80211W
894 [ + + ]: 82 : if (use_sha256)
895 : 2 : hmac_sha256_vector(pmk, pmk_len, 3, addr, len, hash);
896 : : else
897 : : #endif /* CONFIG_IEEE80211W */
898 : 80 : hmac_sha1_vector(pmk, pmk_len, 3, addr, len, hash);
899 : 82 : os_memcpy(pmkid, hash, PMKID_LEN);
900 : 82 : }
901 : :
902 : :
903 : : /**
904 : : * wpa_cipher_txt - Convert cipher suite to a text string
905 : : * @cipher: Cipher suite (WPA_CIPHER_* enum)
906 : : * Returns: Pointer to a text string of the cipher suite name
907 : : */
908 : 1691 : const char * wpa_cipher_txt(int cipher)
909 : : {
910 [ + + - + : 1691 : switch (cipher) {
+ - - - -
- - ]
911 : : case WPA_CIPHER_NONE:
912 : 136 : return "NONE";
913 : : case WPA_CIPHER_WEP40:
914 : 12 : return "WEP-40";
915 : : case WPA_CIPHER_WEP104:
916 : 0 : return "WEP-104";
917 : : case WPA_CIPHER_TKIP:
918 : 101 : return "TKIP";
919 : : case WPA_CIPHER_CCMP:
920 : 1442 : return "CCMP";
921 : : case WPA_CIPHER_CCMP | WPA_CIPHER_TKIP:
922 : 0 : return "CCMP+TKIP";
923 : : case WPA_CIPHER_GCMP:
924 : 0 : return "GCMP";
925 : : case WPA_CIPHER_GCMP_256:
926 : 0 : return "GCMP-256";
927 : : case WPA_CIPHER_CCMP_256:
928 : 0 : return "CCMP-256";
929 : : case WPA_CIPHER_GTK_NOT_USED:
930 : 0 : return "GTK_NOT_USED";
931 : : default:
932 : 1691 : return "UNKNOWN";
933 : : }
934 : : }
935 : :
936 : :
937 : : /**
938 : : * wpa_key_mgmt_txt - Convert key management suite to a text string
939 : : * @key_mgmt: Key management suite (WPA_KEY_MGMT_* enum)
940 : : * @proto: WPA/WPA2 version (WPA_PROTO_*)
941 : : * Returns: Pointer to a text string of the key management suite name
942 : : */
943 : 287 : const char * wpa_key_mgmt_txt(int key_mgmt, int proto)
944 : : {
945 [ + + + - : 287 : switch (key_mgmt) {
+ + + +
+ ]
946 : : case WPA_KEY_MGMT_IEEE8021X:
947 [ - + ]: 55 : if (proto == (WPA_PROTO_RSN | WPA_PROTO_WPA))
948 : 0 : return "WPA2+WPA/IEEE 802.1X/EAP";
949 : 55 : return proto == WPA_PROTO_RSN ?
950 [ + + ]: 55 : "WPA2/IEEE 802.1X/EAP" : "WPA/IEEE 802.1X/EAP";
951 : : case WPA_KEY_MGMT_PSK:
952 [ - + ]: 108 : if (proto == (WPA_PROTO_RSN | WPA_PROTO_WPA))
953 : 0 : return "WPA2-PSK+WPA-PSK";
954 : 108 : return proto == WPA_PROTO_RSN ?
955 [ + + ]: 108 : "WPA2-PSK" : "WPA-PSK";
956 : : case WPA_KEY_MGMT_NONE:
957 : 74 : return "NONE";
958 : : case WPA_KEY_MGMT_IEEE8021X_NO_WPA:
959 : 0 : return "IEEE 802.1X (no WPA)";
960 : : #ifdef CONFIG_IEEE80211R
961 : : case WPA_KEY_MGMT_FT_IEEE8021X:
962 : 3 : return "FT-EAP";
963 : : case WPA_KEY_MGMT_FT_PSK:
964 : 15 : return "FT-PSK";
965 : : #endif /* CONFIG_IEEE80211R */
966 : : #ifdef CONFIG_IEEE80211W
967 : : case WPA_KEY_MGMT_IEEE8021X_SHA256:
968 : 2 : return "WPA2-EAP-SHA256";
969 : : case WPA_KEY_MGMT_PSK_SHA256:
970 : 12 : return "WPA2-PSK-SHA256";
971 : : #endif /* CONFIG_IEEE80211W */
972 : : default:
973 : 287 : return "UNKNOWN";
974 : : }
975 : : }
976 : :
977 : :
978 : 342 : int wpa_compare_rsn_ie(int ft_initial_assoc,
979 : : const u8 *ie1, size_t ie1len,
980 : : const u8 *ie2, size_t ie2len)
981 : : {
982 [ + - ][ - + ]: 342 : if (ie1 == NULL || ie2 == NULL)
983 : 0 : return -1;
984 : :
985 [ + + ][ + - ]: 342 : if (ie1len == ie2len && os_memcmp(ie1, ie2, ie1len) == 0)
986 : 334 : return 0; /* identical IEs */
987 : :
988 : : #ifdef CONFIG_IEEE80211R
989 [ + - ]: 8 : if (ft_initial_assoc) {
990 : : struct wpa_ie_data ie1d, ie2d;
991 : : /*
992 : : * The PMKID-List in RSN IE is different between Beacon/Probe
993 : : * Response/(Re)Association Request frames and EAPOL-Key
994 : : * messages in FT initial mobility domain association. Allow
995 : : * for this, but verify that other parts of the RSN IEs are
996 : : * identical.
997 : : */
998 [ + - - + ]: 16 : if (wpa_parse_wpa_ie_rsn(ie1, ie1len, &ie1d) < 0 ||
999 : 8 : wpa_parse_wpa_ie_rsn(ie2, ie2len, &ie2d) < 0)
1000 : 0 : return -1;
1001 [ + - ][ + - ]: 8 : if (ie1d.proto == ie2d.proto &&
1002 [ + - ]: 8 : ie1d.pairwise_cipher == ie2d.pairwise_cipher &&
1003 [ + - ]: 8 : ie1d.group_cipher == ie2d.group_cipher &&
1004 [ + - ]: 8 : ie1d.key_mgmt == ie2d.key_mgmt &&
1005 [ + - ]: 8 : ie1d.capabilities == ie2d.capabilities &&
1006 : 8 : ie1d.mgmt_group_cipher == ie2d.mgmt_group_cipher)
1007 : 8 : return 0;
1008 : : }
1009 : : #endif /* CONFIG_IEEE80211R */
1010 : :
1011 : 342 : return -1;
1012 : : }
1013 : :
1014 : :
1015 : : #ifdef CONFIG_IEEE80211R
1016 : 8 : int wpa_insert_pmkid(u8 *ies, size_t ies_len, const u8 *pmkid)
1017 : : {
1018 : : u8 *start, *end, *rpos, *rend;
1019 : 8 : int added = 0;
1020 : :
1021 : 8 : start = ies;
1022 : 8 : end = ies + ies_len;
1023 : :
1024 [ + - ]: 8 : while (start < end) {
1025 [ + - ]: 8 : if (*start == WLAN_EID_RSN)
1026 : 8 : break;
1027 : 0 : start += 2 + start[1];
1028 : : }
1029 [ - + ]: 8 : if (start >= end) {
1030 : 0 : wpa_printf(MSG_ERROR, "FT: Could not find RSN IE in "
1031 : : "IEs data");
1032 : 0 : return -1;
1033 : : }
1034 : 8 : wpa_hexdump(MSG_DEBUG, "FT: RSN IE before modification",
1035 : 8 : start, 2 + start[1]);
1036 : :
1037 : : /* Find start of PMKID-Count */
1038 : 8 : rpos = start + 2;
1039 : 8 : rend = rpos + start[1];
1040 : :
1041 : : /* Skip Version and Group Data Cipher Suite */
1042 : 8 : rpos += 2 + 4;
1043 : : /* Skip Pairwise Cipher Suite Count and List */
1044 : 8 : rpos += 2 + WPA_GET_LE16(rpos) * RSN_SELECTOR_LEN;
1045 : : /* Skip AKM Suite Count and List */
1046 : 8 : rpos += 2 + WPA_GET_LE16(rpos) * RSN_SELECTOR_LEN;
1047 : :
1048 [ - + ]: 8 : if (rpos == rend) {
1049 : : /* Add RSN Capabilities */
1050 : 0 : os_memmove(rpos + 2, rpos, end - rpos);
1051 : 0 : *rpos++ = 0;
1052 : 0 : *rpos++ = 0;
1053 : : } else {
1054 : : /* Skip RSN Capabilities */
1055 : 8 : rpos += 2;
1056 [ - + ]: 8 : if (rpos > rend) {
1057 : 0 : wpa_printf(MSG_ERROR, "FT: Could not parse RSN IE in "
1058 : : "IEs data");
1059 : 0 : return -1;
1060 : : }
1061 : : }
1062 : :
1063 [ + + ]: 8 : if (rpos == rend) {
1064 : : /* No PMKID-Count field included; add it */
1065 : 6 : os_memmove(rpos + 2 + PMKID_LEN, rpos, end - rpos);
1066 : 6 : WPA_PUT_LE16(rpos, 1);
1067 : 6 : rpos += 2;
1068 : 6 : os_memcpy(rpos, pmkid, PMKID_LEN);
1069 : 6 : added += 2 + PMKID_LEN;
1070 : 6 : start[1] += 2 + PMKID_LEN;
1071 : : } else {
1072 : : /* PMKID-Count was included; use it */
1073 [ - + ]: 2 : if (WPA_GET_LE16(rpos) != 0) {
1074 : 0 : wpa_printf(MSG_ERROR, "FT: Unexpected PMKID "
1075 : : "in RSN IE in EAPOL-Key data");
1076 : 0 : return -1;
1077 : : }
1078 : 2 : WPA_PUT_LE16(rpos, 1);
1079 : 2 : rpos += 2;
1080 : 2 : os_memmove(rpos + PMKID_LEN, rpos, end - rpos);
1081 : 2 : os_memcpy(rpos, pmkid, PMKID_LEN);
1082 : 2 : added += PMKID_LEN;
1083 : 2 : start[1] += PMKID_LEN;
1084 : : }
1085 : :
1086 : 8 : wpa_hexdump(MSG_DEBUG, "FT: RSN IE after modification "
1087 : 8 : "(PMKID inserted)", start, 2 + start[1]);
1088 : :
1089 : 8 : return added;
1090 : : }
1091 : : #endif /* CONFIG_IEEE80211R */
1092 : :
1093 : :
1094 : 1120 : int wpa_cipher_key_len(int cipher)
1095 : : {
1096 [ - + + - : 1120 : switch (cipher) {
- - ]
1097 : : case WPA_CIPHER_CCMP_256:
1098 : : case WPA_CIPHER_GCMP_256:
1099 : 0 : return 32;
1100 : : case WPA_CIPHER_CCMP:
1101 : : case WPA_CIPHER_GCMP:
1102 : 1081 : return 16;
1103 : : case WPA_CIPHER_TKIP:
1104 : 39 : return 32;
1105 : : case WPA_CIPHER_WEP104:
1106 : 0 : return 13;
1107 : : case WPA_CIPHER_WEP40:
1108 : 0 : return 5;
1109 : : }
1110 : :
1111 : 1120 : return 0;
1112 : : }
1113 : :
1114 : :
1115 : 537 : int wpa_cipher_rsc_len(int cipher)
1116 : : {
1117 [ + - - ]: 537 : switch (cipher) {
1118 : : case WPA_CIPHER_CCMP_256:
1119 : : case WPA_CIPHER_GCMP_256:
1120 : : case WPA_CIPHER_CCMP:
1121 : : case WPA_CIPHER_GCMP:
1122 : : case WPA_CIPHER_TKIP:
1123 : 537 : return 6;
1124 : : case WPA_CIPHER_WEP104:
1125 : : case WPA_CIPHER_WEP40:
1126 : 0 : return 0;
1127 : : }
1128 : :
1129 : 537 : return 0;
1130 : : }
1131 : :
1132 : :
1133 : 758 : int wpa_cipher_to_alg(int cipher)
1134 : : {
1135 [ - - + - : 758 : switch (cipher) {
+ - - ]
1136 : : case WPA_CIPHER_CCMP_256:
1137 : 0 : return WPA_ALG_CCMP_256;
1138 : : case WPA_CIPHER_GCMP_256:
1139 : 0 : return WPA_ALG_GCMP_256;
1140 : : case WPA_CIPHER_CCMP:
1141 : 728 : return WPA_ALG_CCMP;
1142 : : case WPA_CIPHER_GCMP:
1143 : 0 : return WPA_ALG_GCMP;
1144 : : case WPA_CIPHER_TKIP:
1145 : 30 : return WPA_ALG_TKIP;
1146 : : case WPA_CIPHER_WEP104:
1147 : : case WPA_CIPHER_WEP40:
1148 : 0 : return WPA_ALG_WEP;
1149 : : }
1150 : 758 : return WPA_ALG_NONE;
1151 : : }
1152 : :
1153 : :
1154 : 661 : int wpa_cipher_valid_pairwise(int cipher)
1155 : : {
1156 [ + - ][ + - ]: 1322 : return cipher == WPA_CIPHER_CCMP_256 ||
1157 [ + + ]: 661 : cipher == WPA_CIPHER_GCMP_256 ||
1158 [ + - ]: 20 : cipher == WPA_CIPHER_CCMP ||
1159 [ + - ]: 20 : cipher == WPA_CIPHER_GCMP ||
1160 : : cipher == WPA_CIPHER_TKIP;
1161 : : }
1162 : :
1163 : :
1164 : 950 : u32 wpa_cipher_to_suite(int proto, int cipher)
1165 : : {
1166 [ - + ]: 950 : if (cipher & WPA_CIPHER_CCMP_256)
1167 : 0 : return RSN_CIPHER_SUITE_CCMP_256;
1168 [ - + ]: 950 : if (cipher & WPA_CIPHER_GCMP_256)
1169 : 0 : return RSN_CIPHER_SUITE_GCMP_256;
1170 [ + + ]: 950 : if (cipher & WPA_CIPHER_CCMP)
1171 : 906 : return (proto == WPA_PROTO_RSN ?
1172 [ + - ]: 906 : RSN_CIPHER_SUITE_CCMP : WPA_CIPHER_SUITE_CCMP);
1173 [ - + ]: 44 : if (cipher & WPA_CIPHER_GCMP)
1174 : 0 : return RSN_CIPHER_SUITE_GCMP;
1175 [ + - ]: 44 : if (cipher & WPA_CIPHER_TKIP)
1176 : 44 : return (proto == WPA_PROTO_RSN ?
1177 [ + + ]: 44 : RSN_CIPHER_SUITE_TKIP : WPA_CIPHER_SUITE_TKIP);
1178 [ # # ]: 0 : if (cipher & WPA_CIPHER_WEP104)
1179 : 0 : return (proto == WPA_PROTO_RSN ?
1180 [ # # ]: 0 : RSN_CIPHER_SUITE_WEP104 : WPA_CIPHER_SUITE_WEP104);
1181 [ # # ]: 0 : if (cipher & WPA_CIPHER_WEP40)
1182 : 0 : return (proto == WPA_PROTO_RSN ?
1183 [ # # ]: 0 : RSN_CIPHER_SUITE_WEP40 : WPA_CIPHER_SUITE_WEP40);
1184 [ # # ]: 0 : if (cipher & WPA_CIPHER_NONE)
1185 : 0 : return (proto == WPA_PROTO_RSN ?
1186 [ # # ]: 0 : RSN_CIPHER_SUITE_NONE : WPA_CIPHER_SUITE_NONE);
1187 [ # # ]: 0 : if (cipher & WPA_CIPHER_GTK_NOT_USED)
1188 : 0 : return RSN_CIPHER_SUITE_NO_GROUP_ADDRESSED;
1189 : 950 : return 0;
1190 : : }
1191 : :
1192 : :
1193 : 62 : int rsn_cipher_put_suites(u8 *pos, int ciphers)
1194 : : {
1195 : 62 : int num_suites = 0;
1196 : :
1197 [ - + ]: 62 : if (ciphers & WPA_CIPHER_CCMP_256) {
1198 : 0 : RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP_256);
1199 : 0 : pos += RSN_SELECTOR_LEN;
1200 : 0 : num_suites++;
1201 : : }
1202 [ - + ]: 62 : if (ciphers & WPA_CIPHER_GCMP_256) {
1203 : 0 : RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_GCMP_256);
1204 : 0 : pos += RSN_SELECTOR_LEN;
1205 : 0 : num_suites++;
1206 : : }
1207 [ + - ]: 62 : if (ciphers & WPA_CIPHER_CCMP) {
1208 : 62 : RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP);
1209 : 62 : pos += RSN_SELECTOR_LEN;
1210 : 62 : num_suites++;
1211 : : }
1212 [ - + ]: 62 : if (ciphers & WPA_CIPHER_GCMP) {
1213 : 0 : RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_GCMP);
1214 : 0 : pos += RSN_SELECTOR_LEN;
1215 : 0 : num_suites++;
1216 : : }
1217 [ + + ]: 62 : if (ciphers & WPA_CIPHER_TKIP) {
1218 : 1 : RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_TKIP);
1219 : 1 : pos += RSN_SELECTOR_LEN;
1220 : 1 : num_suites++;
1221 : : }
1222 [ - + ]: 62 : if (ciphers & WPA_CIPHER_NONE) {
1223 : 0 : RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_NONE);
1224 : 0 : pos += RSN_SELECTOR_LEN;
1225 : 0 : num_suites++;
1226 : : }
1227 : :
1228 : 62 : return num_suites;
1229 : : }
1230 : :
1231 : :
1232 : 0 : int wpa_cipher_put_suites(u8 *pos, int ciphers)
1233 : : {
1234 : 0 : int num_suites = 0;
1235 : :
1236 [ # # ]: 0 : if (ciphers & WPA_CIPHER_CCMP) {
1237 : 0 : RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_CCMP);
1238 : 0 : pos += WPA_SELECTOR_LEN;
1239 : 0 : num_suites++;
1240 : : }
1241 [ # # ]: 0 : if (ciphers & WPA_CIPHER_TKIP) {
1242 : 0 : RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_TKIP);
1243 : 0 : pos += WPA_SELECTOR_LEN;
1244 : 0 : num_suites++;
1245 : : }
1246 [ # # ]: 0 : if (ciphers & WPA_CIPHER_NONE) {
1247 : 0 : RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_NONE);
1248 : 0 : pos += WPA_SELECTOR_LEN;
1249 : 0 : num_suites++;
1250 : : }
1251 : :
1252 : 0 : return num_suites;
1253 : : }
1254 : :
1255 : :
1256 : 417 : int wpa_pick_pairwise_cipher(int ciphers, int none_allowed)
1257 : : {
1258 [ - + ]: 417 : if (ciphers & WPA_CIPHER_CCMP_256)
1259 : 0 : return WPA_CIPHER_CCMP_256;
1260 [ - + ]: 417 : if (ciphers & WPA_CIPHER_GCMP_256)
1261 : 0 : return WPA_CIPHER_GCMP_256;
1262 [ + + ]: 417 : if (ciphers & WPA_CIPHER_CCMP)
1263 : 406 : return WPA_CIPHER_CCMP;
1264 [ - + ]: 11 : if (ciphers & WPA_CIPHER_GCMP)
1265 : 0 : return WPA_CIPHER_GCMP;
1266 [ + - ]: 11 : if (ciphers & WPA_CIPHER_TKIP)
1267 : 11 : return WPA_CIPHER_TKIP;
1268 [ # # ][ # # ]: 0 : if (none_allowed && (ciphers & WPA_CIPHER_NONE))
1269 : 0 : return WPA_CIPHER_NONE;
1270 : 417 : return -1;
1271 : : }
1272 : :
1273 : :
1274 : 281 : int wpa_pick_group_cipher(int ciphers)
1275 : : {
1276 [ - + ]: 281 : if (ciphers & WPA_CIPHER_CCMP_256)
1277 : 0 : return WPA_CIPHER_CCMP_256;
1278 [ - + ]: 281 : if (ciphers & WPA_CIPHER_GCMP_256)
1279 : 0 : return WPA_CIPHER_GCMP_256;
1280 [ + + ]: 281 : if (ciphers & WPA_CIPHER_CCMP)
1281 : 258 : return WPA_CIPHER_CCMP;
1282 [ - + ]: 23 : if (ciphers & WPA_CIPHER_GCMP)
1283 : 0 : return WPA_CIPHER_GCMP;
1284 [ - + ]: 23 : if (ciphers & WPA_CIPHER_GTK_NOT_USED)
1285 : 0 : return WPA_CIPHER_GTK_NOT_USED;
1286 [ + - ]: 23 : if (ciphers & WPA_CIPHER_TKIP)
1287 : 23 : return WPA_CIPHER_TKIP;
1288 [ # # ]: 0 : if (ciphers & WPA_CIPHER_WEP104)
1289 : 0 : return WPA_CIPHER_WEP104;
1290 [ # # ]: 0 : if (ciphers & WPA_CIPHER_WEP40)
1291 : 0 : return WPA_CIPHER_WEP40;
1292 : 281 : return -1;
1293 : : }
1294 : :
1295 : :
1296 : 54 : int wpa_parse_cipher(const char *value)
1297 : : {
1298 : 54 : int val = 0, last;
1299 : : char *start, *end, *buf;
1300 : :
1301 : 54 : buf = os_strdup(value);
1302 [ - + ]: 54 : if (buf == NULL)
1303 : 0 : return -1;
1304 : 54 : start = buf;
1305 : :
1306 [ + - ]: 54 : while (*start != '\0') {
1307 [ - + ][ - + ]: 54 : while (*start == ' ' || *start == '\t')
1308 : 0 : start++;
1309 [ - + ]: 54 : if (*start == '\0')
1310 : 0 : break;
1311 : 54 : end = start;
1312 [ + - ][ + - ]: 270 : while (*end != ' ' && *end != '\t' && *end != '\0')
[ + + ]
1313 : 216 : end++;
1314 : 54 : last = *end == '\0';
1315 : 54 : *end = '\0';
1316 [ - + ]: 54 : if (os_strcmp(start, "CCMP-256") == 0)
1317 : 0 : val |= WPA_CIPHER_CCMP_256;
1318 [ - + ]: 54 : else if (os_strcmp(start, "GCMP-256") == 0)
1319 : 0 : val |= WPA_CIPHER_GCMP_256;
1320 [ + + ]: 54 : else if (os_strcmp(start, "CCMP") == 0)
1321 : 43 : val |= WPA_CIPHER_CCMP;
1322 [ - + ]: 11 : else if (os_strcmp(start, "GCMP") == 0)
1323 : 0 : val |= WPA_CIPHER_GCMP;
1324 [ + - ]: 11 : else if (os_strcmp(start, "TKIP") == 0)
1325 : 11 : val |= WPA_CIPHER_TKIP;
1326 [ # # ]: 0 : else if (os_strcmp(start, "WEP104") == 0)
1327 : 0 : val |= WPA_CIPHER_WEP104;
1328 [ # # ]: 0 : else if (os_strcmp(start, "WEP40") == 0)
1329 : 0 : val |= WPA_CIPHER_WEP40;
1330 [ # # ]: 0 : else if (os_strcmp(start, "NONE") == 0)
1331 : 0 : val |= WPA_CIPHER_NONE;
1332 [ # # ]: 0 : else if (os_strcmp(start, "GTK_NOT_USED") == 0)
1333 : 0 : val |= WPA_CIPHER_GTK_NOT_USED;
1334 : : else {
1335 : 0 : os_free(buf);
1336 : 0 : return -1;
1337 : : }
1338 : :
1339 [ + - ]: 54 : if (last)
1340 : 54 : break;
1341 : 0 : start = end + 1;
1342 : : }
1343 : 54 : os_free(buf);
1344 : :
1345 : 54 : return val;
1346 : : }
1347 : :
1348 : :
1349 : 25 : int wpa_write_ciphers(char *start, char *end, int ciphers, const char *delim)
1350 : : {
1351 : 25 : char *pos = start;
1352 : : int ret;
1353 : :
1354 [ - + ]: 25 : if (ciphers & WPA_CIPHER_CCMP_256) {
1355 [ # # ]: 0 : ret = os_snprintf(pos, end - pos, "%sCCMP-256",
1356 : : pos == start ? "" : delim);
1357 [ # # ][ # # ]: 0 : if (ret < 0 || ret >= end - pos)
1358 : 0 : return -1;
1359 : 0 : pos += ret;
1360 : : }
1361 [ - + ]: 25 : if (ciphers & WPA_CIPHER_GCMP_256) {
1362 [ # # ]: 0 : ret = os_snprintf(pos, end - pos, "%sGCMP-256",
1363 : : pos == start ? "" : delim);
1364 [ # # ][ # # ]: 0 : if (ret < 0 || ret >= end - pos)
1365 : 0 : return -1;
1366 : 0 : pos += ret;
1367 : : }
1368 [ + + ]: 25 : if (ciphers & WPA_CIPHER_CCMP) {
1369 [ - + ]: 24 : ret = os_snprintf(pos, end - pos, "%sCCMP",
1370 : : pos == start ? "" : delim);
1371 [ + - ][ - + ]: 24 : if (ret < 0 || ret >= end - pos)
1372 : 0 : return -1;
1373 : 24 : pos += ret;
1374 : : }
1375 [ - + ]: 25 : if (ciphers & WPA_CIPHER_GCMP) {
1376 [ # # ]: 0 : ret = os_snprintf(pos, end - pos, "%sGCMP",
1377 : : pos == start ? "" : delim);
1378 [ # # ][ # # ]: 0 : if (ret < 0 || ret >= end - pos)
1379 : 0 : return -1;
1380 : 0 : pos += ret;
1381 : : }
1382 [ + + ]: 25 : if (ciphers & WPA_CIPHER_TKIP) {
1383 [ + + ]: 9 : ret = os_snprintf(pos, end - pos, "%sTKIP",
1384 : : pos == start ? "" : delim);
1385 [ + - ][ - + ]: 9 : if (ret < 0 || ret >= end - pos)
1386 : 0 : return -1;
1387 : 9 : pos += ret;
1388 : : }
1389 [ - + ]: 25 : if (ciphers & WPA_CIPHER_WEP104) {
1390 [ # # ]: 0 : ret = os_snprintf(pos, end - pos, "%sWEP104",
1391 : : pos == start ? "" : delim);
1392 [ # # ][ # # ]: 0 : if (ret < 0 || ret >= end - pos)
1393 : 0 : return -1;
1394 : 0 : pos += ret;
1395 : : }
1396 [ - + ]: 25 : if (ciphers & WPA_CIPHER_WEP40) {
1397 [ # # ]: 0 : ret = os_snprintf(pos, end - pos, "%sWEP40",
1398 : : pos == start ? "" : delim);
1399 [ # # ][ # # ]: 0 : if (ret < 0 || ret >= end - pos)
1400 : 0 : return -1;
1401 : 0 : pos += ret;
1402 : : }
1403 [ - + ]: 25 : if (ciphers & WPA_CIPHER_NONE) {
1404 [ # # ]: 0 : ret = os_snprintf(pos, end - pos, "%sNONE",
1405 : : pos == start ? "" : delim);
1406 [ # # ][ # # ]: 0 : if (ret < 0 || ret >= end - pos)
1407 : 0 : return -1;
1408 : 0 : pos += ret;
1409 : : }
1410 : :
1411 : 25 : return pos - start;
1412 : : }
1413 : :
1414 : :
1415 : 59 : int wpa_select_ap_group_cipher(int wpa, int wpa_pairwise, int rsn_pairwise)
1416 : : {
1417 : 59 : int pairwise = 0;
1418 : :
1419 : : /* Select group cipher based on the enabled pairwise cipher suites */
1420 [ - + ]: 59 : if (wpa & 1)
1421 : 0 : pairwise |= wpa_pairwise;
1422 [ + + ]: 59 : if (wpa & 2)
1423 : 58 : pairwise |= rsn_pairwise;
1424 : :
1425 [ - + ]: 59 : if (pairwise & WPA_CIPHER_TKIP)
1426 : 0 : return WPA_CIPHER_TKIP;
1427 [ - + ]: 59 : if ((pairwise & (WPA_CIPHER_CCMP | WPA_CIPHER_GCMP)) == WPA_CIPHER_GCMP)
1428 : 0 : return WPA_CIPHER_GCMP;
1429 [ - + ]: 59 : if ((pairwise & (WPA_CIPHER_GCMP_256 | WPA_CIPHER_CCMP |
1430 : : WPA_CIPHER_GCMP)) == WPA_CIPHER_GCMP_256)
1431 : 0 : return WPA_CIPHER_GCMP_256;
1432 [ - + ]: 59 : if ((pairwise & (WPA_CIPHER_CCMP_256 | WPA_CIPHER_CCMP |
1433 : : WPA_CIPHER_GCMP)) == WPA_CIPHER_CCMP_256)
1434 : 0 : return WPA_CIPHER_CCMP_256;
1435 : 59 : return WPA_CIPHER_CCMP;
1436 : : }
|