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