wpa_auth_ie.c revision 1f69aa52ea2e0a73ac502565df8c666ee49cab6a
18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* 28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * hostapd - WPA/RSN IE and KDE definitions 38d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi> 48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 58d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This program is free software; you can redistribute it and/or modify 68d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * it under the terms of the GNU General Public License version 2 as 78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * published by the Free Software Foundation. 88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Alternatively, this software may be distributed under the terms of BSD 108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * license. 118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * See README and COPYING for more details. 138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "utils/includes.h" 168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "utils/common.h" 188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common/ieee802_11_defs.h" 198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eapol_auth/eapol_auth_sm.h" 208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "ap_config.h" 218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "ieee802_11.h" 228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "wpa_auth.h" 238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "pmksa_cache_auth.h" 248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "wpa_auth_ie.h" 258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "wpa_auth_i.h" 268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_RSN_TESTING 298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint rsn_testing = 0; 308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_RSN_TESTING */ 318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_write_wpa_ie(struct wpa_auth_config *conf, u8 *buf, size_t len) 348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_ie_hdr *hdr; 368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int num_suites; 378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *pos, *count; 388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr = (struct wpa_ie_hdr *) buf; 408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr->elem_id = WLAN_EID_VENDOR_SPECIFIC; 418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RSN_SELECTOR_PUT(hdr->oui, WPA_OUI_TYPE); 428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_LE16(hdr->version, WPA_VERSION); 438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = (u8 *) (hdr + 1); 448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (conf->wpa_group == WPA_CIPHER_CCMP) { 468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_CCMP); 478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (conf->wpa_group == WPA_CIPHER_TKIP) { 488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_TKIP); 498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (conf->wpa_group == WPA_CIPHER_WEP104) { 508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_WEP104); 518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (conf->wpa_group == WPA_CIPHER_WEP40) { 528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_WEP40); 538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "Invalid group cipher (%d).", 558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conf->wpa_group); 568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += WPA_SELECTOR_LEN; 598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt num_suites = 0; 618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt count = pos; 628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2; 638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (conf->wpa_pairwise & WPA_CIPHER_CCMP) { 658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_CCMP); 668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += WPA_SELECTOR_LEN; 678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt num_suites++; 688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (conf->wpa_pairwise & WPA_CIPHER_TKIP) { 708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_TKIP); 718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += WPA_SELECTOR_LEN; 728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt num_suites++; 738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (conf->wpa_pairwise & WPA_CIPHER_NONE) { 758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_NONE); 768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += WPA_SELECTOR_LEN; 778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt num_suites++; 788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (num_suites == 0) { 818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "Invalid pairwise cipher (%d).", 828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conf->wpa_pairwise); 838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_LE16(count, num_suites); 868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt num_suites = 0; 888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt count = pos; 898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2; 908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X) { 928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RSN_SELECTOR_PUT(pos, WPA_AUTH_KEY_MGMT_UNSPEC_802_1X); 938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += WPA_SELECTOR_LEN; 948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt num_suites++; 958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK) { 978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RSN_SELECTOR_PUT(pos, WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X); 988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += WPA_SELECTOR_LEN; 998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt num_suites++; 1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (num_suites == 0) { 1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "Invalid key management type (%d).", 1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conf->wpa_key_mgmt); 1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_LE16(count, num_suites); 1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* WPA Capabilities; use defaults, so no need to include it */ 1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr->len = (pos - buf) - 2; 1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return pos - buf; 1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len, 1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pmkid) 1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct rsn_ie_hdr *hdr; 1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int num_suites; 1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *pos, *count; 1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 capab; 1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr = (struct rsn_ie_hdr *) buf; 1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr->elem_id = WLAN_EID_RSN; 1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_LE16(hdr->version, RSN_VERSION); 1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = (u8 *) (hdr + 1); 1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (conf->wpa_group == WPA_CIPHER_CCMP) { 1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP); 1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (conf->wpa_group == WPA_CIPHER_TKIP) { 1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_TKIP); 1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (conf->wpa_group == WPA_CIPHER_WEP104) { 1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_WEP104); 1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (conf->wpa_group == WPA_CIPHER_WEP40) { 1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_WEP40); 1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "Invalid group cipher (%d).", 1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conf->wpa_group); 1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += RSN_SELECTOR_LEN; 1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt num_suites = 0; 1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt count = pos; 1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2; 1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_RSN_TESTING 1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (rsn_testing) { 1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RSN_SELECTOR_PUT(pos, RSN_SELECTOR(0x12, 0x34, 0x56, 1)); 1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += RSN_SELECTOR_LEN; 1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt num_suites++; 1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_RSN_TESTING */ 1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (conf->rsn_pairwise & WPA_CIPHER_CCMP) { 1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP); 1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += RSN_SELECTOR_LEN; 1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt num_suites++; 1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (conf->rsn_pairwise & WPA_CIPHER_TKIP) { 1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_TKIP); 1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += RSN_SELECTOR_LEN; 1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt num_suites++; 1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (conf->rsn_pairwise & WPA_CIPHER_NONE) { 1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_NONE); 1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += RSN_SELECTOR_LEN; 1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt num_suites++; 1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_RSN_TESTING 1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (rsn_testing) { 1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RSN_SELECTOR_PUT(pos, RSN_SELECTOR(0x12, 0x34, 0x56, 2)); 1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += RSN_SELECTOR_LEN; 1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt num_suites++; 1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_RSN_TESTING */ 1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (num_suites == 0) { 1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "Invalid pairwise cipher (%d).", 1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conf->rsn_pairwise); 1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_LE16(count, num_suites); 1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt num_suites = 0; 1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt count = pos; 1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2; 1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_RSN_TESTING 1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (rsn_testing) { 1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RSN_SELECTOR_PUT(pos, RSN_SELECTOR(0x12, 0x34, 0x56, 1)); 1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += RSN_SELECTOR_LEN; 1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt num_suites++; 1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_RSN_TESTING */ 1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X) { 2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_UNSPEC_802_1X); 2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += RSN_SELECTOR_LEN; 2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt num_suites++; 2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK) { 2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X); 2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += RSN_SELECTOR_LEN; 2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt num_suites++; 2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R 2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) { 2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_802_1X); 2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += RSN_SELECTOR_LEN; 2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt num_suites++; 2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_PSK) { 2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_PSK); 2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += RSN_SELECTOR_LEN; 2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt num_suites++; 2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */ 2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211W 2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) { 2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_802_1X_SHA256); 2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += RSN_SELECTOR_LEN; 2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt num_suites++; 2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK_SHA256) { 2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_PSK_SHA256); 2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += RSN_SELECTOR_LEN; 2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt num_suites++; 2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211W */ 2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_RSN_TESTING 2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (rsn_testing) { 2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RSN_SELECTOR_PUT(pos, RSN_SELECTOR(0x12, 0x34, 0x56, 2)); 2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += RSN_SELECTOR_LEN; 2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt num_suites++; 2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_RSN_TESTING */ 2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (num_suites == 0) { 2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "Invalid key management type (%d).", 2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conf->wpa_key_mgmt); 2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_LE16(count, num_suites); 2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* RSN Capabilities */ 2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt capab = 0; 2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (conf->rsn_preauth) 2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt capab |= WPA_CAPABILITY_PREAUTH; 2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (conf->peerkey) 2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt capab |= WPA_CAPABILITY_PEERKEY_ENABLED; 2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (conf->wmm_enabled) { 2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 4 PTKSA replay counters when using WMM */ 2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt capab |= (RSN_NUM_REPLAY_COUNTERS_16 << 2); 2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211W 2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (conf->ieee80211w != NO_MGMT_FRAME_PROTECTION) { 2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt capab |= WPA_CAPABILITY_MFPC; 2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (conf->ieee80211w == MGMT_FRAME_PROTECTION_REQUIRED) 2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt capab |= WPA_CAPABILITY_MFPR; 2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211W */ 2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_RSN_TESTING 2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (rsn_testing) 2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt capab |= BIT(8) | BIT(14) | BIT(15); 2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_RSN_TESTING */ 2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_LE16(pos, capab); 2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2; 2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pmkid) { 2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos + 2 + PMKID_LEN > buf + len) 2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* PMKID Count */ 2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_LE16(pos, 1); 2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2; 2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pos, pmkid, PMKID_LEN); 2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += PMKID_LEN; 2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211W 2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (conf->ieee80211w != NO_MGMT_FRAME_PROTECTION) { 2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos + 2 + 4 > buf + len) 2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pmkid == NULL) { 2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* PMKID Count */ 2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_LE16(pos, 0); 2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2; 2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Management Group Cipher Suite */ 2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_AES_128_CMAC); 2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += RSN_SELECTOR_LEN; 2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211W */ 2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_RSN_TESTING 3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (rsn_testing) { 3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Fill in any defined fields and add extra data to the end of 3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * the element. 3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int pmkid_count_set = pmkid != NULL; 3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (conf->ieee80211w != NO_MGMT_FRAME_PROTECTION) 3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pmkid_count_set = 1; 3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* PMKID Count */ 3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_LE16(pos, 0); 3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2; 3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (conf->ieee80211w == NO_MGMT_FRAME_PROTECTION) { 3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Management Group Cipher Suite */ 3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_AES_128_CMAC); 3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += RSN_SELECTOR_LEN; 3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(pos, 0x12, 17); 3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 17; 3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_RSN_TESTING */ 3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr->len = (pos - buf) - 2; 3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return pos - buf; 3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_auth_gen_wpa_ie(struct wpa_authenticator *wpa_auth) 3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *pos, buf[128]; 3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int res; 3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = buf; 3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth->conf.wpa & WPA_PROTO_RSN) { 3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = wpa_write_rsn_ie(&wpa_auth->conf, 3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos, buf + sizeof(buf) - pos, NULL); 3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res < 0) 3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return res; 3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += res; 3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R 3441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (wpa_key_mgmt_ft(wpa_auth->conf.wpa_key_mgmt)) { 3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = wpa_write_mdie(&wpa_auth->conf, pos, 3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf + sizeof(buf) - pos); 3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res < 0) 3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return res; 3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += res; 3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */ 3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth->conf.wpa & WPA_PROTO_WPA) { 3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = wpa_write_wpa_ie(&wpa_auth->conf, 3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos, buf + sizeof(buf) - pos); 3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res < 0) 3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return res; 3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += res; 3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(wpa_auth->wpa_ie); 3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth->wpa_ie = os_malloc(pos - buf); 3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth->wpa_ie == NULL) 3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(wpa_auth->wpa_ie, buf, pos - buf); 3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth->wpa_ie_len = pos - buf; 3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtu8 * wpa_add_kde(u8 *pos, u32 kde, const u8 *data, size_t data_len, 3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *data2, size_t data2_len) 3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos++ = WLAN_EID_VENDOR_SPECIFIC; 3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos++ = RSN_SELECTOR_LEN + data_len + data2_len; 3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RSN_SELECTOR_PUT(pos, kde); 3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += RSN_SELECTOR_LEN; 3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pos, data, data_len); 3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += data_len; 3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data2) { 3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pos, data2, data2_len); 3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += data2_len; 3838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return pos; 3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpa_auth_okc_iter_data { 3898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct rsn_pmksa_cache_entry *pmksa; 3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *aa; 3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *spa; 3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pmkid; 3938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}; 3948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_auth_okc_iter(struct wpa_authenticator *a, void *ctx) 3978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_auth_okc_iter_data *data = ctx; 3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->pmksa = pmksa_cache_get_okc(a->pmksa, data->aa, data->spa, 4008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->pmkid); 4018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->pmksa) 4028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 1; 4038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth, 4088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_state_machine *sm, 4098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *wpa_ie, size_t wpa_ie_len, 4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *mdie, size_t mdie_len) 4118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_ie_data data; 4138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ciphers, key_mgmt, res, version; 4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u32 selector; 4158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t i; 4168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pmkid = NULL; 4178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth == NULL || sm == NULL) 4198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return WPA_NOT_ENABLED; 4208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_ie == NULL || wpa_ie_len < 1) 4228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return WPA_INVALID_IE; 4238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_ie[0] == WLAN_EID_RSN) 4258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt version = WPA_PROTO_RSN; 4268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 4278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt version = WPA_PROTO_WPA; 4288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!(wpa_auth->conf.wpa & version)) { 4308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "Invalid WPA proto (%d) from " MACSTR, 4318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt version, MAC2STR(sm->addr)); 4328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return WPA_INVALID_PROTO; 4338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (version == WPA_PROTO_RSN) { 4368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = wpa_parse_wpa_ie_rsn(wpa_ie, wpa_ie_len, &data); 4378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt selector = RSN_AUTH_KEY_MGMT_UNSPEC_802_1X; 4398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (0) { 4408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R 4428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (data.key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) 4438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt selector = RSN_AUTH_KEY_MGMT_FT_802_1X; 4448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (data.key_mgmt & WPA_KEY_MGMT_FT_PSK) 4458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt selector = RSN_AUTH_KEY_MGMT_FT_PSK; 4468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */ 4478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211W 4488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) 4498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt selector = RSN_AUTH_KEY_MGMT_802_1X_SHA256; 4508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (data.key_mgmt & WPA_KEY_MGMT_PSK_SHA256) 4518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt selector = RSN_AUTH_KEY_MGMT_PSK_SHA256; 4528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211W */ 4538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X) 4548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt selector = RSN_AUTH_KEY_MGMT_UNSPEC_802_1X; 4558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (data.key_mgmt & WPA_KEY_MGMT_PSK) 4568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt selector = RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X; 4578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth->dot11RSNAAuthenticationSuiteSelected = selector; 4588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt selector = RSN_CIPHER_SUITE_CCMP; 4608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data.pairwise_cipher & WPA_CIPHER_CCMP) 4618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt selector = RSN_CIPHER_SUITE_CCMP; 4628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (data.pairwise_cipher & WPA_CIPHER_TKIP) 4638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt selector = RSN_CIPHER_SUITE_TKIP; 4648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (data.pairwise_cipher & WPA_CIPHER_WEP104) 4658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt selector = RSN_CIPHER_SUITE_WEP104; 4668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (data.pairwise_cipher & WPA_CIPHER_WEP40) 4678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt selector = RSN_CIPHER_SUITE_WEP40; 4688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (data.pairwise_cipher & WPA_CIPHER_NONE) 4698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt selector = RSN_CIPHER_SUITE_NONE; 4708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth->dot11RSNAPairwiseCipherSelected = selector; 4718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt selector = RSN_CIPHER_SUITE_CCMP; 4738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data.group_cipher & WPA_CIPHER_CCMP) 4748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt selector = RSN_CIPHER_SUITE_CCMP; 4758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (data.group_cipher & WPA_CIPHER_TKIP) 4768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt selector = RSN_CIPHER_SUITE_TKIP; 4778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (data.group_cipher & WPA_CIPHER_WEP104) 4788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt selector = RSN_CIPHER_SUITE_WEP104; 4798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (data.group_cipher & WPA_CIPHER_WEP40) 4808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt selector = RSN_CIPHER_SUITE_WEP40; 4818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (data.group_cipher & WPA_CIPHER_NONE) 4828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt selector = RSN_CIPHER_SUITE_NONE; 4838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth->dot11RSNAGroupCipherSelected = selector; 4848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 4858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = wpa_parse_wpa_ie_wpa(wpa_ie, wpa_ie_len, &data); 4868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt selector = WPA_AUTH_KEY_MGMT_UNSPEC_802_1X; 4888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X) 4898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt selector = WPA_AUTH_KEY_MGMT_UNSPEC_802_1X; 4908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (data.key_mgmt & WPA_KEY_MGMT_PSK) 4918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt selector = WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X; 4928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth->dot11RSNAAuthenticationSuiteSelected = selector; 4938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt selector = WPA_CIPHER_SUITE_TKIP; 4958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data.pairwise_cipher & WPA_CIPHER_CCMP) 4968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt selector = WPA_CIPHER_SUITE_CCMP; 4978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (data.pairwise_cipher & WPA_CIPHER_TKIP) 4988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt selector = WPA_CIPHER_SUITE_TKIP; 4998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (data.pairwise_cipher & WPA_CIPHER_WEP104) 5008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt selector = WPA_CIPHER_SUITE_WEP104; 5018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (data.pairwise_cipher & WPA_CIPHER_WEP40) 5028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt selector = WPA_CIPHER_SUITE_WEP40; 5038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (data.pairwise_cipher & WPA_CIPHER_NONE) 5048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt selector = WPA_CIPHER_SUITE_NONE; 5058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth->dot11RSNAPairwiseCipherSelected = selector; 5068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt selector = WPA_CIPHER_SUITE_TKIP; 5088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data.group_cipher & WPA_CIPHER_CCMP) 5098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt selector = WPA_CIPHER_SUITE_CCMP; 5108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (data.group_cipher & WPA_CIPHER_TKIP) 5118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt selector = WPA_CIPHER_SUITE_TKIP; 5128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (data.group_cipher & WPA_CIPHER_WEP104) 5138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt selector = WPA_CIPHER_SUITE_WEP104; 5148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (data.group_cipher & WPA_CIPHER_WEP40) 5158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt selector = WPA_CIPHER_SUITE_WEP40; 5168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (data.group_cipher & WPA_CIPHER_NONE) 5178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt selector = WPA_CIPHER_SUITE_NONE; 5188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth->dot11RSNAGroupCipherSelected = selector; 5198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res) { 5218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "Failed to parse WPA/RSN IE from " 5228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MACSTR " (res=%d)", MAC2STR(sm->addr), res); 5238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "WPA/RSN IE", wpa_ie, wpa_ie_len); 5248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return WPA_INVALID_IE; 5258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data.group_cipher != wpa_auth->conf.wpa_group) { 5288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "Invalid WPA group cipher (0x%x) from " 5298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MACSTR, data.group_cipher, MAC2STR(sm->addr)); 5308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return WPA_INVALID_GROUP; 5318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key_mgmt = data.key_mgmt & wpa_auth->conf.wpa_key_mgmt; 5348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!key_mgmt) { 5358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "Invalid WPA key mgmt (0x%x) from " 5368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MACSTR, data.key_mgmt, MAC2STR(sm->addr)); 5378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return WPA_INVALID_AKMP; 5388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (0) { 5408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R 5428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) 5438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->wpa_key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X; 5448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (key_mgmt & WPA_KEY_MGMT_FT_PSK) 5458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->wpa_key_mgmt = WPA_KEY_MGMT_FT_PSK; 5468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */ 5478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211W 5488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) 5498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->wpa_key_mgmt = WPA_KEY_MGMT_IEEE8021X_SHA256; 5508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (key_mgmt & WPA_KEY_MGMT_PSK_SHA256) 5518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->wpa_key_mgmt = WPA_KEY_MGMT_PSK_SHA256; 5528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211W */ 5538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (key_mgmt & WPA_KEY_MGMT_IEEE8021X) 5548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->wpa_key_mgmt = WPA_KEY_MGMT_IEEE8021X; 5558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 5568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->wpa_key_mgmt = WPA_KEY_MGMT_PSK; 5578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (version == WPA_PROTO_RSN) 5598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ciphers = data.pairwise_cipher & wpa_auth->conf.rsn_pairwise; 5608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 5618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ciphers = data.pairwise_cipher & wpa_auth->conf.wpa_pairwise; 5628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!ciphers) { 5638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "Invalid %s pairwise cipher (0x%x) " 5648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "from " MACSTR, 5658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt version == WPA_PROTO_RSN ? "RSN" : "WPA", 5668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data.pairwise_cipher, MAC2STR(sm->addr)); 5678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return WPA_INVALID_PAIRWISE; 5688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211W 5718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth->conf.ieee80211w == MGMT_FRAME_PROTECTION_REQUIRED) { 5728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!(data.capabilities & WPA_CAPABILITY_MFPC)) { 5738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "Management frame protection " 5748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "required, but client did not enable it"); 5758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return WPA_MGMT_FRAME_PROTECTION_VIOLATION; 5768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ciphers & WPA_CIPHER_TKIP) { 5798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "Management frame protection " 5808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "cannot use TKIP"); 5818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return WPA_MGMT_FRAME_PROTECTION_VIOLATION; 5828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data.mgmt_group_cipher != WPA_CIPHER_AES_128_CMAC) { 5858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "Unsupported management group " 5868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "cipher %d", data.mgmt_group_cipher); 5878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return WPA_INVALID_MGMT_GROUP_CIPHER; 5888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_auth->conf.ieee80211w == NO_MGMT_FRAME_PROTECTION || 5928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt !(data.capabilities & WPA_CAPABILITY_MFPC)) 5938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->mgmt_frame_prot = 0; 5948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 5958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->mgmt_frame_prot = 1; 5968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211W */ 5978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R 5998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) { 6008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (mdie == NULL || mdie_len < MOBILITY_DOMAIN_ID_LEN + 1) { 6018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: Trying to use FT, but " 6028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "MDIE not included"); 6038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return WPA_INVALID_MDIE; 6048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(mdie, wpa_auth->conf.mobility_domain, 6068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MOBILITY_DOMAIN_ID_LEN) != 0) { 6078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "RSN: Attempted to use unknown " 6088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "MDIE", mdie, MOBILITY_DOMAIN_ID_LEN); 6098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return WPA_INVALID_MDIE; 6108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */ 6138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ciphers & WPA_CIPHER_CCMP) 6158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->pairwise = WPA_CIPHER_CCMP; 6168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 6178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->pairwise = WPA_CIPHER_TKIP; 6188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: clear WPA/WPA2 state if STA changes from one to another */ 6208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_ie[0] == WLAN_EID_RSN) 6218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->wpa = WPA_VERSION_WPA2; 6228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 6238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->wpa = WPA_VERSION_WPA; 6248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->pmksa = NULL; 6268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; i < data.num_pmkid; i++) { 6278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "RSN IE: STA PMKID", 6288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &data.pmkid[i * PMKID_LEN], PMKID_LEN); 6298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->pmksa = pmksa_cache_auth_get(wpa_auth->pmksa, sm->addr, 6308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &data.pmkid[i * PMKID_LEN]); 6318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->pmksa) { 6328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pmkid = sm->pmksa->pmkid; 6338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 6348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; sm->pmksa == NULL && wpa_auth->conf.okc && 6378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt i < data.num_pmkid; i++) { 6388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_auth_okc_iter_data idata; 6398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt idata.pmksa = NULL; 6408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt idata.aa = wpa_auth->addr; 6418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt idata.spa = sm->addr; 6428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt idata.pmkid = &data.pmkid[i * PMKID_LEN]; 6438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_for_each_auth(wpa_auth, wpa_auth_okc_iter, &idata); 6448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (idata.pmksa) { 6458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG, 6468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "OKC match for PMKID"); 6478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->pmksa = pmksa_cache_add_okc(wpa_auth->pmksa, 6488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt idata.pmksa, 6498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth->addr, 6508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt idata.pmkid); 6518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pmkid = idata.pmkid; 6528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 6538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->pmksa) { 6568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG, 6578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "PMKID found from PMKSA cache " 6588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "eap_type=%d vlan_id=%d", 6598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->pmksa->eap_type_authsrv, 6608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->pmksa->vlan_id); 6618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(wpa_auth->dot11RSNAPMKIDUsed, pmkid, PMKID_LEN); 6628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->wpa_ie == NULL || sm->wpa_ie_len < wpa_ie_len) { 6658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(sm->wpa_ie); 6668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->wpa_ie = os_malloc(wpa_ie_len); 6678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->wpa_ie == NULL) 6688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return WPA_ALLOC_FAIL; 6698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(sm->wpa_ie, wpa_ie, wpa_ie_len); 6718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->wpa_ie_len = wpa_ie_len; 6728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return WPA_IE_OK; 6748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 6788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_parse_generic - Parse EAPOL-Key Key Data Generic IEs 6798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @pos: Pointer to the IE header 6808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @end: Pointer to the end of the Key Data buffer 6818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ie: Pointer to parsed IE data 6828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, 1 if end mark is found, -1 on failure 6838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 6848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_parse_generic(const u8 *pos, const u8 *end, 6858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_eapol_ie_parse *ie) 6868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos[1] == 0) 6888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 1; 6898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos[1] >= 6 && 6918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RSN_SELECTOR_GET(pos + 2) == WPA_OUI_TYPE && 6928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos[2 + WPA_SELECTOR_LEN] == 1 && 6938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos[2 + WPA_SELECTOR_LEN + 1] == 0) { 6948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ie->wpa_ie = pos; 6958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ie->wpa_ie_len = pos[1] + 2; 6968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 6978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos + 1 + RSN_SELECTOR_LEN < end && 7008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos[1] >= RSN_SELECTOR_LEN + PMKID_LEN && 7018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_PMKID) { 7028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ie->pmkid = pos + 2 + RSN_SELECTOR_LEN; 7038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 7048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos[1] > RSN_SELECTOR_LEN + 2 && 7078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_GROUPKEY) { 7088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ie->gtk = pos + 2 + RSN_SELECTOR_LEN; 7098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ie->gtk_len = pos[1] - RSN_SELECTOR_LEN; 7108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 7118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos[1] > RSN_SELECTOR_LEN + 2 && 7148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_MAC_ADDR) { 7158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ie->mac_addr = pos + 2 + RSN_SELECTOR_LEN; 7168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ie->mac_addr_len = pos[1] - RSN_SELECTOR_LEN; 7178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 7188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_PEERKEY 7218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos[1] > RSN_SELECTOR_LEN + 2 && 7228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_SMK) { 7238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ie->smk = pos + 2 + RSN_SELECTOR_LEN; 7248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ie->smk_len = pos[1] - RSN_SELECTOR_LEN; 7258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 7268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos[1] > RSN_SELECTOR_LEN + 2 && 7298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_NONCE) { 7308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ie->nonce = pos + 2 + RSN_SELECTOR_LEN; 7318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ie->nonce_len = pos[1] - RSN_SELECTOR_LEN; 7328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 7338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos[1] > RSN_SELECTOR_LEN + 2 && 7368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_LIFETIME) { 7378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ie->lifetime = pos + 2 + RSN_SELECTOR_LEN; 7388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ie->lifetime_len = pos[1] - RSN_SELECTOR_LEN; 7398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 7408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos[1] > RSN_SELECTOR_LEN + 2 && 7438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_ERROR) { 7448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ie->error = pos + 2 + RSN_SELECTOR_LEN; 7458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ie->error_len = pos[1] - RSN_SELECTOR_LEN; 7468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 7478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_PEERKEY */ 7498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211W 7518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos[1] > RSN_SELECTOR_LEN + 2 && 7528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_IGTK) { 7538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ie->igtk = pos + 2 + RSN_SELECTOR_LEN; 7548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ie->igtk_len = pos[1] - RSN_SELECTOR_LEN; 7558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 7568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211W */ 7588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 7608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 7648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_parse_kde_ies - Parse EAPOL-Key Key Data IEs 7658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @buf: Pointer to the Key Data buffer 7668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @len: Key Data Length 7678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ie: Pointer to parsed IE data 7688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure 7698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 7708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_parse_kde_ies(const u8 *buf, size_t len, struct wpa_eapol_ie_parse *ie) 7718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos, *end; 7738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret = 0; 7748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(ie, 0, sizeof(*ie)); 7768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (pos = buf, end = pos + len; pos + 1 < end; pos += 2 + pos[1]) { 7778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos[0] == 0xdd && 7788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ((pos == buf + len - 1) || pos[1] == 0)) { 7798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Ignore padding */ 7808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 7818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos + 2 + pos[1] > end) { 7838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPA: EAPOL-Key Key Data " 7848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "underflow (ie=%d len=%d pos=%d)", 7858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos[0], pos[1], (int) (pos - buf)); 7868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "WPA: Key Data", 7878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf, len); 7888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = -1; 7898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 7908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (*pos == WLAN_EID_RSN) { 7928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ie->rsn_ie = pos; 7938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ie->rsn_ie_len = pos[1] + 2; 7948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R 7958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (*pos == WLAN_EID_MOBILITY_DOMAIN) { 7968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ie->mdie = pos; 7978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ie->mdie_len = pos[1] + 2; 7988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (*pos == WLAN_EID_FAST_BSS_TRANSITION) { 7998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ie->ftie = pos; 8008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ie->ftie_len = pos[1] + 2; 8018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */ 8028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (*pos == WLAN_EID_VENDOR_SPECIFIC) { 8038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = wpa_parse_generic(pos, end, ie); 8048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret < 0) 8058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 8068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret > 0) { 8078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = 0; 8088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 8098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 8118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "WPA: Unrecognized EAPOL-Key " 8128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Key Data IE", pos, 2 + pos[1]); 8138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 8178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 8188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_auth_uses_mfp(struct wpa_state_machine *sm) 8218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 8228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return sm ? sm->mgmt_frame_prot : 0; 8238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 824