blob: 036890483d42c989223f32d54571d3eb2410a651 [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 Shmidt912c6ec2015-03-30 13:16:51 -0700489 if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_OSEN)
490 return WPA_KEY_MGMT_OSEN;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700491 return 0;
492}
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700493
494
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -0700495static int wpa_cipher_valid_group(int cipher)
496{
497 return wpa_cipher_valid_pairwise(cipher) ||
498 cipher == WPA_CIPHER_WEP104 ||
499 cipher == WPA_CIPHER_WEP40 ||
500 cipher == WPA_CIPHER_GTK_NOT_USED;
501}
502
503
504#ifdef CONFIG_IEEE80211W
505int wpa_cipher_valid_mgmt_group(int cipher)
506{
507 return cipher == WPA_CIPHER_AES_128_CMAC ||
508 cipher == WPA_CIPHER_BIP_GMAC_128 ||
509 cipher == WPA_CIPHER_BIP_GMAC_256 ||
510 cipher == WPA_CIPHER_BIP_CMAC_256;
511}
512#endif /* CONFIG_IEEE80211W */
513
514
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700515/**
516 * wpa_parse_wpa_ie_rsn - Parse RSN IE
517 * @rsn_ie: Buffer containing RSN IE
518 * @rsn_ie_len: RSN IE buffer length (including IE number and length octets)
519 * @data: Pointer to structure that will be filled in with parsed data
520 * Returns: 0 on success, <0 on failure
521 */
522int wpa_parse_wpa_ie_rsn(const u8 *rsn_ie, size_t rsn_ie_len,
523 struct wpa_ie_data *data)
524{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700525 const u8 *pos;
526 int left;
527 int i, count;
528
529 os_memset(data, 0, sizeof(*data));
530 data->proto = WPA_PROTO_RSN;
531 data->pairwise_cipher = WPA_CIPHER_CCMP;
532 data->group_cipher = WPA_CIPHER_CCMP;
533 data->key_mgmt = WPA_KEY_MGMT_IEEE8021X;
534 data->capabilities = 0;
535 data->pmkid = NULL;
536 data->num_pmkid = 0;
537#ifdef CONFIG_IEEE80211W
538 data->mgmt_group_cipher = WPA_CIPHER_AES_128_CMAC;
539#else /* CONFIG_IEEE80211W */
540 data->mgmt_group_cipher = 0;
541#endif /* CONFIG_IEEE80211W */
542
543 if (rsn_ie_len == 0) {
544 /* No RSN IE - fail silently */
545 return -1;
546 }
547
548 if (rsn_ie_len < sizeof(struct rsn_ie_hdr)) {
549 wpa_printf(MSG_DEBUG, "%s: ie len too short %lu",
550 __func__, (unsigned long) rsn_ie_len);
551 return -1;
552 }
553
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -0700554 if (rsn_ie_len >= 6 && rsn_ie[1] >= 4 &&
555 rsn_ie[1] == rsn_ie_len - 2 &&
556 WPA_GET_BE32(&rsn_ie[2]) == OSEN_IE_VENDOR_TYPE) {
557 pos = rsn_ie + 6;
558 left = rsn_ie_len - 6;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700559
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -0700560 data->proto = WPA_PROTO_OSEN;
561 } else {
562 const struct rsn_ie_hdr *hdr;
563
564 hdr = (const struct rsn_ie_hdr *) rsn_ie;
565
566 if (hdr->elem_id != WLAN_EID_RSN ||
567 hdr->len != rsn_ie_len - 2 ||
568 WPA_GET_LE16(hdr->version) != RSN_VERSION) {
569 wpa_printf(MSG_DEBUG, "%s: malformed ie or unknown version",
570 __func__);
571 return -2;
572 }
573
574 pos = (const u8 *) (hdr + 1);
575 left = rsn_ie_len - sizeof(*hdr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700576 }
577
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700578 if (left >= RSN_SELECTOR_LEN) {
579 data->group_cipher = rsn_selector_to_bitfield(pos);
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -0700580 if (!wpa_cipher_valid_group(data->group_cipher)) {
581 wpa_printf(MSG_DEBUG, "%s: invalid group cipher 0x%x",
582 __func__, data->group_cipher);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700583 return -1;
584 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700585 pos += RSN_SELECTOR_LEN;
586 left -= RSN_SELECTOR_LEN;
587 } else if (left > 0) {
588 wpa_printf(MSG_DEBUG, "%s: ie length mismatch, %u too much",
589 __func__, left);
590 return -3;
591 }
592
593 if (left >= 2) {
594 data->pairwise_cipher = 0;
595 count = WPA_GET_LE16(pos);
596 pos += 2;
597 left -= 2;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800598 if (count == 0 || count > left / RSN_SELECTOR_LEN) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700599 wpa_printf(MSG_DEBUG, "%s: ie count botch (pairwise), "
600 "count %u left %u", __func__, count, left);
601 return -4;
602 }
603 for (i = 0; i < count; i++) {
604 data->pairwise_cipher |= rsn_selector_to_bitfield(pos);
605 pos += RSN_SELECTOR_LEN;
606 left -= RSN_SELECTOR_LEN;
607 }
608#ifdef CONFIG_IEEE80211W
609 if (data->pairwise_cipher & WPA_CIPHER_AES_128_CMAC) {
610 wpa_printf(MSG_DEBUG, "%s: AES-128-CMAC used as "
611 "pairwise cipher", __func__);
612 return -1;
613 }
614#endif /* CONFIG_IEEE80211W */
615 } else if (left == 1) {
616 wpa_printf(MSG_DEBUG, "%s: ie too short (for key mgmt)",
617 __func__);
618 return -5;
619 }
620
621 if (left >= 2) {
622 data->key_mgmt = 0;
623 count = WPA_GET_LE16(pos);
624 pos += 2;
625 left -= 2;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800626 if (count == 0 || count > left / RSN_SELECTOR_LEN) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700627 wpa_printf(MSG_DEBUG, "%s: ie count botch (key mgmt), "
628 "count %u left %u", __func__, count, left);
629 return -6;
630 }
631 for (i = 0; i < count; i++) {
632 data->key_mgmt |= rsn_key_mgmt_to_bitfield(pos);
633 pos += RSN_SELECTOR_LEN;
634 left -= RSN_SELECTOR_LEN;
635 }
636 } else if (left == 1) {
637 wpa_printf(MSG_DEBUG, "%s: ie too short (for capabilities)",
638 __func__);
639 return -7;
640 }
641
642 if (left >= 2) {
643 data->capabilities = WPA_GET_LE16(pos);
644 pos += 2;
645 left -= 2;
646 }
647
648 if (left >= 2) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800649 u16 num_pmkid = WPA_GET_LE16(pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700650 pos += 2;
651 left -= 2;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800652 if (num_pmkid > (unsigned int) left / PMKID_LEN) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700653 wpa_printf(MSG_DEBUG, "%s: PMKID underflow "
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800654 "(num_pmkid=%u left=%d)",
655 __func__, num_pmkid, left);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700656 data->num_pmkid = 0;
657 return -9;
658 } else {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800659 data->num_pmkid = num_pmkid;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700660 data->pmkid = pos;
661 pos += data->num_pmkid * PMKID_LEN;
662 left -= data->num_pmkid * PMKID_LEN;
663 }
664 }
665
666#ifdef CONFIG_IEEE80211W
667 if (left >= 4) {
668 data->mgmt_group_cipher = rsn_selector_to_bitfield(pos);
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -0700669 if (!wpa_cipher_valid_mgmt_group(data->mgmt_group_cipher)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700670 wpa_printf(MSG_DEBUG, "%s: Unsupported management "
671 "group cipher 0x%x", __func__,
672 data->mgmt_group_cipher);
673 return -10;
674 }
675 pos += RSN_SELECTOR_LEN;
676 left -= RSN_SELECTOR_LEN;
677 }
678#endif /* CONFIG_IEEE80211W */
679
680 if (left > 0) {
Dmitry Shmidt7d5c8f22014-03-03 13:53:28 -0800681 wpa_hexdump(MSG_DEBUG,
682 "wpa_parse_wpa_ie_rsn: ignore trailing bytes",
683 pos, left);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700684 }
685
686 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700687}
688
689
690static int wpa_selector_to_bitfield(const u8 *s)
691{
692 if (RSN_SELECTOR_GET(s) == WPA_CIPHER_SUITE_NONE)
693 return WPA_CIPHER_NONE;
694 if (RSN_SELECTOR_GET(s) == WPA_CIPHER_SUITE_WEP40)
695 return WPA_CIPHER_WEP40;
696 if (RSN_SELECTOR_GET(s) == WPA_CIPHER_SUITE_TKIP)
697 return WPA_CIPHER_TKIP;
698 if (RSN_SELECTOR_GET(s) == WPA_CIPHER_SUITE_CCMP)
699 return WPA_CIPHER_CCMP;
700 if (RSN_SELECTOR_GET(s) == WPA_CIPHER_SUITE_WEP104)
701 return WPA_CIPHER_WEP104;
702 return 0;
703}
704
705
706static int wpa_key_mgmt_to_bitfield(const u8 *s)
707{
708 if (RSN_SELECTOR_GET(s) == WPA_AUTH_KEY_MGMT_UNSPEC_802_1X)
709 return WPA_KEY_MGMT_IEEE8021X;
710 if (RSN_SELECTOR_GET(s) == WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X)
711 return WPA_KEY_MGMT_PSK;
712 if (RSN_SELECTOR_GET(s) == WPA_AUTH_KEY_MGMT_NONE)
713 return WPA_KEY_MGMT_WPA_NONE;
714 return 0;
715}
716
717
718int wpa_parse_wpa_ie_wpa(const u8 *wpa_ie, size_t wpa_ie_len,
719 struct wpa_ie_data *data)
720{
721 const struct wpa_ie_hdr *hdr;
722 const u8 *pos;
723 int left;
724 int i, count;
725
726 os_memset(data, 0, sizeof(*data));
727 data->proto = WPA_PROTO_WPA;
728 data->pairwise_cipher = WPA_CIPHER_TKIP;
729 data->group_cipher = WPA_CIPHER_TKIP;
730 data->key_mgmt = WPA_KEY_MGMT_IEEE8021X;
731 data->capabilities = 0;
732 data->pmkid = NULL;
733 data->num_pmkid = 0;
734 data->mgmt_group_cipher = 0;
735
736 if (wpa_ie_len == 0) {
737 /* No WPA IE - fail silently */
738 return -1;
739 }
740
741 if (wpa_ie_len < sizeof(struct wpa_ie_hdr)) {
742 wpa_printf(MSG_DEBUG, "%s: ie len too short %lu",
743 __func__, (unsigned long) wpa_ie_len);
744 return -1;
745 }
746
747 hdr = (const struct wpa_ie_hdr *) wpa_ie;
748
749 if (hdr->elem_id != WLAN_EID_VENDOR_SPECIFIC ||
750 hdr->len != wpa_ie_len - 2 ||
751 RSN_SELECTOR_GET(hdr->oui) != WPA_OUI_TYPE ||
752 WPA_GET_LE16(hdr->version) != WPA_VERSION) {
753 wpa_printf(MSG_DEBUG, "%s: malformed ie or unknown version",
754 __func__);
755 return -2;
756 }
757
758 pos = (const u8 *) (hdr + 1);
759 left = wpa_ie_len - sizeof(*hdr);
760
761 if (left >= WPA_SELECTOR_LEN) {
762 data->group_cipher = wpa_selector_to_bitfield(pos);
763 pos += WPA_SELECTOR_LEN;
764 left -= WPA_SELECTOR_LEN;
765 } else if (left > 0) {
766 wpa_printf(MSG_DEBUG, "%s: ie length mismatch, %u too much",
767 __func__, left);
768 return -3;
769 }
770
771 if (left >= 2) {
772 data->pairwise_cipher = 0;
773 count = WPA_GET_LE16(pos);
774 pos += 2;
775 left -= 2;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800776 if (count == 0 || count > left / WPA_SELECTOR_LEN) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700777 wpa_printf(MSG_DEBUG, "%s: ie count botch (pairwise), "
778 "count %u left %u", __func__, count, left);
779 return -4;
780 }
781 for (i = 0; i < count; i++) {
782 data->pairwise_cipher |= wpa_selector_to_bitfield(pos);
783 pos += WPA_SELECTOR_LEN;
784 left -= WPA_SELECTOR_LEN;
785 }
786 } else if (left == 1) {
787 wpa_printf(MSG_DEBUG, "%s: ie too short (for key mgmt)",
788 __func__);
789 return -5;
790 }
791
792 if (left >= 2) {
793 data->key_mgmt = 0;
794 count = WPA_GET_LE16(pos);
795 pos += 2;
796 left -= 2;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800797 if (count == 0 || count > left / WPA_SELECTOR_LEN) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700798 wpa_printf(MSG_DEBUG, "%s: ie count botch (key mgmt), "
799 "count %u left %u", __func__, count, left);
800 return -6;
801 }
802 for (i = 0; i < count; i++) {
803 data->key_mgmt |= wpa_key_mgmt_to_bitfield(pos);
804 pos += WPA_SELECTOR_LEN;
805 left -= WPA_SELECTOR_LEN;
806 }
807 } else if (left == 1) {
808 wpa_printf(MSG_DEBUG, "%s: ie too short (for capabilities)",
809 __func__);
810 return -7;
811 }
812
813 if (left >= 2) {
814 data->capabilities = WPA_GET_LE16(pos);
815 pos += 2;
816 left -= 2;
817 }
818
819 if (left > 0) {
Dmitry Shmidt7d5c8f22014-03-03 13:53:28 -0800820 wpa_hexdump(MSG_DEBUG,
821 "wpa_parse_wpa_ie_wpa: ignore trailing bytes",
822 pos, left);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700823 }
824
825 return 0;
826}
827
828
829#ifdef CONFIG_IEEE80211R
830
831/**
832 * wpa_derive_pmk_r0 - Derive PMK-R0 and PMKR0Name
833 *
834 * IEEE Std 802.11r-2008 - 8.5.1.5.3
835 */
836void wpa_derive_pmk_r0(const u8 *xxkey, size_t xxkey_len,
837 const u8 *ssid, size_t ssid_len,
838 const u8 *mdid, const u8 *r0kh_id, size_t r0kh_id_len,
839 const u8 *s0kh_id, u8 *pmk_r0, u8 *pmk_r0_name)
840{
841 u8 buf[1 + WPA_MAX_SSID_LEN + MOBILITY_DOMAIN_ID_LEN + 1 +
842 FT_R0KH_ID_MAX_LEN + ETH_ALEN];
843 u8 *pos, r0_key_data[48], hash[32];
844 const u8 *addr[2];
845 size_t len[2];
846
847 /*
848 * R0-Key-Data = KDF-384(XXKey, "FT-R0",
849 * SSIDlength || SSID || MDID || R0KHlength ||
850 * R0KH-ID || S0KH-ID)
851 * XXKey is either the second 256 bits of MSK or PSK.
852 * PMK-R0 = L(R0-Key-Data, 0, 256)
853 * PMK-R0Name-Salt = L(R0-Key-Data, 256, 128)
854 */
855 if (ssid_len > WPA_MAX_SSID_LEN || r0kh_id_len > FT_R0KH_ID_MAX_LEN)
856 return;
857 pos = buf;
858 *pos++ = ssid_len;
859 os_memcpy(pos, ssid, ssid_len);
860 pos += ssid_len;
861 os_memcpy(pos, mdid, MOBILITY_DOMAIN_ID_LEN);
862 pos += MOBILITY_DOMAIN_ID_LEN;
863 *pos++ = r0kh_id_len;
864 os_memcpy(pos, r0kh_id, r0kh_id_len);
865 pos += r0kh_id_len;
866 os_memcpy(pos, s0kh_id, ETH_ALEN);
867 pos += ETH_ALEN;
868
869 sha256_prf(xxkey, xxkey_len, "FT-R0", buf, pos - buf,
870 r0_key_data, sizeof(r0_key_data));
871 os_memcpy(pmk_r0, r0_key_data, PMK_LEN);
872
873 /*
874 * PMKR0Name = Truncate-128(SHA-256("FT-R0N" || PMK-R0Name-Salt)
875 */
876 addr[0] = (const u8 *) "FT-R0N";
877 len[0] = 6;
878 addr[1] = r0_key_data + PMK_LEN;
879 len[1] = 16;
880
881 sha256_vector(2, addr, len, hash);
882 os_memcpy(pmk_r0_name, hash, WPA_PMK_NAME_LEN);
883}
884
885
886/**
887 * wpa_derive_pmk_r1_name - Derive PMKR1Name
888 *
889 * IEEE Std 802.11r-2008 - 8.5.1.5.4
890 */
891void wpa_derive_pmk_r1_name(const u8 *pmk_r0_name, const u8 *r1kh_id,
892 const u8 *s1kh_id, u8 *pmk_r1_name)
893{
894 u8 hash[32];
895 const u8 *addr[4];
896 size_t len[4];
897
898 /*
899 * PMKR1Name = Truncate-128(SHA-256("FT-R1N" || PMKR0Name ||
900 * R1KH-ID || S1KH-ID))
901 */
902 addr[0] = (const u8 *) "FT-R1N";
903 len[0] = 6;
904 addr[1] = pmk_r0_name;
905 len[1] = WPA_PMK_NAME_LEN;
906 addr[2] = r1kh_id;
907 len[2] = FT_R1KH_ID_LEN;
908 addr[3] = s1kh_id;
909 len[3] = ETH_ALEN;
910
911 sha256_vector(4, addr, len, hash);
912 os_memcpy(pmk_r1_name, hash, WPA_PMK_NAME_LEN);
913}
914
915
916/**
917 * wpa_derive_pmk_r1 - Derive PMK-R1 and PMKR1Name from PMK-R0
918 *
919 * IEEE Std 802.11r-2008 - 8.5.1.5.4
920 */
921void wpa_derive_pmk_r1(const u8 *pmk_r0, const u8 *pmk_r0_name,
922 const u8 *r1kh_id, const u8 *s1kh_id,
923 u8 *pmk_r1, u8 *pmk_r1_name)
924{
925 u8 buf[FT_R1KH_ID_LEN + ETH_ALEN];
926 u8 *pos;
927
928 /* PMK-R1 = KDF-256(PMK-R0, "FT-R1", R1KH-ID || S1KH-ID) */
929 pos = buf;
930 os_memcpy(pos, r1kh_id, FT_R1KH_ID_LEN);
931 pos += FT_R1KH_ID_LEN;
932 os_memcpy(pos, s1kh_id, ETH_ALEN);
933 pos += ETH_ALEN;
934
935 sha256_prf(pmk_r0, PMK_LEN, "FT-R1", buf, pos - buf, pmk_r1, PMK_LEN);
936
937 wpa_derive_pmk_r1_name(pmk_r0_name, r1kh_id, s1kh_id, pmk_r1_name);
938}
939
940
941/**
942 * wpa_pmk_r1_to_ptk - Derive PTK and PTKName from PMK-R1
943 *
944 * IEEE Std 802.11r-2008 - 8.5.1.5.5
945 */
Dmitry Shmidt807291d2015-01-27 13:40:23 -0800946int wpa_pmk_r1_to_ptk(const u8 *pmk_r1, const u8 *snonce, const u8 *anonce,
947 const u8 *sta_addr, const u8 *bssid,
948 const u8 *pmk_r1_name,
949 struct wpa_ptk *ptk, u8 *ptk_name, int akmp, int cipher)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700950{
951 u8 buf[2 * WPA_NONCE_LEN + 2 * ETH_ALEN];
952 u8 *pos, hash[32];
953 const u8 *addr[6];
954 size_t len[6];
Dmitry Shmidt807291d2015-01-27 13:40:23 -0800955 u8 tmp[WPA_KCK_MAX_LEN + WPA_KEK_MAX_LEN + WPA_TK_MAX_LEN];
956 size_t ptk_len;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700957
958 /*
959 * PTK = KDF-PTKLen(PMK-R1, "FT-PTK", SNonce || ANonce ||
960 * BSSID || STA-ADDR)
961 */
962 pos = buf;
963 os_memcpy(pos, snonce, WPA_NONCE_LEN);
964 pos += WPA_NONCE_LEN;
965 os_memcpy(pos, anonce, WPA_NONCE_LEN);
966 pos += WPA_NONCE_LEN;
967 os_memcpy(pos, bssid, ETH_ALEN);
968 pos += ETH_ALEN;
969 os_memcpy(pos, sta_addr, ETH_ALEN);
970 pos += ETH_ALEN;
971
Dmitry Shmidt807291d2015-01-27 13:40:23 -0800972 ptk->kck_len = wpa_kck_len(akmp);
973 ptk->kek_len = wpa_kek_len(akmp);
974 ptk->tk_len = wpa_cipher_key_len(cipher);
975 ptk_len = ptk->kck_len + ptk->kek_len + ptk->tk_len;
976
977 sha256_prf(pmk_r1, PMK_LEN, "FT-PTK", buf, pos - buf, tmp, ptk_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700978
979 /*
980 * PTKName = Truncate-128(SHA-256(PMKR1Name || "FT-PTKN" || SNonce ||
981 * ANonce || BSSID || STA-ADDR))
982 */
983 addr[0] = pmk_r1_name;
984 len[0] = WPA_PMK_NAME_LEN;
985 addr[1] = (const u8 *) "FT-PTKN";
986 len[1] = 7;
987 addr[2] = snonce;
988 len[2] = WPA_NONCE_LEN;
989 addr[3] = anonce;
990 len[3] = WPA_NONCE_LEN;
991 addr[4] = bssid;
992 len[4] = ETH_ALEN;
993 addr[5] = sta_addr;
994 len[5] = ETH_ALEN;
995
996 sha256_vector(6, addr, len, hash);
997 os_memcpy(ptk_name, hash, WPA_PMK_NAME_LEN);
Dmitry Shmidt807291d2015-01-27 13:40:23 -0800998
999 os_memcpy(ptk->kck, tmp, ptk->kck_len);
1000 os_memcpy(ptk->kek, tmp + ptk->kck_len, ptk->kek_len);
1001 os_memcpy(ptk->tk, tmp + ptk->kck_len + ptk->kek_len, ptk->tk_len);
1002
1003 wpa_hexdump_key(MSG_DEBUG, "FT: KCK", ptk->kck, ptk->kck_len);
1004 wpa_hexdump_key(MSG_DEBUG, "FT: KEK", ptk->kek, ptk->kek_len);
1005 wpa_hexdump_key(MSG_DEBUG, "FT: TK", ptk->tk, ptk->tk_len);
1006 wpa_hexdump(MSG_DEBUG, "FT: PTKName", ptk_name, WPA_PMK_NAME_LEN);
1007
1008 os_memset(tmp, 0, sizeof(tmp));
1009
1010 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001011}
1012
1013#endif /* CONFIG_IEEE80211R */
1014
1015
1016/**
1017 * rsn_pmkid - Calculate PMK identifier
1018 * @pmk: Pairwise master key
1019 * @pmk_len: Length of pmk in bytes
1020 * @aa: Authenticator address
1021 * @spa: Supplicant address
1022 * @pmkid: Buffer for PMKID
1023 * @use_sha256: Whether to use SHA256-based KDF
1024 *
1025 * IEEE Std 802.11i-2004 - 8.5.1.2 Pairwise key hierarchy
1026 * PMKID = HMAC-SHA1-128(PMK, "PMK Name" || AA || SPA)
1027 */
1028void rsn_pmkid(const u8 *pmk, size_t pmk_len, const u8 *aa, const u8 *spa,
1029 u8 *pmkid, int use_sha256)
1030{
1031 char *title = "PMK Name";
1032 const u8 *addr[3];
1033 const size_t len[3] = { 8, ETH_ALEN, ETH_ALEN };
1034 unsigned char hash[SHA256_MAC_LEN];
1035
1036 addr[0] = (u8 *) title;
1037 addr[1] = aa;
1038 addr[2] = spa;
1039
1040#ifdef CONFIG_IEEE80211W
1041 if (use_sha256)
1042 hmac_sha256_vector(pmk, pmk_len, 3, addr, len, hash);
1043 else
1044#endif /* CONFIG_IEEE80211W */
1045 hmac_sha1_vector(pmk, pmk_len, 3, addr, len, hash);
1046 os_memcpy(pmkid, hash, PMKID_LEN);
1047}
1048
1049
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001050#ifdef CONFIG_SUITEB
1051/**
1052 * rsn_pmkid_suite_b - Calculate PMK identifier for Suite B AKM
1053 * @kck: Key confirmation key
1054 * @kck_len: Length of kck in bytes
1055 * @aa: Authenticator address
1056 * @spa: Supplicant address
1057 * @pmkid: Buffer for PMKID
1058 * Returns: 0 on success, -1 on failure
1059 *
1060 * IEEE Std 802.11ac-2013 - 11.6.1.3 Pairwise key hierarchy
1061 * PMKID = Truncate(HMAC-SHA-256(KCK, "PMK Name" || AA || SPA))
1062 */
1063int rsn_pmkid_suite_b(const u8 *kck, size_t kck_len, const u8 *aa,
1064 const u8 *spa, u8 *pmkid)
1065{
1066 char *title = "PMK Name";
1067 const u8 *addr[3];
1068 const size_t len[3] = { 8, ETH_ALEN, ETH_ALEN };
1069 unsigned char hash[SHA256_MAC_LEN];
1070
1071 addr[0] = (u8 *) title;
1072 addr[1] = aa;
1073 addr[2] = spa;
1074
1075 if (hmac_sha256_vector(kck, kck_len, 3, addr, len, hash) < 0)
1076 return -1;
1077 os_memcpy(pmkid, hash, PMKID_LEN);
1078 return 0;
1079}
1080#endif /* CONFIG_SUITEB */
1081
1082
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001083#ifdef CONFIG_SUITEB192
1084/**
1085 * rsn_pmkid_suite_b_192 - Calculate PMK identifier for Suite B AKM
1086 * @kck: Key confirmation key
1087 * @kck_len: Length of kck in bytes
1088 * @aa: Authenticator address
1089 * @spa: Supplicant address
1090 * @pmkid: Buffer for PMKID
1091 * Returns: 0 on success, -1 on failure
1092 *
1093 * IEEE Std 802.11ac-2013 - 11.6.1.3 Pairwise key hierarchy
1094 * PMKID = Truncate(HMAC-SHA-384(KCK, "PMK Name" || AA || SPA))
1095 */
1096int rsn_pmkid_suite_b_192(const u8 *kck, size_t kck_len, const u8 *aa,
1097 const u8 *spa, u8 *pmkid)
1098{
1099 char *title = "PMK Name";
1100 const u8 *addr[3];
1101 const size_t len[3] = { 8, ETH_ALEN, ETH_ALEN };
1102 unsigned char hash[SHA384_MAC_LEN];
1103
1104 addr[0] = (u8 *) title;
1105 addr[1] = aa;
1106 addr[2] = spa;
1107
1108 if (hmac_sha384_vector(kck, kck_len, 3, addr, len, hash) < 0)
1109 return -1;
1110 os_memcpy(pmkid, hash, PMKID_LEN);
1111 return 0;
1112}
1113#endif /* CONFIG_SUITEB192 */
1114
1115
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001116/**
1117 * wpa_cipher_txt - Convert cipher suite to a text string
1118 * @cipher: Cipher suite (WPA_CIPHER_* enum)
1119 * Returns: Pointer to a text string of the cipher suite name
1120 */
1121const char * wpa_cipher_txt(int cipher)
1122{
1123 switch (cipher) {
1124 case WPA_CIPHER_NONE:
1125 return "NONE";
1126 case WPA_CIPHER_WEP40:
1127 return "WEP-40";
1128 case WPA_CIPHER_WEP104:
1129 return "WEP-104";
1130 case WPA_CIPHER_TKIP:
1131 return "TKIP";
1132 case WPA_CIPHER_CCMP:
1133 return "CCMP";
1134 case WPA_CIPHER_CCMP | WPA_CIPHER_TKIP:
1135 return "CCMP+TKIP";
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001136 case WPA_CIPHER_GCMP:
1137 return "GCMP";
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001138 case WPA_CIPHER_GCMP_256:
1139 return "GCMP-256";
1140 case WPA_CIPHER_CCMP_256:
1141 return "CCMP-256";
1142 case WPA_CIPHER_GTK_NOT_USED:
1143 return "GTK_NOT_USED";
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001144 default:
1145 return "UNKNOWN";
1146 }
1147}
1148
1149
1150/**
1151 * wpa_key_mgmt_txt - Convert key management suite to a text string
1152 * @key_mgmt: Key management suite (WPA_KEY_MGMT_* enum)
1153 * @proto: WPA/WPA2 version (WPA_PROTO_*)
1154 * Returns: Pointer to a text string of the key management suite name
1155 */
1156const char * wpa_key_mgmt_txt(int key_mgmt, int proto)
1157{
1158 switch (key_mgmt) {
1159 case WPA_KEY_MGMT_IEEE8021X:
1160 if (proto == (WPA_PROTO_RSN | WPA_PROTO_WPA))
1161 return "WPA2+WPA/IEEE 802.1X/EAP";
1162 return proto == WPA_PROTO_RSN ?
1163 "WPA2/IEEE 802.1X/EAP" : "WPA/IEEE 802.1X/EAP";
1164 case WPA_KEY_MGMT_PSK:
1165 if (proto == (WPA_PROTO_RSN | WPA_PROTO_WPA))
1166 return "WPA2-PSK+WPA-PSK";
1167 return proto == WPA_PROTO_RSN ?
1168 "WPA2-PSK" : "WPA-PSK";
1169 case WPA_KEY_MGMT_NONE:
1170 return "NONE";
1171 case WPA_KEY_MGMT_IEEE8021X_NO_WPA:
1172 return "IEEE 802.1X (no WPA)";
1173#ifdef CONFIG_IEEE80211R
1174 case WPA_KEY_MGMT_FT_IEEE8021X:
1175 return "FT-EAP";
1176 case WPA_KEY_MGMT_FT_PSK:
1177 return "FT-PSK";
1178#endif /* CONFIG_IEEE80211R */
1179#ifdef CONFIG_IEEE80211W
1180 case WPA_KEY_MGMT_IEEE8021X_SHA256:
1181 return "WPA2-EAP-SHA256";
1182 case WPA_KEY_MGMT_PSK_SHA256:
1183 return "WPA2-PSK-SHA256";
1184#endif /* CONFIG_IEEE80211W */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001185 case WPA_KEY_MGMT_WPS:
1186 return "WPS";
1187 case WPA_KEY_MGMT_SAE:
1188 return "SAE";
1189 case WPA_KEY_MGMT_FT_SAE:
1190 return "FT-SAE";
1191 case WPA_KEY_MGMT_OSEN:
1192 return "OSEN";
1193 case WPA_KEY_MGMT_IEEE8021X_SUITE_B:
1194 return "WPA2-EAP-SUITE-B";
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001195 case WPA_KEY_MGMT_IEEE8021X_SUITE_B_192:
1196 return "WPA2-EAP-SUITE-B-192";
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001197 default:
1198 return "UNKNOWN";
1199 }
1200}
1201
1202
Dmitry Shmidt03658832014-08-13 11:03:49 -07001203u32 wpa_akm_to_suite(int akm)
1204{
1205 if (akm & WPA_KEY_MGMT_FT_IEEE8021X)
1206 return WLAN_AKM_SUITE_FT_8021X;
1207 if (akm & WPA_KEY_MGMT_FT_PSK)
1208 return WLAN_AKM_SUITE_FT_PSK;
1209 if (akm & WPA_KEY_MGMT_IEEE8021X)
1210 return WLAN_AKM_SUITE_8021X;
1211 if (akm & WPA_KEY_MGMT_IEEE8021X_SHA256)
1212 return WLAN_AKM_SUITE_8021X_SHA256;
1213 if (akm & WPA_KEY_MGMT_IEEE8021X)
1214 return WLAN_AKM_SUITE_8021X;
1215 if (akm & WPA_KEY_MGMT_PSK_SHA256)
1216 return WLAN_AKM_SUITE_PSK_SHA256;
1217 if (akm & WPA_KEY_MGMT_PSK)
1218 return WLAN_AKM_SUITE_PSK;
1219 if (akm & WPA_KEY_MGMT_CCKM)
1220 return WLAN_AKM_SUITE_CCKM;
1221 if (akm & WPA_KEY_MGMT_OSEN)
1222 return WLAN_AKM_SUITE_OSEN;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001223 if (akm & WPA_KEY_MGMT_IEEE8021X_SUITE_B)
1224 return WLAN_AKM_SUITE_8021X_SUITE_B;
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001225 if (akm & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192)
1226 return WLAN_AKM_SUITE_8021X_SUITE_B_192;
Dmitry Shmidt03658832014-08-13 11:03:49 -07001227 return 0;
1228}
1229
1230
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001231int wpa_compare_rsn_ie(int ft_initial_assoc,
1232 const u8 *ie1, size_t ie1len,
1233 const u8 *ie2, size_t ie2len)
1234{
1235 if (ie1 == NULL || ie2 == NULL)
1236 return -1;
1237
1238 if (ie1len == ie2len && os_memcmp(ie1, ie2, ie1len) == 0)
1239 return 0; /* identical IEs */
1240
1241#ifdef CONFIG_IEEE80211R
1242 if (ft_initial_assoc) {
1243 struct wpa_ie_data ie1d, ie2d;
1244 /*
1245 * The PMKID-List in RSN IE is different between Beacon/Probe
1246 * Response/(Re)Association Request frames and EAPOL-Key
1247 * messages in FT initial mobility domain association. Allow
1248 * for this, but verify that other parts of the RSN IEs are
1249 * identical.
1250 */
1251 if (wpa_parse_wpa_ie_rsn(ie1, ie1len, &ie1d) < 0 ||
1252 wpa_parse_wpa_ie_rsn(ie2, ie2len, &ie2d) < 0)
1253 return -1;
1254 if (ie1d.proto == ie2d.proto &&
1255 ie1d.pairwise_cipher == ie2d.pairwise_cipher &&
1256 ie1d.group_cipher == ie2d.group_cipher &&
1257 ie1d.key_mgmt == ie2d.key_mgmt &&
1258 ie1d.capabilities == ie2d.capabilities &&
1259 ie1d.mgmt_group_cipher == ie2d.mgmt_group_cipher)
1260 return 0;
1261 }
1262#endif /* CONFIG_IEEE80211R */
1263
1264 return -1;
1265}
1266
1267
1268#ifdef CONFIG_IEEE80211R
1269int wpa_insert_pmkid(u8 *ies, size_t ies_len, const u8 *pmkid)
1270{
1271 u8 *start, *end, *rpos, *rend;
1272 int added = 0;
1273
1274 start = ies;
1275 end = ies + ies_len;
1276
1277 while (start < end) {
1278 if (*start == WLAN_EID_RSN)
1279 break;
1280 start += 2 + start[1];
1281 }
1282 if (start >= end) {
1283 wpa_printf(MSG_ERROR, "FT: Could not find RSN IE in "
1284 "IEs data");
1285 return -1;
1286 }
1287 wpa_hexdump(MSG_DEBUG, "FT: RSN IE before modification",
1288 start, 2 + start[1]);
1289
1290 /* Find start of PMKID-Count */
1291 rpos = start + 2;
1292 rend = rpos + start[1];
1293
1294 /* Skip Version and Group Data Cipher Suite */
1295 rpos += 2 + 4;
1296 /* Skip Pairwise Cipher Suite Count and List */
1297 rpos += 2 + WPA_GET_LE16(rpos) * RSN_SELECTOR_LEN;
1298 /* Skip AKM Suite Count and List */
1299 rpos += 2 + WPA_GET_LE16(rpos) * RSN_SELECTOR_LEN;
1300
1301 if (rpos == rend) {
1302 /* Add RSN Capabilities */
1303 os_memmove(rpos + 2, rpos, end - rpos);
1304 *rpos++ = 0;
1305 *rpos++ = 0;
1306 } else {
1307 /* Skip RSN Capabilities */
1308 rpos += 2;
1309 if (rpos > rend) {
1310 wpa_printf(MSG_ERROR, "FT: Could not parse RSN IE in "
1311 "IEs data");
1312 return -1;
1313 }
1314 }
1315
1316 if (rpos == rend) {
1317 /* No PMKID-Count field included; add it */
1318 os_memmove(rpos + 2 + PMKID_LEN, rpos, end - rpos);
1319 WPA_PUT_LE16(rpos, 1);
1320 rpos += 2;
1321 os_memcpy(rpos, pmkid, PMKID_LEN);
1322 added += 2 + PMKID_LEN;
1323 start[1] += 2 + PMKID_LEN;
1324 } else {
1325 /* PMKID-Count was included; use it */
1326 if (WPA_GET_LE16(rpos) != 0) {
1327 wpa_printf(MSG_ERROR, "FT: Unexpected PMKID "
1328 "in RSN IE in EAPOL-Key data");
1329 return -1;
1330 }
1331 WPA_PUT_LE16(rpos, 1);
1332 rpos += 2;
1333 os_memmove(rpos + PMKID_LEN, rpos, end - rpos);
1334 os_memcpy(rpos, pmkid, PMKID_LEN);
1335 added += PMKID_LEN;
1336 start[1] += PMKID_LEN;
1337 }
1338
1339 wpa_hexdump(MSG_DEBUG, "FT: RSN IE after modification "
1340 "(PMKID inserted)", start, 2 + start[1]);
1341
1342 return added;
1343}
1344#endif /* CONFIG_IEEE80211R */
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07001345
1346
1347int wpa_cipher_key_len(int cipher)
1348{
1349 switch (cipher) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001350 case WPA_CIPHER_CCMP_256:
1351 case WPA_CIPHER_GCMP_256:
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07001352 case WPA_CIPHER_BIP_GMAC_256:
1353 case WPA_CIPHER_BIP_CMAC_256:
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001354 return 32;
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07001355 case WPA_CIPHER_CCMP:
1356 case WPA_CIPHER_GCMP:
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07001357 case WPA_CIPHER_AES_128_CMAC:
1358 case WPA_CIPHER_BIP_GMAC_128:
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07001359 return 16;
1360 case WPA_CIPHER_TKIP:
1361 return 32;
1362 case WPA_CIPHER_WEP104:
1363 return 13;
1364 case WPA_CIPHER_WEP40:
1365 return 5;
1366 }
1367
1368 return 0;
1369}
1370
1371
1372int wpa_cipher_rsc_len(int cipher)
1373{
1374 switch (cipher) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001375 case WPA_CIPHER_CCMP_256:
1376 case WPA_CIPHER_GCMP_256:
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07001377 case WPA_CIPHER_CCMP:
1378 case WPA_CIPHER_GCMP:
1379 case WPA_CIPHER_TKIP:
1380 return 6;
1381 case WPA_CIPHER_WEP104:
1382 case WPA_CIPHER_WEP40:
1383 return 0;
1384 }
1385
1386 return 0;
1387}
1388
1389
1390int wpa_cipher_to_alg(int cipher)
1391{
1392 switch (cipher) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001393 case WPA_CIPHER_CCMP_256:
1394 return WPA_ALG_CCMP_256;
1395 case WPA_CIPHER_GCMP_256:
1396 return WPA_ALG_GCMP_256;
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07001397 case WPA_CIPHER_CCMP:
1398 return WPA_ALG_CCMP;
1399 case WPA_CIPHER_GCMP:
1400 return WPA_ALG_GCMP;
1401 case WPA_CIPHER_TKIP:
1402 return WPA_ALG_TKIP;
1403 case WPA_CIPHER_WEP104:
1404 case WPA_CIPHER_WEP40:
1405 return WPA_ALG_WEP;
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07001406 case WPA_CIPHER_AES_128_CMAC:
1407 return WPA_ALG_IGTK;
1408 case WPA_CIPHER_BIP_GMAC_128:
1409 return WPA_ALG_BIP_GMAC_128;
1410 case WPA_CIPHER_BIP_GMAC_256:
1411 return WPA_ALG_BIP_GMAC_256;
1412 case WPA_CIPHER_BIP_CMAC_256:
1413 return WPA_ALG_BIP_CMAC_256;
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07001414 }
1415 return WPA_ALG_NONE;
1416}
1417
1418
1419int wpa_cipher_valid_pairwise(int cipher)
1420{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001421 return cipher == WPA_CIPHER_CCMP_256 ||
1422 cipher == WPA_CIPHER_GCMP_256 ||
1423 cipher == WPA_CIPHER_CCMP ||
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07001424 cipher == WPA_CIPHER_GCMP ||
1425 cipher == WPA_CIPHER_TKIP;
1426}
1427
1428
1429u32 wpa_cipher_to_suite(int proto, int cipher)
1430{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001431 if (cipher & WPA_CIPHER_CCMP_256)
1432 return RSN_CIPHER_SUITE_CCMP_256;
1433 if (cipher & WPA_CIPHER_GCMP_256)
1434 return RSN_CIPHER_SUITE_GCMP_256;
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07001435 if (cipher & WPA_CIPHER_CCMP)
1436 return (proto == WPA_PROTO_RSN ?
1437 RSN_CIPHER_SUITE_CCMP : WPA_CIPHER_SUITE_CCMP);
1438 if (cipher & WPA_CIPHER_GCMP)
1439 return RSN_CIPHER_SUITE_GCMP;
1440 if (cipher & WPA_CIPHER_TKIP)
1441 return (proto == WPA_PROTO_RSN ?
1442 RSN_CIPHER_SUITE_TKIP : WPA_CIPHER_SUITE_TKIP);
1443 if (cipher & WPA_CIPHER_WEP104)
1444 return (proto == WPA_PROTO_RSN ?
1445 RSN_CIPHER_SUITE_WEP104 : WPA_CIPHER_SUITE_WEP104);
1446 if (cipher & WPA_CIPHER_WEP40)
1447 return (proto == WPA_PROTO_RSN ?
1448 RSN_CIPHER_SUITE_WEP40 : WPA_CIPHER_SUITE_WEP40);
1449 if (cipher & WPA_CIPHER_NONE)
1450 return (proto == WPA_PROTO_RSN ?
1451 RSN_CIPHER_SUITE_NONE : WPA_CIPHER_SUITE_NONE);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001452 if (cipher & WPA_CIPHER_GTK_NOT_USED)
1453 return RSN_CIPHER_SUITE_NO_GROUP_ADDRESSED;
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07001454 if (cipher & WPA_CIPHER_AES_128_CMAC)
1455 return RSN_CIPHER_SUITE_AES_128_CMAC;
1456 if (cipher & WPA_CIPHER_BIP_GMAC_128)
1457 return RSN_CIPHER_SUITE_BIP_GMAC_128;
1458 if (cipher & WPA_CIPHER_BIP_GMAC_256)
1459 return RSN_CIPHER_SUITE_BIP_GMAC_256;
1460 if (cipher & WPA_CIPHER_BIP_CMAC_256)
1461 return RSN_CIPHER_SUITE_BIP_CMAC_256;
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07001462 return 0;
1463}
1464
1465
Dmitry Shmidt7d5c8f22014-03-03 13:53:28 -08001466int rsn_cipher_put_suites(u8 *start, int ciphers)
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07001467{
Dmitry Shmidt7d5c8f22014-03-03 13:53:28 -08001468 u8 *pos = start;
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07001469
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001470 if (ciphers & WPA_CIPHER_CCMP_256) {
1471 RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP_256);
1472 pos += RSN_SELECTOR_LEN;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001473 }
1474 if (ciphers & WPA_CIPHER_GCMP_256) {
1475 RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_GCMP_256);
1476 pos += RSN_SELECTOR_LEN;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001477 }
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07001478 if (ciphers & WPA_CIPHER_CCMP) {
1479 RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP);
1480 pos += RSN_SELECTOR_LEN;
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07001481 }
1482 if (ciphers & WPA_CIPHER_GCMP) {
1483 RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_GCMP);
1484 pos += RSN_SELECTOR_LEN;
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07001485 }
1486 if (ciphers & WPA_CIPHER_TKIP) {
1487 RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_TKIP);
1488 pos += RSN_SELECTOR_LEN;
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07001489 }
1490 if (ciphers & WPA_CIPHER_NONE) {
1491 RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_NONE);
1492 pos += RSN_SELECTOR_LEN;
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07001493 }
1494
Dmitry Shmidt7d5c8f22014-03-03 13:53:28 -08001495 return (pos - start) / RSN_SELECTOR_LEN;
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07001496}
1497
1498
Dmitry Shmidt7d5c8f22014-03-03 13:53:28 -08001499int wpa_cipher_put_suites(u8 *start, int ciphers)
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07001500{
Dmitry Shmidt7d5c8f22014-03-03 13:53:28 -08001501 u8 *pos = start;
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07001502
1503 if (ciphers & WPA_CIPHER_CCMP) {
1504 RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_CCMP);
1505 pos += WPA_SELECTOR_LEN;
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07001506 }
1507 if (ciphers & WPA_CIPHER_TKIP) {
1508 RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_TKIP);
1509 pos += WPA_SELECTOR_LEN;
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07001510 }
1511 if (ciphers & WPA_CIPHER_NONE) {
1512 RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_NONE);
1513 pos += WPA_SELECTOR_LEN;
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07001514 }
1515
Dmitry Shmidt7d5c8f22014-03-03 13:53:28 -08001516 return (pos - start) / RSN_SELECTOR_LEN;
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07001517}
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001518
1519
1520int wpa_pick_pairwise_cipher(int ciphers, int none_allowed)
1521{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001522 if (ciphers & WPA_CIPHER_CCMP_256)
1523 return WPA_CIPHER_CCMP_256;
1524 if (ciphers & WPA_CIPHER_GCMP_256)
1525 return WPA_CIPHER_GCMP_256;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001526 if (ciphers & WPA_CIPHER_CCMP)
1527 return WPA_CIPHER_CCMP;
1528 if (ciphers & WPA_CIPHER_GCMP)
1529 return WPA_CIPHER_GCMP;
1530 if (ciphers & WPA_CIPHER_TKIP)
1531 return WPA_CIPHER_TKIP;
1532 if (none_allowed && (ciphers & WPA_CIPHER_NONE))
1533 return WPA_CIPHER_NONE;
1534 return -1;
1535}
1536
1537
1538int wpa_pick_group_cipher(int ciphers)
1539{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001540 if (ciphers & WPA_CIPHER_CCMP_256)
1541 return WPA_CIPHER_CCMP_256;
1542 if (ciphers & WPA_CIPHER_GCMP_256)
1543 return WPA_CIPHER_GCMP_256;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001544 if (ciphers & WPA_CIPHER_CCMP)
1545 return WPA_CIPHER_CCMP;
1546 if (ciphers & WPA_CIPHER_GCMP)
1547 return WPA_CIPHER_GCMP;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001548 if (ciphers & WPA_CIPHER_GTK_NOT_USED)
1549 return WPA_CIPHER_GTK_NOT_USED;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001550 if (ciphers & WPA_CIPHER_TKIP)
1551 return WPA_CIPHER_TKIP;
1552 if (ciphers & WPA_CIPHER_WEP104)
1553 return WPA_CIPHER_WEP104;
1554 if (ciphers & WPA_CIPHER_WEP40)
1555 return WPA_CIPHER_WEP40;
1556 return -1;
1557}
1558
1559
1560int wpa_parse_cipher(const char *value)
1561{
1562 int val = 0, last;
1563 char *start, *end, *buf;
1564
1565 buf = os_strdup(value);
1566 if (buf == NULL)
1567 return -1;
1568 start = buf;
1569
1570 while (*start != '\0') {
1571 while (*start == ' ' || *start == '\t')
1572 start++;
1573 if (*start == '\0')
1574 break;
1575 end = start;
1576 while (*end != ' ' && *end != '\t' && *end != '\0')
1577 end++;
1578 last = *end == '\0';
1579 *end = '\0';
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001580 if (os_strcmp(start, "CCMP-256") == 0)
1581 val |= WPA_CIPHER_CCMP_256;
1582 else if (os_strcmp(start, "GCMP-256") == 0)
1583 val |= WPA_CIPHER_GCMP_256;
1584 else if (os_strcmp(start, "CCMP") == 0)
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001585 val |= WPA_CIPHER_CCMP;
1586 else if (os_strcmp(start, "GCMP") == 0)
1587 val |= WPA_CIPHER_GCMP;
1588 else if (os_strcmp(start, "TKIP") == 0)
1589 val |= WPA_CIPHER_TKIP;
1590 else if (os_strcmp(start, "WEP104") == 0)
1591 val |= WPA_CIPHER_WEP104;
1592 else if (os_strcmp(start, "WEP40") == 0)
1593 val |= WPA_CIPHER_WEP40;
1594 else if (os_strcmp(start, "NONE") == 0)
1595 val |= WPA_CIPHER_NONE;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001596 else if (os_strcmp(start, "GTK_NOT_USED") == 0)
1597 val |= WPA_CIPHER_GTK_NOT_USED;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001598 else {
1599 os_free(buf);
1600 return -1;
1601 }
1602
1603 if (last)
1604 break;
1605 start = end + 1;
1606 }
1607 os_free(buf);
1608
1609 return val;
1610}
1611
1612
1613int wpa_write_ciphers(char *start, char *end, int ciphers, const char *delim)
1614{
1615 char *pos = start;
1616 int ret;
1617
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001618 if (ciphers & WPA_CIPHER_CCMP_256) {
1619 ret = os_snprintf(pos, end - pos, "%sCCMP-256",
1620 pos == start ? "" : delim);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001621 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001622 return -1;
1623 pos += ret;
1624 }
1625 if (ciphers & WPA_CIPHER_GCMP_256) {
1626 ret = os_snprintf(pos, end - pos, "%sGCMP-256",
1627 pos == start ? "" : delim);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001628 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001629 return -1;
1630 pos += ret;
1631 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001632 if (ciphers & WPA_CIPHER_CCMP) {
1633 ret = os_snprintf(pos, end - pos, "%sCCMP",
1634 pos == start ? "" : delim);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001635 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001636 return -1;
1637 pos += ret;
1638 }
1639 if (ciphers & WPA_CIPHER_GCMP) {
1640 ret = os_snprintf(pos, end - pos, "%sGCMP",
1641 pos == start ? "" : delim);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001642 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001643 return -1;
1644 pos += ret;
1645 }
1646 if (ciphers & WPA_CIPHER_TKIP) {
1647 ret = os_snprintf(pos, end - pos, "%sTKIP",
1648 pos == start ? "" : delim);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001649 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001650 return -1;
1651 pos += ret;
1652 }
1653 if (ciphers & WPA_CIPHER_WEP104) {
1654 ret = os_snprintf(pos, end - pos, "%sWEP104",
1655 pos == start ? "" : delim);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001656 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001657 return -1;
1658 pos += ret;
1659 }
1660 if (ciphers & WPA_CIPHER_WEP40) {
1661 ret = os_snprintf(pos, end - pos, "%sWEP40",
1662 pos == start ? "" : delim);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001663 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001664 return -1;
1665 pos += ret;
1666 }
1667 if (ciphers & WPA_CIPHER_NONE) {
1668 ret = os_snprintf(pos, end - pos, "%sNONE",
1669 pos == start ? "" : delim);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001670 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001671 return -1;
1672 pos += ret;
1673 }
1674
1675 return pos - start;
1676}
1677
1678
1679int wpa_select_ap_group_cipher(int wpa, int wpa_pairwise, int rsn_pairwise)
1680{
1681 int pairwise = 0;
1682
1683 /* Select group cipher based on the enabled pairwise cipher suites */
1684 if (wpa & 1)
1685 pairwise |= wpa_pairwise;
1686 if (wpa & 2)
1687 pairwise |= rsn_pairwise;
1688
1689 if (pairwise & WPA_CIPHER_TKIP)
1690 return WPA_CIPHER_TKIP;
1691 if ((pairwise & (WPA_CIPHER_CCMP | WPA_CIPHER_GCMP)) == WPA_CIPHER_GCMP)
1692 return WPA_CIPHER_GCMP;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001693 if ((pairwise & (WPA_CIPHER_GCMP_256 | WPA_CIPHER_CCMP |
1694 WPA_CIPHER_GCMP)) == WPA_CIPHER_GCMP_256)
1695 return WPA_CIPHER_GCMP_256;
1696 if ((pairwise & (WPA_CIPHER_CCMP_256 | WPA_CIPHER_CCMP |
1697 WPA_CIPHER_GCMP)) == WPA_CIPHER_CCMP_256)
1698 return WPA_CIPHER_CCMP_256;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001699 return WPA_CIPHER_CCMP;
1700}