blob: 5534eab4cd8cd64a234b73a783a787ba411c7504 [file] [log] [blame]
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001/*
2 * WPA/RSN - Shared functions for supplicant and authenticator
Dmitry Shmidt807291d2015-01-27 13:40:23 -08003 * Copyright (c) 2002-2015, Jouni Malinen <j@w1.fi>
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004 *
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007 */
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"
Dmitry Shmidt807291d2015-01-27 13:40:23 -080015#include "crypto/sha384.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070016#include "crypto/aes_wrap.h"
17#include "crypto/crypto.h"
18#include "ieee802_11_defs.h"
19#include "defs.h"
20#include "wpa_common.h"
21
22
Dmitry Shmidt807291d2015-01-27 13:40:23 -080023static unsigned int wpa_kck_len(int akmp)
24{
25 if (akmp == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192)
26 return 24;
27 return 16;
28}
29
30
31static unsigned int wpa_kek_len(int akmp)
32{
33 if (akmp == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192)
34 return 32;
35 return 16;
36}
37
38
39unsigned int wpa_mic_len(int akmp)
40{
41 if (akmp == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192)
42 return 24;
43 return 16;
44}
45
46
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070047/**
48 * wpa_eapol_key_mic - Calculate EAPOL-Key MIC
49 * @key: EAPOL-Key Key Confirmation Key (KCK)
Dmitry Shmidt807291d2015-01-27 13:40:23 -080050 * @key_len: KCK length in octets
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080051 * @akmp: WPA_KEY_MGMT_* used in key derivation
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070052 * @ver: Key descriptor version (WPA_KEY_INFO_TYPE_*)
53 * @buf: Pointer to the beginning of the EAPOL header (version field)
54 * @len: Length of the EAPOL frame (from EAPOL header to the end of the frame)
55 * @mic: Pointer to the buffer to which the EAPOL-Key MIC is written
56 * Returns: 0 on success, -1 on failure
57 *
58 * Calculate EAPOL-Key MIC for an EAPOL-Key packet. The EAPOL-Key MIC field has
59 * to be cleared (all zeroes) when calling this function.
60 *
61 * Note: 'IEEE Std 802.11i-2004 - 8.5.2 EAPOL-Key frames' has an error in the
62 * description of the Key MIC calculation. It includes packet data from the
63 * beginning of the EAPOL-Key header, not EAPOL header. This incorrect change
64 * happened during final editing of the standard and the correct behavior is
65 * defined in the last draft (IEEE 802.11i/D10).
66 */
Dmitry Shmidt807291d2015-01-27 13:40:23 -080067int wpa_eapol_key_mic(const u8 *key, size_t key_len, int akmp, int ver,
68 const u8 *buf, size_t len, u8 *mic)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070069{
Dmitry Shmidt807291d2015-01-27 13:40:23 -080070 u8 hash[SHA384_MAC_LEN];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070071
72 switch (ver) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -070073#ifndef CONFIG_FIPS
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070074 case WPA_KEY_INFO_TYPE_HMAC_MD5_RC4:
Dmitry Shmidt807291d2015-01-27 13:40:23 -080075 return hmac_md5(key, key_len, buf, len, mic);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -070076#endif /* CONFIG_FIPS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070077 case WPA_KEY_INFO_TYPE_HMAC_SHA1_AES:
Dmitry Shmidt807291d2015-01-27 13:40:23 -080078 if (hmac_sha1(key, key_len, buf, len, hash))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070079 return -1;
80 os_memcpy(mic, hash, MD5_MAC_LEN);
81 break;
82#if defined(CONFIG_IEEE80211R) || defined(CONFIG_IEEE80211W)
83 case WPA_KEY_INFO_TYPE_AES_128_CMAC:
84 return omac1_aes_128(key, buf, len, mic);
85#endif /* CONFIG_IEEE80211R || CONFIG_IEEE80211W */
Dmitry Shmidtf21452a2014-02-26 10:55:25 -080086 case WPA_KEY_INFO_TYPE_AKM_DEFINED:
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080087 switch (akmp) {
88#ifdef CONFIG_HS20
89 case WPA_KEY_MGMT_OSEN:
90 return omac1_aes_128(key, buf, len, mic);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -080091#endif /* CONFIG_HS20 */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080092#ifdef CONFIG_SUITEB
93 case WPA_KEY_MGMT_IEEE8021X_SUITE_B:
Dmitry Shmidt807291d2015-01-27 13:40:23 -080094 if (hmac_sha256(key, key_len, buf, len, hash))
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080095 return -1;
96 os_memcpy(mic, hash, MD5_MAC_LEN);
97 break;
98#endif /* CONFIG_SUITEB */
Dmitry Shmidt807291d2015-01-27 13:40:23 -080099#ifdef CONFIG_SUITEB192
100 case WPA_KEY_MGMT_IEEE8021X_SUITE_B_192:
101 if (hmac_sha384(key, key_len, buf, len, hash))
102 return -1;
103 os_memcpy(mic, hash, 24);
104 break;
105#endif /* CONFIG_SUITEB192 */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800106 default:
107 return -1;
108 }
109 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700110 default:
111 return -1;
112 }
113
114 return 0;
115}
116
117
118/**
119 * wpa_pmk_to_ptk - Calculate PTK from PMK, addresses, and nonces
120 * @pmk: Pairwise master key
121 * @pmk_len: Length of PMK
122 * @label: Label to use in derivation
123 * @addr1: AA or SA
124 * @addr2: SA or AA
125 * @nonce1: ANonce or SNonce
126 * @nonce2: SNonce or ANonce
127 * @ptk: Buffer for pairwise transient key
Dmitry Shmidt807291d2015-01-27 13:40:23 -0800128 * @akmp: Negotiated AKM
129 * @cipher: Negotiated pairwise cipher
130 * Returns: 0 on success, -1 on failure
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700131 *
132 * IEEE Std 802.11i-2004 - 8.5.1.2 Pairwise key hierarchy
133 * PTK = PRF-X(PMK, "Pairwise key expansion",
134 * Min(AA, SA) || Max(AA, SA) ||
135 * Min(ANonce, SNonce) || Max(ANonce, SNonce))
136 *
137 * STK = PRF-X(SMK, "Peer key expansion",
138 * Min(MAC_I, MAC_P) || Max(MAC_I, MAC_P) ||
139 * Min(INonce, PNonce) || Max(INonce, PNonce))
140 */
Dmitry Shmidt807291d2015-01-27 13:40:23 -0800141int wpa_pmk_to_ptk(const u8 *pmk, size_t pmk_len, const char *label,
142 const u8 *addr1, const u8 *addr2,
143 const u8 *nonce1, const u8 *nonce2,
144 struct wpa_ptk *ptk, int akmp, int cipher)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700145{
146 u8 data[2 * ETH_ALEN + 2 * WPA_NONCE_LEN];
Dmitry Shmidt807291d2015-01-27 13:40:23 -0800147 u8 tmp[WPA_KCK_MAX_LEN + WPA_KEK_MAX_LEN + WPA_TK_MAX_LEN];
148 size_t ptk_len;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700149
150 if (os_memcmp(addr1, addr2, ETH_ALEN) < 0) {
151 os_memcpy(data, addr1, ETH_ALEN);
152 os_memcpy(data + ETH_ALEN, addr2, ETH_ALEN);
153 } else {
154 os_memcpy(data, addr2, ETH_ALEN);
155 os_memcpy(data + ETH_ALEN, addr1, ETH_ALEN);
156 }
157
158 if (os_memcmp(nonce1, nonce2, WPA_NONCE_LEN) < 0) {
159 os_memcpy(data + 2 * ETH_ALEN, nonce1, WPA_NONCE_LEN);
160 os_memcpy(data + 2 * ETH_ALEN + WPA_NONCE_LEN, nonce2,
161 WPA_NONCE_LEN);
162 } else {
163 os_memcpy(data + 2 * ETH_ALEN, nonce2, WPA_NONCE_LEN);
164 os_memcpy(data + 2 * ETH_ALEN + WPA_NONCE_LEN, nonce1,
165 WPA_NONCE_LEN);
166 }
167
Dmitry Shmidt807291d2015-01-27 13:40:23 -0800168 ptk->kck_len = wpa_kck_len(akmp);
169 ptk->kek_len = wpa_kek_len(akmp);
170 ptk->tk_len = wpa_cipher_key_len(cipher);
171 ptk_len = ptk->kck_len + ptk->kek_len + ptk->tk_len;
172
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700173#ifdef CONFIG_IEEE80211W
Dmitry Shmidt807291d2015-01-27 13:40:23 -0800174 if (wpa_key_mgmt_sha256(akmp))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700175 sha256_prf(pmk, pmk_len, label, data, sizeof(data),
Dmitry Shmidt807291d2015-01-27 13:40:23 -0800176 tmp, ptk_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700177 else
178#endif /* CONFIG_IEEE80211W */
Dmitry Shmidt807291d2015-01-27 13:40:23 -0800179 sha1_prf(pmk, pmk_len, label, data, sizeof(data), tmp, ptk_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700180
181 wpa_printf(MSG_DEBUG, "WPA: PTK derivation - A1=" MACSTR " A2=" MACSTR,
182 MAC2STR(addr1), MAC2STR(addr2));
183 wpa_hexdump(MSG_DEBUG, "WPA: Nonce1", nonce1, WPA_NONCE_LEN);
184 wpa_hexdump(MSG_DEBUG, "WPA: Nonce2", nonce2, WPA_NONCE_LEN);
185 wpa_hexdump_key(MSG_DEBUG, "WPA: PMK", pmk, pmk_len);
Dmitry Shmidt807291d2015-01-27 13:40:23 -0800186 wpa_hexdump_key(MSG_DEBUG, "WPA: PTK", tmp, ptk_len);
187
188 os_memcpy(ptk->kck, tmp, ptk->kck_len);
189 wpa_hexdump_key(MSG_DEBUG, "WPA: KCK", ptk->kck, ptk->kck_len);
190
191 os_memcpy(ptk->kek, tmp + ptk->kck_len, ptk->kek_len);
192 wpa_hexdump_key(MSG_DEBUG, "WPA: KEK", ptk->kek, ptk->kek_len);
193
194 os_memcpy(ptk->tk, tmp + ptk->kck_len + ptk->kek_len, ptk->tk_len);
195 wpa_hexdump_key(MSG_DEBUG, "WPA: TK", ptk->tk, ptk->tk_len);
196
197 os_memset(tmp, 0, sizeof(tmp));
198 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700199}
200
201
202#ifdef CONFIG_IEEE80211R
Dmitry Shmidt807291d2015-01-27 13:40:23 -0800203int wpa_ft_mic(const u8 *kck, size_t kck_len, const u8 *sta_addr,
204 const u8 *ap_addr, u8 transaction_seqnum,
205 const u8 *mdie, size_t mdie_len,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700206 const u8 *ftie, size_t ftie_len,
207 const u8 *rsnie, size_t rsnie_len,
208 const u8 *ric, size_t ric_len, u8 *mic)
209{
Dmitry Shmidtf73259c2015-03-17 11:00:54 -0700210 const u8 *addr[9];
211 size_t len[9];
212 size_t i, num_elem = 0;
213 u8 zero_mic[16];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700214
Dmitry Shmidt807291d2015-01-27 13:40:23 -0800215 if (kck_len != 16) {
216 wpa_printf(MSG_WARNING, "FT: Unsupported KCK length %u",
217 (unsigned int) kck_len);
218 return -1;
219 }
220
Dmitry Shmidtf73259c2015-03-17 11:00:54 -0700221 addr[num_elem] = sta_addr;
222 len[num_elem] = ETH_ALEN;
223 num_elem++;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700224
Dmitry Shmidtf73259c2015-03-17 11:00:54 -0700225 addr[num_elem] = ap_addr;
226 len[num_elem] = ETH_ALEN;
227 num_elem++;
228
229 addr[num_elem] = &transaction_seqnum;
230 len[num_elem] = 1;
231 num_elem++;
232
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700233 if (rsnie) {
Dmitry Shmidtf73259c2015-03-17 11:00:54 -0700234 addr[num_elem] = rsnie;
235 len[num_elem] = rsnie_len;
236 num_elem++;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700237 }
238 if (mdie) {
Dmitry Shmidtf73259c2015-03-17 11:00:54 -0700239 addr[num_elem] = mdie;
240 len[num_elem] = mdie_len;
241 num_elem++;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700242 }
243 if (ftie) {
Dmitry Shmidtf73259c2015-03-17 11:00:54 -0700244 if (ftie_len < 2 + sizeof(struct rsn_ftie))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700245 return -1;
Dmitry Shmidtf73259c2015-03-17 11:00:54 -0700246
247 /* IE hdr and mic_control */
248 addr[num_elem] = ftie;
249 len[num_elem] = 2 + 2;
250 num_elem++;
251
252 /* MIC field with all zeros */
253 os_memset(zero_mic, 0, sizeof(zero_mic));
254 addr[num_elem] = zero_mic;
255 len[num_elem] = sizeof(zero_mic);
256 num_elem++;
257
258 /* Rest of FTIE */
259 addr[num_elem] = ftie + 2 + 2 + 16;
260 len[num_elem] = ftie_len - (2 + 2 + 16);
261 num_elem++;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700262 }
263 if (ric) {
Dmitry Shmidtf73259c2015-03-17 11:00:54 -0700264 addr[num_elem] = ric;
265 len[num_elem] = ric_len;
266 num_elem++;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700267 }
268
Dmitry Shmidtf73259c2015-03-17 11:00:54 -0700269 for (i = 0; i < num_elem; i++)
270 wpa_hexdump(MSG_MSGDUMP, "FT: MIC data", addr[i], len[i]);
271 if (omac1_aes_128_vector(kck, num_elem, addr, len, mic))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700272 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700273
274 return 0;
275}
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800276
277
278static int wpa_ft_parse_ftie(const u8 *ie, size_t ie_len,
279 struct wpa_ft_ies *parse)
280{
281 const u8 *end, *pos;
282
283 parse->ftie = ie;
284 parse->ftie_len = ie_len;
285
286 pos = ie + sizeof(struct rsn_ftie);
287 end = ie + ie_len;
288
289 while (pos + 2 <= end && pos + 2 + pos[1] <= end) {
290 switch (pos[0]) {
291 case FTIE_SUBELEM_R1KH_ID:
292 if (pos[1] != FT_R1KH_ID_LEN) {
293 wpa_printf(MSG_DEBUG, "FT: Invalid R1KH-ID "
294 "length in FTIE: %d", pos[1]);
295 return -1;
296 }
297 parse->r1kh_id = pos + 2;
298 break;
299 case FTIE_SUBELEM_GTK:
300 parse->gtk = pos + 2;
301 parse->gtk_len = pos[1];
302 break;
303 case FTIE_SUBELEM_R0KH_ID:
304 if (pos[1] < 1 || pos[1] > FT_R0KH_ID_MAX_LEN) {
305 wpa_printf(MSG_DEBUG, "FT: Invalid R0KH-ID "
306 "length in FTIE: %d", pos[1]);
307 return -1;
308 }
309 parse->r0kh_id = pos + 2;
310 parse->r0kh_id_len = pos[1];
311 break;
312#ifdef CONFIG_IEEE80211W
313 case FTIE_SUBELEM_IGTK:
314 parse->igtk = pos + 2;
315 parse->igtk_len = pos[1];
316 break;
317#endif /* CONFIG_IEEE80211W */
318 }
319
320 pos += 2 + pos[1];
321 }
322
323 return 0;
324}
325
326
327int wpa_ft_parse_ies(const u8 *ies, size_t ies_len,
328 struct wpa_ft_ies *parse)
329{
330 const u8 *end, *pos;
331 struct wpa_ie_data data;
332 int ret;
333 const struct rsn_ftie *ftie;
334 int prot_ie_count = 0;
335
336 os_memset(parse, 0, sizeof(*parse));
337 if (ies == NULL)
338 return 0;
339
340 pos = ies;
341 end = ies + ies_len;
342 while (pos + 2 <= end && pos + 2 + pos[1] <= end) {
343 switch (pos[0]) {
344 case WLAN_EID_RSN:
345 parse->rsn = pos + 2;
346 parse->rsn_len = pos[1];
347 ret = wpa_parse_wpa_ie_rsn(parse->rsn - 2,
348 parse->rsn_len + 2,
349 &data);
350 if (ret < 0) {
351 wpa_printf(MSG_DEBUG, "FT: Failed to parse "
352 "RSN IE: %d", ret);
353 return -1;
354 }
355 if (data.num_pmkid == 1 && data.pmkid)
356 parse->rsn_pmkid = data.pmkid;
357 break;
358 case WLAN_EID_MOBILITY_DOMAIN:
359 parse->mdie = pos + 2;
360 parse->mdie_len = pos[1];
361 break;
362 case WLAN_EID_FAST_BSS_TRANSITION:
363 if (pos[1] < sizeof(*ftie))
364 return -1;
365 ftie = (const struct rsn_ftie *) (pos + 2);
366 prot_ie_count = ftie->mic_control[1];
367 if (wpa_ft_parse_ftie(pos + 2, pos[1], parse) < 0)
368 return -1;
369 break;
370 case WLAN_EID_TIMEOUT_INTERVAL:
371 parse->tie = pos + 2;
372 parse->tie_len = pos[1];
373 break;
374 case WLAN_EID_RIC_DATA:
375 if (parse->ric == NULL)
376 parse->ric = pos;
377 break;
378 }
379
380 pos += 2 + pos[1];
381 }
382
383 if (prot_ie_count == 0)
384 return 0; /* no MIC */
385
386 /*
387 * Check that the protected IE count matches with IEs included in the
388 * frame.
389 */
390 if (parse->rsn)
391 prot_ie_count--;
392 if (parse->mdie)
393 prot_ie_count--;
394 if (parse->ftie)
395 prot_ie_count--;
396 if (prot_ie_count < 0) {
397 wpa_printf(MSG_DEBUG, "FT: Some required IEs not included in "
398 "the protected IE count");
399 return -1;
400 }
401
402 if (prot_ie_count == 0 && parse->ric) {
403 wpa_printf(MSG_DEBUG, "FT: RIC IE(s) in the frame, but not "
404 "included in protected IE count");
405 return -1;
406 }
407
408 /* Determine the end of the RIC IE(s) */
409 pos = parse->ric;
410 while (pos && pos + 2 <= end && pos + 2 + pos[1] <= end &&
411 prot_ie_count) {
412 prot_ie_count--;
413 pos += 2 + pos[1];
414 }
415 parse->ric_len = pos - parse->ric;
416 if (prot_ie_count) {
417 wpa_printf(MSG_DEBUG, "FT: %d protected IEs missing from "
418 "frame", (int) prot_ie_count);
419 return -1;
420 }
421
422 return 0;
423}
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700424#endif /* CONFIG_IEEE80211R */
425
426
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700427static int rsn_selector_to_bitfield(const u8 *s)
428{
429 if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_NONE)
430 return WPA_CIPHER_NONE;
431 if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_WEP40)
432 return WPA_CIPHER_WEP40;
433 if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_TKIP)
434 return WPA_CIPHER_TKIP;
435 if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_CCMP)
436 return WPA_CIPHER_CCMP;
437 if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_WEP104)
438 return WPA_CIPHER_WEP104;
439#ifdef CONFIG_IEEE80211W
440 if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_AES_128_CMAC)
441 return WPA_CIPHER_AES_128_CMAC;
442#endif /* CONFIG_IEEE80211W */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700443 if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_GCMP)
444 return WPA_CIPHER_GCMP;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800445 if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_CCMP_256)
446 return WPA_CIPHER_CCMP_256;
447 if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_GCMP_256)
448 return WPA_CIPHER_GCMP_256;
449 if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_BIP_GMAC_128)
450 return WPA_CIPHER_BIP_GMAC_128;
451 if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_BIP_GMAC_256)
452 return WPA_CIPHER_BIP_GMAC_256;
453 if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_BIP_CMAC_256)
454 return WPA_CIPHER_BIP_CMAC_256;
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -0700455 if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_NO_GROUP_ADDRESSED)
456 return WPA_CIPHER_GTK_NOT_USED;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700457 return 0;
458}
459
460
461static int rsn_key_mgmt_to_bitfield(const u8 *s)
462{
463 if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_UNSPEC_802_1X)
464 return WPA_KEY_MGMT_IEEE8021X;
465 if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X)
466 return WPA_KEY_MGMT_PSK;
467#ifdef CONFIG_IEEE80211R
468 if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_FT_802_1X)
469 return WPA_KEY_MGMT_FT_IEEE8021X;
470 if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_FT_PSK)
471 return WPA_KEY_MGMT_FT_PSK;
472#endif /* CONFIG_IEEE80211R */
473#ifdef CONFIG_IEEE80211W
474 if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_802_1X_SHA256)
475 return WPA_KEY_MGMT_IEEE8021X_SHA256;
476 if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_PSK_SHA256)
477 return WPA_KEY_MGMT_PSK_SHA256;
478#endif /* CONFIG_IEEE80211W */
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800479#ifdef CONFIG_SAE
480 if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_SAE)
481 return WPA_KEY_MGMT_SAE;
482 if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_FT_SAE)
483 return WPA_KEY_MGMT_FT_SAE;
484#endif /* CONFIG_SAE */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800485 if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_802_1X_SUITE_B)
486 return WPA_KEY_MGMT_IEEE8021X_SUITE_B;
Dmitry Shmidt807291d2015-01-27 13:40:23 -0800487 if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_802_1X_SUITE_B_192)
488 return WPA_KEY_MGMT_IEEE8021X_SUITE_B_192;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700489 return 0;
490}
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700491
492
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -0700493static int wpa_cipher_valid_group(int cipher)
494{
495 return wpa_cipher_valid_pairwise(cipher) ||
496 cipher == WPA_CIPHER_WEP104 ||
497 cipher == WPA_CIPHER_WEP40 ||
498 cipher == WPA_CIPHER_GTK_NOT_USED;
499}
500
501
502#ifdef CONFIG_IEEE80211W
503int wpa_cipher_valid_mgmt_group(int cipher)
504{
505 return cipher == WPA_CIPHER_AES_128_CMAC ||
506 cipher == WPA_CIPHER_BIP_GMAC_128 ||
507 cipher == WPA_CIPHER_BIP_GMAC_256 ||
508 cipher == WPA_CIPHER_BIP_CMAC_256;
509}
510#endif /* CONFIG_IEEE80211W */
511
512
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700513/**
514 * wpa_parse_wpa_ie_rsn - Parse RSN IE
515 * @rsn_ie: Buffer containing RSN IE
516 * @rsn_ie_len: RSN IE buffer length (including IE number and length octets)
517 * @data: Pointer to structure that will be filled in with parsed data
518 * Returns: 0 on success, <0 on failure
519 */
520int wpa_parse_wpa_ie_rsn(const u8 *rsn_ie, size_t rsn_ie_len,
521 struct wpa_ie_data *data)
522{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700523 const struct rsn_ie_hdr *hdr;
524 const u8 *pos;
525 int left;
526 int i, count;
527
528 os_memset(data, 0, sizeof(*data));
529 data->proto = WPA_PROTO_RSN;
530 data->pairwise_cipher = WPA_CIPHER_CCMP;
531 data->group_cipher = WPA_CIPHER_CCMP;
532 data->key_mgmt = WPA_KEY_MGMT_IEEE8021X;
533 data->capabilities = 0;
534 data->pmkid = NULL;
535 data->num_pmkid = 0;
536#ifdef CONFIG_IEEE80211W
537 data->mgmt_group_cipher = WPA_CIPHER_AES_128_CMAC;
538#else /* CONFIG_IEEE80211W */
539 data->mgmt_group_cipher = 0;
540#endif /* CONFIG_IEEE80211W */
541
542 if (rsn_ie_len == 0) {
543 /* No RSN IE - fail silently */
544 return -1;
545 }
546
547 if (rsn_ie_len < sizeof(struct rsn_ie_hdr)) {
548 wpa_printf(MSG_DEBUG, "%s: ie len too short %lu",
549 __func__, (unsigned long) rsn_ie_len);
550 return -1;
551 }
552
553 hdr = (const struct rsn_ie_hdr *) rsn_ie;
554
555 if (hdr->elem_id != WLAN_EID_RSN ||
556 hdr->len != rsn_ie_len - 2 ||
557 WPA_GET_LE16(hdr->version) != RSN_VERSION) {
558 wpa_printf(MSG_DEBUG, "%s: malformed ie or unknown version",
559 __func__);
560 return -2;
561 }
562
563 pos = (const u8 *) (hdr + 1);
564 left = rsn_ie_len - sizeof(*hdr);
565
566 if (left >= RSN_SELECTOR_LEN) {
567 data->group_cipher = rsn_selector_to_bitfield(pos);
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -0700568 if (!wpa_cipher_valid_group(data->group_cipher)) {
569 wpa_printf(MSG_DEBUG, "%s: invalid group cipher 0x%x",
570 __func__, data->group_cipher);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700571 return -1;
572 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700573 pos += RSN_SELECTOR_LEN;
574 left -= RSN_SELECTOR_LEN;
575 } else if (left > 0) {
576 wpa_printf(MSG_DEBUG, "%s: ie length mismatch, %u too much",
577 __func__, left);
578 return -3;
579 }
580
581 if (left >= 2) {
582 data->pairwise_cipher = 0;
583 count = WPA_GET_LE16(pos);
584 pos += 2;
585 left -= 2;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800586 if (count == 0 || count > left / RSN_SELECTOR_LEN) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700587 wpa_printf(MSG_DEBUG, "%s: ie count botch (pairwise), "
588 "count %u left %u", __func__, count, left);
589 return -4;
590 }
591 for (i = 0; i < count; i++) {
592 data->pairwise_cipher |= rsn_selector_to_bitfield(pos);
593 pos += RSN_SELECTOR_LEN;
594 left -= RSN_SELECTOR_LEN;
595 }
596#ifdef CONFIG_IEEE80211W
597 if (data->pairwise_cipher & WPA_CIPHER_AES_128_CMAC) {
598 wpa_printf(MSG_DEBUG, "%s: AES-128-CMAC used as "
599 "pairwise cipher", __func__);
600 return -1;
601 }
602#endif /* CONFIG_IEEE80211W */
603 } else if (left == 1) {
604 wpa_printf(MSG_DEBUG, "%s: ie too short (for key mgmt)",
605 __func__);
606 return -5;
607 }
608
609 if (left >= 2) {
610 data->key_mgmt = 0;
611 count = WPA_GET_LE16(pos);
612 pos += 2;
613 left -= 2;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800614 if (count == 0 || count > left / RSN_SELECTOR_LEN) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700615 wpa_printf(MSG_DEBUG, "%s: ie count botch (key mgmt), "
616 "count %u left %u", __func__, count, left);
617 return -6;
618 }
619 for (i = 0; i < count; i++) {
620 data->key_mgmt |= rsn_key_mgmt_to_bitfield(pos);
621 pos += RSN_SELECTOR_LEN;
622 left -= RSN_SELECTOR_LEN;
623 }
624 } else if (left == 1) {
625 wpa_printf(MSG_DEBUG, "%s: ie too short (for capabilities)",
626 __func__);
627 return -7;
628 }
629
630 if (left >= 2) {
631 data->capabilities = WPA_GET_LE16(pos);
632 pos += 2;
633 left -= 2;
634 }
635
636 if (left >= 2) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800637 u16 num_pmkid = WPA_GET_LE16(pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700638 pos += 2;
639 left -= 2;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800640 if (num_pmkid > (unsigned int) left / PMKID_LEN) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700641 wpa_printf(MSG_DEBUG, "%s: PMKID underflow "
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800642 "(num_pmkid=%u left=%d)",
643 __func__, num_pmkid, left);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700644 data->num_pmkid = 0;
645 return -9;
646 } else {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800647 data->num_pmkid = num_pmkid;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700648 data->pmkid = pos;
649 pos += data->num_pmkid * PMKID_LEN;
650 left -= data->num_pmkid * PMKID_LEN;
651 }
652 }
653
654#ifdef CONFIG_IEEE80211W
655 if (left >= 4) {
656 data->mgmt_group_cipher = rsn_selector_to_bitfield(pos);
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -0700657 if (!wpa_cipher_valid_mgmt_group(data->mgmt_group_cipher)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700658 wpa_printf(MSG_DEBUG, "%s: Unsupported management "
659 "group cipher 0x%x", __func__,
660 data->mgmt_group_cipher);
661 return -10;
662 }
663 pos += RSN_SELECTOR_LEN;
664 left -= RSN_SELECTOR_LEN;
665 }
666#endif /* CONFIG_IEEE80211W */
667
668 if (left > 0) {
Dmitry Shmidt7d5c8f22014-03-03 13:53:28 -0800669 wpa_hexdump(MSG_DEBUG,
670 "wpa_parse_wpa_ie_rsn: ignore trailing bytes",
671 pos, left);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700672 }
673
674 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700675}
676
677
678static int wpa_selector_to_bitfield(const u8 *s)
679{
680 if (RSN_SELECTOR_GET(s) == WPA_CIPHER_SUITE_NONE)
681 return WPA_CIPHER_NONE;
682 if (RSN_SELECTOR_GET(s) == WPA_CIPHER_SUITE_WEP40)
683 return WPA_CIPHER_WEP40;
684 if (RSN_SELECTOR_GET(s) == WPA_CIPHER_SUITE_TKIP)
685 return WPA_CIPHER_TKIP;
686 if (RSN_SELECTOR_GET(s) == WPA_CIPHER_SUITE_CCMP)
687 return WPA_CIPHER_CCMP;
688 if (RSN_SELECTOR_GET(s) == WPA_CIPHER_SUITE_WEP104)
689 return WPA_CIPHER_WEP104;
690 return 0;
691}
692
693
694static int wpa_key_mgmt_to_bitfield(const u8 *s)
695{
696 if (RSN_SELECTOR_GET(s) == WPA_AUTH_KEY_MGMT_UNSPEC_802_1X)
697 return WPA_KEY_MGMT_IEEE8021X;
698 if (RSN_SELECTOR_GET(s) == WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X)
699 return WPA_KEY_MGMT_PSK;
700 if (RSN_SELECTOR_GET(s) == WPA_AUTH_KEY_MGMT_NONE)
701 return WPA_KEY_MGMT_WPA_NONE;
702 return 0;
703}
704
705
706int wpa_parse_wpa_ie_wpa(const u8 *wpa_ie, size_t wpa_ie_len,
707 struct wpa_ie_data *data)
708{
709 const struct wpa_ie_hdr *hdr;
710 const u8 *pos;
711 int left;
712 int i, count;
713
714 os_memset(data, 0, sizeof(*data));
715 data->proto = WPA_PROTO_WPA;
716 data->pairwise_cipher = WPA_CIPHER_TKIP;
717 data->group_cipher = WPA_CIPHER_TKIP;
718 data->key_mgmt = WPA_KEY_MGMT_IEEE8021X;
719 data->capabilities = 0;
720 data->pmkid = NULL;
721 data->num_pmkid = 0;
722 data->mgmt_group_cipher = 0;
723
724 if (wpa_ie_len == 0) {
725 /* No WPA IE - fail silently */
726 return -1;
727 }
728
729 if (wpa_ie_len < sizeof(struct wpa_ie_hdr)) {
730 wpa_printf(MSG_DEBUG, "%s: ie len too short %lu",
731 __func__, (unsigned long) wpa_ie_len);
732 return -1;
733 }
734
735 hdr = (const struct wpa_ie_hdr *) wpa_ie;
736
737 if (hdr->elem_id != WLAN_EID_VENDOR_SPECIFIC ||
738 hdr->len != wpa_ie_len - 2 ||
739 RSN_SELECTOR_GET(hdr->oui) != WPA_OUI_TYPE ||
740 WPA_GET_LE16(hdr->version) != WPA_VERSION) {
741 wpa_printf(MSG_DEBUG, "%s: malformed ie or unknown version",
742 __func__);
743 return -2;
744 }
745
746 pos = (const u8 *) (hdr + 1);
747 left = wpa_ie_len - sizeof(*hdr);
748
749 if (left >= WPA_SELECTOR_LEN) {
750 data->group_cipher = wpa_selector_to_bitfield(pos);
751 pos += WPA_SELECTOR_LEN;
752 left -= WPA_SELECTOR_LEN;
753 } else if (left > 0) {
754 wpa_printf(MSG_DEBUG, "%s: ie length mismatch, %u too much",
755 __func__, left);
756 return -3;
757 }
758
759 if (left >= 2) {
760 data->pairwise_cipher = 0;
761 count = WPA_GET_LE16(pos);
762 pos += 2;
763 left -= 2;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800764 if (count == 0 || count > left / WPA_SELECTOR_LEN) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700765 wpa_printf(MSG_DEBUG, "%s: ie count botch (pairwise), "
766 "count %u left %u", __func__, count, left);
767 return -4;
768 }
769 for (i = 0; i < count; i++) {
770 data->pairwise_cipher |= wpa_selector_to_bitfield(pos);
771 pos += WPA_SELECTOR_LEN;
772 left -= WPA_SELECTOR_LEN;
773 }
774 } else if (left == 1) {
775 wpa_printf(MSG_DEBUG, "%s: ie too short (for key mgmt)",
776 __func__);
777 return -5;
778 }
779
780 if (left >= 2) {
781 data->key_mgmt = 0;
782 count = WPA_GET_LE16(pos);
783 pos += 2;
784 left -= 2;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800785 if (count == 0 || count > left / WPA_SELECTOR_LEN) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700786 wpa_printf(MSG_DEBUG, "%s: ie count botch (key mgmt), "
787 "count %u left %u", __func__, count, left);
788 return -6;
789 }
790 for (i = 0; i < count; i++) {
791 data->key_mgmt |= wpa_key_mgmt_to_bitfield(pos);
792 pos += WPA_SELECTOR_LEN;
793 left -= WPA_SELECTOR_LEN;
794 }
795 } else if (left == 1) {
796 wpa_printf(MSG_DEBUG, "%s: ie too short (for capabilities)",
797 __func__);
798 return -7;
799 }
800
801 if (left >= 2) {
802 data->capabilities = WPA_GET_LE16(pos);
803 pos += 2;
804 left -= 2;
805 }
806
807 if (left > 0) {
Dmitry Shmidt7d5c8f22014-03-03 13:53:28 -0800808 wpa_hexdump(MSG_DEBUG,
809 "wpa_parse_wpa_ie_wpa: ignore trailing bytes",
810 pos, left);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700811 }
812
813 return 0;
814}
815
816
817#ifdef CONFIG_IEEE80211R
818
819/**
820 * wpa_derive_pmk_r0 - Derive PMK-R0 and PMKR0Name
821 *
822 * IEEE Std 802.11r-2008 - 8.5.1.5.3
823 */
824void wpa_derive_pmk_r0(const u8 *xxkey, size_t xxkey_len,
825 const u8 *ssid, size_t ssid_len,
826 const u8 *mdid, const u8 *r0kh_id, size_t r0kh_id_len,
827 const u8 *s0kh_id, u8 *pmk_r0, u8 *pmk_r0_name)
828{
829 u8 buf[1 + WPA_MAX_SSID_LEN + MOBILITY_DOMAIN_ID_LEN + 1 +
830 FT_R0KH_ID_MAX_LEN + ETH_ALEN];
831 u8 *pos, r0_key_data[48], hash[32];
832 const u8 *addr[2];
833 size_t len[2];
834
835 /*
836 * R0-Key-Data = KDF-384(XXKey, "FT-R0",
837 * SSIDlength || SSID || MDID || R0KHlength ||
838 * R0KH-ID || S0KH-ID)
839 * XXKey is either the second 256 bits of MSK or PSK.
840 * PMK-R0 = L(R0-Key-Data, 0, 256)
841 * PMK-R0Name-Salt = L(R0-Key-Data, 256, 128)
842 */
843 if (ssid_len > WPA_MAX_SSID_LEN || r0kh_id_len > FT_R0KH_ID_MAX_LEN)
844 return;
845 pos = buf;
846 *pos++ = ssid_len;
847 os_memcpy(pos, ssid, ssid_len);
848 pos += ssid_len;
849 os_memcpy(pos, mdid, MOBILITY_DOMAIN_ID_LEN);
850 pos += MOBILITY_DOMAIN_ID_LEN;
851 *pos++ = r0kh_id_len;
852 os_memcpy(pos, r0kh_id, r0kh_id_len);
853 pos += r0kh_id_len;
854 os_memcpy(pos, s0kh_id, ETH_ALEN);
855 pos += ETH_ALEN;
856
857 sha256_prf(xxkey, xxkey_len, "FT-R0", buf, pos - buf,
858 r0_key_data, sizeof(r0_key_data));
859 os_memcpy(pmk_r0, r0_key_data, PMK_LEN);
860
861 /*
862 * PMKR0Name = Truncate-128(SHA-256("FT-R0N" || PMK-R0Name-Salt)
863 */
864 addr[0] = (const u8 *) "FT-R0N";
865 len[0] = 6;
866 addr[1] = r0_key_data + PMK_LEN;
867 len[1] = 16;
868
869 sha256_vector(2, addr, len, hash);
870 os_memcpy(pmk_r0_name, hash, WPA_PMK_NAME_LEN);
871}
872
873
874/**
875 * wpa_derive_pmk_r1_name - Derive PMKR1Name
876 *
877 * IEEE Std 802.11r-2008 - 8.5.1.5.4
878 */
879void wpa_derive_pmk_r1_name(const u8 *pmk_r0_name, const u8 *r1kh_id,
880 const u8 *s1kh_id, u8 *pmk_r1_name)
881{
882 u8 hash[32];
883 const u8 *addr[4];
884 size_t len[4];
885
886 /*
887 * PMKR1Name = Truncate-128(SHA-256("FT-R1N" || PMKR0Name ||
888 * R1KH-ID || S1KH-ID))
889 */
890 addr[0] = (const u8 *) "FT-R1N";
891 len[0] = 6;
892 addr[1] = pmk_r0_name;
893 len[1] = WPA_PMK_NAME_LEN;
894 addr[2] = r1kh_id;
895 len[2] = FT_R1KH_ID_LEN;
896 addr[3] = s1kh_id;
897 len[3] = ETH_ALEN;
898
899 sha256_vector(4, addr, len, hash);
900 os_memcpy(pmk_r1_name, hash, WPA_PMK_NAME_LEN);
901}
902
903
904/**
905 * wpa_derive_pmk_r1 - Derive PMK-R1 and PMKR1Name from PMK-R0
906 *
907 * IEEE Std 802.11r-2008 - 8.5.1.5.4
908 */
909void wpa_derive_pmk_r1(const u8 *pmk_r0, const u8 *pmk_r0_name,
910 const u8 *r1kh_id, const u8 *s1kh_id,
911 u8 *pmk_r1, u8 *pmk_r1_name)
912{
913 u8 buf[FT_R1KH_ID_LEN + ETH_ALEN];
914 u8 *pos;
915
916 /* PMK-R1 = KDF-256(PMK-R0, "FT-R1", R1KH-ID || S1KH-ID) */
917 pos = buf;
918 os_memcpy(pos, r1kh_id, FT_R1KH_ID_LEN);
919 pos += FT_R1KH_ID_LEN;
920 os_memcpy(pos, s1kh_id, ETH_ALEN);
921 pos += ETH_ALEN;
922
923 sha256_prf(pmk_r0, PMK_LEN, "FT-R1", buf, pos - buf, pmk_r1, PMK_LEN);
924
925 wpa_derive_pmk_r1_name(pmk_r0_name, r1kh_id, s1kh_id, pmk_r1_name);
926}
927
928
929/**
930 * wpa_pmk_r1_to_ptk - Derive PTK and PTKName from PMK-R1
931 *
932 * IEEE Std 802.11r-2008 - 8.5.1.5.5
933 */
Dmitry Shmidt807291d2015-01-27 13:40:23 -0800934int wpa_pmk_r1_to_ptk(const u8 *pmk_r1, const u8 *snonce, const u8 *anonce,
935 const u8 *sta_addr, const u8 *bssid,
936 const u8 *pmk_r1_name,
937 struct wpa_ptk *ptk, u8 *ptk_name, int akmp, int cipher)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700938{
939 u8 buf[2 * WPA_NONCE_LEN + 2 * ETH_ALEN];
940 u8 *pos, hash[32];
941 const u8 *addr[6];
942 size_t len[6];
Dmitry Shmidt807291d2015-01-27 13:40:23 -0800943 u8 tmp[WPA_KCK_MAX_LEN + WPA_KEK_MAX_LEN + WPA_TK_MAX_LEN];
944 size_t ptk_len;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700945
946 /*
947 * PTK = KDF-PTKLen(PMK-R1, "FT-PTK", SNonce || ANonce ||
948 * BSSID || STA-ADDR)
949 */
950 pos = buf;
951 os_memcpy(pos, snonce, WPA_NONCE_LEN);
952 pos += WPA_NONCE_LEN;
953 os_memcpy(pos, anonce, WPA_NONCE_LEN);
954 pos += WPA_NONCE_LEN;
955 os_memcpy(pos, bssid, ETH_ALEN);
956 pos += ETH_ALEN;
957 os_memcpy(pos, sta_addr, ETH_ALEN);
958 pos += ETH_ALEN;
959
Dmitry Shmidt807291d2015-01-27 13:40:23 -0800960 ptk->kck_len = wpa_kck_len(akmp);
961 ptk->kek_len = wpa_kek_len(akmp);
962 ptk->tk_len = wpa_cipher_key_len(cipher);
963 ptk_len = ptk->kck_len + ptk->kek_len + ptk->tk_len;
964
965 sha256_prf(pmk_r1, PMK_LEN, "FT-PTK", buf, pos - buf, tmp, ptk_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700966
967 /*
968 * PTKName = Truncate-128(SHA-256(PMKR1Name || "FT-PTKN" || SNonce ||
969 * ANonce || BSSID || STA-ADDR))
970 */
971 addr[0] = pmk_r1_name;
972 len[0] = WPA_PMK_NAME_LEN;
973 addr[1] = (const u8 *) "FT-PTKN";
974 len[1] = 7;
975 addr[2] = snonce;
976 len[2] = WPA_NONCE_LEN;
977 addr[3] = anonce;
978 len[3] = WPA_NONCE_LEN;
979 addr[4] = bssid;
980 len[4] = ETH_ALEN;
981 addr[5] = sta_addr;
982 len[5] = ETH_ALEN;
983
984 sha256_vector(6, addr, len, hash);
985 os_memcpy(ptk_name, hash, WPA_PMK_NAME_LEN);
Dmitry Shmidt807291d2015-01-27 13:40:23 -0800986
987 os_memcpy(ptk->kck, tmp, ptk->kck_len);
988 os_memcpy(ptk->kek, tmp + ptk->kck_len, ptk->kek_len);
989 os_memcpy(ptk->tk, tmp + ptk->kck_len + ptk->kek_len, ptk->tk_len);
990
991 wpa_hexdump_key(MSG_DEBUG, "FT: KCK", ptk->kck, ptk->kck_len);
992 wpa_hexdump_key(MSG_DEBUG, "FT: KEK", ptk->kek, ptk->kek_len);
993 wpa_hexdump_key(MSG_DEBUG, "FT: TK", ptk->tk, ptk->tk_len);
994 wpa_hexdump(MSG_DEBUG, "FT: PTKName", ptk_name, WPA_PMK_NAME_LEN);
995
996 os_memset(tmp, 0, sizeof(tmp));
997
998 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700999}
1000
1001#endif /* CONFIG_IEEE80211R */
1002
1003
1004/**
1005 * rsn_pmkid - Calculate PMK identifier
1006 * @pmk: Pairwise master key
1007 * @pmk_len: Length of pmk in bytes
1008 * @aa: Authenticator address
1009 * @spa: Supplicant address
1010 * @pmkid: Buffer for PMKID
1011 * @use_sha256: Whether to use SHA256-based KDF
1012 *
1013 * IEEE Std 802.11i-2004 - 8.5.1.2 Pairwise key hierarchy
1014 * PMKID = HMAC-SHA1-128(PMK, "PMK Name" || AA || SPA)
1015 */
1016void rsn_pmkid(const u8 *pmk, size_t pmk_len, const u8 *aa, const u8 *spa,
1017 u8 *pmkid, int use_sha256)
1018{
1019 char *title = "PMK Name";
1020 const u8 *addr[3];
1021 const size_t len[3] = { 8, ETH_ALEN, ETH_ALEN };
1022 unsigned char hash[SHA256_MAC_LEN];
1023
1024 addr[0] = (u8 *) title;
1025 addr[1] = aa;
1026 addr[2] = spa;
1027
1028#ifdef CONFIG_IEEE80211W
1029 if (use_sha256)
1030 hmac_sha256_vector(pmk, pmk_len, 3, addr, len, hash);
1031 else
1032#endif /* CONFIG_IEEE80211W */
1033 hmac_sha1_vector(pmk, pmk_len, 3, addr, len, hash);
1034 os_memcpy(pmkid, hash, PMKID_LEN);
1035}
1036
1037
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001038#ifdef CONFIG_SUITEB
1039/**
1040 * rsn_pmkid_suite_b - Calculate PMK identifier for Suite B AKM
1041 * @kck: Key confirmation key
1042 * @kck_len: Length of kck in bytes
1043 * @aa: Authenticator address
1044 * @spa: Supplicant address
1045 * @pmkid: Buffer for PMKID
1046 * Returns: 0 on success, -1 on failure
1047 *
1048 * IEEE Std 802.11ac-2013 - 11.6.1.3 Pairwise key hierarchy
1049 * PMKID = Truncate(HMAC-SHA-256(KCK, "PMK Name" || AA || SPA))
1050 */
1051int rsn_pmkid_suite_b(const u8 *kck, size_t kck_len, const u8 *aa,
1052 const u8 *spa, u8 *pmkid)
1053{
1054 char *title = "PMK Name";
1055 const u8 *addr[3];
1056 const size_t len[3] = { 8, ETH_ALEN, ETH_ALEN };
1057 unsigned char hash[SHA256_MAC_LEN];
1058
1059 addr[0] = (u8 *) title;
1060 addr[1] = aa;
1061 addr[2] = spa;
1062
1063 if (hmac_sha256_vector(kck, kck_len, 3, addr, len, hash) < 0)
1064 return -1;
1065 os_memcpy(pmkid, hash, PMKID_LEN);
1066 return 0;
1067}
1068#endif /* CONFIG_SUITEB */
1069
1070
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001071#ifdef CONFIG_SUITEB192
1072/**
1073 * rsn_pmkid_suite_b_192 - Calculate PMK identifier for Suite B AKM
1074 * @kck: Key confirmation key
1075 * @kck_len: Length of kck in bytes
1076 * @aa: Authenticator address
1077 * @spa: Supplicant address
1078 * @pmkid: Buffer for PMKID
1079 * Returns: 0 on success, -1 on failure
1080 *
1081 * IEEE Std 802.11ac-2013 - 11.6.1.3 Pairwise key hierarchy
1082 * PMKID = Truncate(HMAC-SHA-384(KCK, "PMK Name" || AA || SPA))
1083 */
1084int rsn_pmkid_suite_b_192(const u8 *kck, size_t kck_len, const u8 *aa,
1085 const u8 *spa, u8 *pmkid)
1086{
1087 char *title = "PMK Name";
1088 const u8 *addr[3];
1089 const size_t len[3] = { 8, ETH_ALEN, ETH_ALEN };
1090 unsigned char hash[SHA384_MAC_LEN];
1091
1092 addr[0] = (u8 *) title;
1093 addr[1] = aa;
1094 addr[2] = spa;
1095
1096 if (hmac_sha384_vector(kck, kck_len, 3, addr, len, hash) < 0)
1097 return -1;
1098 os_memcpy(pmkid, hash, PMKID_LEN);
1099 return 0;
1100}
1101#endif /* CONFIG_SUITEB192 */
1102
1103
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001104/**
1105 * wpa_cipher_txt - Convert cipher suite to a text string
1106 * @cipher: Cipher suite (WPA_CIPHER_* enum)
1107 * Returns: Pointer to a text string of the cipher suite name
1108 */
1109const char * wpa_cipher_txt(int cipher)
1110{
1111 switch (cipher) {
1112 case WPA_CIPHER_NONE:
1113 return "NONE";
1114 case WPA_CIPHER_WEP40:
1115 return "WEP-40";
1116 case WPA_CIPHER_WEP104:
1117 return "WEP-104";
1118 case WPA_CIPHER_TKIP:
1119 return "TKIP";
1120 case WPA_CIPHER_CCMP:
1121 return "CCMP";
1122 case WPA_CIPHER_CCMP | WPA_CIPHER_TKIP:
1123 return "CCMP+TKIP";
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001124 case WPA_CIPHER_GCMP:
1125 return "GCMP";
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001126 case WPA_CIPHER_GCMP_256:
1127 return "GCMP-256";
1128 case WPA_CIPHER_CCMP_256:
1129 return "CCMP-256";
1130 case WPA_CIPHER_GTK_NOT_USED:
1131 return "GTK_NOT_USED";
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001132 default:
1133 return "UNKNOWN";
1134 }
1135}
1136
1137
1138/**
1139 * wpa_key_mgmt_txt - Convert key management suite to a text string
1140 * @key_mgmt: Key management suite (WPA_KEY_MGMT_* enum)
1141 * @proto: WPA/WPA2 version (WPA_PROTO_*)
1142 * Returns: Pointer to a text string of the key management suite name
1143 */
1144const char * wpa_key_mgmt_txt(int key_mgmt, int proto)
1145{
1146 switch (key_mgmt) {
1147 case WPA_KEY_MGMT_IEEE8021X:
1148 if (proto == (WPA_PROTO_RSN | WPA_PROTO_WPA))
1149 return "WPA2+WPA/IEEE 802.1X/EAP";
1150 return proto == WPA_PROTO_RSN ?
1151 "WPA2/IEEE 802.1X/EAP" : "WPA/IEEE 802.1X/EAP";
1152 case WPA_KEY_MGMT_PSK:
1153 if (proto == (WPA_PROTO_RSN | WPA_PROTO_WPA))
1154 return "WPA2-PSK+WPA-PSK";
1155 return proto == WPA_PROTO_RSN ?
1156 "WPA2-PSK" : "WPA-PSK";
1157 case WPA_KEY_MGMT_NONE:
1158 return "NONE";
1159 case WPA_KEY_MGMT_IEEE8021X_NO_WPA:
1160 return "IEEE 802.1X (no WPA)";
1161#ifdef CONFIG_IEEE80211R
1162 case WPA_KEY_MGMT_FT_IEEE8021X:
1163 return "FT-EAP";
1164 case WPA_KEY_MGMT_FT_PSK:
1165 return "FT-PSK";
1166#endif /* CONFIG_IEEE80211R */
1167#ifdef CONFIG_IEEE80211W
1168 case WPA_KEY_MGMT_IEEE8021X_SHA256:
1169 return "WPA2-EAP-SHA256";
1170 case WPA_KEY_MGMT_PSK_SHA256:
1171 return "WPA2-PSK-SHA256";
1172#endif /* CONFIG_IEEE80211W */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001173 case WPA_KEY_MGMT_WPS:
1174 return "WPS";
1175 case WPA_KEY_MGMT_SAE:
1176 return "SAE";
1177 case WPA_KEY_MGMT_FT_SAE:
1178 return "FT-SAE";
1179 case WPA_KEY_MGMT_OSEN:
1180 return "OSEN";
1181 case WPA_KEY_MGMT_IEEE8021X_SUITE_B:
1182 return "WPA2-EAP-SUITE-B";
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001183 case WPA_KEY_MGMT_IEEE8021X_SUITE_B_192:
1184 return "WPA2-EAP-SUITE-B-192";
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001185 default:
1186 return "UNKNOWN";
1187 }
1188}
1189
1190
Dmitry Shmidt03658832014-08-13 11:03:49 -07001191u32 wpa_akm_to_suite(int akm)
1192{
1193 if (akm & WPA_KEY_MGMT_FT_IEEE8021X)
1194 return WLAN_AKM_SUITE_FT_8021X;
1195 if (akm & WPA_KEY_MGMT_FT_PSK)
1196 return WLAN_AKM_SUITE_FT_PSK;
1197 if (akm & WPA_KEY_MGMT_IEEE8021X)
1198 return WLAN_AKM_SUITE_8021X;
1199 if (akm & WPA_KEY_MGMT_IEEE8021X_SHA256)
1200 return WLAN_AKM_SUITE_8021X_SHA256;
1201 if (akm & WPA_KEY_MGMT_IEEE8021X)
1202 return WLAN_AKM_SUITE_8021X;
1203 if (akm & WPA_KEY_MGMT_PSK_SHA256)
1204 return WLAN_AKM_SUITE_PSK_SHA256;
1205 if (akm & WPA_KEY_MGMT_PSK)
1206 return WLAN_AKM_SUITE_PSK;
1207 if (akm & WPA_KEY_MGMT_CCKM)
1208 return WLAN_AKM_SUITE_CCKM;
1209 if (akm & WPA_KEY_MGMT_OSEN)
1210 return WLAN_AKM_SUITE_OSEN;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001211 if (akm & WPA_KEY_MGMT_IEEE8021X_SUITE_B)
1212 return WLAN_AKM_SUITE_8021X_SUITE_B;
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001213 if (akm & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192)
1214 return WLAN_AKM_SUITE_8021X_SUITE_B_192;
Dmitry Shmidt03658832014-08-13 11:03:49 -07001215 return 0;
1216}
1217
1218
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001219int wpa_compare_rsn_ie(int ft_initial_assoc,
1220 const u8 *ie1, size_t ie1len,
1221 const u8 *ie2, size_t ie2len)
1222{
1223 if (ie1 == NULL || ie2 == NULL)
1224 return -1;
1225
1226 if (ie1len == ie2len && os_memcmp(ie1, ie2, ie1len) == 0)
1227 return 0; /* identical IEs */
1228
1229#ifdef CONFIG_IEEE80211R
1230 if (ft_initial_assoc) {
1231 struct wpa_ie_data ie1d, ie2d;
1232 /*
1233 * The PMKID-List in RSN IE is different between Beacon/Probe
1234 * Response/(Re)Association Request frames and EAPOL-Key
1235 * messages in FT initial mobility domain association. Allow
1236 * for this, but verify that other parts of the RSN IEs are
1237 * identical.
1238 */
1239 if (wpa_parse_wpa_ie_rsn(ie1, ie1len, &ie1d) < 0 ||
1240 wpa_parse_wpa_ie_rsn(ie2, ie2len, &ie2d) < 0)
1241 return -1;
1242 if (ie1d.proto == ie2d.proto &&
1243 ie1d.pairwise_cipher == ie2d.pairwise_cipher &&
1244 ie1d.group_cipher == ie2d.group_cipher &&
1245 ie1d.key_mgmt == ie2d.key_mgmt &&
1246 ie1d.capabilities == ie2d.capabilities &&
1247 ie1d.mgmt_group_cipher == ie2d.mgmt_group_cipher)
1248 return 0;
1249 }
1250#endif /* CONFIG_IEEE80211R */
1251
1252 return -1;
1253}
1254
1255
1256#ifdef CONFIG_IEEE80211R
1257int wpa_insert_pmkid(u8 *ies, size_t ies_len, const u8 *pmkid)
1258{
1259 u8 *start, *end, *rpos, *rend;
1260 int added = 0;
1261
1262 start = ies;
1263 end = ies + ies_len;
1264
1265 while (start < end) {
1266 if (*start == WLAN_EID_RSN)
1267 break;
1268 start += 2 + start[1];
1269 }
1270 if (start >= end) {
1271 wpa_printf(MSG_ERROR, "FT: Could not find RSN IE in "
1272 "IEs data");
1273 return -1;
1274 }
1275 wpa_hexdump(MSG_DEBUG, "FT: RSN IE before modification",
1276 start, 2 + start[1]);
1277
1278 /* Find start of PMKID-Count */
1279 rpos = start + 2;
1280 rend = rpos + start[1];
1281
1282 /* Skip Version and Group Data Cipher Suite */
1283 rpos += 2 + 4;
1284 /* Skip Pairwise Cipher Suite Count and List */
1285 rpos += 2 + WPA_GET_LE16(rpos) * RSN_SELECTOR_LEN;
1286 /* Skip AKM Suite Count and List */
1287 rpos += 2 + WPA_GET_LE16(rpos) * RSN_SELECTOR_LEN;
1288
1289 if (rpos == rend) {
1290 /* Add RSN Capabilities */
1291 os_memmove(rpos + 2, rpos, end - rpos);
1292 *rpos++ = 0;
1293 *rpos++ = 0;
1294 } else {
1295 /* Skip RSN Capabilities */
1296 rpos += 2;
1297 if (rpos > rend) {
1298 wpa_printf(MSG_ERROR, "FT: Could not parse RSN IE in "
1299 "IEs data");
1300 return -1;
1301 }
1302 }
1303
1304 if (rpos == rend) {
1305 /* No PMKID-Count field included; add it */
1306 os_memmove(rpos + 2 + PMKID_LEN, rpos, end - rpos);
1307 WPA_PUT_LE16(rpos, 1);
1308 rpos += 2;
1309 os_memcpy(rpos, pmkid, PMKID_LEN);
1310 added += 2 + PMKID_LEN;
1311 start[1] += 2 + PMKID_LEN;
1312 } else {
1313 /* PMKID-Count was included; use it */
1314 if (WPA_GET_LE16(rpos) != 0) {
1315 wpa_printf(MSG_ERROR, "FT: Unexpected PMKID "
1316 "in RSN IE in EAPOL-Key data");
1317 return -1;
1318 }
1319 WPA_PUT_LE16(rpos, 1);
1320 rpos += 2;
1321 os_memmove(rpos + PMKID_LEN, rpos, end - rpos);
1322 os_memcpy(rpos, pmkid, PMKID_LEN);
1323 added += PMKID_LEN;
1324 start[1] += PMKID_LEN;
1325 }
1326
1327 wpa_hexdump(MSG_DEBUG, "FT: RSN IE after modification "
1328 "(PMKID inserted)", start, 2 + start[1]);
1329
1330 return added;
1331}
1332#endif /* CONFIG_IEEE80211R */
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07001333
1334
1335int wpa_cipher_key_len(int cipher)
1336{
1337 switch (cipher) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001338 case WPA_CIPHER_CCMP_256:
1339 case WPA_CIPHER_GCMP_256:
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07001340 case WPA_CIPHER_BIP_GMAC_256:
1341 case WPA_CIPHER_BIP_CMAC_256:
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001342 return 32;
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07001343 case WPA_CIPHER_CCMP:
1344 case WPA_CIPHER_GCMP:
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07001345 case WPA_CIPHER_AES_128_CMAC:
1346 case WPA_CIPHER_BIP_GMAC_128:
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07001347 return 16;
1348 case WPA_CIPHER_TKIP:
1349 return 32;
1350 case WPA_CIPHER_WEP104:
1351 return 13;
1352 case WPA_CIPHER_WEP40:
1353 return 5;
1354 }
1355
1356 return 0;
1357}
1358
1359
1360int wpa_cipher_rsc_len(int cipher)
1361{
1362 switch (cipher) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001363 case WPA_CIPHER_CCMP_256:
1364 case WPA_CIPHER_GCMP_256:
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07001365 case WPA_CIPHER_CCMP:
1366 case WPA_CIPHER_GCMP:
1367 case WPA_CIPHER_TKIP:
1368 return 6;
1369 case WPA_CIPHER_WEP104:
1370 case WPA_CIPHER_WEP40:
1371 return 0;
1372 }
1373
1374 return 0;
1375}
1376
1377
1378int wpa_cipher_to_alg(int cipher)
1379{
1380 switch (cipher) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001381 case WPA_CIPHER_CCMP_256:
1382 return WPA_ALG_CCMP_256;
1383 case WPA_CIPHER_GCMP_256:
1384 return WPA_ALG_GCMP_256;
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07001385 case WPA_CIPHER_CCMP:
1386 return WPA_ALG_CCMP;
1387 case WPA_CIPHER_GCMP:
1388 return WPA_ALG_GCMP;
1389 case WPA_CIPHER_TKIP:
1390 return WPA_ALG_TKIP;
1391 case WPA_CIPHER_WEP104:
1392 case WPA_CIPHER_WEP40:
1393 return WPA_ALG_WEP;
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07001394 case WPA_CIPHER_AES_128_CMAC:
1395 return WPA_ALG_IGTK;
1396 case WPA_CIPHER_BIP_GMAC_128:
1397 return WPA_ALG_BIP_GMAC_128;
1398 case WPA_CIPHER_BIP_GMAC_256:
1399 return WPA_ALG_BIP_GMAC_256;
1400 case WPA_CIPHER_BIP_CMAC_256:
1401 return WPA_ALG_BIP_CMAC_256;
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07001402 }
1403 return WPA_ALG_NONE;
1404}
1405
1406
1407int wpa_cipher_valid_pairwise(int cipher)
1408{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001409 return cipher == WPA_CIPHER_CCMP_256 ||
1410 cipher == WPA_CIPHER_GCMP_256 ||
1411 cipher == WPA_CIPHER_CCMP ||
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07001412 cipher == WPA_CIPHER_GCMP ||
1413 cipher == WPA_CIPHER_TKIP;
1414}
1415
1416
1417u32 wpa_cipher_to_suite(int proto, int cipher)
1418{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001419 if (cipher & WPA_CIPHER_CCMP_256)
1420 return RSN_CIPHER_SUITE_CCMP_256;
1421 if (cipher & WPA_CIPHER_GCMP_256)
1422 return RSN_CIPHER_SUITE_GCMP_256;
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07001423 if (cipher & WPA_CIPHER_CCMP)
1424 return (proto == WPA_PROTO_RSN ?
1425 RSN_CIPHER_SUITE_CCMP : WPA_CIPHER_SUITE_CCMP);
1426 if (cipher & WPA_CIPHER_GCMP)
1427 return RSN_CIPHER_SUITE_GCMP;
1428 if (cipher & WPA_CIPHER_TKIP)
1429 return (proto == WPA_PROTO_RSN ?
1430 RSN_CIPHER_SUITE_TKIP : WPA_CIPHER_SUITE_TKIP);
1431 if (cipher & WPA_CIPHER_WEP104)
1432 return (proto == WPA_PROTO_RSN ?
1433 RSN_CIPHER_SUITE_WEP104 : WPA_CIPHER_SUITE_WEP104);
1434 if (cipher & WPA_CIPHER_WEP40)
1435 return (proto == WPA_PROTO_RSN ?
1436 RSN_CIPHER_SUITE_WEP40 : WPA_CIPHER_SUITE_WEP40);
1437 if (cipher & WPA_CIPHER_NONE)
1438 return (proto == WPA_PROTO_RSN ?
1439 RSN_CIPHER_SUITE_NONE : WPA_CIPHER_SUITE_NONE);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001440 if (cipher & WPA_CIPHER_GTK_NOT_USED)
1441 return RSN_CIPHER_SUITE_NO_GROUP_ADDRESSED;
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07001442 if (cipher & WPA_CIPHER_AES_128_CMAC)
1443 return RSN_CIPHER_SUITE_AES_128_CMAC;
1444 if (cipher & WPA_CIPHER_BIP_GMAC_128)
1445 return RSN_CIPHER_SUITE_BIP_GMAC_128;
1446 if (cipher & WPA_CIPHER_BIP_GMAC_256)
1447 return RSN_CIPHER_SUITE_BIP_GMAC_256;
1448 if (cipher & WPA_CIPHER_BIP_CMAC_256)
1449 return RSN_CIPHER_SUITE_BIP_CMAC_256;
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07001450 return 0;
1451}
1452
1453
Dmitry Shmidt7d5c8f22014-03-03 13:53:28 -08001454int rsn_cipher_put_suites(u8 *start, int ciphers)
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07001455{
Dmitry Shmidt7d5c8f22014-03-03 13:53:28 -08001456 u8 *pos = start;
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07001457
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001458 if (ciphers & WPA_CIPHER_CCMP_256) {
1459 RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP_256);
1460 pos += RSN_SELECTOR_LEN;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001461 }
1462 if (ciphers & WPA_CIPHER_GCMP_256) {
1463 RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_GCMP_256);
1464 pos += RSN_SELECTOR_LEN;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001465 }
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07001466 if (ciphers & WPA_CIPHER_CCMP) {
1467 RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP);
1468 pos += RSN_SELECTOR_LEN;
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07001469 }
1470 if (ciphers & WPA_CIPHER_GCMP) {
1471 RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_GCMP);
1472 pos += RSN_SELECTOR_LEN;
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07001473 }
1474 if (ciphers & WPA_CIPHER_TKIP) {
1475 RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_TKIP);
1476 pos += RSN_SELECTOR_LEN;
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07001477 }
1478 if (ciphers & WPA_CIPHER_NONE) {
1479 RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_NONE);
1480 pos += RSN_SELECTOR_LEN;
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07001481 }
1482
Dmitry Shmidt7d5c8f22014-03-03 13:53:28 -08001483 return (pos - start) / RSN_SELECTOR_LEN;
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07001484}
1485
1486
Dmitry Shmidt7d5c8f22014-03-03 13:53:28 -08001487int wpa_cipher_put_suites(u8 *start, int ciphers)
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07001488{
Dmitry Shmidt7d5c8f22014-03-03 13:53:28 -08001489 u8 *pos = start;
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07001490
1491 if (ciphers & WPA_CIPHER_CCMP) {
1492 RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_CCMP);
1493 pos += WPA_SELECTOR_LEN;
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07001494 }
1495 if (ciphers & WPA_CIPHER_TKIP) {
1496 RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_TKIP);
1497 pos += WPA_SELECTOR_LEN;
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07001498 }
1499 if (ciphers & WPA_CIPHER_NONE) {
1500 RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_NONE);
1501 pos += WPA_SELECTOR_LEN;
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07001502 }
1503
Dmitry Shmidt7d5c8f22014-03-03 13:53:28 -08001504 return (pos - start) / RSN_SELECTOR_LEN;
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07001505}
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001506
1507
1508int wpa_pick_pairwise_cipher(int ciphers, int none_allowed)
1509{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001510 if (ciphers & WPA_CIPHER_CCMP_256)
1511 return WPA_CIPHER_CCMP_256;
1512 if (ciphers & WPA_CIPHER_GCMP_256)
1513 return WPA_CIPHER_GCMP_256;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001514 if (ciphers & WPA_CIPHER_CCMP)
1515 return WPA_CIPHER_CCMP;
1516 if (ciphers & WPA_CIPHER_GCMP)
1517 return WPA_CIPHER_GCMP;
1518 if (ciphers & WPA_CIPHER_TKIP)
1519 return WPA_CIPHER_TKIP;
1520 if (none_allowed && (ciphers & WPA_CIPHER_NONE))
1521 return WPA_CIPHER_NONE;
1522 return -1;
1523}
1524
1525
1526int wpa_pick_group_cipher(int ciphers)
1527{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001528 if (ciphers & WPA_CIPHER_CCMP_256)
1529 return WPA_CIPHER_CCMP_256;
1530 if (ciphers & WPA_CIPHER_GCMP_256)
1531 return WPA_CIPHER_GCMP_256;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001532 if (ciphers & WPA_CIPHER_CCMP)
1533 return WPA_CIPHER_CCMP;
1534 if (ciphers & WPA_CIPHER_GCMP)
1535 return WPA_CIPHER_GCMP;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001536 if (ciphers & WPA_CIPHER_GTK_NOT_USED)
1537 return WPA_CIPHER_GTK_NOT_USED;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001538 if (ciphers & WPA_CIPHER_TKIP)
1539 return WPA_CIPHER_TKIP;
1540 if (ciphers & WPA_CIPHER_WEP104)
1541 return WPA_CIPHER_WEP104;
1542 if (ciphers & WPA_CIPHER_WEP40)
1543 return WPA_CIPHER_WEP40;
1544 return -1;
1545}
1546
1547
1548int wpa_parse_cipher(const char *value)
1549{
1550 int val = 0, last;
1551 char *start, *end, *buf;
1552
1553 buf = os_strdup(value);
1554 if (buf == NULL)
1555 return -1;
1556 start = buf;
1557
1558 while (*start != '\0') {
1559 while (*start == ' ' || *start == '\t')
1560 start++;
1561 if (*start == '\0')
1562 break;
1563 end = start;
1564 while (*end != ' ' && *end != '\t' && *end != '\0')
1565 end++;
1566 last = *end == '\0';
1567 *end = '\0';
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001568 if (os_strcmp(start, "CCMP-256") == 0)
1569 val |= WPA_CIPHER_CCMP_256;
1570 else if (os_strcmp(start, "GCMP-256") == 0)
1571 val |= WPA_CIPHER_GCMP_256;
1572 else if (os_strcmp(start, "CCMP") == 0)
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001573 val |= WPA_CIPHER_CCMP;
1574 else if (os_strcmp(start, "GCMP") == 0)
1575 val |= WPA_CIPHER_GCMP;
1576 else if (os_strcmp(start, "TKIP") == 0)
1577 val |= WPA_CIPHER_TKIP;
1578 else if (os_strcmp(start, "WEP104") == 0)
1579 val |= WPA_CIPHER_WEP104;
1580 else if (os_strcmp(start, "WEP40") == 0)
1581 val |= WPA_CIPHER_WEP40;
1582 else if (os_strcmp(start, "NONE") == 0)
1583 val |= WPA_CIPHER_NONE;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001584 else if (os_strcmp(start, "GTK_NOT_USED") == 0)
1585 val |= WPA_CIPHER_GTK_NOT_USED;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001586 else {
1587 os_free(buf);
1588 return -1;
1589 }
1590
1591 if (last)
1592 break;
1593 start = end + 1;
1594 }
1595 os_free(buf);
1596
1597 return val;
1598}
1599
1600
1601int wpa_write_ciphers(char *start, char *end, int ciphers, const char *delim)
1602{
1603 char *pos = start;
1604 int ret;
1605
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001606 if (ciphers & WPA_CIPHER_CCMP_256) {
1607 ret = os_snprintf(pos, end - pos, "%sCCMP-256",
1608 pos == start ? "" : delim);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001609 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001610 return -1;
1611 pos += ret;
1612 }
1613 if (ciphers & WPA_CIPHER_GCMP_256) {
1614 ret = os_snprintf(pos, end - pos, "%sGCMP-256",
1615 pos == start ? "" : delim);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001616 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001617 return -1;
1618 pos += ret;
1619 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001620 if (ciphers & WPA_CIPHER_CCMP) {
1621 ret = os_snprintf(pos, end - pos, "%sCCMP",
1622 pos == start ? "" : delim);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001623 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001624 return -1;
1625 pos += ret;
1626 }
1627 if (ciphers & WPA_CIPHER_GCMP) {
1628 ret = os_snprintf(pos, end - pos, "%sGCMP",
1629 pos == start ? "" : delim);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001630 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001631 return -1;
1632 pos += ret;
1633 }
1634 if (ciphers & WPA_CIPHER_TKIP) {
1635 ret = os_snprintf(pos, end - pos, "%sTKIP",
1636 pos == start ? "" : delim);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001637 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001638 return -1;
1639 pos += ret;
1640 }
1641 if (ciphers & WPA_CIPHER_WEP104) {
1642 ret = os_snprintf(pos, end - pos, "%sWEP104",
1643 pos == start ? "" : delim);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001644 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001645 return -1;
1646 pos += ret;
1647 }
1648 if (ciphers & WPA_CIPHER_WEP40) {
1649 ret = os_snprintf(pos, end - pos, "%sWEP40",
1650 pos == start ? "" : delim);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001651 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001652 return -1;
1653 pos += ret;
1654 }
1655 if (ciphers & WPA_CIPHER_NONE) {
1656 ret = os_snprintf(pos, end - pos, "%sNONE",
1657 pos == start ? "" : delim);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001658 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001659 return -1;
1660 pos += ret;
1661 }
1662
1663 return pos - start;
1664}
1665
1666
1667int wpa_select_ap_group_cipher(int wpa, int wpa_pairwise, int rsn_pairwise)
1668{
1669 int pairwise = 0;
1670
1671 /* Select group cipher based on the enabled pairwise cipher suites */
1672 if (wpa & 1)
1673 pairwise |= wpa_pairwise;
1674 if (wpa & 2)
1675 pairwise |= rsn_pairwise;
1676
1677 if (pairwise & WPA_CIPHER_TKIP)
1678 return WPA_CIPHER_TKIP;
1679 if ((pairwise & (WPA_CIPHER_CCMP | WPA_CIPHER_GCMP)) == WPA_CIPHER_GCMP)
1680 return WPA_CIPHER_GCMP;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001681 if ((pairwise & (WPA_CIPHER_GCMP_256 | WPA_CIPHER_CCMP |
1682 WPA_CIPHER_GCMP)) == WPA_CIPHER_GCMP_256)
1683 return WPA_CIPHER_GCMP_256;
1684 if ((pairwise & (WPA_CIPHER_CCMP_256 | WPA_CIPHER_CCMP |
1685 WPA_CIPHER_GCMP)) == WPA_CIPHER_CCMP_256)
1686 return WPA_CIPHER_CCMP_256;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001687 return WPA_CIPHER_CCMP;
1688}