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" 19*c1d255d3SCy 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 */ 98*c1d255d3SCy 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 116*c1d255d3SCy Schubert if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_CONTROL_PORT) { 117*c1d255d3SCy Schubert int encrypt = wpa_s->wpa && 118*c1d255d3SCy Schubert wpa_sm_has_ptk_installed(wpa_s->wpa); 119*c1d255d3SCy Schubert 120*c1d255d3SCy Schubert return wpa_drv_tx_control_port(wpa_s, dest, proto, buf, len, 121*c1d255d3SCy Schubert !encrypt); 122*c1d255d3SCy Schubert } 123*c1d255d3SCy 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 231*c1d255d3SCy 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, 255*c1d255d3SCy Schubert keyidx, unicast, NULL, 0, key, keylen, 256*c1d255d3SCy Schubert unicast ? KEY_FLAG_PAIRWISE_RX_TX : 257*c1d255d3SCy Schubert KEY_FLAG_GROUP_RX_TX_DEFAULT); 25839beb93cSSam Leffler } 259*c1d255d3SCy 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 356*c1d255d3SCy Schubert if (wpa_drv_set_key(wpa_s, 0, NULL, 0, 0, NULL, 0, pmk, 357*c1d255d3SCy 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 } 402*c1d255d3SCy Schubert #ifdef CONFIG_OWE 403*c1d255d3SCy Schubert if (ssid && (ssid->key_mgmt & WPA_KEY_MGMT_OWE) && 404*c1d255d3SCy Schubert (bss->flags & WPA_BSS_OWE_TRANSITION)) { 405*c1d255d3SCy Schubert curr = bss; 406*c1d255d3SCy Schubert break; 407*c1d255d3SCy Schubert } 408*c1d255d3SCy 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; 419*c1d255d3SCy Schubert 420*c1d255d3SCy Schubert ie = wpa_bss_get_ie(curr, WLAN_EID_RSNX); 421*c1d255d3SCy Schubert if (wpa_sm_set_ap_rsnxe(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0)) 422*c1d255d3SCy 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 499*c1d255d3SCy Schubert static void _wpa_supplicant_reconnect(void *wpa_s) 500*c1d255d3SCy Schubert { 501*c1d255d3SCy Schubert wpa_supplicant_reconnect(wpa_s); 502*c1d255d3SCy Schubert } 503*c1d255d3SCy Schubert 504*c1d255d3SCy 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, 521*c1d255d3SCy Schubert const u8 *key, size_t key_len, 522*c1d255d3SCy 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 537*c1d255d3SCy Schubert if (addr && !is_broadcast_ether_addr(addr) && 538*c1d255d3SCy 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, 548*c1d255d3SCy 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, 578*c1d255d3SCy Schubert const u8 *pmk, size_t pmk_len, 579*c1d255d3SCy Schubert u32 pmk_lifetime, u8 pmk_reauth_threshold, 580*c1d255d3SCy 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); 588*c1d255d3SCy Schubert if (ssid) { 58985732ac8SCy Schubert wpa_msg(wpa_s, MSG_INFO, PMKSA_CACHE_ADDED MACSTR " %d", 59085732ac8SCy Schubert MAC2STR(bssid), ssid->id); 591*c1d255d3SCy Schubert if ((akmp == WPA_KEY_MGMT_FT_IEEE8021X || 592*c1d255d3SCy Schubert akmp == WPA_KEY_MGMT_FT_IEEE8021X_SHA384) && 593*c1d255d3SCy Schubert !ssid->ft_eap_pmksa_caching) { 594*c1d255d3SCy Schubert /* Since we will not be using PMKSA caching for FT-EAP 595*c1d255d3SCy Schubert * within wpa_supplicant to avoid known interop issues 596*c1d255d3SCy Schubert * with APs, do not add this PMKID to the driver either 597*c1d255d3SCy Schubert * so that we won't be hitting those interop issues 598*c1d255d3SCy Schubert * with driver-based RSNE generation. */ 599*c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, 600*c1d255d3SCy Schubert "FT: Do not add PMKID entry to the driver since FT-EAP PMKSA caching is not enabled in configuration"); 601*c1d255d3SCy Schubert return 0; 602*c1d255d3SCy Schubert } 603*c1d255d3SCy 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; 615*c1d255d3SCy Schubert params.pmk_lifetime = pmk_lifetime; 616*c1d255d3SCy 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, 781*c1d255d3SCy Schubert const struct ieee80211_he_capabilities *he_capab, 782*c1d255d3SCy Schubert size_t he_capab_len, 7835b9c547cSRui Paulo u8 qosinfo, int wmm, const u8 *ext_capab, size_t ext_capab_len, 7845b9c547cSRui Paulo const u8 *supp_channels, size_t supp_channels_len, 7855b9c547cSRui Paulo const u8 *supp_oper_classes, size_t supp_oper_classes_len) 786f05cddf9SRui Paulo { 787f05cddf9SRui Paulo struct wpa_supplicant *wpa_s = ctx; 788f05cddf9SRui Paulo struct hostapd_sta_add_params params; 789f05cddf9SRui Paulo 7905b9c547cSRui Paulo os_memset(¶ms, 0, sizeof(params)); 7915b9c547cSRui Paulo 792f05cddf9SRui Paulo params.addr = peer; 7935b9c547cSRui Paulo params.aid = aid; 794f05cddf9SRui Paulo params.capability = capability; 795f05cddf9SRui Paulo params.flags = WPA_STA_TDLS_PEER | WPA_STA_AUTHORIZED; 7965b9c547cSRui Paulo 7975b9c547cSRui Paulo /* 7985b9c547cSRui Paulo * Don't rely only on qosinfo for WMM capability. It may be 0 even when 7995b9c547cSRui Paulo * present. Allow the WMM IE to also indicate QoS support. 8005b9c547cSRui Paulo */ 8015b9c547cSRui Paulo if (wmm || qosinfo) 8025b9c547cSRui Paulo params.flags |= WPA_STA_WMM; 8035b9c547cSRui Paulo 8045b9c547cSRui Paulo params.ht_capabilities = ht_capab; 8055b9c547cSRui Paulo params.vht_capabilities = vht_capab; 806*c1d255d3SCy Schubert params.he_capab = he_capab; 807*c1d255d3SCy Schubert params.he_capab_len = he_capab_len; 8085b9c547cSRui Paulo params.qosinfo = qosinfo; 809f05cddf9SRui Paulo params.listen_interval = 0; 810f05cddf9SRui Paulo params.supp_rates = supp_rates; 811f05cddf9SRui Paulo params.supp_rates_len = supp_rates_len; 812f05cddf9SRui Paulo params.set = !add; 8135b9c547cSRui Paulo params.ext_capab = ext_capab; 8145b9c547cSRui Paulo params.ext_capab_len = ext_capab_len; 8155b9c547cSRui Paulo params.supp_channels = supp_channels; 8165b9c547cSRui Paulo params.supp_channels_len = supp_channels_len; 8175b9c547cSRui Paulo params.supp_oper_classes = supp_oper_classes; 8185b9c547cSRui Paulo params.supp_oper_classes_len = supp_oper_classes_len; 819f05cddf9SRui Paulo 820f05cddf9SRui Paulo return wpa_drv_sta_add(wpa_s, ¶ms); 821f05cddf9SRui Paulo } 822f05cddf9SRui Paulo 8235b9c547cSRui Paulo 8245b9c547cSRui Paulo static int wpa_supplicant_tdls_enable_channel_switch( 8255b9c547cSRui Paulo void *ctx, const u8 *addr, u8 oper_class, 8265b9c547cSRui Paulo const struct hostapd_freq_params *params) 8275b9c547cSRui Paulo { 8285b9c547cSRui Paulo struct wpa_supplicant *wpa_s = ctx; 8295b9c547cSRui Paulo 8305b9c547cSRui Paulo return wpa_drv_tdls_enable_channel_switch(wpa_s, addr, oper_class, 8315b9c547cSRui Paulo params); 8325b9c547cSRui Paulo } 8335b9c547cSRui Paulo 8345b9c547cSRui Paulo 8355b9c547cSRui Paulo static int wpa_supplicant_tdls_disable_channel_switch(void *ctx, const u8 *addr) 8365b9c547cSRui Paulo { 8375b9c547cSRui Paulo struct wpa_supplicant *wpa_s = ctx; 8385b9c547cSRui Paulo 8395b9c547cSRui Paulo return wpa_drv_tdls_disable_channel_switch(wpa_s, addr); 8405b9c547cSRui Paulo } 8415b9c547cSRui Paulo 842f05cddf9SRui Paulo #endif /* CONFIG_TDLS */ 843f05cddf9SRui Paulo 8445b9c547cSRui Paulo #endif /* CONFIG_NO_WPA */ 8455b9c547cSRui Paulo 846f05cddf9SRui Paulo 847f05cddf9SRui Paulo enum wpa_ctrl_req_type wpa_supplicant_ctrl_req_from_string(const char *field) 848f05cddf9SRui Paulo { 849f05cddf9SRui Paulo if (os_strcmp(field, "IDENTITY") == 0) 850f05cddf9SRui Paulo return WPA_CTRL_REQ_EAP_IDENTITY; 851f05cddf9SRui Paulo else if (os_strcmp(field, "PASSWORD") == 0) 852f05cddf9SRui Paulo return WPA_CTRL_REQ_EAP_PASSWORD; 853f05cddf9SRui Paulo else if (os_strcmp(field, "NEW_PASSWORD") == 0) 854f05cddf9SRui Paulo return WPA_CTRL_REQ_EAP_NEW_PASSWORD; 855f05cddf9SRui Paulo else if (os_strcmp(field, "PIN") == 0) 856f05cddf9SRui Paulo return WPA_CTRL_REQ_EAP_PIN; 857f05cddf9SRui Paulo else if (os_strcmp(field, "OTP") == 0) 858f05cddf9SRui Paulo return WPA_CTRL_REQ_EAP_OTP; 859f05cddf9SRui Paulo else if (os_strcmp(field, "PASSPHRASE") == 0) 860f05cddf9SRui Paulo return WPA_CTRL_REQ_EAP_PASSPHRASE; 8615b9c547cSRui Paulo else if (os_strcmp(field, "SIM") == 0) 8625b9c547cSRui Paulo return WPA_CTRL_REQ_SIM; 863325151a3SRui Paulo else if (os_strcmp(field, "PSK_PASSPHRASE") == 0) 864325151a3SRui Paulo return WPA_CTRL_REQ_PSK_PASSPHRASE; 865780fb4a2SCy Schubert else if (os_strcmp(field, "EXT_CERT_CHECK") == 0) 866780fb4a2SCy Schubert return WPA_CTRL_REQ_EXT_CERT_CHECK; 867f05cddf9SRui Paulo return WPA_CTRL_REQ_UNKNOWN; 868f05cddf9SRui Paulo } 869f05cddf9SRui Paulo 870f05cddf9SRui Paulo 871f05cddf9SRui Paulo const char * wpa_supplicant_ctrl_req_to_string(enum wpa_ctrl_req_type field, 872f05cddf9SRui Paulo const char *default_txt, 873f05cddf9SRui Paulo const char **txt) 874f05cddf9SRui Paulo { 875f05cddf9SRui Paulo const char *ret = NULL; 876f05cddf9SRui Paulo 877f05cddf9SRui Paulo *txt = default_txt; 878f05cddf9SRui Paulo 879f05cddf9SRui Paulo switch (field) { 880f05cddf9SRui Paulo case WPA_CTRL_REQ_EAP_IDENTITY: 881f05cddf9SRui Paulo *txt = "Identity"; 882f05cddf9SRui Paulo ret = "IDENTITY"; 883f05cddf9SRui Paulo break; 884f05cddf9SRui Paulo case WPA_CTRL_REQ_EAP_PASSWORD: 885f05cddf9SRui Paulo *txt = "Password"; 886f05cddf9SRui Paulo ret = "PASSWORD"; 887f05cddf9SRui Paulo break; 888f05cddf9SRui Paulo case WPA_CTRL_REQ_EAP_NEW_PASSWORD: 889f05cddf9SRui Paulo *txt = "New Password"; 890f05cddf9SRui Paulo ret = "NEW_PASSWORD"; 891f05cddf9SRui Paulo break; 892f05cddf9SRui Paulo case WPA_CTRL_REQ_EAP_PIN: 893f05cddf9SRui Paulo *txt = "PIN"; 894f05cddf9SRui Paulo ret = "PIN"; 895f05cddf9SRui Paulo break; 896f05cddf9SRui Paulo case WPA_CTRL_REQ_EAP_OTP: 897f05cddf9SRui Paulo ret = "OTP"; 898f05cddf9SRui Paulo break; 899f05cddf9SRui Paulo case WPA_CTRL_REQ_EAP_PASSPHRASE: 900f05cddf9SRui Paulo *txt = "Private key passphrase"; 901f05cddf9SRui Paulo ret = "PASSPHRASE"; 902f05cddf9SRui Paulo break; 9035b9c547cSRui Paulo case WPA_CTRL_REQ_SIM: 9045b9c547cSRui Paulo ret = "SIM"; 9055b9c547cSRui Paulo break; 906325151a3SRui Paulo case WPA_CTRL_REQ_PSK_PASSPHRASE: 907325151a3SRui Paulo *txt = "PSK or passphrase"; 908325151a3SRui Paulo ret = "PSK_PASSPHRASE"; 909325151a3SRui Paulo break; 910780fb4a2SCy Schubert case WPA_CTRL_REQ_EXT_CERT_CHECK: 911780fb4a2SCy Schubert *txt = "External server certificate validation"; 912780fb4a2SCy Schubert ret = "EXT_CERT_CHECK"; 913780fb4a2SCy Schubert break; 914f05cddf9SRui Paulo default: 915f05cddf9SRui Paulo break; 916f05cddf9SRui Paulo } 917f05cddf9SRui Paulo 918f05cddf9SRui Paulo /* txt needs to be something */ 919f05cddf9SRui Paulo if (*txt == NULL) { 920f05cddf9SRui Paulo wpa_printf(MSG_WARNING, "No message for request %d", field); 921f05cddf9SRui Paulo ret = NULL; 922f05cddf9SRui Paulo } 923f05cddf9SRui Paulo 924f05cddf9SRui Paulo return ret; 925f05cddf9SRui Paulo } 926f05cddf9SRui Paulo 927325151a3SRui Paulo 928325151a3SRui Paulo void wpas_send_ctrl_req(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid, 929325151a3SRui Paulo const char *field_name, const char *txt) 930325151a3SRui Paulo { 931325151a3SRui Paulo char *buf; 932325151a3SRui Paulo size_t buflen; 933325151a3SRui Paulo int len; 934325151a3SRui Paulo 935325151a3SRui Paulo buflen = 100 + os_strlen(txt) + ssid->ssid_len; 936325151a3SRui Paulo buf = os_malloc(buflen); 937325151a3SRui Paulo if (buf == NULL) 938325151a3SRui Paulo return; 939325151a3SRui Paulo len = os_snprintf(buf, buflen, "%s-%d:%s needed for SSID ", 940325151a3SRui Paulo field_name, ssid->id, txt); 941325151a3SRui Paulo if (os_snprintf_error(buflen, len)) { 942325151a3SRui Paulo os_free(buf); 943325151a3SRui Paulo return; 944325151a3SRui Paulo } 945325151a3SRui Paulo if (ssid->ssid && buflen > len + ssid->ssid_len) { 946325151a3SRui Paulo os_memcpy(buf + len, ssid->ssid, ssid->ssid_len); 947325151a3SRui Paulo len += ssid->ssid_len; 948325151a3SRui Paulo buf[len] = '\0'; 949325151a3SRui Paulo } 950325151a3SRui Paulo buf[buflen - 1] = '\0'; 951325151a3SRui Paulo wpa_msg(wpa_s, MSG_INFO, WPA_CTRL_REQ "%s", buf); 952325151a3SRui Paulo os_free(buf); 953325151a3SRui Paulo } 954325151a3SRui Paulo 955325151a3SRui Paulo 956e28a4053SRui Paulo #ifdef IEEE8021X_EAPOL 95739beb93cSSam Leffler #if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG) 958f05cddf9SRui Paulo static void wpa_supplicant_eap_param_needed(void *ctx, 959f05cddf9SRui Paulo enum wpa_ctrl_req_type field, 960f05cddf9SRui Paulo const char *default_txt) 96139beb93cSSam Leffler { 96239beb93cSSam Leffler struct wpa_supplicant *wpa_s = ctx; 96339beb93cSSam Leffler struct wpa_ssid *ssid = wpa_s->current_ssid; 964f05cddf9SRui Paulo const char *field_name, *txt = NULL; 96539beb93cSSam Leffler 96639beb93cSSam Leffler if (ssid == NULL) 96739beb93cSSam Leffler return; 96839beb93cSSam Leffler 969780fb4a2SCy Schubert if (field == WPA_CTRL_REQ_EXT_CERT_CHECK) 970780fb4a2SCy Schubert ssid->eap.pending_ext_cert_check = PENDING_CHECK; 971f05cddf9SRui Paulo wpas_notify_network_request(wpa_s, ssid, field, default_txt); 972f05cddf9SRui Paulo 973f05cddf9SRui Paulo field_name = wpa_supplicant_ctrl_req_to_string(field, default_txt, 974f05cddf9SRui Paulo &txt); 975f05cddf9SRui Paulo if (field_name == NULL) { 976f05cddf9SRui Paulo wpa_printf(MSG_WARNING, "Unhandled EAP param %d needed", 977f05cddf9SRui Paulo field); 978f05cddf9SRui Paulo return; 979f05cddf9SRui Paulo } 980f05cddf9SRui Paulo 9815b9c547cSRui Paulo wpas_notify_eap_status(wpa_s, "eap parameter needed", field_name); 9825b9c547cSRui Paulo 983325151a3SRui Paulo wpas_send_ctrl_req(wpa_s, ssid, field_name, txt); 98439beb93cSSam Leffler } 98539beb93cSSam Leffler #else /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */ 98639beb93cSSam Leffler #define wpa_supplicant_eap_param_needed NULL 98739beb93cSSam Leffler #endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */ 98839beb93cSSam Leffler 98939beb93cSSam Leffler 9905b9c547cSRui Paulo #ifdef CONFIG_EAP_PROXY 99185732ac8SCy Schubert 9925b9c547cSRui Paulo static void wpa_supplicant_eap_proxy_cb(void *ctx) 9935b9c547cSRui Paulo { 9945b9c547cSRui Paulo struct wpa_supplicant *wpa_s = ctx; 9955b9c547cSRui Paulo size_t len; 9965b9c547cSRui Paulo 99785732ac8SCy Schubert wpa_s->mnc_len = eapol_sm_get_eap_proxy_imsi(wpa_s->eapol, -1, 9985b9c547cSRui Paulo wpa_s->imsi, &len); 9995b9c547cSRui Paulo if (wpa_s->mnc_len > 0) { 10005b9c547cSRui Paulo wpa_s->imsi[len] = '\0'; 10015b9c547cSRui Paulo wpa_printf(MSG_DEBUG, "eap_proxy: IMSI %s (MNC length %d)", 10025b9c547cSRui Paulo wpa_s->imsi, wpa_s->mnc_len); 10035b9c547cSRui Paulo } else { 10045b9c547cSRui Paulo wpa_printf(MSG_DEBUG, "eap_proxy: IMSI not available"); 10055b9c547cSRui Paulo } 10065b9c547cSRui Paulo } 100785732ac8SCy Schubert 100885732ac8SCy Schubert 100985732ac8SCy Schubert static void wpa_sm_sim_state_error_handler(struct wpa_supplicant *wpa_s) 101085732ac8SCy Schubert { 101185732ac8SCy Schubert int i; 101285732ac8SCy Schubert struct wpa_ssid *ssid; 101385732ac8SCy Schubert const struct eap_method_type *eap_methods; 101485732ac8SCy Schubert 101585732ac8SCy Schubert if (!wpa_s->conf) 101685732ac8SCy Schubert return; 101785732ac8SCy Schubert 101885732ac8SCy Schubert for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) { 101985732ac8SCy Schubert eap_methods = ssid->eap.eap_methods; 102085732ac8SCy Schubert if (!eap_methods) 102185732ac8SCy Schubert continue; 102285732ac8SCy Schubert 102385732ac8SCy Schubert for (i = 0; eap_methods[i].method != EAP_TYPE_NONE; i++) { 102485732ac8SCy Schubert if (eap_methods[i].vendor == EAP_VENDOR_IETF && 102585732ac8SCy Schubert (eap_methods[i].method == EAP_TYPE_SIM || 102685732ac8SCy Schubert eap_methods[i].method == EAP_TYPE_AKA || 102785732ac8SCy Schubert eap_methods[i].method == EAP_TYPE_AKA_PRIME)) { 102885732ac8SCy Schubert wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid); 102985732ac8SCy Schubert break; 103085732ac8SCy Schubert } 103185732ac8SCy Schubert } 103285732ac8SCy Schubert } 103385732ac8SCy Schubert } 103485732ac8SCy Schubert 103585732ac8SCy Schubert 103685732ac8SCy Schubert static void 103785732ac8SCy Schubert wpa_supplicant_eap_proxy_notify_sim_status(void *ctx, 103885732ac8SCy Schubert enum eap_proxy_sim_state sim_state) 103985732ac8SCy Schubert { 104085732ac8SCy Schubert struct wpa_supplicant *wpa_s = ctx; 104185732ac8SCy Schubert 104285732ac8SCy Schubert wpa_printf(MSG_DEBUG, "eap_proxy: SIM card status %u", sim_state); 104385732ac8SCy Schubert switch (sim_state) { 104485732ac8SCy Schubert case SIM_STATE_ERROR: 104585732ac8SCy Schubert wpa_sm_sim_state_error_handler(wpa_s); 104685732ac8SCy Schubert break; 104785732ac8SCy Schubert default: 104885732ac8SCy Schubert wpa_printf(MSG_DEBUG, "eap_proxy: SIM card status unknown"); 104985732ac8SCy Schubert break; 105085732ac8SCy Schubert } 105185732ac8SCy Schubert } 105285732ac8SCy Schubert 10535b9c547cSRui Paulo #endif /* CONFIG_EAP_PROXY */ 10545b9c547cSRui Paulo 10555b9c547cSRui Paulo 1056e28a4053SRui Paulo static void wpa_supplicant_port_cb(void *ctx, int authorized) 1057e28a4053SRui Paulo { 1058e28a4053SRui Paulo struct wpa_supplicant *wpa_s = ctx; 1059e28a4053SRui Paulo #ifdef CONFIG_AP 1060e28a4053SRui Paulo if (wpa_s->ap_iface) { 1061e28a4053SRui Paulo wpa_printf(MSG_DEBUG, "AP mode active - skip EAPOL Supplicant " 1062e28a4053SRui Paulo "port status: %s", 1063e28a4053SRui Paulo authorized ? "Authorized" : "Unauthorized"); 1064e28a4053SRui Paulo return; 1065e28a4053SRui Paulo } 1066e28a4053SRui Paulo #endif /* CONFIG_AP */ 1067e28a4053SRui Paulo wpa_printf(MSG_DEBUG, "EAPOL: Supplicant port status: %s", 1068e28a4053SRui Paulo authorized ? "Authorized" : "Unauthorized"); 1069e28a4053SRui Paulo wpa_drv_set_supp_port(wpa_s, authorized); 1070e28a4053SRui Paulo } 1071f05cddf9SRui Paulo 1072f05cddf9SRui Paulo 1073206b73d0SCy Schubert static void wpa_supplicant_cert_cb(void *ctx, struct tls_cert_data *cert, 1074206b73d0SCy Schubert const char *cert_hash) 1075f05cddf9SRui Paulo { 1076f05cddf9SRui Paulo struct wpa_supplicant *wpa_s = ctx; 1077f05cddf9SRui Paulo 1078206b73d0SCy Schubert wpas_notify_certification(wpa_s, cert, cert_hash); 1079f05cddf9SRui Paulo } 1080f05cddf9SRui Paulo 1081f05cddf9SRui Paulo 1082f05cddf9SRui Paulo static void wpa_supplicant_status_cb(void *ctx, const char *status, 1083f05cddf9SRui Paulo const char *parameter) 1084f05cddf9SRui Paulo { 1085f05cddf9SRui Paulo struct wpa_supplicant *wpa_s = ctx; 1086f05cddf9SRui Paulo 1087f05cddf9SRui Paulo wpas_notify_eap_status(wpa_s, status, parameter); 1088f05cddf9SRui Paulo } 1089f05cddf9SRui Paulo 1090f05cddf9SRui Paulo 109185732ac8SCy Schubert static void wpa_supplicant_eap_error_cb(void *ctx, int error_code) 109285732ac8SCy Schubert { 109385732ac8SCy Schubert struct wpa_supplicant *wpa_s = ctx; 109485732ac8SCy Schubert 109585732ac8SCy Schubert wpas_notify_eap_error(wpa_s, error_code); 109685732ac8SCy Schubert } 109785732ac8SCy Schubert 109885732ac8SCy Schubert 1099*c1d255d3SCy Schubert static int wpa_supplicant_eap_auth_start_cb(void *ctx) 1100*c1d255d3SCy Schubert { 1101*c1d255d3SCy Schubert struct wpa_supplicant *wpa_s = ctx; 1102*c1d255d3SCy Schubert 1103*c1d255d3SCy Schubert if (!wpa_s->new_connection && wpa_s->deny_ptk0_rekey && 1104*c1d255d3SCy Schubert !wpa_sm_ext_key_id_active(wpa_s->wpa)) { 1105*c1d255d3SCy Schubert wpa_msg(wpa_s, MSG_INFO, 1106*c1d255d3SCy Schubert "WPA: PTK0 rekey not allowed, reconnecting"); 1107*c1d255d3SCy Schubert wpa_supplicant_reconnect(wpa_s); 1108*c1d255d3SCy Schubert return -1; 1109*c1d255d3SCy Schubert } 1110*c1d255d3SCy Schubert return 0; 1111*c1d255d3SCy Schubert } 1112*c1d255d3SCy Schubert 1113*c1d255d3SCy Schubert 1114f05cddf9SRui Paulo static void wpa_supplicant_set_anon_id(void *ctx, const u8 *id, size_t len) 1115f05cddf9SRui Paulo { 1116f05cddf9SRui Paulo struct wpa_supplicant *wpa_s = ctx; 1117f05cddf9SRui Paulo char *str; 1118f05cddf9SRui Paulo int res; 1119f05cddf9SRui Paulo 1120f05cddf9SRui Paulo wpa_hexdump_ascii(MSG_DEBUG, "EAP method updated anonymous_identity", 1121f05cddf9SRui Paulo id, len); 1122f05cddf9SRui Paulo 1123f05cddf9SRui Paulo if (wpa_s->current_ssid == NULL) 1124f05cddf9SRui Paulo return; 1125f05cddf9SRui Paulo 1126f05cddf9SRui Paulo if (id == NULL) { 1127f05cddf9SRui Paulo if (wpa_config_set(wpa_s->current_ssid, "anonymous_identity", 1128f05cddf9SRui Paulo "NULL", 0) < 0) 1129f05cddf9SRui Paulo return; 1130f05cddf9SRui Paulo } else { 1131f05cddf9SRui Paulo str = os_malloc(len * 2 + 1); 1132f05cddf9SRui Paulo if (str == NULL) 1133f05cddf9SRui Paulo return; 1134f05cddf9SRui Paulo wpa_snprintf_hex(str, len * 2 + 1, id, len); 1135f05cddf9SRui Paulo res = wpa_config_set(wpa_s->current_ssid, "anonymous_identity", 1136f05cddf9SRui Paulo str, 0); 1137f05cddf9SRui Paulo os_free(str); 1138f05cddf9SRui Paulo if (res < 0) 1139f05cddf9SRui Paulo return; 1140f05cddf9SRui Paulo } 1141f05cddf9SRui Paulo 1142f05cddf9SRui Paulo if (wpa_s->conf->update_config) { 1143f05cddf9SRui Paulo res = wpa_config_write(wpa_s->confname, wpa_s->conf); 1144f05cddf9SRui Paulo if (res) { 1145f05cddf9SRui Paulo wpa_printf(MSG_DEBUG, "Failed to update config after " 1146f05cddf9SRui Paulo "anonymous_id update"); 1147f05cddf9SRui Paulo } 1148f05cddf9SRui Paulo } 1149f05cddf9SRui Paulo } 1150e28a4053SRui Paulo #endif /* IEEE8021X_EAPOL */ 1151e28a4053SRui Paulo 1152e28a4053SRui Paulo 115339beb93cSSam Leffler int wpa_supplicant_init_eapol(struct wpa_supplicant *wpa_s) 115439beb93cSSam Leffler { 115539beb93cSSam Leffler #ifdef IEEE8021X_EAPOL 115639beb93cSSam Leffler struct eapol_ctx *ctx; 115739beb93cSSam Leffler ctx = os_zalloc(sizeof(*ctx)); 115839beb93cSSam Leffler if (ctx == NULL) { 115939beb93cSSam Leffler wpa_printf(MSG_ERROR, "Failed to allocate EAPOL context."); 116039beb93cSSam Leffler return -1; 116139beb93cSSam Leffler } 116239beb93cSSam Leffler 116339beb93cSSam Leffler ctx->ctx = wpa_s; 116439beb93cSSam Leffler ctx->msg_ctx = wpa_s; 116539beb93cSSam Leffler ctx->eapol_send_ctx = wpa_s; 116639beb93cSSam Leffler ctx->preauth = 0; 116739beb93cSSam Leffler ctx->eapol_done_cb = wpa_supplicant_notify_eapol_done; 116839beb93cSSam Leffler ctx->eapol_send = wpa_supplicant_eapol_send; 1169*c1d255d3SCy Schubert #ifdef CONFIG_WEP 117039beb93cSSam Leffler ctx->set_wep_key = wpa_eapol_set_wep_key; 1171*c1d255d3SCy Schubert #endif /* CONFIG_WEP */ 11725b9c547cSRui Paulo #ifndef CONFIG_NO_CONFIG_BLOBS 117339beb93cSSam Leffler ctx->set_config_blob = wpa_supplicant_set_config_blob; 117439beb93cSSam Leffler ctx->get_config_blob = wpa_supplicant_get_config_blob; 11755b9c547cSRui Paulo #endif /* CONFIG_NO_CONFIG_BLOBS */ 117639beb93cSSam Leffler ctx->aborted_cached = wpa_supplicant_aborted_cached; 117739beb93cSSam Leffler ctx->opensc_engine_path = wpa_s->conf->opensc_engine_path; 117839beb93cSSam Leffler ctx->pkcs11_engine_path = wpa_s->conf->pkcs11_engine_path; 117939beb93cSSam Leffler ctx->pkcs11_module_path = wpa_s->conf->pkcs11_module_path; 11805b9c547cSRui Paulo ctx->openssl_ciphers = wpa_s->conf->openssl_ciphers; 118139beb93cSSam Leffler ctx->wps = wpa_s->wps; 118239beb93cSSam Leffler ctx->eap_param_needed = wpa_supplicant_eap_param_needed; 11835b9c547cSRui Paulo #ifdef CONFIG_EAP_PROXY 11845b9c547cSRui Paulo ctx->eap_proxy_cb = wpa_supplicant_eap_proxy_cb; 118585732ac8SCy Schubert ctx->eap_proxy_notify_sim_status = 118685732ac8SCy Schubert wpa_supplicant_eap_proxy_notify_sim_status; 11875b9c547cSRui Paulo #endif /* CONFIG_EAP_PROXY */ 1188e28a4053SRui Paulo ctx->port_cb = wpa_supplicant_port_cb; 118939beb93cSSam Leffler ctx->cb = wpa_supplicant_eapol_cb; 1190f05cddf9SRui Paulo ctx->cert_cb = wpa_supplicant_cert_cb; 11915b9c547cSRui Paulo ctx->cert_in_cb = wpa_s->conf->cert_in_cb; 1192f05cddf9SRui Paulo ctx->status_cb = wpa_supplicant_status_cb; 119385732ac8SCy Schubert ctx->eap_error_cb = wpa_supplicant_eap_error_cb; 1194*c1d255d3SCy Schubert ctx->confirm_auth_cb = wpa_supplicant_eap_auth_start_cb; 1195f05cddf9SRui Paulo ctx->set_anon_id = wpa_supplicant_set_anon_id; 119639beb93cSSam Leffler ctx->cb_ctx = wpa_s; 119739beb93cSSam Leffler wpa_s->eapol = eapol_sm_init(ctx); 119839beb93cSSam Leffler if (wpa_s->eapol == NULL) { 119939beb93cSSam Leffler os_free(ctx); 120039beb93cSSam Leffler wpa_printf(MSG_ERROR, "Failed to initialize EAPOL state " 120139beb93cSSam Leffler "machines."); 120239beb93cSSam Leffler return -1; 120339beb93cSSam Leffler } 120439beb93cSSam Leffler #endif /* IEEE8021X_EAPOL */ 120539beb93cSSam Leffler 120639beb93cSSam Leffler return 0; 120739beb93cSSam Leffler } 120839beb93cSSam Leffler 120939beb93cSSam Leffler 1210f05cddf9SRui Paulo #ifndef CONFIG_NO_WPA 121185732ac8SCy Schubert 12125b9c547cSRui Paulo static void wpa_supplicant_set_rekey_offload(void *ctx, 12135b9c547cSRui Paulo const u8 *kek, size_t kek_len, 12145b9c547cSRui Paulo const u8 *kck, size_t kck_len, 1215f05cddf9SRui Paulo const u8 *replay_ctr) 1216f05cddf9SRui Paulo { 1217f05cddf9SRui Paulo struct wpa_supplicant *wpa_s = ctx; 1218f05cddf9SRui Paulo 12195b9c547cSRui Paulo wpa_drv_set_rekey_info(wpa_s, kek, kek_len, kck, kck_len, replay_ctr); 1220f05cddf9SRui Paulo } 1221f05cddf9SRui Paulo 1222f05cddf9SRui Paulo 12235b9c547cSRui Paulo static int wpa_supplicant_key_mgmt_set_pmk(void *ctx, const u8 *pmk, 12245b9c547cSRui Paulo size_t pmk_len) 12255b9c547cSRui Paulo { 12265b9c547cSRui Paulo struct wpa_supplicant *wpa_s = ctx; 12275b9c547cSRui Paulo 1228325151a3SRui Paulo if (wpa_s->conf->key_mgmt_offload && 1229325151a3SRui Paulo (wpa_s->drv_flags & WPA_DRIVER_FLAGS_KEY_MGMT_OFFLOAD)) 1230*c1d255d3SCy Schubert return wpa_drv_set_key(wpa_s, 0, NULL, 0, 0, 1231*c1d255d3SCy Schubert NULL, 0, pmk, pmk_len, KEY_FLAG_PMK); 12325b9c547cSRui Paulo else 12335b9c547cSRui Paulo return 0; 12345b9c547cSRui Paulo } 123585732ac8SCy Schubert 123685732ac8SCy Schubert 123785732ac8SCy Schubert static void wpa_supplicant_fils_hlp_rx(void *ctx, const u8 *dst, const u8 *src, 123885732ac8SCy Schubert const u8 *pkt, size_t pkt_len) 123985732ac8SCy Schubert { 124085732ac8SCy Schubert struct wpa_supplicant *wpa_s = ctx; 124185732ac8SCy Schubert char *hex; 124285732ac8SCy Schubert size_t hexlen; 124385732ac8SCy Schubert 124485732ac8SCy Schubert hexlen = pkt_len * 2 + 1; 124585732ac8SCy Schubert hex = os_malloc(hexlen); 124685732ac8SCy Schubert if (!hex) 124785732ac8SCy Schubert return; 124885732ac8SCy Schubert wpa_snprintf_hex(hex, hexlen, pkt, pkt_len); 124985732ac8SCy Schubert wpa_msg(wpa_s, MSG_INFO, FILS_HLP_RX "dst=" MACSTR " src=" MACSTR 125085732ac8SCy Schubert " frame=%s", MAC2STR(dst), MAC2STR(src), hex); 125185732ac8SCy Schubert os_free(hex); 125285732ac8SCy Schubert } 125385732ac8SCy Schubert 12544bc52338SCy Schubert 12554bc52338SCy Schubert static int wpa_supplicant_channel_info(void *_wpa_s, 12564bc52338SCy Schubert struct wpa_channel_info *ci) 12574bc52338SCy Schubert { 12584bc52338SCy Schubert struct wpa_supplicant *wpa_s = _wpa_s; 12594bc52338SCy Schubert 12604bc52338SCy Schubert return wpa_drv_channel_info(wpa_s, ci); 12614bc52338SCy Schubert } 12624bc52338SCy Schubert 1263*c1d255d3SCy Schubert 1264*c1d255d3SCy Schubert static void disable_wpa_wpa2(struct wpa_ssid *ssid) 1265*c1d255d3SCy Schubert { 1266*c1d255d3SCy Schubert ssid->proto &= ~WPA_PROTO_WPA; 1267*c1d255d3SCy Schubert ssid->proto |= WPA_PROTO_RSN; 1268*c1d255d3SCy Schubert ssid->key_mgmt &= ~(WPA_KEY_MGMT_PSK | WPA_KEY_MGMT_FT_PSK | 1269*c1d255d3SCy Schubert WPA_KEY_MGMT_PSK_SHA256); 1270*c1d255d3SCy Schubert ssid->group_cipher &= ~WPA_CIPHER_TKIP; 1271*c1d255d3SCy Schubert if (!(ssid->group_cipher & (WPA_CIPHER_CCMP | WPA_CIPHER_GCMP | 1272*c1d255d3SCy Schubert WPA_CIPHER_GCMP_256 | WPA_CIPHER_CCMP_256))) 1273*c1d255d3SCy Schubert ssid->group_cipher |= WPA_CIPHER_CCMP; 1274*c1d255d3SCy Schubert ssid->ieee80211w = MGMT_FRAME_PROTECTION_REQUIRED; 1275*c1d255d3SCy Schubert } 1276*c1d255d3SCy Schubert 1277*c1d255d3SCy Schubert 1278*c1d255d3SCy Schubert static void wpa_supplicant_transition_disable(void *_wpa_s, u8 bitmap) 1279*c1d255d3SCy Schubert { 1280*c1d255d3SCy Schubert struct wpa_supplicant *wpa_s = _wpa_s; 1281*c1d255d3SCy Schubert struct wpa_ssid *ssid; 1282*c1d255d3SCy Schubert int changed = 0; 1283*c1d255d3SCy Schubert 1284*c1d255d3SCy Schubert wpa_msg(wpa_s, MSG_INFO, TRANSITION_DISABLE "%02x", bitmap); 1285*c1d255d3SCy Schubert 1286*c1d255d3SCy Schubert ssid = wpa_s->current_ssid; 1287*c1d255d3SCy Schubert if (!ssid) 1288*c1d255d3SCy Schubert return; 1289*c1d255d3SCy Schubert 1290*c1d255d3SCy Schubert #ifdef CONFIG_SAE 1291*c1d255d3SCy Schubert if ((bitmap & TRANSITION_DISABLE_WPA3_PERSONAL) && 1292*c1d255d3SCy Schubert wpa_key_mgmt_sae(wpa_s->key_mgmt) && 1293*c1d255d3SCy Schubert (ssid->key_mgmt & (WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_FT_SAE)) && 1294*c1d255d3SCy Schubert (ssid->ieee80211w != MGMT_FRAME_PROTECTION_REQUIRED || 1295*c1d255d3SCy Schubert (ssid->group_cipher & WPA_CIPHER_TKIP))) { 1296*c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, 1297*c1d255d3SCy Schubert "WPA3-Personal transition mode disabled based on AP notification"); 1298*c1d255d3SCy Schubert disable_wpa_wpa2(ssid); 1299*c1d255d3SCy Schubert changed = 1; 1300*c1d255d3SCy Schubert } 1301*c1d255d3SCy Schubert 1302*c1d255d3SCy Schubert if ((bitmap & TRANSITION_DISABLE_SAE_PK) && 1303*c1d255d3SCy Schubert wpa_key_mgmt_sae(wpa_s->key_mgmt) && 1304*c1d255d3SCy Schubert #ifdef CONFIG_SME 1305*c1d255d3SCy Schubert wpa_s->sme.sae.state == SAE_ACCEPTED && 1306*c1d255d3SCy Schubert wpa_s->sme.sae.pk && 1307*c1d255d3SCy Schubert #endif /* CONFIG_SME */ 1308*c1d255d3SCy Schubert (ssid->key_mgmt & (WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_FT_SAE)) && 1309*c1d255d3SCy Schubert (ssid->sae_pk != SAE_PK_MODE_ONLY || 1310*c1d255d3SCy Schubert ssid->ieee80211w != MGMT_FRAME_PROTECTION_REQUIRED || 1311*c1d255d3SCy Schubert (ssid->group_cipher & WPA_CIPHER_TKIP))) { 1312*c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, 1313*c1d255d3SCy Schubert "SAE-PK: SAE authentication without PK disabled based on AP notification"); 1314*c1d255d3SCy Schubert disable_wpa_wpa2(ssid); 1315*c1d255d3SCy Schubert ssid->sae_pk = SAE_PK_MODE_ONLY; 1316*c1d255d3SCy Schubert changed = 1; 1317*c1d255d3SCy Schubert } 1318*c1d255d3SCy Schubert #endif /* CONFIG_SAE */ 1319*c1d255d3SCy Schubert 1320*c1d255d3SCy Schubert if ((bitmap & TRANSITION_DISABLE_WPA3_ENTERPRISE) && 1321*c1d255d3SCy Schubert wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) && 1322*c1d255d3SCy Schubert (ssid->key_mgmt & (WPA_KEY_MGMT_IEEE8021X | 1323*c1d255d3SCy Schubert WPA_KEY_MGMT_FT_IEEE8021X | 1324*c1d255d3SCy Schubert WPA_KEY_MGMT_IEEE8021X_SHA256)) && 1325*c1d255d3SCy Schubert (ssid->ieee80211w != MGMT_FRAME_PROTECTION_REQUIRED || 1326*c1d255d3SCy Schubert (ssid->group_cipher & WPA_CIPHER_TKIP))) { 1327*c1d255d3SCy Schubert disable_wpa_wpa2(ssid); 1328*c1d255d3SCy Schubert changed = 1; 1329*c1d255d3SCy Schubert } 1330*c1d255d3SCy Schubert 1331*c1d255d3SCy Schubert if ((bitmap & TRANSITION_DISABLE_ENHANCED_OPEN) && 1332*c1d255d3SCy Schubert wpa_s->key_mgmt == WPA_KEY_MGMT_OWE && 1333*c1d255d3SCy Schubert (ssid->key_mgmt & WPA_KEY_MGMT_OWE) && 1334*c1d255d3SCy Schubert !ssid->owe_only) { 1335*c1d255d3SCy Schubert ssid->owe_only = 1; 1336*c1d255d3SCy Schubert changed = 1; 1337*c1d255d3SCy Schubert } 1338*c1d255d3SCy Schubert 1339*c1d255d3SCy Schubert if (!changed) 1340*c1d255d3SCy Schubert return; 1341*c1d255d3SCy Schubert 1342*c1d255d3SCy Schubert #ifndef CONFIG_NO_CONFIG_WRITE 1343*c1d255d3SCy Schubert if (wpa_s->conf->update_config && 1344*c1d255d3SCy Schubert wpa_config_write(wpa_s->confname, wpa_s->conf)) 1345*c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, "Failed to update configuration"); 1346*c1d255d3SCy Schubert #endif /* CONFIG_NO_CONFIG_WRITE */ 1347*c1d255d3SCy Schubert } 1348*c1d255d3SCy Schubert 1349*c1d255d3SCy Schubert 1350*c1d255d3SCy Schubert static void wpa_supplicant_store_ptk(void *ctx, u8 *addr, int cipher, 1351*c1d255d3SCy Schubert u32 life_time, const struct wpa_ptk *ptk) 1352*c1d255d3SCy Schubert { 1353*c1d255d3SCy Schubert struct wpa_supplicant *wpa_s = ctx; 1354*c1d255d3SCy Schubert 1355*c1d255d3SCy Schubert ptksa_cache_add(wpa_s->ptksa, addr, cipher, life_time, ptk); 1356*c1d255d3SCy Schubert } 1357*c1d255d3SCy Schubert 1358780fb4a2SCy Schubert #endif /* CONFIG_NO_WPA */ 13595b9c547cSRui Paulo 13605b9c547cSRui Paulo 136139beb93cSSam Leffler int wpa_supplicant_init_wpa(struct wpa_supplicant *wpa_s) 136239beb93cSSam Leffler { 136339beb93cSSam Leffler #ifndef CONFIG_NO_WPA 136439beb93cSSam Leffler struct wpa_sm_ctx *ctx; 1365*c1d255d3SCy Schubert 1366*c1d255d3SCy Schubert wpa_s->ptksa = ptksa_cache_init(); 1367*c1d255d3SCy Schubert if (!wpa_s->ptksa) { 1368*c1d255d3SCy Schubert wpa_printf(MSG_ERROR, "Failed to allocate PTKSA"); 1369*c1d255d3SCy Schubert return -1; 1370*c1d255d3SCy Schubert } 1371*c1d255d3SCy Schubert 137239beb93cSSam Leffler ctx = os_zalloc(sizeof(*ctx)); 137339beb93cSSam Leffler if (ctx == NULL) { 137439beb93cSSam Leffler wpa_printf(MSG_ERROR, "Failed to allocate WPA context."); 1375*c1d255d3SCy Schubert 1376*c1d255d3SCy Schubert ptksa_cache_deinit(wpa_s->ptksa); 1377*c1d255d3SCy Schubert wpa_s->ptksa = NULL; 1378*c1d255d3SCy Schubert 137939beb93cSSam Leffler return -1; 138039beb93cSSam Leffler } 138139beb93cSSam Leffler 138239beb93cSSam Leffler ctx->ctx = wpa_s; 1383e28a4053SRui Paulo ctx->msg_ctx = wpa_s; 138439beb93cSSam Leffler ctx->set_state = _wpa_supplicant_set_state; 138539beb93cSSam Leffler ctx->get_state = _wpa_supplicant_get_state; 138639beb93cSSam Leffler ctx->deauthenticate = _wpa_supplicant_deauthenticate; 1387*c1d255d3SCy Schubert ctx->reconnect = _wpa_supplicant_reconnect; 138839beb93cSSam Leffler ctx->set_key = wpa_supplicant_set_key; 138939beb93cSSam Leffler ctx->get_network_ctx = wpa_supplicant_get_network_ctx; 139039beb93cSSam Leffler ctx->get_bssid = wpa_supplicant_get_bssid; 139139beb93cSSam Leffler ctx->ether_send = _wpa_ether_send; 139239beb93cSSam Leffler ctx->get_beacon_ie = wpa_supplicant_get_beacon_ie; 139339beb93cSSam Leffler ctx->alloc_eapol = _wpa_alloc_eapol; 139439beb93cSSam Leffler ctx->cancel_auth_timeout = _wpa_supplicant_cancel_auth_timeout; 139539beb93cSSam Leffler ctx->add_pmkid = wpa_supplicant_add_pmkid; 139639beb93cSSam Leffler ctx->remove_pmkid = wpa_supplicant_remove_pmkid; 139739beb93cSSam Leffler #ifndef CONFIG_NO_CONFIG_BLOBS 139839beb93cSSam Leffler ctx->set_config_blob = wpa_supplicant_set_config_blob; 139939beb93cSSam Leffler ctx->get_config_blob = wpa_supplicant_get_config_blob; 140039beb93cSSam Leffler #endif /* CONFIG_NO_CONFIG_BLOBS */ 140139beb93cSSam Leffler ctx->mlme_setprotection = wpa_supplicant_mlme_setprotection; 140239beb93cSSam Leffler #ifdef CONFIG_IEEE80211R 140339beb93cSSam Leffler ctx->update_ft_ies = wpa_supplicant_update_ft_ies; 140439beb93cSSam Leffler ctx->send_ft_action = wpa_supplicant_send_ft_action; 1405e28a4053SRui Paulo ctx->mark_authenticated = wpa_supplicant_mark_authenticated; 140639beb93cSSam Leffler #endif /* CONFIG_IEEE80211R */ 1407f05cddf9SRui Paulo #ifdef CONFIG_TDLS 1408f05cddf9SRui Paulo ctx->tdls_get_capa = wpa_supplicant_tdls_get_capa; 1409f05cddf9SRui Paulo ctx->send_tdls_mgmt = wpa_supplicant_send_tdls_mgmt; 1410f05cddf9SRui Paulo ctx->tdls_oper = wpa_supplicant_tdls_oper; 1411f05cddf9SRui Paulo ctx->tdls_peer_addset = wpa_supplicant_tdls_peer_addset; 14125b9c547cSRui Paulo ctx->tdls_enable_channel_switch = 14135b9c547cSRui Paulo wpa_supplicant_tdls_enable_channel_switch; 14145b9c547cSRui Paulo ctx->tdls_disable_channel_switch = 14155b9c547cSRui Paulo wpa_supplicant_tdls_disable_channel_switch; 1416f05cddf9SRui Paulo #endif /* CONFIG_TDLS */ 1417f05cddf9SRui Paulo ctx->set_rekey_offload = wpa_supplicant_set_rekey_offload; 14185b9c547cSRui Paulo ctx->key_mgmt_set_pmk = wpa_supplicant_key_mgmt_set_pmk; 141985732ac8SCy Schubert ctx->fils_hlp_rx = wpa_supplicant_fils_hlp_rx; 14204bc52338SCy Schubert ctx->channel_info = wpa_supplicant_channel_info; 1421*c1d255d3SCy Schubert ctx->transition_disable = wpa_supplicant_transition_disable; 1422*c1d255d3SCy Schubert ctx->store_ptk = wpa_supplicant_store_ptk; 142339beb93cSSam Leffler 142439beb93cSSam Leffler wpa_s->wpa = wpa_sm_init(ctx); 142539beb93cSSam Leffler if (wpa_s->wpa == NULL) { 1426*c1d255d3SCy Schubert wpa_printf(MSG_ERROR, 1427*c1d255d3SCy Schubert "Failed to initialize WPA state machine"); 14285b9c547cSRui Paulo os_free(ctx); 1429*c1d255d3SCy Schubert ptksa_cache_deinit(wpa_s->ptksa); 1430*c1d255d3SCy Schubert wpa_s->ptksa = NULL; 143139beb93cSSam Leffler return -1; 143239beb93cSSam Leffler } 143339beb93cSSam Leffler #endif /* CONFIG_NO_WPA */ 143439beb93cSSam Leffler 143539beb93cSSam Leffler return 0; 143639beb93cSSam Leffler } 143739beb93cSSam Leffler 143839beb93cSSam Leffler 143939beb93cSSam Leffler void wpa_supplicant_rsn_supp_set_config(struct wpa_supplicant *wpa_s, 144039beb93cSSam Leffler struct wpa_ssid *ssid) 144139beb93cSSam Leffler { 144239beb93cSSam Leffler struct rsn_supp_config conf; 144339beb93cSSam Leffler if (ssid) { 144439beb93cSSam Leffler os_memset(&conf, 0, sizeof(conf)); 144539beb93cSSam Leffler conf.network_ctx = ssid; 144639beb93cSSam Leffler conf.allowed_pairwise_cipher = ssid->pairwise_cipher; 144739beb93cSSam Leffler #ifdef IEEE8021X_EAPOL 1448f05cddf9SRui Paulo conf.proactive_key_caching = ssid->proactive_key_caching < 0 ? 1449f05cddf9SRui Paulo wpa_s->conf->okc : ssid->proactive_key_caching; 145039beb93cSSam Leffler conf.eap_workaround = ssid->eap_workaround; 145139beb93cSSam Leffler conf.eap_conf_ctx = &ssid->eap; 145239beb93cSSam Leffler #endif /* IEEE8021X_EAPOL */ 145339beb93cSSam Leffler conf.ssid = ssid->ssid; 145439beb93cSSam Leffler conf.ssid_len = ssid->ssid_len; 145539beb93cSSam Leffler conf.wpa_ptk_rekey = ssid->wpa_ptk_rekey; 1456*c1d255d3SCy Schubert conf.wpa_deny_ptk0_rekey = ssid->wpa_deny_ptk0_rekey; 1457*c1d255d3SCy Schubert conf.owe_ptk_workaround = ssid->owe_ptk_workaround; 14585b9c547cSRui Paulo #ifdef CONFIG_P2P 14595b9c547cSRui Paulo if (ssid->p2p_group && wpa_s->current_bss && 14605b9c547cSRui Paulo !wpa_s->p2p_disable_ip_addr_req) { 14615b9c547cSRui Paulo struct wpabuf *p2p; 14625b9c547cSRui Paulo p2p = wpa_bss_get_vendor_ie_multi(wpa_s->current_bss, 14635b9c547cSRui Paulo P2P_IE_VENDOR_TYPE); 14645b9c547cSRui Paulo if (p2p) { 14655b9c547cSRui Paulo u8 group_capab; 14665b9c547cSRui Paulo group_capab = p2p_get_group_capab(p2p); 14675b9c547cSRui Paulo if (group_capab & 14685b9c547cSRui Paulo P2P_GROUP_CAPAB_IP_ADDR_ALLOCATION) 14695b9c547cSRui Paulo conf.p2p = 1; 14705b9c547cSRui Paulo wpabuf_free(p2p); 14715b9c547cSRui Paulo } 14725b9c547cSRui Paulo } 14735b9c547cSRui Paulo #endif /* CONFIG_P2P */ 1474780fb4a2SCy Schubert conf.wpa_rsc_relaxation = wpa_s->conf->wpa_rsc_relaxation; 147585732ac8SCy Schubert #ifdef CONFIG_FILS 147685732ac8SCy Schubert if (wpa_key_mgmt_fils(wpa_s->key_mgmt)) 147785732ac8SCy Schubert conf.fils_cache_id = 147885732ac8SCy Schubert wpa_bss_get_fils_cache_id(wpa_s->current_bss); 147985732ac8SCy Schubert #endif /* CONFIG_FILS */ 1480*c1d255d3SCy Schubert if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_BEACON_PROTECTION) || 1481*c1d255d3SCy Schubert (wpa_s->drv_flags2 & 1482*c1d255d3SCy Schubert WPA_DRIVER_FLAGS2_BEACON_PROTECTION_CLIENT)) 1483*c1d255d3SCy Schubert conf.beacon_prot = ssid->beacon_prot; 1484*c1d255d3SCy Schubert 1485*c1d255d3SCy Schubert #ifdef CONFIG_PASN 1486*c1d255d3SCy Schubert #ifdef CONFIG_TESTING_OPTIONS 1487*c1d255d3SCy Schubert conf.force_kdk_derivation = wpa_s->conf->force_kdk_derivation; 1488*c1d255d3SCy Schubert #endif /* CONFIG_TESTING_OPTIONS */ 1489*c1d255d3SCy Schubert #endif /* CONFIG_PASN */ 149039beb93cSSam Leffler } 149139beb93cSSam Leffler wpa_sm_set_config(wpa_s->wpa, ssid ? &conf : NULL); 149239beb93cSSam Leffler } 1493