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 : 1416 : 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 [ + + + - ]: 1416 : switch (ver) {
46 : : #ifndef CONFIG_FIPS
47 : : case WPA_KEY_INFO_TYPE_HMAC_MD5_RC4:
48 : 66 : return hmac_md5(key, 16, buf, len, mic);
49 : : #endif /* CONFIG_FIPS */
50 : : case WPA_KEY_INFO_TYPE_HMAC_SHA1_AES:
51 [ - + ]: 1254 : if (hmac_sha1(key, 16, buf, len, hash))
52 : 0 : return -1;
53 : 1254 : os_memcpy(mic, hash, MD5_MAC_LEN);
54 : 1254 : 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 : : default:
60 : 0 : return -1;
61 : : }
62 : :
63 : 1416 : 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 : 470 : 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 [ + + ]: 470 : if (os_memcmp(addr1, addr2, ETH_ALEN) < 0) {
97 : 235 : os_memcpy(data, addr1, ETH_ALEN);
98 : 235 : os_memcpy(data + ETH_ALEN, addr2, ETH_ALEN);
99 : : } else {
100 : 235 : os_memcpy(data, addr2, ETH_ALEN);
101 : 235 : os_memcpy(data + ETH_ALEN, addr1, ETH_ALEN);
102 : : }
103 : :
104 [ + + ]: 470 : if (os_memcmp(nonce1, nonce2, WPA_NONCE_LEN) < 0) {
105 : 235 : os_memcpy(data + 2 * ETH_ALEN, nonce1, WPA_NONCE_LEN);
106 : 235 : os_memcpy(data + 2 * ETH_ALEN + WPA_NONCE_LEN, nonce2,
107 : : WPA_NONCE_LEN);
108 : : } else {
109 : 235 : os_memcpy(data + 2 * ETH_ALEN, nonce2, WPA_NONCE_LEN);
110 : 235 : os_memcpy(data + 2 * ETH_ALEN + WPA_NONCE_LEN, nonce1,
111 : : WPA_NONCE_LEN);
112 : : }
113 : :
114 : : #ifdef CONFIG_IEEE80211W
115 [ + + ]: 470 : if (use_sha256)
116 : 16 : sha256_prf(pmk, pmk_len, label, data, sizeof(data),
117 : : ptk, ptk_len);
118 : : else
119 : : #endif /* CONFIG_IEEE80211W */
120 : 454 : sha1_prf(pmk, pmk_len, label, data, sizeof(data), ptk,
121 : : ptk_len);
122 : :
123 : 470 : wpa_printf(MSG_DEBUG, "WPA: PTK derivation - A1=" MACSTR " A2=" MACSTR,
124 : 5640 : MAC2STR(addr1), MAC2STR(addr2));
125 : 470 : wpa_hexdump(MSG_DEBUG, "WPA: Nonce1", nonce1, WPA_NONCE_LEN);
126 : 470 : wpa_hexdump(MSG_DEBUG, "WPA: Nonce2", nonce2, WPA_NONCE_LEN);
127 : 470 : wpa_hexdump_key(MSG_DEBUG, "WPA: PMK", pmk, pmk_len);
128 : 470 : wpa_hexdump_key(MSG_DEBUG, "WPA: PTK", ptk, ptk_len);
129 : 470 : }
130 : :
131 : :
132 : : #ifdef CONFIG_IEEE80211R
133 : 56 : 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 : 56 : buf_len = 2 * ETH_ALEN + 1 + mdie_len + ftie_len + rsnie_len + ric_len;
143 : 56 : buf = os_malloc(buf_len);
144 [ - + ]: 56 : if (buf == NULL)
145 : 0 : return -1;
146 : :
147 : 56 : pos = buf;
148 : 56 : os_memcpy(pos, sta_addr, ETH_ALEN);
149 : 56 : pos += ETH_ALEN;
150 : 56 : os_memcpy(pos, ap_addr, ETH_ALEN);
151 : 56 : pos += ETH_ALEN;
152 : 56 : *pos++ = transaction_seqnum;
153 [ + - ]: 56 : if (rsnie) {
154 : 56 : os_memcpy(pos, rsnie, rsnie_len);
155 : 56 : pos += rsnie_len;
156 : : }
157 [ + - ]: 56 : if (mdie) {
158 : 56 : os_memcpy(pos, mdie, mdie_len);
159 : 56 : pos += mdie_len;
160 : : }
161 [ + - ]: 56 : if (ftie) {
162 : : struct rsn_ftie *_ftie;
163 : 56 : os_memcpy(pos, ftie, ftie_len);
164 [ - + ]: 56 : if (ftie_len < 2 + sizeof(*_ftie)) {
165 : 0 : os_free(buf);
166 : 0 : return -1;
167 : : }
168 : 56 : _ftie = (struct rsn_ftie *) (pos + 2);
169 : 56 : os_memset(_ftie->mic, 0, sizeof(_ftie->mic));
170 : 56 : pos += ftie_len;
171 : : }
172 [ - + ]: 56 : if (ric) {
173 : 0 : os_memcpy(pos, ric, ric_len);
174 : 0 : pos += ric_len;
175 : : }
176 : :
177 : 56 : wpa_hexdump(MSG_MSGDUMP, "FT: MIC data", buf, pos - buf);
178 [ - + ]: 56 : if (omac1_aes_128(kck, buf, pos - buf, mic)) {
179 : 0 : os_free(buf);
180 : 0 : return -1;
181 : : }
182 : :
183 : 56 : os_free(buf);
184 : :
185 : 56 : return 0;
186 : : }
187 : :
188 : :
189 : 92 : 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 : 92 : parse->ftie = ie;
195 : 92 : parse->ftie_len = ie_len;
196 : :
197 : 92 : pos = ie + sizeof(struct rsn_ftie);
198 : 92 : end = ie + ie_len;
199 : :
200 [ + + ][ + - ]: 294 : while (pos + 2 <= end && pos + 2 + pos[1] <= end) {
201 [ + + + + : 202 : switch (pos[0]) {
- ]
202 : : case FTIE_SUBELEM_R1KH_ID:
203 [ - + ]: 78 : 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 : 78 : parse->r1kh_id = pos + 2;
209 : 78 : break;
210 : : case FTIE_SUBELEM_GTK:
211 : 28 : parse->gtk = pos + 2;
212 : 28 : parse->gtk_len = pos[1];
213 : 28 : break;
214 : : case FTIE_SUBELEM_R0KH_ID:
215 [ + - ][ - + ]: 92 : 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 : 92 : parse->r0kh_id = pos + 2;
221 : 92 : parse->r0kh_id_len = pos[1];
222 : 92 : break;
223 : : #ifdef CONFIG_IEEE80211W
224 : : case FTIE_SUBELEM_IGTK:
225 : 4 : parse->igtk = pos + 2;
226 : 4 : parse->igtk_len = pos[1];
227 : 4 : break;
228 : : #endif /* CONFIG_IEEE80211W */
229 : : }
230 : :
231 : 202 : pos += 2 + pos[1];
232 : : }
233 : :
234 : 92 : return 0;
235 : : }
236 : :
237 : :
238 : 807 : 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 : 807 : int prot_ie_count = 0;
246 : :
247 : 807 : os_memset(parse, 0, sizeof(*parse));
248 [ + + ]: 807 : if (ies == NULL)
249 : 353 : return 0;
250 : :
251 : 454 : pos = ies;
252 : 454 : end = ies + ies_len;
253 [ + + ][ + - ]: 3327 : while (pos + 2 <= end && pos + 2 + pos[1] <= end) {
254 [ + + + - : 2873 : switch (pos[0]) {
- + ]
255 : : case WLAN_EID_RSN:
256 : 92 : parse->rsn = pos + 2;
257 : 92 : parse->rsn_len = pos[1];
258 : 92 : ret = wpa_parse_wpa_ie_rsn(parse->rsn - 2,
259 : 92 : parse->rsn_len + 2,
260 : : &data);
261 [ - + ]: 92 : if (ret < 0) {
262 : 0 : wpa_printf(MSG_DEBUG, "FT: Failed to parse "
263 : : "RSN IE: %d", ret);
264 : 0 : return -1;
265 : : }
266 [ + + ][ + - ]: 92 : if (data.num_pmkid == 1 && data.pmkid)
267 : 84 : parse->rsn_pmkid = data.pmkid;
268 : 92 : break;
269 : : case WLAN_EID_MOBILITY_DOMAIN:
270 : 120 : parse->mdie = pos + 2;
271 : 120 : parse->mdie_len = pos[1];
272 : 120 : break;
273 : : case WLAN_EID_FAST_BSS_TRANSITION:
274 [ - + ]: 92 : if (pos[1] < sizeof(*ftie))
275 : 0 : return -1;
276 : 92 : ftie = (const struct rsn_ftie *) (pos + 2);
277 : 92 : prot_ie_count = ftie->mic_control[1];
278 [ - + ]: 92 : if (wpa_ft_parse_ftie(pos + 2, pos[1], parse) < 0)
279 : 0 : return -1;
280 : 92 : 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 : 2873 : pos += 2 + pos[1];
292 : : }
293 : :
294 [ + + ]: 454 : if (prot_ie_count == 0)
295 : 398 : return 0; /* no MIC */
296 : :
297 : : /*
298 : : * Check that the protected IE count matches with IEs included in the
299 : : * frame.
300 : : */
301 [ + - ]: 56 : if (parse->rsn)
302 : 56 : prot_ie_count--;
303 [ + - ]: 56 : if (parse->mdie)
304 : 56 : prot_ie_count--;
305 [ + - ]: 56 : if (parse->ftie)
306 : 56 : prot_ie_count--;
307 [ - + ]: 56 : 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 [ + - ][ - + ]: 56 : 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 : 56 : pos = parse->ric;
321 [ - + ][ # # ]: 56 : 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 : 56 : parse->ric_len = pos - parse->ric;
327 [ - + ]: 56 : 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 : 807 : return 0;
334 : : }
335 : : #endif /* CONFIG_IEEE80211R */
336 : :
337 : :
338 : 2352 : static int rsn_selector_to_bitfield(const u8 *s)
339 : : {
340 [ - + ]: 2352 : if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_NONE)
341 : 0 : return WPA_CIPHER_NONE;
342 [ - + ]: 2352 : if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_WEP40)
343 : 0 : return WPA_CIPHER_WEP40;
344 [ + + ]: 2352 : if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_TKIP)
345 : 62 : return WPA_CIPHER_TKIP;
346 [ + + ]: 2290 : if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_CCMP)
347 : 2071 : return WPA_CIPHER_CCMP;
348 [ - + ]: 219 : if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_WEP104)
349 : 0 : return WPA_CIPHER_WEP104;
350 : : #ifdef CONFIG_IEEE80211W
351 [ + + ]: 219 : if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_AES_128_CMAC)
352 : 163 : return WPA_CIPHER_AES_128_CMAC;
353 : : #endif /* CONFIG_IEEE80211W */
354 [ + + ]: 56 : if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_GCMP)
355 : 6 : return WPA_CIPHER_GCMP;
356 [ + + ]: 50 : if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_CCMP_256)
357 : 6 : return WPA_CIPHER_CCMP_256;
358 [ + + ]: 44 : if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_GCMP_256)
359 : 6 : 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 : 2352 : return 0;
367 : : }
368 : :
369 : :
370 : 1119 : static int rsn_key_mgmt_to_bitfield(const u8 *s)
371 : : {
372 [ + + ]: 1119 : if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_UNSPEC_802_1X)
373 : 211 : return WPA_KEY_MGMT_IEEE8021X;
374 [ + + ]: 908 : if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X)
375 : 502 : return WPA_KEY_MGMT_PSK;
376 : : #ifdef CONFIG_IEEE80211R
377 [ + + ]: 406 : if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_FT_802_1X)
378 : 33 : return WPA_KEY_MGMT_FT_IEEE8021X;
379 [ + + ]: 373 : if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_FT_PSK)
380 : 141 : return WPA_KEY_MGMT_FT_PSK;
381 : : #endif /* CONFIG_IEEE80211R */
382 : : #ifdef CONFIG_IEEE80211W
383 [ + + ]: 232 : if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_802_1X_SHA256)
384 : 6 : return WPA_KEY_MGMT_IEEE8021X_SHA256;
385 [ + + ]: 226 : if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_PSK_SHA256)
386 : 38 : return WPA_KEY_MGMT_PSK_SHA256;
387 : : #endif /* CONFIG_IEEE80211W */
388 : : #ifdef CONFIG_SAE
389 [ + + ]: 188 : if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_SAE)
390 : 78 : return WPA_KEY_MGMT_SAE;
391 [ + + ]: 110 : if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_FT_SAE)
392 : 72 : return WPA_KEY_MGMT_FT_SAE;
393 : : #endif /* CONFIG_SAE */
394 : 1119 : 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 : 1091 : 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 : 1091 : os_memset(data, 0, sizeof(*data));
414 : 1091 : data->proto = WPA_PROTO_RSN;
415 : 1091 : data->pairwise_cipher = WPA_CIPHER_CCMP;
416 : 1091 : data->group_cipher = WPA_CIPHER_CCMP;
417 : 1091 : data->key_mgmt = WPA_KEY_MGMT_IEEE8021X;
418 : 1091 : data->capabilities = 0;
419 : 1091 : data->pmkid = NULL;
420 : 1091 : data->num_pmkid = 0;
421 : : #ifdef CONFIG_IEEE80211W
422 : 1091 : 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 [ - + ]: 1091 : if (rsn_ie_len == 0) {
428 : : /* No RSN IE - fail silently */
429 : 0 : return -1;
430 : : }
431 : :
432 [ - + ]: 1091 : 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 : 1091 : hdr = (const struct rsn_ie_hdr *) rsn_ie;
439 : :
440 [ + - ][ + - ]: 1091 : if (hdr->elem_id != WLAN_EID_RSN ||
441 [ - + ]: 1091 : hdr->len != rsn_ie_len - 2 ||
442 : 1091 : 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 : 1091 : pos = (const u8 *) (hdr + 1);
449 : 1091 : left = rsn_ie_len - sizeof(*hdr);
450 : :
451 [ + - ]: 1091 : if (left >= RSN_SELECTOR_LEN) {
452 : 1091 : data->group_cipher = rsn_selector_to_bitfield(pos);
453 : : #ifdef CONFIG_IEEE80211W
454 [ - + ]: 1091 : 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 : 1091 : pos += RSN_SELECTOR_LEN;
461 : 1091 : 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 [ + - ]: 1091 : if (left >= 2) {
469 : 1091 : data->pairwise_cipher = 0;
470 : 1091 : count = WPA_GET_LE16(pos);
471 : 1091 : pos += 2;
472 : 1091 : left -= 2;
473 [ - + ][ + - ]: 1091 : 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 [ + + ]: 2189 : for (i = 0; i < count; i++) {
479 : 1098 : data->pairwise_cipher |= rsn_selector_to_bitfield(pos);
480 : 1098 : pos += RSN_SELECTOR_LEN;
481 : 1098 : left -= RSN_SELECTOR_LEN;
482 : : }
483 : : #ifdef CONFIG_IEEE80211W
484 [ - + ]: 1091 : 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 [ + + ]: 1091 : if (left >= 2) {
497 : 1089 : data->key_mgmt = 0;
498 : 1089 : count = WPA_GET_LE16(pos);
499 : 1089 : pos += 2;
500 : 1089 : left -= 2;
501 [ - + ][ + - ]: 1089 : 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 [ + + ]: 2208 : for (i = 0; i < count; i++) {
507 : 1119 : data->key_mgmt |= rsn_key_mgmt_to_bitfield(pos);
508 : 1119 : pos += RSN_SELECTOR_LEN;
509 : 1119 : 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 [ + + ]: 1091 : if (left >= 2) {
518 : 1089 : data->capabilities = WPA_GET_LE16(pos);
519 : 1089 : pos += 2;
520 : 1089 : left -= 2;
521 : : }
522 : :
523 [ + + ]: 1091 : if (left >= 2) {
524 : 274 : data->num_pmkid = WPA_GET_LE16(pos);
525 : 274 : pos += 2;
526 : 274 : left -= 2;
527 [ - + ]: 274 : 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 : 274 : data->pmkid = pos;
536 : 274 : pos += data->num_pmkid * PMKID_LEN;
537 : 274 : left -= data->num_pmkid * PMKID_LEN;
538 : : }
539 : : }
540 : :
541 : : #ifdef CONFIG_IEEE80211W
542 [ + + ]: 1091 : if (left >= 4) {
543 : 163 : data->mgmt_group_cipher = rsn_selector_to_bitfield(pos);
544 [ - + ]: 163 : 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 : 163 : pos += RSN_SELECTOR_LEN;
551 : 163 : left -= RSN_SELECTOR_LEN;
552 : : }
553 : : #endif /* CONFIG_IEEE80211W */
554 : :
555 [ - + ]: 1091 : if (left > 0) {
556 : 0 : wpa_printf(MSG_DEBUG, "%s: ie has %u trailing bytes - ignored",
557 : : __func__, left);
558 : : }
559 : :
560 : 1091 : return 0;
561 : : }
562 : :
563 : :
564 : 30 : static int wpa_selector_to_bitfield(const u8 *s)
565 : : {
566 [ - + ]: 30 : if (RSN_SELECTOR_GET(s) == WPA_CIPHER_SUITE_NONE)
567 : 0 : return WPA_CIPHER_NONE;
568 [ - + ]: 30 : if (RSN_SELECTOR_GET(s) == WPA_CIPHER_SUITE_WEP40)
569 : 0 : return WPA_CIPHER_WEP40;
570 [ + - ]: 30 : if (RSN_SELECTOR_GET(s) == WPA_CIPHER_SUITE_TKIP)
571 : 30 : return WPA_CIPHER_TKIP;
572 [ # # ]: 0 : if (RSN_SELECTOR_GET(s) == WPA_CIPHER_SUITE_CCMP)
573 : 0 : return WPA_CIPHER_CCMP;
574 [ # # ]: 0 : if (RSN_SELECTOR_GET(s) == WPA_CIPHER_SUITE_WEP104)
575 : 0 : return WPA_CIPHER_WEP104;
576 : 30 : return 0;
577 : : }
578 : :
579 : :
580 : 15 : static int wpa_key_mgmt_to_bitfield(const u8 *s)
581 : : {
582 [ + + ]: 15 : if (RSN_SELECTOR_GET(s) == WPA_AUTH_KEY_MGMT_UNSPEC_802_1X)
583 : 3 : return WPA_KEY_MGMT_IEEE8021X;
584 [ + - ]: 12 : if (RSN_SELECTOR_GET(s) == WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X)
585 : 12 : 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 : 15 : return 0;
589 : : }
590 : :
591 : :
592 : 15 : 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 : 15 : os_memset(data, 0, sizeof(*data));
601 : 15 : data->proto = WPA_PROTO_WPA;
602 : 15 : data->pairwise_cipher = WPA_CIPHER_TKIP;
603 : 15 : data->group_cipher = WPA_CIPHER_TKIP;
604 : 15 : data->key_mgmt = WPA_KEY_MGMT_IEEE8021X;
605 : 15 : data->capabilities = 0;
606 : 15 : data->pmkid = NULL;
607 : 15 : data->num_pmkid = 0;
608 : 15 : data->mgmt_group_cipher = 0;
609 : :
610 [ - + ]: 15 : if (wpa_ie_len == 0) {
611 : : /* No WPA IE - fail silently */
612 : 0 : return -1;
613 : : }
614 : :
615 [ - + ]: 15 : 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 : 15 : hdr = (const struct wpa_ie_hdr *) wpa_ie;
622 : :
623 [ + - ][ + - ]: 15 : if (hdr->elem_id != WLAN_EID_VENDOR_SPECIFIC ||
624 [ + - ]: 15 : hdr->len != wpa_ie_len - 2 ||
625 [ - + ]: 30 : RSN_SELECTOR_GET(hdr->oui) != WPA_OUI_TYPE ||
626 : 15 : 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 : 15 : pos = (const u8 *) (hdr + 1);
633 : 15 : left = wpa_ie_len - sizeof(*hdr);
634 : :
635 [ + - ]: 15 : if (left >= WPA_SELECTOR_LEN) {
636 : 15 : data->group_cipher = wpa_selector_to_bitfield(pos);
637 : 15 : pos += WPA_SELECTOR_LEN;
638 : 15 : 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 [ + - ]: 15 : if (left >= 2) {
646 : 15 : data->pairwise_cipher = 0;
647 : 15 : count = WPA_GET_LE16(pos);
648 : 15 : pos += 2;
649 : 15 : left -= 2;
650 [ - + ][ + - ]: 15 : 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 [ + + ]: 30 : for (i = 0; i < count; i++) {
656 : 15 : data->pairwise_cipher |= wpa_selector_to_bitfield(pos);
657 : 15 : pos += WPA_SELECTOR_LEN;
658 : 15 : 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 [ + - ]: 15 : if (left >= 2) {
667 : 15 : data->key_mgmt = 0;
668 : 15 : count = WPA_GET_LE16(pos);
669 : 15 : pos += 2;
670 : 15 : left -= 2;
671 [ - + ][ + - ]: 15 : 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 [ + + ]: 30 : for (i = 0; i < count; i++) {
677 : 15 : data->key_mgmt |= wpa_key_mgmt_to_bitfield(pos);
678 : 15 : pos += WPA_SELECTOR_LEN;
679 : 15 : 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 [ - + ]: 15 : if (left >= 2) {
688 : 0 : data->capabilities = WPA_GET_LE16(pos);
689 : 0 : pos += 2;
690 : 0 : left -= 2;
691 : : }
692 : :
693 [ - + ]: 15 : if (left > 0) {
694 : 0 : wpa_printf(MSG_DEBUG, "%s: ie has %u trailing bytes - ignored",
695 : : __func__, left);
696 : : }
697 : :
698 : 15 : 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 : 16 : 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 [ + - ][ - + ]: 16 : if (ssid_len > WPA_MAX_SSID_LEN || r0kh_id_len > FT_R0KH_ID_MAX_LEN)
729 : 16 : return;
730 : 16 : pos = buf;
731 : 16 : *pos++ = ssid_len;
732 : 16 : os_memcpy(pos, ssid, ssid_len);
733 : 16 : pos += ssid_len;
734 : 16 : os_memcpy(pos, mdid, MOBILITY_DOMAIN_ID_LEN);
735 : 16 : pos += MOBILITY_DOMAIN_ID_LEN;
736 : 16 : *pos++ = r0kh_id_len;
737 : 16 : os_memcpy(pos, r0kh_id, r0kh_id_len);
738 : 16 : pos += r0kh_id_len;
739 : 16 : os_memcpy(pos, s0kh_id, ETH_ALEN);
740 : 16 : pos += ETH_ALEN;
741 : :
742 : 16 : sha256_prf(xxkey, xxkey_len, "FT-R0", buf, pos - buf,
743 : : r0_key_data, sizeof(r0_key_data));
744 : 16 : os_memcpy(pmk_r0, r0_key_data, PMK_LEN);
745 : :
746 : : /*
747 : : * PMKR0Name = Truncate-128(SHA-256("FT-R0N" || PMK-R0Name-Salt)
748 : : */
749 : 16 : addr[0] = (const u8 *) "FT-R0N";
750 : 16 : len[0] = 6;
751 : 16 : addr[1] = r0_key_data + PMK_LEN;
752 : 16 : len[1] = 16;
753 : :
754 : 16 : sha256_vector(2, addr, len, hash);
755 : 16 : 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 : 52 : 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 : 52 : addr[0] = (const u8 *) "FT-R1N";
776 : 52 : len[0] = 6;
777 : 52 : addr[1] = pmk_r0_name;
778 : 52 : len[1] = WPA_PMK_NAME_LEN;
779 : 52 : addr[2] = r1kh_id;
780 : 52 : len[2] = FT_R1KH_ID_LEN;
781 : 52 : addr[3] = s1kh_id;
782 : 52 : len[3] = ETH_ALEN;
783 : :
784 : 52 : sha256_vector(4, addr, len, hash);
785 : 52 : os_memcpy(pmk_r1_name, hash, WPA_PMK_NAME_LEN);
786 : 52 : }
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 : 38 : 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 : 38 : pos = buf;
803 : 38 : os_memcpy(pos, r1kh_id, FT_R1KH_ID_LEN);
804 : 38 : pos += FT_R1KH_ID_LEN;
805 : 38 : os_memcpy(pos, s1kh_id, ETH_ALEN);
806 : 38 : pos += ETH_ALEN;
807 : :
808 : 38 : sha256_prf(pmk_r0, PMK_LEN, "FT-R1", buf, pos - buf, pmk_r1, PMK_LEN);
809 : :
810 : 38 : wpa_derive_pmk_r1_name(pmk_r0_name, r1kh_id, s1kh_id, pmk_r1_name);
811 : 38 : }
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 : 44 : 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 : 44 : pos = buf;
834 : 44 : os_memcpy(pos, snonce, WPA_NONCE_LEN);
835 : 44 : pos += WPA_NONCE_LEN;
836 : 44 : os_memcpy(pos, anonce, WPA_NONCE_LEN);
837 : 44 : pos += WPA_NONCE_LEN;
838 : 44 : os_memcpy(pos, bssid, ETH_ALEN);
839 : 44 : pos += ETH_ALEN;
840 : 44 : os_memcpy(pos, sta_addr, ETH_ALEN);
841 : 44 : pos += ETH_ALEN;
842 : :
843 : 44 : 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 : 44 : addr[0] = pmk_r1_name;
850 : 44 : len[0] = WPA_PMK_NAME_LEN;
851 : 44 : addr[1] = (const u8 *) "FT-PTKN";
852 : 44 : len[1] = 7;
853 : 44 : addr[2] = snonce;
854 : 44 : len[2] = WPA_NONCE_LEN;
855 : 44 : addr[3] = anonce;
856 : 44 : len[3] = WPA_NONCE_LEN;
857 : 44 : addr[4] = bssid;
858 : 44 : len[4] = ETH_ALEN;
859 : 44 : addr[5] = sta_addr;
860 : 44 : len[5] = ETH_ALEN;
861 : :
862 : 44 : sha256_vector(6, addr, len, hash);
863 : 44 : os_memcpy(ptk_name, hash, WPA_PMK_NAME_LEN);
864 : 44 : }
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 : 206 : void rsn_pmkid(const u8 *pmk, size_t pmk_len, const u8 *aa, const u8 *spa,
882 : : u8 *pmkid, int use_sha256)
883 : : {
884 : 206 : char *title = "PMK Name";
885 : : const u8 *addr[3];
886 : 206 : const size_t len[3] = { 8, ETH_ALEN, ETH_ALEN };
887 : : unsigned char hash[SHA256_MAC_LEN];
888 : :
889 : 206 : addr[0] = (u8 *) title;
890 : 206 : addr[1] = aa;
891 : 206 : addr[2] = spa;
892 : :
893 : : #ifdef CONFIG_IEEE80211W
894 [ + + ]: 206 : if (use_sha256)
895 : 6 : hmac_sha256_vector(pmk, pmk_len, 3, addr, len, hash);
896 : : else
897 : : #endif /* CONFIG_IEEE80211W */
898 : 200 : hmac_sha1_vector(pmk, pmk_len, 3, addr, len, hash);
899 : 206 : os_memcpy(pmkid, hash, PMKID_LEN);
900 : 206 : }
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 : 1475 : const char * wpa_cipher_txt(int cipher)
909 : : {
910 [ + + - + : 1475 : switch (cipher) {
+ - + + +
- - ]
911 : : case WPA_CIPHER_NONE:
912 : 102 : 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 : 80 : return "TKIP";
919 : : case WPA_CIPHER_CCMP:
920 : 1269 : return "CCMP";
921 : : case WPA_CIPHER_CCMP | WPA_CIPHER_TKIP:
922 : 0 : return "CCMP+TKIP";
923 : : case WPA_CIPHER_GCMP:
924 : 4 : return "GCMP";
925 : : case WPA_CIPHER_GCMP_256:
926 : 4 : return "GCMP-256";
927 : : case WPA_CIPHER_CCMP_256:
928 : 4 : return "CCMP-256";
929 : : case WPA_CIPHER_GTK_NOT_USED:
930 : 0 : return "GTK_NOT_USED";
931 : : default:
932 : 1475 : 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 : 262 : const char * wpa_key_mgmt_txt(int key_mgmt, int proto)
944 : : {
945 [ + + + - : 262 : 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 [ - + ]: 102 : if (proto == (WPA_PROTO_RSN | WPA_PROTO_WPA))
953 : 0 : return "WPA2-PSK+WPA-PSK";
954 : 102 : return proto == WPA_PROTO_RSN ?
955 [ + + ]: 102 : "WPA2-PSK" : "WPA-PSK";
956 : : case WPA_KEY_MGMT_NONE:
957 : 57 : 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 : 13 : 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 : 262 : return "UNKNOWN";
974 : : }
975 : : }
976 : :
977 : :
978 : 458 : 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 [ + - ][ - + ]: 458 : if (ie1 == NULL || ie2 == NULL)
983 : 0 : return -1;
984 : :
985 [ + + ][ + - ]: 458 : if (ie1len == ie2len && os_memcmp(ie1, ie2, ie1len) == 0)
986 : 442 : return 0; /* identical IEs */
987 : :
988 : : #ifdef CONFIG_IEEE80211R
989 [ + - ]: 16 : 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 [ + - - + ]: 32 : if (wpa_parse_wpa_ie_rsn(ie1, ie1len, &ie1d) < 0 ||
999 : 16 : wpa_parse_wpa_ie_rsn(ie2, ie2len, &ie2d) < 0)
1000 : 0 : return -1;
1001 [ + - ][ + - ]: 16 : if (ie1d.proto == ie2d.proto &&
1002 [ + - ]: 16 : ie1d.pairwise_cipher == ie2d.pairwise_cipher &&
1003 [ + - ]: 16 : ie1d.group_cipher == ie2d.group_cipher &&
1004 [ + - ]: 16 : ie1d.key_mgmt == ie2d.key_mgmt &&
1005 [ + - ]: 16 : ie1d.capabilities == ie2d.capabilities &&
1006 : 16 : ie1d.mgmt_group_cipher == ie2d.mgmt_group_cipher)
1007 : 16 : return 0;
1008 : : }
1009 : : #endif /* CONFIG_IEEE80211R */
1010 : :
1011 : 458 : return -1;
1012 : : }
1013 : :
1014 : :
1015 : : #ifdef CONFIG_IEEE80211R
1016 : 16 : int wpa_insert_pmkid(u8 *ies, size_t ies_len, const u8 *pmkid)
1017 : : {
1018 : : u8 *start, *end, *rpos, *rend;
1019 : 16 : int added = 0;
1020 : :
1021 : 16 : start = ies;
1022 : 16 : end = ies + ies_len;
1023 : :
1024 [ + - ]: 16 : while (start < end) {
1025 [ + - ]: 16 : if (*start == WLAN_EID_RSN)
1026 : 16 : break;
1027 : 0 : start += 2 + start[1];
1028 : : }
1029 [ - + ]: 16 : 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 : 16 : wpa_hexdump(MSG_DEBUG, "FT: RSN IE before modification",
1035 : 16 : start, 2 + start[1]);
1036 : :
1037 : : /* Find start of PMKID-Count */
1038 : 16 : rpos = start + 2;
1039 : 16 : rend = rpos + start[1];
1040 : :
1041 : : /* Skip Version and Group Data Cipher Suite */
1042 : 16 : rpos += 2 + 4;
1043 : : /* Skip Pairwise Cipher Suite Count and List */
1044 : 16 : rpos += 2 + WPA_GET_LE16(rpos) * RSN_SELECTOR_LEN;
1045 : : /* Skip AKM Suite Count and List */
1046 : 16 : rpos += 2 + WPA_GET_LE16(rpos) * RSN_SELECTOR_LEN;
1047 : :
1048 [ - + ]: 16 : 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 : 16 : rpos += 2;
1056 [ - + ]: 16 : 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 [ + + ]: 16 : if (rpos == rend) {
1064 : : /* No PMKID-Count field included; add it */
1065 : 12 : os_memmove(rpos + 2 + PMKID_LEN, rpos, end - rpos);
1066 : 12 : WPA_PUT_LE16(rpos, 1);
1067 : 12 : rpos += 2;
1068 : 12 : os_memcpy(rpos, pmkid, PMKID_LEN);
1069 : 12 : added += 2 + PMKID_LEN;
1070 : 12 : start[1] += 2 + PMKID_LEN;
1071 : : } else {
1072 : : /* PMKID-Count was included; use it */
1073 [ - + ]: 4 : 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 : 4 : WPA_PUT_LE16(rpos, 1);
1079 : 4 : rpos += 2;
1080 : 4 : os_memmove(rpos + PMKID_LEN, rpos, end - rpos);
1081 : 4 : os_memcpy(rpos, pmkid, PMKID_LEN);
1082 : 4 : added += PMKID_LEN;
1083 : 4 : start[1] += PMKID_LEN;
1084 : : }
1085 : :
1086 : 16 : wpa_hexdump(MSG_DEBUG, "FT: RSN IE after modification "
1087 : 16 : "(PMKID inserted)", start, 2 + start[1]);
1088 : :
1089 : 16 : return added;
1090 : : }
1091 : : #endif /* CONFIG_IEEE80211R */
1092 : :
1093 : :
1094 : 1628 : int wpa_cipher_key_len(int cipher)
1095 : : {
1096 [ + + + - : 1628 : switch (cipher) {
- - ]
1097 : : case WPA_CIPHER_CCMP_256:
1098 : : case WPA_CIPHER_GCMP_256:
1099 : 14 : return 32;
1100 : : case WPA_CIPHER_CCMP:
1101 : : case WPA_CIPHER_GCMP:
1102 : 1547 : return 16;
1103 : : case WPA_CIPHER_TKIP:
1104 : 67 : return 32;
1105 : : case WPA_CIPHER_WEP104:
1106 : 0 : return 13;
1107 : : case WPA_CIPHER_WEP40:
1108 : 0 : return 5;
1109 : : }
1110 : :
1111 : 1628 : return 0;
1112 : : }
1113 : :
1114 : :
1115 : 461 : int wpa_cipher_rsc_len(int cipher)
1116 : : {
1117 [ + - - ]: 461 : 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 : 461 : return 6;
1124 : : case WPA_CIPHER_WEP104:
1125 : : case WPA_CIPHER_WEP40:
1126 : 0 : return 0;
1127 : : }
1128 : :
1129 : 461 : return 0;
1130 : : }
1131 : :
1132 : :
1133 : 1094 : int wpa_cipher_to_alg(int cipher)
1134 : : {
1135 [ + + + + : 1094 : switch (cipher) {
+ - - ]
1136 : : case WPA_CIPHER_CCMP_256:
1137 : 5 : return WPA_ALG_CCMP_256;
1138 : : case WPA_CIPHER_GCMP_256:
1139 : 5 : return WPA_ALG_GCMP_256;
1140 : : case WPA_CIPHER_CCMP:
1141 : 1029 : return WPA_ALG_CCMP;
1142 : : case WPA_CIPHER_GCMP:
1143 : 5 : return WPA_ALG_GCMP;
1144 : : case WPA_CIPHER_TKIP:
1145 : 50 : return WPA_ALG_TKIP;
1146 : : case WPA_CIPHER_WEP104:
1147 : : case WPA_CIPHER_WEP40:
1148 : 0 : return WPA_ALG_WEP;
1149 : : }
1150 : 1094 : return WPA_ALG_NONE;
1151 : : }
1152 : :
1153 : :
1154 : 781 : enum wpa_cipher wpa_cipher_to_suite_driver(int cipher)
1155 : : {
1156 [ + + - + : 781 : switch (cipher) {
+ + + + ]
1157 : : case WPA_CIPHER_NONE:
1158 : 278 : return CIPHER_NONE;
1159 : : case WPA_CIPHER_WEP40:
1160 : 4 : return CIPHER_WEP40;
1161 : : case WPA_CIPHER_WEP104:
1162 : 0 : return CIPHER_WEP104;
1163 : : case WPA_CIPHER_CCMP:
1164 : 467 : return CIPHER_CCMP;
1165 : : case WPA_CIPHER_GCMP:
1166 : 2 : return CIPHER_GCMP;
1167 : : case WPA_CIPHER_CCMP_256:
1168 : 2 : return CIPHER_CCMP_256;
1169 : : case WPA_CIPHER_GCMP_256:
1170 : 2 : return CIPHER_GCMP_256;
1171 : : case WPA_CIPHER_TKIP:
1172 : : default:
1173 : 781 : return CIPHER_TKIP;
1174 : : }
1175 : : }
1176 : :
1177 : :
1178 : 597 : int wpa_cipher_valid_pairwise(int cipher)
1179 : : {
1180 [ + + ][ + + ]: 1190 : return cipher == WPA_CIPHER_CCMP_256 ||
1181 [ + + ]: 593 : cipher == WPA_CIPHER_GCMP_256 ||
1182 [ + + ]: 18 : cipher == WPA_CIPHER_CCMP ||
1183 [ + - ]: 16 : cipher == WPA_CIPHER_GCMP ||
1184 : : cipher == WPA_CIPHER_TKIP;
1185 : : }
1186 : :
1187 : :
1188 : 1317 : u32 wpa_cipher_to_suite(int proto, int cipher)
1189 : : {
1190 [ + + ]: 1317 : if (cipher & WPA_CIPHER_CCMP_256)
1191 : 5 : return RSN_CIPHER_SUITE_CCMP_256;
1192 [ + + ]: 1312 : if (cipher & WPA_CIPHER_GCMP_256)
1193 : 5 : return RSN_CIPHER_SUITE_GCMP_256;
1194 [ + + ]: 1307 : if (cipher & WPA_CIPHER_CCMP)
1195 : 1224 : return (proto == WPA_PROTO_RSN ?
1196 [ + - ]: 1224 : RSN_CIPHER_SUITE_CCMP : WPA_CIPHER_SUITE_CCMP);
1197 [ + + ]: 83 : if (cipher & WPA_CIPHER_GCMP)
1198 : 5 : return RSN_CIPHER_SUITE_GCMP;
1199 [ + - ]: 78 : if (cipher & WPA_CIPHER_TKIP)
1200 : 78 : return (proto == WPA_PROTO_RSN ?
1201 [ + + ]: 78 : RSN_CIPHER_SUITE_TKIP : WPA_CIPHER_SUITE_TKIP);
1202 [ # # ]: 0 : if (cipher & WPA_CIPHER_WEP104)
1203 : 0 : return (proto == WPA_PROTO_RSN ?
1204 [ # # ]: 0 : RSN_CIPHER_SUITE_WEP104 : WPA_CIPHER_SUITE_WEP104);
1205 [ # # ]: 0 : if (cipher & WPA_CIPHER_WEP40)
1206 : 0 : return (proto == WPA_PROTO_RSN ?
1207 [ # # ]: 0 : RSN_CIPHER_SUITE_WEP40 : WPA_CIPHER_SUITE_WEP40);
1208 [ # # ]: 0 : if (cipher & WPA_CIPHER_NONE)
1209 : 0 : return (proto == WPA_PROTO_RSN ?
1210 [ # # ]: 0 : RSN_CIPHER_SUITE_NONE : WPA_CIPHER_SUITE_NONE);
1211 [ # # ]: 0 : if (cipher & WPA_CIPHER_GTK_NOT_USED)
1212 : 0 : return RSN_CIPHER_SUITE_NO_GROUP_ADDRESSED;
1213 : 1317 : return 0;
1214 : : }
1215 : :
1216 : :
1217 : 219 : int rsn_cipher_put_suites(u8 *pos, int ciphers)
1218 : : {
1219 : 219 : int num_suites = 0;
1220 : :
1221 [ + + ]: 219 : if (ciphers & WPA_CIPHER_CCMP_256) {
1222 : 1 : RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP_256);
1223 : 1 : pos += RSN_SELECTOR_LEN;
1224 : 1 : num_suites++;
1225 : : }
1226 [ + + ]: 219 : if (ciphers & WPA_CIPHER_GCMP_256) {
1227 : 1 : RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_GCMP_256);
1228 : 1 : pos += RSN_SELECTOR_LEN;
1229 : 1 : num_suites++;
1230 : : }
1231 [ + + ]: 219 : if (ciphers & WPA_CIPHER_CCMP) {
1232 : 215 : RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP);
1233 : 215 : pos += RSN_SELECTOR_LEN;
1234 : 215 : num_suites++;
1235 : : }
1236 [ + + ]: 219 : if (ciphers & WPA_CIPHER_GCMP) {
1237 : 1 : RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_GCMP);
1238 : 1 : pos += RSN_SELECTOR_LEN;
1239 : 1 : num_suites++;
1240 : : }
1241 [ + + ]: 219 : if (ciphers & WPA_CIPHER_TKIP) {
1242 : 5 : RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_TKIP);
1243 : 5 : pos += RSN_SELECTOR_LEN;
1244 : 5 : num_suites++;
1245 : : }
1246 [ - + ]: 219 : if (ciphers & WPA_CIPHER_NONE) {
1247 : 0 : RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_NONE);
1248 : 0 : pos += RSN_SELECTOR_LEN;
1249 : 0 : num_suites++;
1250 : : }
1251 : :
1252 : 219 : return num_suites;
1253 : : }
1254 : :
1255 : :
1256 : 10 : int wpa_cipher_put_suites(u8 *pos, int ciphers)
1257 : : {
1258 : 10 : int num_suites = 0;
1259 : :
1260 [ + + ]: 10 : if (ciphers & WPA_CIPHER_CCMP) {
1261 : 3 : RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_CCMP);
1262 : 3 : pos += WPA_SELECTOR_LEN;
1263 : 3 : num_suites++;
1264 : : }
1265 [ + - ]: 10 : if (ciphers & WPA_CIPHER_TKIP) {
1266 : 10 : RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_TKIP);
1267 : 10 : pos += WPA_SELECTOR_LEN;
1268 : 10 : num_suites++;
1269 : : }
1270 [ - + ]: 10 : if (ciphers & WPA_CIPHER_NONE) {
1271 : 0 : RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_NONE);
1272 : 0 : pos += WPA_SELECTOR_LEN;
1273 : 0 : num_suites++;
1274 : : }
1275 : :
1276 : 10 : return num_suites;
1277 : : }
1278 : :
1279 : :
1280 : 517 : int wpa_pick_pairwise_cipher(int ciphers, int none_allowed)
1281 : : {
1282 [ + + ]: 517 : if (ciphers & WPA_CIPHER_CCMP_256)
1283 : 2 : return WPA_CIPHER_CCMP_256;
1284 [ + + ]: 515 : if (ciphers & WPA_CIPHER_GCMP_256)
1285 : 2 : return WPA_CIPHER_GCMP_256;
1286 [ + + ]: 513 : if (ciphers & WPA_CIPHER_CCMP)
1287 : 496 : return WPA_CIPHER_CCMP;
1288 [ + + ]: 17 : if (ciphers & WPA_CIPHER_GCMP)
1289 : 2 : return WPA_CIPHER_GCMP;
1290 [ + - ]: 15 : if (ciphers & WPA_CIPHER_TKIP)
1291 : 15 : return WPA_CIPHER_TKIP;
1292 [ # # ][ # # ]: 0 : if (none_allowed && (ciphers & WPA_CIPHER_NONE))
1293 : 0 : return WPA_CIPHER_NONE;
1294 : 517 : return -1;
1295 : : }
1296 : :
1297 : :
1298 : 238 : int wpa_pick_group_cipher(int ciphers)
1299 : : {
1300 [ + + ]: 238 : if (ciphers & WPA_CIPHER_CCMP_256)
1301 : 1 : return WPA_CIPHER_CCMP_256;
1302 [ + + ]: 237 : if (ciphers & WPA_CIPHER_GCMP_256)
1303 : 1 : return WPA_CIPHER_GCMP_256;
1304 [ + + ]: 236 : if (ciphers & WPA_CIPHER_CCMP)
1305 : 218 : return WPA_CIPHER_CCMP;
1306 [ + + ]: 18 : if (ciphers & WPA_CIPHER_GCMP)
1307 : 1 : return WPA_CIPHER_GCMP;
1308 [ - + ]: 17 : if (ciphers & WPA_CIPHER_GTK_NOT_USED)
1309 : 0 : return WPA_CIPHER_GTK_NOT_USED;
1310 [ + - ]: 17 : if (ciphers & WPA_CIPHER_TKIP)
1311 : 17 : return WPA_CIPHER_TKIP;
1312 [ # # ]: 0 : if (ciphers & WPA_CIPHER_WEP104)
1313 : 0 : return WPA_CIPHER_WEP104;
1314 [ # # ]: 0 : if (ciphers & WPA_CIPHER_WEP40)
1315 : 0 : return WPA_CIPHER_WEP40;
1316 : 238 : return -1;
1317 : : }
1318 : :
1319 : :
1320 : 183 : int wpa_parse_cipher(const char *value)
1321 : : {
1322 : 183 : int val = 0, last;
1323 : : char *start, *end, *buf;
1324 : :
1325 : 183 : buf = os_strdup(value);
1326 [ - + ]: 183 : if (buf == NULL)
1327 : 0 : return -1;
1328 : 183 : start = buf;
1329 : :
1330 [ + - ]: 183 : while (*start != '\0') {
1331 [ - + ][ - + ]: 183 : while (*start == ' ' || *start == '\t')
1332 : 0 : start++;
1333 [ - + ]: 183 : if (*start == '\0')
1334 : 0 : break;
1335 : 183 : end = start;
1336 [ + - ][ + - ]: 939 : while (*end != ' ' && *end != '\t' && *end != '\0')
[ + + ]
1337 : 756 : end++;
1338 : 183 : last = *end == '\0';
1339 : 183 : *end = '\0';
1340 [ + + ]: 183 : if (os_strcmp(start, "CCMP-256") == 0)
1341 : 3 : val |= WPA_CIPHER_CCMP_256;
1342 [ + + ]: 180 : else if (os_strcmp(start, "GCMP-256") == 0)
1343 : 3 : val |= WPA_CIPHER_GCMP_256;
1344 [ + + ]: 177 : else if (os_strcmp(start, "CCMP") == 0)
1345 : 158 : val |= WPA_CIPHER_CCMP;
1346 [ + + ]: 19 : else if (os_strcmp(start, "GCMP") == 0)
1347 : 3 : val |= WPA_CIPHER_GCMP;
1348 [ + - ]: 16 : else if (os_strcmp(start, "TKIP") == 0)
1349 : 16 : val |= WPA_CIPHER_TKIP;
1350 [ # # ]: 0 : else if (os_strcmp(start, "WEP104") == 0)
1351 : 0 : val |= WPA_CIPHER_WEP104;
1352 [ # # ]: 0 : else if (os_strcmp(start, "WEP40") == 0)
1353 : 0 : val |= WPA_CIPHER_WEP40;
1354 [ # # ]: 0 : else if (os_strcmp(start, "NONE") == 0)
1355 : 0 : val |= WPA_CIPHER_NONE;
1356 [ # # ]: 0 : else if (os_strcmp(start, "GTK_NOT_USED") == 0)
1357 : 0 : val |= WPA_CIPHER_GTK_NOT_USED;
1358 : : else {
1359 : 0 : os_free(buf);
1360 : 0 : return -1;
1361 : : }
1362 : :
1363 [ + - ]: 183 : if (last)
1364 : 183 : break;
1365 : 0 : start = end + 1;
1366 : : }
1367 : 183 : os_free(buf);
1368 : :
1369 : 183 : return val;
1370 : : }
1371 : :
1372 : :
1373 : 8 : int wpa_write_ciphers(char *start, char *end, int ciphers, const char *delim)
1374 : : {
1375 : 8 : char *pos = start;
1376 : : int ret;
1377 : :
1378 [ - + ]: 8 : if (ciphers & WPA_CIPHER_CCMP_256) {
1379 [ # # ]: 0 : ret = os_snprintf(pos, end - pos, "%sCCMP-256",
1380 : : pos == start ? "" : delim);
1381 [ # # ][ # # ]: 0 : if (ret < 0 || ret >= end - pos)
1382 : 0 : return -1;
1383 : 0 : pos += ret;
1384 : : }
1385 [ - + ]: 8 : if (ciphers & WPA_CIPHER_GCMP_256) {
1386 [ # # ]: 0 : ret = os_snprintf(pos, end - pos, "%sGCMP-256",
1387 : : pos == start ? "" : delim);
1388 [ # # ][ # # ]: 0 : if (ret < 0 || ret >= end - pos)
1389 : 0 : return -1;
1390 : 0 : pos += ret;
1391 : : }
1392 [ + - ]: 8 : if (ciphers & WPA_CIPHER_CCMP) {
1393 [ - + ]: 8 : ret = os_snprintf(pos, end - pos, "%sCCMP",
1394 : : pos == start ? "" : delim);
1395 [ + - ][ - + ]: 8 : if (ret < 0 || ret >= end - pos)
1396 : 0 : return -1;
1397 : 8 : pos += ret;
1398 : : }
1399 [ - + ]: 8 : if (ciphers & WPA_CIPHER_GCMP) {
1400 [ # # ]: 0 : ret = os_snprintf(pos, end - pos, "%sGCMP",
1401 : : pos == start ? "" : delim);
1402 [ # # ][ # # ]: 0 : if (ret < 0 || ret >= end - pos)
1403 : 0 : return -1;
1404 : 0 : pos += ret;
1405 : : }
1406 [ - + ]: 8 : if (ciphers & WPA_CIPHER_TKIP) {
1407 [ # # ]: 0 : ret = os_snprintf(pos, end - pos, "%sTKIP",
1408 : : pos == start ? "" : delim);
1409 [ # # ][ # # ]: 0 : if (ret < 0 || ret >= end - pos)
1410 : 0 : return -1;
1411 : 0 : pos += ret;
1412 : : }
1413 [ - + ]: 8 : if (ciphers & WPA_CIPHER_WEP104) {
1414 [ # # ]: 0 : ret = os_snprintf(pos, end - pos, "%sWEP104",
1415 : : pos == start ? "" : delim);
1416 [ # # ][ # # ]: 0 : if (ret < 0 || ret >= end - pos)
1417 : 0 : return -1;
1418 : 0 : pos += ret;
1419 : : }
1420 [ - + ]: 8 : if (ciphers & WPA_CIPHER_WEP40) {
1421 [ # # ]: 0 : ret = os_snprintf(pos, end - pos, "%sWEP40",
1422 : : pos == start ? "" : delim);
1423 [ # # ][ # # ]: 0 : if (ret < 0 || ret >= end - pos)
1424 : 0 : return -1;
1425 : 0 : pos += ret;
1426 : : }
1427 [ - + ]: 8 : if (ciphers & WPA_CIPHER_NONE) {
1428 [ # # ]: 0 : ret = os_snprintf(pos, end - pos, "%sNONE",
1429 : : pos == start ? "" : delim);
1430 [ # # ][ # # ]: 0 : if (ret < 0 || ret >= end - pos)
1431 : 0 : return -1;
1432 : 0 : pos += ret;
1433 : : }
1434 : :
1435 : 8 : return pos - start;
1436 : : }
1437 : :
1438 : :
1439 : 3283 : int wpa_select_ap_group_cipher(int wpa, int wpa_pairwise, int rsn_pairwise)
1440 : : {
1441 : 3283 : int pairwise = 0;
1442 : :
1443 : : /* Select group cipher based on the enabled pairwise cipher suites */
1444 [ + + ]: 3283 : if (wpa & 1)
1445 : 43 : pairwise |= wpa_pairwise;
1446 [ + + ]: 3283 : if (wpa & 2)
1447 : 1844 : pairwise |= rsn_pairwise;
1448 : :
1449 [ + + ]: 3283 : if (pairwise & WPA_CIPHER_TKIP)
1450 : 38 : return WPA_CIPHER_TKIP;
1451 [ + + ]: 3245 : if ((pairwise & (WPA_CIPHER_CCMP | WPA_CIPHER_GCMP)) == WPA_CIPHER_GCMP)
1452 : 1 : return WPA_CIPHER_GCMP;
1453 [ + + ]: 3244 : if ((pairwise & (WPA_CIPHER_GCMP_256 | WPA_CIPHER_CCMP |
1454 : : WPA_CIPHER_GCMP)) == WPA_CIPHER_GCMP_256)
1455 : 1 : return WPA_CIPHER_GCMP_256;
1456 [ + + ]: 3243 : if ((pairwise & (WPA_CIPHER_CCMP_256 | WPA_CIPHER_CCMP |
1457 : : WPA_CIPHER_GCMP)) == WPA_CIPHER_CCMP_256)
1458 : 1 : return WPA_CIPHER_CCMP_256;
1459 : 3283 : return WPA_CIPHER_CCMP;
1460 : : }
|