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" 13*85732ac8SCy 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" 1939beb93cSSam Leffler #include "wpa_supplicant_i.h" 20e28a4053SRui Paulo #include "driver_i.h" 21e28a4053SRui Paulo #include "rsn_supp/pmksa_cache.h" 22e28a4053SRui Paulo #include "sme.h" 23e28a4053SRui Paulo #include "common/ieee802_11_defs.h" 24e28a4053SRui Paulo #include "common/wpa_ctrl.h" 2539beb93cSSam Leffler #include "wpas_glue.h" 2639beb93cSSam Leffler #include "wps_supplicant.h" 27e28a4053SRui Paulo #include "bss.h" 28e28a4053SRui Paulo #include "scan.h" 29f05cddf9SRui Paulo #include "notify.h" 305b9c547cSRui Paulo #include "wpas_kay.h" 3139beb93cSSam Leffler 3239beb93cSSam Leffler 3339beb93cSSam Leffler #ifndef CONFIG_NO_CONFIG_BLOBS 3439beb93cSSam Leffler #if defined(IEEE8021X_EAPOL) || !defined(CONFIG_NO_WPA) 3539beb93cSSam Leffler static void wpa_supplicant_set_config_blob(void *ctx, 3639beb93cSSam Leffler struct wpa_config_blob *blob) 3739beb93cSSam Leffler { 3839beb93cSSam Leffler struct wpa_supplicant *wpa_s = ctx; 3939beb93cSSam Leffler wpa_config_set_blob(wpa_s->conf, blob); 4039beb93cSSam Leffler if (wpa_s->conf->update_config) { 4139beb93cSSam Leffler int ret = wpa_config_write(wpa_s->confname, wpa_s->conf); 4239beb93cSSam Leffler if (ret) { 4339beb93cSSam Leffler wpa_printf(MSG_DEBUG, "Failed to update config after " 4439beb93cSSam Leffler "blob set"); 4539beb93cSSam Leffler } 4639beb93cSSam Leffler } 4739beb93cSSam Leffler } 4839beb93cSSam Leffler 4939beb93cSSam Leffler 5039beb93cSSam Leffler static const struct wpa_config_blob * 5139beb93cSSam Leffler wpa_supplicant_get_config_blob(void *ctx, const char *name) 5239beb93cSSam Leffler { 5339beb93cSSam Leffler struct wpa_supplicant *wpa_s = ctx; 5439beb93cSSam Leffler return wpa_config_get_blob(wpa_s->conf, name); 5539beb93cSSam Leffler } 5639beb93cSSam Leffler #endif /* defined(IEEE8021X_EAPOL) || !defined(CONFIG_NO_WPA) */ 5739beb93cSSam Leffler #endif /* CONFIG_NO_CONFIG_BLOBS */ 5839beb93cSSam Leffler 5939beb93cSSam Leffler 6039beb93cSSam Leffler #if defined(IEEE8021X_EAPOL) || !defined(CONFIG_NO_WPA) 6139beb93cSSam Leffler static u8 * wpa_alloc_eapol(const struct wpa_supplicant *wpa_s, u8 type, 6239beb93cSSam Leffler const void *data, u16 data_len, 6339beb93cSSam Leffler size_t *msg_len, void **data_pos) 6439beb93cSSam Leffler { 6539beb93cSSam Leffler struct ieee802_1x_hdr *hdr; 6639beb93cSSam Leffler 6739beb93cSSam Leffler *msg_len = sizeof(*hdr) + data_len; 6839beb93cSSam Leffler hdr = os_malloc(*msg_len); 6939beb93cSSam Leffler if (hdr == NULL) 7039beb93cSSam Leffler return NULL; 7139beb93cSSam Leffler 7239beb93cSSam Leffler hdr->version = wpa_s->conf->eapol_version; 7339beb93cSSam Leffler hdr->type = type; 7439beb93cSSam Leffler hdr->length = host_to_be16(data_len); 7539beb93cSSam Leffler 7639beb93cSSam Leffler if (data) 7739beb93cSSam Leffler os_memcpy(hdr + 1, data, data_len); 7839beb93cSSam Leffler else 7939beb93cSSam Leffler os_memset(hdr + 1, 0, data_len); 8039beb93cSSam Leffler 8139beb93cSSam Leffler if (data_pos) 8239beb93cSSam Leffler *data_pos = hdr + 1; 8339beb93cSSam Leffler 8439beb93cSSam Leffler return (u8 *) hdr; 8539beb93cSSam Leffler } 8639beb93cSSam Leffler 8739beb93cSSam Leffler 8839beb93cSSam Leffler /** 8939beb93cSSam Leffler * wpa_ether_send - Send Ethernet frame 9039beb93cSSam Leffler * @wpa_s: Pointer to wpa_supplicant data 9139beb93cSSam Leffler * @dest: Destination MAC address 9239beb93cSSam Leffler * @proto: Ethertype in host byte order 9339beb93cSSam Leffler * @buf: Frame payload starting from IEEE 802.1X header 9439beb93cSSam Leffler * @len: Frame payload length 9539beb93cSSam Leffler * Returns: >=0 on success, <0 on failure 9639beb93cSSam Leffler */ 9739beb93cSSam Leffler static int wpa_ether_send(struct wpa_supplicant *wpa_s, const u8 *dest, 9839beb93cSSam Leffler u16 proto, const u8 *buf, size_t len) 9939beb93cSSam Leffler { 1005b9c547cSRui Paulo #ifdef CONFIG_TESTING_OPTIONS 1015b9c547cSRui Paulo if (wpa_s->ext_eapol_frame_io && proto == ETH_P_EAPOL) { 1025b9c547cSRui Paulo size_t hex_len = 2 * len + 1; 1035b9c547cSRui Paulo char *hex = os_malloc(hex_len); 1045b9c547cSRui Paulo 1055b9c547cSRui Paulo if (hex == NULL) 1065b9c547cSRui Paulo return -1; 1075b9c547cSRui Paulo wpa_snprintf_hex(hex, hex_len, buf, len); 1085b9c547cSRui Paulo wpa_msg(wpa_s, MSG_INFO, "EAPOL-TX " MACSTR " %s", 1095b9c547cSRui Paulo MAC2STR(dest), hex); 1105b9c547cSRui Paulo os_free(hex); 1115b9c547cSRui Paulo return 0; 1125b9c547cSRui Paulo } 1135b9c547cSRui Paulo #endif /* CONFIG_TESTING_OPTIONS */ 1145b9c547cSRui Paulo 11539beb93cSSam Leffler if (wpa_s->l2) { 11639beb93cSSam Leffler return l2_packet_send(wpa_s->l2, dest, proto, buf, len); 11739beb93cSSam Leffler } 11839beb93cSSam Leffler 1195b9c547cSRui Paulo return -1; 12039beb93cSSam Leffler } 12139beb93cSSam Leffler #endif /* IEEE8021X_EAPOL || !CONFIG_NO_WPA */ 12239beb93cSSam Leffler 12339beb93cSSam Leffler 12439beb93cSSam Leffler #ifdef IEEE8021X_EAPOL 12539beb93cSSam Leffler 12639beb93cSSam Leffler /** 12739beb93cSSam Leffler * wpa_supplicant_eapol_send - Send IEEE 802.1X EAPOL packet to Authenticator 12839beb93cSSam Leffler * @ctx: Pointer to wpa_supplicant data (wpa_s) 12939beb93cSSam Leffler * @type: IEEE 802.1X packet type (IEEE802_1X_TYPE_*) 13039beb93cSSam Leffler * @buf: EAPOL payload (after IEEE 802.1X header) 13139beb93cSSam Leffler * @len: EAPOL payload length 13239beb93cSSam Leffler * Returns: >=0 on success, <0 on failure 13339beb93cSSam Leffler * 13439beb93cSSam Leffler * This function adds Ethernet and IEEE 802.1X header and sends the EAPOL frame 13539beb93cSSam Leffler * to the current Authenticator. 13639beb93cSSam Leffler */ 13739beb93cSSam Leffler static int wpa_supplicant_eapol_send(void *ctx, int type, const u8 *buf, 13839beb93cSSam Leffler size_t len) 13939beb93cSSam Leffler { 14039beb93cSSam Leffler struct wpa_supplicant *wpa_s = ctx; 14139beb93cSSam Leffler u8 *msg, *dst, bssid[ETH_ALEN]; 14239beb93cSSam Leffler size_t msglen; 14339beb93cSSam Leffler int res; 14439beb93cSSam Leffler 14539beb93cSSam Leffler /* TODO: could add l2_packet_sendmsg that allows fragments to avoid 14639beb93cSSam Leffler * extra copy here */ 14739beb93cSSam Leffler 14839beb93cSSam Leffler if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) || 149*85732ac8SCy Schubert wpa_s->key_mgmt == WPA_KEY_MGMT_OWE || 150*85732ac8SCy Schubert wpa_s->key_mgmt == WPA_KEY_MGMT_DPP || 15139beb93cSSam Leffler wpa_s->key_mgmt == WPA_KEY_MGMT_NONE) { 15239beb93cSSam Leffler /* Current SSID is not using IEEE 802.1X/EAP, so drop possible 15339beb93cSSam Leffler * EAPOL frames (mainly, EAPOL-Start) from EAPOL state 15439beb93cSSam Leffler * machines. */ 15539beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPA: drop TX EAPOL in non-IEEE 802.1X " 15639beb93cSSam Leffler "mode (type=%d len=%lu)", type, 15739beb93cSSam Leffler (unsigned long) len); 15839beb93cSSam Leffler return -1; 15939beb93cSSam Leffler } 16039beb93cSSam Leffler 16139beb93cSSam Leffler if (pmksa_cache_get_current(wpa_s->wpa) && 16239beb93cSSam Leffler type == IEEE802_1X_TYPE_EAPOL_START) { 1635b9c547cSRui Paulo /* 1645b9c547cSRui Paulo * We were trying to use PMKSA caching and sending EAPOL-Start 1655b9c547cSRui Paulo * would abort that and trigger full EAPOL authentication. 1665b9c547cSRui Paulo * However, we've already waited for the AP/Authenticator to 1675b9c547cSRui Paulo * start 4-way handshake or EAP authentication, and apparently 1685b9c547cSRui Paulo * it has not done so since the startWhen timer has reached zero 1695b9c547cSRui Paulo * to get the state machine sending EAPOL-Start. This is not 1705b9c547cSRui Paulo * really supposed to happen, but an interoperability issue with 1715b9c547cSRui Paulo * a deployed AP has been identified where the connection fails 1725b9c547cSRui Paulo * due to that AP failing to operate correctly if PMKID is 1735b9c547cSRui Paulo * included in the Association Request frame. To work around 1745b9c547cSRui Paulo * this, assume PMKSA caching failed and try to initiate full 1755b9c547cSRui Paulo * EAP authentication. 1765b9c547cSRui Paulo */ 1775b9c547cSRui Paulo if (!wpa_s->current_ssid || 1785b9c547cSRui Paulo wpa_s->current_ssid->eap_workaround) { 1795b9c547cSRui Paulo wpa_printf(MSG_DEBUG, 1805b9c547cSRui 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"); 1815b9c547cSRui Paulo } else { 1825b9c547cSRui Paulo wpa_printf(MSG_DEBUG, 1835b9c547cSRui Paulo "RSN: PMKSA caching - do not send EAPOL-Start"); 18439beb93cSSam Leffler return -1; 18539beb93cSSam Leffler } 1865b9c547cSRui Paulo } 18739beb93cSSam Leffler 18839beb93cSSam Leffler if (is_zero_ether_addr(wpa_s->bssid)) { 18939beb93cSSam Leffler wpa_printf(MSG_DEBUG, "BSSID not set when trying to send an " 19039beb93cSSam Leffler "EAPOL frame"); 19139beb93cSSam Leffler if (wpa_drv_get_bssid(wpa_s, bssid) == 0 && 19239beb93cSSam Leffler !is_zero_ether_addr(bssid)) { 19339beb93cSSam Leffler dst = bssid; 19439beb93cSSam Leffler wpa_printf(MSG_DEBUG, "Using current BSSID " MACSTR 19539beb93cSSam Leffler " from the driver as the EAPOL destination", 19639beb93cSSam Leffler MAC2STR(dst)); 19739beb93cSSam Leffler } else { 19839beb93cSSam Leffler dst = wpa_s->last_eapol_src; 19939beb93cSSam Leffler wpa_printf(MSG_DEBUG, "Using the source address of the" 20039beb93cSSam Leffler " last received EAPOL frame " MACSTR " as " 20139beb93cSSam Leffler "the EAPOL destination", 20239beb93cSSam Leffler MAC2STR(dst)); 20339beb93cSSam Leffler } 20439beb93cSSam Leffler } else { 20539beb93cSSam Leffler /* BSSID was already set (from (Re)Assoc event, so use it as 20639beb93cSSam Leffler * the EAPOL destination. */ 20739beb93cSSam Leffler dst = wpa_s->bssid; 20839beb93cSSam Leffler } 20939beb93cSSam Leffler 21039beb93cSSam Leffler msg = wpa_alloc_eapol(wpa_s, type, buf, len, &msglen, NULL); 21139beb93cSSam Leffler if (msg == NULL) 21239beb93cSSam Leffler return -1; 21339beb93cSSam Leffler 21439beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TX EAPOL: dst=" MACSTR, MAC2STR(dst)); 21539beb93cSSam Leffler wpa_hexdump(MSG_MSGDUMP, "TX EAPOL", msg, msglen); 21639beb93cSSam Leffler res = wpa_ether_send(wpa_s, dst, ETH_P_EAPOL, msg, msglen); 21739beb93cSSam Leffler os_free(msg); 21839beb93cSSam Leffler return res; 21939beb93cSSam Leffler } 22039beb93cSSam Leffler 22139beb93cSSam Leffler 22239beb93cSSam Leffler /** 22339beb93cSSam Leffler * wpa_eapol_set_wep_key - set WEP key for the driver 22439beb93cSSam Leffler * @ctx: Pointer to wpa_supplicant data (wpa_s) 22539beb93cSSam Leffler * @unicast: 1 = individual unicast key, 0 = broadcast key 22639beb93cSSam Leffler * @keyidx: WEP key index (0..3) 22739beb93cSSam Leffler * @key: Pointer to key data 22839beb93cSSam Leffler * @keylen: Key length in bytes 22939beb93cSSam Leffler * Returns: 0 on success or < 0 on error. 23039beb93cSSam Leffler */ 23139beb93cSSam Leffler static int wpa_eapol_set_wep_key(void *ctx, int unicast, int keyidx, 23239beb93cSSam Leffler const u8 *key, size_t keylen) 23339beb93cSSam Leffler { 23439beb93cSSam Leffler struct wpa_supplicant *wpa_s = ctx; 23539beb93cSSam Leffler if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) { 23639beb93cSSam Leffler int cipher = (keylen == 5) ? WPA_CIPHER_WEP40 : 23739beb93cSSam Leffler WPA_CIPHER_WEP104; 23839beb93cSSam Leffler if (unicast) 23939beb93cSSam Leffler wpa_s->pairwise_cipher = cipher; 24039beb93cSSam Leffler else 24139beb93cSSam Leffler wpa_s->group_cipher = cipher; 24239beb93cSSam Leffler } 24339beb93cSSam Leffler return wpa_drv_set_key(wpa_s, WPA_ALG_WEP, 244f05cddf9SRui Paulo unicast ? wpa_s->bssid : NULL, 245f05cddf9SRui Paulo keyidx, unicast, NULL, 0, key, keylen); 24639beb93cSSam Leffler } 24739beb93cSSam Leffler 24839beb93cSSam Leffler 24939beb93cSSam Leffler static void wpa_supplicant_aborted_cached(void *ctx) 25039beb93cSSam Leffler { 25139beb93cSSam Leffler struct wpa_supplicant *wpa_s = ctx; 25239beb93cSSam Leffler wpa_sm_aborted_cached(wpa_s->wpa); 25339beb93cSSam Leffler } 25439beb93cSSam Leffler 25539beb93cSSam Leffler 2565b9c547cSRui Paulo static const char * result_str(enum eapol_supp_result result) 2575b9c547cSRui Paulo { 2585b9c547cSRui Paulo switch (result) { 2595b9c547cSRui Paulo case EAPOL_SUPP_RESULT_FAILURE: 2605b9c547cSRui Paulo return "FAILURE"; 2615b9c547cSRui Paulo case EAPOL_SUPP_RESULT_SUCCESS: 2625b9c547cSRui Paulo return "SUCCESS"; 2635b9c547cSRui Paulo case EAPOL_SUPP_RESULT_EXPECTED_FAILURE: 2645b9c547cSRui Paulo return "EXPECTED_FAILURE"; 2655b9c547cSRui Paulo } 2665b9c547cSRui Paulo return "?"; 2675b9c547cSRui Paulo } 2685b9c547cSRui Paulo 2695b9c547cSRui Paulo 2705b9c547cSRui Paulo static void wpa_supplicant_eapol_cb(struct eapol_sm *eapol, 2715b9c547cSRui Paulo enum eapol_supp_result result, 27239beb93cSSam Leffler void *ctx) 27339beb93cSSam Leffler { 27439beb93cSSam Leffler struct wpa_supplicant *wpa_s = ctx; 27539beb93cSSam Leffler int res, pmk_len; 27639beb93cSSam Leffler u8 pmk[PMK_LEN]; 27739beb93cSSam Leffler 2785b9c547cSRui Paulo wpa_printf(MSG_DEBUG, "EAPOL authentication completed - result=%s", 2795b9c547cSRui Paulo result_str(result)); 28039beb93cSSam Leffler 28139beb93cSSam Leffler if (wpas_wps_eapol_cb(wpa_s) > 0) 28239beb93cSSam Leffler return; 28339beb93cSSam Leffler 2845b9c547cSRui Paulo wpa_s->eap_expected_failure = result == 2855b9c547cSRui Paulo EAPOL_SUPP_RESULT_EXPECTED_FAILURE; 2865b9c547cSRui Paulo 2875b9c547cSRui Paulo if (result != EAPOL_SUPP_RESULT_SUCCESS) { 28839beb93cSSam Leffler /* 28939beb93cSSam Leffler * Make sure we do not get stuck here waiting for long EAPOL 29039beb93cSSam Leffler * timeout if the AP does not disconnect in case of 29139beb93cSSam Leffler * authentication failure. 29239beb93cSSam Leffler */ 29339beb93cSSam Leffler wpa_supplicant_req_auth_timeout(wpa_s, 2, 0); 2945b9c547cSRui Paulo } else { 2955b9c547cSRui Paulo ieee802_1x_notify_create_actor(wpa_s, wpa_s->last_eapol_src); 29639beb93cSSam Leffler } 29739beb93cSSam Leffler 2985b9c547cSRui Paulo if (result != EAPOL_SUPP_RESULT_SUCCESS || 2995b9c547cSRui Paulo !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE)) 30039beb93cSSam Leffler return; 30139beb93cSSam Leffler 30239beb93cSSam Leffler if (!wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) 30339beb93cSSam Leffler return; 30439beb93cSSam Leffler 30539beb93cSSam Leffler wpa_printf(MSG_DEBUG, "Configure PMK for driver-based RSN 4-way " 30639beb93cSSam Leffler "handshake"); 30739beb93cSSam Leffler 30839beb93cSSam Leffler pmk_len = PMK_LEN; 309f05cddf9SRui Paulo if (wpa_key_mgmt_ft(wpa_s->key_mgmt)) { 310f05cddf9SRui Paulo #ifdef CONFIG_IEEE80211R 311f05cddf9SRui Paulo u8 buf[2 * PMK_LEN]; 312f05cddf9SRui Paulo wpa_printf(MSG_DEBUG, "RSN: Use FT XXKey as PMK for " 313f05cddf9SRui Paulo "driver-based 4-way hs and FT"); 314f05cddf9SRui Paulo res = eapol_sm_get_key(eapol, buf, 2 * PMK_LEN); 315f05cddf9SRui Paulo if (res == 0) { 316f05cddf9SRui Paulo os_memcpy(pmk, buf + PMK_LEN, PMK_LEN); 317f05cddf9SRui Paulo os_memset(buf, 0, sizeof(buf)); 318f05cddf9SRui Paulo } 319f05cddf9SRui Paulo #else /* CONFIG_IEEE80211R */ 320f05cddf9SRui Paulo res = -1; 321f05cddf9SRui Paulo #endif /* CONFIG_IEEE80211R */ 322f05cddf9SRui Paulo } else { 32339beb93cSSam Leffler res = eapol_sm_get_key(eapol, pmk, PMK_LEN); 32439beb93cSSam Leffler if (res) { 32539beb93cSSam Leffler /* 32639beb93cSSam Leffler * EAP-LEAP is an exception from other EAP methods: it 32739beb93cSSam Leffler * uses only 16-byte PMK. 32839beb93cSSam Leffler */ 32939beb93cSSam Leffler res = eapol_sm_get_key(eapol, pmk, 16); 33039beb93cSSam Leffler pmk_len = 16; 33139beb93cSSam Leffler } 332f05cddf9SRui Paulo } 33339beb93cSSam Leffler 33439beb93cSSam Leffler if (res) { 33539beb93cSSam Leffler wpa_printf(MSG_DEBUG, "Failed to get PMK from EAPOL state " 33639beb93cSSam Leffler "machines"); 33739beb93cSSam Leffler return; 33839beb93cSSam Leffler } 33939beb93cSSam Leffler 340f05cddf9SRui Paulo wpa_hexdump_key(MSG_DEBUG, "RSN: Configure PMK for driver-based 4-way " 341f05cddf9SRui Paulo "handshake", pmk, pmk_len); 342f05cddf9SRui Paulo 34339beb93cSSam Leffler if (wpa_drv_set_key(wpa_s, WPA_ALG_PMK, NULL, 0, 0, NULL, 0, pmk, 34439beb93cSSam Leffler pmk_len)) { 34539beb93cSSam Leffler wpa_printf(MSG_DEBUG, "Failed to set PMK to the driver"); 34639beb93cSSam Leffler } 34739beb93cSSam Leffler 34839beb93cSSam Leffler wpa_supplicant_cancel_scan(wpa_s); 34939beb93cSSam Leffler wpa_supplicant_cancel_auth_timeout(wpa_s); 35039beb93cSSam Leffler wpa_supplicant_set_state(wpa_s, WPA_COMPLETED); 35139beb93cSSam Leffler 35239beb93cSSam Leffler } 35339beb93cSSam Leffler 35439beb93cSSam Leffler 35539beb93cSSam Leffler static void wpa_supplicant_notify_eapol_done(void *ctx) 35639beb93cSSam Leffler { 35739beb93cSSam Leffler struct wpa_supplicant *wpa_s = ctx; 35839beb93cSSam Leffler wpa_msg(wpa_s, MSG_DEBUG, "WPA: EAPOL processing complete"); 35939beb93cSSam Leffler if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) { 36039beb93cSSam Leffler wpa_supplicant_set_state(wpa_s, WPA_4WAY_HANDSHAKE); 36139beb93cSSam Leffler } else { 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 #endif /* IEEE8021X_EAPOL */ 36839beb93cSSam Leffler 36939beb93cSSam Leffler 37039beb93cSSam Leffler #ifndef CONFIG_NO_WPA 37139beb93cSSam Leffler 37239beb93cSSam Leffler static int wpa_get_beacon_ie(struct wpa_supplicant *wpa_s) 37339beb93cSSam Leffler { 37439beb93cSSam Leffler int ret = 0; 375e28a4053SRui Paulo struct wpa_bss *curr = NULL, *bss; 37639beb93cSSam Leffler struct wpa_ssid *ssid = wpa_s->current_ssid; 37739beb93cSSam Leffler const u8 *ie; 37839beb93cSSam Leffler 379e28a4053SRui Paulo dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) { 380e28a4053SRui Paulo if (os_memcmp(bss->bssid, wpa_s->bssid, ETH_ALEN) != 0) 38139beb93cSSam Leffler continue; 38239beb93cSSam Leffler if (ssid == NULL || 383e28a4053SRui Paulo ((bss->ssid_len == ssid->ssid_len && 384e28a4053SRui Paulo os_memcmp(bss->ssid, ssid->ssid, ssid->ssid_len) == 0) || 38539beb93cSSam Leffler ssid->ssid_len == 0)) { 386e28a4053SRui Paulo curr = bss; 38739beb93cSSam Leffler break; 38839beb93cSSam Leffler } 38939beb93cSSam Leffler } 39039beb93cSSam Leffler 39139beb93cSSam Leffler if (curr) { 392e28a4053SRui Paulo ie = wpa_bss_get_vendor_ie(curr, WPA_IE_VENDOR_TYPE); 39339beb93cSSam Leffler if (wpa_sm_set_ap_wpa_ie(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0)) 39439beb93cSSam Leffler ret = -1; 39539beb93cSSam Leffler 396e28a4053SRui Paulo ie = wpa_bss_get_ie(curr, WLAN_EID_RSN); 39739beb93cSSam Leffler if (wpa_sm_set_ap_rsn_ie(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0)) 39839beb93cSSam Leffler ret = -1; 39939beb93cSSam Leffler } else { 40039beb93cSSam Leffler ret = -1; 40139beb93cSSam Leffler } 40239beb93cSSam Leffler 40339beb93cSSam Leffler return ret; 40439beb93cSSam Leffler } 40539beb93cSSam Leffler 40639beb93cSSam Leffler 40739beb93cSSam Leffler static int wpa_supplicant_get_beacon_ie(void *ctx) 40839beb93cSSam Leffler { 40939beb93cSSam Leffler struct wpa_supplicant *wpa_s = ctx; 41039beb93cSSam Leffler if (wpa_get_beacon_ie(wpa_s) == 0) { 41139beb93cSSam Leffler return 0; 41239beb93cSSam Leffler } 41339beb93cSSam Leffler 41439beb93cSSam Leffler /* No WPA/RSN IE found in the cached scan results. Try to get updated 41539beb93cSSam Leffler * scan results from the driver. */ 416e28a4053SRui Paulo if (wpa_supplicant_update_scan_results(wpa_s) < 0) 41739beb93cSSam Leffler return -1; 41839beb93cSSam Leffler 41939beb93cSSam Leffler return wpa_get_beacon_ie(wpa_s); 42039beb93cSSam Leffler } 42139beb93cSSam Leffler 42239beb93cSSam Leffler 42339beb93cSSam Leffler static u8 * _wpa_alloc_eapol(void *wpa_s, u8 type, 42439beb93cSSam Leffler const void *data, u16 data_len, 42539beb93cSSam Leffler size_t *msg_len, void **data_pos) 42639beb93cSSam Leffler { 42739beb93cSSam Leffler return wpa_alloc_eapol(wpa_s, type, data, data_len, msg_len, data_pos); 42839beb93cSSam Leffler } 42939beb93cSSam Leffler 43039beb93cSSam Leffler 43139beb93cSSam Leffler static int _wpa_ether_send(void *wpa_s, const u8 *dest, u16 proto, 43239beb93cSSam Leffler const u8 *buf, size_t len) 43339beb93cSSam Leffler { 43439beb93cSSam Leffler return wpa_ether_send(wpa_s, dest, proto, buf, len); 43539beb93cSSam Leffler } 43639beb93cSSam Leffler 43739beb93cSSam Leffler 43839beb93cSSam Leffler static void _wpa_supplicant_cancel_auth_timeout(void *wpa_s) 43939beb93cSSam Leffler { 44039beb93cSSam Leffler wpa_supplicant_cancel_auth_timeout(wpa_s); 44139beb93cSSam Leffler } 44239beb93cSSam Leffler 44339beb93cSSam Leffler 444e28a4053SRui Paulo static void _wpa_supplicant_set_state(void *wpa_s, enum wpa_states state) 44539beb93cSSam Leffler { 44639beb93cSSam Leffler wpa_supplicant_set_state(wpa_s, state); 44739beb93cSSam Leffler } 44839beb93cSSam Leffler 44939beb93cSSam Leffler 45039beb93cSSam Leffler /** 45139beb93cSSam Leffler * wpa_supplicant_get_state - Get the connection state 45239beb93cSSam Leffler * @wpa_s: Pointer to wpa_supplicant data 45339beb93cSSam Leffler * Returns: The current connection state (WPA_*) 45439beb93cSSam Leffler */ 455e28a4053SRui Paulo static enum wpa_states wpa_supplicant_get_state(struct wpa_supplicant *wpa_s) 45639beb93cSSam Leffler { 45739beb93cSSam Leffler return wpa_s->wpa_state; 45839beb93cSSam Leffler } 45939beb93cSSam Leffler 46039beb93cSSam Leffler 461e28a4053SRui Paulo static enum wpa_states _wpa_supplicant_get_state(void *wpa_s) 46239beb93cSSam Leffler { 46339beb93cSSam Leffler return wpa_supplicant_get_state(wpa_s); 46439beb93cSSam Leffler } 46539beb93cSSam Leffler 46639beb93cSSam Leffler 46739beb93cSSam Leffler static void _wpa_supplicant_deauthenticate(void *wpa_s, int reason_code) 46839beb93cSSam Leffler { 46939beb93cSSam Leffler wpa_supplicant_deauthenticate(wpa_s, reason_code); 47039beb93cSSam Leffler /* Schedule a scan to make sure we continue looking for networks */ 4713157ba21SRui Paulo wpa_supplicant_req_scan(wpa_s, 5, 0); 47239beb93cSSam Leffler } 47339beb93cSSam Leffler 47439beb93cSSam Leffler 47539beb93cSSam Leffler static void * wpa_supplicant_get_network_ctx(void *wpa_s) 47639beb93cSSam Leffler { 47739beb93cSSam Leffler return wpa_supplicant_get_ssid(wpa_s); 47839beb93cSSam Leffler } 47939beb93cSSam Leffler 48039beb93cSSam Leffler 48139beb93cSSam Leffler static int wpa_supplicant_get_bssid(void *ctx, u8 *bssid) 48239beb93cSSam Leffler { 48339beb93cSSam Leffler struct wpa_supplicant *wpa_s = ctx; 48439beb93cSSam Leffler return wpa_drv_get_bssid(wpa_s, bssid); 48539beb93cSSam Leffler } 48639beb93cSSam Leffler 48739beb93cSSam Leffler 488e28a4053SRui Paulo static int wpa_supplicant_set_key(void *_wpa_s, enum wpa_alg alg, 48939beb93cSSam Leffler const u8 *addr, int key_idx, int set_tx, 49039beb93cSSam Leffler const u8 *seq, size_t seq_len, 49139beb93cSSam Leffler const u8 *key, size_t key_len) 49239beb93cSSam Leffler { 49339beb93cSSam Leffler struct wpa_supplicant *wpa_s = _wpa_s; 49439beb93cSSam Leffler if (alg == WPA_ALG_TKIP && key_idx == 0 && key_len == 32) { 49539beb93cSSam Leffler /* Clear the MIC error counter when setting a new PTK. */ 49639beb93cSSam Leffler wpa_s->mic_errors_seen = 0; 49739beb93cSSam Leffler } 4985b9c547cSRui Paulo #ifdef CONFIG_TESTING_GET_GTK 4995b9c547cSRui Paulo if (key_idx > 0 && addr && is_broadcast_ether_addr(addr) && 5005b9c547cSRui Paulo alg != WPA_ALG_NONE && key_len <= sizeof(wpa_s->last_gtk)) { 5015b9c547cSRui Paulo os_memcpy(wpa_s->last_gtk, key, key_len); 5025b9c547cSRui Paulo wpa_s->last_gtk_len = key_len; 5035b9c547cSRui Paulo } 5045b9c547cSRui Paulo #endif /* CONFIG_TESTING_GET_GTK */ 505*85732ac8SCy Schubert #ifdef CONFIG_TESTING_OPTIONS 506*85732ac8SCy Schubert if (addr && !is_broadcast_ether_addr(addr)) { 507*85732ac8SCy Schubert wpa_s->last_tk_alg = alg; 508*85732ac8SCy Schubert os_memcpy(wpa_s->last_tk_addr, addr, ETH_ALEN); 509*85732ac8SCy Schubert wpa_s->last_tk_key_idx = key_idx; 510*85732ac8SCy Schubert if (key) 511*85732ac8SCy Schubert os_memcpy(wpa_s->last_tk, key, key_len); 512*85732ac8SCy Schubert wpa_s->last_tk_len = key_len; 513*85732ac8SCy Schubert } 514*85732ac8SCy Schubert #endif /* CONFIG_TESTING_OPTIONS */ 51539beb93cSSam Leffler return wpa_drv_set_key(wpa_s, alg, addr, key_idx, set_tx, seq, seq_len, 51639beb93cSSam Leffler key, key_len); 51739beb93cSSam Leffler } 51839beb93cSSam Leffler 51939beb93cSSam Leffler 52039beb93cSSam Leffler static int wpa_supplicant_mlme_setprotection(void *wpa_s, const u8 *addr, 52139beb93cSSam Leffler int protection_type, 52239beb93cSSam Leffler int key_type) 52339beb93cSSam Leffler { 52439beb93cSSam Leffler return wpa_drv_mlme_setprotection(wpa_s, addr, protection_type, 52539beb93cSSam Leffler key_type); 52639beb93cSSam Leffler } 52739beb93cSSam Leffler 52839beb93cSSam Leffler 529*85732ac8SCy Schubert static struct wpa_ssid * wpas_get_network_ctx(struct wpa_supplicant *wpa_s, 530*85732ac8SCy Schubert void *network_ctx) 53139beb93cSSam Leffler { 532*85732ac8SCy Schubert struct wpa_ssid *ssid; 533*85732ac8SCy Schubert 534*85732ac8SCy Schubert for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) { 535*85732ac8SCy Schubert if (network_ctx == ssid) 536*85732ac8SCy Schubert return ssid; 537*85732ac8SCy Schubert } 538*85732ac8SCy Schubert 539*85732ac8SCy Schubert return NULL; 54039beb93cSSam Leffler } 54139beb93cSSam Leffler 54239beb93cSSam Leffler 543*85732ac8SCy Schubert static int wpa_supplicant_add_pmkid(void *_wpa_s, void *network_ctx, 544*85732ac8SCy Schubert const u8 *bssid, const u8 *pmkid, 545*85732ac8SCy Schubert const u8 *fils_cache_id, 546*85732ac8SCy Schubert const u8 *pmk, size_t pmk_len) 54739beb93cSSam Leffler { 548*85732ac8SCy Schubert struct wpa_supplicant *wpa_s = _wpa_s; 549*85732ac8SCy Schubert struct wpa_ssid *ssid; 550*85732ac8SCy Schubert struct wpa_pmkid_params params; 551*85732ac8SCy Schubert 552*85732ac8SCy Schubert os_memset(¶ms, 0, sizeof(params)); 553*85732ac8SCy Schubert ssid = wpas_get_network_ctx(wpa_s, network_ctx); 554*85732ac8SCy Schubert if (ssid) 555*85732ac8SCy Schubert wpa_msg(wpa_s, MSG_INFO, PMKSA_CACHE_ADDED MACSTR " %d", 556*85732ac8SCy Schubert MAC2STR(bssid), ssid->id); 557*85732ac8SCy Schubert if (ssid && fils_cache_id) { 558*85732ac8SCy Schubert params.ssid = ssid->ssid; 559*85732ac8SCy Schubert params.ssid_len = ssid->ssid_len; 560*85732ac8SCy Schubert params.fils_cache_id = fils_cache_id; 561*85732ac8SCy Schubert } else { 562*85732ac8SCy Schubert params.bssid = bssid; 563*85732ac8SCy Schubert } 564*85732ac8SCy Schubert 565*85732ac8SCy Schubert params.pmkid = pmkid; 566*85732ac8SCy Schubert params.pmk = pmk; 567*85732ac8SCy Schubert params.pmk_len = pmk_len; 568*85732ac8SCy Schubert 569*85732ac8SCy Schubert return wpa_drv_add_pmkid(wpa_s, ¶ms); 570*85732ac8SCy Schubert } 571*85732ac8SCy Schubert 572*85732ac8SCy Schubert 573*85732ac8SCy Schubert static int wpa_supplicant_remove_pmkid(void *_wpa_s, void *network_ctx, 574*85732ac8SCy Schubert const u8 *bssid, const u8 *pmkid, 575*85732ac8SCy Schubert const u8 *fils_cache_id) 576*85732ac8SCy Schubert { 577*85732ac8SCy Schubert struct wpa_supplicant *wpa_s = _wpa_s; 578*85732ac8SCy Schubert struct wpa_ssid *ssid; 579*85732ac8SCy Schubert struct wpa_pmkid_params params; 580*85732ac8SCy Schubert 581*85732ac8SCy Schubert os_memset(¶ms, 0, sizeof(params)); 582*85732ac8SCy Schubert ssid = wpas_get_network_ctx(wpa_s, network_ctx); 583*85732ac8SCy Schubert if (ssid) 584*85732ac8SCy Schubert wpa_msg(wpa_s, MSG_INFO, PMKSA_CACHE_REMOVED MACSTR " %d", 585*85732ac8SCy Schubert MAC2STR(bssid), ssid->id); 586*85732ac8SCy Schubert if (ssid && fils_cache_id) { 587*85732ac8SCy Schubert params.ssid = ssid->ssid; 588*85732ac8SCy Schubert params.ssid_len = ssid->ssid_len; 589*85732ac8SCy Schubert params.fils_cache_id = fils_cache_id; 590*85732ac8SCy Schubert } else { 591*85732ac8SCy Schubert params.bssid = bssid; 592*85732ac8SCy Schubert } 593*85732ac8SCy Schubert 594*85732ac8SCy Schubert params.pmkid = pmkid; 595*85732ac8SCy Schubert 596*85732ac8SCy Schubert return wpa_drv_remove_pmkid(wpa_s, ¶ms); 59739beb93cSSam Leffler } 59839beb93cSSam Leffler 59939beb93cSSam Leffler 60039beb93cSSam Leffler #ifdef CONFIG_IEEE80211R 60139beb93cSSam Leffler static int wpa_supplicant_update_ft_ies(void *ctx, const u8 *md, 60239beb93cSSam Leffler const u8 *ies, size_t ies_len) 60339beb93cSSam Leffler { 60439beb93cSSam Leffler struct wpa_supplicant *wpa_s = ctx; 605e28a4053SRui Paulo if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) 606e28a4053SRui Paulo return sme_update_ft_ies(wpa_s, md, ies, ies_len); 60739beb93cSSam Leffler return wpa_drv_update_ft_ies(wpa_s, md, ies, ies_len); 60839beb93cSSam Leffler } 60939beb93cSSam Leffler 61039beb93cSSam Leffler 61139beb93cSSam Leffler static int wpa_supplicant_send_ft_action(void *ctx, u8 action, 61239beb93cSSam Leffler const u8 *target_ap, 61339beb93cSSam Leffler const u8 *ies, size_t ies_len) 61439beb93cSSam Leffler { 61539beb93cSSam Leffler struct wpa_supplicant *wpa_s = ctx; 6165b9c547cSRui Paulo int ret; 6175b9c547cSRui Paulo u8 *data, *pos; 6185b9c547cSRui Paulo size_t data_len; 6195b9c547cSRui Paulo 6205b9c547cSRui Paulo if (action != 1) { 6215b9c547cSRui Paulo wpa_printf(MSG_ERROR, "Unsupported send_ft_action action %d", 6225b9c547cSRui Paulo action); 6235b9c547cSRui Paulo return -1; 6245b9c547cSRui Paulo } 6255b9c547cSRui Paulo 6265b9c547cSRui Paulo /* 6275b9c547cSRui Paulo * Action frame payload: 6285b9c547cSRui Paulo * Category[1] = 6 (Fast BSS Transition) 6295b9c547cSRui Paulo * Action[1] = 1 (Fast BSS Transition Request) 6305b9c547cSRui Paulo * STA Address 6315b9c547cSRui Paulo * Target AP Address 6325b9c547cSRui Paulo * FT IEs 6335b9c547cSRui Paulo */ 6345b9c547cSRui Paulo 6355b9c547cSRui Paulo data_len = 2 + 2 * ETH_ALEN + ies_len; 6365b9c547cSRui Paulo data = os_malloc(data_len); 6375b9c547cSRui Paulo if (data == NULL) 6385b9c547cSRui Paulo return -1; 6395b9c547cSRui Paulo pos = data; 6405b9c547cSRui Paulo *pos++ = 0x06; /* FT Action category */ 6415b9c547cSRui Paulo *pos++ = action; 6425b9c547cSRui Paulo os_memcpy(pos, wpa_s->own_addr, ETH_ALEN); 6435b9c547cSRui Paulo pos += ETH_ALEN; 6445b9c547cSRui Paulo os_memcpy(pos, target_ap, ETH_ALEN); 6455b9c547cSRui Paulo pos += ETH_ALEN; 6465b9c547cSRui Paulo os_memcpy(pos, ies, ies_len); 6475b9c547cSRui Paulo 6485b9c547cSRui Paulo ret = wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, 6495b9c547cSRui Paulo wpa_s->bssid, wpa_s->own_addr, wpa_s->bssid, 6505b9c547cSRui Paulo data, data_len, 0); 6515b9c547cSRui Paulo os_free(data); 6525b9c547cSRui Paulo 6535b9c547cSRui Paulo return ret; 65439beb93cSSam Leffler } 655e28a4053SRui Paulo 656e28a4053SRui Paulo 657e28a4053SRui Paulo static int wpa_supplicant_mark_authenticated(void *ctx, const u8 *target_ap) 658e28a4053SRui Paulo { 659e28a4053SRui Paulo struct wpa_supplicant *wpa_s = ctx; 660e28a4053SRui Paulo struct wpa_driver_auth_params params; 661e28a4053SRui Paulo struct wpa_bss *bss; 662e28a4053SRui Paulo 663e28a4053SRui Paulo bss = wpa_bss_get_bssid(wpa_s, target_ap); 664e28a4053SRui Paulo if (bss == NULL) 665e28a4053SRui Paulo return -1; 666e28a4053SRui Paulo 667e28a4053SRui Paulo os_memset(¶ms, 0, sizeof(params)); 668e28a4053SRui Paulo params.bssid = target_ap; 669e28a4053SRui Paulo params.freq = bss->freq; 670e28a4053SRui Paulo params.ssid = bss->ssid; 671e28a4053SRui Paulo params.ssid_len = bss->ssid_len; 672e28a4053SRui Paulo params.auth_alg = WPA_AUTH_ALG_FT; 673e28a4053SRui Paulo params.local_state_change = 1; 674e28a4053SRui Paulo return wpa_drv_authenticate(wpa_s, ¶ms); 675e28a4053SRui Paulo } 67639beb93cSSam Leffler #endif /* CONFIG_IEEE80211R */ 67739beb93cSSam Leffler 67839beb93cSSam Leffler 679f05cddf9SRui Paulo #ifdef CONFIG_TDLS 680f05cddf9SRui Paulo 681f05cddf9SRui Paulo static int wpa_supplicant_tdls_get_capa(void *ctx, int *tdls_supported, 6825b9c547cSRui Paulo int *tdls_ext_setup, 6835b9c547cSRui Paulo int *tdls_chan_switch) 684f05cddf9SRui Paulo { 685f05cddf9SRui Paulo struct wpa_supplicant *wpa_s = ctx; 686f05cddf9SRui Paulo 687f05cddf9SRui Paulo *tdls_supported = 0; 688f05cddf9SRui Paulo *tdls_ext_setup = 0; 6895b9c547cSRui Paulo *tdls_chan_switch = 0; 690f05cddf9SRui Paulo 691f05cddf9SRui Paulo if (!wpa_s->drv_capa_known) 692f05cddf9SRui Paulo return -1; 693f05cddf9SRui Paulo 694f05cddf9SRui Paulo if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_TDLS_SUPPORT) 695f05cddf9SRui Paulo *tdls_supported = 1; 696f05cddf9SRui Paulo 697f05cddf9SRui Paulo if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_TDLS_EXTERNAL_SETUP) 698f05cddf9SRui Paulo *tdls_ext_setup = 1; 699f05cddf9SRui Paulo 7005b9c547cSRui Paulo if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_TDLS_CHANNEL_SWITCH) 7015b9c547cSRui Paulo *tdls_chan_switch = 1; 7025b9c547cSRui Paulo 703f05cddf9SRui Paulo return 0; 704f05cddf9SRui Paulo } 705f05cddf9SRui Paulo 706f05cddf9SRui Paulo 707f05cddf9SRui Paulo static int wpa_supplicant_send_tdls_mgmt(void *ctx, const u8 *dst, 708f05cddf9SRui Paulo u8 action_code, u8 dialog_token, 7095b9c547cSRui Paulo u16 status_code, u32 peer_capab, 7105b9c547cSRui Paulo int initiator, const u8 *buf, 711f05cddf9SRui Paulo size_t len) 712f05cddf9SRui Paulo { 713f05cddf9SRui Paulo struct wpa_supplicant *wpa_s = ctx; 714f05cddf9SRui Paulo return wpa_drv_send_tdls_mgmt(wpa_s, dst, action_code, dialog_token, 7155b9c547cSRui Paulo status_code, peer_capab, initiator, buf, 7165b9c547cSRui Paulo len); 717f05cddf9SRui Paulo } 718f05cddf9SRui Paulo 719f05cddf9SRui Paulo 720f05cddf9SRui Paulo static int wpa_supplicant_tdls_oper(void *ctx, int oper, const u8 *peer) 721f05cddf9SRui Paulo { 722f05cddf9SRui Paulo struct wpa_supplicant *wpa_s = ctx; 723f05cddf9SRui Paulo return wpa_drv_tdls_oper(wpa_s, oper, peer); 724f05cddf9SRui Paulo } 725f05cddf9SRui Paulo 726f05cddf9SRui Paulo 727f05cddf9SRui Paulo static int wpa_supplicant_tdls_peer_addset( 7285b9c547cSRui Paulo void *ctx, const u8 *peer, int add, u16 aid, u16 capability, 7295b9c547cSRui Paulo const u8 *supp_rates, size_t supp_rates_len, 7305b9c547cSRui Paulo const struct ieee80211_ht_capabilities *ht_capab, 7315b9c547cSRui Paulo const struct ieee80211_vht_capabilities *vht_capab, 7325b9c547cSRui Paulo u8 qosinfo, int wmm, const u8 *ext_capab, size_t ext_capab_len, 7335b9c547cSRui Paulo const u8 *supp_channels, size_t supp_channels_len, 7345b9c547cSRui Paulo const u8 *supp_oper_classes, size_t supp_oper_classes_len) 735f05cddf9SRui Paulo { 736f05cddf9SRui Paulo struct wpa_supplicant *wpa_s = ctx; 737f05cddf9SRui Paulo struct hostapd_sta_add_params params; 738f05cddf9SRui Paulo 7395b9c547cSRui Paulo os_memset(¶ms, 0, sizeof(params)); 7405b9c547cSRui Paulo 741f05cddf9SRui Paulo params.addr = peer; 7425b9c547cSRui Paulo params.aid = aid; 743f05cddf9SRui Paulo params.capability = capability; 744f05cddf9SRui Paulo params.flags = WPA_STA_TDLS_PEER | WPA_STA_AUTHORIZED; 7455b9c547cSRui Paulo 7465b9c547cSRui Paulo /* 7475b9c547cSRui Paulo * Don't rely only on qosinfo for WMM capability. It may be 0 even when 7485b9c547cSRui Paulo * present. Allow the WMM IE to also indicate QoS support. 7495b9c547cSRui Paulo */ 7505b9c547cSRui Paulo if (wmm || qosinfo) 7515b9c547cSRui Paulo params.flags |= WPA_STA_WMM; 7525b9c547cSRui Paulo 7535b9c547cSRui Paulo params.ht_capabilities = ht_capab; 7545b9c547cSRui Paulo params.vht_capabilities = vht_capab; 7555b9c547cSRui Paulo params.qosinfo = qosinfo; 756f05cddf9SRui Paulo params.listen_interval = 0; 757f05cddf9SRui Paulo params.supp_rates = supp_rates; 758f05cddf9SRui Paulo params.supp_rates_len = supp_rates_len; 759f05cddf9SRui Paulo params.set = !add; 7605b9c547cSRui Paulo params.ext_capab = ext_capab; 7615b9c547cSRui Paulo params.ext_capab_len = ext_capab_len; 7625b9c547cSRui Paulo params.supp_channels = supp_channels; 7635b9c547cSRui Paulo params.supp_channels_len = supp_channels_len; 7645b9c547cSRui Paulo params.supp_oper_classes = supp_oper_classes; 7655b9c547cSRui Paulo params.supp_oper_classes_len = supp_oper_classes_len; 766f05cddf9SRui Paulo 767f05cddf9SRui Paulo return wpa_drv_sta_add(wpa_s, ¶ms); 768f05cddf9SRui Paulo } 769f05cddf9SRui Paulo 7705b9c547cSRui Paulo 7715b9c547cSRui Paulo static int wpa_supplicant_tdls_enable_channel_switch( 7725b9c547cSRui Paulo void *ctx, const u8 *addr, u8 oper_class, 7735b9c547cSRui Paulo const struct hostapd_freq_params *params) 7745b9c547cSRui Paulo { 7755b9c547cSRui Paulo struct wpa_supplicant *wpa_s = ctx; 7765b9c547cSRui Paulo 7775b9c547cSRui Paulo return wpa_drv_tdls_enable_channel_switch(wpa_s, addr, oper_class, 7785b9c547cSRui Paulo params); 7795b9c547cSRui Paulo } 7805b9c547cSRui Paulo 7815b9c547cSRui Paulo 7825b9c547cSRui Paulo static int wpa_supplicant_tdls_disable_channel_switch(void *ctx, const u8 *addr) 7835b9c547cSRui Paulo { 7845b9c547cSRui Paulo struct wpa_supplicant *wpa_s = ctx; 7855b9c547cSRui Paulo 7865b9c547cSRui Paulo return wpa_drv_tdls_disable_channel_switch(wpa_s, addr); 7875b9c547cSRui Paulo } 7885b9c547cSRui Paulo 789f05cddf9SRui Paulo #endif /* CONFIG_TDLS */ 790f05cddf9SRui Paulo 7915b9c547cSRui Paulo #endif /* CONFIG_NO_WPA */ 7925b9c547cSRui Paulo 793f05cddf9SRui Paulo 794f05cddf9SRui Paulo enum wpa_ctrl_req_type wpa_supplicant_ctrl_req_from_string(const char *field) 795f05cddf9SRui Paulo { 796f05cddf9SRui Paulo if (os_strcmp(field, "IDENTITY") == 0) 797f05cddf9SRui Paulo return WPA_CTRL_REQ_EAP_IDENTITY; 798f05cddf9SRui Paulo else if (os_strcmp(field, "PASSWORD") == 0) 799f05cddf9SRui Paulo return WPA_CTRL_REQ_EAP_PASSWORD; 800f05cddf9SRui Paulo else if (os_strcmp(field, "NEW_PASSWORD") == 0) 801f05cddf9SRui Paulo return WPA_CTRL_REQ_EAP_NEW_PASSWORD; 802f05cddf9SRui Paulo else if (os_strcmp(field, "PIN") == 0) 803f05cddf9SRui Paulo return WPA_CTRL_REQ_EAP_PIN; 804f05cddf9SRui Paulo else if (os_strcmp(field, "OTP") == 0) 805f05cddf9SRui Paulo return WPA_CTRL_REQ_EAP_OTP; 806f05cddf9SRui Paulo else if (os_strcmp(field, "PASSPHRASE") == 0) 807f05cddf9SRui Paulo return WPA_CTRL_REQ_EAP_PASSPHRASE; 8085b9c547cSRui Paulo else if (os_strcmp(field, "SIM") == 0) 8095b9c547cSRui Paulo return WPA_CTRL_REQ_SIM; 810325151a3SRui Paulo else if (os_strcmp(field, "PSK_PASSPHRASE") == 0) 811325151a3SRui Paulo return WPA_CTRL_REQ_PSK_PASSPHRASE; 812780fb4a2SCy Schubert else if (os_strcmp(field, "EXT_CERT_CHECK") == 0) 813780fb4a2SCy Schubert return WPA_CTRL_REQ_EXT_CERT_CHECK; 814f05cddf9SRui Paulo return WPA_CTRL_REQ_UNKNOWN; 815f05cddf9SRui Paulo } 816f05cddf9SRui Paulo 817f05cddf9SRui Paulo 818f05cddf9SRui Paulo const char * wpa_supplicant_ctrl_req_to_string(enum wpa_ctrl_req_type field, 819f05cddf9SRui Paulo const char *default_txt, 820f05cddf9SRui Paulo const char **txt) 821f05cddf9SRui Paulo { 822f05cddf9SRui Paulo const char *ret = NULL; 823f05cddf9SRui Paulo 824f05cddf9SRui Paulo *txt = default_txt; 825f05cddf9SRui Paulo 826f05cddf9SRui Paulo switch (field) { 827f05cddf9SRui Paulo case WPA_CTRL_REQ_EAP_IDENTITY: 828f05cddf9SRui Paulo *txt = "Identity"; 829f05cddf9SRui Paulo ret = "IDENTITY"; 830f05cddf9SRui Paulo break; 831f05cddf9SRui Paulo case WPA_CTRL_REQ_EAP_PASSWORD: 832f05cddf9SRui Paulo *txt = "Password"; 833f05cddf9SRui Paulo ret = "PASSWORD"; 834f05cddf9SRui Paulo break; 835f05cddf9SRui Paulo case WPA_CTRL_REQ_EAP_NEW_PASSWORD: 836f05cddf9SRui Paulo *txt = "New Password"; 837f05cddf9SRui Paulo ret = "NEW_PASSWORD"; 838f05cddf9SRui Paulo break; 839f05cddf9SRui Paulo case WPA_CTRL_REQ_EAP_PIN: 840f05cddf9SRui Paulo *txt = "PIN"; 841f05cddf9SRui Paulo ret = "PIN"; 842f05cddf9SRui Paulo break; 843f05cddf9SRui Paulo case WPA_CTRL_REQ_EAP_OTP: 844f05cddf9SRui Paulo ret = "OTP"; 845f05cddf9SRui Paulo break; 846f05cddf9SRui Paulo case WPA_CTRL_REQ_EAP_PASSPHRASE: 847f05cddf9SRui Paulo *txt = "Private key passphrase"; 848f05cddf9SRui Paulo ret = "PASSPHRASE"; 849f05cddf9SRui Paulo break; 8505b9c547cSRui Paulo case WPA_CTRL_REQ_SIM: 8515b9c547cSRui Paulo ret = "SIM"; 8525b9c547cSRui Paulo break; 853325151a3SRui Paulo case WPA_CTRL_REQ_PSK_PASSPHRASE: 854325151a3SRui Paulo *txt = "PSK or passphrase"; 855325151a3SRui Paulo ret = "PSK_PASSPHRASE"; 856325151a3SRui Paulo break; 857780fb4a2SCy Schubert case WPA_CTRL_REQ_EXT_CERT_CHECK: 858780fb4a2SCy Schubert *txt = "External server certificate validation"; 859780fb4a2SCy Schubert ret = "EXT_CERT_CHECK"; 860780fb4a2SCy Schubert break; 861f05cddf9SRui Paulo default: 862f05cddf9SRui Paulo break; 863f05cddf9SRui Paulo } 864f05cddf9SRui Paulo 865f05cddf9SRui Paulo /* txt needs to be something */ 866f05cddf9SRui Paulo if (*txt == NULL) { 867f05cddf9SRui Paulo wpa_printf(MSG_WARNING, "No message for request %d", field); 868f05cddf9SRui Paulo ret = NULL; 869f05cddf9SRui Paulo } 870f05cddf9SRui Paulo 871f05cddf9SRui Paulo return ret; 872f05cddf9SRui Paulo } 873f05cddf9SRui Paulo 874325151a3SRui Paulo 875325151a3SRui Paulo void wpas_send_ctrl_req(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid, 876325151a3SRui Paulo const char *field_name, const char *txt) 877325151a3SRui Paulo { 878325151a3SRui Paulo char *buf; 879325151a3SRui Paulo size_t buflen; 880325151a3SRui Paulo int len; 881325151a3SRui Paulo 882325151a3SRui Paulo buflen = 100 + os_strlen(txt) + ssid->ssid_len; 883325151a3SRui Paulo buf = os_malloc(buflen); 884325151a3SRui Paulo if (buf == NULL) 885325151a3SRui Paulo return; 886325151a3SRui Paulo len = os_snprintf(buf, buflen, "%s-%d:%s needed for SSID ", 887325151a3SRui Paulo field_name, ssid->id, txt); 888325151a3SRui Paulo if (os_snprintf_error(buflen, len)) { 889325151a3SRui Paulo os_free(buf); 890325151a3SRui Paulo return; 891325151a3SRui Paulo } 892325151a3SRui Paulo if (ssid->ssid && buflen > len + ssid->ssid_len) { 893325151a3SRui Paulo os_memcpy(buf + len, ssid->ssid, ssid->ssid_len); 894325151a3SRui Paulo len += ssid->ssid_len; 895325151a3SRui Paulo buf[len] = '\0'; 896325151a3SRui Paulo } 897325151a3SRui Paulo buf[buflen - 1] = '\0'; 898325151a3SRui Paulo wpa_msg(wpa_s, MSG_INFO, WPA_CTRL_REQ "%s", buf); 899325151a3SRui Paulo os_free(buf); 900325151a3SRui Paulo } 901325151a3SRui Paulo 902325151a3SRui Paulo 903e28a4053SRui Paulo #ifdef IEEE8021X_EAPOL 90439beb93cSSam Leffler #if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG) 905f05cddf9SRui Paulo static void wpa_supplicant_eap_param_needed(void *ctx, 906f05cddf9SRui Paulo enum wpa_ctrl_req_type field, 907f05cddf9SRui Paulo const char *default_txt) 90839beb93cSSam Leffler { 90939beb93cSSam Leffler struct wpa_supplicant *wpa_s = ctx; 91039beb93cSSam Leffler struct wpa_ssid *ssid = wpa_s->current_ssid; 911f05cddf9SRui Paulo const char *field_name, *txt = NULL; 91239beb93cSSam Leffler 91339beb93cSSam Leffler if (ssid == NULL) 91439beb93cSSam Leffler return; 91539beb93cSSam Leffler 916780fb4a2SCy Schubert if (field == WPA_CTRL_REQ_EXT_CERT_CHECK) 917780fb4a2SCy Schubert ssid->eap.pending_ext_cert_check = PENDING_CHECK; 918f05cddf9SRui Paulo wpas_notify_network_request(wpa_s, ssid, field, default_txt); 919f05cddf9SRui Paulo 920f05cddf9SRui Paulo field_name = wpa_supplicant_ctrl_req_to_string(field, default_txt, 921f05cddf9SRui Paulo &txt); 922f05cddf9SRui Paulo if (field_name == NULL) { 923f05cddf9SRui Paulo wpa_printf(MSG_WARNING, "Unhandled EAP param %d needed", 924f05cddf9SRui Paulo field); 925f05cddf9SRui Paulo return; 926f05cddf9SRui Paulo } 927f05cddf9SRui Paulo 9285b9c547cSRui Paulo wpas_notify_eap_status(wpa_s, "eap parameter needed", field_name); 9295b9c547cSRui Paulo 930325151a3SRui Paulo wpas_send_ctrl_req(wpa_s, ssid, field_name, txt); 93139beb93cSSam Leffler } 93239beb93cSSam Leffler #else /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */ 93339beb93cSSam Leffler #define wpa_supplicant_eap_param_needed NULL 93439beb93cSSam Leffler #endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */ 93539beb93cSSam Leffler 93639beb93cSSam Leffler 9375b9c547cSRui Paulo #ifdef CONFIG_EAP_PROXY 938*85732ac8SCy Schubert 9395b9c547cSRui Paulo static void wpa_supplicant_eap_proxy_cb(void *ctx) 9405b9c547cSRui Paulo { 9415b9c547cSRui Paulo struct wpa_supplicant *wpa_s = ctx; 9425b9c547cSRui Paulo size_t len; 9435b9c547cSRui Paulo 944*85732ac8SCy Schubert wpa_s->mnc_len = eapol_sm_get_eap_proxy_imsi(wpa_s->eapol, -1, 9455b9c547cSRui Paulo wpa_s->imsi, &len); 9465b9c547cSRui Paulo if (wpa_s->mnc_len > 0) { 9475b9c547cSRui Paulo wpa_s->imsi[len] = '\0'; 9485b9c547cSRui Paulo wpa_printf(MSG_DEBUG, "eap_proxy: IMSI %s (MNC length %d)", 9495b9c547cSRui Paulo wpa_s->imsi, wpa_s->mnc_len); 9505b9c547cSRui Paulo } else { 9515b9c547cSRui Paulo wpa_printf(MSG_DEBUG, "eap_proxy: IMSI not available"); 9525b9c547cSRui Paulo } 9535b9c547cSRui Paulo } 954*85732ac8SCy Schubert 955*85732ac8SCy Schubert 956*85732ac8SCy Schubert static void wpa_sm_sim_state_error_handler(struct wpa_supplicant *wpa_s) 957*85732ac8SCy Schubert { 958*85732ac8SCy Schubert int i; 959*85732ac8SCy Schubert struct wpa_ssid *ssid; 960*85732ac8SCy Schubert const struct eap_method_type *eap_methods; 961*85732ac8SCy Schubert 962*85732ac8SCy Schubert if (!wpa_s->conf) 963*85732ac8SCy Schubert return; 964*85732ac8SCy Schubert 965*85732ac8SCy Schubert for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) { 966*85732ac8SCy Schubert eap_methods = ssid->eap.eap_methods; 967*85732ac8SCy Schubert if (!eap_methods) 968*85732ac8SCy Schubert continue; 969*85732ac8SCy Schubert 970*85732ac8SCy Schubert for (i = 0; eap_methods[i].method != EAP_TYPE_NONE; i++) { 971*85732ac8SCy Schubert if (eap_methods[i].vendor == EAP_VENDOR_IETF && 972*85732ac8SCy Schubert (eap_methods[i].method == EAP_TYPE_SIM || 973*85732ac8SCy Schubert eap_methods[i].method == EAP_TYPE_AKA || 974*85732ac8SCy Schubert eap_methods[i].method == EAP_TYPE_AKA_PRIME)) { 975*85732ac8SCy Schubert wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid); 976*85732ac8SCy Schubert break; 977*85732ac8SCy Schubert } 978*85732ac8SCy Schubert } 979*85732ac8SCy Schubert } 980*85732ac8SCy Schubert } 981*85732ac8SCy Schubert 982*85732ac8SCy Schubert 983*85732ac8SCy Schubert static void 984*85732ac8SCy Schubert wpa_supplicant_eap_proxy_notify_sim_status(void *ctx, 985*85732ac8SCy Schubert enum eap_proxy_sim_state sim_state) 986*85732ac8SCy Schubert { 987*85732ac8SCy Schubert struct wpa_supplicant *wpa_s = ctx; 988*85732ac8SCy Schubert 989*85732ac8SCy Schubert wpa_printf(MSG_DEBUG, "eap_proxy: SIM card status %u", sim_state); 990*85732ac8SCy Schubert switch (sim_state) { 991*85732ac8SCy Schubert case SIM_STATE_ERROR: 992*85732ac8SCy Schubert wpa_sm_sim_state_error_handler(wpa_s); 993*85732ac8SCy Schubert break; 994*85732ac8SCy Schubert default: 995*85732ac8SCy Schubert wpa_printf(MSG_DEBUG, "eap_proxy: SIM card status unknown"); 996*85732ac8SCy Schubert break; 997*85732ac8SCy Schubert } 998*85732ac8SCy Schubert } 999*85732ac8SCy Schubert 10005b9c547cSRui Paulo #endif /* CONFIG_EAP_PROXY */ 10015b9c547cSRui Paulo 10025b9c547cSRui Paulo 1003e28a4053SRui Paulo static void wpa_supplicant_port_cb(void *ctx, int authorized) 1004e28a4053SRui Paulo { 1005e28a4053SRui Paulo struct wpa_supplicant *wpa_s = ctx; 1006e28a4053SRui Paulo #ifdef CONFIG_AP 1007e28a4053SRui Paulo if (wpa_s->ap_iface) { 1008e28a4053SRui Paulo wpa_printf(MSG_DEBUG, "AP mode active - skip EAPOL Supplicant " 1009e28a4053SRui Paulo "port status: %s", 1010e28a4053SRui Paulo authorized ? "Authorized" : "Unauthorized"); 1011e28a4053SRui Paulo return; 1012e28a4053SRui Paulo } 1013e28a4053SRui Paulo #endif /* CONFIG_AP */ 1014e28a4053SRui Paulo wpa_printf(MSG_DEBUG, "EAPOL: Supplicant port status: %s", 1015e28a4053SRui Paulo authorized ? "Authorized" : "Unauthorized"); 1016e28a4053SRui Paulo wpa_drv_set_supp_port(wpa_s, authorized); 1017e28a4053SRui Paulo } 1018f05cddf9SRui Paulo 1019f05cddf9SRui Paulo 1020f05cddf9SRui Paulo static void wpa_supplicant_cert_cb(void *ctx, int depth, const char *subject, 10215b9c547cSRui Paulo const char *altsubject[], int num_altsubject, 1022f05cddf9SRui Paulo const char *cert_hash, 1023f05cddf9SRui Paulo const struct wpabuf *cert) 1024f05cddf9SRui Paulo { 1025f05cddf9SRui Paulo struct wpa_supplicant *wpa_s = ctx; 1026f05cddf9SRui Paulo 10275b9c547cSRui Paulo wpas_notify_certification(wpa_s, depth, subject, altsubject, 10285b9c547cSRui Paulo num_altsubject, cert_hash, cert); 1029f05cddf9SRui Paulo } 1030f05cddf9SRui Paulo 1031f05cddf9SRui Paulo 1032f05cddf9SRui Paulo static void wpa_supplicant_status_cb(void *ctx, const char *status, 1033f05cddf9SRui Paulo const char *parameter) 1034f05cddf9SRui Paulo { 1035f05cddf9SRui Paulo struct wpa_supplicant *wpa_s = ctx; 1036f05cddf9SRui Paulo 1037f05cddf9SRui Paulo wpas_notify_eap_status(wpa_s, status, parameter); 1038f05cddf9SRui Paulo } 1039f05cddf9SRui Paulo 1040f05cddf9SRui Paulo 1041*85732ac8SCy Schubert static void wpa_supplicant_eap_error_cb(void *ctx, int error_code) 1042*85732ac8SCy Schubert { 1043*85732ac8SCy Schubert struct wpa_supplicant *wpa_s = ctx; 1044*85732ac8SCy Schubert 1045*85732ac8SCy Schubert wpas_notify_eap_error(wpa_s, error_code); 1046*85732ac8SCy Schubert } 1047*85732ac8SCy Schubert 1048*85732ac8SCy Schubert 1049f05cddf9SRui Paulo static void wpa_supplicant_set_anon_id(void *ctx, const u8 *id, size_t len) 1050f05cddf9SRui Paulo { 1051f05cddf9SRui Paulo struct wpa_supplicant *wpa_s = ctx; 1052f05cddf9SRui Paulo char *str; 1053f05cddf9SRui Paulo int res; 1054f05cddf9SRui Paulo 1055f05cddf9SRui Paulo wpa_hexdump_ascii(MSG_DEBUG, "EAP method updated anonymous_identity", 1056f05cddf9SRui Paulo id, len); 1057f05cddf9SRui Paulo 1058f05cddf9SRui Paulo if (wpa_s->current_ssid == NULL) 1059f05cddf9SRui Paulo return; 1060f05cddf9SRui Paulo 1061f05cddf9SRui Paulo if (id == NULL) { 1062f05cddf9SRui Paulo if (wpa_config_set(wpa_s->current_ssid, "anonymous_identity", 1063f05cddf9SRui Paulo "NULL", 0) < 0) 1064f05cddf9SRui Paulo return; 1065f05cddf9SRui Paulo } else { 1066f05cddf9SRui Paulo str = os_malloc(len * 2 + 1); 1067f05cddf9SRui Paulo if (str == NULL) 1068f05cddf9SRui Paulo return; 1069f05cddf9SRui Paulo wpa_snprintf_hex(str, len * 2 + 1, id, len); 1070f05cddf9SRui Paulo res = wpa_config_set(wpa_s->current_ssid, "anonymous_identity", 1071f05cddf9SRui Paulo str, 0); 1072f05cddf9SRui Paulo os_free(str); 1073f05cddf9SRui Paulo if (res < 0) 1074f05cddf9SRui Paulo return; 1075f05cddf9SRui Paulo } 1076f05cddf9SRui Paulo 1077f05cddf9SRui Paulo if (wpa_s->conf->update_config) { 1078f05cddf9SRui Paulo res = wpa_config_write(wpa_s->confname, wpa_s->conf); 1079f05cddf9SRui Paulo if (res) { 1080f05cddf9SRui Paulo wpa_printf(MSG_DEBUG, "Failed to update config after " 1081f05cddf9SRui Paulo "anonymous_id update"); 1082f05cddf9SRui Paulo } 1083f05cddf9SRui Paulo } 1084f05cddf9SRui Paulo } 1085e28a4053SRui Paulo #endif /* IEEE8021X_EAPOL */ 1086e28a4053SRui Paulo 1087e28a4053SRui Paulo 108839beb93cSSam Leffler int wpa_supplicant_init_eapol(struct wpa_supplicant *wpa_s) 108939beb93cSSam Leffler { 109039beb93cSSam Leffler #ifdef IEEE8021X_EAPOL 109139beb93cSSam Leffler struct eapol_ctx *ctx; 109239beb93cSSam Leffler ctx = os_zalloc(sizeof(*ctx)); 109339beb93cSSam Leffler if (ctx == NULL) { 109439beb93cSSam Leffler wpa_printf(MSG_ERROR, "Failed to allocate EAPOL context."); 109539beb93cSSam Leffler return -1; 109639beb93cSSam Leffler } 109739beb93cSSam Leffler 109839beb93cSSam Leffler ctx->ctx = wpa_s; 109939beb93cSSam Leffler ctx->msg_ctx = wpa_s; 110039beb93cSSam Leffler ctx->eapol_send_ctx = wpa_s; 110139beb93cSSam Leffler ctx->preauth = 0; 110239beb93cSSam Leffler ctx->eapol_done_cb = wpa_supplicant_notify_eapol_done; 110339beb93cSSam Leffler ctx->eapol_send = wpa_supplicant_eapol_send; 110439beb93cSSam Leffler ctx->set_wep_key = wpa_eapol_set_wep_key; 11055b9c547cSRui Paulo #ifndef CONFIG_NO_CONFIG_BLOBS 110639beb93cSSam Leffler ctx->set_config_blob = wpa_supplicant_set_config_blob; 110739beb93cSSam Leffler ctx->get_config_blob = wpa_supplicant_get_config_blob; 11085b9c547cSRui Paulo #endif /* CONFIG_NO_CONFIG_BLOBS */ 110939beb93cSSam Leffler ctx->aborted_cached = wpa_supplicant_aborted_cached; 111039beb93cSSam Leffler ctx->opensc_engine_path = wpa_s->conf->opensc_engine_path; 111139beb93cSSam Leffler ctx->pkcs11_engine_path = wpa_s->conf->pkcs11_engine_path; 111239beb93cSSam Leffler ctx->pkcs11_module_path = wpa_s->conf->pkcs11_module_path; 11135b9c547cSRui Paulo ctx->openssl_ciphers = wpa_s->conf->openssl_ciphers; 111439beb93cSSam Leffler ctx->wps = wpa_s->wps; 111539beb93cSSam Leffler ctx->eap_param_needed = wpa_supplicant_eap_param_needed; 11165b9c547cSRui Paulo #ifdef CONFIG_EAP_PROXY 11175b9c547cSRui Paulo ctx->eap_proxy_cb = wpa_supplicant_eap_proxy_cb; 1118*85732ac8SCy Schubert ctx->eap_proxy_notify_sim_status = 1119*85732ac8SCy Schubert wpa_supplicant_eap_proxy_notify_sim_status; 11205b9c547cSRui Paulo #endif /* CONFIG_EAP_PROXY */ 1121e28a4053SRui Paulo ctx->port_cb = wpa_supplicant_port_cb; 112239beb93cSSam Leffler ctx->cb = wpa_supplicant_eapol_cb; 1123f05cddf9SRui Paulo ctx->cert_cb = wpa_supplicant_cert_cb; 11245b9c547cSRui Paulo ctx->cert_in_cb = wpa_s->conf->cert_in_cb; 1125f05cddf9SRui Paulo ctx->status_cb = wpa_supplicant_status_cb; 1126*85732ac8SCy Schubert ctx->eap_error_cb = wpa_supplicant_eap_error_cb; 1127f05cddf9SRui Paulo ctx->set_anon_id = wpa_supplicant_set_anon_id; 112839beb93cSSam Leffler ctx->cb_ctx = wpa_s; 112939beb93cSSam Leffler wpa_s->eapol = eapol_sm_init(ctx); 113039beb93cSSam Leffler if (wpa_s->eapol == NULL) { 113139beb93cSSam Leffler os_free(ctx); 113239beb93cSSam Leffler wpa_printf(MSG_ERROR, "Failed to initialize EAPOL state " 113339beb93cSSam Leffler "machines."); 113439beb93cSSam Leffler return -1; 113539beb93cSSam Leffler } 113639beb93cSSam Leffler #endif /* IEEE8021X_EAPOL */ 113739beb93cSSam Leffler 113839beb93cSSam Leffler return 0; 113939beb93cSSam Leffler } 114039beb93cSSam Leffler 114139beb93cSSam Leffler 1142f05cddf9SRui Paulo #ifndef CONFIG_NO_WPA 1143*85732ac8SCy Schubert 11445b9c547cSRui Paulo static void wpa_supplicant_set_rekey_offload(void *ctx, 11455b9c547cSRui Paulo const u8 *kek, size_t kek_len, 11465b9c547cSRui Paulo const u8 *kck, size_t kck_len, 1147f05cddf9SRui Paulo const u8 *replay_ctr) 1148f05cddf9SRui Paulo { 1149f05cddf9SRui Paulo struct wpa_supplicant *wpa_s = ctx; 1150f05cddf9SRui Paulo 11515b9c547cSRui Paulo wpa_drv_set_rekey_info(wpa_s, kek, kek_len, kck, kck_len, replay_ctr); 1152f05cddf9SRui Paulo } 1153f05cddf9SRui Paulo 1154f05cddf9SRui Paulo 11555b9c547cSRui Paulo static int wpa_supplicant_key_mgmt_set_pmk(void *ctx, const u8 *pmk, 11565b9c547cSRui Paulo size_t pmk_len) 11575b9c547cSRui Paulo { 11585b9c547cSRui Paulo struct wpa_supplicant *wpa_s = ctx; 11595b9c547cSRui Paulo 1160325151a3SRui Paulo if (wpa_s->conf->key_mgmt_offload && 1161325151a3SRui Paulo (wpa_s->drv_flags & WPA_DRIVER_FLAGS_KEY_MGMT_OFFLOAD)) 11625b9c547cSRui Paulo return wpa_drv_set_key(wpa_s, WPA_ALG_PMK, NULL, 0, 0, 11635b9c547cSRui Paulo NULL, 0, pmk, pmk_len); 11645b9c547cSRui Paulo else 11655b9c547cSRui Paulo return 0; 11665b9c547cSRui Paulo } 1167*85732ac8SCy Schubert 1168*85732ac8SCy Schubert 1169*85732ac8SCy Schubert static void wpa_supplicant_fils_hlp_rx(void *ctx, const u8 *dst, const u8 *src, 1170*85732ac8SCy Schubert const u8 *pkt, size_t pkt_len) 1171*85732ac8SCy Schubert { 1172*85732ac8SCy Schubert struct wpa_supplicant *wpa_s = ctx; 1173*85732ac8SCy Schubert char *hex; 1174*85732ac8SCy Schubert size_t hexlen; 1175*85732ac8SCy Schubert 1176*85732ac8SCy Schubert hexlen = pkt_len * 2 + 1; 1177*85732ac8SCy Schubert hex = os_malloc(hexlen); 1178*85732ac8SCy Schubert if (!hex) 1179*85732ac8SCy Schubert return; 1180*85732ac8SCy Schubert wpa_snprintf_hex(hex, hexlen, pkt, pkt_len); 1181*85732ac8SCy Schubert wpa_msg(wpa_s, MSG_INFO, FILS_HLP_RX "dst=" MACSTR " src=" MACSTR 1182*85732ac8SCy Schubert " frame=%s", MAC2STR(dst), MAC2STR(src), hex); 1183*85732ac8SCy Schubert os_free(hex); 1184*85732ac8SCy Schubert } 1185*85732ac8SCy Schubert 1186780fb4a2SCy Schubert #endif /* CONFIG_NO_WPA */ 11875b9c547cSRui Paulo 11885b9c547cSRui Paulo 118939beb93cSSam Leffler int wpa_supplicant_init_wpa(struct wpa_supplicant *wpa_s) 119039beb93cSSam Leffler { 119139beb93cSSam Leffler #ifndef CONFIG_NO_WPA 119239beb93cSSam Leffler struct wpa_sm_ctx *ctx; 119339beb93cSSam Leffler ctx = os_zalloc(sizeof(*ctx)); 119439beb93cSSam Leffler if (ctx == NULL) { 119539beb93cSSam Leffler wpa_printf(MSG_ERROR, "Failed to allocate WPA context."); 119639beb93cSSam Leffler return -1; 119739beb93cSSam Leffler } 119839beb93cSSam Leffler 119939beb93cSSam Leffler ctx->ctx = wpa_s; 1200e28a4053SRui Paulo ctx->msg_ctx = wpa_s; 120139beb93cSSam Leffler ctx->set_state = _wpa_supplicant_set_state; 120239beb93cSSam Leffler ctx->get_state = _wpa_supplicant_get_state; 120339beb93cSSam Leffler ctx->deauthenticate = _wpa_supplicant_deauthenticate; 120439beb93cSSam Leffler ctx->set_key = wpa_supplicant_set_key; 120539beb93cSSam Leffler ctx->get_network_ctx = wpa_supplicant_get_network_ctx; 120639beb93cSSam Leffler ctx->get_bssid = wpa_supplicant_get_bssid; 120739beb93cSSam Leffler ctx->ether_send = _wpa_ether_send; 120839beb93cSSam Leffler ctx->get_beacon_ie = wpa_supplicant_get_beacon_ie; 120939beb93cSSam Leffler ctx->alloc_eapol = _wpa_alloc_eapol; 121039beb93cSSam Leffler ctx->cancel_auth_timeout = _wpa_supplicant_cancel_auth_timeout; 121139beb93cSSam Leffler ctx->add_pmkid = wpa_supplicant_add_pmkid; 121239beb93cSSam Leffler ctx->remove_pmkid = wpa_supplicant_remove_pmkid; 121339beb93cSSam Leffler #ifndef CONFIG_NO_CONFIG_BLOBS 121439beb93cSSam Leffler ctx->set_config_blob = wpa_supplicant_set_config_blob; 121539beb93cSSam Leffler ctx->get_config_blob = wpa_supplicant_get_config_blob; 121639beb93cSSam Leffler #endif /* CONFIG_NO_CONFIG_BLOBS */ 121739beb93cSSam Leffler ctx->mlme_setprotection = wpa_supplicant_mlme_setprotection; 121839beb93cSSam Leffler #ifdef CONFIG_IEEE80211R 121939beb93cSSam Leffler ctx->update_ft_ies = wpa_supplicant_update_ft_ies; 122039beb93cSSam Leffler ctx->send_ft_action = wpa_supplicant_send_ft_action; 1221e28a4053SRui Paulo ctx->mark_authenticated = wpa_supplicant_mark_authenticated; 122239beb93cSSam Leffler #endif /* CONFIG_IEEE80211R */ 1223f05cddf9SRui Paulo #ifdef CONFIG_TDLS 1224f05cddf9SRui Paulo ctx->tdls_get_capa = wpa_supplicant_tdls_get_capa; 1225f05cddf9SRui Paulo ctx->send_tdls_mgmt = wpa_supplicant_send_tdls_mgmt; 1226f05cddf9SRui Paulo ctx->tdls_oper = wpa_supplicant_tdls_oper; 1227f05cddf9SRui Paulo ctx->tdls_peer_addset = wpa_supplicant_tdls_peer_addset; 12285b9c547cSRui Paulo ctx->tdls_enable_channel_switch = 12295b9c547cSRui Paulo wpa_supplicant_tdls_enable_channel_switch; 12305b9c547cSRui Paulo ctx->tdls_disable_channel_switch = 12315b9c547cSRui Paulo wpa_supplicant_tdls_disable_channel_switch; 1232f05cddf9SRui Paulo #endif /* CONFIG_TDLS */ 1233f05cddf9SRui Paulo ctx->set_rekey_offload = wpa_supplicant_set_rekey_offload; 12345b9c547cSRui Paulo ctx->key_mgmt_set_pmk = wpa_supplicant_key_mgmt_set_pmk; 1235*85732ac8SCy Schubert ctx->fils_hlp_rx = wpa_supplicant_fils_hlp_rx; 123639beb93cSSam Leffler 123739beb93cSSam Leffler wpa_s->wpa = wpa_sm_init(ctx); 123839beb93cSSam Leffler if (wpa_s->wpa == NULL) { 123939beb93cSSam Leffler wpa_printf(MSG_ERROR, "Failed to initialize WPA state " 124039beb93cSSam Leffler "machine"); 12415b9c547cSRui Paulo os_free(ctx); 124239beb93cSSam Leffler return -1; 124339beb93cSSam Leffler } 124439beb93cSSam Leffler #endif /* CONFIG_NO_WPA */ 124539beb93cSSam Leffler 124639beb93cSSam Leffler return 0; 124739beb93cSSam Leffler } 124839beb93cSSam Leffler 124939beb93cSSam Leffler 125039beb93cSSam Leffler void wpa_supplicant_rsn_supp_set_config(struct wpa_supplicant *wpa_s, 125139beb93cSSam Leffler struct wpa_ssid *ssid) 125239beb93cSSam Leffler { 125339beb93cSSam Leffler struct rsn_supp_config conf; 125439beb93cSSam Leffler if (ssid) { 125539beb93cSSam Leffler os_memset(&conf, 0, sizeof(conf)); 125639beb93cSSam Leffler conf.network_ctx = ssid; 125739beb93cSSam Leffler conf.allowed_pairwise_cipher = ssid->pairwise_cipher; 125839beb93cSSam Leffler #ifdef IEEE8021X_EAPOL 1259f05cddf9SRui Paulo conf.proactive_key_caching = ssid->proactive_key_caching < 0 ? 1260f05cddf9SRui Paulo wpa_s->conf->okc : ssid->proactive_key_caching; 126139beb93cSSam Leffler conf.eap_workaround = ssid->eap_workaround; 126239beb93cSSam Leffler conf.eap_conf_ctx = &ssid->eap; 126339beb93cSSam Leffler #endif /* IEEE8021X_EAPOL */ 126439beb93cSSam Leffler conf.ssid = ssid->ssid; 126539beb93cSSam Leffler conf.ssid_len = ssid->ssid_len; 126639beb93cSSam Leffler conf.wpa_ptk_rekey = ssid->wpa_ptk_rekey; 12675b9c547cSRui Paulo #ifdef CONFIG_P2P 12685b9c547cSRui Paulo if (ssid->p2p_group && wpa_s->current_bss && 12695b9c547cSRui Paulo !wpa_s->p2p_disable_ip_addr_req) { 12705b9c547cSRui Paulo struct wpabuf *p2p; 12715b9c547cSRui Paulo p2p = wpa_bss_get_vendor_ie_multi(wpa_s->current_bss, 12725b9c547cSRui Paulo P2P_IE_VENDOR_TYPE); 12735b9c547cSRui Paulo if (p2p) { 12745b9c547cSRui Paulo u8 group_capab; 12755b9c547cSRui Paulo group_capab = p2p_get_group_capab(p2p); 12765b9c547cSRui Paulo if (group_capab & 12775b9c547cSRui Paulo P2P_GROUP_CAPAB_IP_ADDR_ALLOCATION) 12785b9c547cSRui Paulo conf.p2p = 1; 12795b9c547cSRui Paulo wpabuf_free(p2p); 12805b9c547cSRui Paulo } 12815b9c547cSRui Paulo } 12825b9c547cSRui Paulo #endif /* CONFIG_P2P */ 1283780fb4a2SCy Schubert conf.wpa_rsc_relaxation = wpa_s->conf->wpa_rsc_relaxation; 1284*85732ac8SCy Schubert #ifdef CONFIG_FILS 1285*85732ac8SCy Schubert if (wpa_key_mgmt_fils(wpa_s->key_mgmt)) 1286*85732ac8SCy Schubert conf.fils_cache_id = 1287*85732ac8SCy Schubert wpa_bss_get_fils_cache_id(wpa_s->current_bss); 1288*85732ac8SCy Schubert #endif /* CONFIG_FILS */ 128939beb93cSSam Leffler } 129039beb93cSSam Leffler wpa_sm_set_config(wpa_s->wpa, ssid ? &conf : NULL); 129139beb93cSSam Leffler } 1292