18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* 28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * WPA/RSN - Shared functions for supplicant and authenticator 3a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * Copyright (c) 2002-2013, Jouni Malinen <j@w1.fi> 48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 5c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * This software may be distributed under the terms of the BSD license. 6c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * See README for more details. 78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "includes.h" 108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common.h" 128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/md5.h" 138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/sha1.h" 148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/sha256.h" 158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/aes_wrap.h" 168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/crypto.h" 170207e233ee2e741f7b2c124c1366e905ebb634c8Dmitry Shmidt#include "drivers/driver.h" 188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "ieee802_11_defs.h" 198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "defs.h" 208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "wpa_common.h" 218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_eapol_key_mic - Calculate EAPOL-Key MIC 258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @key: EAPOL-Key Key Confirmation Key (KCK) 268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ver: Key descriptor version (WPA_KEY_INFO_TYPE_*) 278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @buf: Pointer to the beginning of the EAPOL header (version field) 288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @len: Length of the EAPOL frame (from EAPOL header to the end of the frame) 298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @mic: Pointer to the buffer to which the EAPOL-Key MIC is written 308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure 318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Calculate EAPOL-Key MIC for an EAPOL-Key packet. The EAPOL-Key MIC field has 338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * to be cleared (all zeroes) when calling this function. 348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Note: 'IEEE Std 802.11i-2004 - 8.5.2 EAPOL-Key frames' has an error in the 368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * description of the Key MIC calculation. It includes packet data from the 378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * beginning of the EAPOL-Key header, not EAPOL header. This incorrect change 388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * happened during final editing of the standard and the correct behavior is 398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * defined in the last draft (IEEE 802.11i/D10). 408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_eapol_key_mic(const u8 *key, int ver, const u8 *buf, size_t len, 428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *mic) 438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 hash[SHA1_MAC_LEN]; 458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (ver) { 4761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifndef CONFIG_FIPS 488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_KEY_INFO_TYPE_HMAC_MD5_RC4: 498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return hmac_md5(key, 16, buf, len, mic); 5061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_FIPS */ 518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_KEY_INFO_TYPE_HMAC_SHA1_AES: 528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hmac_sha1(key, 16, buf, len, hash)) 538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(mic, hash, MD5_MAC_LEN); 558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#if defined(CONFIG_IEEE80211R) || defined(CONFIG_IEEE80211W) 578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_KEY_INFO_TYPE_AES_128_CMAC: 588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return omac1_aes_128(key, buf, len, mic); 598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R || CONFIG_IEEE80211W */ 60f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt#ifdef CONFIG_HS20 61f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt case WPA_KEY_INFO_TYPE_AKM_DEFINED: 62f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt /* FIX: This should be based on negotiated AKM */ 63f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt return omac1_aes_128(key, buf, len, mic); 64f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt#endif /* CONFIG_HS20 */ 658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_pmk_to_ptk - Calculate PTK from PMK, addresses, and nonces 758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @pmk: Pairwise master key 768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @pmk_len: Length of PMK 778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @label: Label to use in derivation 788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @addr1: AA or SA 798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @addr2: SA or AA 808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @nonce1: ANonce or SNonce 818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @nonce2: SNonce or ANonce 828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ptk: Buffer for pairwise transient key 838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ptk_len: Length of PTK 848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @use_sha256: Whether to use SHA256-based KDF 858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * IEEE Std 802.11i-2004 - 8.5.1.2 Pairwise key hierarchy 878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * PTK = PRF-X(PMK, "Pairwise key expansion", 888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Min(AA, SA) || Max(AA, SA) || 898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Min(ANonce, SNonce) || Max(ANonce, SNonce)) 908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * STK = PRF-X(SMK, "Peer key expansion", 928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Min(MAC_I, MAC_P) || Max(MAC_I, MAC_P) || 938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Min(INonce, PNonce) || Max(INonce, PNonce)) 948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_pmk_to_ptk(const u8 *pmk, size_t pmk_len, const char *label, 968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *addr1, const u8 *addr2, 978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *nonce1, const u8 *nonce2, 988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *ptk, size_t ptk_len, int use_sha256) 998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 data[2 * ETH_ALEN + 2 * WPA_NONCE_LEN]; 1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(addr1, addr2, ETH_ALEN) < 0) { 1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(data, addr1, ETH_ALEN); 1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(data + ETH_ALEN, addr2, ETH_ALEN); 1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(data, addr2, ETH_ALEN); 1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(data + ETH_ALEN, addr1, ETH_ALEN); 1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(nonce1, nonce2, WPA_NONCE_LEN) < 0) { 1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(data + 2 * ETH_ALEN, nonce1, WPA_NONCE_LEN); 1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(data + 2 * ETH_ALEN + WPA_NONCE_LEN, nonce2, 1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_NONCE_LEN); 1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(data + 2 * ETH_ALEN, nonce2, WPA_NONCE_LEN); 1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(data + 2 * ETH_ALEN + WPA_NONCE_LEN, nonce1, 1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_NONCE_LEN); 1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211W 1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (use_sha256) 1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sha256_prf(pmk, pmk_len, label, data, sizeof(data), 1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ptk, ptk_len); 1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211W */ 1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sha1_prf(pmk, pmk_len, label, data, sizeof(data), ptk, 1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ptk_len); 1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPA: PTK derivation - A1=" MACSTR " A2=" MACSTR, 1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(addr1), MAC2STR(addr2)); 1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "WPA: Nonce1", nonce1, WPA_NONCE_LEN); 1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "WPA: Nonce2", nonce2, WPA_NONCE_LEN); 1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "WPA: PMK", pmk, pmk_len); 1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "WPA: PTK", ptk, ptk_len); 1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R 1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_ft_mic(const u8 *kck, const u8 *sta_addr, const u8 *ap_addr, 1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 transaction_seqnum, const u8 *mdie, size_t mdie_len, 1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *ftie, size_t ftie_len, 1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *rsnie, size_t rsnie_len, 1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *ric, size_t ric_len, u8 *mic) 1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *buf, *pos; 1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t buf_len; 1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf_len = 2 * ETH_ALEN + 1 + mdie_len + ftie_len + rsnie_len + ric_len; 1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf = os_malloc(buf_len); 1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (buf == NULL) 1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = buf; 1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pos, sta_addr, ETH_ALEN); 1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += ETH_ALEN; 1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pos, ap_addr, ETH_ALEN); 1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += ETH_ALEN; 1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos++ = transaction_seqnum; 1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (rsnie) { 1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pos, rsnie, rsnie_len); 1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += rsnie_len; 1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (mdie) { 1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pos, mdie, mdie_len); 1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += mdie_len; 1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ftie) { 1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct rsn_ftie *_ftie; 1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pos, ftie, ftie_len); 1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ftie_len < 2 + sizeof(*_ftie)) { 1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(buf); 1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt _ftie = (struct rsn_ftie *) (pos + 2); 1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(_ftie->mic, 0, sizeof(_ftie->mic)); 1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += ftie_len; 1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ric) { 1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pos, ric, ric_len); 1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += ric_len; 1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "FT: MIC data", buf, pos - buf); 1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (omac1_aes_128(kck, buf, pos - buf, mic)) { 1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(buf); 1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(buf); 1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1931f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 1941f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 1951f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic int wpa_ft_parse_ftie(const u8 *ie, size_t ie_len, 1961f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct wpa_ft_ies *parse) 1971f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 1981f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt const u8 *end, *pos; 1991f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 2001f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt parse->ftie = ie; 2011f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt parse->ftie_len = ie_len; 2021f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 2031f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pos = ie + sizeof(struct rsn_ftie); 2041f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt end = ie + ie_len; 2051f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 2061f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt while (pos + 2 <= end && pos + 2 + pos[1] <= end) { 2071f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt switch (pos[0]) { 2081f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt case FTIE_SUBELEM_R1KH_ID: 2091f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (pos[1] != FT_R1KH_ID_LEN) { 2101f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "FT: Invalid R1KH-ID " 2111f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "length in FTIE: %d", pos[1]); 2121f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return -1; 2131f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 2141f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt parse->r1kh_id = pos + 2; 2151f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 2161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt case FTIE_SUBELEM_GTK: 2171f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt parse->gtk = pos + 2; 2181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt parse->gtk_len = pos[1]; 2191f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 2201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt case FTIE_SUBELEM_R0KH_ID: 2211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (pos[1] < 1 || pos[1] > FT_R0KH_ID_MAX_LEN) { 2221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "FT: Invalid R0KH-ID " 2231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "length in FTIE: %d", pos[1]); 2241f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return -1; 2251f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 2261f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt parse->r0kh_id = pos + 2; 2271f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt parse->r0kh_id_len = pos[1]; 2281f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 2291f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#ifdef CONFIG_IEEE80211W 2301f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt case FTIE_SUBELEM_IGTK: 2311f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt parse->igtk = pos + 2; 2321f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt parse->igtk_len = pos[1]; 2331f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 2341f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#endif /* CONFIG_IEEE80211W */ 2351f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 2361f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 2371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pos += 2 + pos[1]; 2381f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 2391f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 2401f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return 0; 2411f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 2421f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 2431f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 2441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtint wpa_ft_parse_ies(const u8 *ies, size_t ies_len, 2451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct wpa_ft_ies *parse) 2461f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 2471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt const u8 *end, *pos; 2481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct wpa_ie_data data; 2491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt int ret; 2501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt const struct rsn_ftie *ftie; 2511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt int prot_ie_count = 0; 2521f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 2531f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt os_memset(parse, 0, sizeof(*parse)); 2541f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (ies == NULL) 2551f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return 0; 2561f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 2571f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pos = ies; 2581f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt end = ies + ies_len; 2591f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt while (pos + 2 <= end && pos + 2 + pos[1] <= end) { 2601f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt switch (pos[0]) { 2611f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt case WLAN_EID_RSN: 2621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt parse->rsn = pos + 2; 2631f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt parse->rsn_len = pos[1]; 2641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt ret = wpa_parse_wpa_ie_rsn(parse->rsn - 2, 2651f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt parse->rsn_len + 2, 2661f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt &data); 2671f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (ret < 0) { 2681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "FT: Failed to parse " 2691f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "RSN IE: %d", ret); 2701f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return -1; 2711f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 2721f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (data.num_pmkid == 1 && data.pmkid) 2731f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt parse->rsn_pmkid = data.pmkid; 2741f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 2751f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt case WLAN_EID_MOBILITY_DOMAIN: 2761f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt parse->mdie = pos + 2; 2771f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt parse->mdie_len = pos[1]; 2781f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 2791f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt case WLAN_EID_FAST_BSS_TRANSITION: 2801f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (pos[1] < sizeof(*ftie)) 2811f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return -1; 2821f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt ftie = (const struct rsn_ftie *) (pos + 2); 2831f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt prot_ie_count = ftie->mic_control[1]; 2841f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (wpa_ft_parse_ftie(pos + 2, pos[1], parse) < 0) 2851f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return -1; 2861f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 2871f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt case WLAN_EID_TIMEOUT_INTERVAL: 2881f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt parse->tie = pos + 2; 2891f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt parse->tie_len = pos[1]; 2901f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 2911f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt case WLAN_EID_RIC_DATA: 2921f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (parse->ric == NULL) 2931f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt parse->ric = pos; 2941f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 2951f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 2961f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 2971f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pos += 2 + pos[1]; 2981f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 2991f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 3001f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (prot_ie_count == 0) 3011f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return 0; /* no MIC */ 3021f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 3031f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt /* 3041f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * Check that the protected IE count matches with IEs included in the 3051f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * frame. 3061f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt */ 3071f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (parse->rsn) 3081f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt prot_ie_count--; 3091f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (parse->mdie) 3101f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt prot_ie_count--; 3111f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (parse->ftie) 3121f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt prot_ie_count--; 3131f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (prot_ie_count < 0) { 3141f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "FT: Some required IEs not included in " 3151f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "the protected IE count"); 3161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return -1; 3171f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 3181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 3191f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (prot_ie_count == 0 && parse->ric) { 3201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "FT: RIC IE(s) in the frame, but not " 3211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "included in protected IE count"); 3221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return -1; 3231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 3241f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 3251f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt /* Determine the end of the RIC IE(s) */ 3261f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pos = parse->ric; 3271f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt while (pos && pos + 2 <= end && pos + 2 + pos[1] <= end && 3281f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt prot_ie_count) { 3291f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt prot_ie_count--; 3301f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pos += 2 + pos[1]; 3311f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 3321f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt parse->ric_len = pos - parse->ric; 3331f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (prot_ie_count) { 3341f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "FT: %d protected IEs missing from " 3351f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "frame", (int) prot_ie_count); 3361f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return -1; 3371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 3381f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 3391f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return 0; 3401f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */ 3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int rsn_selector_to_bitfield(const u8 *s) 3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_NONE) 3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return WPA_CIPHER_NONE; 3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_WEP40) 3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return WPA_CIPHER_WEP40; 3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_TKIP) 3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return WPA_CIPHER_TKIP; 3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_CCMP) 3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return WPA_CIPHER_CCMP; 3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_WEP104) 3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return WPA_CIPHER_WEP104; 3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211W 3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_AES_128_CMAC) 3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return WPA_CIPHER_AES_128_CMAC; 3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211W */ 36061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_GCMP) 36161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return WPA_CIPHER_GCMP; 362fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_CCMP_256) 363fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt return WPA_CIPHER_CCMP_256; 364fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_GCMP_256) 365fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt return WPA_CIPHER_GCMP_256; 366fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_BIP_GMAC_128) 367fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt return WPA_CIPHER_BIP_GMAC_128; 368fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_BIP_GMAC_256) 369fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt return WPA_CIPHER_BIP_GMAC_256; 370fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_BIP_CMAC_256) 371fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt return WPA_CIPHER_BIP_CMAC_256; 372b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_NO_GROUP_ADDRESSED) 373b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt return WPA_CIPHER_GTK_NOT_USED; 3748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int rsn_key_mgmt_to_bitfield(const u8 *s) 3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_UNSPEC_802_1X) 3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return WPA_KEY_MGMT_IEEE8021X; 3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X) 3838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return WPA_KEY_MGMT_PSK; 3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R 3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_FT_802_1X) 3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return WPA_KEY_MGMT_FT_IEEE8021X; 3878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_FT_PSK) 3888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return WPA_KEY_MGMT_FT_PSK; 3898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */ 3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211W 3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_802_1X_SHA256) 3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return WPA_KEY_MGMT_IEEE8021X_SHA256; 3938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_PSK_SHA256) 3948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return WPA_KEY_MGMT_PSK_SHA256; 3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211W */ 396d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt#ifdef CONFIG_SAE 397d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_SAE) 398d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt return WPA_KEY_MGMT_SAE; 399d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_FT_SAE) 400d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt return WPA_KEY_MGMT_FT_SAE; 401d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt#endif /* CONFIG_SAE */ 4028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 4038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 406b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidtstatic int wpa_cipher_valid_group(int cipher) 407b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt{ 408b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt return wpa_cipher_valid_pairwise(cipher) || 409b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt cipher == WPA_CIPHER_WEP104 || 410b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt cipher == WPA_CIPHER_WEP40 || 411b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt cipher == WPA_CIPHER_GTK_NOT_USED; 412b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt} 413b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt 414b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt 415b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt#ifdef CONFIG_IEEE80211W 416b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidtint wpa_cipher_valid_mgmt_group(int cipher) 417b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt{ 418b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt return cipher == WPA_CIPHER_AES_128_CMAC || 419b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt cipher == WPA_CIPHER_BIP_GMAC_128 || 420b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt cipher == WPA_CIPHER_BIP_GMAC_256 || 421b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt cipher == WPA_CIPHER_BIP_CMAC_256; 422b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt} 423b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt#endif /* CONFIG_IEEE80211W */ 424b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt 425b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt 4268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 4278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_parse_wpa_ie_rsn - Parse RSN IE 4288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @rsn_ie: Buffer containing RSN IE 4298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @rsn_ie_len: RSN IE buffer length (including IE number and length octets) 4308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @data: Pointer to structure that will be filled in with parsed data 4318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, <0 on failure 4328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 4338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_parse_wpa_ie_rsn(const u8 *rsn_ie, size_t rsn_ie_len, 4348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_ie_data *data) 4358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct rsn_ie_hdr *hdr; 4378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos; 4388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int left; 4398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int i, count; 4408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(data, 0, sizeof(*data)); 4428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->proto = WPA_PROTO_RSN; 4438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->pairwise_cipher = WPA_CIPHER_CCMP; 4448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->group_cipher = WPA_CIPHER_CCMP; 4458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->key_mgmt = WPA_KEY_MGMT_IEEE8021X; 4468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->capabilities = 0; 4478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->pmkid = NULL; 4488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->num_pmkid = 0; 4498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211W 4508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->mgmt_group_cipher = WPA_CIPHER_AES_128_CMAC; 4518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* CONFIG_IEEE80211W */ 4528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->mgmt_group_cipher = 0; 4538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211W */ 4548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (rsn_ie_len == 0) { 4568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* No RSN IE - fail silently */ 4578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (rsn_ie_len < sizeof(struct rsn_ie_hdr)) { 4618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "%s: ie len too short %lu", 4628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt __func__, (unsigned long) rsn_ie_len); 4638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr = (const struct rsn_ie_hdr *) rsn_ie; 4678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hdr->elem_id != WLAN_EID_RSN || 4698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr->len != rsn_ie_len - 2 || 4708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_GET_LE16(hdr->version) != RSN_VERSION) { 4718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "%s: malformed ie or unknown version", 4728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt __func__); 4738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -2; 4748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = (const u8 *) (hdr + 1); 4778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt left = rsn_ie_len - sizeof(*hdr); 4788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (left >= RSN_SELECTOR_LEN) { 4808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->group_cipher = rsn_selector_to_bitfield(pos); 481b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt if (!wpa_cipher_valid_group(data->group_cipher)) { 482b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt wpa_printf(MSG_DEBUG, "%s: invalid group cipher 0x%x", 483b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt __func__, data->group_cipher); 4848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += RSN_SELECTOR_LEN; 4878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt left -= RSN_SELECTOR_LEN; 4888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (left > 0) { 4898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "%s: ie length mismatch, %u too much", 4908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt __func__, left); 4918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -3; 4928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (left >= 2) { 4958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->pairwise_cipher = 0; 4968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt count = WPA_GET_LE16(pos); 4978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2; 4988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt left -= 2; 4998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (count == 0 || left < count * RSN_SELECTOR_LEN) { 5008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "%s: ie count botch (pairwise), " 5018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "count %u left %u", __func__, count, left); 5028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -4; 5038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; i < count; i++) { 5058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->pairwise_cipher |= rsn_selector_to_bitfield(pos); 5068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += RSN_SELECTOR_LEN; 5078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt left -= RSN_SELECTOR_LEN; 5088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211W 5108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->pairwise_cipher & WPA_CIPHER_AES_128_CMAC) { 5118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "%s: AES-128-CMAC used as " 5128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "pairwise cipher", __func__); 5138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211W */ 5168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (left == 1) { 5178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "%s: ie too short (for key mgmt)", 5188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt __func__); 5198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -5; 5208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (left >= 2) { 5238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->key_mgmt = 0; 5248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt count = WPA_GET_LE16(pos); 5258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2; 5268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt left -= 2; 5278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (count == 0 || left < count * RSN_SELECTOR_LEN) { 5288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "%s: ie count botch (key mgmt), " 5298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "count %u left %u", __func__, count, left); 5308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -6; 5318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; i < count; i++) { 5338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->key_mgmt |= rsn_key_mgmt_to_bitfield(pos); 5348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += RSN_SELECTOR_LEN; 5358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt left -= RSN_SELECTOR_LEN; 5368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (left == 1) { 5388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "%s: ie too short (for capabilities)", 5398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt __func__); 5408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -7; 5418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (left >= 2) { 5448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->capabilities = WPA_GET_LE16(pos); 5458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2; 5468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt left -= 2; 5478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (left >= 2) { 5508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->num_pmkid = WPA_GET_LE16(pos); 5518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2; 5528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt left -= 2; 5538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (left < (int) data->num_pmkid * PMKID_LEN) { 5548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "%s: PMKID underflow " 5558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(num_pmkid=%lu left=%d)", 5568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt __func__, (unsigned long) data->num_pmkid, 5578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt left); 5588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->num_pmkid = 0; 5598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -9; 5608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 5618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->pmkid = pos; 5628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += data->num_pmkid * PMKID_LEN; 5638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt left -= data->num_pmkid * PMKID_LEN; 5648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211W 5688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (left >= 4) { 5698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->mgmt_group_cipher = rsn_selector_to_bitfield(pos); 570b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt if (!wpa_cipher_valid_mgmt_group(data->mgmt_group_cipher)) { 5718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "%s: Unsupported management " 5728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "group cipher 0x%x", __func__, 5738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->mgmt_group_cipher); 5748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -10; 5758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += RSN_SELECTOR_LEN; 5778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt left -= RSN_SELECTOR_LEN; 5788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211W */ 5808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (left > 0) { 5827d5c8f257a74ac0d12828962a492e8b84ef83923Dmitry Shmidt wpa_hexdump(MSG_DEBUG, 5837d5c8f257a74ac0d12828962a492e8b84ef83923Dmitry Shmidt "wpa_parse_wpa_ie_rsn: ignore trailing bytes", 5847d5c8f257a74ac0d12828962a492e8b84ef83923Dmitry Shmidt pos, left); 5858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 5888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_selector_to_bitfield(const u8 *s) 5928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (RSN_SELECTOR_GET(s) == WPA_CIPHER_SUITE_NONE) 5948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return WPA_CIPHER_NONE; 5958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (RSN_SELECTOR_GET(s) == WPA_CIPHER_SUITE_WEP40) 5968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return WPA_CIPHER_WEP40; 5978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (RSN_SELECTOR_GET(s) == WPA_CIPHER_SUITE_TKIP) 5988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return WPA_CIPHER_TKIP; 5998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (RSN_SELECTOR_GET(s) == WPA_CIPHER_SUITE_CCMP) 6008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return WPA_CIPHER_CCMP; 6018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (RSN_SELECTOR_GET(s) == WPA_CIPHER_SUITE_WEP104) 6028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return WPA_CIPHER_WEP104; 6038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 6048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_key_mgmt_to_bitfield(const u8 *s) 6088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (RSN_SELECTOR_GET(s) == WPA_AUTH_KEY_MGMT_UNSPEC_802_1X) 6108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return WPA_KEY_MGMT_IEEE8021X; 6118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (RSN_SELECTOR_GET(s) == WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X) 6128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return WPA_KEY_MGMT_PSK; 6138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (RSN_SELECTOR_GET(s) == WPA_AUTH_KEY_MGMT_NONE) 6148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return WPA_KEY_MGMT_WPA_NONE; 6158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 6168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_parse_wpa_ie_wpa(const u8 *wpa_ie, size_t wpa_ie_len, 6208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_ie_data *data) 6218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpa_ie_hdr *hdr; 6238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos; 6248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int left; 6258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int i, count; 6268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(data, 0, sizeof(*data)); 6288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->proto = WPA_PROTO_WPA; 6298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->pairwise_cipher = WPA_CIPHER_TKIP; 6308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->group_cipher = WPA_CIPHER_TKIP; 6318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->key_mgmt = WPA_KEY_MGMT_IEEE8021X; 6328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->capabilities = 0; 6338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->pmkid = NULL; 6348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->num_pmkid = 0; 6358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->mgmt_group_cipher = 0; 6368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_ie_len == 0) { 6388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* No WPA IE - fail silently */ 6398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 6408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_ie_len < sizeof(struct wpa_ie_hdr)) { 6438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "%s: ie len too short %lu", 6448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt __func__, (unsigned long) wpa_ie_len); 6458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 6468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr = (const struct wpa_ie_hdr *) wpa_ie; 6498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hdr->elem_id != WLAN_EID_VENDOR_SPECIFIC || 6518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr->len != wpa_ie_len - 2 || 6528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RSN_SELECTOR_GET(hdr->oui) != WPA_OUI_TYPE || 6538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_GET_LE16(hdr->version) != WPA_VERSION) { 6548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "%s: malformed ie or unknown version", 6558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt __func__); 6568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -2; 6578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = (const u8 *) (hdr + 1); 6608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt left = wpa_ie_len - sizeof(*hdr); 6618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (left >= WPA_SELECTOR_LEN) { 6638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->group_cipher = wpa_selector_to_bitfield(pos); 6648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += WPA_SELECTOR_LEN; 6658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt left -= WPA_SELECTOR_LEN; 6668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (left > 0) { 6678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "%s: ie length mismatch, %u too much", 6688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt __func__, left); 6698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -3; 6708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (left >= 2) { 6738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->pairwise_cipher = 0; 6748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt count = WPA_GET_LE16(pos); 6758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2; 6768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt left -= 2; 6778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (count == 0 || left < count * WPA_SELECTOR_LEN) { 6788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "%s: ie count botch (pairwise), " 6798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "count %u left %u", __func__, count, left); 6808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -4; 6818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; i < count; i++) { 6838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->pairwise_cipher |= wpa_selector_to_bitfield(pos); 6848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += WPA_SELECTOR_LEN; 6858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt left -= WPA_SELECTOR_LEN; 6868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (left == 1) { 6888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "%s: ie too short (for key mgmt)", 6898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt __func__); 6908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -5; 6918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (left >= 2) { 6948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->key_mgmt = 0; 6958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt count = WPA_GET_LE16(pos); 6968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2; 6978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt left -= 2; 6988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (count == 0 || left < count * WPA_SELECTOR_LEN) { 6998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "%s: ie count botch (key mgmt), " 7008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "count %u left %u", __func__, count, left); 7018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -6; 7028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; i < count; i++) { 7048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->key_mgmt |= wpa_key_mgmt_to_bitfield(pos); 7058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += WPA_SELECTOR_LEN; 7068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt left -= WPA_SELECTOR_LEN; 7078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (left == 1) { 7098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "%s: ie too short (for capabilities)", 7108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt __func__); 7118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -7; 7128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (left >= 2) { 7158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->capabilities = WPA_GET_LE16(pos); 7168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2; 7178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt left -= 2; 7188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (left > 0) { 7217d5c8f257a74ac0d12828962a492e8b84ef83923Dmitry Shmidt wpa_hexdump(MSG_DEBUG, 7227d5c8f257a74ac0d12828962a492e8b84ef83923Dmitry Shmidt "wpa_parse_wpa_ie_wpa: ignore trailing bytes", 7237d5c8f257a74ac0d12828962a492e8b84ef83923Dmitry Shmidt pos, left); 7248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 7278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R 7318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 7338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_derive_pmk_r0 - Derive PMK-R0 and PMKR0Name 7348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 7358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * IEEE Std 802.11r-2008 - 8.5.1.5.3 7368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 7378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_derive_pmk_r0(const u8 *xxkey, size_t xxkey_len, 7388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *ssid, size_t ssid_len, 7398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *mdid, const u8 *r0kh_id, size_t r0kh_id_len, 7408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *s0kh_id, u8 *pmk_r0, u8 *pmk_r0_name) 7418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 buf[1 + WPA_MAX_SSID_LEN + MOBILITY_DOMAIN_ID_LEN + 1 + 7438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt FT_R0KH_ID_MAX_LEN + ETH_ALEN]; 7448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *pos, r0_key_data[48], hash[32]; 7458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *addr[2]; 7468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len[2]; 7478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 7498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * R0-Key-Data = KDF-384(XXKey, "FT-R0", 7508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * SSIDlength || SSID || MDID || R0KHlength || 7518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * R0KH-ID || S0KH-ID) 7528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * XXKey is either the second 256 bits of MSK or PSK. 7538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * PMK-R0 = L(R0-Key-Data, 0, 256) 7548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * PMK-R0Name-Salt = L(R0-Key-Data, 256, 128) 7558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 7568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ssid_len > WPA_MAX_SSID_LEN || r0kh_id_len > FT_R0KH_ID_MAX_LEN) 7578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 7588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = buf; 7598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos++ = ssid_len; 7608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pos, ssid, ssid_len); 7618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += ssid_len; 7628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pos, mdid, MOBILITY_DOMAIN_ID_LEN); 7638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += MOBILITY_DOMAIN_ID_LEN; 7648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos++ = r0kh_id_len; 7658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pos, r0kh_id, r0kh_id_len); 7668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += r0kh_id_len; 7678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pos, s0kh_id, ETH_ALEN); 7688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += ETH_ALEN; 7698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sha256_prf(xxkey, xxkey_len, "FT-R0", buf, pos - buf, 7718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt r0_key_data, sizeof(r0_key_data)); 7728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pmk_r0, r0_key_data, PMK_LEN); 7738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 7758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * PMKR0Name = Truncate-128(SHA-256("FT-R0N" || PMK-R0Name-Salt) 7768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 7778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr[0] = (const u8 *) "FT-R0N"; 7788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len[0] = 6; 7798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr[1] = r0_key_data + PMK_LEN; 7808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len[1] = 16; 7818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sha256_vector(2, addr, len, hash); 7838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pmk_r0_name, hash, WPA_PMK_NAME_LEN); 7848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 7888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_derive_pmk_r1_name - Derive PMKR1Name 7898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 7908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * IEEE Std 802.11r-2008 - 8.5.1.5.4 7918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 7928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_derive_pmk_r1_name(const u8 *pmk_r0_name, const u8 *r1kh_id, 7938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *s1kh_id, u8 *pmk_r1_name) 7948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 hash[32]; 7968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *addr[4]; 7978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len[4]; 7988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 8008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * PMKR1Name = Truncate-128(SHA-256("FT-R1N" || PMKR0Name || 8018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * R1KH-ID || S1KH-ID)) 8028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 8038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr[0] = (const u8 *) "FT-R1N"; 8048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len[0] = 6; 8058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr[1] = pmk_r0_name; 8068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len[1] = WPA_PMK_NAME_LEN; 8078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr[2] = r1kh_id; 8088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len[2] = FT_R1KH_ID_LEN; 8098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr[3] = s1kh_id; 8108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len[3] = ETH_ALEN; 8118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sha256_vector(4, addr, len, hash); 8138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pmk_r1_name, hash, WPA_PMK_NAME_LEN); 8148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 8158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 8188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_derive_pmk_r1 - Derive PMK-R1 and PMKR1Name from PMK-R0 8198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 8208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * IEEE Std 802.11r-2008 - 8.5.1.5.4 8218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 8228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_derive_pmk_r1(const u8 *pmk_r0, const u8 *pmk_r0_name, 8238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *r1kh_id, const u8 *s1kh_id, 8248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *pmk_r1, u8 *pmk_r1_name) 8258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 8268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 buf[FT_R1KH_ID_LEN + ETH_ALEN]; 8278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *pos; 8288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* PMK-R1 = KDF-256(PMK-R0, "FT-R1", R1KH-ID || S1KH-ID) */ 8308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = buf; 8318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pos, r1kh_id, FT_R1KH_ID_LEN); 8328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += FT_R1KH_ID_LEN; 8338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pos, s1kh_id, ETH_ALEN); 8348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += ETH_ALEN; 8358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sha256_prf(pmk_r0, PMK_LEN, "FT-R1", buf, pos - buf, pmk_r1, PMK_LEN); 8378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_derive_pmk_r1_name(pmk_r0_name, r1kh_id, s1kh_id, pmk_r1_name); 8398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 8408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 8438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_pmk_r1_to_ptk - Derive PTK and PTKName from PMK-R1 8448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 8458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * IEEE Std 802.11r-2008 - 8.5.1.5.5 8468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 8478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_pmk_r1_to_ptk(const u8 *pmk_r1, const u8 *snonce, const u8 *anonce, 8488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *sta_addr, const u8 *bssid, 8498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pmk_r1_name, 8508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *ptk, size_t ptk_len, u8 *ptk_name) 8518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 8528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 buf[2 * WPA_NONCE_LEN + 2 * ETH_ALEN]; 8538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *pos, hash[32]; 8548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *addr[6]; 8558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len[6]; 8568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 8588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * PTK = KDF-PTKLen(PMK-R1, "FT-PTK", SNonce || ANonce || 8598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * BSSID || STA-ADDR) 8608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 8618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = buf; 8628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pos, snonce, WPA_NONCE_LEN); 8638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += WPA_NONCE_LEN; 8648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pos, anonce, WPA_NONCE_LEN); 8658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += WPA_NONCE_LEN; 8668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pos, bssid, ETH_ALEN); 8678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += ETH_ALEN; 8688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pos, sta_addr, ETH_ALEN); 8698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += ETH_ALEN; 8708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sha256_prf(pmk_r1, PMK_LEN, "FT-PTK", buf, pos - buf, ptk, ptk_len); 8728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 8748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * PTKName = Truncate-128(SHA-256(PMKR1Name || "FT-PTKN" || SNonce || 8758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * ANonce || BSSID || STA-ADDR)) 8768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 8778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr[0] = pmk_r1_name; 8788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len[0] = WPA_PMK_NAME_LEN; 8798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr[1] = (const u8 *) "FT-PTKN"; 8808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len[1] = 7; 8818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr[2] = snonce; 8828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len[2] = WPA_NONCE_LEN; 8838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr[3] = anonce; 8848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len[3] = WPA_NONCE_LEN; 8858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr[4] = bssid; 8868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len[4] = ETH_ALEN; 8878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr[5] = sta_addr; 8888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len[5] = ETH_ALEN; 8898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sha256_vector(6, addr, len, hash); 8918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(ptk_name, hash, WPA_PMK_NAME_LEN); 8928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 8938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */ 8958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 8988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * rsn_pmkid - Calculate PMK identifier 8998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @pmk: Pairwise master key 9008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @pmk_len: Length of pmk in bytes 9018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @aa: Authenticator address 9028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @spa: Supplicant address 9038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @pmkid: Buffer for PMKID 9048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @use_sha256: Whether to use SHA256-based KDF 9058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 9068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * IEEE Std 802.11i-2004 - 8.5.1.2 Pairwise key hierarchy 9078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * PMKID = HMAC-SHA1-128(PMK, "PMK Name" || AA || SPA) 9088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 9098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid rsn_pmkid(const u8 *pmk, size_t pmk_len, const u8 *aa, const u8 *spa, 9108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *pmkid, int use_sha256) 9118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 9128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *title = "PMK Name"; 9138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *addr[3]; 9148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const size_t len[3] = { 8, ETH_ALEN, ETH_ALEN }; 9158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt unsigned char hash[SHA256_MAC_LEN]; 9168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr[0] = (u8 *) title; 9188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr[1] = aa; 9198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr[2] = spa; 9208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211W 9228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (use_sha256) 9238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hmac_sha256_vector(pmk, pmk_len, 3, addr, len, hash); 9248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 9258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211W */ 9268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hmac_sha1_vector(pmk, pmk_len, 3, addr, len, hash); 9278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pmkid, hash, PMKID_LEN); 9288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 9298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 9328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_cipher_txt - Convert cipher suite to a text string 9338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @cipher: Cipher suite (WPA_CIPHER_* enum) 9348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Pointer to a text string of the cipher suite name 9358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 9368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtconst char * wpa_cipher_txt(int cipher) 9378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 9388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (cipher) { 9398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_CIPHER_NONE: 9408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "NONE"; 9418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_CIPHER_WEP40: 9428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "WEP-40"; 9438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_CIPHER_WEP104: 9448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "WEP-104"; 9458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_CIPHER_TKIP: 9468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "TKIP"; 9478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_CIPHER_CCMP: 9488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "CCMP"; 9498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_CIPHER_CCMP | WPA_CIPHER_TKIP: 9508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "CCMP+TKIP"; 95161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt case WPA_CIPHER_GCMP: 95261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return "GCMP"; 953fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt case WPA_CIPHER_GCMP_256: 954fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt return "GCMP-256"; 955fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt case WPA_CIPHER_CCMP_256: 956fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt return "CCMP-256"; 957fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt case WPA_CIPHER_GTK_NOT_USED: 958fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt return "GTK_NOT_USED"; 9598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 9608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "UNKNOWN"; 9618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 9638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 9668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_key_mgmt_txt - Convert key management suite to a text string 9678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @key_mgmt: Key management suite (WPA_KEY_MGMT_* enum) 9688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @proto: WPA/WPA2 version (WPA_PROTO_*) 9698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Pointer to a text string of the key management suite name 9708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 9718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtconst char * wpa_key_mgmt_txt(int key_mgmt, int proto) 9728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 9738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (key_mgmt) { 9748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_KEY_MGMT_IEEE8021X: 9758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (proto == (WPA_PROTO_RSN | WPA_PROTO_WPA)) 9768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "WPA2+WPA/IEEE 802.1X/EAP"; 9778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return proto == WPA_PROTO_RSN ? 9788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA2/IEEE 802.1X/EAP" : "WPA/IEEE 802.1X/EAP"; 9798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_KEY_MGMT_PSK: 9808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (proto == (WPA_PROTO_RSN | WPA_PROTO_WPA)) 9818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "WPA2-PSK+WPA-PSK"; 9828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return proto == WPA_PROTO_RSN ? 9838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA2-PSK" : "WPA-PSK"; 9848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_KEY_MGMT_NONE: 9858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "NONE"; 9868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_KEY_MGMT_IEEE8021X_NO_WPA: 9878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "IEEE 802.1X (no WPA)"; 9888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R 9898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_KEY_MGMT_FT_IEEE8021X: 9908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "FT-EAP"; 9918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_KEY_MGMT_FT_PSK: 9928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "FT-PSK"; 9938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */ 9948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211W 9958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_KEY_MGMT_IEEE8021X_SHA256: 9968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "WPA2-EAP-SHA256"; 9978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_KEY_MGMT_PSK_SHA256: 9988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "WPA2-PSK-SHA256"; 9998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211W */ 10008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 10018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "UNKNOWN"; 10028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 10048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 100603658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidtu32 wpa_akm_to_suite(int akm) 100703658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt{ 100803658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt if (akm & WPA_KEY_MGMT_FT_IEEE8021X) 100903658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt return WLAN_AKM_SUITE_FT_8021X; 101003658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt if (akm & WPA_KEY_MGMT_FT_PSK) 101103658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt return WLAN_AKM_SUITE_FT_PSK; 101203658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt if (akm & WPA_KEY_MGMT_IEEE8021X) 101303658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt return WLAN_AKM_SUITE_8021X; 101403658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt if (akm & WPA_KEY_MGMT_IEEE8021X_SHA256) 101503658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt return WLAN_AKM_SUITE_8021X_SHA256; 101603658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt if (akm & WPA_KEY_MGMT_IEEE8021X) 101703658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt return WLAN_AKM_SUITE_8021X; 101803658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt if (akm & WPA_KEY_MGMT_PSK_SHA256) 101903658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt return WLAN_AKM_SUITE_PSK_SHA256; 102003658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt if (akm & WPA_KEY_MGMT_PSK) 102103658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt return WLAN_AKM_SUITE_PSK; 102203658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt if (akm & WPA_KEY_MGMT_CCKM) 102303658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt return WLAN_AKM_SUITE_CCKM; 102403658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt if (akm & WPA_KEY_MGMT_OSEN) 102503658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt return WLAN_AKM_SUITE_OSEN; 102603658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt return 0; 102703658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt} 102803658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt 102903658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt 10308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_compare_rsn_ie(int ft_initial_assoc, 10318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *ie1, size_t ie1len, 10328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *ie2, size_t ie2len) 10338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 10348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ie1 == NULL || ie2 == NULL) 10358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 10368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ie1len == ie2len && os_memcmp(ie1, ie2, ie1len) == 0) 10388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; /* identical IEs */ 10398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R 10418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ft_initial_assoc) { 10428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_ie_data ie1d, ie2d; 10438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 10448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * The PMKID-List in RSN IE is different between Beacon/Probe 10458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Response/(Re)Association Request frames and EAPOL-Key 10468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * messages in FT initial mobility domain association. Allow 10478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * for this, but verify that other parts of the RSN IEs are 10488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * identical. 10498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 10508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_parse_wpa_ie_rsn(ie1, ie1len, &ie1d) < 0 || 10518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_parse_wpa_ie_rsn(ie2, ie2len, &ie2d) < 0) 10528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 10538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ie1d.proto == ie2d.proto && 10548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ie1d.pairwise_cipher == ie2d.pairwise_cipher && 10558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ie1d.group_cipher == ie2d.group_cipher && 10568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ie1d.key_mgmt == ie2d.key_mgmt && 10578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ie1d.capabilities == ie2d.capabilities && 10588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ie1d.mgmt_group_cipher == ie2d.mgmt_group_cipher) 10598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 10608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */ 10628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 10648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 10658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R 10688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_insert_pmkid(u8 *ies, size_t ies_len, const u8 *pmkid) 10698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 10708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *start, *end, *rpos, *rend; 10718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int added = 0; 10728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt start = ies; 10748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt end = ies + ies_len; 10758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (start < end) { 10778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (*start == WLAN_EID_RSN) 10788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 10798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt start += 2 + start[1]; 10808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (start >= end) { 10828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "FT: Could not find RSN IE in " 10838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "IEs data"); 10848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 10858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "FT: RSN IE before modification", 10878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt start, 2 + start[1]); 10888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Find start of PMKID-Count */ 10908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rpos = start + 2; 10918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rend = rpos + start[1]; 10928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Skip Version and Group Data Cipher Suite */ 10948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rpos += 2 + 4; 10958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Skip Pairwise Cipher Suite Count and List */ 10968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rpos += 2 + WPA_GET_LE16(rpos) * RSN_SELECTOR_LEN; 10978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Skip AKM Suite Count and List */ 10988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rpos += 2 + WPA_GET_LE16(rpos) * RSN_SELECTOR_LEN; 10998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (rpos == rend) { 11018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Add RSN Capabilities */ 11028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memmove(rpos + 2, rpos, end - rpos); 11038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *rpos++ = 0; 11048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *rpos++ = 0; 11058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 11068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Skip RSN Capabilities */ 11078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rpos += 2; 11088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (rpos > rend) { 11098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "FT: Could not parse RSN IE in " 11108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "IEs data"); 11118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 11128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (rpos == rend) { 11168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* No PMKID-Count field included; add it */ 11178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memmove(rpos + 2 + PMKID_LEN, rpos, end - rpos); 11188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_LE16(rpos, 1); 11198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rpos += 2; 11208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(rpos, pmkid, PMKID_LEN); 11218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt added += 2 + PMKID_LEN; 11228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt start[1] += 2 + PMKID_LEN; 11238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 11248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* PMKID-Count was included; use it */ 11258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (WPA_GET_LE16(rpos) != 0) { 11268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "FT: Unexpected PMKID " 11278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "in RSN IE in EAPOL-Key data"); 11288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 11298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_LE16(rpos, 1); 11318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rpos += 2; 11328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memmove(rpos + PMKID_LEN, rpos, end - rpos); 11338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(rpos, pmkid, PMKID_LEN); 11348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt added += PMKID_LEN; 11358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt start[1] += PMKID_LEN; 11368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "FT: RSN IE after modification " 11398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(PMKID inserted)", start, 2 + start[1]); 11408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return added; 11428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 11438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */ 11444530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 11454530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 11464530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtint wpa_cipher_key_len(int cipher) 11474530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt{ 11484530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt switch (cipher) { 1149fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt case WPA_CIPHER_CCMP_256: 1150fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt case WPA_CIPHER_GCMP_256: 1151b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt case WPA_CIPHER_BIP_GMAC_256: 1152b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt case WPA_CIPHER_BIP_CMAC_256: 1153fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt return 32; 11544530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt case WPA_CIPHER_CCMP: 11554530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt case WPA_CIPHER_GCMP: 1156b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt case WPA_CIPHER_AES_128_CMAC: 1157b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt case WPA_CIPHER_BIP_GMAC_128: 11584530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt return 16; 11594530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt case WPA_CIPHER_TKIP: 11604530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt return 32; 11614530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt case WPA_CIPHER_WEP104: 11624530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt return 13; 11634530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt case WPA_CIPHER_WEP40: 11644530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt return 5; 11654530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt } 11664530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 11674530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt return 0; 11684530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt} 11694530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 11704530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 11714530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtint wpa_cipher_rsc_len(int cipher) 11724530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt{ 11734530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt switch (cipher) { 1174fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt case WPA_CIPHER_CCMP_256: 1175fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt case WPA_CIPHER_GCMP_256: 11764530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt case WPA_CIPHER_CCMP: 11774530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt case WPA_CIPHER_GCMP: 11784530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt case WPA_CIPHER_TKIP: 11794530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt return 6; 11804530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt case WPA_CIPHER_WEP104: 11814530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt case WPA_CIPHER_WEP40: 11824530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt return 0; 11834530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt } 11844530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 11854530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt return 0; 11864530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt} 11874530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 11884530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 11894530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtint wpa_cipher_to_alg(int cipher) 11904530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt{ 11914530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt switch (cipher) { 1192fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt case WPA_CIPHER_CCMP_256: 1193fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt return WPA_ALG_CCMP_256; 1194fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt case WPA_CIPHER_GCMP_256: 1195fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt return WPA_ALG_GCMP_256; 11964530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt case WPA_CIPHER_CCMP: 11974530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt return WPA_ALG_CCMP; 11984530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt case WPA_CIPHER_GCMP: 11994530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt return WPA_ALG_GCMP; 12004530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt case WPA_CIPHER_TKIP: 12014530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt return WPA_ALG_TKIP; 12024530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt case WPA_CIPHER_WEP104: 12034530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt case WPA_CIPHER_WEP40: 12044530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt return WPA_ALG_WEP; 1205b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt case WPA_CIPHER_AES_128_CMAC: 1206b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt return WPA_ALG_IGTK; 1207b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt case WPA_CIPHER_BIP_GMAC_128: 1208b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt return WPA_ALG_BIP_GMAC_128; 1209b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt case WPA_CIPHER_BIP_GMAC_256: 1210b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt return WPA_ALG_BIP_GMAC_256; 1211b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt case WPA_CIPHER_BIP_CMAC_256: 1212b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt return WPA_ALG_BIP_CMAC_256; 12134530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt } 12144530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt return WPA_ALG_NONE; 12154530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt} 12164530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 12174530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 12184530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtint wpa_cipher_valid_pairwise(int cipher) 12194530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt{ 1220fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt return cipher == WPA_CIPHER_CCMP_256 || 1221fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt cipher == WPA_CIPHER_GCMP_256 || 1222fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt cipher == WPA_CIPHER_CCMP || 12234530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt cipher == WPA_CIPHER_GCMP || 12244530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt cipher == WPA_CIPHER_TKIP; 12254530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt} 12264530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 12274530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 12284530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtu32 wpa_cipher_to_suite(int proto, int cipher) 12294530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt{ 1230fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (cipher & WPA_CIPHER_CCMP_256) 1231fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt return RSN_CIPHER_SUITE_CCMP_256; 1232fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (cipher & WPA_CIPHER_GCMP_256) 1233fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt return RSN_CIPHER_SUITE_GCMP_256; 12344530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (cipher & WPA_CIPHER_CCMP) 12354530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt return (proto == WPA_PROTO_RSN ? 12364530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt RSN_CIPHER_SUITE_CCMP : WPA_CIPHER_SUITE_CCMP); 12374530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (cipher & WPA_CIPHER_GCMP) 12384530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt return RSN_CIPHER_SUITE_GCMP; 12394530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (cipher & WPA_CIPHER_TKIP) 12404530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt return (proto == WPA_PROTO_RSN ? 12414530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt RSN_CIPHER_SUITE_TKIP : WPA_CIPHER_SUITE_TKIP); 12424530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (cipher & WPA_CIPHER_WEP104) 12434530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt return (proto == WPA_PROTO_RSN ? 12444530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt RSN_CIPHER_SUITE_WEP104 : WPA_CIPHER_SUITE_WEP104); 12454530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (cipher & WPA_CIPHER_WEP40) 12464530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt return (proto == WPA_PROTO_RSN ? 12474530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt RSN_CIPHER_SUITE_WEP40 : WPA_CIPHER_SUITE_WEP40); 12484530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (cipher & WPA_CIPHER_NONE) 12494530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt return (proto == WPA_PROTO_RSN ? 12504530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt RSN_CIPHER_SUITE_NONE : WPA_CIPHER_SUITE_NONE); 1251fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (cipher & WPA_CIPHER_GTK_NOT_USED) 1252fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt return RSN_CIPHER_SUITE_NO_GROUP_ADDRESSED; 1253b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt if (cipher & WPA_CIPHER_AES_128_CMAC) 1254b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt return RSN_CIPHER_SUITE_AES_128_CMAC; 1255b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt if (cipher & WPA_CIPHER_BIP_GMAC_128) 1256b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt return RSN_CIPHER_SUITE_BIP_GMAC_128; 1257b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt if (cipher & WPA_CIPHER_BIP_GMAC_256) 1258b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt return RSN_CIPHER_SUITE_BIP_GMAC_256; 1259b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt if (cipher & WPA_CIPHER_BIP_CMAC_256) 1260b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt return RSN_CIPHER_SUITE_BIP_CMAC_256; 12614530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt return 0; 12624530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt} 12634530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 12644530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 12657d5c8f257a74ac0d12828962a492e8b84ef83923Dmitry Shmidtint rsn_cipher_put_suites(u8 *start, int ciphers) 12664530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt{ 12677d5c8f257a74ac0d12828962a492e8b84ef83923Dmitry Shmidt u8 *pos = start; 12684530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 1269fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (ciphers & WPA_CIPHER_CCMP_256) { 1270fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP_256); 1271fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt pos += RSN_SELECTOR_LEN; 1272fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt } 1273fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (ciphers & WPA_CIPHER_GCMP_256) { 1274fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_GCMP_256); 1275fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt pos += RSN_SELECTOR_LEN; 1276fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt } 12774530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (ciphers & WPA_CIPHER_CCMP) { 12784530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP); 12794530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt pos += RSN_SELECTOR_LEN; 12804530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt } 12814530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (ciphers & WPA_CIPHER_GCMP) { 12824530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_GCMP); 12834530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt pos += RSN_SELECTOR_LEN; 12844530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt } 12854530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (ciphers & WPA_CIPHER_TKIP) { 12864530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_TKIP); 12874530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt pos += RSN_SELECTOR_LEN; 12884530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt } 12894530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (ciphers & WPA_CIPHER_NONE) { 12904530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_NONE); 12914530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt pos += RSN_SELECTOR_LEN; 12924530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt } 12934530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 12947d5c8f257a74ac0d12828962a492e8b84ef83923Dmitry Shmidt return (pos - start) / RSN_SELECTOR_LEN; 12954530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt} 12964530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 12974530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 12987d5c8f257a74ac0d12828962a492e8b84ef83923Dmitry Shmidtint wpa_cipher_put_suites(u8 *start, int ciphers) 12994530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt{ 13007d5c8f257a74ac0d12828962a492e8b84ef83923Dmitry Shmidt u8 *pos = start; 13014530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 13024530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (ciphers & WPA_CIPHER_CCMP) { 13034530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_CCMP); 13044530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt pos += WPA_SELECTOR_LEN; 13054530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt } 13064530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (ciphers & WPA_CIPHER_TKIP) { 13074530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_TKIP); 13084530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt pos += WPA_SELECTOR_LEN; 13094530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt } 13104530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (ciphers & WPA_CIPHER_NONE) { 13114530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_NONE); 13124530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt pos += WPA_SELECTOR_LEN; 13134530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt } 13144530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 13157d5c8f257a74ac0d12828962a492e8b84ef83923Dmitry Shmidt return (pos - start) / RSN_SELECTOR_LEN; 13164530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt} 1317a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 1318a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 1319a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidtint wpa_pick_pairwise_cipher(int ciphers, int none_allowed) 1320a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt{ 1321fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (ciphers & WPA_CIPHER_CCMP_256) 1322fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt return WPA_CIPHER_CCMP_256; 1323fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (ciphers & WPA_CIPHER_GCMP_256) 1324fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt return WPA_CIPHER_GCMP_256; 1325a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (ciphers & WPA_CIPHER_CCMP) 1326a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt return WPA_CIPHER_CCMP; 1327a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (ciphers & WPA_CIPHER_GCMP) 1328a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt return WPA_CIPHER_GCMP; 1329a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (ciphers & WPA_CIPHER_TKIP) 1330a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt return WPA_CIPHER_TKIP; 1331a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (none_allowed && (ciphers & WPA_CIPHER_NONE)) 1332a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt return WPA_CIPHER_NONE; 1333a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt return -1; 1334a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt} 1335a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 1336a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 1337a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidtint wpa_pick_group_cipher(int ciphers) 1338a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt{ 1339fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (ciphers & WPA_CIPHER_CCMP_256) 1340fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt return WPA_CIPHER_CCMP_256; 1341fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (ciphers & WPA_CIPHER_GCMP_256) 1342fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt return WPA_CIPHER_GCMP_256; 1343a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (ciphers & WPA_CIPHER_CCMP) 1344a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt return WPA_CIPHER_CCMP; 1345a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (ciphers & WPA_CIPHER_GCMP) 1346a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt return WPA_CIPHER_GCMP; 1347fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (ciphers & WPA_CIPHER_GTK_NOT_USED) 1348fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt return WPA_CIPHER_GTK_NOT_USED; 1349a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (ciphers & WPA_CIPHER_TKIP) 1350a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt return WPA_CIPHER_TKIP; 1351a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (ciphers & WPA_CIPHER_WEP104) 1352a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt return WPA_CIPHER_WEP104; 1353a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (ciphers & WPA_CIPHER_WEP40) 1354a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt return WPA_CIPHER_WEP40; 1355a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt return -1; 1356a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt} 1357a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 1358a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 1359a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidtint wpa_parse_cipher(const char *value) 1360a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt{ 1361a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt int val = 0, last; 1362a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt char *start, *end, *buf; 1363a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 1364a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt buf = os_strdup(value); 1365a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (buf == NULL) 1366a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt return -1; 1367a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt start = buf; 1368a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 1369a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt while (*start != '\0') { 1370a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt while (*start == ' ' || *start == '\t') 1371a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt start++; 1372a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (*start == '\0') 1373a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt break; 1374a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt end = start; 1375a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt while (*end != ' ' && *end != '\t' && *end != '\0') 1376a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt end++; 1377a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt last = *end == '\0'; 1378a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt *end = '\0'; 1379fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (os_strcmp(start, "CCMP-256") == 0) 1380fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt val |= WPA_CIPHER_CCMP_256; 1381fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt else if (os_strcmp(start, "GCMP-256") == 0) 1382fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt val |= WPA_CIPHER_GCMP_256; 1383fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt else if (os_strcmp(start, "CCMP") == 0) 1384a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt val |= WPA_CIPHER_CCMP; 1385a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt else if (os_strcmp(start, "GCMP") == 0) 1386a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt val |= WPA_CIPHER_GCMP; 1387a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt else if (os_strcmp(start, "TKIP") == 0) 1388a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt val |= WPA_CIPHER_TKIP; 1389a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt else if (os_strcmp(start, "WEP104") == 0) 1390a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt val |= WPA_CIPHER_WEP104; 1391a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt else if (os_strcmp(start, "WEP40") == 0) 1392a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt val |= WPA_CIPHER_WEP40; 1393a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt else if (os_strcmp(start, "NONE") == 0) 1394a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt val |= WPA_CIPHER_NONE; 1395fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt else if (os_strcmp(start, "GTK_NOT_USED") == 0) 1396fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt val |= WPA_CIPHER_GTK_NOT_USED; 1397a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt else { 1398a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt os_free(buf); 1399a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt return -1; 1400a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt } 1401a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 1402a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (last) 1403a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt break; 1404a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt start = end + 1; 1405a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt } 1406a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt os_free(buf); 1407a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 1408a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt return val; 1409a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt} 1410a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 1411a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 1412a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidtint wpa_write_ciphers(char *start, char *end, int ciphers, const char *delim) 1413a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt{ 1414a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt char *pos = start; 1415a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt int ret; 1416a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 1417fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (ciphers & WPA_CIPHER_CCMP_256) { 1418fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt ret = os_snprintf(pos, end - pos, "%sCCMP-256", 1419fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt pos == start ? "" : delim); 1420fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (ret < 0 || ret >= end - pos) 1421fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt return -1; 1422fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt pos += ret; 1423fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt } 1424fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (ciphers & WPA_CIPHER_GCMP_256) { 1425fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt ret = os_snprintf(pos, end - pos, "%sGCMP-256", 1426fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt pos == start ? "" : delim); 1427fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (ret < 0 || ret >= end - pos) 1428fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt return -1; 1429fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt pos += ret; 1430fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt } 1431a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (ciphers & WPA_CIPHER_CCMP) { 1432a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt ret = os_snprintf(pos, end - pos, "%sCCMP", 1433a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt pos == start ? "" : delim); 1434a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (ret < 0 || ret >= end - pos) 1435a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt return -1; 1436a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt pos += ret; 1437a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt } 1438a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (ciphers & WPA_CIPHER_GCMP) { 1439a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt ret = os_snprintf(pos, end - pos, "%sGCMP", 1440a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt pos == start ? "" : delim); 1441a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (ret < 0 || ret >= end - pos) 1442a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt return -1; 1443a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt pos += ret; 1444a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt } 1445a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (ciphers & WPA_CIPHER_TKIP) { 1446a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt ret = os_snprintf(pos, end - pos, "%sTKIP", 1447a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt pos == start ? "" : delim); 1448a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (ret < 0 || ret >= end - pos) 1449a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt return -1; 1450a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt pos += ret; 1451a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt } 1452a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (ciphers & WPA_CIPHER_WEP104) { 1453a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt ret = os_snprintf(pos, end - pos, "%sWEP104", 1454a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt pos == start ? "" : delim); 1455a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (ret < 0 || ret >= end - pos) 1456a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt return -1; 1457a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt pos += ret; 1458a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt } 1459a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (ciphers & WPA_CIPHER_WEP40) { 1460a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt ret = os_snprintf(pos, end - pos, "%sWEP40", 1461a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt pos == start ? "" : delim); 1462a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (ret < 0 || ret >= end - pos) 1463a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt return -1; 1464a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt pos += ret; 1465a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt } 1466a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (ciphers & WPA_CIPHER_NONE) { 1467a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt ret = os_snprintf(pos, end - pos, "%sNONE", 1468a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt pos == start ? "" : delim); 1469a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (ret < 0 || ret >= end - pos) 1470a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt return -1; 1471a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt pos += ret; 1472a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt } 1473a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 1474a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt return pos - start; 1475a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt} 1476a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 1477a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 1478a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidtint wpa_select_ap_group_cipher(int wpa, int wpa_pairwise, int rsn_pairwise) 1479a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt{ 1480a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt int pairwise = 0; 1481a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 1482a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt /* Select group cipher based on the enabled pairwise cipher suites */ 1483a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (wpa & 1) 1484a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt pairwise |= wpa_pairwise; 1485a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (wpa & 2) 1486a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt pairwise |= rsn_pairwise; 1487a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 1488a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (pairwise & WPA_CIPHER_TKIP) 1489a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt return WPA_CIPHER_TKIP; 1490a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if ((pairwise & (WPA_CIPHER_CCMP | WPA_CIPHER_GCMP)) == WPA_CIPHER_GCMP) 1491a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt return WPA_CIPHER_GCMP; 1492fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if ((pairwise & (WPA_CIPHER_GCMP_256 | WPA_CIPHER_CCMP | 1493fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt WPA_CIPHER_GCMP)) == WPA_CIPHER_GCMP_256) 1494fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt return WPA_CIPHER_GCMP_256; 1495fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if ((pairwise & (WPA_CIPHER_CCMP_256 | WPA_CIPHER_CCMP | 1496fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt WPA_CIPHER_GCMP)) == WPA_CIPHER_CCMP_256) 1497fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt return WPA_CIPHER_CCMP_256; 1498a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt return WPA_CIPHER_CCMP; 1499a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt} 15000207e233ee2e741f7b2c124c1366e905ebb634c8Dmitry Shmidt 15010207e233ee2e741f7b2c124c1366e905ebb634c8Dmitry Shmidt 15020207e233ee2e741f7b2c124c1366e905ebb634c8Dmitry Shmidtstatic int wpa_check_wowlan_trigger(const char *start, const char *trigger, 15030207e233ee2e741f7b2c124c1366e905ebb634c8Dmitry Shmidt int capa_trigger, u8 *param_trigger) 15040207e233ee2e741f7b2c124c1366e905ebb634c8Dmitry Shmidt{ 15050207e233ee2e741f7b2c124c1366e905ebb634c8Dmitry Shmidt if (os_strcmp(start, trigger) != 0) 15060207e233ee2e741f7b2c124c1366e905ebb634c8Dmitry Shmidt return 0; 15070207e233ee2e741f7b2c124c1366e905ebb634c8Dmitry Shmidt if (!capa_trigger) 15080207e233ee2e741f7b2c124c1366e905ebb634c8Dmitry Shmidt return 0; 15090207e233ee2e741f7b2c124c1366e905ebb634c8Dmitry Shmidt 15100207e233ee2e741f7b2c124c1366e905ebb634c8Dmitry Shmidt *param_trigger = 1; 15110207e233ee2e741f7b2c124c1366e905ebb634c8Dmitry Shmidt return 1; 15120207e233ee2e741f7b2c124c1366e905ebb634c8Dmitry Shmidt} 15130207e233ee2e741f7b2c124c1366e905ebb634c8Dmitry Shmidt 15140207e233ee2e741f7b2c124c1366e905ebb634c8Dmitry Shmidt 15150207e233ee2e741f7b2c124c1366e905ebb634c8Dmitry Shmidtstruct wowlan_triggers *wpa_get_wowlan_triggers(const char *wowlan_triggers, 15160207e233ee2e741f7b2c124c1366e905ebb634c8Dmitry Shmidt struct wpa_driver_capa *capa) 15170207e233ee2e741f7b2c124c1366e905ebb634c8Dmitry Shmidt{ 15180207e233ee2e741f7b2c124c1366e905ebb634c8Dmitry Shmidt struct wowlan_triggers *triggers; 15190207e233ee2e741f7b2c124c1366e905ebb634c8Dmitry Shmidt char *start, *end, *buf; 15200207e233ee2e741f7b2c124c1366e905ebb634c8Dmitry Shmidt int last; 15210207e233ee2e741f7b2c124c1366e905ebb634c8Dmitry Shmidt 15220207e233ee2e741f7b2c124c1366e905ebb634c8Dmitry Shmidt if (!wowlan_triggers) 15230207e233ee2e741f7b2c124c1366e905ebb634c8Dmitry Shmidt return NULL; 15240207e233ee2e741f7b2c124c1366e905ebb634c8Dmitry Shmidt 15250207e233ee2e741f7b2c124c1366e905ebb634c8Dmitry Shmidt buf = os_strdup(wowlan_triggers); 15260207e233ee2e741f7b2c124c1366e905ebb634c8Dmitry Shmidt if (buf == NULL) 15270207e233ee2e741f7b2c124c1366e905ebb634c8Dmitry Shmidt return NULL; 15280207e233ee2e741f7b2c124c1366e905ebb634c8Dmitry Shmidt 15290207e233ee2e741f7b2c124c1366e905ebb634c8Dmitry Shmidt triggers = os_zalloc(sizeof(*triggers)); 15300207e233ee2e741f7b2c124c1366e905ebb634c8Dmitry Shmidt if (triggers == NULL) 15310207e233ee2e741f7b2c124c1366e905ebb634c8Dmitry Shmidt goto out; 15320207e233ee2e741f7b2c124c1366e905ebb634c8Dmitry Shmidt 15330207e233ee2e741f7b2c124c1366e905ebb634c8Dmitry Shmidt#define CHECK_TRIGGER(trigger) \ 15340207e233ee2e741f7b2c124c1366e905ebb634c8Dmitry Shmidt wpa_check_wowlan_trigger(start, #trigger, \ 15350207e233ee2e741f7b2c124c1366e905ebb634c8Dmitry Shmidt capa->wowlan_triggers.trigger, \ 15360207e233ee2e741f7b2c124c1366e905ebb634c8Dmitry Shmidt &triggers->trigger) 15370207e233ee2e741f7b2c124c1366e905ebb634c8Dmitry Shmidt 15380207e233ee2e741f7b2c124c1366e905ebb634c8Dmitry Shmidt start = buf; 15390207e233ee2e741f7b2c124c1366e905ebb634c8Dmitry Shmidt while (*start != '\0') { 15400207e233ee2e741f7b2c124c1366e905ebb634c8Dmitry Shmidt while (isblank(*start)) 15410207e233ee2e741f7b2c124c1366e905ebb634c8Dmitry Shmidt start++; 15420207e233ee2e741f7b2c124c1366e905ebb634c8Dmitry Shmidt if (*start == '\0') 15430207e233ee2e741f7b2c124c1366e905ebb634c8Dmitry Shmidt break; 15440207e233ee2e741f7b2c124c1366e905ebb634c8Dmitry Shmidt end = start; 15450207e233ee2e741f7b2c124c1366e905ebb634c8Dmitry Shmidt while (!isblank(*end) && *end != '\0') 15460207e233ee2e741f7b2c124c1366e905ebb634c8Dmitry Shmidt end++; 15470207e233ee2e741f7b2c124c1366e905ebb634c8Dmitry Shmidt last = *end == '\0'; 15480207e233ee2e741f7b2c124c1366e905ebb634c8Dmitry Shmidt *end = '\0'; 15490207e233ee2e741f7b2c124c1366e905ebb634c8Dmitry Shmidt 15500207e233ee2e741f7b2c124c1366e905ebb634c8Dmitry Shmidt if (!CHECK_TRIGGER(any) && 15510207e233ee2e741f7b2c124c1366e905ebb634c8Dmitry Shmidt !CHECK_TRIGGER(disconnect) && 15520207e233ee2e741f7b2c124c1366e905ebb634c8Dmitry Shmidt !CHECK_TRIGGER(magic_pkt) && 15530207e233ee2e741f7b2c124c1366e905ebb634c8Dmitry Shmidt !CHECK_TRIGGER(gtk_rekey_failure) && 15540207e233ee2e741f7b2c124c1366e905ebb634c8Dmitry Shmidt !CHECK_TRIGGER(eap_identity_req) && 15550207e233ee2e741f7b2c124c1366e905ebb634c8Dmitry Shmidt !CHECK_TRIGGER(four_way_handshake) && 15560207e233ee2e741f7b2c124c1366e905ebb634c8Dmitry Shmidt !CHECK_TRIGGER(rfkill_release)) { 15570207e233ee2e741f7b2c124c1366e905ebb634c8Dmitry Shmidt wpa_printf(MSG_DEBUG, 15580207e233ee2e741f7b2c124c1366e905ebb634c8Dmitry Shmidt "Unknown/unsupported wowlan trigger '%s'", 15590207e233ee2e741f7b2c124c1366e905ebb634c8Dmitry Shmidt start); 15600207e233ee2e741f7b2c124c1366e905ebb634c8Dmitry Shmidt os_free(triggers); 15610207e233ee2e741f7b2c124c1366e905ebb634c8Dmitry Shmidt triggers = NULL; 15620207e233ee2e741f7b2c124c1366e905ebb634c8Dmitry Shmidt goto out; 15630207e233ee2e741f7b2c124c1366e905ebb634c8Dmitry Shmidt } 15640207e233ee2e741f7b2c124c1366e905ebb634c8Dmitry Shmidt 15650207e233ee2e741f7b2c124c1366e905ebb634c8Dmitry Shmidt if (last) 15660207e233ee2e741f7b2c124c1366e905ebb634c8Dmitry Shmidt break; 15670207e233ee2e741f7b2c124c1366e905ebb634c8Dmitry Shmidt start = end + 1; 15680207e233ee2e741f7b2c124c1366e905ebb634c8Dmitry Shmidt } 15690207e233ee2e741f7b2c124c1366e905ebb634c8Dmitry Shmidt#undef CHECK_TRIGGER 15700207e233ee2e741f7b2c124c1366e905ebb634c8Dmitry Shmidt 15710207e233ee2e741f7b2c124c1366e905ebb634c8Dmitry Shmidtout: 15720207e233ee2e741f7b2c124c1366e905ebb634c8Dmitry Shmidt os_free(buf); 15730207e233ee2e741f7b2c124c1366e905ebb634c8Dmitry Shmidt return triggers; 15740207e233ee2e741f7b2c124c1366e905ebb634c8Dmitry Shmidt} 1575