wpa_auth_ie.c revision 289549
1214501Srpaulo/* 2214501Srpaulo * hostapd - WPA/RSN IE and KDE definitions 3281806Srpaulo * Copyright (c) 2004-2015, Jouni Malinen <j@w1.fi> 4214501Srpaulo * 5252726Srpaulo * This software may be distributed under the terms of the BSD license. 6252726Srpaulo * See README for more details. 7214501Srpaulo */ 8214501Srpaulo 9214501Srpaulo#include "utils/includes.h" 10214501Srpaulo 11214501Srpaulo#include "utils/common.h" 12214501Srpaulo#include "common/ieee802_11_defs.h" 13214501Srpaulo#include "eapol_auth/eapol_auth_sm.h" 14214501Srpaulo#include "ap_config.h" 15214501Srpaulo#include "ieee802_11.h" 16214501Srpaulo#include "wpa_auth.h" 17214501Srpaulo#include "pmksa_cache_auth.h" 18214501Srpaulo#include "wpa_auth_ie.h" 19214501Srpaulo#include "wpa_auth_i.h" 20214501Srpaulo 21214501Srpaulo 22252726Srpaulo#ifdef CONFIG_RSN_TESTING 23252726Srpauloint rsn_testing = 0; 24252726Srpaulo#endif /* CONFIG_RSN_TESTING */ 25252726Srpaulo 26252726Srpaulo 27214501Srpaulostatic int wpa_write_wpa_ie(struct wpa_auth_config *conf, u8 *buf, size_t len) 28214501Srpaulo{ 29214501Srpaulo struct wpa_ie_hdr *hdr; 30214501Srpaulo int num_suites; 31214501Srpaulo u8 *pos, *count; 32252726Srpaulo u32 suite; 33214501Srpaulo 34214501Srpaulo hdr = (struct wpa_ie_hdr *) buf; 35214501Srpaulo hdr->elem_id = WLAN_EID_VENDOR_SPECIFIC; 36214501Srpaulo RSN_SELECTOR_PUT(hdr->oui, WPA_OUI_TYPE); 37214501Srpaulo WPA_PUT_LE16(hdr->version, WPA_VERSION); 38214501Srpaulo pos = (u8 *) (hdr + 1); 39214501Srpaulo 40252726Srpaulo suite = wpa_cipher_to_suite(WPA_PROTO_WPA, conf->wpa_group); 41252726Srpaulo if (suite == 0) { 42214501Srpaulo wpa_printf(MSG_DEBUG, "Invalid group cipher (%d).", 43214501Srpaulo conf->wpa_group); 44214501Srpaulo return -1; 45214501Srpaulo } 46252726Srpaulo RSN_SELECTOR_PUT(pos, suite); 47214501Srpaulo pos += WPA_SELECTOR_LEN; 48214501Srpaulo 49214501Srpaulo count = pos; 50214501Srpaulo pos += 2; 51214501Srpaulo 52252726Srpaulo num_suites = wpa_cipher_put_suites(pos, conf->wpa_pairwise); 53214501Srpaulo if (num_suites == 0) { 54214501Srpaulo wpa_printf(MSG_DEBUG, "Invalid pairwise cipher (%d).", 55214501Srpaulo conf->wpa_pairwise); 56214501Srpaulo return -1; 57214501Srpaulo } 58252726Srpaulo pos += num_suites * WPA_SELECTOR_LEN; 59214501Srpaulo WPA_PUT_LE16(count, num_suites); 60214501Srpaulo 61214501Srpaulo num_suites = 0; 62214501Srpaulo count = pos; 63214501Srpaulo pos += 2; 64214501Srpaulo 65214501Srpaulo if (conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X) { 66214501Srpaulo RSN_SELECTOR_PUT(pos, WPA_AUTH_KEY_MGMT_UNSPEC_802_1X); 67214501Srpaulo pos += WPA_SELECTOR_LEN; 68214501Srpaulo num_suites++; 69214501Srpaulo } 70214501Srpaulo if (conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK) { 71214501Srpaulo RSN_SELECTOR_PUT(pos, WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X); 72214501Srpaulo pos += WPA_SELECTOR_LEN; 73214501Srpaulo num_suites++; 74214501Srpaulo } 75214501Srpaulo 76214501Srpaulo if (num_suites == 0) { 77214501Srpaulo wpa_printf(MSG_DEBUG, "Invalid key management type (%d).", 78214501Srpaulo conf->wpa_key_mgmt); 79214501Srpaulo return -1; 80214501Srpaulo } 81214501Srpaulo WPA_PUT_LE16(count, num_suites); 82214501Srpaulo 83214501Srpaulo /* WPA Capabilities; use defaults, so no need to include it */ 84214501Srpaulo 85214501Srpaulo hdr->len = (pos - buf) - 2; 86214501Srpaulo 87214501Srpaulo return pos - buf; 88214501Srpaulo} 89214501Srpaulo 90214501Srpaulo 91214501Srpauloint wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len, 92214501Srpaulo const u8 *pmkid) 93214501Srpaulo{ 94214501Srpaulo struct rsn_ie_hdr *hdr; 95252726Srpaulo int num_suites, res; 96214501Srpaulo u8 *pos, *count; 97214501Srpaulo u16 capab; 98252726Srpaulo u32 suite; 99214501Srpaulo 100214501Srpaulo hdr = (struct rsn_ie_hdr *) buf; 101214501Srpaulo hdr->elem_id = WLAN_EID_RSN; 102214501Srpaulo WPA_PUT_LE16(hdr->version, RSN_VERSION); 103214501Srpaulo pos = (u8 *) (hdr + 1); 104214501Srpaulo 105252726Srpaulo suite = wpa_cipher_to_suite(WPA_PROTO_RSN, conf->wpa_group); 106252726Srpaulo if (suite == 0) { 107214501Srpaulo wpa_printf(MSG_DEBUG, "Invalid group cipher (%d).", 108214501Srpaulo conf->wpa_group); 109214501Srpaulo return -1; 110214501Srpaulo } 111252726Srpaulo RSN_SELECTOR_PUT(pos, suite); 112214501Srpaulo pos += RSN_SELECTOR_LEN; 113214501Srpaulo 114214501Srpaulo num_suites = 0; 115214501Srpaulo count = pos; 116214501Srpaulo pos += 2; 117214501Srpaulo 118252726Srpaulo#ifdef CONFIG_RSN_TESTING 119252726Srpaulo if (rsn_testing) { 120252726Srpaulo RSN_SELECTOR_PUT(pos, RSN_SELECTOR(0x12, 0x34, 0x56, 1)); 121214501Srpaulo pos += RSN_SELECTOR_LEN; 122214501Srpaulo num_suites++; 123214501Srpaulo } 124252726Srpaulo#endif /* CONFIG_RSN_TESTING */ 125252726Srpaulo 126252726Srpaulo res = rsn_cipher_put_suites(pos, conf->rsn_pairwise); 127252726Srpaulo num_suites += res; 128252726Srpaulo pos += res * RSN_SELECTOR_LEN; 129252726Srpaulo 130252726Srpaulo#ifdef CONFIG_RSN_TESTING 131252726Srpaulo if (rsn_testing) { 132252726Srpaulo RSN_SELECTOR_PUT(pos, RSN_SELECTOR(0x12, 0x34, 0x56, 2)); 133214501Srpaulo pos += RSN_SELECTOR_LEN; 134214501Srpaulo num_suites++; 135214501Srpaulo } 136252726Srpaulo#endif /* CONFIG_RSN_TESTING */ 137214501Srpaulo 138214501Srpaulo if (num_suites == 0) { 139214501Srpaulo wpa_printf(MSG_DEBUG, "Invalid pairwise cipher (%d).", 140214501Srpaulo conf->rsn_pairwise); 141214501Srpaulo return -1; 142214501Srpaulo } 143214501Srpaulo WPA_PUT_LE16(count, num_suites); 144214501Srpaulo 145214501Srpaulo num_suites = 0; 146214501Srpaulo count = pos; 147214501Srpaulo pos += 2; 148214501Srpaulo 149252726Srpaulo#ifdef CONFIG_RSN_TESTING 150252726Srpaulo if (rsn_testing) { 151252726Srpaulo RSN_SELECTOR_PUT(pos, RSN_SELECTOR(0x12, 0x34, 0x56, 1)); 152252726Srpaulo pos += RSN_SELECTOR_LEN; 153252726Srpaulo num_suites++; 154252726Srpaulo } 155252726Srpaulo#endif /* CONFIG_RSN_TESTING */ 156252726Srpaulo 157214501Srpaulo if (conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X) { 158214501Srpaulo RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_UNSPEC_802_1X); 159214501Srpaulo pos += RSN_SELECTOR_LEN; 160214501Srpaulo num_suites++; 161214501Srpaulo } 162214501Srpaulo if (conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK) { 163214501Srpaulo RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X); 164214501Srpaulo pos += RSN_SELECTOR_LEN; 165214501Srpaulo num_suites++; 166214501Srpaulo } 167214501Srpaulo#ifdef CONFIG_IEEE80211R 168214501Srpaulo if (conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) { 169214501Srpaulo RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_802_1X); 170214501Srpaulo pos += RSN_SELECTOR_LEN; 171214501Srpaulo num_suites++; 172214501Srpaulo } 173214501Srpaulo if (conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_PSK) { 174214501Srpaulo RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_PSK); 175214501Srpaulo pos += RSN_SELECTOR_LEN; 176214501Srpaulo num_suites++; 177214501Srpaulo } 178214501Srpaulo#endif /* CONFIG_IEEE80211R */ 179214501Srpaulo#ifdef CONFIG_IEEE80211W 180214501Srpaulo if (conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) { 181214501Srpaulo RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_802_1X_SHA256); 182214501Srpaulo pos += RSN_SELECTOR_LEN; 183214501Srpaulo num_suites++; 184214501Srpaulo } 185214501Srpaulo if (conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK_SHA256) { 186214501Srpaulo RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_PSK_SHA256); 187214501Srpaulo pos += RSN_SELECTOR_LEN; 188214501Srpaulo num_suites++; 189214501Srpaulo } 190214501Srpaulo#endif /* CONFIG_IEEE80211W */ 191252726Srpaulo#ifdef CONFIG_SAE 192252726Srpaulo if (conf->wpa_key_mgmt & WPA_KEY_MGMT_SAE) { 193252726Srpaulo RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_SAE); 194252726Srpaulo pos += RSN_SELECTOR_LEN; 195252726Srpaulo num_suites++; 196252726Srpaulo } 197252726Srpaulo if (conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_SAE) { 198252726Srpaulo RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_SAE); 199252726Srpaulo pos += RSN_SELECTOR_LEN; 200252726Srpaulo num_suites++; 201252726Srpaulo } 202252726Srpaulo#endif /* CONFIG_SAE */ 203281806Srpaulo if (conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B) { 204281806Srpaulo RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_802_1X_SUITE_B); 205281806Srpaulo pos += RSN_SELECTOR_LEN; 206281806Srpaulo num_suites++; 207281806Srpaulo } 208281806Srpaulo if (conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) { 209281806Srpaulo RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_802_1X_SUITE_B_192); 210281806Srpaulo pos += RSN_SELECTOR_LEN; 211281806Srpaulo num_suites++; 212281806Srpaulo } 213214501Srpaulo 214252726Srpaulo#ifdef CONFIG_RSN_TESTING 215252726Srpaulo if (rsn_testing) { 216252726Srpaulo RSN_SELECTOR_PUT(pos, RSN_SELECTOR(0x12, 0x34, 0x56, 2)); 217252726Srpaulo pos += RSN_SELECTOR_LEN; 218252726Srpaulo num_suites++; 219252726Srpaulo } 220252726Srpaulo#endif /* CONFIG_RSN_TESTING */ 221252726Srpaulo 222214501Srpaulo if (num_suites == 0) { 223214501Srpaulo wpa_printf(MSG_DEBUG, "Invalid key management type (%d).", 224214501Srpaulo conf->wpa_key_mgmt); 225214501Srpaulo return -1; 226214501Srpaulo } 227214501Srpaulo WPA_PUT_LE16(count, num_suites); 228214501Srpaulo 229214501Srpaulo /* RSN Capabilities */ 230214501Srpaulo capab = 0; 231214501Srpaulo if (conf->rsn_preauth) 232214501Srpaulo capab |= WPA_CAPABILITY_PREAUTH; 233214501Srpaulo if (conf->peerkey) 234214501Srpaulo capab |= WPA_CAPABILITY_PEERKEY_ENABLED; 235214501Srpaulo if (conf->wmm_enabled) { 236214501Srpaulo /* 4 PTKSA replay counters when using WMM */ 237214501Srpaulo capab |= (RSN_NUM_REPLAY_COUNTERS_16 << 2); 238214501Srpaulo } 239214501Srpaulo#ifdef CONFIG_IEEE80211W 240214501Srpaulo if (conf->ieee80211w != NO_MGMT_FRAME_PROTECTION) { 241214501Srpaulo capab |= WPA_CAPABILITY_MFPC; 242214501Srpaulo if (conf->ieee80211w == MGMT_FRAME_PROTECTION_REQUIRED) 243214501Srpaulo capab |= WPA_CAPABILITY_MFPR; 244214501Srpaulo } 245214501Srpaulo#endif /* CONFIG_IEEE80211W */ 246252726Srpaulo#ifdef CONFIG_RSN_TESTING 247252726Srpaulo if (rsn_testing) 248252726Srpaulo capab |= BIT(8) | BIT(14) | BIT(15); 249252726Srpaulo#endif /* CONFIG_RSN_TESTING */ 250214501Srpaulo WPA_PUT_LE16(pos, capab); 251214501Srpaulo pos += 2; 252214501Srpaulo 253214501Srpaulo if (pmkid) { 254214501Srpaulo if (pos + 2 + PMKID_LEN > buf + len) 255214501Srpaulo return -1; 256214501Srpaulo /* PMKID Count */ 257214501Srpaulo WPA_PUT_LE16(pos, 1); 258214501Srpaulo pos += 2; 259214501Srpaulo os_memcpy(pos, pmkid, PMKID_LEN); 260214501Srpaulo pos += PMKID_LEN; 261214501Srpaulo } 262214501Srpaulo 263214501Srpaulo#ifdef CONFIG_IEEE80211W 264289549Srpaulo if (conf->ieee80211w != NO_MGMT_FRAME_PROTECTION && 265289549Srpaulo conf->group_mgmt_cipher != WPA_CIPHER_AES_128_CMAC) { 266214501Srpaulo if (pos + 2 + 4 > buf + len) 267214501Srpaulo return -1; 268214501Srpaulo if (pmkid == NULL) { 269214501Srpaulo /* PMKID Count */ 270214501Srpaulo WPA_PUT_LE16(pos, 0); 271214501Srpaulo pos += 2; 272214501Srpaulo } 273214501Srpaulo 274214501Srpaulo /* Management Group Cipher Suite */ 275281806Srpaulo switch (conf->group_mgmt_cipher) { 276281806Srpaulo case WPA_CIPHER_AES_128_CMAC: 277281806Srpaulo RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_AES_128_CMAC); 278281806Srpaulo break; 279281806Srpaulo case WPA_CIPHER_BIP_GMAC_128: 280281806Srpaulo RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_BIP_GMAC_128); 281281806Srpaulo break; 282281806Srpaulo case WPA_CIPHER_BIP_GMAC_256: 283281806Srpaulo RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_BIP_GMAC_256); 284281806Srpaulo break; 285281806Srpaulo case WPA_CIPHER_BIP_CMAC_256: 286281806Srpaulo RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_BIP_CMAC_256); 287281806Srpaulo break; 288281806Srpaulo default: 289281806Srpaulo wpa_printf(MSG_DEBUG, 290281806Srpaulo "Invalid group management cipher (0x%x)", 291281806Srpaulo conf->group_mgmt_cipher); 292281806Srpaulo return -1; 293281806Srpaulo } 294214501Srpaulo pos += RSN_SELECTOR_LEN; 295214501Srpaulo } 296214501Srpaulo#endif /* CONFIG_IEEE80211W */ 297214501Srpaulo 298252726Srpaulo#ifdef CONFIG_RSN_TESTING 299252726Srpaulo if (rsn_testing) { 300252726Srpaulo /* 301252726Srpaulo * Fill in any defined fields and add extra data to the end of 302252726Srpaulo * the element. 303252726Srpaulo */ 304252726Srpaulo int pmkid_count_set = pmkid != NULL; 305252726Srpaulo if (conf->ieee80211w != NO_MGMT_FRAME_PROTECTION) 306252726Srpaulo pmkid_count_set = 1; 307252726Srpaulo /* PMKID Count */ 308252726Srpaulo WPA_PUT_LE16(pos, 0); 309252726Srpaulo pos += 2; 310252726Srpaulo if (conf->ieee80211w == NO_MGMT_FRAME_PROTECTION) { 311252726Srpaulo /* Management Group Cipher Suite */ 312252726Srpaulo RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_AES_128_CMAC); 313252726Srpaulo pos += RSN_SELECTOR_LEN; 314252726Srpaulo } 315252726Srpaulo 316252726Srpaulo os_memset(pos, 0x12, 17); 317252726Srpaulo pos += 17; 318252726Srpaulo } 319252726Srpaulo#endif /* CONFIG_RSN_TESTING */ 320252726Srpaulo 321214501Srpaulo hdr->len = (pos - buf) - 2; 322214501Srpaulo 323214501Srpaulo return pos - buf; 324214501Srpaulo} 325214501Srpaulo 326214501Srpaulo 327281806Srpaulostatic u8 * wpa_write_osen(struct wpa_auth_config *conf, u8 *eid) 328281806Srpaulo{ 329281806Srpaulo u8 *len; 330281806Srpaulo u16 capab; 331281806Srpaulo 332281806Srpaulo *eid++ = WLAN_EID_VENDOR_SPECIFIC; 333281806Srpaulo len = eid++; /* to be filled */ 334281806Srpaulo WPA_PUT_BE24(eid, OUI_WFA); 335281806Srpaulo eid += 3; 336281806Srpaulo *eid++ = HS20_OSEN_OUI_TYPE; 337281806Srpaulo 338281806Srpaulo /* Group Data Cipher Suite */ 339281806Srpaulo RSN_SELECTOR_PUT(eid, RSN_CIPHER_SUITE_NO_GROUP_ADDRESSED); 340281806Srpaulo eid += RSN_SELECTOR_LEN; 341281806Srpaulo 342281806Srpaulo /* Pairwise Cipher Suite Count and List */ 343281806Srpaulo WPA_PUT_LE16(eid, 1); 344281806Srpaulo eid += 2; 345281806Srpaulo RSN_SELECTOR_PUT(eid, RSN_CIPHER_SUITE_CCMP); 346281806Srpaulo eid += RSN_SELECTOR_LEN; 347281806Srpaulo 348281806Srpaulo /* AKM Suite Count and List */ 349281806Srpaulo WPA_PUT_LE16(eid, 1); 350281806Srpaulo eid += 2; 351281806Srpaulo RSN_SELECTOR_PUT(eid, RSN_AUTH_KEY_MGMT_OSEN); 352281806Srpaulo eid += RSN_SELECTOR_LEN; 353281806Srpaulo 354281806Srpaulo /* RSN Capabilities */ 355281806Srpaulo capab = 0; 356281806Srpaulo if (conf->wmm_enabled) { 357281806Srpaulo /* 4 PTKSA replay counters when using WMM */ 358281806Srpaulo capab |= (RSN_NUM_REPLAY_COUNTERS_16 << 2); 359281806Srpaulo } 360281806Srpaulo#ifdef CONFIG_IEEE80211W 361281806Srpaulo if (conf->ieee80211w != NO_MGMT_FRAME_PROTECTION) { 362281806Srpaulo capab |= WPA_CAPABILITY_MFPC; 363281806Srpaulo if (conf->ieee80211w == MGMT_FRAME_PROTECTION_REQUIRED) 364281806Srpaulo capab |= WPA_CAPABILITY_MFPR; 365281806Srpaulo } 366281806Srpaulo#endif /* CONFIG_IEEE80211W */ 367281806Srpaulo WPA_PUT_LE16(eid, capab); 368281806Srpaulo eid += 2; 369281806Srpaulo 370281806Srpaulo *len = eid - len - 1; 371281806Srpaulo 372281806Srpaulo return eid; 373281806Srpaulo} 374281806Srpaulo 375281806Srpaulo 376214501Srpauloint wpa_auth_gen_wpa_ie(struct wpa_authenticator *wpa_auth) 377214501Srpaulo{ 378214501Srpaulo u8 *pos, buf[128]; 379214501Srpaulo int res; 380214501Srpaulo 381289549Srpaulo#ifdef CONFIG_TESTING_OPTIONS 382289549Srpaulo if (wpa_auth->conf.own_ie_override_len) { 383289549Srpaulo wpa_hexdump(MSG_DEBUG, "WPA: Forced own IE(s) for testing", 384289549Srpaulo wpa_auth->conf.own_ie_override, 385289549Srpaulo wpa_auth->conf.own_ie_override_len); 386289549Srpaulo os_free(wpa_auth->wpa_ie); 387289549Srpaulo wpa_auth->wpa_ie = 388289549Srpaulo os_malloc(wpa_auth->conf.own_ie_override_len); 389289549Srpaulo if (wpa_auth->wpa_ie == NULL) 390289549Srpaulo return -1; 391289549Srpaulo os_memcpy(wpa_auth->wpa_ie, wpa_auth->conf.own_ie_override, 392289549Srpaulo wpa_auth->conf.own_ie_override_len); 393289549Srpaulo wpa_auth->wpa_ie_len = wpa_auth->conf.own_ie_override_len; 394289549Srpaulo return 0; 395289549Srpaulo } 396289549Srpaulo#endif /* CONFIG_TESTING_OPTIONS */ 397289549Srpaulo 398214501Srpaulo pos = buf; 399214501Srpaulo 400281806Srpaulo if (wpa_auth->conf.wpa == WPA_PROTO_OSEN) { 401281806Srpaulo pos = wpa_write_osen(&wpa_auth->conf, pos); 402281806Srpaulo } 403214501Srpaulo if (wpa_auth->conf.wpa & WPA_PROTO_RSN) { 404214501Srpaulo res = wpa_write_rsn_ie(&wpa_auth->conf, 405214501Srpaulo pos, buf + sizeof(buf) - pos, NULL); 406214501Srpaulo if (res < 0) 407214501Srpaulo return res; 408214501Srpaulo pos += res; 409214501Srpaulo } 410214501Srpaulo#ifdef CONFIG_IEEE80211R 411252726Srpaulo if (wpa_key_mgmt_ft(wpa_auth->conf.wpa_key_mgmt)) { 412214501Srpaulo res = wpa_write_mdie(&wpa_auth->conf, pos, 413214501Srpaulo buf + sizeof(buf) - pos); 414214501Srpaulo if (res < 0) 415214501Srpaulo return res; 416214501Srpaulo pos += res; 417214501Srpaulo } 418214501Srpaulo#endif /* CONFIG_IEEE80211R */ 419214501Srpaulo if (wpa_auth->conf.wpa & WPA_PROTO_WPA) { 420214501Srpaulo res = wpa_write_wpa_ie(&wpa_auth->conf, 421214501Srpaulo pos, buf + sizeof(buf) - pos); 422214501Srpaulo if (res < 0) 423214501Srpaulo return res; 424214501Srpaulo pos += res; 425214501Srpaulo } 426214501Srpaulo 427214501Srpaulo os_free(wpa_auth->wpa_ie); 428214501Srpaulo wpa_auth->wpa_ie = os_malloc(pos - buf); 429214501Srpaulo if (wpa_auth->wpa_ie == NULL) 430214501Srpaulo return -1; 431214501Srpaulo os_memcpy(wpa_auth->wpa_ie, buf, pos - buf); 432214501Srpaulo wpa_auth->wpa_ie_len = pos - buf; 433214501Srpaulo 434214501Srpaulo return 0; 435214501Srpaulo} 436214501Srpaulo 437214501Srpaulo 438214501Srpaulou8 * wpa_add_kde(u8 *pos, u32 kde, const u8 *data, size_t data_len, 439214501Srpaulo const u8 *data2, size_t data2_len) 440214501Srpaulo{ 441214501Srpaulo *pos++ = WLAN_EID_VENDOR_SPECIFIC; 442214501Srpaulo *pos++ = RSN_SELECTOR_LEN + data_len + data2_len; 443214501Srpaulo RSN_SELECTOR_PUT(pos, kde); 444214501Srpaulo pos += RSN_SELECTOR_LEN; 445214501Srpaulo os_memcpy(pos, data, data_len); 446214501Srpaulo pos += data_len; 447214501Srpaulo if (data2) { 448214501Srpaulo os_memcpy(pos, data2, data2_len); 449214501Srpaulo pos += data2_len; 450214501Srpaulo } 451214501Srpaulo return pos; 452214501Srpaulo} 453214501Srpaulo 454214501Srpaulo 455214501Srpaulostruct wpa_auth_okc_iter_data { 456214501Srpaulo struct rsn_pmksa_cache_entry *pmksa; 457214501Srpaulo const u8 *aa; 458214501Srpaulo const u8 *spa; 459214501Srpaulo const u8 *pmkid; 460214501Srpaulo}; 461214501Srpaulo 462214501Srpaulo 463214501Srpaulostatic int wpa_auth_okc_iter(struct wpa_authenticator *a, void *ctx) 464214501Srpaulo{ 465214501Srpaulo struct wpa_auth_okc_iter_data *data = ctx; 466214501Srpaulo data->pmksa = pmksa_cache_get_okc(a->pmksa, data->aa, data->spa, 467214501Srpaulo data->pmkid); 468214501Srpaulo if (data->pmksa) 469214501Srpaulo return 1; 470214501Srpaulo return 0; 471214501Srpaulo} 472214501Srpaulo 473214501Srpaulo 474214501Srpauloint wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth, 475214501Srpaulo struct wpa_state_machine *sm, 476214501Srpaulo const u8 *wpa_ie, size_t wpa_ie_len, 477214501Srpaulo const u8 *mdie, size_t mdie_len) 478214501Srpaulo{ 479214501Srpaulo struct wpa_ie_data data; 480214501Srpaulo int ciphers, key_mgmt, res, version; 481214501Srpaulo u32 selector; 482214501Srpaulo size_t i; 483214501Srpaulo const u8 *pmkid = NULL; 484214501Srpaulo 485214501Srpaulo if (wpa_auth == NULL || sm == NULL) 486214501Srpaulo return WPA_NOT_ENABLED; 487214501Srpaulo 488214501Srpaulo if (wpa_ie == NULL || wpa_ie_len < 1) 489214501Srpaulo return WPA_INVALID_IE; 490214501Srpaulo 491214501Srpaulo if (wpa_ie[0] == WLAN_EID_RSN) 492214501Srpaulo version = WPA_PROTO_RSN; 493214501Srpaulo else 494214501Srpaulo version = WPA_PROTO_WPA; 495214501Srpaulo 496214501Srpaulo if (!(wpa_auth->conf.wpa & version)) { 497214501Srpaulo wpa_printf(MSG_DEBUG, "Invalid WPA proto (%d) from " MACSTR, 498214501Srpaulo version, MAC2STR(sm->addr)); 499214501Srpaulo return WPA_INVALID_PROTO; 500214501Srpaulo } 501214501Srpaulo 502214501Srpaulo if (version == WPA_PROTO_RSN) { 503214501Srpaulo res = wpa_parse_wpa_ie_rsn(wpa_ie, wpa_ie_len, &data); 504214501Srpaulo 505214501Srpaulo selector = RSN_AUTH_KEY_MGMT_UNSPEC_802_1X; 506214501Srpaulo if (0) { 507214501Srpaulo } 508281806Srpaulo else if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) 509281806Srpaulo selector = RSN_AUTH_KEY_MGMT_802_1X_SUITE_B_192; 510281806Srpaulo else if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B) 511281806Srpaulo selector = RSN_AUTH_KEY_MGMT_802_1X_SUITE_B; 512214501Srpaulo#ifdef CONFIG_IEEE80211R 513214501Srpaulo else if (data.key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) 514214501Srpaulo selector = RSN_AUTH_KEY_MGMT_FT_802_1X; 515214501Srpaulo else if (data.key_mgmt & WPA_KEY_MGMT_FT_PSK) 516214501Srpaulo selector = RSN_AUTH_KEY_MGMT_FT_PSK; 517214501Srpaulo#endif /* CONFIG_IEEE80211R */ 518214501Srpaulo#ifdef CONFIG_IEEE80211W 519214501Srpaulo else if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) 520214501Srpaulo selector = RSN_AUTH_KEY_MGMT_802_1X_SHA256; 521214501Srpaulo else if (data.key_mgmt & WPA_KEY_MGMT_PSK_SHA256) 522214501Srpaulo selector = RSN_AUTH_KEY_MGMT_PSK_SHA256; 523214501Srpaulo#endif /* CONFIG_IEEE80211W */ 524252726Srpaulo#ifdef CONFIG_SAE 525252726Srpaulo else if (data.key_mgmt & WPA_KEY_MGMT_SAE) 526252726Srpaulo selector = RSN_AUTH_KEY_MGMT_SAE; 527252726Srpaulo else if (data.key_mgmt & WPA_KEY_MGMT_FT_SAE) 528252726Srpaulo selector = RSN_AUTH_KEY_MGMT_FT_SAE; 529252726Srpaulo#endif /* CONFIG_SAE */ 530214501Srpaulo else if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X) 531214501Srpaulo selector = RSN_AUTH_KEY_MGMT_UNSPEC_802_1X; 532214501Srpaulo else if (data.key_mgmt & WPA_KEY_MGMT_PSK) 533214501Srpaulo selector = RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X; 534214501Srpaulo wpa_auth->dot11RSNAAuthenticationSuiteSelected = selector; 535214501Srpaulo 536252726Srpaulo selector = wpa_cipher_to_suite(WPA_PROTO_RSN, 537252726Srpaulo data.pairwise_cipher); 538252726Srpaulo if (!selector) 539214501Srpaulo selector = RSN_CIPHER_SUITE_CCMP; 540214501Srpaulo wpa_auth->dot11RSNAPairwiseCipherSelected = selector; 541214501Srpaulo 542252726Srpaulo selector = wpa_cipher_to_suite(WPA_PROTO_RSN, 543252726Srpaulo data.group_cipher); 544252726Srpaulo if (!selector) 545214501Srpaulo selector = RSN_CIPHER_SUITE_CCMP; 546214501Srpaulo wpa_auth->dot11RSNAGroupCipherSelected = selector; 547214501Srpaulo } else { 548214501Srpaulo res = wpa_parse_wpa_ie_wpa(wpa_ie, wpa_ie_len, &data); 549214501Srpaulo 550214501Srpaulo selector = WPA_AUTH_KEY_MGMT_UNSPEC_802_1X; 551214501Srpaulo if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X) 552214501Srpaulo selector = WPA_AUTH_KEY_MGMT_UNSPEC_802_1X; 553214501Srpaulo else if (data.key_mgmt & WPA_KEY_MGMT_PSK) 554214501Srpaulo selector = WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X; 555214501Srpaulo wpa_auth->dot11RSNAAuthenticationSuiteSelected = selector; 556214501Srpaulo 557252726Srpaulo selector = wpa_cipher_to_suite(WPA_PROTO_WPA, 558252726Srpaulo data.pairwise_cipher); 559252726Srpaulo if (!selector) 560252726Srpaulo selector = RSN_CIPHER_SUITE_TKIP; 561214501Srpaulo wpa_auth->dot11RSNAPairwiseCipherSelected = selector; 562214501Srpaulo 563252726Srpaulo selector = wpa_cipher_to_suite(WPA_PROTO_WPA, 564252726Srpaulo data.group_cipher); 565252726Srpaulo if (!selector) 566214501Srpaulo selector = WPA_CIPHER_SUITE_TKIP; 567214501Srpaulo wpa_auth->dot11RSNAGroupCipherSelected = selector; 568214501Srpaulo } 569214501Srpaulo if (res) { 570214501Srpaulo wpa_printf(MSG_DEBUG, "Failed to parse WPA/RSN IE from " 571214501Srpaulo MACSTR " (res=%d)", MAC2STR(sm->addr), res); 572214501Srpaulo wpa_hexdump(MSG_DEBUG, "WPA/RSN IE", wpa_ie, wpa_ie_len); 573214501Srpaulo return WPA_INVALID_IE; 574214501Srpaulo } 575214501Srpaulo 576214501Srpaulo if (data.group_cipher != wpa_auth->conf.wpa_group) { 577214501Srpaulo wpa_printf(MSG_DEBUG, "Invalid WPA group cipher (0x%x) from " 578214501Srpaulo MACSTR, data.group_cipher, MAC2STR(sm->addr)); 579214501Srpaulo return WPA_INVALID_GROUP; 580214501Srpaulo } 581214501Srpaulo 582214501Srpaulo key_mgmt = data.key_mgmt & wpa_auth->conf.wpa_key_mgmt; 583214501Srpaulo if (!key_mgmt) { 584214501Srpaulo wpa_printf(MSG_DEBUG, "Invalid WPA key mgmt (0x%x) from " 585214501Srpaulo MACSTR, data.key_mgmt, MAC2STR(sm->addr)); 586214501Srpaulo return WPA_INVALID_AKMP; 587214501Srpaulo } 588214501Srpaulo if (0) { 589214501Srpaulo } 590281806Srpaulo else if (key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) 591281806Srpaulo sm->wpa_key_mgmt = WPA_KEY_MGMT_IEEE8021X_SUITE_B_192; 592281806Srpaulo else if (key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B) 593281806Srpaulo sm->wpa_key_mgmt = WPA_KEY_MGMT_IEEE8021X_SUITE_B; 594214501Srpaulo#ifdef CONFIG_IEEE80211R 595214501Srpaulo else if (key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) 596214501Srpaulo sm->wpa_key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X; 597214501Srpaulo else if (key_mgmt & WPA_KEY_MGMT_FT_PSK) 598214501Srpaulo sm->wpa_key_mgmt = WPA_KEY_MGMT_FT_PSK; 599214501Srpaulo#endif /* CONFIG_IEEE80211R */ 600214501Srpaulo#ifdef CONFIG_IEEE80211W 601214501Srpaulo else if (key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) 602214501Srpaulo sm->wpa_key_mgmt = WPA_KEY_MGMT_IEEE8021X_SHA256; 603214501Srpaulo else if (key_mgmt & WPA_KEY_MGMT_PSK_SHA256) 604214501Srpaulo sm->wpa_key_mgmt = WPA_KEY_MGMT_PSK_SHA256; 605214501Srpaulo#endif /* CONFIG_IEEE80211W */ 606252726Srpaulo#ifdef CONFIG_SAE 607252726Srpaulo else if (key_mgmt & WPA_KEY_MGMT_SAE) 608252726Srpaulo sm->wpa_key_mgmt = WPA_KEY_MGMT_SAE; 609252726Srpaulo else if (key_mgmt & WPA_KEY_MGMT_FT_SAE) 610252726Srpaulo sm->wpa_key_mgmt = WPA_KEY_MGMT_FT_SAE; 611252726Srpaulo#endif /* CONFIG_SAE */ 612214501Srpaulo else if (key_mgmt & WPA_KEY_MGMT_IEEE8021X) 613214501Srpaulo sm->wpa_key_mgmt = WPA_KEY_MGMT_IEEE8021X; 614214501Srpaulo else 615214501Srpaulo sm->wpa_key_mgmt = WPA_KEY_MGMT_PSK; 616214501Srpaulo 617214501Srpaulo if (version == WPA_PROTO_RSN) 618214501Srpaulo ciphers = data.pairwise_cipher & wpa_auth->conf.rsn_pairwise; 619214501Srpaulo else 620214501Srpaulo ciphers = data.pairwise_cipher & wpa_auth->conf.wpa_pairwise; 621214501Srpaulo if (!ciphers) { 622214501Srpaulo wpa_printf(MSG_DEBUG, "Invalid %s pairwise cipher (0x%x) " 623214501Srpaulo "from " MACSTR, 624214501Srpaulo version == WPA_PROTO_RSN ? "RSN" : "WPA", 625214501Srpaulo data.pairwise_cipher, MAC2STR(sm->addr)); 626214501Srpaulo return WPA_INVALID_PAIRWISE; 627214501Srpaulo } 628214501Srpaulo 629214501Srpaulo#ifdef CONFIG_IEEE80211W 630214501Srpaulo if (wpa_auth->conf.ieee80211w == MGMT_FRAME_PROTECTION_REQUIRED) { 631214501Srpaulo if (!(data.capabilities & WPA_CAPABILITY_MFPC)) { 632214501Srpaulo wpa_printf(MSG_DEBUG, "Management frame protection " 633214501Srpaulo "required, but client did not enable it"); 634214501Srpaulo return WPA_MGMT_FRAME_PROTECTION_VIOLATION; 635214501Srpaulo } 636214501Srpaulo 637214501Srpaulo if (ciphers & WPA_CIPHER_TKIP) { 638214501Srpaulo wpa_printf(MSG_DEBUG, "Management frame protection " 639214501Srpaulo "cannot use TKIP"); 640214501Srpaulo return WPA_MGMT_FRAME_PROTECTION_VIOLATION; 641214501Srpaulo } 642214501Srpaulo 643281806Srpaulo if (data.mgmt_group_cipher != wpa_auth->conf.group_mgmt_cipher) 644281806Srpaulo { 645214501Srpaulo wpa_printf(MSG_DEBUG, "Unsupported management group " 646214501Srpaulo "cipher %d", data.mgmt_group_cipher); 647214501Srpaulo return WPA_INVALID_MGMT_GROUP_CIPHER; 648214501Srpaulo } 649214501Srpaulo } 650214501Srpaulo 651214501Srpaulo if (wpa_auth->conf.ieee80211w == NO_MGMT_FRAME_PROTECTION || 652214501Srpaulo !(data.capabilities & WPA_CAPABILITY_MFPC)) 653214501Srpaulo sm->mgmt_frame_prot = 0; 654214501Srpaulo else 655214501Srpaulo sm->mgmt_frame_prot = 1; 656214501Srpaulo#endif /* CONFIG_IEEE80211W */ 657214501Srpaulo 658214501Srpaulo#ifdef CONFIG_IEEE80211R 659214501Srpaulo if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) { 660214501Srpaulo if (mdie == NULL || mdie_len < MOBILITY_DOMAIN_ID_LEN + 1) { 661214501Srpaulo wpa_printf(MSG_DEBUG, "RSN: Trying to use FT, but " 662214501Srpaulo "MDIE not included"); 663214501Srpaulo return WPA_INVALID_MDIE; 664214501Srpaulo } 665214501Srpaulo if (os_memcmp(mdie, wpa_auth->conf.mobility_domain, 666214501Srpaulo MOBILITY_DOMAIN_ID_LEN) != 0) { 667214501Srpaulo wpa_hexdump(MSG_DEBUG, "RSN: Attempted to use unknown " 668214501Srpaulo "MDIE", mdie, MOBILITY_DOMAIN_ID_LEN); 669214501Srpaulo return WPA_INVALID_MDIE; 670214501Srpaulo } 671214501Srpaulo } 672214501Srpaulo#endif /* CONFIG_IEEE80211R */ 673214501Srpaulo 674281806Srpaulo sm->pairwise = wpa_pick_pairwise_cipher(ciphers, 0); 675281806Srpaulo if (sm->pairwise < 0) 676281806Srpaulo return WPA_INVALID_PAIRWISE; 677214501Srpaulo 678214501Srpaulo /* TODO: clear WPA/WPA2 state if STA changes from one to another */ 679214501Srpaulo if (wpa_ie[0] == WLAN_EID_RSN) 680214501Srpaulo sm->wpa = WPA_VERSION_WPA2; 681214501Srpaulo else 682214501Srpaulo sm->wpa = WPA_VERSION_WPA; 683214501Srpaulo 684214501Srpaulo sm->pmksa = NULL; 685214501Srpaulo for (i = 0; i < data.num_pmkid; i++) { 686214501Srpaulo wpa_hexdump(MSG_DEBUG, "RSN IE: STA PMKID", 687214501Srpaulo &data.pmkid[i * PMKID_LEN], PMKID_LEN); 688214501Srpaulo sm->pmksa = pmksa_cache_auth_get(wpa_auth->pmksa, sm->addr, 689214501Srpaulo &data.pmkid[i * PMKID_LEN]); 690214501Srpaulo if (sm->pmksa) { 691214501Srpaulo pmkid = sm->pmksa->pmkid; 692214501Srpaulo break; 693214501Srpaulo } 694214501Srpaulo } 695214501Srpaulo for (i = 0; sm->pmksa == NULL && wpa_auth->conf.okc && 696214501Srpaulo i < data.num_pmkid; i++) { 697214501Srpaulo struct wpa_auth_okc_iter_data idata; 698214501Srpaulo idata.pmksa = NULL; 699214501Srpaulo idata.aa = wpa_auth->addr; 700214501Srpaulo idata.spa = sm->addr; 701214501Srpaulo idata.pmkid = &data.pmkid[i * PMKID_LEN]; 702214501Srpaulo wpa_auth_for_each_auth(wpa_auth, wpa_auth_okc_iter, &idata); 703214501Srpaulo if (idata.pmksa) { 704214501Srpaulo wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG, 705214501Srpaulo "OKC match for PMKID"); 706214501Srpaulo sm->pmksa = pmksa_cache_add_okc(wpa_auth->pmksa, 707214501Srpaulo idata.pmksa, 708214501Srpaulo wpa_auth->addr, 709214501Srpaulo idata.pmkid); 710214501Srpaulo pmkid = idata.pmkid; 711214501Srpaulo break; 712214501Srpaulo } 713214501Srpaulo } 714281806Srpaulo if (sm->pmksa && pmkid) { 715214501Srpaulo wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG, 716214501Srpaulo "PMKID found from PMKSA cache " 717214501Srpaulo "eap_type=%d vlan_id=%d", 718214501Srpaulo sm->pmksa->eap_type_authsrv, 719214501Srpaulo sm->pmksa->vlan_id); 720214501Srpaulo os_memcpy(wpa_auth->dot11RSNAPMKIDUsed, pmkid, PMKID_LEN); 721214501Srpaulo } 722214501Srpaulo 723214501Srpaulo if (sm->wpa_ie == NULL || sm->wpa_ie_len < wpa_ie_len) { 724214501Srpaulo os_free(sm->wpa_ie); 725214501Srpaulo sm->wpa_ie = os_malloc(wpa_ie_len); 726214501Srpaulo if (sm->wpa_ie == NULL) 727214501Srpaulo return WPA_ALLOC_FAIL; 728214501Srpaulo } 729214501Srpaulo os_memcpy(sm->wpa_ie, wpa_ie, wpa_ie_len); 730214501Srpaulo sm->wpa_ie_len = wpa_ie_len; 731214501Srpaulo 732214501Srpaulo return WPA_IE_OK; 733214501Srpaulo} 734214501Srpaulo 735214501Srpaulo 736281806Srpaulo#ifdef CONFIG_HS20 737281806Srpauloint wpa_validate_osen(struct wpa_authenticator *wpa_auth, 738281806Srpaulo struct wpa_state_machine *sm, 739281806Srpaulo const u8 *osen_ie, size_t osen_ie_len) 740281806Srpaulo{ 741281806Srpaulo if (wpa_auth == NULL || sm == NULL) 742281806Srpaulo return -1; 743281806Srpaulo 744281806Srpaulo /* TODO: parse OSEN element */ 745281806Srpaulo sm->wpa_key_mgmt = WPA_KEY_MGMT_OSEN; 746281806Srpaulo sm->mgmt_frame_prot = 1; 747281806Srpaulo sm->pairwise = WPA_CIPHER_CCMP; 748281806Srpaulo sm->wpa = WPA_VERSION_WPA2; 749281806Srpaulo 750281806Srpaulo if (sm->wpa_ie == NULL || sm->wpa_ie_len < osen_ie_len) { 751281806Srpaulo os_free(sm->wpa_ie); 752281806Srpaulo sm->wpa_ie = os_malloc(osen_ie_len); 753281806Srpaulo if (sm->wpa_ie == NULL) 754281806Srpaulo return -1; 755281806Srpaulo } 756281806Srpaulo 757281806Srpaulo os_memcpy(sm->wpa_ie, osen_ie, osen_ie_len); 758281806Srpaulo sm->wpa_ie_len = osen_ie_len; 759281806Srpaulo 760281806Srpaulo return 0; 761281806Srpaulo} 762281806Srpaulo 763281806Srpaulo#endif /* CONFIG_HS20 */ 764281806Srpaulo 765281806Srpaulo 766214501Srpaulo/** 767214501Srpaulo * wpa_parse_generic - Parse EAPOL-Key Key Data Generic IEs 768214501Srpaulo * @pos: Pointer to the IE header 769214501Srpaulo * @end: Pointer to the end of the Key Data buffer 770214501Srpaulo * @ie: Pointer to parsed IE data 771214501Srpaulo * Returns: 0 on success, 1 if end mark is found, -1 on failure 772214501Srpaulo */ 773214501Srpaulostatic int wpa_parse_generic(const u8 *pos, const u8 *end, 774214501Srpaulo struct wpa_eapol_ie_parse *ie) 775214501Srpaulo{ 776214501Srpaulo if (pos[1] == 0) 777214501Srpaulo return 1; 778214501Srpaulo 779214501Srpaulo if (pos[1] >= 6 && 780214501Srpaulo RSN_SELECTOR_GET(pos + 2) == WPA_OUI_TYPE && 781214501Srpaulo pos[2 + WPA_SELECTOR_LEN] == 1 && 782214501Srpaulo pos[2 + WPA_SELECTOR_LEN + 1] == 0) { 783214501Srpaulo ie->wpa_ie = pos; 784214501Srpaulo ie->wpa_ie_len = pos[1] + 2; 785214501Srpaulo return 0; 786214501Srpaulo } 787214501Srpaulo 788281806Srpaulo if (pos[1] >= 4 && WPA_GET_BE32(pos + 2) == OSEN_IE_VENDOR_TYPE) { 789281806Srpaulo ie->osen = pos; 790281806Srpaulo ie->osen_len = pos[1] + 2; 791281806Srpaulo return 0; 792281806Srpaulo } 793281806Srpaulo 794214501Srpaulo if (pos + 1 + RSN_SELECTOR_LEN < end && 795214501Srpaulo pos[1] >= RSN_SELECTOR_LEN + PMKID_LEN && 796214501Srpaulo RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_PMKID) { 797214501Srpaulo ie->pmkid = pos + 2 + RSN_SELECTOR_LEN; 798214501Srpaulo return 0; 799214501Srpaulo } 800214501Srpaulo 801214501Srpaulo if (pos[1] > RSN_SELECTOR_LEN + 2 && 802214501Srpaulo RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_GROUPKEY) { 803214501Srpaulo ie->gtk = pos + 2 + RSN_SELECTOR_LEN; 804214501Srpaulo ie->gtk_len = pos[1] - RSN_SELECTOR_LEN; 805214501Srpaulo return 0; 806214501Srpaulo } 807214501Srpaulo 808214501Srpaulo if (pos[1] > RSN_SELECTOR_LEN + 2 && 809214501Srpaulo RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_MAC_ADDR) { 810214501Srpaulo ie->mac_addr = pos + 2 + RSN_SELECTOR_LEN; 811214501Srpaulo ie->mac_addr_len = pos[1] - RSN_SELECTOR_LEN; 812214501Srpaulo return 0; 813214501Srpaulo } 814214501Srpaulo 815214501Srpaulo#ifdef CONFIG_PEERKEY 816214501Srpaulo if (pos[1] > RSN_SELECTOR_LEN + 2 && 817214501Srpaulo RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_SMK) { 818214501Srpaulo ie->smk = pos + 2 + RSN_SELECTOR_LEN; 819214501Srpaulo ie->smk_len = pos[1] - RSN_SELECTOR_LEN; 820214501Srpaulo return 0; 821214501Srpaulo } 822214501Srpaulo 823214501Srpaulo if (pos[1] > RSN_SELECTOR_LEN + 2 && 824214501Srpaulo RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_NONCE) { 825214501Srpaulo ie->nonce = pos + 2 + RSN_SELECTOR_LEN; 826214501Srpaulo ie->nonce_len = pos[1] - RSN_SELECTOR_LEN; 827214501Srpaulo return 0; 828214501Srpaulo } 829214501Srpaulo 830214501Srpaulo if (pos[1] > RSN_SELECTOR_LEN + 2 && 831214501Srpaulo RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_LIFETIME) { 832214501Srpaulo ie->lifetime = pos + 2 + RSN_SELECTOR_LEN; 833214501Srpaulo ie->lifetime_len = pos[1] - RSN_SELECTOR_LEN; 834214501Srpaulo return 0; 835214501Srpaulo } 836214501Srpaulo 837214501Srpaulo if (pos[1] > RSN_SELECTOR_LEN + 2 && 838214501Srpaulo RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_ERROR) { 839214501Srpaulo ie->error = pos + 2 + RSN_SELECTOR_LEN; 840214501Srpaulo ie->error_len = pos[1] - RSN_SELECTOR_LEN; 841214501Srpaulo return 0; 842214501Srpaulo } 843214501Srpaulo#endif /* CONFIG_PEERKEY */ 844214501Srpaulo 845214501Srpaulo#ifdef CONFIG_IEEE80211W 846214501Srpaulo if (pos[1] > RSN_SELECTOR_LEN + 2 && 847214501Srpaulo RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_IGTK) { 848214501Srpaulo ie->igtk = pos + 2 + RSN_SELECTOR_LEN; 849214501Srpaulo ie->igtk_len = pos[1] - RSN_SELECTOR_LEN; 850214501Srpaulo return 0; 851214501Srpaulo } 852214501Srpaulo#endif /* CONFIG_IEEE80211W */ 853214501Srpaulo 854281806Srpaulo#ifdef CONFIG_P2P 855281806Srpaulo if (pos[1] >= RSN_SELECTOR_LEN + 1 && 856281806Srpaulo RSN_SELECTOR_GET(pos + 2) == WFA_KEY_DATA_IP_ADDR_REQ) { 857281806Srpaulo ie->ip_addr_req = pos + 2 + RSN_SELECTOR_LEN; 858281806Srpaulo wpa_hexdump(MSG_DEBUG, "WPA: IP Address Request in EAPOL-Key", 859281806Srpaulo ie->ip_addr_req, pos[1] - RSN_SELECTOR_LEN); 860281806Srpaulo return 0; 861281806Srpaulo } 862281806Srpaulo 863281806Srpaulo if (pos[1] >= RSN_SELECTOR_LEN + 3 * 4 && 864281806Srpaulo RSN_SELECTOR_GET(pos + 2) == WFA_KEY_DATA_IP_ADDR_ALLOC) { 865281806Srpaulo ie->ip_addr_alloc = pos + 2 + RSN_SELECTOR_LEN; 866281806Srpaulo wpa_hexdump(MSG_DEBUG, 867281806Srpaulo "WPA: IP Address Allocation in EAPOL-Key", 868281806Srpaulo ie->ip_addr_alloc, pos[1] - RSN_SELECTOR_LEN); 869281806Srpaulo return 0; 870281806Srpaulo } 871281806Srpaulo#endif /* CONFIG_P2P */ 872281806Srpaulo 873214501Srpaulo return 0; 874214501Srpaulo} 875214501Srpaulo 876214501Srpaulo 877214501Srpaulo/** 878214501Srpaulo * wpa_parse_kde_ies - Parse EAPOL-Key Key Data IEs 879214501Srpaulo * @buf: Pointer to the Key Data buffer 880214501Srpaulo * @len: Key Data Length 881214501Srpaulo * @ie: Pointer to parsed IE data 882214501Srpaulo * Returns: 0 on success, -1 on failure 883214501Srpaulo */ 884214501Srpauloint wpa_parse_kde_ies(const u8 *buf, size_t len, struct wpa_eapol_ie_parse *ie) 885214501Srpaulo{ 886214501Srpaulo const u8 *pos, *end; 887214501Srpaulo int ret = 0; 888214501Srpaulo 889214501Srpaulo os_memset(ie, 0, sizeof(*ie)); 890214501Srpaulo for (pos = buf, end = pos + len; pos + 1 < end; pos += 2 + pos[1]) { 891214501Srpaulo if (pos[0] == 0xdd && 892214501Srpaulo ((pos == buf + len - 1) || pos[1] == 0)) { 893214501Srpaulo /* Ignore padding */ 894214501Srpaulo break; 895214501Srpaulo } 896214501Srpaulo if (pos + 2 + pos[1] > end) { 897214501Srpaulo wpa_printf(MSG_DEBUG, "WPA: EAPOL-Key Key Data " 898214501Srpaulo "underflow (ie=%d len=%d pos=%d)", 899214501Srpaulo pos[0], pos[1], (int) (pos - buf)); 900214501Srpaulo wpa_hexdump_key(MSG_DEBUG, "WPA: Key Data", 901214501Srpaulo buf, len); 902214501Srpaulo ret = -1; 903214501Srpaulo break; 904214501Srpaulo } 905214501Srpaulo if (*pos == WLAN_EID_RSN) { 906214501Srpaulo ie->rsn_ie = pos; 907214501Srpaulo ie->rsn_ie_len = pos[1] + 2; 908214501Srpaulo#ifdef CONFIG_IEEE80211R 909214501Srpaulo } else if (*pos == WLAN_EID_MOBILITY_DOMAIN) { 910214501Srpaulo ie->mdie = pos; 911214501Srpaulo ie->mdie_len = pos[1] + 2; 912214501Srpaulo } else if (*pos == WLAN_EID_FAST_BSS_TRANSITION) { 913214501Srpaulo ie->ftie = pos; 914214501Srpaulo ie->ftie_len = pos[1] + 2; 915214501Srpaulo#endif /* CONFIG_IEEE80211R */ 916214501Srpaulo } else if (*pos == WLAN_EID_VENDOR_SPECIFIC) { 917214501Srpaulo ret = wpa_parse_generic(pos, end, ie); 918214501Srpaulo if (ret < 0) 919214501Srpaulo break; 920214501Srpaulo if (ret > 0) { 921214501Srpaulo ret = 0; 922214501Srpaulo break; 923214501Srpaulo } 924214501Srpaulo } else { 925214501Srpaulo wpa_hexdump(MSG_DEBUG, "WPA: Unrecognized EAPOL-Key " 926214501Srpaulo "Key Data IE", pos, 2 + pos[1]); 927214501Srpaulo } 928214501Srpaulo } 929214501Srpaulo 930214501Srpaulo return ret; 931214501Srpaulo} 932214501Srpaulo 933214501Srpaulo 934214501Srpauloint wpa_auth_uses_mfp(struct wpa_state_machine *sm) 935214501Srpaulo{ 936214501Srpaulo return sm ? sm->mgmt_frame_prot : 0; 937214501Srpaulo} 938