18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* 28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * WPA/RSN - Shared functions for supplicant and authenticator 3807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt * Copyright (c) 2002-2015, 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" 15807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt#include "crypto/sha384.h" 168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/aes_wrap.h" 178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/crypto.h" 188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "ieee802_11_defs.h" 198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "defs.h" 208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "wpa_common.h" 218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 23807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidtstatic unsigned int wpa_kck_len(int akmp) 24807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt{ 25807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt if (akmp == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) 26807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt return 24; 27807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt return 16; 28807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt} 29807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt 30807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt 31807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidtstatic unsigned int wpa_kek_len(int akmp) 32807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt{ 33807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt if (akmp == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) 34807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt return 32; 35807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt return 16; 36807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt} 37807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt 38807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt 39807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidtunsigned int wpa_mic_len(int akmp) 40807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt{ 41807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt if (akmp == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) 42807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt return 24; 43807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt return 16; 44807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt} 45807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt 46807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt 478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_eapol_key_mic - Calculate EAPOL-Key MIC 498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @key: EAPOL-Key Key Confirmation Key (KCK) 50807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt * @key_len: KCK length in octets 516c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * @akmp: WPA_KEY_MGMT_* used in key derivation 528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ver: Key descriptor version (WPA_KEY_INFO_TYPE_*) 538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @buf: Pointer to the beginning of the EAPOL header (version field) 548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @len: Length of the EAPOL frame (from EAPOL header to the end of the frame) 558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @mic: Pointer to the buffer to which the EAPOL-Key MIC is written 568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure 578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Calculate EAPOL-Key MIC for an EAPOL-Key packet. The EAPOL-Key MIC field has 598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * to be cleared (all zeroes) when calling this function. 608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Note: 'IEEE Std 802.11i-2004 - 8.5.2 EAPOL-Key frames' has an error in the 628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * description of the Key MIC calculation. It includes packet data from the 638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * beginning of the EAPOL-Key header, not EAPOL header. This incorrect change 648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * happened during final editing of the standard and the correct behavior is 658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * defined in the last draft (IEEE 802.11i/D10). 668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 67807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidtint wpa_eapol_key_mic(const u8 *key, size_t key_len, int akmp, int ver, 68807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt const u8 *buf, size_t len, u8 *mic) 698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 70807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt u8 hash[SHA384_MAC_LEN]; 718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (ver) { 7361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifndef CONFIG_FIPS 748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_KEY_INFO_TYPE_HMAC_MD5_RC4: 75807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt return hmac_md5(key, key_len, buf, len, mic); 7661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_FIPS */ 778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_KEY_INFO_TYPE_HMAC_SHA1_AES: 78807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt if (hmac_sha1(key, key_len, buf, len, hash)) 798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(mic, hash, MD5_MAC_LEN); 818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#if defined(CONFIG_IEEE80211R) || defined(CONFIG_IEEE80211W) 838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_KEY_INFO_TYPE_AES_128_CMAC: 848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return omac1_aes_128(key, buf, len, mic); 858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R || CONFIG_IEEE80211W */ 86f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt case WPA_KEY_INFO_TYPE_AKM_DEFINED: 876c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt switch (akmp) { 886c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt#ifdef CONFIG_HS20 896c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt case WPA_KEY_MGMT_OSEN: 906c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return omac1_aes_128(key, buf, len, mic); 91f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt#endif /* CONFIG_HS20 */ 926c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt#ifdef CONFIG_SUITEB 936c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt case WPA_KEY_MGMT_IEEE8021X_SUITE_B: 94807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt if (hmac_sha256(key, key_len, buf, len, hash)) 956c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -1; 966c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt os_memcpy(mic, hash, MD5_MAC_LEN); 976c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt break; 986c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt#endif /* CONFIG_SUITEB */ 99807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt#ifdef CONFIG_SUITEB192 100807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt case WPA_KEY_MGMT_IEEE8021X_SUITE_B_192: 101807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt if (hmac_sha384(key, key_len, buf, len, hash)) 102807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt return -1; 103807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt os_memcpy(mic, hash, 24); 104807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt break; 105807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt#endif /* CONFIG_SUITEB192 */ 1066c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt default: 1076c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -1; 1086c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 1096c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt break; 1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_pmk_to_ptk - Calculate PTK from PMK, addresses, and nonces 1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @pmk: Pairwise master key 1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @pmk_len: Length of PMK 1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @label: Label to use in derivation 1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @addr1: AA or SA 1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @addr2: SA or AA 1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @nonce1: ANonce or SNonce 1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @nonce2: SNonce or ANonce 1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ptk: Buffer for pairwise transient key 128807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt * @akmp: Negotiated AKM 129807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt * @cipher: Negotiated pairwise cipher 130807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt * Returns: 0 on success, -1 on failure 1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * IEEE Std 802.11i-2004 - 8.5.1.2 Pairwise key hierarchy 1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * PTK = PRF-X(PMK, "Pairwise key expansion", 1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Min(AA, SA) || Max(AA, SA) || 1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Min(ANonce, SNonce) || Max(ANonce, SNonce)) 1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * STK = PRF-X(SMK, "Peer key expansion", 1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Min(MAC_I, MAC_P) || Max(MAC_I, MAC_P) || 1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Min(INonce, PNonce) || Max(INonce, PNonce)) 1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 141807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidtint wpa_pmk_to_ptk(const u8 *pmk, size_t pmk_len, const char *label, 142807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt const u8 *addr1, const u8 *addr2, 143807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt const u8 *nonce1, const u8 *nonce2, 144807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt struct wpa_ptk *ptk, int akmp, int cipher) 1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 data[2 * ETH_ALEN + 2 * WPA_NONCE_LEN]; 147807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt u8 tmp[WPA_KCK_MAX_LEN + WPA_KEK_MAX_LEN + WPA_TK_MAX_LEN]; 148807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt size_t ptk_len; 1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(addr1, addr2, ETH_ALEN) < 0) { 1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(data, addr1, ETH_ALEN); 1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(data + ETH_ALEN, addr2, ETH_ALEN); 1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(data, addr2, ETH_ALEN); 1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(data + ETH_ALEN, addr1, ETH_ALEN); 1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(nonce1, nonce2, WPA_NONCE_LEN) < 0) { 1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(data + 2 * ETH_ALEN, nonce1, WPA_NONCE_LEN); 1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(data + 2 * ETH_ALEN + WPA_NONCE_LEN, nonce2, 1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_NONCE_LEN); 1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(data + 2 * ETH_ALEN, nonce2, WPA_NONCE_LEN); 1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(data + 2 * ETH_ALEN + WPA_NONCE_LEN, nonce1, 1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_NONCE_LEN); 1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 168807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt ptk->kck_len = wpa_kck_len(akmp); 169807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt ptk->kek_len = wpa_kek_len(akmp); 170807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt ptk->tk_len = wpa_cipher_key_len(cipher); 171807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt ptk_len = ptk->kck_len + ptk->kek_len + ptk->tk_len; 172807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt 1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211W 174807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt if (wpa_key_mgmt_sha256(akmp)) 1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sha256_prf(pmk, pmk_len, label, data, sizeof(data), 176807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt tmp, ptk_len); 1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211W */ 179807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt sha1_prf(pmk, pmk_len, label, data, sizeof(data), tmp, ptk_len); 1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPA: PTK derivation - A1=" MACSTR " A2=" MACSTR, 1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(addr1), MAC2STR(addr2)); 1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "WPA: Nonce1", nonce1, WPA_NONCE_LEN); 1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "WPA: Nonce2", nonce2, WPA_NONCE_LEN); 1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "WPA: PMK", pmk, pmk_len); 186807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "WPA: PTK", tmp, ptk_len); 187807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt 188807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt os_memcpy(ptk->kck, tmp, ptk->kck_len); 189807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "WPA: KCK", ptk->kck, ptk->kck_len); 190807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt 191807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt os_memcpy(ptk->kek, tmp + ptk->kck_len, ptk->kek_len); 192807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "WPA: KEK", ptk->kek, ptk->kek_len); 193807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt 194807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt os_memcpy(ptk->tk, tmp + ptk->kck_len + ptk->kek_len, ptk->tk_len); 195807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "WPA: TK", ptk->tk, ptk->tk_len); 196807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt 197807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt os_memset(tmp, 0, sizeof(tmp)); 198807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt return 0; 1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R 203807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidtint wpa_ft_mic(const u8 *kck, size_t kck_len, const u8 *sta_addr, 204807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt const u8 *ap_addr, u8 transaction_seqnum, 205807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt const u8 *mdie, size_t mdie_len, 2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *ftie, size_t ftie_len, 2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *rsnie, size_t rsnie_len, 2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *ric, size_t ric_len, u8 *mic) 2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 210f73259cc00af557e36add405799b7f2326587c13Dmitry Shmidt const u8 *addr[9]; 211f73259cc00af557e36add405799b7f2326587c13Dmitry Shmidt size_t len[9]; 212f73259cc00af557e36add405799b7f2326587c13Dmitry Shmidt size_t i, num_elem = 0; 213f73259cc00af557e36add405799b7f2326587c13Dmitry Shmidt u8 zero_mic[16]; 2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 215807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt if (kck_len != 16) { 216807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt wpa_printf(MSG_WARNING, "FT: Unsupported KCK length %u", 217807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt (unsigned int) kck_len); 218807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt return -1; 219807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt } 220807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt 221f73259cc00af557e36add405799b7f2326587c13Dmitry Shmidt addr[num_elem] = sta_addr; 222f73259cc00af557e36add405799b7f2326587c13Dmitry Shmidt len[num_elem] = ETH_ALEN; 223f73259cc00af557e36add405799b7f2326587c13Dmitry Shmidt num_elem++; 224f73259cc00af557e36add405799b7f2326587c13Dmitry Shmidt 225f73259cc00af557e36add405799b7f2326587c13Dmitry Shmidt addr[num_elem] = ap_addr; 226f73259cc00af557e36add405799b7f2326587c13Dmitry Shmidt len[num_elem] = ETH_ALEN; 227f73259cc00af557e36add405799b7f2326587c13Dmitry Shmidt num_elem++; 228f73259cc00af557e36add405799b7f2326587c13Dmitry Shmidt 229f73259cc00af557e36add405799b7f2326587c13Dmitry Shmidt addr[num_elem] = &transaction_seqnum; 230f73259cc00af557e36add405799b7f2326587c13Dmitry Shmidt len[num_elem] = 1; 231f73259cc00af557e36add405799b7f2326587c13Dmitry Shmidt num_elem++; 2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (rsnie) { 234f73259cc00af557e36add405799b7f2326587c13Dmitry Shmidt addr[num_elem] = rsnie; 235f73259cc00af557e36add405799b7f2326587c13Dmitry Shmidt len[num_elem] = rsnie_len; 236f73259cc00af557e36add405799b7f2326587c13Dmitry Shmidt num_elem++; 2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (mdie) { 239f73259cc00af557e36add405799b7f2326587c13Dmitry Shmidt addr[num_elem] = mdie; 240f73259cc00af557e36add405799b7f2326587c13Dmitry Shmidt len[num_elem] = mdie_len; 241f73259cc00af557e36add405799b7f2326587c13Dmitry Shmidt num_elem++; 2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ftie) { 244f73259cc00af557e36add405799b7f2326587c13Dmitry Shmidt if (ftie_len < 2 + sizeof(struct rsn_ftie)) 2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 246f73259cc00af557e36add405799b7f2326587c13Dmitry Shmidt 247f73259cc00af557e36add405799b7f2326587c13Dmitry Shmidt /* IE hdr and mic_control */ 248f73259cc00af557e36add405799b7f2326587c13Dmitry Shmidt addr[num_elem] = ftie; 249f73259cc00af557e36add405799b7f2326587c13Dmitry Shmidt len[num_elem] = 2 + 2; 250f73259cc00af557e36add405799b7f2326587c13Dmitry Shmidt num_elem++; 251f73259cc00af557e36add405799b7f2326587c13Dmitry Shmidt 252f73259cc00af557e36add405799b7f2326587c13Dmitry Shmidt /* MIC field with all zeros */ 253f73259cc00af557e36add405799b7f2326587c13Dmitry Shmidt os_memset(zero_mic, 0, sizeof(zero_mic)); 254f73259cc00af557e36add405799b7f2326587c13Dmitry Shmidt addr[num_elem] = zero_mic; 255f73259cc00af557e36add405799b7f2326587c13Dmitry Shmidt len[num_elem] = sizeof(zero_mic); 256f73259cc00af557e36add405799b7f2326587c13Dmitry Shmidt num_elem++; 257f73259cc00af557e36add405799b7f2326587c13Dmitry Shmidt 258f73259cc00af557e36add405799b7f2326587c13Dmitry Shmidt /* Rest of FTIE */ 259f73259cc00af557e36add405799b7f2326587c13Dmitry Shmidt addr[num_elem] = ftie + 2 + 2 + 16; 260f73259cc00af557e36add405799b7f2326587c13Dmitry Shmidt len[num_elem] = ftie_len - (2 + 2 + 16); 261f73259cc00af557e36add405799b7f2326587c13Dmitry Shmidt num_elem++; 2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ric) { 264f73259cc00af557e36add405799b7f2326587c13Dmitry Shmidt addr[num_elem] = ric; 265f73259cc00af557e36add405799b7f2326587c13Dmitry Shmidt len[num_elem] = ric_len; 266f73259cc00af557e36add405799b7f2326587c13Dmitry Shmidt num_elem++; 2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 269f73259cc00af557e36add405799b7f2326587c13Dmitry Shmidt for (i = 0; i < num_elem; i++) 270f73259cc00af557e36add405799b7f2326587c13Dmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "FT: MIC data", addr[i], len[i]); 271f73259cc00af557e36add405799b7f2326587c13Dmitry Shmidt if (omac1_aes_128_vector(kck, num_elem, addr, len, mic)) 2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2761f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 2771f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 2781f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic int wpa_ft_parse_ftie(const u8 *ie, size_t ie_len, 2791f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct wpa_ft_ies *parse) 2801f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 2811f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt const u8 *end, *pos; 2821f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 2831f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt parse->ftie = ie; 2841f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt parse->ftie_len = ie_len; 2851f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 2861f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pos = ie + sizeof(struct rsn_ftie); 2871f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt end = ie + ie_len; 2881f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 2891f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt while (pos + 2 <= end && pos + 2 + pos[1] <= end) { 2901f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt switch (pos[0]) { 2911f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt case FTIE_SUBELEM_R1KH_ID: 2921f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (pos[1] != FT_R1KH_ID_LEN) { 2931f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "FT: Invalid R1KH-ID " 2941f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "length in FTIE: %d", pos[1]); 2951f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return -1; 2961f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 2971f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt parse->r1kh_id = pos + 2; 2981f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 2991f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt case FTIE_SUBELEM_GTK: 3001f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt parse->gtk = pos + 2; 3011f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt parse->gtk_len = pos[1]; 3021f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 3031f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt case FTIE_SUBELEM_R0KH_ID: 3041f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (pos[1] < 1 || pos[1] > FT_R0KH_ID_MAX_LEN) { 3051f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "FT: Invalid R0KH-ID " 3061f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "length in FTIE: %d", pos[1]); 3071f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return -1; 3081f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 3091f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt parse->r0kh_id = pos + 2; 3101f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt parse->r0kh_id_len = pos[1]; 3111f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 3121f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#ifdef CONFIG_IEEE80211W 3131f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt case FTIE_SUBELEM_IGTK: 3141f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt parse->igtk = pos + 2; 3151f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt parse->igtk_len = pos[1]; 3161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 3171f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#endif /* CONFIG_IEEE80211W */ 3181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 3191f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 3201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pos += 2 + pos[1]; 3211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 3221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 3231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return 0; 3241f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 3251f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 3261f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 3271f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtint wpa_ft_parse_ies(const u8 *ies, size_t ies_len, 3281f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct wpa_ft_ies *parse) 3291f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 3301f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt const u8 *end, *pos; 3311f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct wpa_ie_data data; 3321f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt int ret; 3331f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt const struct rsn_ftie *ftie; 3341f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt int prot_ie_count = 0; 3351f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 3361f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt os_memset(parse, 0, sizeof(*parse)); 3371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (ies == NULL) 3381f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return 0; 3391f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 3401f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pos = ies; 3411f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt end = ies + ies_len; 3421f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt while (pos + 2 <= end && pos + 2 + pos[1] <= end) { 3431f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt switch (pos[0]) { 3441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt case WLAN_EID_RSN: 3451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt parse->rsn = pos + 2; 3461f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt parse->rsn_len = pos[1]; 3471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt ret = wpa_parse_wpa_ie_rsn(parse->rsn - 2, 3481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt parse->rsn_len + 2, 3491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt &data); 3501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (ret < 0) { 3511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "FT: Failed to parse " 3521f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "RSN IE: %d", ret); 3531f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return -1; 3541f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 3551f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (data.num_pmkid == 1 && data.pmkid) 3561f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt parse->rsn_pmkid = data.pmkid; 3571f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 3581f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt case WLAN_EID_MOBILITY_DOMAIN: 3599d9e60286e05ae45025b672636490bd12586138dDmitry Shmidt if (pos[1] < sizeof(struct rsn_mdie)) 3609d9e60286e05ae45025b672636490bd12586138dDmitry Shmidt return -1; 3611f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt parse->mdie = pos + 2; 3621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt parse->mdie_len = pos[1]; 3631f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 3641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt case WLAN_EID_FAST_BSS_TRANSITION: 3651f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (pos[1] < sizeof(*ftie)) 3661f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return -1; 3671f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt ftie = (const struct rsn_ftie *) (pos + 2); 3681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt prot_ie_count = ftie->mic_control[1]; 3691f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (wpa_ft_parse_ftie(pos + 2, pos[1], parse) < 0) 3701f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return -1; 3711f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 3721f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt case WLAN_EID_TIMEOUT_INTERVAL: 3739d9e60286e05ae45025b672636490bd12586138dDmitry Shmidt if (pos[1] != 5) 3749d9e60286e05ae45025b672636490bd12586138dDmitry Shmidt break; 3751f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt parse->tie = pos + 2; 3761f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt parse->tie_len = pos[1]; 3771f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 3781f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt case WLAN_EID_RIC_DATA: 3791f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (parse->ric == NULL) 3801f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt parse->ric = pos; 3811f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 3821f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 3831f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 3841f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pos += 2 + pos[1]; 3851f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 3861f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 3871f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (prot_ie_count == 0) 3881f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return 0; /* no MIC */ 3891f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 3901f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt /* 3911f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * Check that the protected IE count matches with IEs included in the 3921f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * frame. 3931f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt */ 3941f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (parse->rsn) 3951f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt prot_ie_count--; 3961f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (parse->mdie) 3971f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt prot_ie_count--; 3981f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (parse->ftie) 3991f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt prot_ie_count--; 4001f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (prot_ie_count < 0) { 4011f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "FT: Some required IEs not included in " 4021f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "the protected IE count"); 4031f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return -1; 4041f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 4051f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 4061f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (prot_ie_count == 0 && parse->ric) { 4071f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "FT: RIC IE(s) in the frame, but not " 4081f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "included in protected IE count"); 4091f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return -1; 4101f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 4111f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 4121f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt /* Determine the end of the RIC IE(s) */ 4131f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pos = parse->ric; 4141f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt while (pos && pos + 2 <= end && pos + 2 + pos[1] <= end && 4151f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt prot_ie_count) { 4161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt prot_ie_count--; 4171f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pos += 2 + pos[1]; 4181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 4191f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt parse->ric_len = pos - parse->ric; 4201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (prot_ie_count) { 4211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "FT: %d protected IEs missing from " 4221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "frame", (int) prot_ie_count); 4231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return -1; 4241f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 4251f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 4261f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return 0; 4271f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 4288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */ 4298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int rsn_selector_to_bitfield(const u8 *s) 4328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_NONE) 4348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return WPA_CIPHER_NONE; 4358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_TKIP) 4368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return WPA_CIPHER_TKIP; 4378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_CCMP) 4388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return WPA_CIPHER_CCMP; 4398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211W 4408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_AES_128_CMAC) 4418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return WPA_CIPHER_AES_128_CMAC; 4428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211W */ 44361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_GCMP) 44461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return WPA_CIPHER_GCMP; 445fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_CCMP_256) 446fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt return WPA_CIPHER_CCMP_256; 447fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_GCMP_256) 448fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt return WPA_CIPHER_GCMP_256; 449fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_BIP_GMAC_128) 450fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt return WPA_CIPHER_BIP_GMAC_128; 451fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_BIP_GMAC_256) 452fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt return WPA_CIPHER_BIP_GMAC_256; 453fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_BIP_CMAC_256) 454fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt return WPA_CIPHER_BIP_CMAC_256; 455b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_NO_GROUP_ADDRESSED) 456b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt return WPA_CIPHER_GTK_NOT_USED; 4578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 4588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int rsn_key_mgmt_to_bitfield(const u8 *s) 4628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_UNSPEC_802_1X) 4648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return WPA_KEY_MGMT_IEEE8021X; 4658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X) 4668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return WPA_KEY_MGMT_PSK; 4678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R 4688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_FT_802_1X) 4698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return WPA_KEY_MGMT_FT_IEEE8021X; 4708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_FT_PSK) 4718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return WPA_KEY_MGMT_FT_PSK; 4728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */ 4738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211W 4748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_802_1X_SHA256) 4758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return WPA_KEY_MGMT_IEEE8021X_SHA256; 4768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_PSK_SHA256) 4778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return WPA_KEY_MGMT_PSK_SHA256; 4788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211W */ 479d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt#ifdef CONFIG_SAE 480d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_SAE) 481d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt return WPA_KEY_MGMT_SAE; 482d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_FT_SAE) 483d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt return WPA_KEY_MGMT_FT_SAE; 484d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt#endif /* CONFIG_SAE */ 4856c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_802_1X_SUITE_B) 4866c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return WPA_KEY_MGMT_IEEE8021X_SUITE_B; 487807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_802_1X_SUITE_B_192) 488807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt return WPA_KEY_MGMT_IEEE8021X_SUITE_B_192; 489912c6ecf72fb2c84fbf17dbd0666492778dbd9fcDmitry Shmidt if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_OSEN) 490912c6ecf72fb2c84fbf17dbd0666492778dbd9fcDmitry Shmidt return WPA_KEY_MGMT_OSEN; 4918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 4928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 495b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidtstatic int wpa_cipher_valid_group(int cipher) 496b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt{ 497b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt return wpa_cipher_valid_pairwise(cipher) || 498b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt cipher == WPA_CIPHER_GTK_NOT_USED; 499b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt} 500b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt 501b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt 502b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt#ifdef CONFIG_IEEE80211W 503b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidtint wpa_cipher_valid_mgmt_group(int cipher) 504b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt{ 505b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt return cipher == WPA_CIPHER_AES_128_CMAC || 506b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt cipher == WPA_CIPHER_BIP_GMAC_128 || 507b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt cipher == WPA_CIPHER_BIP_GMAC_256 || 508b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt cipher == WPA_CIPHER_BIP_CMAC_256; 509b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt} 510b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt#endif /* CONFIG_IEEE80211W */ 511b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt 512b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt 5138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 5148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_parse_wpa_ie_rsn - Parse RSN IE 5158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @rsn_ie: Buffer containing RSN IE 5168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @rsn_ie_len: RSN IE buffer length (including IE number and length octets) 5178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @data: Pointer to structure that will be filled in with parsed data 5188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, <0 on failure 5198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 5208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_parse_wpa_ie_rsn(const u8 *rsn_ie, size_t rsn_ie_len, 5218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_ie_data *data) 5228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos; 5248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int left; 5258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int i, count; 5268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(data, 0, sizeof(*data)); 5288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->proto = WPA_PROTO_RSN; 5298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->pairwise_cipher = WPA_CIPHER_CCMP; 5308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->group_cipher = WPA_CIPHER_CCMP; 5318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->key_mgmt = WPA_KEY_MGMT_IEEE8021X; 5328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->capabilities = 0; 5338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->pmkid = NULL; 5348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->num_pmkid = 0; 5358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211W 5368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->mgmt_group_cipher = WPA_CIPHER_AES_128_CMAC; 5378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* CONFIG_IEEE80211W */ 5388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->mgmt_group_cipher = 0; 5398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211W */ 5408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (rsn_ie_len == 0) { 5428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* No RSN IE - fail silently */ 5438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (rsn_ie_len < sizeof(struct rsn_ie_hdr)) { 5478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "%s: ie len too short %lu", 5488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt __func__, (unsigned long) rsn_ie_len); 5498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 552912c6ecf72fb2c84fbf17dbd0666492778dbd9fcDmitry Shmidt if (rsn_ie_len >= 6 && rsn_ie[1] >= 4 && 553912c6ecf72fb2c84fbf17dbd0666492778dbd9fcDmitry Shmidt rsn_ie[1] == rsn_ie_len - 2 && 554912c6ecf72fb2c84fbf17dbd0666492778dbd9fcDmitry Shmidt WPA_GET_BE32(&rsn_ie[2]) == OSEN_IE_VENDOR_TYPE) { 555912c6ecf72fb2c84fbf17dbd0666492778dbd9fcDmitry Shmidt pos = rsn_ie + 6; 556912c6ecf72fb2c84fbf17dbd0666492778dbd9fcDmitry Shmidt left = rsn_ie_len - 6; 5578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 558912c6ecf72fb2c84fbf17dbd0666492778dbd9fcDmitry Shmidt data->proto = WPA_PROTO_OSEN; 559912c6ecf72fb2c84fbf17dbd0666492778dbd9fcDmitry Shmidt } else { 560912c6ecf72fb2c84fbf17dbd0666492778dbd9fcDmitry Shmidt const struct rsn_ie_hdr *hdr; 561912c6ecf72fb2c84fbf17dbd0666492778dbd9fcDmitry Shmidt 562912c6ecf72fb2c84fbf17dbd0666492778dbd9fcDmitry Shmidt hdr = (const struct rsn_ie_hdr *) rsn_ie; 5638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 564912c6ecf72fb2c84fbf17dbd0666492778dbd9fcDmitry Shmidt if (hdr->elem_id != WLAN_EID_RSN || 565912c6ecf72fb2c84fbf17dbd0666492778dbd9fcDmitry Shmidt hdr->len != rsn_ie_len - 2 || 566912c6ecf72fb2c84fbf17dbd0666492778dbd9fcDmitry Shmidt WPA_GET_LE16(hdr->version) != RSN_VERSION) { 567912c6ecf72fb2c84fbf17dbd0666492778dbd9fcDmitry Shmidt wpa_printf(MSG_DEBUG, "%s: malformed ie or unknown version", 568912c6ecf72fb2c84fbf17dbd0666492778dbd9fcDmitry Shmidt __func__); 569912c6ecf72fb2c84fbf17dbd0666492778dbd9fcDmitry Shmidt return -2; 570912c6ecf72fb2c84fbf17dbd0666492778dbd9fcDmitry Shmidt } 571912c6ecf72fb2c84fbf17dbd0666492778dbd9fcDmitry Shmidt 572912c6ecf72fb2c84fbf17dbd0666492778dbd9fcDmitry Shmidt pos = (const u8 *) (hdr + 1); 573912c6ecf72fb2c84fbf17dbd0666492778dbd9fcDmitry Shmidt left = rsn_ie_len - sizeof(*hdr); 574912c6ecf72fb2c84fbf17dbd0666492778dbd9fcDmitry Shmidt } 5758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (left >= RSN_SELECTOR_LEN) { 5778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->group_cipher = rsn_selector_to_bitfield(pos); 578b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt if (!wpa_cipher_valid_group(data->group_cipher)) { 579b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt wpa_printf(MSG_DEBUG, "%s: invalid group cipher 0x%x", 580b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt __func__, data->group_cipher); 5818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += RSN_SELECTOR_LEN; 5848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt left -= RSN_SELECTOR_LEN; 5858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (left > 0) { 5868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "%s: ie length mismatch, %u too much", 5878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt __func__, left); 5888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -3; 5898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (left >= 2) { 5928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->pairwise_cipher = 0; 5938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt count = WPA_GET_LE16(pos); 5948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2; 5958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt left -= 2; 5966c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (count == 0 || count > left / RSN_SELECTOR_LEN) { 5978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "%s: ie count botch (pairwise), " 5988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "count %u left %u", __func__, count, left); 5998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -4; 6008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; i < count; i++) { 6028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->pairwise_cipher |= rsn_selector_to_bitfield(pos); 6038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += RSN_SELECTOR_LEN; 6048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt left -= RSN_SELECTOR_LEN; 6058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211W 6078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->pairwise_cipher & WPA_CIPHER_AES_128_CMAC) { 6088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "%s: AES-128-CMAC used as " 6098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "pairwise cipher", __func__); 6108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 6118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211W */ 6138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (left == 1) { 6148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "%s: ie too short (for key mgmt)", 6158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt __func__); 6168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -5; 6178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (left >= 2) { 6208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->key_mgmt = 0; 6218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt count = WPA_GET_LE16(pos); 6228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2; 6238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt left -= 2; 6246c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (count == 0 || count > left / RSN_SELECTOR_LEN) { 6258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "%s: ie count botch (key mgmt), " 6268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "count %u left %u", __func__, count, left); 6278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -6; 6288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; i < count; i++) { 6308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->key_mgmt |= rsn_key_mgmt_to_bitfield(pos); 6318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += RSN_SELECTOR_LEN; 6328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt left -= RSN_SELECTOR_LEN; 6338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (left == 1) { 6358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "%s: ie too short (for capabilities)", 6368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt __func__); 6378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -7; 6388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (left >= 2) { 6418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->capabilities = WPA_GET_LE16(pos); 6428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2; 6438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt left -= 2; 6448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (left >= 2) { 6476c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt u16 num_pmkid = WPA_GET_LE16(pos); 6488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2; 6498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt left -= 2; 6506c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (num_pmkid > (unsigned int) left / PMKID_LEN) { 6518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "%s: PMKID underflow " 6526c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "(num_pmkid=%u left=%d)", 6536c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt __func__, num_pmkid, left); 6548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->num_pmkid = 0; 6558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -9; 6568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 6576c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt data->num_pmkid = num_pmkid; 6588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->pmkid = pos; 6598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += data->num_pmkid * PMKID_LEN; 6608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt left -= data->num_pmkid * PMKID_LEN; 6618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211W 6658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (left >= 4) { 6668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->mgmt_group_cipher = rsn_selector_to_bitfield(pos); 667b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt if (!wpa_cipher_valid_mgmt_group(data->mgmt_group_cipher)) { 6688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "%s: Unsupported management " 6698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "group cipher 0x%x", __func__, 6708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->mgmt_group_cipher); 6718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -10; 6728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += RSN_SELECTOR_LEN; 6748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt left -= RSN_SELECTOR_LEN; 6758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211W */ 6778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (left > 0) { 6797d5c8f257a74ac0d12828962a492e8b84ef83923Dmitry Shmidt wpa_hexdump(MSG_DEBUG, 6807d5c8f257a74ac0d12828962a492e8b84ef83923Dmitry Shmidt "wpa_parse_wpa_ie_rsn: ignore trailing bytes", 6817d5c8f257a74ac0d12828962a492e8b84ef83923Dmitry Shmidt pos, left); 6828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 6858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_selector_to_bitfield(const u8 *s) 6898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (RSN_SELECTOR_GET(s) == WPA_CIPHER_SUITE_NONE) 6918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return WPA_CIPHER_NONE; 6928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (RSN_SELECTOR_GET(s) == WPA_CIPHER_SUITE_TKIP) 6938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return WPA_CIPHER_TKIP; 6948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (RSN_SELECTOR_GET(s) == WPA_CIPHER_SUITE_CCMP) 6958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return WPA_CIPHER_CCMP; 6968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 6978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_key_mgmt_to_bitfield(const u8 *s) 7018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (RSN_SELECTOR_GET(s) == WPA_AUTH_KEY_MGMT_UNSPEC_802_1X) 7038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return WPA_KEY_MGMT_IEEE8021X; 7048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (RSN_SELECTOR_GET(s) == WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X) 7058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return WPA_KEY_MGMT_PSK; 7068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (RSN_SELECTOR_GET(s) == WPA_AUTH_KEY_MGMT_NONE) 7078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return WPA_KEY_MGMT_WPA_NONE; 7088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 7098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_parse_wpa_ie_wpa(const u8 *wpa_ie, size_t wpa_ie_len, 7138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_ie_data *data) 7148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpa_ie_hdr *hdr; 7168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos; 7178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int left; 7188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int i, count; 7198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(data, 0, sizeof(*data)); 7218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->proto = WPA_PROTO_WPA; 7228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->pairwise_cipher = WPA_CIPHER_TKIP; 7238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->group_cipher = WPA_CIPHER_TKIP; 7248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->key_mgmt = WPA_KEY_MGMT_IEEE8021X; 7258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->capabilities = 0; 7268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->pmkid = NULL; 7278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->num_pmkid = 0; 7288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->mgmt_group_cipher = 0; 7298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_ie_len < sizeof(struct wpa_ie_hdr)) { 7318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "%s: ie len too short %lu", 7328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt __func__, (unsigned long) wpa_ie_len); 7338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 7348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr = (const struct wpa_ie_hdr *) wpa_ie; 7378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hdr->elem_id != WLAN_EID_VENDOR_SPECIFIC || 7398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr->len != wpa_ie_len - 2 || 7408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RSN_SELECTOR_GET(hdr->oui) != WPA_OUI_TYPE || 7418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_GET_LE16(hdr->version) != WPA_VERSION) { 7428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "%s: malformed ie or unknown version", 7438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt __func__); 7448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -2; 7458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = (const u8 *) (hdr + 1); 7488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt left = wpa_ie_len - sizeof(*hdr); 7498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (left >= WPA_SELECTOR_LEN) { 7518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->group_cipher = wpa_selector_to_bitfield(pos); 7528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += WPA_SELECTOR_LEN; 7538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt left -= WPA_SELECTOR_LEN; 7548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (left > 0) { 7558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "%s: ie length mismatch, %u too much", 7568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt __func__, left); 7578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -3; 7588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (left >= 2) { 7618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->pairwise_cipher = 0; 7628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt count = WPA_GET_LE16(pos); 7638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2; 7648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt left -= 2; 7656c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (count == 0 || count > left / WPA_SELECTOR_LEN) { 7668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "%s: ie count botch (pairwise), " 7678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "count %u left %u", __func__, count, left); 7688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -4; 7698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; i < count; i++) { 7718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->pairwise_cipher |= wpa_selector_to_bitfield(pos); 7728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += WPA_SELECTOR_LEN; 7738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt left -= WPA_SELECTOR_LEN; 7748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (left == 1) { 7768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "%s: ie too short (for key mgmt)", 7778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt __func__); 7788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -5; 7798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (left >= 2) { 7828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->key_mgmt = 0; 7838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt count = WPA_GET_LE16(pos); 7848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2; 7858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt left -= 2; 7866c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (count == 0 || count > left / WPA_SELECTOR_LEN) { 7878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "%s: ie count botch (key mgmt), " 7888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "count %u left %u", __func__, count, left); 7898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -6; 7908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; i < count; i++) { 7928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->key_mgmt |= wpa_key_mgmt_to_bitfield(pos); 7938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += WPA_SELECTOR_LEN; 7948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt left -= WPA_SELECTOR_LEN; 7958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (left == 1) { 7978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "%s: ie too short (for capabilities)", 7988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt __func__); 7998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -7; 8008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (left >= 2) { 8038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->capabilities = WPA_GET_LE16(pos); 8048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2; 8058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt left -= 2; 8068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (left > 0) { 8097d5c8f257a74ac0d12828962a492e8b84ef83923Dmitry Shmidt wpa_hexdump(MSG_DEBUG, 8107d5c8f257a74ac0d12828962a492e8b84ef83923Dmitry Shmidt "wpa_parse_wpa_ie_wpa: ignore trailing bytes", 8117d5c8f257a74ac0d12828962a492e8b84ef83923Dmitry Shmidt pos, left); 8128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 8158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 8168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R 8198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 8218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_derive_pmk_r0 - Derive PMK-R0 and PMKR0Name 8228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 8238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * IEEE Std 802.11r-2008 - 8.5.1.5.3 8248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 8258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_derive_pmk_r0(const u8 *xxkey, size_t xxkey_len, 8268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *ssid, size_t ssid_len, 8278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *mdid, const u8 *r0kh_id, size_t r0kh_id_len, 8288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *s0kh_id, u8 *pmk_r0, u8 *pmk_r0_name) 8298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 8309d9e60286e05ae45025b672636490bd12586138dDmitry Shmidt u8 buf[1 + SSID_MAX_LEN + MOBILITY_DOMAIN_ID_LEN + 1 + 8318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt FT_R0KH_ID_MAX_LEN + ETH_ALEN]; 8328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *pos, r0_key_data[48], hash[32]; 8338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *addr[2]; 8348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len[2]; 8358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 8378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * R0-Key-Data = KDF-384(XXKey, "FT-R0", 8388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * SSIDlength || SSID || MDID || R0KHlength || 8398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * R0KH-ID || S0KH-ID) 8408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * XXKey is either the second 256 bits of MSK or PSK. 8418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * PMK-R0 = L(R0-Key-Data, 0, 256) 8428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * PMK-R0Name-Salt = L(R0-Key-Data, 256, 128) 8438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 8449d9e60286e05ae45025b672636490bd12586138dDmitry Shmidt if (ssid_len > SSID_MAX_LEN || r0kh_id_len > FT_R0KH_ID_MAX_LEN) 8458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 8468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = buf; 8478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos++ = ssid_len; 8488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pos, ssid, ssid_len); 8498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += ssid_len; 8508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pos, mdid, MOBILITY_DOMAIN_ID_LEN); 8518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += MOBILITY_DOMAIN_ID_LEN; 8528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos++ = r0kh_id_len; 8538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pos, r0kh_id, r0kh_id_len); 8548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += r0kh_id_len; 8558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pos, s0kh_id, ETH_ALEN); 8568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += ETH_ALEN; 8578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sha256_prf(xxkey, xxkey_len, "FT-R0", buf, pos - buf, 8598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt r0_key_data, sizeof(r0_key_data)); 8608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pmk_r0, r0_key_data, PMK_LEN); 8618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 8638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * PMKR0Name = Truncate-128(SHA-256("FT-R0N" || PMK-R0Name-Salt) 8648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 8658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr[0] = (const u8 *) "FT-R0N"; 8668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len[0] = 6; 8678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr[1] = r0_key_data + PMK_LEN; 8688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len[1] = 16; 8698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sha256_vector(2, addr, len, hash); 8718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pmk_r0_name, hash, WPA_PMK_NAME_LEN); 8728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 8738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 8768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_derive_pmk_r1_name - Derive PMKR1Name 8778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 8788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * IEEE Std 802.11r-2008 - 8.5.1.5.4 8798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 8808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_derive_pmk_r1_name(const u8 *pmk_r0_name, const u8 *r1kh_id, 8818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *s1kh_id, u8 *pmk_r1_name) 8828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 8838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 hash[32]; 8848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *addr[4]; 8858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len[4]; 8868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 8888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * PMKR1Name = Truncate-128(SHA-256("FT-R1N" || PMKR0Name || 8898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * R1KH-ID || S1KH-ID)) 8908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 8918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr[0] = (const u8 *) "FT-R1N"; 8928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len[0] = 6; 8938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr[1] = pmk_r0_name; 8948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len[1] = WPA_PMK_NAME_LEN; 8958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr[2] = r1kh_id; 8968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len[2] = FT_R1KH_ID_LEN; 8978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr[3] = s1kh_id; 8988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len[3] = ETH_ALEN; 8998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sha256_vector(4, addr, len, hash); 9018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pmk_r1_name, hash, WPA_PMK_NAME_LEN); 9028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 9038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 9068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_derive_pmk_r1 - Derive PMK-R1 and PMKR1Name from PMK-R0 9078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 9088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * IEEE Std 802.11r-2008 - 8.5.1.5.4 9098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 9108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_derive_pmk_r1(const u8 *pmk_r0, const u8 *pmk_r0_name, 9118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *r1kh_id, const u8 *s1kh_id, 9128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *pmk_r1, u8 *pmk_r1_name) 9138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 9148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 buf[FT_R1KH_ID_LEN + ETH_ALEN]; 9158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *pos; 9168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* PMK-R1 = KDF-256(PMK-R0, "FT-R1", R1KH-ID || S1KH-ID) */ 9188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = buf; 9198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pos, r1kh_id, FT_R1KH_ID_LEN); 9208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += FT_R1KH_ID_LEN; 9218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pos, s1kh_id, ETH_ALEN); 9228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += ETH_ALEN; 9238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sha256_prf(pmk_r0, PMK_LEN, "FT-R1", buf, pos - buf, pmk_r1, PMK_LEN); 9258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_derive_pmk_r1_name(pmk_r0_name, r1kh_id, s1kh_id, pmk_r1_name); 9278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 9288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 9318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_pmk_r1_to_ptk - Derive PTK and PTKName from PMK-R1 9328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 9338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * IEEE Std 802.11r-2008 - 8.5.1.5.5 9348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 935807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidtint wpa_pmk_r1_to_ptk(const u8 *pmk_r1, const u8 *snonce, const u8 *anonce, 936807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt const u8 *sta_addr, const u8 *bssid, 937807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt const u8 *pmk_r1_name, 938807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt struct wpa_ptk *ptk, u8 *ptk_name, int akmp, int cipher) 9398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 9408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 buf[2 * WPA_NONCE_LEN + 2 * ETH_ALEN]; 9418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *pos, hash[32]; 9428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *addr[6]; 9438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len[6]; 944807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt u8 tmp[WPA_KCK_MAX_LEN + WPA_KEK_MAX_LEN + WPA_TK_MAX_LEN]; 945807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt size_t ptk_len; 9468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 9488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * PTK = KDF-PTKLen(PMK-R1, "FT-PTK", SNonce || ANonce || 9498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * BSSID || STA-ADDR) 9508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 9518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = buf; 9528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pos, snonce, WPA_NONCE_LEN); 9538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += WPA_NONCE_LEN; 9548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pos, anonce, WPA_NONCE_LEN); 9558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += WPA_NONCE_LEN; 9568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pos, bssid, ETH_ALEN); 9578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += ETH_ALEN; 9588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pos, sta_addr, ETH_ALEN); 9598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += ETH_ALEN; 9608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 961807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt ptk->kck_len = wpa_kck_len(akmp); 962807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt ptk->kek_len = wpa_kek_len(akmp); 963807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt ptk->tk_len = wpa_cipher_key_len(cipher); 964807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt ptk_len = ptk->kck_len + ptk->kek_len + ptk->tk_len; 965807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt 966807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt sha256_prf(pmk_r1, PMK_LEN, "FT-PTK", buf, pos - buf, tmp, ptk_len); 9678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 9698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * PTKName = Truncate-128(SHA-256(PMKR1Name || "FT-PTKN" || SNonce || 9708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * ANonce || BSSID || STA-ADDR)) 9718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 9728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr[0] = pmk_r1_name; 9738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len[0] = WPA_PMK_NAME_LEN; 9748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr[1] = (const u8 *) "FT-PTKN"; 9758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len[1] = 7; 9768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr[2] = snonce; 9778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len[2] = WPA_NONCE_LEN; 9788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr[3] = anonce; 9798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len[3] = WPA_NONCE_LEN; 9808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr[4] = bssid; 9818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len[4] = ETH_ALEN; 9828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr[5] = sta_addr; 9838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len[5] = ETH_ALEN; 9848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sha256_vector(6, addr, len, hash); 9868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(ptk_name, hash, WPA_PMK_NAME_LEN); 987807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt 988807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt os_memcpy(ptk->kck, tmp, ptk->kck_len); 989807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt os_memcpy(ptk->kek, tmp + ptk->kck_len, ptk->kek_len); 990807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt os_memcpy(ptk->tk, tmp + ptk->kck_len + ptk->kek_len, ptk->tk_len); 991807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt 992807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "FT: KCK", ptk->kck, ptk->kck_len); 993807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "FT: KEK", ptk->kek, ptk->kek_len); 994807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "FT: TK", ptk->tk, ptk->tk_len); 995807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "FT: PTKName", ptk_name, WPA_PMK_NAME_LEN); 996807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt 997807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt os_memset(tmp, 0, sizeof(tmp)); 998807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt 999807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt return 0; 10008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 10018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */ 10038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 10068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * rsn_pmkid - Calculate PMK identifier 10078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @pmk: Pairwise master key 10088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @pmk_len: Length of pmk in bytes 10098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @aa: Authenticator address 10108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @spa: Supplicant address 10118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @pmkid: Buffer for PMKID 10128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @use_sha256: Whether to use SHA256-based KDF 10138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 10148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * IEEE Std 802.11i-2004 - 8.5.1.2 Pairwise key hierarchy 10158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * PMKID = HMAC-SHA1-128(PMK, "PMK Name" || AA || SPA) 10168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 10178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid rsn_pmkid(const u8 *pmk, size_t pmk_len, const u8 *aa, const u8 *spa, 10188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *pmkid, int use_sha256) 10198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 10208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *title = "PMK Name"; 10218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *addr[3]; 10228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const size_t len[3] = { 8, ETH_ALEN, ETH_ALEN }; 10238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt unsigned char hash[SHA256_MAC_LEN]; 10248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr[0] = (u8 *) title; 10268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr[1] = aa; 10278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr[2] = spa; 10288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211W 10308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (use_sha256) 10318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hmac_sha256_vector(pmk, pmk_len, 3, addr, len, hash); 10328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 10338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211W */ 10348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hmac_sha1_vector(pmk, pmk_len, 3, addr, len, hash); 10358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pmkid, hash, PMKID_LEN); 10368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 10378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10396c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt#ifdef CONFIG_SUITEB 10406c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt/** 10416c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * rsn_pmkid_suite_b - Calculate PMK identifier for Suite B AKM 10426c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * @kck: Key confirmation key 10436c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * @kck_len: Length of kck in bytes 10446c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * @aa: Authenticator address 10456c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * @spa: Supplicant address 10466c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * @pmkid: Buffer for PMKID 10476c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * Returns: 0 on success, -1 on failure 10486c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * 10496c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * IEEE Std 802.11ac-2013 - 11.6.1.3 Pairwise key hierarchy 10506c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * PMKID = Truncate(HMAC-SHA-256(KCK, "PMK Name" || AA || SPA)) 10516c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt */ 10526c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtint rsn_pmkid_suite_b(const u8 *kck, size_t kck_len, const u8 *aa, 10536c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt const u8 *spa, u8 *pmkid) 10546c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{ 10556c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt char *title = "PMK Name"; 10566c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt const u8 *addr[3]; 10576c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt const size_t len[3] = { 8, ETH_ALEN, ETH_ALEN }; 10586c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt unsigned char hash[SHA256_MAC_LEN]; 10596c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 10606c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt addr[0] = (u8 *) title; 10616c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt addr[1] = aa; 10626c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt addr[2] = spa; 10636c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 10646c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (hmac_sha256_vector(kck, kck_len, 3, addr, len, hash) < 0) 10656c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -1; 10666c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt os_memcpy(pmkid, hash, PMKID_LEN); 10676c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return 0; 10686c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt} 10696c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt#endif /* CONFIG_SUITEB */ 10706c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 10716c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 1072807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt#ifdef CONFIG_SUITEB192 1073807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt/** 1074807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt * rsn_pmkid_suite_b_192 - Calculate PMK identifier for Suite B AKM 1075807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt * @kck: Key confirmation key 1076807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt * @kck_len: Length of kck in bytes 1077807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt * @aa: Authenticator address 1078807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt * @spa: Supplicant address 1079807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt * @pmkid: Buffer for PMKID 1080807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt * Returns: 0 on success, -1 on failure 1081807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt * 1082807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt * IEEE Std 802.11ac-2013 - 11.6.1.3 Pairwise key hierarchy 1083807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt * PMKID = Truncate(HMAC-SHA-384(KCK, "PMK Name" || AA || SPA)) 1084807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt */ 1085807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidtint rsn_pmkid_suite_b_192(const u8 *kck, size_t kck_len, const u8 *aa, 1086807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt const u8 *spa, u8 *pmkid) 1087807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt{ 1088807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt char *title = "PMK Name"; 1089807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt const u8 *addr[3]; 1090807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt const size_t len[3] = { 8, ETH_ALEN, ETH_ALEN }; 1091807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt unsigned char hash[SHA384_MAC_LEN]; 1092807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt 1093807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt addr[0] = (u8 *) title; 1094807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt addr[1] = aa; 1095807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt addr[2] = spa; 1096807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt 1097807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt if (hmac_sha384_vector(kck, kck_len, 3, addr, len, hash) < 0) 1098807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt return -1; 1099807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt os_memcpy(pmkid, hash, PMKID_LEN); 1100807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt return 0; 1101807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt} 1102807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt#endif /* CONFIG_SUITEB192 */ 1103807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt 1104807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt 11058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 11068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_cipher_txt - Convert cipher suite to a text string 11078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @cipher: Cipher suite (WPA_CIPHER_* enum) 11088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Pointer to a text string of the cipher suite name 11098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 11108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtconst char * wpa_cipher_txt(int cipher) 11118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 11128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (cipher) { 11138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_CIPHER_NONE: 11148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "NONE"; 11158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_CIPHER_WEP40: 11168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "WEP-40"; 11178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_CIPHER_WEP104: 11188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "WEP-104"; 11198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_CIPHER_TKIP: 11208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "TKIP"; 11218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_CIPHER_CCMP: 11228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "CCMP"; 11238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_CIPHER_CCMP | WPA_CIPHER_TKIP: 11248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "CCMP+TKIP"; 112561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt case WPA_CIPHER_GCMP: 112661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return "GCMP"; 1127fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt case WPA_CIPHER_GCMP_256: 1128fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt return "GCMP-256"; 1129fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt case WPA_CIPHER_CCMP_256: 1130fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt return "CCMP-256"; 1131fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt case WPA_CIPHER_GTK_NOT_USED: 1132fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt return "GTK_NOT_USED"; 11338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 11348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "UNKNOWN"; 11358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 11378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 11408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_key_mgmt_txt - Convert key management suite to a text string 11418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @key_mgmt: Key management suite (WPA_KEY_MGMT_* enum) 11428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @proto: WPA/WPA2 version (WPA_PROTO_*) 11438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Pointer to a text string of the key management suite name 11448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 11458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtconst char * wpa_key_mgmt_txt(int key_mgmt, int proto) 11468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 11478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (key_mgmt) { 11488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_KEY_MGMT_IEEE8021X: 11498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (proto == (WPA_PROTO_RSN | WPA_PROTO_WPA)) 11508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "WPA2+WPA/IEEE 802.1X/EAP"; 11518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return proto == WPA_PROTO_RSN ? 11528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA2/IEEE 802.1X/EAP" : "WPA/IEEE 802.1X/EAP"; 11538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_KEY_MGMT_PSK: 11548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (proto == (WPA_PROTO_RSN | WPA_PROTO_WPA)) 11558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "WPA2-PSK+WPA-PSK"; 11568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return proto == WPA_PROTO_RSN ? 11578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WPA2-PSK" : "WPA-PSK"; 11588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_KEY_MGMT_NONE: 11598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "NONE"; 11608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_KEY_MGMT_IEEE8021X_NO_WPA: 11618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "IEEE 802.1X (no WPA)"; 11628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R 11638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_KEY_MGMT_FT_IEEE8021X: 11648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "FT-EAP"; 11658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_KEY_MGMT_FT_PSK: 11668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "FT-PSK"; 11678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */ 11688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211W 11698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_KEY_MGMT_IEEE8021X_SHA256: 11708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "WPA2-EAP-SHA256"; 11718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_KEY_MGMT_PSK_SHA256: 11728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "WPA2-PSK-SHA256"; 11738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211W */ 11746c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt case WPA_KEY_MGMT_WPS: 11756c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return "WPS"; 11766c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt case WPA_KEY_MGMT_SAE: 11776c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return "SAE"; 11786c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt case WPA_KEY_MGMT_FT_SAE: 11796c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return "FT-SAE"; 11806c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt case WPA_KEY_MGMT_OSEN: 11816c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return "OSEN"; 11826c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt case WPA_KEY_MGMT_IEEE8021X_SUITE_B: 11836c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return "WPA2-EAP-SUITE-B"; 1184807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt case WPA_KEY_MGMT_IEEE8021X_SUITE_B_192: 1185807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt return "WPA2-EAP-SUITE-B-192"; 11868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 11878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "UNKNOWN"; 11888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 11908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 119203658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidtu32 wpa_akm_to_suite(int akm) 119303658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt{ 119403658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt if (akm & WPA_KEY_MGMT_FT_IEEE8021X) 119503658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt return WLAN_AKM_SUITE_FT_8021X; 119603658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt if (akm & WPA_KEY_MGMT_FT_PSK) 119703658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt return WLAN_AKM_SUITE_FT_PSK; 119803658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt if (akm & WPA_KEY_MGMT_IEEE8021X) 119903658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt return WLAN_AKM_SUITE_8021X; 120003658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt if (akm & WPA_KEY_MGMT_IEEE8021X_SHA256) 120103658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt return WLAN_AKM_SUITE_8021X_SHA256; 120203658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt if (akm & WPA_KEY_MGMT_IEEE8021X) 120303658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt return WLAN_AKM_SUITE_8021X; 120403658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt if (akm & WPA_KEY_MGMT_PSK_SHA256) 120503658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt return WLAN_AKM_SUITE_PSK_SHA256; 120603658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt if (akm & WPA_KEY_MGMT_PSK) 120703658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt return WLAN_AKM_SUITE_PSK; 120803658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt if (akm & WPA_KEY_MGMT_CCKM) 120903658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt return WLAN_AKM_SUITE_CCKM; 121003658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt if (akm & WPA_KEY_MGMT_OSEN) 121103658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt return WLAN_AKM_SUITE_OSEN; 12126c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (akm & WPA_KEY_MGMT_IEEE8021X_SUITE_B) 12136c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return WLAN_AKM_SUITE_8021X_SUITE_B; 1214807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt if (akm & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) 1215807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt return WLAN_AKM_SUITE_8021X_SUITE_B_192; 121603658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt return 0; 121703658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt} 121803658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt 121903658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt 12208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_compare_rsn_ie(int ft_initial_assoc, 12218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *ie1, size_t ie1len, 12228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *ie2, size_t ie2len) 12238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 12248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ie1 == NULL || ie2 == NULL) 12258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 12268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ie1len == ie2len && os_memcmp(ie1, ie2, ie1len) == 0) 12288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; /* identical IEs */ 12298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R 12318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ft_initial_assoc) { 12328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_ie_data ie1d, ie2d; 12338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 12348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * The PMKID-List in RSN IE is different between Beacon/Probe 12358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Response/(Re)Association Request frames and EAPOL-Key 12368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * messages in FT initial mobility domain association. Allow 12378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * for this, but verify that other parts of the RSN IEs are 12388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * identical. 12398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 12408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_parse_wpa_ie_rsn(ie1, ie1len, &ie1d) < 0 || 12418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_parse_wpa_ie_rsn(ie2, ie2len, &ie2d) < 0) 12428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 12438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ie1d.proto == ie2d.proto && 12448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ie1d.pairwise_cipher == ie2d.pairwise_cipher && 12458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ie1d.group_cipher == ie2d.group_cipher && 12468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ie1d.key_mgmt == ie2d.key_mgmt && 12478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ie1d.capabilities == ie2d.capabilities && 12488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ie1d.mgmt_group_cipher == ie2d.mgmt_group_cipher) 12498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 12508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */ 12528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 12548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 12558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R 12588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_insert_pmkid(u8 *ies, size_t ies_len, const u8 *pmkid) 12598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 12608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *start, *end, *rpos, *rend; 12618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int added = 0; 12628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt start = ies; 12648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt end = ies + ies_len; 12658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (start < end) { 12678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (*start == WLAN_EID_RSN) 12688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 12698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt start += 2 + start[1]; 12708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (start >= end) { 12728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "FT: Could not find RSN IE in " 12738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "IEs data"); 12748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 12758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "FT: RSN IE before modification", 12778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt start, 2 + start[1]); 12788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Find start of PMKID-Count */ 12808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rpos = start + 2; 12818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rend = rpos + start[1]; 12828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Skip Version and Group Data Cipher Suite */ 12848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rpos += 2 + 4; 12858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Skip Pairwise Cipher Suite Count and List */ 12868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rpos += 2 + WPA_GET_LE16(rpos) * RSN_SELECTOR_LEN; 12878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Skip AKM Suite Count and List */ 12888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rpos += 2 + WPA_GET_LE16(rpos) * RSN_SELECTOR_LEN; 12898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (rpos == rend) { 12918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Add RSN Capabilities */ 12928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memmove(rpos + 2, rpos, end - rpos); 12938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *rpos++ = 0; 12948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *rpos++ = 0; 12958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 12968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Skip RSN Capabilities */ 12978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rpos += 2; 12988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (rpos > rend) { 12998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "FT: Could not parse RSN IE in " 13008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "IEs data"); 13018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 13028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 13038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 13048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (rpos == rend) { 13068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* No PMKID-Count field included; add it */ 13078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memmove(rpos + 2 + PMKID_LEN, rpos, end - rpos); 13088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_LE16(rpos, 1); 13098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rpos += 2; 13108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(rpos, pmkid, PMKID_LEN); 13118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt added += 2 + PMKID_LEN; 13128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt start[1] += 2 + PMKID_LEN; 13138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 13148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* PMKID-Count was included; use it */ 13158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (WPA_GET_LE16(rpos) != 0) { 13168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "FT: Unexpected PMKID " 13178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "in RSN IE in EAPOL-Key data"); 13188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 13198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 13208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_LE16(rpos, 1); 13218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rpos += 2; 13228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memmove(rpos + PMKID_LEN, rpos, end - rpos); 13238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(rpos, pmkid, PMKID_LEN); 13248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt added += PMKID_LEN; 13258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt start[1] += PMKID_LEN; 13268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 13278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "FT: RSN IE after modification " 13298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(PMKID inserted)", start, 2 + start[1]); 13308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return added; 13328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 13338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */ 13344530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 13354530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 13364530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtint wpa_cipher_key_len(int cipher) 13374530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt{ 13384530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt switch (cipher) { 1339fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt case WPA_CIPHER_CCMP_256: 1340fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt case WPA_CIPHER_GCMP_256: 1341b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt case WPA_CIPHER_BIP_GMAC_256: 1342b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt case WPA_CIPHER_BIP_CMAC_256: 1343fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt return 32; 13444530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt case WPA_CIPHER_CCMP: 13454530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt case WPA_CIPHER_GCMP: 1346b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt case WPA_CIPHER_AES_128_CMAC: 1347b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt case WPA_CIPHER_BIP_GMAC_128: 13484530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt return 16; 13494530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt case WPA_CIPHER_TKIP: 13504530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt return 32; 13514530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt } 13524530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 13534530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt return 0; 13544530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt} 13554530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 13564530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 13574530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtint wpa_cipher_rsc_len(int cipher) 13584530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt{ 13594530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt switch (cipher) { 1360fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt case WPA_CIPHER_CCMP_256: 1361fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt case WPA_CIPHER_GCMP_256: 13624530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt case WPA_CIPHER_CCMP: 13634530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt case WPA_CIPHER_GCMP: 13644530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt case WPA_CIPHER_TKIP: 13654530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt return 6; 13664530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt } 13674530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 13684530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt return 0; 13694530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt} 13704530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 13714530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 13724530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtint wpa_cipher_to_alg(int cipher) 13734530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt{ 13744530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt switch (cipher) { 1375fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt case WPA_CIPHER_CCMP_256: 1376fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt return WPA_ALG_CCMP_256; 1377fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt case WPA_CIPHER_GCMP_256: 1378fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt return WPA_ALG_GCMP_256; 13794530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt case WPA_CIPHER_CCMP: 13804530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt return WPA_ALG_CCMP; 13814530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt case WPA_CIPHER_GCMP: 13824530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt return WPA_ALG_GCMP; 13834530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt case WPA_CIPHER_TKIP: 13844530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt return WPA_ALG_TKIP; 1385b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt case WPA_CIPHER_AES_128_CMAC: 1386b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt return WPA_ALG_IGTK; 1387b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt case WPA_CIPHER_BIP_GMAC_128: 1388b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt return WPA_ALG_BIP_GMAC_128; 1389b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt case WPA_CIPHER_BIP_GMAC_256: 1390b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt return WPA_ALG_BIP_GMAC_256; 1391b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt case WPA_CIPHER_BIP_CMAC_256: 1392b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt return WPA_ALG_BIP_CMAC_256; 13934530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt } 13944530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt return WPA_ALG_NONE; 13954530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt} 13964530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 13974530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 13984530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtint wpa_cipher_valid_pairwise(int cipher) 13994530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt{ 1400fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt return cipher == WPA_CIPHER_CCMP_256 || 1401fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt cipher == WPA_CIPHER_GCMP_256 || 1402fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt cipher == WPA_CIPHER_CCMP || 14034530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt cipher == WPA_CIPHER_GCMP || 14044530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt cipher == WPA_CIPHER_TKIP; 14054530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt} 14064530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 14074530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 14084530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidtu32 wpa_cipher_to_suite(int proto, int cipher) 14094530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt{ 1410fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (cipher & WPA_CIPHER_CCMP_256) 1411fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt return RSN_CIPHER_SUITE_CCMP_256; 1412fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (cipher & WPA_CIPHER_GCMP_256) 1413fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt return RSN_CIPHER_SUITE_GCMP_256; 14144530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (cipher & WPA_CIPHER_CCMP) 14154530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt return (proto == WPA_PROTO_RSN ? 14164530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt RSN_CIPHER_SUITE_CCMP : WPA_CIPHER_SUITE_CCMP); 14174530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (cipher & WPA_CIPHER_GCMP) 14184530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt return RSN_CIPHER_SUITE_GCMP; 14194530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (cipher & WPA_CIPHER_TKIP) 14204530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt return (proto == WPA_PROTO_RSN ? 14214530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt RSN_CIPHER_SUITE_TKIP : WPA_CIPHER_SUITE_TKIP); 14224530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (cipher & WPA_CIPHER_NONE) 14234530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt return (proto == WPA_PROTO_RSN ? 14244530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt RSN_CIPHER_SUITE_NONE : WPA_CIPHER_SUITE_NONE); 1425fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (cipher & WPA_CIPHER_GTK_NOT_USED) 1426fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt return RSN_CIPHER_SUITE_NO_GROUP_ADDRESSED; 1427b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt if (cipher & WPA_CIPHER_AES_128_CMAC) 1428b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt return RSN_CIPHER_SUITE_AES_128_CMAC; 1429b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt if (cipher & WPA_CIPHER_BIP_GMAC_128) 1430b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt return RSN_CIPHER_SUITE_BIP_GMAC_128; 1431b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt if (cipher & WPA_CIPHER_BIP_GMAC_256) 1432b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt return RSN_CIPHER_SUITE_BIP_GMAC_256; 1433b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt if (cipher & WPA_CIPHER_BIP_CMAC_256) 1434b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt return RSN_CIPHER_SUITE_BIP_CMAC_256; 14354530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt return 0; 14364530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt} 14374530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 14384530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 14397d5c8f257a74ac0d12828962a492e8b84ef83923Dmitry Shmidtint rsn_cipher_put_suites(u8 *start, int ciphers) 14404530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt{ 14417d5c8f257a74ac0d12828962a492e8b84ef83923Dmitry Shmidt u8 *pos = start; 14424530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 1443fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (ciphers & WPA_CIPHER_CCMP_256) { 1444fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP_256); 1445fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt pos += RSN_SELECTOR_LEN; 1446fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt } 1447fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (ciphers & WPA_CIPHER_GCMP_256) { 1448fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_GCMP_256); 1449fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt pos += RSN_SELECTOR_LEN; 1450fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt } 14514530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (ciphers & WPA_CIPHER_CCMP) { 14524530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP); 14534530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt pos += RSN_SELECTOR_LEN; 14544530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt } 14554530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (ciphers & WPA_CIPHER_GCMP) { 14564530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_GCMP); 14574530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt pos += RSN_SELECTOR_LEN; 14584530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt } 14594530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (ciphers & WPA_CIPHER_TKIP) { 14604530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_TKIP); 14614530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt pos += RSN_SELECTOR_LEN; 14624530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt } 14634530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (ciphers & WPA_CIPHER_NONE) { 14644530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_NONE); 14654530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt pos += RSN_SELECTOR_LEN; 14664530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt } 14674530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 14687d5c8f257a74ac0d12828962a492e8b84ef83923Dmitry Shmidt return (pos - start) / RSN_SELECTOR_LEN; 14694530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt} 14704530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 14714530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 14727d5c8f257a74ac0d12828962a492e8b84ef83923Dmitry Shmidtint wpa_cipher_put_suites(u8 *start, int ciphers) 14734530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt{ 14747d5c8f257a74ac0d12828962a492e8b84ef83923Dmitry Shmidt u8 *pos = start; 14754530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 14764530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (ciphers & WPA_CIPHER_CCMP) { 14774530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_CCMP); 14784530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt pos += WPA_SELECTOR_LEN; 14794530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt } 14804530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (ciphers & WPA_CIPHER_TKIP) { 14814530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_TKIP); 14824530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt pos += WPA_SELECTOR_LEN; 14834530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt } 14844530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (ciphers & WPA_CIPHER_NONE) { 14854530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_NONE); 14864530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt pos += WPA_SELECTOR_LEN; 14874530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt } 14884530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt 14897d5c8f257a74ac0d12828962a492e8b84ef83923Dmitry Shmidt return (pos - start) / RSN_SELECTOR_LEN; 14904530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt} 1491a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 1492a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 1493a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidtint wpa_pick_pairwise_cipher(int ciphers, int none_allowed) 1494a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt{ 1495fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (ciphers & WPA_CIPHER_CCMP_256) 1496fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt return WPA_CIPHER_CCMP_256; 1497fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (ciphers & WPA_CIPHER_GCMP_256) 1498fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt return WPA_CIPHER_GCMP_256; 1499a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (ciphers & WPA_CIPHER_CCMP) 1500a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt return WPA_CIPHER_CCMP; 1501a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (ciphers & WPA_CIPHER_GCMP) 1502a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt return WPA_CIPHER_GCMP; 1503a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (ciphers & WPA_CIPHER_TKIP) 1504a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt return WPA_CIPHER_TKIP; 1505a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (none_allowed && (ciphers & WPA_CIPHER_NONE)) 1506a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt return WPA_CIPHER_NONE; 1507a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt return -1; 1508a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt} 1509a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 1510a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 1511a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidtint wpa_pick_group_cipher(int ciphers) 1512a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt{ 1513fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (ciphers & WPA_CIPHER_CCMP_256) 1514fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt return WPA_CIPHER_CCMP_256; 1515fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (ciphers & WPA_CIPHER_GCMP_256) 1516fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt return WPA_CIPHER_GCMP_256; 1517a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (ciphers & WPA_CIPHER_CCMP) 1518a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt return WPA_CIPHER_CCMP; 1519a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (ciphers & WPA_CIPHER_GCMP) 1520a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt return WPA_CIPHER_GCMP; 1521fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (ciphers & WPA_CIPHER_GTK_NOT_USED) 1522fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt return WPA_CIPHER_GTK_NOT_USED; 1523a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (ciphers & WPA_CIPHER_TKIP) 1524a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt return WPA_CIPHER_TKIP; 1525a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt return -1; 1526a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt} 1527a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 1528a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 1529a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidtint wpa_parse_cipher(const char *value) 1530a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt{ 1531a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt int val = 0, last; 1532a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt char *start, *end, *buf; 1533a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 1534a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt buf = os_strdup(value); 1535a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (buf == NULL) 1536a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt return -1; 1537a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt start = buf; 1538a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 1539a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt while (*start != '\0') { 1540a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt while (*start == ' ' || *start == '\t') 1541a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt start++; 1542a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (*start == '\0') 1543a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt break; 1544a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt end = start; 1545a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt while (*end != ' ' && *end != '\t' && *end != '\0') 1546a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt end++; 1547a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt last = *end == '\0'; 1548a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt *end = '\0'; 1549fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (os_strcmp(start, "CCMP-256") == 0) 1550fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt val |= WPA_CIPHER_CCMP_256; 1551fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt else if (os_strcmp(start, "GCMP-256") == 0) 1552fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt val |= WPA_CIPHER_GCMP_256; 1553fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt else if (os_strcmp(start, "CCMP") == 0) 1554a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt val |= WPA_CIPHER_CCMP; 1555a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt else if (os_strcmp(start, "GCMP") == 0) 1556a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt val |= WPA_CIPHER_GCMP; 1557a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt else if (os_strcmp(start, "TKIP") == 0) 1558a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt val |= WPA_CIPHER_TKIP; 1559a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt else if (os_strcmp(start, "WEP104") == 0) 1560a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt val |= WPA_CIPHER_WEP104; 1561a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt else if (os_strcmp(start, "WEP40") == 0) 1562a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt val |= WPA_CIPHER_WEP40; 1563a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt else if (os_strcmp(start, "NONE") == 0) 1564a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt val |= WPA_CIPHER_NONE; 1565fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt else if (os_strcmp(start, "GTK_NOT_USED") == 0) 1566fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt val |= WPA_CIPHER_GTK_NOT_USED; 1567a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt else { 1568a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt os_free(buf); 1569a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt return -1; 1570a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt } 1571a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 1572a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (last) 1573a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt break; 1574a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt start = end + 1; 1575a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt } 1576a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt os_free(buf); 1577a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 1578a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt return val; 1579a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt} 1580a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 1581a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 1582a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidtint wpa_write_ciphers(char *start, char *end, int ciphers, const char *delim) 1583a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt{ 1584a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt char *pos = start; 1585a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt int ret; 1586a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 1587fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (ciphers & WPA_CIPHER_CCMP_256) { 1588fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt ret = os_snprintf(pos, end - pos, "%sCCMP-256", 1589fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt pos == start ? "" : delim); 15906c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (os_snprintf_error(end - pos, ret)) 1591fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt return -1; 1592fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt pos += ret; 1593fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt } 1594fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (ciphers & WPA_CIPHER_GCMP_256) { 1595fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt ret = os_snprintf(pos, end - pos, "%sGCMP-256", 1596fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt pos == start ? "" : delim); 15976c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (os_snprintf_error(end - pos, ret)) 1598fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt return -1; 1599fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt pos += ret; 1600fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt } 1601a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (ciphers & WPA_CIPHER_CCMP) { 1602a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt ret = os_snprintf(pos, end - pos, "%sCCMP", 1603a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt pos == start ? "" : delim); 16046c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (os_snprintf_error(end - pos, ret)) 1605a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt return -1; 1606a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt pos += ret; 1607a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt } 1608a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (ciphers & WPA_CIPHER_GCMP) { 1609a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt ret = os_snprintf(pos, end - pos, "%sGCMP", 1610a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt pos == start ? "" : delim); 16116c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (os_snprintf_error(end - pos, ret)) 1612a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt return -1; 1613a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt pos += ret; 1614a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt } 1615a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (ciphers & WPA_CIPHER_TKIP) { 1616a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt ret = os_snprintf(pos, end - pos, "%sTKIP", 1617a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt pos == start ? "" : delim); 16186c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (os_snprintf_error(end - pos, ret)) 1619a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt return -1; 1620a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt pos += ret; 1621a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt } 1622a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (ciphers & WPA_CIPHER_NONE) { 1623a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt ret = os_snprintf(pos, end - pos, "%sNONE", 1624a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt pos == start ? "" : delim); 16256c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (os_snprintf_error(end - pos, ret)) 1626a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt return -1; 1627a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt pos += ret; 1628a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt } 1629a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 1630a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt return pos - start; 1631a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt} 1632a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 1633a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 1634a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidtint wpa_select_ap_group_cipher(int wpa, int wpa_pairwise, int rsn_pairwise) 1635a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt{ 1636a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt int pairwise = 0; 1637a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 1638a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt /* Select group cipher based on the enabled pairwise cipher suites */ 1639a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (wpa & 1) 1640a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt pairwise |= wpa_pairwise; 1641a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (wpa & 2) 1642a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt pairwise |= rsn_pairwise; 1643a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 1644a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (pairwise & WPA_CIPHER_TKIP) 1645a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt return WPA_CIPHER_TKIP; 1646a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if ((pairwise & (WPA_CIPHER_CCMP | WPA_CIPHER_GCMP)) == WPA_CIPHER_GCMP) 1647a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt return WPA_CIPHER_GCMP; 1648fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if ((pairwise & (WPA_CIPHER_GCMP_256 | WPA_CIPHER_CCMP | 1649fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt WPA_CIPHER_GCMP)) == WPA_CIPHER_GCMP_256) 1650fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt return WPA_CIPHER_GCMP_256; 1651fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if ((pairwise & (WPA_CIPHER_CCMP_256 | WPA_CIPHER_CCMP | 1652fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt WPA_CIPHER_GCMP)) == WPA_CIPHER_CCMP_256) 1653fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt return WPA_CIPHER_CCMP_256; 1654a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt return WPA_CIPHER_CCMP; 1655a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt} 1656