139beb93cSSam Leffler /* 239beb93cSSam Leffler * WPA Supplicant - Glue code to setup EAPOL and RSN modules 35b9c547cSRui Paulo * Copyright (c) 2003-2015, Jouni Malinen <j@w1.fi> 439beb93cSSam Leffler * 5f05cddf9SRui Paulo * This software may be distributed under the terms of the BSD license. 6f05cddf9SRui Paulo * See README for more details. 739beb93cSSam Leffler */ 839beb93cSSam Leffler 939beb93cSSam Leffler #include "includes.h" 1039beb93cSSam Leffler 1139beb93cSSam Leffler #include "common.h" 1239beb93cSSam Leffler #include "eapol_supp/eapol_supp_sm.h" 1385732ac8SCy Schubert #include "eap_peer/eap.h" 14e28a4053SRui Paulo #include "rsn_supp/wpa.h" 1539beb93cSSam Leffler #include "eloop.h" 1639beb93cSSam Leffler #include "config.h" 1739beb93cSSam Leffler #include "l2_packet/l2_packet.h" 18e28a4053SRui Paulo #include "common/wpa_common.h" 19c1d255d3SCy Schubert #include "common/ptksa_cache.h" 2039beb93cSSam Leffler #include "wpa_supplicant_i.h" 21e28a4053SRui Paulo #include "driver_i.h" 22e28a4053SRui Paulo #include "rsn_supp/pmksa_cache.h" 23e28a4053SRui Paulo #include "sme.h" 24e28a4053SRui Paulo #include "common/ieee802_11_defs.h" 25e28a4053SRui Paulo #include "common/wpa_ctrl.h" 2639beb93cSSam Leffler #include "wpas_glue.h" 2739beb93cSSam Leffler #include "wps_supplicant.h" 28e28a4053SRui Paulo #include "bss.h" 29e28a4053SRui Paulo #include "scan.h" 30f05cddf9SRui Paulo #include "notify.h" 315b9c547cSRui Paulo #include "wpas_kay.h" 3239beb93cSSam Leffler 3339beb93cSSam Leffler 3439beb93cSSam Leffler #ifndef CONFIG_NO_CONFIG_BLOBS 3539beb93cSSam Leffler #if defined(IEEE8021X_EAPOL) || !defined(CONFIG_NO_WPA) 3639beb93cSSam Leffler static void wpa_supplicant_set_config_blob(void *ctx, 3739beb93cSSam Leffler struct wpa_config_blob *blob) 3839beb93cSSam Leffler { 3939beb93cSSam Leffler struct wpa_supplicant *wpa_s = ctx; 4039beb93cSSam Leffler wpa_config_set_blob(wpa_s->conf, blob); 4139beb93cSSam Leffler if (wpa_s->conf->update_config) { 4239beb93cSSam Leffler int ret = wpa_config_write(wpa_s->confname, wpa_s->conf); 4339beb93cSSam Leffler if (ret) { 4439beb93cSSam Leffler wpa_printf(MSG_DEBUG, "Failed to update config after " 4539beb93cSSam Leffler "blob set"); 4639beb93cSSam Leffler } 4739beb93cSSam Leffler } 4839beb93cSSam Leffler } 4939beb93cSSam Leffler 5039beb93cSSam Leffler 5139beb93cSSam Leffler static const struct wpa_config_blob * 5239beb93cSSam Leffler wpa_supplicant_get_config_blob(void *ctx, const char *name) 5339beb93cSSam Leffler { 5439beb93cSSam Leffler struct wpa_supplicant *wpa_s = ctx; 5539beb93cSSam Leffler return wpa_config_get_blob(wpa_s->conf, name); 5639beb93cSSam Leffler } 5739beb93cSSam Leffler #endif /* defined(IEEE8021X_EAPOL) || !defined(CONFIG_NO_WPA) */ 5839beb93cSSam Leffler #endif /* CONFIG_NO_CONFIG_BLOBS */ 5939beb93cSSam Leffler 6039beb93cSSam Leffler 6139beb93cSSam Leffler #if defined(IEEE8021X_EAPOL) || !defined(CONFIG_NO_WPA) 6239beb93cSSam Leffler static u8 * wpa_alloc_eapol(const struct wpa_supplicant *wpa_s, u8 type, 6339beb93cSSam Leffler const void *data, u16 data_len, 6439beb93cSSam Leffler size_t *msg_len, void **data_pos) 6539beb93cSSam Leffler { 6639beb93cSSam Leffler struct ieee802_1x_hdr *hdr; 6739beb93cSSam Leffler 6839beb93cSSam Leffler *msg_len = sizeof(*hdr) + data_len; 6939beb93cSSam Leffler hdr = os_malloc(*msg_len); 7039beb93cSSam Leffler if (hdr == NULL) 7139beb93cSSam Leffler return NULL; 7239beb93cSSam Leffler 7339beb93cSSam Leffler hdr->version = wpa_s->conf->eapol_version; 7439beb93cSSam Leffler hdr->type = type; 7539beb93cSSam Leffler hdr->length = host_to_be16(data_len); 7639beb93cSSam Leffler 7739beb93cSSam Leffler if (data) 7839beb93cSSam Leffler os_memcpy(hdr + 1, data, data_len); 7939beb93cSSam Leffler else 8039beb93cSSam Leffler os_memset(hdr + 1, 0, data_len); 8139beb93cSSam Leffler 8239beb93cSSam Leffler if (data_pos) 8339beb93cSSam Leffler *data_pos = hdr + 1; 8439beb93cSSam Leffler 8539beb93cSSam Leffler return (u8 *) hdr; 8639beb93cSSam Leffler } 8739beb93cSSam Leffler 8839beb93cSSam Leffler 8939beb93cSSam Leffler /** 9039beb93cSSam Leffler * wpa_ether_send - Send Ethernet frame 9139beb93cSSam Leffler * @wpa_s: Pointer to wpa_supplicant data 9239beb93cSSam Leffler * @dest: Destination MAC address 9339beb93cSSam Leffler * @proto: Ethertype in host byte order 9439beb93cSSam Leffler * @buf: Frame payload starting from IEEE 802.1X header 9539beb93cSSam Leffler * @len: Frame payload length 9639beb93cSSam Leffler * Returns: >=0 on success, <0 on failure 9739beb93cSSam Leffler */ 98c1d255d3SCy Schubert int wpa_ether_send(struct wpa_supplicant *wpa_s, const u8 *dest, 9939beb93cSSam Leffler u16 proto, const u8 *buf, size_t len) 10039beb93cSSam Leffler { 1015b9c547cSRui Paulo #ifdef CONFIG_TESTING_OPTIONS 1025b9c547cSRui Paulo if (wpa_s->ext_eapol_frame_io && proto == ETH_P_EAPOL) { 1035b9c547cSRui Paulo size_t hex_len = 2 * len + 1; 1045b9c547cSRui Paulo char *hex = os_malloc(hex_len); 1055b9c547cSRui Paulo 1065b9c547cSRui Paulo if (hex == NULL) 1075b9c547cSRui Paulo return -1; 1085b9c547cSRui Paulo wpa_snprintf_hex(hex, hex_len, buf, len); 1095b9c547cSRui Paulo wpa_msg(wpa_s, MSG_INFO, "EAPOL-TX " MACSTR " %s", 1105b9c547cSRui Paulo MAC2STR(dest), hex); 1115b9c547cSRui Paulo os_free(hex); 1125b9c547cSRui Paulo return 0; 1135b9c547cSRui Paulo } 1145b9c547cSRui Paulo #endif /* CONFIG_TESTING_OPTIONS */ 1155b9c547cSRui Paulo 116c1d255d3SCy Schubert if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_CONTROL_PORT) { 117c1d255d3SCy Schubert int encrypt = wpa_s->wpa && 118c1d255d3SCy Schubert wpa_sm_has_ptk_installed(wpa_s->wpa); 119c1d255d3SCy Schubert 120c1d255d3SCy Schubert return wpa_drv_tx_control_port(wpa_s, dest, proto, buf, len, 121c1d255d3SCy Schubert !encrypt); 122c1d255d3SCy Schubert } 123c1d255d3SCy Schubert 12439beb93cSSam Leffler if (wpa_s->l2) { 12539beb93cSSam Leffler return l2_packet_send(wpa_s->l2, dest, proto, buf, len); 12639beb93cSSam Leffler } 12739beb93cSSam Leffler 1285b9c547cSRui Paulo return -1; 12939beb93cSSam Leffler } 13039beb93cSSam Leffler #endif /* IEEE8021X_EAPOL || !CONFIG_NO_WPA */ 13139beb93cSSam Leffler 13239beb93cSSam Leffler 13339beb93cSSam Leffler #ifdef IEEE8021X_EAPOL 13439beb93cSSam Leffler 13539beb93cSSam Leffler /** 13639beb93cSSam Leffler * wpa_supplicant_eapol_send - Send IEEE 802.1X EAPOL packet to Authenticator 13739beb93cSSam Leffler * @ctx: Pointer to wpa_supplicant data (wpa_s) 13839beb93cSSam Leffler * @type: IEEE 802.1X packet type (IEEE802_1X_TYPE_*) 13939beb93cSSam Leffler * @buf: EAPOL payload (after IEEE 802.1X header) 14039beb93cSSam Leffler * @len: EAPOL payload length 14139beb93cSSam Leffler * Returns: >=0 on success, <0 on failure 14239beb93cSSam Leffler * 14339beb93cSSam Leffler * This function adds Ethernet and IEEE 802.1X header and sends the EAPOL frame 14439beb93cSSam Leffler * to the current Authenticator. 14539beb93cSSam Leffler */ 14639beb93cSSam Leffler static int wpa_supplicant_eapol_send(void *ctx, int type, const u8 *buf, 14739beb93cSSam Leffler size_t len) 14839beb93cSSam Leffler { 14939beb93cSSam Leffler struct wpa_supplicant *wpa_s = ctx; 15039beb93cSSam Leffler u8 *msg, *dst, bssid[ETH_ALEN]; 15139beb93cSSam Leffler size_t msglen; 15239beb93cSSam Leffler int res; 15339beb93cSSam Leffler 15439beb93cSSam Leffler /* TODO: could add l2_packet_sendmsg that allows fragments to avoid 15539beb93cSSam Leffler * extra copy here */ 15639beb93cSSam Leffler 15739beb93cSSam Leffler if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) || 15885732ac8SCy Schubert wpa_s->key_mgmt == WPA_KEY_MGMT_OWE || 15985732ac8SCy Schubert wpa_s->key_mgmt == WPA_KEY_MGMT_DPP || 16039beb93cSSam Leffler wpa_s->key_mgmt == WPA_KEY_MGMT_NONE) { 16139beb93cSSam Leffler /* Current SSID is not using IEEE 802.1X/EAP, so drop possible 16239beb93cSSam Leffler * EAPOL frames (mainly, EAPOL-Start) from EAPOL state 16339beb93cSSam Leffler * machines. */ 16439beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPA: drop TX EAPOL in non-IEEE 802.1X " 16539beb93cSSam Leffler "mode (type=%d len=%lu)", type, 16639beb93cSSam Leffler (unsigned long) len); 16739beb93cSSam Leffler return -1; 16839beb93cSSam Leffler } 16939beb93cSSam Leffler 17039beb93cSSam Leffler if (pmksa_cache_get_current(wpa_s->wpa) && 17139beb93cSSam Leffler type == IEEE802_1X_TYPE_EAPOL_START) { 1725b9c547cSRui Paulo /* 1735b9c547cSRui Paulo * We were trying to use PMKSA caching and sending EAPOL-Start 1745b9c547cSRui Paulo * would abort that and trigger full EAPOL authentication. 1755b9c547cSRui Paulo * However, we've already waited for the AP/Authenticator to 1765b9c547cSRui Paulo * start 4-way handshake or EAP authentication, and apparently 1775b9c547cSRui Paulo * it has not done so since the startWhen timer has reached zero 1785b9c547cSRui Paulo * to get the state machine sending EAPOL-Start. This is not 1795b9c547cSRui Paulo * really supposed to happen, but an interoperability issue with 1805b9c547cSRui Paulo * a deployed AP has been identified where the connection fails 1815b9c547cSRui Paulo * due to that AP failing to operate correctly if PMKID is 1825b9c547cSRui Paulo * included in the Association Request frame. To work around 1835b9c547cSRui Paulo * this, assume PMKSA caching failed and try to initiate full 1845b9c547cSRui Paulo * EAP authentication. 1855b9c547cSRui Paulo */ 1865b9c547cSRui Paulo if (!wpa_s->current_ssid || 1875b9c547cSRui Paulo wpa_s->current_ssid->eap_workaround) { 1885b9c547cSRui Paulo wpa_printf(MSG_DEBUG, 1895b9c547cSRui Paulo "RSN: Timeout on waiting for the AP to initiate 4-way handshake for PMKSA caching or EAP authentication - try to force it to start EAP authentication"); 1905b9c547cSRui Paulo } else { 1915b9c547cSRui Paulo wpa_printf(MSG_DEBUG, 1925b9c547cSRui Paulo "RSN: PMKSA caching - do not send EAPOL-Start"); 19339beb93cSSam Leffler return -1; 19439beb93cSSam Leffler } 1955b9c547cSRui Paulo } 19639beb93cSSam Leffler 19739beb93cSSam Leffler if (is_zero_ether_addr(wpa_s->bssid)) { 19839beb93cSSam Leffler wpa_printf(MSG_DEBUG, "BSSID not set when trying to send an " 19939beb93cSSam Leffler "EAPOL frame"); 20039beb93cSSam Leffler if (wpa_drv_get_bssid(wpa_s, bssid) == 0 && 20139beb93cSSam Leffler !is_zero_ether_addr(bssid)) { 20239beb93cSSam Leffler dst = bssid; 20339beb93cSSam Leffler wpa_printf(MSG_DEBUG, "Using current BSSID " MACSTR 20439beb93cSSam Leffler " from the driver as the EAPOL destination", 20539beb93cSSam Leffler MAC2STR(dst)); 20639beb93cSSam Leffler } else { 20739beb93cSSam Leffler dst = wpa_s->last_eapol_src; 20839beb93cSSam Leffler wpa_printf(MSG_DEBUG, "Using the source address of the" 20939beb93cSSam Leffler " last received EAPOL frame " MACSTR " as " 21039beb93cSSam Leffler "the EAPOL destination", 21139beb93cSSam Leffler MAC2STR(dst)); 21239beb93cSSam Leffler } 21339beb93cSSam Leffler } else { 21439beb93cSSam Leffler /* BSSID was already set (from (Re)Assoc event, so use it as 21539beb93cSSam Leffler * the EAPOL destination. */ 21639beb93cSSam Leffler dst = wpa_s->bssid; 21739beb93cSSam Leffler } 21839beb93cSSam Leffler 21939beb93cSSam Leffler msg = wpa_alloc_eapol(wpa_s, type, buf, len, &msglen, NULL); 22039beb93cSSam Leffler if (msg == NULL) 22139beb93cSSam Leffler return -1; 22239beb93cSSam Leffler 22339beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TX EAPOL: dst=" MACSTR, MAC2STR(dst)); 22439beb93cSSam Leffler wpa_hexdump(MSG_MSGDUMP, "TX EAPOL", msg, msglen); 22539beb93cSSam Leffler res = wpa_ether_send(wpa_s, dst, ETH_P_EAPOL, msg, msglen); 22639beb93cSSam Leffler os_free(msg); 22739beb93cSSam Leffler return res; 22839beb93cSSam Leffler } 22939beb93cSSam Leffler 23039beb93cSSam Leffler 231c1d255d3SCy Schubert #ifdef CONFIG_WEP 23239beb93cSSam Leffler /** 23339beb93cSSam Leffler * wpa_eapol_set_wep_key - set WEP key for the driver 23439beb93cSSam Leffler * @ctx: Pointer to wpa_supplicant data (wpa_s) 23539beb93cSSam Leffler * @unicast: 1 = individual unicast key, 0 = broadcast key 23639beb93cSSam Leffler * @keyidx: WEP key index (0..3) 23739beb93cSSam Leffler * @key: Pointer to key data 23839beb93cSSam Leffler * @keylen: Key length in bytes 23939beb93cSSam Leffler * Returns: 0 on success or < 0 on error. 24039beb93cSSam Leffler */ 24139beb93cSSam Leffler static int wpa_eapol_set_wep_key(void *ctx, int unicast, int keyidx, 24239beb93cSSam Leffler const u8 *key, size_t keylen) 24339beb93cSSam Leffler { 24439beb93cSSam Leffler struct wpa_supplicant *wpa_s = ctx; 24539beb93cSSam Leffler if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) { 24639beb93cSSam Leffler int cipher = (keylen == 5) ? WPA_CIPHER_WEP40 : 24739beb93cSSam Leffler WPA_CIPHER_WEP104; 24839beb93cSSam Leffler if (unicast) 24939beb93cSSam Leffler wpa_s->pairwise_cipher = cipher; 25039beb93cSSam Leffler else 25139beb93cSSam Leffler wpa_s->group_cipher = cipher; 25239beb93cSSam Leffler } 25339beb93cSSam Leffler return wpa_drv_set_key(wpa_s, WPA_ALG_WEP, 254f05cddf9SRui Paulo unicast ? wpa_s->bssid : NULL, 255c1d255d3SCy Schubert keyidx, unicast, NULL, 0, key, keylen, 256c1d255d3SCy Schubert unicast ? KEY_FLAG_PAIRWISE_RX_TX : 257c1d255d3SCy Schubert KEY_FLAG_GROUP_RX_TX_DEFAULT); 25839beb93cSSam Leffler } 259c1d255d3SCy Schubert #endif /* CONFIG_WEP */ 26039beb93cSSam Leffler 26139beb93cSSam Leffler 26239beb93cSSam Leffler static void wpa_supplicant_aborted_cached(void *ctx) 26339beb93cSSam Leffler { 26439beb93cSSam Leffler struct wpa_supplicant *wpa_s = ctx; 26539beb93cSSam Leffler wpa_sm_aborted_cached(wpa_s->wpa); 26639beb93cSSam Leffler } 26739beb93cSSam Leffler 26839beb93cSSam Leffler 2695b9c547cSRui Paulo static const char * result_str(enum eapol_supp_result result) 2705b9c547cSRui Paulo { 2715b9c547cSRui Paulo switch (result) { 2725b9c547cSRui Paulo case EAPOL_SUPP_RESULT_FAILURE: 2735b9c547cSRui Paulo return "FAILURE"; 2745b9c547cSRui Paulo case EAPOL_SUPP_RESULT_SUCCESS: 2755b9c547cSRui Paulo return "SUCCESS"; 2765b9c547cSRui Paulo case EAPOL_SUPP_RESULT_EXPECTED_FAILURE: 2775b9c547cSRui Paulo return "EXPECTED_FAILURE"; 2785b9c547cSRui Paulo } 2795b9c547cSRui Paulo return "?"; 2805b9c547cSRui Paulo } 2815b9c547cSRui Paulo 2825b9c547cSRui Paulo 2835b9c547cSRui Paulo static void wpa_supplicant_eapol_cb(struct eapol_sm *eapol, 2845b9c547cSRui Paulo enum eapol_supp_result result, 28539beb93cSSam Leffler void *ctx) 28639beb93cSSam Leffler { 28739beb93cSSam Leffler struct wpa_supplicant *wpa_s = ctx; 28839beb93cSSam Leffler int res, pmk_len; 28939beb93cSSam Leffler u8 pmk[PMK_LEN]; 29039beb93cSSam Leffler 2915b9c547cSRui Paulo wpa_printf(MSG_DEBUG, "EAPOL authentication completed - result=%s", 2925b9c547cSRui Paulo result_str(result)); 29339beb93cSSam Leffler 29439beb93cSSam Leffler if (wpas_wps_eapol_cb(wpa_s) > 0) 29539beb93cSSam Leffler return; 29639beb93cSSam Leffler 2975b9c547cSRui Paulo wpa_s->eap_expected_failure = result == 2985b9c547cSRui Paulo EAPOL_SUPP_RESULT_EXPECTED_FAILURE; 2995b9c547cSRui Paulo 3005b9c547cSRui Paulo if (result != EAPOL_SUPP_RESULT_SUCCESS) { 30139beb93cSSam Leffler /* 30239beb93cSSam Leffler * Make sure we do not get stuck here waiting for long EAPOL 30339beb93cSSam Leffler * timeout if the AP does not disconnect in case of 30439beb93cSSam Leffler * authentication failure. 30539beb93cSSam Leffler */ 30639beb93cSSam Leffler wpa_supplicant_req_auth_timeout(wpa_s, 2, 0); 3075b9c547cSRui Paulo } else { 3085b9c547cSRui Paulo ieee802_1x_notify_create_actor(wpa_s, wpa_s->last_eapol_src); 30939beb93cSSam Leffler } 31039beb93cSSam Leffler 3115b9c547cSRui Paulo if (result != EAPOL_SUPP_RESULT_SUCCESS || 3124bc52338SCy Schubert !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_8021X)) 31339beb93cSSam Leffler return; 31439beb93cSSam Leffler 31539beb93cSSam Leffler if (!wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) 31639beb93cSSam Leffler return; 31739beb93cSSam Leffler 31839beb93cSSam Leffler wpa_printf(MSG_DEBUG, "Configure PMK for driver-based RSN 4-way " 31939beb93cSSam Leffler "handshake"); 32039beb93cSSam Leffler 32139beb93cSSam Leffler pmk_len = PMK_LEN; 322f05cddf9SRui Paulo if (wpa_key_mgmt_ft(wpa_s->key_mgmt)) { 323f05cddf9SRui Paulo #ifdef CONFIG_IEEE80211R 324f05cddf9SRui Paulo u8 buf[2 * PMK_LEN]; 325f05cddf9SRui Paulo wpa_printf(MSG_DEBUG, "RSN: Use FT XXKey as PMK for " 326f05cddf9SRui Paulo "driver-based 4-way hs and FT"); 327f05cddf9SRui Paulo res = eapol_sm_get_key(eapol, buf, 2 * PMK_LEN); 328f05cddf9SRui Paulo if (res == 0) { 329f05cddf9SRui Paulo os_memcpy(pmk, buf + PMK_LEN, PMK_LEN); 330f05cddf9SRui Paulo os_memset(buf, 0, sizeof(buf)); 331f05cddf9SRui Paulo } 332f05cddf9SRui Paulo #else /* CONFIG_IEEE80211R */ 333f05cddf9SRui Paulo res = -1; 334f05cddf9SRui Paulo #endif /* CONFIG_IEEE80211R */ 335f05cddf9SRui Paulo } else { 33639beb93cSSam Leffler res = eapol_sm_get_key(eapol, pmk, PMK_LEN); 33739beb93cSSam Leffler if (res) { 33839beb93cSSam Leffler /* 33939beb93cSSam Leffler * EAP-LEAP is an exception from other EAP methods: it 34039beb93cSSam Leffler * uses only 16-byte PMK. 34139beb93cSSam Leffler */ 34239beb93cSSam Leffler res = eapol_sm_get_key(eapol, pmk, 16); 34339beb93cSSam Leffler pmk_len = 16; 34439beb93cSSam Leffler } 345f05cddf9SRui Paulo } 34639beb93cSSam Leffler 34739beb93cSSam Leffler if (res) { 34839beb93cSSam Leffler wpa_printf(MSG_DEBUG, "Failed to get PMK from EAPOL state " 34939beb93cSSam Leffler "machines"); 35039beb93cSSam Leffler return; 35139beb93cSSam Leffler } 35239beb93cSSam Leffler 353f05cddf9SRui Paulo wpa_hexdump_key(MSG_DEBUG, "RSN: Configure PMK for driver-based 4-way " 354f05cddf9SRui Paulo "handshake", pmk, pmk_len); 355f05cddf9SRui Paulo 356c1d255d3SCy Schubert if (wpa_drv_set_key(wpa_s, 0, NULL, 0, 0, NULL, 0, pmk, 357c1d255d3SCy Schubert pmk_len, KEY_FLAG_PMK)) { 35839beb93cSSam Leffler wpa_printf(MSG_DEBUG, "Failed to set PMK to the driver"); 35939beb93cSSam Leffler } 36039beb93cSSam Leffler 36139beb93cSSam Leffler wpa_supplicant_cancel_scan(wpa_s); 36239beb93cSSam Leffler wpa_supplicant_cancel_auth_timeout(wpa_s); 36339beb93cSSam Leffler wpa_supplicant_set_state(wpa_s, WPA_COMPLETED); 36439beb93cSSam Leffler 36539beb93cSSam Leffler } 36639beb93cSSam Leffler 36739beb93cSSam Leffler 36839beb93cSSam Leffler static void wpa_supplicant_notify_eapol_done(void *ctx) 36939beb93cSSam Leffler { 37039beb93cSSam Leffler struct wpa_supplicant *wpa_s = ctx; 37139beb93cSSam Leffler wpa_msg(wpa_s, MSG_DEBUG, "WPA: EAPOL processing complete"); 37239beb93cSSam Leffler if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) { 37339beb93cSSam Leffler wpa_supplicant_set_state(wpa_s, WPA_4WAY_HANDSHAKE); 37439beb93cSSam Leffler } else { 37539beb93cSSam Leffler wpa_supplicant_cancel_auth_timeout(wpa_s); 37639beb93cSSam Leffler wpa_supplicant_set_state(wpa_s, WPA_COMPLETED); 37739beb93cSSam Leffler } 37839beb93cSSam Leffler } 37939beb93cSSam Leffler 38039beb93cSSam Leffler #endif /* IEEE8021X_EAPOL */ 38139beb93cSSam Leffler 38239beb93cSSam Leffler 38339beb93cSSam Leffler #ifndef CONFIG_NO_WPA 38439beb93cSSam Leffler 38539beb93cSSam Leffler static int wpa_get_beacon_ie(struct wpa_supplicant *wpa_s) 38639beb93cSSam Leffler { 38739beb93cSSam Leffler int ret = 0; 388e28a4053SRui Paulo struct wpa_bss *curr = NULL, *bss; 38939beb93cSSam Leffler struct wpa_ssid *ssid = wpa_s->current_ssid; 39039beb93cSSam Leffler const u8 *ie; 39139beb93cSSam Leffler 392e28a4053SRui Paulo dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) { 393e28a4053SRui Paulo if (os_memcmp(bss->bssid, wpa_s->bssid, ETH_ALEN) != 0) 39439beb93cSSam Leffler continue; 39539beb93cSSam Leffler if (ssid == NULL || 396e28a4053SRui Paulo ((bss->ssid_len == ssid->ssid_len && 397e28a4053SRui Paulo os_memcmp(bss->ssid, ssid->ssid, ssid->ssid_len) == 0) || 39839beb93cSSam Leffler ssid->ssid_len == 0)) { 399e28a4053SRui Paulo curr = bss; 40039beb93cSSam Leffler break; 40139beb93cSSam Leffler } 402c1d255d3SCy Schubert #ifdef CONFIG_OWE 403c1d255d3SCy Schubert if (ssid && (ssid->key_mgmt & WPA_KEY_MGMT_OWE) && 404c1d255d3SCy Schubert (bss->flags & WPA_BSS_OWE_TRANSITION)) { 405c1d255d3SCy Schubert curr = bss; 406c1d255d3SCy Schubert break; 407c1d255d3SCy Schubert } 408c1d255d3SCy Schubert #endif /* CONFIG_OWE */ 40939beb93cSSam Leffler } 41039beb93cSSam Leffler 41139beb93cSSam Leffler if (curr) { 412e28a4053SRui Paulo ie = wpa_bss_get_vendor_ie(curr, WPA_IE_VENDOR_TYPE); 41339beb93cSSam Leffler if (wpa_sm_set_ap_wpa_ie(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0)) 41439beb93cSSam Leffler ret = -1; 41539beb93cSSam Leffler 416e28a4053SRui Paulo ie = wpa_bss_get_ie(curr, WLAN_EID_RSN); 41739beb93cSSam Leffler if (wpa_sm_set_ap_rsn_ie(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0)) 41839beb93cSSam Leffler ret = -1; 419c1d255d3SCy Schubert 420c1d255d3SCy Schubert ie = wpa_bss_get_ie(curr, WLAN_EID_RSNX); 421c1d255d3SCy Schubert if (wpa_sm_set_ap_rsnxe(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0)) 422c1d255d3SCy Schubert ret = -1; 42339beb93cSSam Leffler } else { 42439beb93cSSam Leffler ret = -1; 42539beb93cSSam Leffler } 42639beb93cSSam Leffler 42739beb93cSSam Leffler return ret; 42839beb93cSSam Leffler } 42939beb93cSSam Leffler 43039beb93cSSam Leffler 43139beb93cSSam Leffler static int wpa_supplicant_get_beacon_ie(void *ctx) 43239beb93cSSam Leffler { 43339beb93cSSam Leffler struct wpa_supplicant *wpa_s = ctx; 43439beb93cSSam Leffler if (wpa_get_beacon_ie(wpa_s) == 0) { 43539beb93cSSam Leffler return 0; 43639beb93cSSam Leffler } 43739beb93cSSam Leffler 43839beb93cSSam Leffler /* No WPA/RSN IE found in the cached scan results. Try to get updated 43939beb93cSSam Leffler * scan results from the driver. */ 440e28a4053SRui Paulo if (wpa_supplicant_update_scan_results(wpa_s) < 0) 44139beb93cSSam Leffler return -1; 44239beb93cSSam Leffler 44339beb93cSSam Leffler return wpa_get_beacon_ie(wpa_s); 44439beb93cSSam Leffler } 44539beb93cSSam Leffler 44639beb93cSSam Leffler 44739beb93cSSam Leffler static u8 * _wpa_alloc_eapol(void *wpa_s, u8 type, 44839beb93cSSam Leffler const void *data, u16 data_len, 44939beb93cSSam Leffler size_t *msg_len, void **data_pos) 45039beb93cSSam Leffler { 45139beb93cSSam Leffler return wpa_alloc_eapol(wpa_s, type, data, data_len, msg_len, data_pos); 45239beb93cSSam Leffler } 45339beb93cSSam Leffler 45439beb93cSSam Leffler 45539beb93cSSam Leffler static int _wpa_ether_send(void *wpa_s, const u8 *dest, u16 proto, 45639beb93cSSam Leffler const u8 *buf, size_t len) 45739beb93cSSam Leffler { 45839beb93cSSam Leffler return wpa_ether_send(wpa_s, dest, proto, buf, len); 45939beb93cSSam Leffler } 46039beb93cSSam Leffler 46139beb93cSSam Leffler 46239beb93cSSam Leffler static void _wpa_supplicant_cancel_auth_timeout(void *wpa_s) 46339beb93cSSam Leffler { 46439beb93cSSam Leffler wpa_supplicant_cancel_auth_timeout(wpa_s); 46539beb93cSSam Leffler } 46639beb93cSSam Leffler 46739beb93cSSam Leffler 468e28a4053SRui Paulo static void _wpa_supplicant_set_state(void *wpa_s, enum wpa_states state) 46939beb93cSSam Leffler { 47039beb93cSSam Leffler wpa_supplicant_set_state(wpa_s, state); 47139beb93cSSam Leffler } 47239beb93cSSam Leffler 47339beb93cSSam Leffler 47439beb93cSSam Leffler /** 47539beb93cSSam Leffler * wpa_supplicant_get_state - Get the connection state 47639beb93cSSam Leffler * @wpa_s: Pointer to wpa_supplicant data 47739beb93cSSam Leffler * Returns: The current connection state (WPA_*) 47839beb93cSSam Leffler */ 479e28a4053SRui Paulo static enum wpa_states wpa_supplicant_get_state(struct wpa_supplicant *wpa_s) 48039beb93cSSam Leffler { 48139beb93cSSam Leffler return wpa_s->wpa_state; 48239beb93cSSam Leffler } 48339beb93cSSam Leffler 48439beb93cSSam Leffler 485e28a4053SRui Paulo static enum wpa_states _wpa_supplicant_get_state(void *wpa_s) 48639beb93cSSam Leffler { 48739beb93cSSam Leffler return wpa_supplicant_get_state(wpa_s); 48839beb93cSSam Leffler } 48939beb93cSSam Leffler 49039beb93cSSam Leffler 491206b73d0SCy Schubert static void _wpa_supplicant_deauthenticate(void *wpa_s, u16 reason_code) 49239beb93cSSam Leffler { 49339beb93cSSam Leffler wpa_supplicant_deauthenticate(wpa_s, reason_code); 49439beb93cSSam Leffler /* Schedule a scan to make sure we continue looking for networks */ 4953157ba21SRui Paulo wpa_supplicant_req_scan(wpa_s, 5, 0); 49639beb93cSSam Leffler } 49739beb93cSSam Leffler 49839beb93cSSam Leffler 499c1d255d3SCy Schubert static void _wpa_supplicant_reconnect(void *wpa_s) 500c1d255d3SCy Schubert { 501c1d255d3SCy Schubert wpa_supplicant_reconnect(wpa_s); 502c1d255d3SCy Schubert } 503c1d255d3SCy Schubert 504c1d255d3SCy Schubert 50539beb93cSSam Leffler static void * wpa_supplicant_get_network_ctx(void *wpa_s) 50639beb93cSSam Leffler { 50739beb93cSSam Leffler return wpa_supplicant_get_ssid(wpa_s); 50839beb93cSSam Leffler } 50939beb93cSSam Leffler 51039beb93cSSam Leffler 51139beb93cSSam Leffler static int wpa_supplicant_get_bssid(void *ctx, u8 *bssid) 51239beb93cSSam Leffler { 51339beb93cSSam Leffler struct wpa_supplicant *wpa_s = ctx; 51439beb93cSSam Leffler return wpa_drv_get_bssid(wpa_s, bssid); 51539beb93cSSam Leffler } 51639beb93cSSam Leffler 51739beb93cSSam Leffler 518e28a4053SRui Paulo static int wpa_supplicant_set_key(void *_wpa_s, enum wpa_alg alg, 51939beb93cSSam Leffler const u8 *addr, int key_idx, int set_tx, 52039beb93cSSam Leffler const u8 *seq, size_t seq_len, 521c1d255d3SCy Schubert const u8 *key, size_t key_len, 522c1d255d3SCy Schubert enum key_flag key_flag) 52339beb93cSSam Leffler { 52439beb93cSSam Leffler struct wpa_supplicant *wpa_s = _wpa_s; 52539beb93cSSam Leffler if (alg == WPA_ALG_TKIP && key_idx == 0 && key_len == 32) { 52639beb93cSSam Leffler /* Clear the MIC error counter when setting a new PTK. */ 52739beb93cSSam Leffler wpa_s->mic_errors_seen = 0; 52839beb93cSSam Leffler } 5295b9c547cSRui Paulo #ifdef CONFIG_TESTING_GET_GTK 5305b9c547cSRui Paulo if (key_idx > 0 && addr && is_broadcast_ether_addr(addr) && 5315b9c547cSRui Paulo alg != WPA_ALG_NONE && key_len <= sizeof(wpa_s->last_gtk)) { 5325b9c547cSRui Paulo os_memcpy(wpa_s->last_gtk, key, key_len); 5335b9c547cSRui Paulo wpa_s->last_gtk_len = key_len; 5345b9c547cSRui Paulo } 5355b9c547cSRui Paulo #endif /* CONFIG_TESTING_GET_GTK */ 53685732ac8SCy Schubert #ifdef CONFIG_TESTING_OPTIONS 537c1d255d3SCy Schubert if (addr && !is_broadcast_ether_addr(addr) && 538c1d255d3SCy Schubert !(key_flag & KEY_FLAG_MODIFY)) { 53985732ac8SCy Schubert wpa_s->last_tk_alg = alg; 54085732ac8SCy Schubert os_memcpy(wpa_s->last_tk_addr, addr, ETH_ALEN); 54185732ac8SCy Schubert wpa_s->last_tk_key_idx = key_idx; 54285732ac8SCy Schubert if (key) 54385732ac8SCy Schubert os_memcpy(wpa_s->last_tk, key, key_len); 54485732ac8SCy Schubert wpa_s->last_tk_len = key_len; 54585732ac8SCy Schubert } 54685732ac8SCy Schubert #endif /* CONFIG_TESTING_OPTIONS */ 54739beb93cSSam Leffler return wpa_drv_set_key(wpa_s, alg, addr, key_idx, set_tx, seq, seq_len, 548c1d255d3SCy Schubert key, key_len, key_flag); 54939beb93cSSam Leffler } 55039beb93cSSam Leffler 55139beb93cSSam Leffler 55239beb93cSSam Leffler static int wpa_supplicant_mlme_setprotection(void *wpa_s, const u8 *addr, 55339beb93cSSam Leffler int protection_type, 55439beb93cSSam Leffler int key_type) 55539beb93cSSam Leffler { 55639beb93cSSam Leffler return wpa_drv_mlme_setprotection(wpa_s, addr, protection_type, 55739beb93cSSam Leffler key_type); 55839beb93cSSam Leffler } 55939beb93cSSam Leffler 56039beb93cSSam Leffler 56185732ac8SCy Schubert static struct wpa_ssid * wpas_get_network_ctx(struct wpa_supplicant *wpa_s, 56285732ac8SCy Schubert void *network_ctx) 56339beb93cSSam Leffler { 56485732ac8SCy Schubert struct wpa_ssid *ssid; 56585732ac8SCy Schubert 56685732ac8SCy Schubert for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) { 56785732ac8SCy Schubert if (network_ctx == ssid) 56885732ac8SCy Schubert return ssid; 56985732ac8SCy Schubert } 57085732ac8SCy Schubert 57185732ac8SCy Schubert return NULL; 57239beb93cSSam Leffler } 57339beb93cSSam Leffler 57439beb93cSSam Leffler 57585732ac8SCy Schubert static int wpa_supplicant_add_pmkid(void *_wpa_s, void *network_ctx, 57685732ac8SCy Schubert const u8 *bssid, const u8 *pmkid, 57785732ac8SCy Schubert const u8 *fils_cache_id, 578c1d255d3SCy Schubert const u8 *pmk, size_t pmk_len, 579c1d255d3SCy Schubert u32 pmk_lifetime, u8 pmk_reauth_threshold, 580c1d255d3SCy Schubert int akmp) 58139beb93cSSam Leffler { 58285732ac8SCy Schubert struct wpa_supplicant *wpa_s = _wpa_s; 58385732ac8SCy Schubert struct wpa_ssid *ssid; 58485732ac8SCy Schubert struct wpa_pmkid_params params; 58585732ac8SCy Schubert 58685732ac8SCy Schubert os_memset(¶ms, 0, sizeof(params)); 58785732ac8SCy Schubert ssid = wpas_get_network_ctx(wpa_s, network_ctx); 588c1d255d3SCy Schubert if (ssid) { 58985732ac8SCy Schubert wpa_msg(wpa_s, MSG_INFO, PMKSA_CACHE_ADDED MACSTR " %d", 59085732ac8SCy Schubert MAC2STR(bssid), ssid->id); 591c1d255d3SCy Schubert if ((akmp == WPA_KEY_MGMT_FT_IEEE8021X || 592c1d255d3SCy Schubert akmp == WPA_KEY_MGMT_FT_IEEE8021X_SHA384) && 593c1d255d3SCy Schubert !ssid->ft_eap_pmksa_caching) { 594c1d255d3SCy Schubert /* Since we will not be using PMKSA caching for FT-EAP 595c1d255d3SCy Schubert * within wpa_supplicant to avoid known interop issues 596c1d255d3SCy Schubert * with APs, do not add this PMKID to the driver either 597c1d255d3SCy Schubert * so that we won't be hitting those interop issues 598c1d255d3SCy Schubert * with driver-based RSNE generation. */ 599c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, 600c1d255d3SCy Schubert "FT: Do not add PMKID entry to the driver since FT-EAP PMKSA caching is not enabled in configuration"); 601c1d255d3SCy Schubert return 0; 602c1d255d3SCy Schubert } 603c1d255d3SCy Schubert } 60485732ac8SCy Schubert if (ssid && fils_cache_id) { 60585732ac8SCy Schubert params.ssid = ssid->ssid; 60685732ac8SCy Schubert params.ssid_len = ssid->ssid_len; 60785732ac8SCy Schubert params.fils_cache_id = fils_cache_id; 60885732ac8SCy Schubert } else { 60985732ac8SCy Schubert params.bssid = bssid; 61085732ac8SCy Schubert } 61185732ac8SCy Schubert 61285732ac8SCy Schubert params.pmkid = pmkid; 61385732ac8SCy Schubert params.pmk = pmk; 61485732ac8SCy Schubert params.pmk_len = pmk_len; 615c1d255d3SCy Schubert params.pmk_lifetime = pmk_lifetime; 616c1d255d3SCy Schubert params.pmk_reauth_threshold = pmk_reauth_threshold; 61785732ac8SCy Schubert 61885732ac8SCy Schubert return wpa_drv_add_pmkid(wpa_s, ¶ms); 61985732ac8SCy Schubert } 62085732ac8SCy Schubert 62185732ac8SCy Schubert 62285732ac8SCy Schubert static int wpa_supplicant_remove_pmkid(void *_wpa_s, void *network_ctx, 62385732ac8SCy Schubert const u8 *bssid, const u8 *pmkid, 62485732ac8SCy Schubert const u8 *fils_cache_id) 62585732ac8SCy Schubert { 62685732ac8SCy Schubert struct wpa_supplicant *wpa_s = _wpa_s; 62785732ac8SCy Schubert struct wpa_ssid *ssid; 62885732ac8SCy Schubert struct wpa_pmkid_params params; 62985732ac8SCy Schubert 63085732ac8SCy Schubert os_memset(¶ms, 0, sizeof(params)); 63185732ac8SCy Schubert ssid = wpas_get_network_ctx(wpa_s, network_ctx); 63285732ac8SCy Schubert if (ssid) 63385732ac8SCy Schubert wpa_msg(wpa_s, MSG_INFO, PMKSA_CACHE_REMOVED MACSTR " %d", 63485732ac8SCy Schubert MAC2STR(bssid), ssid->id); 63585732ac8SCy Schubert if (ssid && fils_cache_id) { 63685732ac8SCy Schubert params.ssid = ssid->ssid; 63785732ac8SCy Schubert params.ssid_len = ssid->ssid_len; 63885732ac8SCy Schubert params.fils_cache_id = fils_cache_id; 63985732ac8SCy Schubert } else { 64085732ac8SCy Schubert params.bssid = bssid; 64185732ac8SCy Schubert } 64285732ac8SCy Schubert 64385732ac8SCy Schubert params.pmkid = pmkid; 64485732ac8SCy Schubert 64585732ac8SCy Schubert return wpa_drv_remove_pmkid(wpa_s, ¶ms); 64639beb93cSSam Leffler } 64739beb93cSSam Leffler 64839beb93cSSam Leffler 64939beb93cSSam Leffler #ifdef CONFIG_IEEE80211R 65039beb93cSSam Leffler static int wpa_supplicant_update_ft_ies(void *ctx, const u8 *md, 65139beb93cSSam Leffler const u8 *ies, size_t ies_len) 65239beb93cSSam Leffler { 65339beb93cSSam Leffler struct wpa_supplicant *wpa_s = ctx; 654e28a4053SRui Paulo if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) 655e28a4053SRui Paulo return sme_update_ft_ies(wpa_s, md, ies, ies_len); 65639beb93cSSam Leffler return wpa_drv_update_ft_ies(wpa_s, md, ies, ies_len); 65739beb93cSSam Leffler } 65839beb93cSSam Leffler 65939beb93cSSam Leffler 66039beb93cSSam Leffler static int wpa_supplicant_send_ft_action(void *ctx, u8 action, 66139beb93cSSam Leffler const u8 *target_ap, 66239beb93cSSam Leffler const u8 *ies, size_t ies_len) 66339beb93cSSam Leffler { 66439beb93cSSam Leffler struct wpa_supplicant *wpa_s = ctx; 6655b9c547cSRui Paulo int ret; 6665b9c547cSRui Paulo u8 *data, *pos; 6675b9c547cSRui Paulo size_t data_len; 6685b9c547cSRui Paulo 6695b9c547cSRui Paulo if (action != 1) { 6705b9c547cSRui Paulo wpa_printf(MSG_ERROR, "Unsupported send_ft_action action %d", 6715b9c547cSRui Paulo action); 6725b9c547cSRui Paulo return -1; 6735b9c547cSRui Paulo } 6745b9c547cSRui Paulo 6755b9c547cSRui Paulo /* 6765b9c547cSRui Paulo * Action frame payload: 6775b9c547cSRui Paulo * Category[1] = 6 (Fast BSS Transition) 6785b9c547cSRui Paulo * Action[1] = 1 (Fast BSS Transition Request) 6795b9c547cSRui Paulo * STA Address 6805b9c547cSRui Paulo * Target AP Address 6815b9c547cSRui Paulo * FT IEs 6825b9c547cSRui Paulo */ 6835b9c547cSRui Paulo 6845b9c547cSRui Paulo data_len = 2 + 2 * ETH_ALEN + ies_len; 6855b9c547cSRui Paulo data = os_malloc(data_len); 6865b9c547cSRui Paulo if (data == NULL) 6875b9c547cSRui Paulo return -1; 6885b9c547cSRui Paulo pos = data; 6895b9c547cSRui Paulo *pos++ = 0x06; /* FT Action category */ 6905b9c547cSRui Paulo *pos++ = action; 6915b9c547cSRui Paulo os_memcpy(pos, wpa_s->own_addr, ETH_ALEN); 6925b9c547cSRui Paulo pos += ETH_ALEN; 6935b9c547cSRui Paulo os_memcpy(pos, target_ap, ETH_ALEN); 6945b9c547cSRui Paulo pos += ETH_ALEN; 6955b9c547cSRui Paulo os_memcpy(pos, ies, ies_len); 6965b9c547cSRui Paulo 6975b9c547cSRui Paulo ret = wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, 6985b9c547cSRui Paulo wpa_s->bssid, wpa_s->own_addr, wpa_s->bssid, 6995b9c547cSRui Paulo data, data_len, 0); 7005b9c547cSRui Paulo os_free(data); 7015b9c547cSRui Paulo 7025b9c547cSRui Paulo return ret; 70339beb93cSSam Leffler } 704e28a4053SRui Paulo 705e28a4053SRui Paulo 706e28a4053SRui Paulo static int wpa_supplicant_mark_authenticated(void *ctx, const u8 *target_ap) 707e28a4053SRui Paulo { 708e28a4053SRui Paulo struct wpa_supplicant *wpa_s = ctx; 709e28a4053SRui Paulo struct wpa_driver_auth_params params; 710e28a4053SRui Paulo struct wpa_bss *bss; 711e28a4053SRui Paulo 712e28a4053SRui Paulo bss = wpa_bss_get_bssid(wpa_s, target_ap); 713e28a4053SRui Paulo if (bss == NULL) 714e28a4053SRui Paulo return -1; 715e28a4053SRui Paulo 716e28a4053SRui Paulo os_memset(¶ms, 0, sizeof(params)); 717e28a4053SRui Paulo params.bssid = target_ap; 718e28a4053SRui Paulo params.freq = bss->freq; 719e28a4053SRui Paulo params.ssid = bss->ssid; 720e28a4053SRui Paulo params.ssid_len = bss->ssid_len; 721e28a4053SRui Paulo params.auth_alg = WPA_AUTH_ALG_FT; 722e28a4053SRui Paulo params.local_state_change = 1; 723e28a4053SRui Paulo return wpa_drv_authenticate(wpa_s, ¶ms); 724e28a4053SRui Paulo } 72539beb93cSSam Leffler #endif /* CONFIG_IEEE80211R */ 72639beb93cSSam Leffler 72739beb93cSSam Leffler 728f05cddf9SRui Paulo #ifdef CONFIG_TDLS 729f05cddf9SRui Paulo 730f05cddf9SRui Paulo static int wpa_supplicant_tdls_get_capa(void *ctx, int *tdls_supported, 7315b9c547cSRui Paulo int *tdls_ext_setup, 7325b9c547cSRui Paulo int *tdls_chan_switch) 733f05cddf9SRui Paulo { 734f05cddf9SRui Paulo struct wpa_supplicant *wpa_s = ctx; 735f05cddf9SRui Paulo 736f05cddf9SRui Paulo *tdls_supported = 0; 737f05cddf9SRui Paulo *tdls_ext_setup = 0; 7385b9c547cSRui Paulo *tdls_chan_switch = 0; 739f05cddf9SRui Paulo 740f05cddf9SRui Paulo if (!wpa_s->drv_capa_known) 741f05cddf9SRui Paulo return -1; 742f05cddf9SRui Paulo 743f05cddf9SRui Paulo if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_TDLS_SUPPORT) 744f05cddf9SRui Paulo *tdls_supported = 1; 745f05cddf9SRui Paulo 746f05cddf9SRui Paulo if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_TDLS_EXTERNAL_SETUP) 747f05cddf9SRui Paulo *tdls_ext_setup = 1; 748f05cddf9SRui Paulo 7495b9c547cSRui Paulo if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_TDLS_CHANNEL_SWITCH) 7505b9c547cSRui Paulo *tdls_chan_switch = 1; 7515b9c547cSRui Paulo 752f05cddf9SRui Paulo return 0; 753f05cddf9SRui Paulo } 754f05cddf9SRui Paulo 755f05cddf9SRui Paulo 756f05cddf9SRui Paulo static int wpa_supplicant_send_tdls_mgmt(void *ctx, const u8 *dst, 757f05cddf9SRui Paulo u8 action_code, u8 dialog_token, 7585b9c547cSRui Paulo u16 status_code, u32 peer_capab, 7595b9c547cSRui Paulo int initiator, const u8 *buf, 760f05cddf9SRui Paulo size_t len) 761f05cddf9SRui Paulo { 762f05cddf9SRui Paulo struct wpa_supplicant *wpa_s = ctx; 763f05cddf9SRui Paulo return wpa_drv_send_tdls_mgmt(wpa_s, dst, action_code, dialog_token, 7645b9c547cSRui Paulo status_code, peer_capab, initiator, buf, 7655b9c547cSRui Paulo len); 766f05cddf9SRui Paulo } 767f05cddf9SRui Paulo 768f05cddf9SRui Paulo 769f05cddf9SRui Paulo static int wpa_supplicant_tdls_oper(void *ctx, int oper, const u8 *peer) 770f05cddf9SRui Paulo { 771f05cddf9SRui Paulo struct wpa_supplicant *wpa_s = ctx; 772f05cddf9SRui Paulo return wpa_drv_tdls_oper(wpa_s, oper, peer); 773f05cddf9SRui Paulo } 774f05cddf9SRui Paulo 775f05cddf9SRui Paulo 776f05cddf9SRui Paulo static int wpa_supplicant_tdls_peer_addset( 7775b9c547cSRui Paulo void *ctx, const u8 *peer, int add, u16 aid, u16 capability, 7785b9c547cSRui Paulo const u8 *supp_rates, size_t supp_rates_len, 7795b9c547cSRui Paulo const struct ieee80211_ht_capabilities *ht_capab, 7805b9c547cSRui Paulo const struct ieee80211_vht_capabilities *vht_capab, 781c1d255d3SCy Schubert const struct ieee80211_he_capabilities *he_capab, 782c1d255d3SCy Schubert size_t he_capab_len, 783*4b72b91aSCy Schubert const struct ieee80211_he_6ghz_band_cap *he_6ghz_he_capab, 7845b9c547cSRui Paulo u8 qosinfo, int wmm, const u8 *ext_capab, size_t ext_capab_len, 7855b9c547cSRui Paulo const u8 *supp_channels, size_t supp_channels_len, 7865b9c547cSRui Paulo const u8 *supp_oper_classes, size_t supp_oper_classes_len) 787f05cddf9SRui Paulo { 788f05cddf9SRui Paulo struct wpa_supplicant *wpa_s = ctx; 789f05cddf9SRui Paulo struct hostapd_sta_add_params params; 790f05cddf9SRui Paulo 7915b9c547cSRui Paulo os_memset(¶ms, 0, sizeof(params)); 7925b9c547cSRui Paulo 793f05cddf9SRui Paulo params.addr = peer; 7945b9c547cSRui Paulo params.aid = aid; 795f05cddf9SRui Paulo params.capability = capability; 796f05cddf9SRui Paulo params.flags = WPA_STA_TDLS_PEER | WPA_STA_AUTHORIZED; 7975b9c547cSRui Paulo 7985b9c547cSRui Paulo /* 7995b9c547cSRui Paulo * Don't rely only on qosinfo for WMM capability. It may be 0 even when 8005b9c547cSRui Paulo * present. Allow the WMM IE to also indicate QoS support. 8015b9c547cSRui Paulo */ 8025b9c547cSRui Paulo if (wmm || qosinfo) 8035b9c547cSRui Paulo params.flags |= WPA_STA_WMM; 8045b9c547cSRui Paulo 8055b9c547cSRui Paulo params.ht_capabilities = ht_capab; 8065b9c547cSRui Paulo params.vht_capabilities = vht_capab; 807c1d255d3SCy Schubert params.he_capab = he_capab; 808c1d255d3SCy Schubert params.he_capab_len = he_capab_len; 809*4b72b91aSCy Schubert params.he_6ghz_capab = he_6ghz_he_capab; 8105b9c547cSRui Paulo params.qosinfo = qosinfo; 811f05cddf9SRui Paulo params.listen_interval = 0; 812f05cddf9SRui Paulo params.supp_rates = supp_rates; 813f05cddf9SRui Paulo params.supp_rates_len = supp_rates_len; 814f05cddf9SRui Paulo params.set = !add; 8155b9c547cSRui Paulo params.ext_capab = ext_capab; 8165b9c547cSRui Paulo params.ext_capab_len = ext_capab_len; 8175b9c547cSRui Paulo params.supp_channels = supp_channels; 8185b9c547cSRui Paulo params.supp_channels_len = supp_channels_len; 8195b9c547cSRui Paulo params.supp_oper_classes = supp_oper_classes; 8205b9c547cSRui Paulo params.supp_oper_classes_len = supp_oper_classes_len; 821f05cddf9SRui Paulo 822f05cddf9SRui Paulo return wpa_drv_sta_add(wpa_s, ¶ms); 823f05cddf9SRui Paulo } 824f05cddf9SRui Paulo 8255b9c547cSRui Paulo 8265b9c547cSRui Paulo static int wpa_supplicant_tdls_enable_channel_switch( 8275b9c547cSRui Paulo void *ctx, const u8 *addr, u8 oper_class, 8285b9c547cSRui Paulo const struct hostapd_freq_params *params) 8295b9c547cSRui Paulo { 8305b9c547cSRui Paulo struct wpa_supplicant *wpa_s = ctx; 8315b9c547cSRui Paulo 8325b9c547cSRui Paulo return wpa_drv_tdls_enable_channel_switch(wpa_s, addr, oper_class, 8335b9c547cSRui Paulo params); 8345b9c547cSRui Paulo } 8355b9c547cSRui Paulo 8365b9c547cSRui Paulo 8375b9c547cSRui Paulo static int wpa_supplicant_tdls_disable_channel_switch(void *ctx, const u8 *addr) 8385b9c547cSRui Paulo { 8395b9c547cSRui Paulo struct wpa_supplicant *wpa_s = ctx; 8405b9c547cSRui Paulo 8415b9c547cSRui Paulo return wpa_drv_tdls_disable_channel_switch(wpa_s, addr); 8425b9c547cSRui Paulo } 8435b9c547cSRui Paulo 844f05cddf9SRui Paulo #endif /* CONFIG_TDLS */ 845f05cddf9SRui Paulo 8465b9c547cSRui Paulo #endif /* CONFIG_NO_WPA */ 8475b9c547cSRui Paulo 848f05cddf9SRui Paulo 849f05cddf9SRui Paulo enum wpa_ctrl_req_type wpa_supplicant_ctrl_req_from_string(const char *field) 850f05cddf9SRui Paulo { 851f05cddf9SRui Paulo if (os_strcmp(field, "IDENTITY") == 0) 852f05cddf9SRui Paulo return WPA_CTRL_REQ_EAP_IDENTITY; 853f05cddf9SRui Paulo else if (os_strcmp(field, "PASSWORD") == 0) 854f05cddf9SRui Paulo return WPA_CTRL_REQ_EAP_PASSWORD; 855f05cddf9SRui Paulo else if (os_strcmp(field, "NEW_PASSWORD") == 0) 856f05cddf9SRui Paulo return WPA_CTRL_REQ_EAP_NEW_PASSWORD; 857f05cddf9SRui Paulo else if (os_strcmp(field, "PIN") == 0) 858f05cddf9SRui Paulo return WPA_CTRL_REQ_EAP_PIN; 859f05cddf9SRui Paulo else if (os_strcmp(field, "OTP") == 0) 860f05cddf9SRui Paulo return WPA_CTRL_REQ_EAP_OTP; 861f05cddf9SRui Paulo else if (os_strcmp(field, "PASSPHRASE") == 0) 862f05cddf9SRui Paulo return WPA_CTRL_REQ_EAP_PASSPHRASE; 8635b9c547cSRui Paulo else if (os_strcmp(field, "SIM") == 0) 8645b9c547cSRui Paulo return WPA_CTRL_REQ_SIM; 865325151a3SRui Paulo else if (os_strcmp(field, "PSK_PASSPHRASE") == 0) 866325151a3SRui Paulo return WPA_CTRL_REQ_PSK_PASSPHRASE; 867780fb4a2SCy Schubert else if (os_strcmp(field, "EXT_CERT_CHECK") == 0) 868780fb4a2SCy Schubert return WPA_CTRL_REQ_EXT_CERT_CHECK; 869f05cddf9SRui Paulo return WPA_CTRL_REQ_UNKNOWN; 870f05cddf9SRui Paulo } 871f05cddf9SRui Paulo 872f05cddf9SRui Paulo 873f05cddf9SRui Paulo const char * wpa_supplicant_ctrl_req_to_string(enum wpa_ctrl_req_type field, 874f05cddf9SRui Paulo const char *default_txt, 875f05cddf9SRui Paulo const char **txt) 876f05cddf9SRui Paulo { 877f05cddf9SRui Paulo const char *ret = NULL; 878f05cddf9SRui Paulo 879f05cddf9SRui Paulo *txt = default_txt; 880f05cddf9SRui Paulo 881f05cddf9SRui Paulo switch (field) { 882f05cddf9SRui Paulo case WPA_CTRL_REQ_EAP_IDENTITY: 883f05cddf9SRui Paulo *txt = "Identity"; 884f05cddf9SRui Paulo ret = "IDENTITY"; 885f05cddf9SRui Paulo break; 886f05cddf9SRui Paulo case WPA_CTRL_REQ_EAP_PASSWORD: 887f05cddf9SRui Paulo *txt = "Password"; 888f05cddf9SRui Paulo ret = "PASSWORD"; 889f05cddf9SRui Paulo break; 890f05cddf9SRui Paulo case WPA_CTRL_REQ_EAP_NEW_PASSWORD: 891f05cddf9SRui Paulo *txt = "New Password"; 892f05cddf9SRui Paulo ret = "NEW_PASSWORD"; 893f05cddf9SRui Paulo break; 894f05cddf9SRui Paulo case WPA_CTRL_REQ_EAP_PIN: 895f05cddf9SRui Paulo *txt = "PIN"; 896f05cddf9SRui Paulo ret = "PIN"; 897f05cddf9SRui Paulo break; 898f05cddf9SRui Paulo case WPA_CTRL_REQ_EAP_OTP: 899f05cddf9SRui Paulo ret = "OTP"; 900f05cddf9SRui Paulo break; 901f05cddf9SRui Paulo case WPA_CTRL_REQ_EAP_PASSPHRASE: 902f05cddf9SRui Paulo *txt = "Private key passphrase"; 903f05cddf9SRui Paulo ret = "PASSPHRASE"; 904f05cddf9SRui Paulo break; 9055b9c547cSRui Paulo case WPA_CTRL_REQ_SIM: 9065b9c547cSRui Paulo ret = "SIM"; 9075b9c547cSRui Paulo break; 908325151a3SRui Paulo case WPA_CTRL_REQ_PSK_PASSPHRASE: 909325151a3SRui Paulo *txt = "PSK or passphrase"; 910325151a3SRui Paulo ret = "PSK_PASSPHRASE"; 911325151a3SRui Paulo break; 912780fb4a2SCy Schubert case WPA_CTRL_REQ_EXT_CERT_CHECK: 913780fb4a2SCy Schubert *txt = "External server certificate validation"; 914780fb4a2SCy Schubert ret = "EXT_CERT_CHECK"; 915780fb4a2SCy Schubert break; 916f05cddf9SRui Paulo default: 917f05cddf9SRui Paulo break; 918f05cddf9SRui Paulo } 919f05cddf9SRui Paulo 920f05cddf9SRui Paulo /* txt needs to be something */ 921f05cddf9SRui Paulo if (*txt == NULL) { 922f05cddf9SRui Paulo wpa_printf(MSG_WARNING, "No message for request %d", field); 923f05cddf9SRui Paulo ret = NULL; 924f05cddf9SRui Paulo } 925f05cddf9SRui Paulo 926f05cddf9SRui Paulo return ret; 927f05cddf9SRui Paulo } 928f05cddf9SRui Paulo 929325151a3SRui Paulo 930325151a3SRui Paulo void wpas_send_ctrl_req(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid, 931325151a3SRui Paulo const char *field_name, const char *txt) 932325151a3SRui Paulo { 933325151a3SRui Paulo char *buf; 934325151a3SRui Paulo size_t buflen; 935325151a3SRui Paulo int len; 936325151a3SRui Paulo 937325151a3SRui Paulo buflen = 100 + os_strlen(txt) + ssid->ssid_len; 938325151a3SRui Paulo buf = os_malloc(buflen); 939325151a3SRui Paulo if (buf == NULL) 940325151a3SRui Paulo return; 941325151a3SRui Paulo len = os_snprintf(buf, buflen, "%s-%d:%s needed for SSID ", 942325151a3SRui Paulo field_name, ssid->id, txt); 943325151a3SRui Paulo if (os_snprintf_error(buflen, len)) { 944325151a3SRui Paulo os_free(buf); 945325151a3SRui Paulo return; 946325151a3SRui Paulo } 947325151a3SRui Paulo if (ssid->ssid && buflen > len + ssid->ssid_len) { 948325151a3SRui Paulo os_memcpy(buf + len, ssid->ssid, ssid->ssid_len); 949325151a3SRui Paulo len += ssid->ssid_len; 950325151a3SRui Paulo buf[len] = '\0'; 951325151a3SRui Paulo } 952325151a3SRui Paulo buf[buflen - 1] = '\0'; 953325151a3SRui Paulo wpa_msg(wpa_s, MSG_INFO, WPA_CTRL_REQ "%s", buf); 954325151a3SRui Paulo os_free(buf); 955325151a3SRui Paulo } 956325151a3SRui Paulo 957325151a3SRui Paulo 958e28a4053SRui Paulo #ifdef IEEE8021X_EAPOL 95939beb93cSSam Leffler #if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG) 960f05cddf9SRui Paulo static void wpa_supplicant_eap_param_needed(void *ctx, 961f05cddf9SRui Paulo enum wpa_ctrl_req_type field, 962f05cddf9SRui Paulo const char *default_txt) 96339beb93cSSam Leffler { 96439beb93cSSam Leffler struct wpa_supplicant *wpa_s = ctx; 96539beb93cSSam Leffler struct wpa_ssid *ssid = wpa_s->current_ssid; 966f05cddf9SRui Paulo const char *field_name, *txt = NULL; 96739beb93cSSam Leffler 96839beb93cSSam Leffler if (ssid == NULL) 96939beb93cSSam Leffler return; 97039beb93cSSam Leffler 971780fb4a2SCy Schubert if (field == WPA_CTRL_REQ_EXT_CERT_CHECK) 972780fb4a2SCy Schubert ssid->eap.pending_ext_cert_check = PENDING_CHECK; 973f05cddf9SRui Paulo wpas_notify_network_request(wpa_s, ssid, field, default_txt); 974f05cddf9SRui Paulo 975f05cddf9SRui Paulo field_name = wpa_supplicant_ctrl_req_to_string(field, default_txt, 976f05cddf9SRui Paulo &txt); 977f05cddf9SRui Paulo if (field_name == NULL) { 978f05cddf9SRui Paulo wpa_printf(MSG_WARNING, "Unhandled EAP param %d needed", 979f05cddf9SRui Paulo field); 980f05cddf9SRui Paulo return; 981f05cddf9SRui Paulo } 982f05cddf9SRui Paulo 9835b9c547cSRui Paulo wpas_notify_eap_status(wpa_s, "eap parameter needed", field_name); 9845b9c547cSRui Paulo 985325151a3SRui Paulo wpas_send_ctrl_req(wpa_s, ssid, field_name, txt); 98639beb93cSSam Leffler } 98739beb93cSSam Leffler #else /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */ 98839beb93cSSam Leffler #define wpa_supplicant_eap_param_needed NULL 98939beb93cSSam Leffler #endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */ 99039beb93cSSam Leffler 99139beb93cSSam Leffler 9925b9c547cSRui Paulo #ifdef CONFIG_EAP_PROXY 99385732ac8SCy Schubert 9945b9c547cSRui Paulo static void wpa_supplicant_eap_proxy_cb(void *ctx) 9955b9c547cSRui Paulo { 9965b9c547cSRui Paulo struct wpa_supplicant *wpa_s = ctx; 9975b9c547cSRui Paulo size_t len; 9985b9c547cSRui Paulo 99985732ac8SCy Schubert wpa_s->mnc_len = eapol_sm_get_eap_proxy_imsi(wpa_s->eapol, -1, 10005b9c547cSRui Paulo wpa_s->imsi, &len); 10015b9c547cSRui Paulo if (wpa_s->mnc_len > 0) { 10025b9c547cSRui Paulo wpa_s->imsi[len] = '\0'; 10035b9c547cSRui Paulo wpa_printf(MSG_DEBUG, "eap_proxy: IMSI %s (MNC length %d)", 10045b9c547cSRui Paulo wpa_s->imsi, wpa_s->mnc_len); 10055b9c547cSRui Paulo } else { 10065b9c547cSRui Paulo wpa_printf(MSG_DEBUG, "eap_proxy: IMSI not available"); 10075b9c547cSRui Paulo } 10085b9c547cSRui Paulo } 100985732ac8SCy Schubert 101085732ac8SCy Schubert 101185732ac8SCy Schubert static void wpa_sm_sim_state_error_handler(struct wpa_supplicant *wpa_s) 101285732ac8SCy Schubert { 101385732ac8SCy Schubert int i; 101485732ac8SCy Schubert struct wpa_ssid *ssid; 101585732ac8SCy Schubert const struct eap_method_type *eap_methods; 101685732ac8SCy Schubert 101785732ac8SCy Schubert if (!wpa_s->conf) 101885732ac8SCy Schubert return; 101985732ac8SCy Schubert 102085732ac8SCy Schubert for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) { 102185732ac8SCy Schubert eap_methods = ssid->eap.eap_methods; 102285732ac8SCy Schubert if (!eap_methods) 102385732ac8SCy Schubert continue; 102485732ac8SCy Schubert 102585732ac8SCy Schubert for (i = 0; eap_methods[i].method != EAP_TYPE_NONE; i++) { 102685732ac8SCy Schubert if (eap_methods[i].vendor == EAP_VENDOR_IETF && 102785732ac8SCy Schubert (eap_methods[i].method == EAP_TYPE_SIM || 102885732ac8SCy Schubert eap_methods[i].method == EAP_TYPE_AKA || 102985732ac8SCy Schubert eap_methods[i].method == EAP_TYPE_AKA_PRIME)) { 103085732ac8SCy Schubert wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid); 103185732ac8SCy Schubert break; 103285732ac8SCy Schubert } 103385732ac8SCy Schubert } 103485732ac8SCy Schubert } 103585732ac8SCy Schubert } 103685732ac8SCy Schubert 103785732ac8SCy Schubert 103885732ac8SCy Schubert static void 103985732ac8SCy Schubert wpa_supplicant_eap_proxy_notify_sim_status(void *ctx, 104085732ac8SCy Schubert enum eap_proxy_sim_state sim_state) 104185732ac8SCy Schubert { 104285732ac8SCy Schubert struct wpa_supplicant *wpa_s = ctx; 104385732ac8SCy Schubert 104485732ac8SCy Schubert wpa_printf(MSG_DEBUG, "eap_proxy: SIM card status %u", sim_state); 104585732ac8SCy Schubert switch (sim_state) { 104685732ac8SCy Schubert case SIM_STATE_ERROR: 104785732ac8SCy Schubert wpa_sm_sim_state_error_handler(wpa_s); 104885732ac8SCy Schubert break; 104985732ac8SCy Schubert default: 105085732ac8SCy Schubert wpa_printf(MSG_DEBUG, "eap_proxy: SIM card status unknown"); 105185732ac8SCy Schubert break; 105285732ac8SCy Schubert } 105385732ac8SCy Schubert } 105485732ac8SCy Schubert 10555b9c547cSRui Paulo #endif /* CONFIG_EAP_PROXY */ 10565b9c547cSRui Paulo 10575b9c547cSRui Paulo 1058e28a4053SRui Paulo static void wpa_supplicant_port_cb(void *ctx, int authorized) 1059e28a4053SRui Paulo { 1060e28a4053SRui Paulo struct wpa_supplicant *wpa_s = ctx; 1061e28a4053SRui Paulo #ifdef CONFIG_AP 1062e28a4053SRui Paulo if (wpa_s->ap_iface) { 1063e28a4053SRui Paulo wpa_printf(MSG_DEBUG, "AP mode active - skip EAPOL Supplicant " 1064e28a4053SRui Paulo "port status: %s", 1065e28a4053SRui Paulo authorized ? "Authorized" : "Unauthorized"); 1066e28a4053SRui Paulo return; 1067e28a4053SRui Paulo } 1068e28a4053SRui Paulo #endif /* CONFIG_AP */ 1069e28a4053SRui Paulo wpa_printf(MSG_DEBUG, "EAPOL: Supplicant port status: %s", 1070e28a4053SRui Paulo authorized ? "Authorized" : "Unauthorized"); 1071e28a4053SRui Paulo wpa_drv_set_supp_port(wpa_s, authorized); 1072e28a4053SRui Paulo } 1073f05cddf9SRui Paulo 1074f05cddf9SRui Paulo 1075206b73d0SCy Schubert static void wpa_supplicant_cert_cb(void *ctx, struct tls_cert_data *cert, 1076206b73d0SCy Schubert const char *cert_hash) 1077f05cddf9SRui Paulo { 1078f05cddf9SRui Paulo struct wpa_supplicant *wpa_s = ctx; 1079f05cddf9SRui Paulo 1080206b73d0SCy Schubert wpas_notify_certification(wpa_s, cert, cert_hash); 1081f05cddf9SRui Paulo } 1082f05cddf9SRui Paulo 1083f05cddf9SRui Paulo 1084f05cddf9SRui Paulo static void wpa_supplicant_status_cb(void *ctx, const char *status, 1085f05cddf9SRui Paulo const char *parameter) 1086f05cddf9SRui Paulo { 1087f05cddf9SRui Paulo struct wpa_supplicant *wpa_s = ctx; 1088f05cddf9SRui Paulo 1089f05cddf9SRui Paulo wpas_notify_eap_status(wpa_s, status, parameter); 1090f05cddf9SRui Paulo } 1091f05cddf9SRui Paulo 1092f05cddf9SRui Paulo 109385732ac8SCy Schubert static void wpa_supplicant_eap_error_cb(void *ctx, int error_code) 109485732ac8SCy Schubert { 109585732ac8SCy Schubert struct wpa_supplicant *wpa_s = ctx; 109685732ac8SCy Schubert 109785732ac8SCy Schubert wpas_notify_eap_error(wpa_s, error_code); 109885732ac8SCy Schubert } 109985732ac8SCy Schubert 110085732ac8SCy Schubert 1101c1d255d3SCy Schubert static int wpa_supplicant_eap_auth_start_cb(void *ctx) 1102c1d255d3SCy Schubert { 1103c1d255d3SCy Schubert struct wpa_supplicant *wpa_s = ctx; 1104c1d255d3SCy Schubert 1105c1d255d3SCy Schubert if (!wpa_s->new_connection && wpa_s->deny_ptk0_rekey && 1106c1d255d3SCy Schubert !wpa_sm_ext_key_id_active(wpa_s->wpa)) { 1107c1d255d3SCy Schubert wpa_msg(wpa_s, MSG_INFO, 1108c1d255d3SCy Schubert "WPA: PTK0 rekey not allowed, reconnecting"); 1109c1d255d3SCy Schubert wpa_supplicant_reconnect(wpa_s); 1110c1d255d3SCy Schubert return -1; 1111c1d255d3SCy Schubert } 1112c1d255d3SCy Schubert return 0; 1113c1d255d3SCy Schubert } 1114c1d255d3SCy Schubert 1115c1d255d3SCy Schubert 1116f05cddf9SRui Paulo static void wpa_supplicant_set_anon_id(void *ctx, const u8 *id, size_t len) 1117f05cddf9SRui Paulo { 1118f05cddf9SRui Paulo struct wpa_supplicant *wpa_s = ctx; 1119f05cddf9SRui Paulo char *str; 1120f05cddf9SRui Paulo int res; 1121f05cddf9SRui Paulo 1122f05cddf9SRui Paulo wpa_hexdump_ascii(MSG_DEBUG, "EAP method updated anonymous_identity", 1123f05cddf9SRui Paulo id, len); 1124f05cddf9SRui Paulo 1125f05cddf9SRui Paulo if (wpa_s->current_ssid == NULL) 1126f05cddf9SRui Paulo return; 1127f05cddf9SRui Paulo 1128f05cddf9SRui Paulo if (id == NULL) { 1129f05cddf9SRui Paulo if (wpa_config_set(wpa_s->current_ssid, "anonymous_identity", 1130f05cddf9SRui Paulo "NULL", 0) < 0) 1131f05cddf9SRui Paulo return; 1132f05cddf9SRui Paulo } else { 1133f05cddf9SRui Paulo str = os_malloc(len * 2 + 1); 1134f05cddf9SRui Paulo if (str == NULL) 1135f05cddf9SRui Paulo return; 1136f05cddf9SRui Paulo wpa_snprintf_hex(str, len * 2 + 1, id, len); 1137f05cddf9SRui Paulo res = wpa_config_set(wpa_s->current_ssid, "anonymous_identity", 1138f05cddf9SRui Paulo str, 0); 1139f05cddf9SRui Paulo os_free(str); 1140f05cddf9SRui Paulo if (res < 0) 1141f05cddf9SRui Paulo return; 1142f05cddf9SRui Paulo } 1143f05cddf9SRui Paulo 1144f05cddf9SRui Paulo if (wpa_s->conf->update_config) { 1145f05cddf9SRui Paulo res = wpa_config_write(wpa_s->confname, wpa_s->conf); 1146f05cddf9SRui Paulo if (res) { 1147f05cddf9SRui Paulo wpa_printf(MSG_DEBUG, "Failed to update config after " 1148f05cddf9SRui Paulo "anonymous_id update"); 1149f05cddf9SRui Paulo } 1150f05cddf9SRui Paulo } 1151f05cddf9SRui Paulo } 1152e28a4053SRui Paulo #endif /* IEEE8021X_EAPOL */ 1153e28a4053SRui Paulo 1154e28a4053SRui Paulo 115539beb93cSSam Leffler int wpa_supplicant_init_eapol(struct wpa_supplicant *wpa_s) 115639beb93cSSam Leffler { 115739beb93cSSam Leffler #ifdef IEEE8021X_EAPOL 115839beb93cSSam Leffler struct eapol_ctx *ctx; 115939beb93cSSam Leffler ctx = os_zalloc(sizeof(*ctx)); 116039beb93cSSam Leffler if (ctx == NULL) { 116139beb93cSSam Leffler wpa_printf(MSG_ERROR, "Failed to allocate EAPOL context."); 116239beb93cSSam Leffler return -1; 116339beb93cSSam Leffler } 116439beb93cSSam Leffler 116539beb93cSSam Leffler ctx->ctx = wpa_s; 116639beb93cSSam Leffler ctx->msg_ctx = wpa_s; 116739beb93cSSam Leffler ctx->eapol_send_ctx = wpa_s; 116839beb93cSSam Leffler ctx->preauth = 0; 116939beb93cSSam Leffler ctx->eapol_done_cb = wpa_supplicant_notify_eapol_done; 117039beb93cSSam Leffler ctx->eapol_send = wpa_supplicant_eapol_send; 1171c1d255d3SCy Schubert #ifdef CONFIG_WEP 117239beb93cSSam Leffler ctx->set_wep_key = wpa_eapol_set_wep_key; 1173c1d255d3SCy Schubert #endif /* CONFIG_WEP */ 11745b9c547cSRui Paulo #ifndef CONFIG_NO_CONFIG_BLOBS 117539beb93cSSam Leffler ctx->set_config_blob = wpa_supplicant_set_config_blob; 117639beb93cSSam Leffler ctx->get_config_blob = wpa_supplicant_get_config_blob; 11775b9c547cSRui Paulo #endif /* CONFIG_NO_CONFIG_BLOBS */ 117839beb93cSSam Leffler ctx->aborted_cached = wpa_supplicant_aborted_cached; 117939beb93cSSam Leffler ctx->opensc_engine_path = wpa_s->conf->opensc_engine_path; 118039beb93cSSam Leffler ctx->pkcs11_engine_path = wpa_s->conf->pkcs11_engine_path; 118139beb93cSSam Leffler ctx->pkcs11_module_path = wpa_s->conf->pkcs11_module_path; 11825b9c547cSRui Paulo ctx->openssl_ciphers = wpa_s->conf->openssl_ciphers; 118339beb93cSSam Leffler ctx->wps = wpa_s->wps; 118439beb93cSSam Leffler ctx->eap_param_needed = wpa_supplicant_eap_param_needed; 11855b9c547cSRui Paulo #ifdef CONFIG_EAP_PROXY 11865b9c547cSRui Paulo ctx->eap_proxy_cb = wpa_supplicant_eap_proxy_cb; 118785732ac8SCy Schubert ctx->eap_proxy_notify_sim_status = 118885732ac8SCy Schubert wpa_supplicant_eap_proxy_notify_sim_status; 11895b9c547cSRui Paulo #endif /* CONFIG_EAP_PROXY */ 1190e28a4053SRui Paulo ctx->port_cb = wpa_supplicant_port_cb; 119139beb93cSSam Leffler ctx->cb = wpa_supplicant_eapol_cb; 1192f05cddf9SRui Paulo ctx->cert_cb = wpa_supplicant_cert_cb; 11935b9c547cSRui Paulo ctx->cert_in_cb = wpa_s->conf->cert_in_cb; 1194f05cddf9SRui Paulo ctx->status_cb = wpa_supplicant_status_cb; 119585732ac8SCy Schubert ctx->eap_error_cb = wpa_supplicant_eap_error_cb; 1196c1d255d3SCy Schubert ctx->confirm_auth_cb = wpa_supplicant_eap_auth_start_cb; 1197f05cddf9SRui Paulo ctx->set_anon_id = wpa_supplicant_set_anon_id; 119839beb93cSSam Leffler ctx->cb_ctx = wpa_s; 119939beb93cSSam Leffler wpa_s->eapol = eapol_sm_init(ctx); 120039beb93cSSam Leffler if (wpa_s->eapol == NULL) { 120139beb93cSSam Leffler os_free(ctx); 120239beb93cSSam Leffler wpa_printf(MSG_ERROR, "Failed to initialize EAPOL state " 120339beb93cSSam Leffler "machines."); 120439beb93cSSam Leffler return -1; 120539beb93cSSam Leffler } 120639beb93cSSam Leffler #endif /* IEEE8021X_EAPOL */ 120739beb93cSSam Leffler 120839beb93cSSam Leffler return 0; 120939beb93cSSam Leffler } 121039beb93cSSam Leffler 121139beb93cSSam Leffler 1212f05cddf9SRui Paulo #ifndef CONFIG_NO_WPA 121385732ac8SCy Schubert 12145b9c547cSRui Paulo static void wpa_supplicant_set_rekey_offload(void *ctx, 12155b9c547cSRui Paulo const u8 *kek, size_t kek_len, 12165b9c547cSRui Paulo const u8 *kck, size_t kck_len, 1217f05cddf9SRui Paulo const u8 *replay_ctr) 1218f05cddf9SRui Paulo { 1219f05cddf9SRui Paulo struct wpa_supplicant *wpa_s = ctx; 1220f05cddf9SRui Paulo 12215b9c547cSRui Paulo wpa_drv_set_rekey_info(wpa_s, kek, kek_len, kck, kck_len, replay_ctr); 1222f05cddf9SRui Paulo } 1223f05cddf9SRui Paulo 1224f05cddf9SRui Paulo 12255b9c547cSRui Paulo static int wpa_supplicant_key_mgmt_set_pmk(void *ctx, const u8 *pmk, 12265b9c547cSRui Paulo size_t pmk_len) 12275b9c547cSRui Paulo { 12285b9c547cSRui Paulo struct wpa_supplicant *wpa_s = ctx; 12295b9c547cSRui Paulo 1230325151a3SRui Paulo if (wpa_s->conf->key_mgmt_offload && 1231325151a3SRui Paulo (wpa_s->drv_flags & WPA_DRIVER_FLAGS_KEY_MGMT_OFFLOAD)) 1232c1d255d3SCy Schubert return wpa_drv_set_key(wpa_s, 0, NULL, 0, 0, 1233c1d255d3SCy Schubert NULL, 0, pmk, pmk_len, KEY_FLAG_PMK); 12345b9c547cSRui Paulo else 12355b9c547cSRui Paulo return 0; 12365b9c547cSRui Paulo } 123785732ac8SCy Schubert 123885732ac8SCy Schubert 123985732ac8SCy Schubert static void wpa_supplicant_fils_hlp_rx(void *ctx, const u8 *dst, const u8 *src, 124085732ac8SCy Schubert const u8 *pkt, size_t pkt_len) 124185732ac8SCy Schubert { 124285732ac8SCy Schubert struct wpa_supplicant *wpa_s = ctx; 124385732ac8SCy Schubert char *hex; 124485732ac8SCy Schubert size_t hexlen; 124585732ac8SCy Schubert 124685732ac8SCy Schubert hexlen = pkt_len * 2 + 1; 124785732ac8SCy Schubert hex = os_malloc(hexlen); 124885732ac8SCy Schubert if (!hex) 124985732ac8SCy Schubert return; 125085732ac8SCy Schubert wpa_snprintf_hex(hex, hexlen, pkt, pkt_len); 125185732ac8SCy Schubert wpa_msg(wpa_s, MSG_INFO, FILS_HLP_RX "dst=" MACSTR " src=" MACSTR 125285732ac8SCy Schubert " frame=%s", MAC2STR(dst), MAC2STR(src), hex); 125385732ac8SCy Schubert os_free(hex); 125485732ac8SCy Schubert } 125585732ac8SCy Schubert 12564bc52338SCy Schubert 12574bc52338SCy Schubert static int wpa_supplicant_channel_info(void *_wpa_s, 12584bc52338SCy Schubert struct wpa_channel_info *ci) 12594bc52338SCy Schubert { 12604bc52338SCy Schubert struct wpa_supplicant *wpa_s = _wpa_s; 12614bc52338SCy Schubert 12624bc52338SCy Schubert return wpa_drv_channel_info(wpa_s, ci); 12634bc52338SCy Schubert } 12644bc52338SCy Schubert 1265c1d255d3SCy Schubert 1266c1d255d3SCy Schubert static void disable_wpa_wpa2(struct wpa_ssid *ssid) 1267c1d255d3SCy Schubert { 1268c1d255d3SCy Schubert ssid->proto &= ~WPA_PROTO_WPA; 1269c1d255d3SCy Schubert ssid->proto |= WPA_PROTO_RSN; 1270c1d255d3SCy Schubert ssid->key_mgmt &= ~(WPA_KEY_MGMT_PSK | WPA_KEY_MGMT_FT_PSK | 1271c1d255d3SCy Schubert WPA_KEY_MGMT_PSK_SHA256); 1272c1d255d3SCy Schubert ssid->group_cipher &= ~WPA_CIPHER_TKIP; 1273c1d255d3SCy Schubert if (!(ssid->group_cipher & (WPA_CIPHER_CCMP | WPA_CIPHER_GCMP | 1274c1d255d3SCy Schubert WPA_CIPHER_GCMP_256 | WPA_CIPHER_CCMP_256))) 1275c1d255d3SCy Schubert ssid->group_cipher |= WPA_CIPHER_CCMP; 1276c1d255d3SCy Schubert ssid->ieee80211w = MGMT_FRAME_PROTECTION_REQUIRED; 1277c1d255d3SCy Schubert } 1278c1d255d3SCy Schubert 1279c1d255d3SCy Schubert 1280c1d255d3SCy Schubert static void wpa_supplicant_transition_disable(void *_wpa_s, u8 bitmap) 1281c1d255d3SCy Schubert { 1282c1d255d3SCy Schubert struct wpa_supplicant *wpa_s = _wpa_s; 1283c1d255d3SCy Schubert struct wpa_ssid *ssid; 1284c1d255d3SCy Schubert int changed = 0; 1285c1d255d3SCy Schubert 1286c1d255d3SCy Schubert wpa_msg(wpa_s, MSG_INFO, TRANSITION_DISABLE "%02x", bitmap); 1287c1d255d3SCy Schubert 1288c1d255d3SCy Schubert ssid = wpa_s->current_ssid; 1289c1d255d3SCy Schubert if (!ssid) 1290c1d255d3SCy Schubert return; 1291c1d255d3SCy Schubert 1292c1d255d3SCy Schubert #ifdef CONFIG_SAE 1293c1d255d3SCy Schubert if ((bitmap & TRANSITION_DISABLE_WPA3_PERSONAL) && 1294c1d255d3SCy Schubert wpa_key_mgmt_sae(wpa_s->key_mgmt) && 1295c1d255d3SCy Schubert (ssid->key_mgmt & (WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_FT_SAE)) && 1296c1d255d3SCy Schubert (ssid->ieee80211w != MGMT_FRAME_PROTECTION_REQUIRED || 1297c1d255d3SCy Schubert (ssid->group_cipher & WPA_CIPHER_TKIP))) { 1298c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, 1299c1d255d3SCy Schubert "WPA3-Personal transition mode disabled based on AP notification"); 1300c1d255d3SCy Schubert disable_wpa_wpa2(ssid); 1301c1d255d3SCy Schubert changed = 1; 1302c1d255d3SCy Schubert } 1303c1d255d3SCy Schubert 1304c1d255d3SCy Schubert if ((bitmap & TRANSITION_DISABLE_SAE_PK) && 1305c1d255d3SCy Schubert wpa_key_mgmt_sae(wpa_s->key_mgmt) && 1306c1d255d3SCy Schubert #ifdef CONFIG_SME 1307c1d255d3SCy Schubert wpa_s->sme.sae.state == SAE_ACCEPTED && 1308c1d255d3SCy Schubert wpa_s->sme.sae.pk && 1309c1d255d3SCy Schubert #endif /* CONFIG_SME */ 1310c1d255d3SCy Schubert (ssid->key_mgmt & (WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_FT_SAE)) && 1311c1d255d3SCy Schubert (ssid->sae_pk != SAE_PK_MODE_ONLY || 1312c1d255d3SCy Schubert ssid->ieee80211w != MGMT_FRAME_PROTECTION_REQUIRED || 1313c1d255d3SCy Schubert (ssid->group_cipher & WPA_CIPHER_TKIP))) { 1314c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, 1315c1d255d3SCy Schubert "SAE-PK: SAE authentication without PK disabled based on AP notification"); 1316c1d255d3SCy Schubert disable_wpa_wpa2(ssid); 1317c1d255d3SCy Schubert ssid->sae_pk = SAE_PK_MODE_ONLY; 1318c1d255d3SCy Schubert changed = 1; 1319c1d255d3SCy Schubert } 1320c1d255d3SCy Schubert #endif /* CONFIG_SAE */ 1321c1d255d3SCy Schubert 1322c1d255d3SCy Schubert if ((bitmap & TRANSITION_DISABLE_WPA3_ENTERPRISE) && 1323c1d255d3SCy Schubert wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) && 1324c1d255d3SCy Schubert (ssid->key_mgmt & (WPA_KEY_MGMT_IEEE8021X | 1325c1d255d3SCy Schubert WPA_KEY_MGMT_FT_IEEE8021X | 1326c1d255d3SCy Schubert WPA_KEY_MGMT_IEEE8021X_SHA256)) && 1327c1d255d3SCy Schubert (ssid->ieee80211w != MGMT_FRAME_PROTECTION_REQUIRED || 1328c1d255d3SCy Schubert (ssid->group_cipher & WPA_CIPHER_TKIP))) { 1329c1d255d3SCy Schubert disable_wpa_wpa2(ssid); 1330c1d255d3SCy Schubert changed = 1; 1331c1d255d3SCy Schubert } 1332c1d255d3SCy Schubert 1333c1d255d3SCy Schubert if ((bitmap & TRANSITION_DISABLE_ENHANCED_OPEN) && 1334c1d255d3SCy Schubert wpa_s->key_mgmt == WPA_KEY_MGMT_OWE && 1335c1d255d3SCy Schubert (ssid->key_mgmt & WPA_KEY_MGMT_OWE) && 1336c1d255d3SCy Schubert !ssid->owe_only) { 1337c1d255d3SCy Schubert ssid->owe_only = 1; 1338c1d255d3SCy Schubert changed = 1; 1339c1d255d3SCy Schubert } 1340c1d255d3SCy Schubert 1341c1d255d3SCy Schubert if (!changed) 1342c1d255d3SCy Schubert return; 1343c1d255d3SCy Schubert 1344c1d255d3SCy Schubert #ifndef CONFIG_NO_CONFIG_WRITE 1345c1d255d3SCy Schubert if (wpa_s->conf->update_config && 1346c1d255d3SCy Schubert wpa_config_write(wpa_s->confname, wpa_s->conf)) 1347c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, "Failed to update configuration"); 1348c1d255d3SCy Schubert #endif /* CONFIG_NO_CONFIG_WRITE */ 1349c1d255d3SCy Schubert } 1350c1d255d3SCy Schubert 1351c1d255d3SCy Schubert 1352c1d255d3SCy Schubert static void wpa_supplicant_store_ptk(void *ctx, u8 *addr, int cipher, 1353c1d255d3SCy Schubert u32 life_time, const struct wpa_ptk *ptk) 1354c1d255d3SCy Schubert { 1355c1d255d3SCy Schubert struct wpa_supplicant *wpa_s = ctx; 1356c1d255d3SCy Schubert 1357c1d255d3SCy Schubert ptksa_cache_add(wpa_s->ptksa, addr, cipher, life_time, ptk); 1358c1d255d3SCy Schubert } 1359c1d255d3SCy Schubert 1360780fb4a2SCy Schubert #endif /* CONFIG_NO_WPA */ 13615b9c547cSRui Paulo 13625b9c547cSRui Paulo 136339beb93cSSam Leffler int wpa_supplicant_init_wpa(struct wpa_supplicant *wpa_s) 136439beb93cSSam Leffler { 136539beb93cSSam Leffler #ifndef CONFIG_NO_WPA 136639beb93cSSam Leffler struct wpa_sm_ctx *ctx; 1367c1d255d3SCy Schubert 1368c1d255d3SCy Schubert wpa_s->ptksa = ptksa_cache_init(); 1369c1d255d3SCy Schubert if (!wpa_s->ptksa) { 1370c1d255d3SCy Schubert wpa_printf(MSG_ERROR, "Failed to allocate PTKSA"); 1371c1d255d3SCy Schubert return -1; 1372c1d255d3SCy Schubert } 1373c1d255d3SCy Schubert 137439beb93cSSam Leffler ctx = os_zalloc(sizeof(*ctx)); 137539beb93cSSam Leffler if (ctx == NULL) { 137639beb93cSSam Leffler wpa_printf(MSG_ERROR, "Failed to allocate WPA context."); 1377c1d255d3SCy Schubert 1378c1d255d3SCy Schubert ptksa_cache_deinit(wpa_s->ptksa); 1379c1d255d3SCy Schubert wpa_s->ptksa = NULL; 1380c1d255d3SCy Schubert 138139beb93cSSam Leffler return -1; 138239beb93cSSam Leffler } 138339beb93cSSam Leffler 138439beb93cSSam Leffler ctx->ctx = wpa_s; 1385e28a4053SRui Paulo ctx->msg_ctx = wpa_s; 138639beb93cSSam Leffler ctx->set_state = _wpa_supplicant_set_state; 138739beb93cSSam Leffler ctx->get_state = _wpa_supplicant_get_state; 138839beb93cSSam Leffler ctx->deauthenticate = _wpa_supplicant_deauthenticate; 1389c1d255d3SCy Schubert ctx->reconnect = _wpa_supplicant_reconnect; 139039beb93cSSam Leffler ctx->set_key = wpa_supplicant_set_key; 139139beb93cSSam Leffler ctx->get_network_ctx = wpa_supplicant_get_network_ctx; 139239beb93cSSam Leffler ctx->get_bssid = wpa_supplicant_get_bssid; 139339beb93cSSam Leffler ctx->ether_send = _wpa_ether_send; 139439beb93cSSam Leffler ctx->get_beacon_ie = wpa_supplicant_get_beacon_ie; 139539beb93cSSam Leffler ctx->alloc_eapol = _wpa_alloc_eapol; 139639beb93cSSam Leffler ctx->cancel_auth_timeout = _wpa_supplicant_cancel_auth_timeout; 139739beb93cSSam Leffler ctx->add_pmkid = wpa_supplicant_add_pmkid; 139839beb93cSSam Leffler ctx->remove_pmkid = wpa_supplicant_remove_pmkid; 139939beb93cSSam Leffler #ifndef CONFIG_NO_CONFIG_BLOBS 140039beb93cSSam Leffler ctx->set_config_blob = wpa_supplicant_set_config_blob; 140139beb93cSSam Leffler ctx->get_config_blob = wpa_supplicant_get_config_blob; 140239beb93cSSam Leffler #endif /* CONFIG_NO_CONFIG_BLOBS */ 140339beb93cSSam Leffler ctx->mlme_setprotection = wpa_supplicant_mlme_setprotection; 140439beb93cSSam Leffler #ifdef CONFIG_IEEE80211R 140539beb93cSSam Leffler ctx->update_ft_ies = wpa_supplicant_update_ft_ies; 140639beb93cSSam Leffler ctx->send_ft_action = wpa_supplicant_send_ft_action; 1407e28a4053SRui Paulo ctx->mark_authenticated = wpa_supplicant_mark_authenticated; 140839beb93cSSam Leffler #endif /* CONFIG_IEEE80211R */ 1409f05cddf9SRui Paulo #ifdef CONFIG_TDLS 1410f05cddf9SRui Paulo ctx->tdls_get_capa = wpa_supplicant_tdls_get_capa; 1411f05cddf9SRui Paulo ctx->send_tdls_mgmt = wpa_supplicant_send_tdls_mgmt; 1412f05cddf9SRui Paulo ctx->tdls_oper = wpa_supplicant_tdls_oper; 1413f05cddf9SRui Paulo ctx->tdls_peer_addset = wpa_supplicant_tdls_peer_addset; 14145b9c547cSRui Paulo ctx->tdls_enable_channel_switch = 14155b9c547cSRui Paulo wpa_supplicant_tdls_enable_channel_switch; 14165b9c547cSRui Paulo ctx->tdls_disable_channel_switch = 14175b9c547cSRui Paulo wpa_supplicant_tdls_disable_channel_switch; 1418f05cddf9SRui Paulo #endif /* CONFIG_TDLS */ 1419f05cddf9SRui Paulo ctx->set_rekey_offload = wpa_supplicant_set_rekey_offload; 14205b9c547cSRui Paulo ctx->key_mgmt_set_pmk = wpa_supplicant_key_mgmt_set_pmk; 142185732ac8SCy Schubert ctx->fils_hlp_rx = wpa_supplicant_fils_hlp_rx; 14224bc52338SCy Schubert ctx->channel_info = wpa_supplicant_channel_info; 1423c1d255d3SCy Schubert ctx->transition_disable = wpa_supplicant_transition_disable; 1424c1d255d3SCy Schubert ctx->store_ptk = wpa_supplicant_store_ptk; 142539beb93cSSam Leffler 142639beb93cSSam Leffler wpa_s->wpa = wpa_sm_init(ctx); 142739beb93cSSam Leffler if (wpa_s->wpa == NULL) { 1428c1d255d3SCy Schubert wpa_printf(MSG_ERROR, 1429c1d255d3SCy Schubert "Failed to initialize WPA state machine"); 14305b9c547cSRui Paulo os_free(ctx); 1431c1d255d3SCy Schubert ptksa_cache_deinit(wpa_s->ptksa); 1432c1d255d3SCy Schubert wpa_s->ptksa = NULL; 143339beb93cSSam Leffler return -1; 143439beb93cSSam Leffler } 143539beb93cSSam Leffler #endif /* CONFIG_NO_WPA */ 143639beb93cSSam Leffler 143739beb93cSSam Leffler return 0; 143839beb93cSSam Leffler } 143939beb93cSSam Leffler 144039beb93cSSam Leffler 144139beb93cSSam Leffler void wpa_supplicant_rsn_supp_set_config(struct wpa_supplicant *wpa_s, 144239beb93cSSam Leffler struct wpa_ssid *ssid) 144339beb93cSSam Leffler { 144439beb93cSSam Leffler struct rsn_supp_config conf; 144539beb93cSSam Leffler if (ssid) { 144639beb93cSSam Leffler os_memset(&conf, 0, sizeof(conf)); 144739beb93cSSam Leffler conf.network_ctx = ssid; 144839beb93cSSam Leffler conf.allowed_pairwise_cipher = ssid->pairwise_cipher; 144939beb93cSSam Leffler #ifdef IEEE8021X_EAPOL 1450f05cddf9SRui Paulo conf.proactive_key_caching = ssid->proactive_key_caching < 0 ? 1451f05cddf9SRui Paulo wpa_s->conf->okc : ssid->proactive_key_caching; 145239beb93cSSam Leffler conf.eap_workaround = ssid->eap_workaround; 145339beb93cSSam Leffler conf.eap_conf_ctx = &ssid->eap; 145439beb93cSSam Leffler #endif /* IEEE8021X_EAPOL */ 145539beb93cSSam Leffler conf.ssid = ssid->ssid; 145639beb93cSSam Leffler conf.ssid_len = ssid->ssid_len; 145739beb93cSSam Leffler conf.wpa_ptk_rekey = ssid->wpa_ptk_rekey; 1458c1d255d3SCy Schubert conf.wpa_deny_ptk0_rekey = ssid->wpa_deny_ptk0_rekey; 1459c1d255d3SCy Schubert conf.owe_ptk_workaround = ssid->owe_ptk_workaround; 14605b9c547cSRui Paulo #ifdef CONFIG_P2P 14615b9c547cSRui Paulo if (ssid->p2p_group && wpa_s->current_bss && 14625b9c547cSRui Paulo !wpa_s->p2p_disable_ip_addr_req) { 14635b9c547cSRui Paulo struct wpabuf *p2p; 14645b9c547cSRui Paulo p2p = wpa_bss_get_vendor_ie_multi(wpa_s->current_bss, 14655b9c547cSRui Paulo P2P_IE_VENDOR_TYPE); 14665b9c547cSRui Paulo if (p2p) { 14675b9c547cSRui Paulo u8 group_capab; 14685b9c547cSRui Paulo group_capab = p2p_get_group_capab(p2p); 14695b9c547cSRui Paulo if (group_capab & 14705b9c547cSRui Paulo P2P_GROUP_CAPAB_IP_ADDR_ALLOCATION) 14715b9c547cSRui Paulo conf.p2p = 1; 14725b9c547cSRui Paulo wpabuf_free(p2p); 14735b9c547cSRui Paulo } 14745b9c547cSRui Paulo } 14755b9c547cSRui Paulo #endif /* CONFIG_P2P */ 1476780fb4a2SCy Schubert conf.wpa_rsc_relaxation = wpa_s->conf->wpa_rsc_relaxation; 147785732ac8SCy Schubert #ifdef CONFIG_FILS 147885732ac8SCy Schubert if (wpa_key_mgmt_fils(wpa_s->key_mgmt)) 147985732ac8SCy Schubert conf.fils_cache_id = 148085732ac8SCy Schubert wpa_bss_get_fils_cache_id(wpa_s->current_bss); 148185732ac8SCy Schubert #endif /* CONFIG_FILS */ 1482c1d255d3SCy Schubert if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_BEACON_PROTECTION) || 1483c1d255d3SCy Schubert (wpa_s->drv_flags2 & 1484c1d255d3SCy Schubert WPA_DRIVER_FLAGS2_BEACON_PROTECTION_CLIENT)) 1485c1d255d3SCy Schubert conf.beacon_prot = ssid->beacon_prot; 1486c1d255d3SCy Schubert 1487c1d255d3SCy Schubert #ifdef CONFIG_PASN 1488c1d255d3SCy Schubert #ifdef CONFIG_TESTING_OPTIONS 1489c1d255d3SCy Schubert conf.force_kdk_derivation = wpa_s->conf->force_kdk_derivation; 1490c1d255d3SCy Schubert #endif /* CONFIG_TESTING_OPTIONS */ 1491c1d255d3SCy Schubert #endif /* CONFIG_PASN */ 149239beb93cSSam Leffler } 149339beb93cSSam Leffler wpa_sm_set_config(wpa_s->wpa, ssid ? &conf : NULL); 149439beb93cSSam Leffler } 1495