wpa_auth_ie.c revision f21452aea786ac056eb01f1cbba4f553bd502747
1e837dead3c8dc3445ef6a0e2322179c57e264a13Evan Cheng/* 2d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner * hostapd - WPA/RSN IE and KDE definitions 3d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner * Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi> 4d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner * 5d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner * This software may be distributed under the terms of the BSD license. 6d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner * See README for more details. 7d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner */ 8d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner 9d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner#include "utils/includes.h" 1022fee2dff4c43b551aefa44a96ca74fcade6bfacEvan Cheng 110ba45d4fb3e11d8085b01008e31477bece20d01dJim Grosbach#include "utils/common.h" 12d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner#include "common/ieee802_11_defs.h" 13d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner#include "eapol_auth/eapol_auth_sm.h" 14d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner#include "ap_config.h" 15e837dead3c8dc3445ef6a0e2322179c57e264a13Evan Cheng#include "ieee802_11.h" 16e837dead3c8dc3445ef6a0e2322179c57e264a13Evan Cheng#include "wpa_auth.h" 17d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner#include "pmksa_cache_auth.h" 181f6efa3996dd1929fbc129203ce5009b620e6969Michael J. Spencer#include "wpa_auth_ie.h" 1999405df044f2c584242e711cc9023ec90356da82Bruno Cardoso Lopes#include "wpa_auth_i.h" 20d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner 21d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner 22d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner#ifdef CONFIG_RSN_TESTING 23d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattnerint rsn_testing = 0; 24d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner#endif /* CONFIG_RSN_TESTING */ 250ba45d4fb3e11d8085b01008e31477bece20d01dJim Grosbach 26e837dead3c8dc3445ef6a0e2322179c57e264a13Evan Cheng 2706801722a43c697eff0acee905de6b50257ce19bJim Grosbachstatic int wpa_write_wpa_ie(struct wpa_auth_config *conf, u8 *buf, size_t len) 28d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner{ 2906801722a43c697eff0acee905de6b50257ce19bJim Grosbach struct wpa_ie_hdr *hdr; 3006801722a43c697eff0acee905de6b50257ce19bJim Grosbach int num_suites; 31d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner u8 *pos, *count; 320ba45d4fb3e11d8085b01008e31477bece20d01dJim Grosbach u32 suite; 33d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner 34e837dead3c8dc3445ef6a0e2322179c57e264a13Evan Cheng hdr = (struct wpa_ie_hdr *) buf; 35d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner hdr->elem_id = WLAN_EID_VENDOR_SPECIFIC; 36d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner RSN_SELECTOR_PUT(hdr->oui, WPA_OUI_TYPE); 37d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner WPA_PUT_LE16(hdr->version, WPA_VERSION); 38d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner pos = (u8 *) (hdr + 1); 39d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner 40d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner suite = wpa_cipher_to_suite(WPA_PROTO_WPA, conf->wpa_group); 415196c12e9fdec9ef3c63d96cb529c1c1cb732773Benjamin Kramer if (suite == 0) { 425196c12e9fdec9ef3c63d96cb529c1c1cb732773Benjamin Kramer wpa_printf(MSG_DEBUG, "Invalid group cipher (%d).", 435196c12e9fdec9ef3c63d96cb529c1c1cb732773Benjamin Kramer conf->wpa_group); 445196c12e9fdec9ef3c63d96cb529c1c1cb732773Benjamin Kramer return -1; 455196c12e9fdec9ef3c63d96cb529c1c1cb732773Benjamin Kramer } 465196c12e9fdec9ef3c63d96cb529c1c1cb732773Benjamin Kramer RSN_SELECTOR_PUT(pos, suite); 475196c12e9fdec9ef3c63d96cb529c1c1cb732773Benjamin Kramer pos += WPA_SELECTOR_LEN; 485196c12e9fdec9ef3c63d96cb529c1c1cb732773Benjamin Kramer 495196c12e9fdec9ef3c63d96cb529c1c1cb732773Benjamin Kramer count = pos; 50d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner pos += 2; 51d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner 52e837dead3c8dc3445ef6a0e2322179c57e264a13Evan Cheng num_suites = wpa_cipher_put_suites(pos, conf->wpa_pairwise); 53d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner if (num_suites == 0) { 54d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner wpa_printf(MSG_DEBUG, "Invalid pairwise cipher (%d).", 55e837dead3c8dc3445ef6a0e2322179c57e264a13Evan Cheng conf->wpa_pairwise); 56d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner return -1; 570ba45d4fb3e11d8085b01008e31477bece20d01dJim Grosbach } 58cb778a8634454c70d88955b3732f330a6cbe5b07Chris Lattner pos += num_suites * WPA_SELECTOR_LEN; 59cb778a8634454c70d88955b3732f330a6cbe5b07Chris Lattner WPA_PUT_LE16(count, num_suites); 60cb778a8634454c70d88955b3732f330a6cbe5b07Chris Lattner 61a606d955de3b0f777131d74162eb6f11b5f95d75Dan Gohman num_suites = 0; 620ba45d4fb3e11d8085b01008e31477bece20d01dJim Grosbach count = pos; 63e837dead3c8dc3445ef6a0e2322179c57e264a13Evan Cheng pos += 2; 64d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner 650ba45d4fb3e11d8085b01008e31477bece20d01dJim Grosbach if (conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X) { 66d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner RSN_SELECTOR_PUT(pos, WPA_AUTH_KEY_MGMT_UNSPEC_802_1X); 67d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner pos += WPA_SELECTOR_LEN; 68cb778a8634454c70d88955b3732f330a6cbe5b07Chris Lattner num_suites++; 695196c12e9fdec9ef3c63d96cb529c1c1cb732773Benjamin Kramer } 705196c12e9fdec9ef3c63d96cb529c1c1cb732773Benjamin Kramer if (conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK) { 715196c12e9fdec9ef3c63d96cb529c1c1cb732773Benjamin Kramer RSN_SELECTOR_PUT(pos, WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X); 72d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner pos += WPA_SELECTOR_LEN; 730ba45d4fb3e11d8085b01008e31477bece20d01dJim Grosbach num_suites++; 74d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner } 75d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner 767e0d22cbf7b41e93279f574c9b3c557cdf517dcbJim Grosbach if (num_suites == 0) { 770ba45d4fb3e11d8085b01008e31477bece20d01dJim Grosbach wpa_printf(MSG_DEBUG, "Invalid key management type (%d).", 78d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner conf->wpa_key_mgmt); 79d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner return -1; 80e837dead3c8dc3445ef6a0e2322179c57e264a13Evan Cheng } 810ba45d4fb3e11d8085b01008e31477bece20d01dJim Grosbach WPA_PUT_LE16(count, num_suites); 82d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner 83d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner /* WPA Capabilities; use defaults, so no need to include it */ 84e837dead3c8dc3445ef6a0e2322179c57e264a13Evan Cheng 85d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner hdr->len = (pos - buf) - 2; 86d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner 870ba45d4fb3e11d8085b01008e31477bece20d01dJim Grosbach return pos - buf; 88d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner} 89d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner 90d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner 91d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattnerint wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len, 92e837dead3c8dc3445ef6a0e2322179c57e264a13Evan Cheng const u8 *pmkid) 93e837dead3c8dc3445ef6a0e2322179c57e264a13Evan Cheng{ 94e837dead3c8dc3445ef6a0e2322179c57e264a13Evan Cheng struct rsn_ie_hdr *hdr; 95e837dead3c8dc3445ef6a0e2322179c57e264a13Evan Cheng int num_suites, res; 96e837dead3c8dc3445ef6a0e2322179c57e264a13Evan Cheng u8 *pos, *count; 97d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner u16 capab; 98d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner u32 suite; 99d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner 100d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner hdr = (struct rsn_ie_hdr *) buf; 101d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner hdr->elem_id = WLAN_EID_RSN; 102d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner WPA_PUT_LE16(hdr->version, RSN_VERSION); 103d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner pos = (u8 *) (hdr + 1); 104d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner 105d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner suite = wpa_cipher_to_suite(WPA_PROTO_RSN, conf->wpa_group); 10673739d0bf19af3944aff6afaea2c4eda61061652Bill Wendling if (suite == 0) { 107c4af4638dfdab0dc3b6257276cfad2ee45053060Evan Cheng wpa_printf(MSG_DEBUG, "Invalid group cipher (%d).", 1080f040a258ff6a2372fc232212b5e4189e8e7185dEvan Cheng conf->wpa_group); 109d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner return -1; 11015511cf1660cfd6bb8b8e8fca2db9450f50430eeDan Gohman } 111dcc8b4f5d3f62ae84aae100638085dedeee91588Chris Lattner RSN_SELECTOR_PUT(pos, suite); 112d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner pos += RSN_SELECTOR_LEN; 113c4af4638dfdab0dc3b6257276cfad2ee45053060Evan Cheng 114c4af4638dfdab0dc3b6257276cfad2ee45053060Evan Cheng num_suites = 0; 115a22edc82cab86be4cb8876da1e6e78f82bb47a3eChris Lattner count = pos; 116d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner pos += 2; 117d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner 118533297b58da8c74bec65551e1aface9801fc2259Dan Gohman#ifdef CONFIG_RSN_TESTING 11937fefc20d3a1e3934a377567d54a141f67752227Evan Cheng if (rsn_testing) { 1208370d38adee63b3a4d87bfe81be4aacc55fe7cdaBill Wendling RSN_SELECTOR_PUT(pos, RSN_SELECTOR(0x12, 0x34, 0x56, 1)); 121799d697bf8d45ec404d0d105fc788ea5cf81c841Evan Cheng pos += RSN_SELECTOR_LEN; 122799d697bf8d45ec404d0d105fc788ea5cf81c841Evan Cheng num_suites++; 123799d697bf8d45ec404d0d105fc788ea5cf81c841Evan Cheng } 124d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner#endif /* CONFIG_RSN_TESTING */ 125d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner 126d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner res = rsn_cipher_put_suites(pos, conf->rsn_pairwise); 127e837dead3c8dc3445ef6a0e2322179c57e264a13Evan Cheng num_suites += res; 128e837dead3c8dc3445ef6a0e2322179c57e264a13Evan Cheng pos += res * RSN_SELECTOR_LEN; 129e837dead3c8dc3445ef6a0e2322179c57e264a13Evan Cheng 130e837dead3c8dc3445ef6a0e2322179c57e264a13Evan Cheng#ifdef CONFIG_RSN_TESTING 131e837dead3c8dc3445ef6a0e2322179c57e264a13Evan Cheng if (rsn_testing) { 132e837dead3c8dc3445ef6a0e2322179c57e264a13Evan Cheng RSN_SELECTOR_PUT(pos, RSN_SELECTOR(0x12, 0x34, 0x56, 2)); 133d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner pos += RSN_SELECTOR_LEN; 134b89be6150a8ea38fdaa2a242f6442e2d73326dabEvan Cheng num_suites++; 135d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner } 136b89be6150a8ea38fdaa2a242f6442e2d73326dabEvan Cheng#endif /* CONFIG_RSN_TESTING */ 137d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner 13816884415db751c75f2133bd04921393c792b1158Owen Anderson if (num_suites == 0) { 139b89be6150a8ea38fdaa2a242f6442e2d73326dabEvan Cheng wpa_printf(MSG_DEBUG, "Invalid pairwise cipher (%d).", 140b89be6150a8ea38fdaa2a242f6442e2d73326dabEvan Cheng conf->rsn_pairwise); 14199405df044f2c584242e711cc9023ec90356da82Bruno Cardoso Lopes return -1; 142d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner } 143d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner WPA_PUT_LE16(count, num_suites); 144e837dead3c8dc3445ef6a0e2322179c57e264a13Evan Cheng 145d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner num_suites = 0; 146d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner count = pos; 147d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner pos += 2; 148d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner 149e837dead3c8dc3445ef6a0e2322179c57e264a13Evan Cheng#ifdef CONFIG_RSN_TESTING 150d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner if (rsn_testing) { 151d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner RSN_SELECTOR_PUT(pos, RSN_SELECTOR(0x12, 0x34, 0x56, 1)); 152d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner pos += RSN_SELECTOR_LEN; 153d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner num_suites++; 154d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner } 155d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner#endif /* CONFIG_RSN_TESTING */ 156d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner 157d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner if (conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X) { 158d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_UNSPEC_802_1X); 159d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner pos += RSN_SELECTOR_LEN; 160d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner num_suites++; 161d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner } 1620ba45d4fb3e11d8085b01008e31477bece20d01dJim Grosbach if (conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK) { 163d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X); 164d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner pos += RSN_SELECTOR_LEN; 165d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner num_suites++; 166d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner } 167d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner#ifdef CONFIG_IEEE80211R 1680ba45d4fb3e11d8085b01008e31477bece20d01dJim Grosbach if (conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) { 169d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_802_1X); 170d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner pos += RSN_SELECTOR_LEN; 171d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner num_suites++; 172d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner } 173d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner if (conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_PSK) { 174d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_PSK); 175d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner pos += RSN_SELECTOR_LEN; 176d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner num_suites++; 1770ba45d4fb3e11d8085b01008e31477bece20d01dJim Grosbach } 178d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner#endif /* CONFIG_IEEE80211R */ 1790ba45d4fb3e11d8085b01008e31477bece20d01dJim Grosbach#ifdef CONFIG_IEEE80211W 180b5544940c17720f51a74fea9fba33f26fafe4819Dan Gohman if (conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) { 181b5544940c17720f51a74fea9fba33f26fafe4819Dan Gohman RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_802_1X_SHA256); 182d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner pos += RSN_SELECTOR_LEN; 183d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner num_suites++; 184d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner } 1850ba45d4fb3e11d8085b01008e31477bece20d01dJim Grosbach if (conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK_SHA256) { 186d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_PSK_SHA256); 187d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner pos += RSN_SELECTOR_LEN; 188d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner num_suites++; 189d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner } 190d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner#endif /* CONFIG_IEEE80211W */ 191e837dead3c8dc3445ef6a0e2322179c57e264a13Evan Cheng#ifdef CONFIG_SAE 192d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner if (conf->wpa_key_mgmt & WPA_KEY_MGMT_SAE) { 1930ba45d4fb3e11d8085b01008e31477bece20d01dJim Grosbach RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_SAE); 194d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner pos += RSN_SELECTOR_LEN; 195d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner num_suites++; 196d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner } 197e837dead3c8dc3445ef6a0e2322179c57e264a13Evan Cheng if (conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_SAE) { 198d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_SAE); 1990ba45d4fb3e11d8085b01008e31477bece20d01dJim Grosbach pos += RSN_SELECTOR_LEN; 200920c6828ee2a31b324e2b0a9d16e01574955485dDan Gohman num_suites++; 201d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner } 202d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner#endif /* CONFIG_SAE */ 203d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner 204d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner#ifdef CONFIG_RSN_TESTING 205d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner if (rsn_testing) { 206d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner RSN_SELECTOR_PUT(pos, RSN_SELECTOR(0x12, 0x34, 0x56, 2)); 207d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner pos += RSN_SELECTOR_LEN; 208d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner num_suites++; 209d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner } 210d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner#endif /* CONFIG_RSN_TESTING */ 211d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner 2120ba45d4fb3e11d8085b01008e31477bece20d01dJim Grosbach if (num_suites == 0) { 213375cf52638cc5330abf0fe95dfa63a013a97a5f5Chris Lattner wpa_printf(MSG_DEBUG, "Invalid key management type (%d).", 214375cf52638cc5330abf0fe95dfa63a013a97a5f5Chris Lattner conf->wpa_key_mgmt); 215375cf52638cc5330abf0fe95dfa63a013a97a5f5Chris Lattner return -1; 216375cf52638cc5330abf0fe95dfa63a013a97a5f5Chris Lattner } 217375cf52638cc5330abf0fe95dfa63a013a97a5f5Chris Lattner WPA_PUT_LE16(count, num_suites); 218375cf52638cc5330abf0fe95dfa63a013a97a5f5Chris Lattner 219375cf52638cc5330abf0fe95dfa63a013a97a5f5Chris Lattner /* RSN Capabilities */ 220375cf52638cc5330abf0fe95dfa63a013a97a5f5Chris Lattner capab = 0; 221e837dead3c8dc3445ef6a0e2322179c57e264a13Evan Cheng if (conf->rsn_preauth) 222920c6828ee2a31b324e2b0a9d16e01574955485dDan Gohman capab |= WPA_CAPABILITY_PREAUTH; 223d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner if (conf->peerkey) 224d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner capab |= WPA_CAPABILITY_PEERKEY_ENABLED; 225d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner if (conf->wmm_enabled) { 226d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner /* 4 PTKSA replay counters when using WMM */ 227d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner capab |= (RSN_NUM_REPLAY_COUNTERS_16 << 2); 228d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner } 229d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner#ifdef CONFIG_IEEE80211W 230d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner if (conf->ieee80211w != NO_MGMT_FRAME_PROTECTION) { 231920c6828ee2a31b324e2b0a9d16e01574955485dDan Gohman capab |= WPA_CAPABILITY_MFPC; 232d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner if (conf->ieee80211w == MGMT_FRAME_PROTECTION_REQUIRED) 233d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner capab |= WPA_CAPABILITY_MFPR; 234d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner } 2350ba45d4fb3e11d8085b01008e31477bece20d01dJim Grosbach#endif /* CONFIG_IEEE80211W */ 236375cf52638cc5330abf0fe95dfa63a013a97a5f5Chris Lattner#ifdef CONFIG_RSN_TESTING 237375cf52638cc5330abf0fe95dfa63a013a97a5f5Chris Lattner if (rsn_testing) 238375cf52638cc5330abf0fe95dfa63a013a97a5f5Chris Lattner capab |= BIT(8) | BIT(14) | BIT(15); 239375cf52638cc5330abf0fe95dfa63a013a97a5f5Chris Lattner#endif /* CONFIG_RSN_TESTING */ 240375cf52638cc5330abf0fe95dfa63a013a97a5f5Chris Lattner WPA_PUT_LE16(pos, capab); 241375cf52638cc5330abf0fe95dfa63a013a97a5f5Chris Lattner pos += 2; 242375cf52638cc5330abf0fe95dfa63a013a97a5f5Chris Lattner 243375cf52638cc5330abf0fe95dfa63a013a97a5f5Chris Lattner if (pmkid) { 2440ba45d4fb3e11d8085b01008e31477bece20d01dJim Grosbach if (pos + 2 + PMKID_LEN > buf + len) 2450461c0a8f5b476794a061e995210906670a4542dChris Lattner return -1; 2460461c0a8f5b476794a061e995210906670a4542dChris Lattner /* PMKID Count */ 2470461c0a8f5b476794a061e995210906670a4542dChris Lattner WPA_PUT_LE16(pos, 1); 2480461c0a8f5b476794a061e995210906670a4542dChris Lattner pos += 2; 2490461c0a8f5b476794a061e995210906670a4542dChris Lattner os_memcpy(pos, pmkid, PMKID_LEN); 2500461c0a8f5b476794a061e995210906670a4542dChris Lattner pos += PMKID_LEN; 2510461c0a8f5b476794a061e995210906670a4542dChris Lattner } 2520461c0a8f5b476794a061e995210906670a4542dChris Lattner 2530ba45d4fb3e11d8085b01008e31477bece20d01dJim Grosbach#ifdef CONFIG_IEEE80211W 2540461c0a8f5b476794a061e995210906670a4542dChris Lattner if (conf->ieee80211w != NO_MGMT_FRAME_PROTECTION) { 2550461c0a8f5b476794a061e995210906670a4542dChris Lattner if (pos + 2 + 4 > buf + len) 2560461c0a8f5b476794a061e995210906670a4542dChris Lattner return -1; 2570461c0a8f5b476794a061e995210906670a4542dChris Lattner if (pmkid == NULL) { 2580461c0a8f5b476794a061e995210906670a4542dChris Lattner /* PMKID Count */ 2590461c0a8f5b476794a061e995210906670a4542dChris Lattner WPA_PUT_LE16(pos, 0); 2600461c0a8f5b476794a061e995210906670a4542dChris Lattner pos += 2; 2610461c0a8f5b476794a061e995210906670a4542dChris Lattner } 262d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner 263d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner /* Management Group Cipher Suite */ 264d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_AES_128_CMAC); 265d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner pos += RSN_SELECTOR_LEN; 266d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner } 267d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner#endif /* CONFIG_IEEE80211W */ 268d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner 269d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner#ifdef CONFIG_RSN_TESTING 270d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner if (rsn_testing) { 2710ba45d4fb3e11d8085b01008e31477bece20d01dJim Grosbach /* 27216884415db751c75f2133bd04921393c792b1158Owen Anderson * Fill in any defined fields and add extra data to the end of 27316884415db751c75f2133bd04921393c792b1158Owen Anderson * the element. 27416884415db751c75f2133bd04921393c792b1158Owen Anderson */ 27516884415db751c75f2133bd04921393c792b1158Owen Anderson int pmkid_count_set = pmkid != NULL; 27616884415db751c75f2133bd04921393c792b1158Owen Anderson if (conf->ieee80211w != NO_MGMT_FRAME_PROTECTION) 27716884415db751c75f2133bd04921393c792b1158Owen Anderson pmkid_count_set = 1; 278d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner /* PMKID Count */ 279e837dead3c8dc3445ef6a0e2322179c57e264a13Evan Cheng WPA_PUT_LE16(pos, 0); 280d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner pos += 2; 2810ba45d4fb3e11d8085b01008e31477bece20d01dJim Grosbach if (conf->ieee80211w == NO_MGMT_FRAME_PROTECTION) { 282d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner /* Management Group Cipher Suite */ 283e837dead3c8dc3445ef6a0e2322179c57e264a13Evan Cheng RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_AES_128_CMAC); 284d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner pos += RSN_SELECTOR_LEN; 2850ba45d4fb3e11d8085b01008e31477bece20d01dJim Grosbach } 286d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner 287d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner os_memset(pos, 0x12, 17); 288d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner pos += 17; 289d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner } 290e837dead3c8dc3445ef6a0e2322179c57e264a13Evan Cheng#endif /* CONFIG_RSN_TESTING */ 291d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner 2920ba45d4fb3e11d8085b01008e31477bece20d01dJim Grosbach hdr->len = (pos - buf) - 2; 293f8e1e3e729473b8b2b7ee6134b6417976af84d05Jim Grosbach 294f8e1e3e729473b8b2b7ee6134b6417976af84d05Jim Grosbach return pos - buf; 295f8e1e3e729473b8b2b7ee6134b6417976af84d05Jim Grosbach} 296f8e1e3e729473b8b2b7ee6134b6417976af84d05Jim Grosbach 297f8e1e3e729473b8b2b7ee6134b6417976af84d05Jim Grosbach 298f8e1e3e729473b8b2b7ee6134b6417976af84d05Jim Grosbachstatic u8 * wpa_write_osen(struct wpa_auth_config *conf, u8 *eid) 299f8e1e3e729473b8b2b7ee6134b6417976af84d05Jim Grosbach{ 300f8e1e3e729473b8b2b7ee6134b6417976af84d05Jim Grosbach u8 *len; 301f8e1e3e729473b8b2b7ee6134b6417976af84d05Jim Grosbach u16 capab; 302f8e1e3e729473b8b2b7ee6134b6417976af84d05Jim Grosbach 303f8e1e3e729473b8b2b7ee6134b6417976af84d05Jim Grosbach *eid++ = WLAN_EID_VENDOR_SPECIFIC; 304f8e1e3e729473b8b2b7ee6134b6417976af84d05Jim Grosbach len = eid++; /* to be filled */ 305d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner WPA_PUT_BE24(eid, OUI_WFA); 306d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner eid += 3; 307d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner *eid++ = HS20_OSEN_OUI_TYPE; 308d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner 309d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner /* Group Data Cipher Suite */ 310d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner RSN_SELECTOR_PUT(eid, RSN_CIPHER_SUITE_NO_GROUP_ADDRESSED); 311d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner eid += RSN_SELECTOR_LEN; 312e837dead3c8dc3445ef6a0e2322179c57e264a13Evan Cheng 313d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner /* Pairwise Cipher Suite Count and List */ 3140ba45d4fb3e11d8085b01008e31477bece20d01dJim Grosbach WPA_PUT_LE16(eid, 1); 315d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner eid += 2; 316d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner RSN_SELECTOR_PUT(eid, RSN_CIPHER_SUITE_CCMP); 317d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner eid += RSN_SELECTOR_LEN; 318d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner 319d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner /* AKM Suite Count and List */ 320e837dead3c8dc3445ef6a0e2322179c57e264a13Evan Cheng WPA_PUT_LE16(eid, 1); 321d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner eid += 2; 322d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner RSN_SELECTOR_PUT(eid, RSN_AUTH_KEY_MGMT_OSEN); 323d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner eid += RSN_SELECTOR_LEN; 324d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner 325d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner /* RSN Capabilities */ 326e837dead3c8dc3445ef6a0e2322179c57e264a13Evan Cheng capab = 0; 327d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner if (conf->wmm_enabled) { 32873739d0bf19af3944aff6afaea2c4eda61061652Bill Wendling /* 4 PTKSA replay counters when using WMM */ 329d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner capab |= (RSN_NUM_REPLAY_COUNTERS_16 << 2); 330d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner } 331d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner#ifdef CONFIG_IEEE80211W 332d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner if (conf->ieee80211w != NO_MGMT_FRAME_PROTECTION) { 333d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner capab |= WPA_CAPABILITY_MFPC; 334d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner if (conf->ieee80211w == MGMT_FRAME_PROTECTION_REQUIRED) 335d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner capab |= WPA_CAPABILITY_MFPR; 3360ba45d4fb3e11d8085b01008e31477bece20d01dJim Grosbach } 337d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner#endif /* CONFIG_IEEE80211W */ 338d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner WPA_PUT_LE16(eid, capab); 339d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner eid += 2; 340d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner 341d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner *len = eid - len - 1; 342d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner 343d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner return eid; 3440ba45d4fb3e11d8085b01008e31477bece20d01dJim Grosbach} 345d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner 346d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner 347d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattnerint wpa_auth_gen_wpa_ie(struct wpa_authenticator *wpa_auth) 348d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner{ 349d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner u8 *pos, buf[128]; 350e837dead3c8dc3445ef6a0e2322179c57e264a13Evan Cheng int res; 351d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner 3520ba45d4fb3e11d8085b01008e31477bece20d01dJim Grosbach pos = buf; 35373739d0bf19af3944aff6afaea2c4eda61061652Bill Wendling 35473739d0bf19af3944aff6afaea2c4eda61061652Bill Wendling if (wpa_auth->conf.wpa == WPA_PROTO_OSEN) { 355e837dead3c8dc3445ef6a0e2322179c57e264a13Evan Cheng pos = wpa_write_osen(&wpa_auth->conf, pos); 35673739d0bf19af3944aff6afaea2c4eda61061652Bill Wendling } 3570ba45d4fb3e11d8085b01008e31477bece20d01dJim Grosbach if (wpa_auth->conf.wpa & WPA_PROTO_RSN) { 358c4af4638dfdab0dc3b6257276cfad2ee45053060Evan Cheng res = wpa_write_rsn_ie(&wpa_auth->conf, 3590ba45d4fb3e11d8085b01008e31477bece20d01dJim Grosbach pos, buf + sizeof(buf) - pos, NULL); 360c4af4638dfdab0dc3b6257276cfad2ee45053060Evan Cheng if (res < 0) 361e837dead3c8dc3445ef6a0e2322179c57e264a13Evan Cheng return res; 362c4af4638dfdab0dc3b6257276cfad2ee45053060Evan Cheng pos += res; 3630f040a258ff6a2372fc232212b5e4189e8e7185dEvan Cheng } 3640f040a258ff6a2372fc232212b5e4189e8e7185dEvan Cheng#ifdef CONFIG_IEEE80211R 3650f040a258ff6a2372fc232212b5e4189e8e7185dEvan Cheng if (wpa_key_mgmt_ft(wpa_auth->conf.wpa_key_mgmt)) { 3660f040a258ff6a2372fc232212b5e4189e8e7185dEvan Cheng res = wpa_write_mdie(&wpa_auth->conf, pos, 367e837dead3c8dc3445ef6a0e2322179c57e264a13Evan Cheng buf + sizeof(buf) - pos); 3680f040a258ff6a2372fc232212b5e4189e8e7185dEvan Cheng if (res < 0) 3690ba45d4fb3e11d8085b01008e31477bece20d01dJim Grosbach return res; 370d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner pos += res; 371d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner } 372d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner#endif /* CONFIG_IEEE80211R */ 373d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner if (wpa_auth->conf.wpa & WPA_PROTO_WPA) { 374e837dead3c8dc3445ef6a0e2322179c57e264a13Evan Cheng res = wpa_write_wpa_ie(&wpa_auth->conf, 375d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner pos, buf + sizeof(buf) - pos); 3760ba45d4fb3e11d8085b01008e31477bece20d01dJim Grosbach if (res < 0) 377d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner return res; 378d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner pos += res; 379d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner } 380e837dead3c8dc3445ef6a0e2322179c57e264a13Evan Cheng 381d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner os_free(wpa_auth->wpa_ie); 3820ba45d4fb3e11d8085b01008e31477bece20d01dJim Grosbach wpa_auth->wpa_ie = os_malloc(pos - buf); 38315511cf1660cfd6bb8b8e8fca2db9450f50430eeDan Gohman if (wpa_auth->wpa_ie == NULL) 38462c939d7d5572e57963a5f26fb6fe802e13dc0bfDan Gohman return -1; 38562c939d7d5572e57963a5f26fb6fe802e13dc0bfDan Gohman os_memcpy(wpa_auth->wpa_ie, buf, pos - buf); 38662c939d7d5572e57963a5f26fb6fe802e13dc0bfDan Gohman wpa_auth->wpa_ie_len = pos - buf; 38762c939d7d5572e57963a5f26fb6fe802e13dc0bfDan Gohman 38862c939d7d5572e57963a5f26fb6fe802e13dc0bfDan Gohman return 0; 38962c939d7d5572e57963a5f26fb6fe802e13dc0bfDan Gohman} 39062c939d7d5572e57963a5f26fb6fe802e13dc0bfDan Gohman 39115511cf1660cfd6bb8b8e8fca2db9450f50430eeDan Gohman 392e837dead3c8dc3445ef6a0e2322179c57e264a13Evan Chengu8 * wpa_add_kde(u8 *pos, u32 kde, const u8 *data, size_t data_len, 393d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner const u8 *data2, size_t data2_len) 3940ba45d4fb3e11d8085b01008e31477bece20d01dJim Grosbach{ 395d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner *pos++ = WLAN_EID_VENDOR_SPECIFIC; 396d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner *pos++ = RSN_SELECTOR_LEN + data_len + data2_len; 397d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner RSN_SELECTOR_PUT(pos, kde); 398dcc8b4f5d3f62ae84aae100638085dedeee91588Chris Lattner pos += RSN_SELECTOR_LEN; 399dcc8b4f5d3f62ae84aae100638085dedeee91588Chris Lattner os_memcpy(pos, data, data_len); 400dcc8b4f5d3f62ae84aae100638085dedeee91588Chris Lattner pos += data_len; 401dcc8b4f5d3f62ae84aae100638085dedeee91588Chris Lattner if (data2) { 402dcc8b4f5d3f62ae84aae100638085dedeee91588Chris Lattner os_memcpy(pos, data2, data2_len); 403e837dead3c8dc3445ef6a0e2322179c57e264a13Evan Cheng pos += data2_len; 404dcc8b4f5d3f62ae84aae100638085dedeee91588Chris Lattner } 4050ba45d4fb3e11d8085b01008e31477bece20d01dJim Grosbach return pos; 4060ba45d4fb3e11d8085b01008e31477bece20d01dJim Grosbach} 407d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner 408d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner 409d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattnerstruct wpa_auth_okc_iter_data { 410d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner struct rsn_pmksa_cache_entry *pmksa; 411d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner const u8 *aa; 412e837dead3c8dc3445ef6a0e2322179c57e264a13Evan Cheng const u8 *spa; 413d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner const u8 *pmkid; 4140ba45d4fb3e11d8085b01008e31477bece20d01dJim Grosbach}; 415a22edc82cab86be4cb8876da1e6e78f82bb47a3eChris Lattner 416a22edc82cab86be4cb8876da1e6e78f82bb47a3eChris Lattner 417a22edc82cab86be4cb8876da1e6e78f82bb47a3eChris Lattnerstatic int wpa_auth_okc_iter(struct wpa_authenticator *a, void *ctx) 418d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner{ 419a22edc82cab86be4cb8876da1e6e78f82bb47a3eChris Lattner struct wpa_auth_okc_iter_data *data = ctx; 420a22edc82cab86be4cb8876da1e6e78f82bb47a3eChris Lattner data->pmksa = pmksa_cache_get_okc(a->pmksa, data->aa, data->spa, 421a22edc82cab86be4cb8876da1e6e78f82bb47a3eChris Lattner data->pmkid); 422a22edc82cab86be4cb8876da1e6e78f82bb47a3eChris Lattner if (data->pmksa) 423d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner return 1; 424a22edc82cab86be4cb8876da1e6e78f82bb47a3eChris Lattner return 0; 425a22edc82cab86be4cb8876da1e6e78f82bb47a3eChris Lattner} 426a22edc82cab86be4cb8876da1e6e78f82bb47a3eChris Lattner 427d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner 428a22edc82cab86be4cb8876da1e6e78f82bb47a3eChris Lattnerint wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth, 429e837dead3c8dc3445ef6a0e2322179c57e264a13Evan Cheng struct wpa_state_machine *sm, 430d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner const u8 *wpa_ie, size_t wpa_ie_len, 4310ba45d4fb3e11d8085b01008e31477bece20d01dJim Grosbach const u8 *mdie, size_t mdie_len) 432d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner{ 433d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner struct wpa_ie_data data; 434d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner int ciphers, key_mgmt, res, version; 4350ba45d4fb3e11d8085b01008e31477bece20d01dJim Grosbach u32 selector; 436d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner size_t i; 437d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner const u8 *pmkid = NULL; 4380ba45d4fb3e11d8085b01008e31477bece20d01dJim Grosbach 439d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner if (wpa_auth == NULL || sm == NULL) 440d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner return WPA_NOT_ENABLED; 441d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner 442d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner if (wpa_ie == NULL || wpa_ie_len < 1) 443d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner return WPA_INVALID_IE; 444d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner 445d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner if (wpa_ie[0] == WLAN_EID_RSN) 446d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner version = WPA_PROTO_RSN; 447e837dead3c8dc3445ef6a0e2322179c57e264a13Evan Cheng else 448d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner version = WPA_PROTO_WPA; 4490ba45d4fb3e11d8085b01008e31477bece20d01dJim Grosbach 450d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner if (!(wpa_auth->conf.wpa & version)) { 451d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner wpa_printf(MSG_DEBUG, "Invalid WPA proto (%d) from " MACSTR, 452d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner version, MAC2STR(sm->addr)); 453d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner return WPA_INVALID_PROTO; 454d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner } 455d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner 456d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner if (version == WPA_PROTO_RSN) { 457d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner res = wpa_parse_wpa_ie_rsn(wpa_ie, wpa_ie_len, &data); 458d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner 459d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner selector = RSN_AUTH_KEY_MGMT_UNSPEC_802_1X; 460d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner if (0) { 461d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner } 462d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner#ifdef CONFIG_IEEE80211R 463d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner else if (data.key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) 464d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner selector = RSN_AUTH_KEY_MGMT_FT_802_1X; 465e837dead3c8dc3445ef6a0e2322179c57e264a13Evan Cheng else if (data.key_mgmt & WPA_KEY_MGMT_FT_PSK) 466d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner selector = RSN_AUTH_KEY_MGMT_FT_PSK; 4670ba45d4fb3e11d8085b01008e31477bece20d01dJim Grosbach#endif /* CONFIG_IEEE80211R */ 468533297b58da8c74bec65551e1aface9801fc2259Dan Gohman#ifdef CONFIG_IEEE80211W 469d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner else if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) 470d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner selector = RSN_AUTH_KEY_MGMT_802_1X_SHA256; 4710ba45d4fb3e11d8085b01008e31477bece20d01dJim Grosbach else if (data.key_mgmt & WPA_KEY_MGMT_PSK_SHA256) 472d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner selector = RSN_AUTH_KEY_MGMT_PSK_SHA256; 473d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner#endif /* CONFIG_IEEE80211W */ 474d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner#ifdef CONFIG_SAE 475d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner else if (data.key_mgmt & WPA_KEY_MGMT_SAE) 476533297b58da8c74bec65551e1aface9801fc2259Dan Gohman selector = RSN_AUTH_KEY_MGMT_SAE; 477e837dead3c8dc3445ef6a0e2322179c57e264a13Evan Cheng else if (data.key_mgmt & WPA_KEY_MGMT_FT_SAE) 478d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner selector = RSN_AUTH_KEY_MGMT_FT_SAE; 4790ba45d4fb3e11d8085b01008e31477bece20d01dJim Grosbach#endif /* CONFIG_SAE */ 48083a8031336a1155e6b0c3e9a84164324e08d1c8bAndrew Trick else if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X) 48183a8031336a1155e6b0c3e9a84164324e08d1c8bAndrew Trick selector = RSN_AUTH_KEY_MGMT_UNSPEC_802_1X; 48283a8031336a1155e6b0c3e9a84164324e08d1c8bAndrew Trick else if (data.key_mgmt & WPA_KEY_MGMT_PSK) 48383a8031336a1155e6b0c3e9a84164324e08d1c8bAndrew Trick selector = RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X; 48483a8031336a1155e6b0c3e9a84164324e08d1c8bAndrew Trick wpa_auth->dot11RSNAAuthenticationSuiteSelected = selector; 48583a8031336a1155e6b0c3e9a84164324e08d1c8bAndrew Trick 48683a8031336a1155e6b0c3e9a84164324e08d1c8bAndrew Trick selector = wpa_cipher_to_suite(WPA_PROTO_RSN, 48783a8031336a1155e6b0c3e9a84164324e08d1c8bAndrew Trick data.pairwise_cipher); 488d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner if (!selector) 489d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner selector = RSN_CIPHER_SUITE_CCMP; 490d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner wpa_auth->dot11RSNAPairwiseCipherSelected = selector; 491d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner 492d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner selector = wpa_cipher_to_suite(WPA_PROTO_RSN, 493e837dead3c8dc3445ef6a0e2322179c57e264a13Evan Cheng data.group_cipher); 494d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner if (!selector) 4958370d38adee63b3a4d87bfe81be4aacc55fe7cdaBill Wendling selector = RSN_CIPHER_SUITE_CCMP; 4968370d38adee63b3a4d87bfe81be4aacc55fe7cdaBill Wendling wpa_auth->dot11RSNAGroupCipherSelected = selector; 4978370d38adee63b3a4d87bfe81be4aacc55fe7cdaBill Wendling } else { 498758d20f653302ca2fd64f2c13b501156525093d2Evan Cheng res = wpa_parse_wpa_ie_wpa(wpa_ie, wpa_ie_len, &data); 499758d20f653302ca2fd64f2c13b501156525093d2Evan Cheng 500758d20f653302ca2fd64f2c13b501156525093d2Evan Cheng selector = WPA_AUTH_KEY_MGMT_UNSPEC_802_1X; 501758d20f653302ca2fd64f2c13b501156525093d2Evan Cheng if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X) 5028370d38adee63b3a4d87bfe81be4aacc55fe7cdaBill Wendling selector = WPA_AUTH_KEY_MGMT_UNSPEC_802_1X; 503e837dead3c8dc3445ef6a0e2322179c57e264a13Evan Cheng else if (data.key_mgmt & WPA_KEY_MGMT_PSK) 5048370d38adee63b3a4d87bfe81be4aacc55fe7cdaBill Wendling selector = WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X; 505799d697bf8d45ec404d0d105fc788ea5cf81c841Evan Cheng wpa_auth->dot11RSNAAuthenticationSuiteSelected = selector; 506799d697bf8d45ec404d0d105fc788ea5cf81c841Evan Cheng 507799d697bf8d45ec404d0d105fc788ea5cf81c841Evan Cheng selector = wpa_cipher_to_suite(WPA_PROTO_WPA, 508799d697bf8d45ec404d0d105fc788ea5cf81c841Evan Cheng data.pairwise_cipher); 509799d697bf8d45ec404d0d105fc788ea5cf81c841Evan Cheng if (!selector) 510799d697bf8d45ec404d0d105fc788ea5cf81c841Evan Cheng selector = RSN_CIPHER_SUITE_TKIP; 511799d697bf8d45ec404d0d105fc788ea5cf81c841Evan Cheng wpa_auth->dot11RSNAPairwiseCipherSelected = selector; 512799d697bf8d45ec404d0d105fc788ea5cf81c841Evan Cheng 513e837dead3c8dc3445ef6a0e2322179c57e264a13Evan Cheng selector = wpa_cipher_to_suite(WPA_PROTO_WPA, 514799d697bf8d45ec404d0d105fc788ea5cf81c841Evan Cheng data.group_cipher); 515799d697bf8d45ec404d0d105fc788ea5cf81c841Evan Cheng if (!selector) 516799d697bf8d45ec404d0d105fc788ea5cf81c841Evan Cheng selector = WPA_CIPHER_SUITE_TKIP; 517799d697bf8d45ec404d0d105fc788ea5cf81c841Evan Cheng wpa_auth->dot11RSNAGroupCipherSelected = selector; 518799d697bf8d45ec404d0d105fc788ea5cf81c841Evan Cheng } 519799d697bf8d45ec404d0d105fc788ea5cf81c841Evan Cheng if (res) { 520799d697bf8d45ec404d0d105fc788ea5cf81c841Evan Cheng wpa_printf(MSG_DEBUG, "Failed to parse WPA/RSN IE from " 521799d697bf8d45ec404d0d105fc788ea5cf81c841Evan Cheng MACSTR " (res=%d)", MAC2STR(sm->addr), res); 522799d697bf8d45ec404d0d105fc788ea5cf81c841Evan Cheng wpa_hexdump(MSG_DEBUG, "WPA/RSN IE", wpa_ie, wpa_ie_len); 523e837dead3c8dc3445ef6a0e2322179c57e264a13Evan Cheng return WPA_INVALID_IE; 524799d697bf8d45ec404d0d105fc788ea5cf81c841Evan Cheng } 525d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner 526d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner if (data.group_cipher != wpa_auth->conf.wpa_group) { 527d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner wpa_printf(MSG_DEBUG, "Invalid WPA group cipher (0x%x) from " 528d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner MACSTR, data.group_cipher, MAC2STR(sm->addr)); 529d3f99e2bbf5e62261c8948127aacfe9a7d3b2456Chris Lattner return WPA_INVALID_GROUP; 530 } 531 532 key_mgmt = data.key_mgmt & wpa_auth->conf.wpa_key_mgmt; 533 if (!key_mgmt) { 534 wpa_printf(MSG_DEBUG, "Invalid WPA key mgmt (0x%x) from " 535 MACSTR, data.key_mgmt, MAC2STR(sm->addr)); 536 return WPA_INVALID_AKMP; 537 } 538 if (0) { 539 } 540#ifdef CONFIG_IEEE80211R 541 else if (key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) 542 sm->wpa_key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X; 543 else if (key_mgmt & WPA_KEY_MGMT_FT_PSK) 544 sm->wpa_key_mgmt = WPA_KEY_MGMT_FT_PSK; 545#endif /* CONFIG_IEEE80211R */ 546#ifdef CONFIG_IEEE80211W 547 else if (key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) 548 sm->wpa_key_mgmt = WPA_KEY_MGMT_IEEE8021X_SHA256; 549 else if (key_mgmt & WPA_KEY_MGMT_PSK_SHA256) 550 sm->wpa_key_mgmt = WPA_KEY_MGMT_PSK_SHA256; 551#endif /* CONFIG_IEEE80211W */ 552#ifdef CONFIG_SAE 553 else if (key_mgmt & WPA_KEY_MGMT_SAE) 554 sm->wpa_key_mgmt = WPA_KEY_MGMT_SAE; 555 else if (key_mgmt & WPA_KEY_MGMT_FT_SAE) 556 sm->wpa_key_mgmt = WPA_KEY_MGMT_FT_SAE; 557#endif /* CONFIG_SAE */ 558 else if (key_mgmt & WPA_KEY_MGMT_IEEE8021X) 559 sm->wpa_key_mgmt = WPA_KEY_MGMT_IEEE8021X; 560 else 561 sm->wpa_key_mgmt = WPA_KEY_MGMT_PSK; 562 563 if (version == WPA_PROTO_RSN) 564 ciphers = data.pairwise_cipher & wpa_auth->conf.rsn_pairwise; 565 else 566 ciphers = data.pairwise_cipher & wpa_auth->conf.wpa_pairwise; 567 if (!ciphers) { 568 wpa_printf(MSG_DEBUG, "Invalid %s pairwise cipher (0x%x) " 569 "from " MACSTR, 570 version == WPA_PROTO_RSN ? "RSN" : "WPA", 571 data.pairwise_cipher, MAC2STR(sm->addr)); 572 return WPA_INVALID_PAIRWISE; 573 } 574 575#ifdef CONFIG_IEEE80211W 576 if (wpa_auth->conf.ieee80211w == MGMT_FRAME_PROTECTION_REQUIRED) { 577 if (!(data.capabilities & WPA_CAPABILITY_MFPC)) { 578 wpa_printf(MSG_DEBUG, "Management frame protection " 579 "required, but client did not enable it"); 580 return WPA_MGMT_FRAME_PROTECTION_VIOLATION; 581 } 582 583 if (ciphers & WPA_CIPHER_TKIP) { 584 wpa_printf(MSG_DEBUG, "Management frame protection " 585 "cannot use TKIP"); 586 return WPA_MGMT_FRAME_PROTECTION_VIOLATION; 587 } 588 589 if (data.mgmt_group_cipher != WPA_CIPHER_AES_128_CMAC) { 590 wpa_printf(MSG_DEBUG, "Unsupported management group " 591 "cipher %d", data.mgmt_group_cipher); 592 return WPA_INVALID_MGMT_GROUP_CIPHER; 593 } 594 } 595 596 if (wpa_auth->conf.ieee80211w == NO_MGMT_FRAME_PROTECTION || 597 !(data.capabilities & WPA_CAPABILITY_MFPC)) 598 sm->mgmt_frame_prot = 0; 599 else 600 sm->mgmt_frame_prot = 1; 601#endif /* CONFIG_IEEE80211W */ 602 603#ifdef CONFIG_IEEE80211R 604 if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) { 605 if (mdie == NULL || mdie_len < MOBILITY_DOMAIN_ID_LEN + 1) { 606 wpa_printf(MSG_DEBUG, "RSN: Trying to use FT, but " 607 "MDIE not included"); 608 return WPA_INVALID_MDIE; 609 } 610 if (os_memcmp(mdie, wpa_auth->conf.mobility_domain, 611 MOBILITY_DOMAIN_ID_LEN) != 0) { 612 wpa_hexdump(MSG_DEBUG, "RSN: Attempted to use unknown " 613 "MDIE", mdie, MOBILITY_DOMAIN_ID_LEN); 614 return WPA_INVALID_MDIE; 615 } 616 } 617#endif /* CONFIG_IEEE80211R */ 618 619 sm->pairwise = wpa_pick_pairwise_cipher(ciphers, 0); 620 if (sm->pairwise < 0) 621 return WPA_INVALID_PAIRWISE; 622 623 /* TODO: clear WPA/WPA2 state if STA changes from one to another */ 624 if (wpa_ie[0] == WLAN_EID_RSN) 625 sm->wpa = WPA_VERSION_WPA2; 626 else 627 sm->wpa = WPA_VERSION_WPA; 628 629 sm->pmksa = NULL; 630 for (i = 0; i < data.num_pmkid; i++) { 631 wpa_hexdump(MSG_DEBUG, "RSN IE: STA PMKID", 632 &data.pmkid[i * PMKID_LEN], PMKID_LEN); 633 sm->pmksa = pmksa_cache_auth_get(wpa_auth->pmksa, sm->addr, 634 &data.pmkid[i * PMKID_LEN]); 635 if (sm->pmksa) { 636 pmkid = sm->pmksa->pmkid; 637 break; 638 } 639 } 640 for (i = 0; sm->pmksa == NULL && wpa_auth->conf.okc && 641 i < data.num_pmkid; i++) { 642 struct wpa_auth_okc_iter_data idata; 643 idata.pmksa = NULL; 644 idata.aa = wpa_auth->addr; 645 idata.spa = sm->addr; 646 idata.pmkid = &data.pmkid[i * PMKID_LEN]; 647 wpa_auth_for_each_auth(wpa_auth, wpa_auth_okc_iter, &idata); 648 if (idata.pmksa) { 649 wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG, 650 "OKC match for PMKID"); 651 sm->pmksa = pmksa_cache_add_okc(wpa_auth->pmksa, 652 idata.pmksa, 653 wpa_auth->addr, 654 idata.pmkid); 655 pmkid = idata.pmkid; 656 break; 657 } 658 } 659 if (sm->pmksa) { 660 wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG, 661 "PMKID found from PMKSA cache " 662 "eap_type=%d vlan_id=%d", 663 sm->pmksa->eap_type_authsrv, 664 sm->pmksa->vlan_id); 665 os_memcpy(wpa_auth->dot11RSNAPMKIDUsed, pmkid, PMKID_LEN); 666 } 667 668 if (sm->wpa_ie == NULL || sm->wpa_ie_len < wpa_ie_len) { 669 os_free(sm->wpa_ie); 670 sm->wpa_ie = os_malloc(wpa_ie_len); 671 if (sm->wpa_ie == NULL) 672 return WPA_ALLOC_FAIL; 673 } 674 os_memcpy(sm->wpa_ie, wpa_ie, wpa_ie_len); 675 sm->wpa_ie_len = wpa_ie_len; 676 677 return WPA_IE_OK; 678} 679 680 681#ifdef CONFIG_HS20 682int wpa_validate_osen(struct wpa_authenticator *wpa_auth, 683 struct wpa_state_machine *sm, 684 const u8 *osen_ie, size_t osen_ie_len) 685{ 686 if (wpa_auth == NULL || sm == NULL) 687 return -1; 688 689 /* TODO: parse OSEN element */ 690 sm->wpa_key_mgmt = WPA_KEY_MGMT_OSEN; 691 sm->mgmt_frame_prot = 1; 692 sm->pairwise = WPA_CIPHER_CCMP; 693 sm->wpa = WPA_VERSION_WPA2; 694 695 if (sm->wpa_ie == NULL || sm->wpa_ie_len < osen_ie_len) { 696 os_free(sm->wpa_ie); 697 sm->wpa_ie = os_malloc(osen_ie_len); 698 if (sm->wpa_ie == NULL) 699 return -1; 700 } 701 702 os_memcpy(sm->wpa_ie, osen_ie, osen_ie_len); 703 sm->wpa_ie_len = osen_ie_len; 704 705 return 0; 706} 707 708#endif /* CONFIG_HS20 */ 709 710 711/** 712 * wpa_parse_generic - Parse EAPOL-Key Key Data Generic IEs 713 * @pos: Pointer to the IE header 714 * @end: Pointer to the end of the Key Data buffer 715 * @ie: Pointer to parsed IE data 716 * Returns: 0 on success, 1 if end mark is found, -1 on failure 717 */ 718static int wpa_parse_generic(const u8 *pos, const u8 *end, 719 struct wpa_eapol_ie_parse *ie) 720{ 721 if (pos[1] == 0) 722 return 1; 723 724 if (pos[1] >= 6 && 725 RSN_SELECTOR_GET(pos + 2) == WPA_OUI_TYPE && 726 pos[2 + WPA_SELECTOR_LEN] == 1 && 727 pos[2 + WPA_SELECTOR_LEN + 1] == 0) { 728 ie->wpa_ie = pos; 729 ie->wpa_ie_len = pos[1] + 2; 730 return 0; 731 } 732 733 if (pos[1] >= 4 && WPA_GET_BE32(pos + 2) == OSEN_IE_VENDOR_TYPE) { 734 ie->osen = pos; 735 ie->osen_len = pos[1] + 2; 736 return 0; 737 } 738 739 if (pos + 1 + RSN_SELECTOR_LEN < end && 740 pos[1] >= RSN_SELECTOR_LEN + PMKID_LEN && 741 RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_PMKID) { 742 ie->pmkid = pos + 2 + RSN_SELECTOR_LEN; 743 return 0; 744 } 745 746 if (pos[1] > RSN_SELECTOR_LEN + 2 && 747 RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_GROUPKEY) { 748 ie->gtk = pos + 2 + RSN_SELECTOR_LEN; 749 ie->gtk_len = pos[1] - RSN_SELECTOR_LEN; 750 return 0; 751 } 752 753 if (pos[1] > RSN_SELECTOR_LEN + 2 && 754 RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_MAC_ADDR) { 755 ie->mac_addr = pos + 2 + RSN_SELECTOR_LEN; 756 ie->mac_addr_len = pos[1] - RSN_SELECTOR_LEN; 757 return 0; 758 } 759 760#ifdef CONFIG_PEERKEY 761 if (pos[1] > RSN_SELECTOR_LEN + 2 && 762 RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_SMK) { 763 ie->smk = pos + 2 + RSN_SELECTOR_LEN; 764 ie->smk_len = pos[1] - RSN_SELECTOR_LEN; 765 return 0; 766 } 767 768 if (pos[1] > RSN_SELECTOR_LEN + 2 && 769 RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_NONCE) { 770 ie->nonce = pos + 2 + RSN_SELECTOR_LEN; 771 ie->nonce_len = pos[1] - RSN_SELECTOR_LEN; 772 return 0; 773 } 774 775 if (pos[1] > RSN_SELECTOR_LEN + 2 && 776 RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_LIFETIME) { 777 ie->lifetime = pos + 2 + RSN_SELECTOR_LEN; 778 ie->lifetime_len = pos[1] - RSN_SELECTOR_LEN; 779 return 0; 780 } 781 782 if (pos[1] > RSN_SELECTOR_LEN + 2 && 783 RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_ERROR) { 784 ie->error = pos + 2 + RSN_SELECTOR_LEN; 785 ie->error_len = pos[1] - RSN_SELECTOR_LEN; 786 return 0; 787 } 788#endif /* CONFIG_PEERKEY */ 789 790#ifdef CONFIG_IEEE80211W 791 if (pos[1] > RSN_SELECTOR_LEN + 2 && 792 RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_IGTK) { 793 ie->igtk = pos + 2 + RSN_SELECTOR_LEN; 794 ie->igtk_len = pos[1] - RSN_SELECTOR_LEN; 795 return 0; 796 } 797#endif /* CONFIG_IEEE80211W */ 798 799#ifdef CONFIG_P2P 800 if (pos[1] >= RSN_SELECTOR_LEN + 1 && 801 RSN_SELECTOR_GET(pos + 2) == WFA_KEY_DATA_IP_ADDR_REQ) { 802 ie->ip_addr_req = pos + 2 + RSN_SELECTOR_LEN; 803 wpa_hexdump(MSG_DEBUG, "WPA: IP Address Request in EAPOL-Key", 804 ie->ip_addr_req, pos[1] - RSN_SELECTOR_LEN); 805 return 0; 806 } 807 808 if (pos[1] >= RSN_SELECTOR_LEN + 3 * 4 && 809 RSN_SELECTOR_GET(pos + 2) == WFA_KEY_DATA_IP_ADDR_ALLOC) { 810 ie->ip_addr_alloc = pos + 2 + RSN_SELECTOR_LEN; 811 wpa_hexdump(MSG_DEBUG, 812 "WPA: IP Address Allocation in EAPOL-Key", 813 ie->ip_addr_alloc, pos[1] - RSN_SELECTOR_LEN); 814 return 0; 815 } 816#endif /* CONFIG_P2P */ 817 818 return 0; 819} 820 821 822/** 823 * wpa_parse_kde_ies - Parse EAPOL-Key Key Data IEs 824 * @buf: Pointer to the Key Data buffer 825 * @len: Key Data Length 826 * @ie: Pointer to parsed IE data 827 * Returns: 0 on success, -1 on failure 828 */ 829int wpa_parse_kde_ies(const u8 *buf, size_t len, struct wpa_eapol_ie_parse *ie) 830{ 831 const u8 *pos, *end; 832 int ret = 0; 833 834 os_memset(ie, 0, sizeof(*ie)); 835 for (pos = buf, end = pos + len; pos + 1 < end; pos += 2 + pos[1]) { 836 if (pos[0] == 0xdd && 837 ((pos == buf + len - 1) || pos[1] == 0)) { 838 /* Ignore padding */ 839 break; 840 } 841 if (pos + 2 + pos[1] > end) { 842 wpa_printf(MSG_DEBUG, "WPA: EAPOL-Key Key Data " 843 "underflow (ie=%d len=%d pos=%d)", 844 pos[0], pos[1], (int) (pos - buf)); 845 wpa_hexdump_key(MSG_DEBUG, "WPA: Key Data", 846 buf, len); 847 ret = -1; 848 break; 849 } 850 if (*pos == WLAN_EID_RSN) { 851 ie->rsn_ie = pos; 852 ie->rsn_ie_len = pos[1] + 2; 853#ifdef CONFIG_IEEE80211R 854 } else if (*pos == WLAN_EID_MOBILITY_DOMAIN) { 855 ie->mdie = pos; 856 ie->mdie_len = pos[1] + 2; 857 } else if (*pos == WLAN_EID_FAST_BSS_TRANSITION) { 858 ie->ftie = pos; 859 ie->ftie_len = pos[1] + 2; 860#endif /* CONFIG_IEEE80211R */ 861 } else if (*pos == WLAN_EID_VENDOR_SPECIFIC) { 862 ret = wpa_parse_generic(pos, end, ie); 863 if (ret < 0) 864 break; 865 if (ret > 0) { 866 ret = 0; 867 break; 868 } 869 } else { 870 wpa_hexdump(MSG_DEBUG, "WPA: Unrecognized EAPOL-Key " 871 "Key Data IE", pos, 2 + pos[1]); 872 } 873 } 874 875 return ret; 876} 877 878 879int wpa_auth_uses_mfp(struct wpa_state_machine *sm) 880{ 881 return sm ? sm->mgmt_frame_prot : 0; 882} 883