diff --git a/components/esp_wifi/Kconfig b/components/esp_wifi/Kconfig index 7d315d5205..233cf3480d 100644 --- a/components/esp_wifi/Kconfig +++ b/components/esp_wifi/Kconfig @@ -540,9 +540,37 @@ menu "Wi-Fi" and on the radio environment. Current implementation adds beacon report, link measurement, neighbor report. + config ESP_WIFI_RRM_SUPPORT + bool "Enable 802.11k APIs Support" + depends on ESP_WIFI_11KV_SUPPORT + default y + help + Select this option to enable 802.11k APIs(RRM support). + Only APIs which are helpful for network assisted roaming + are supported for now. + Enable this option with RRM enabled in sta config + to make device ready for network assisted roaming. + RRM: Radio measurements enable STAs to understand the radio environment, + it enables STAs to observe and gather data on radio link performance + and on the radio environment. Current implementation adds beacon report, + link measurement, neighbor report. + + config ESP_WIFI_WNM_SUPPORT + bool "Enable 802.11v APIs Support" + depends on ESP_WIFI_11KV_SUPPORT + default y + help + Select this option to enable 802.11v APIs(BTM support). + Only APIs which are helpful for network assisted roaming + are supported for now. + Enable this option with BTM enabled in sta config + to make device ready for network assisted roaming. + BTM: BSS transition management enables an AP to request a station to transition + to a specific AP, or to indicate to a station a set of preferred APs. + config ESP_WIFI_SCAN_CACHE bool "Keep scan results in cache" - depends on ESP_WIFI_11KV_SUPPORT + depends on ESP_WIFI_RRM_SUPPORT default n help Keep scan results in cache, if not enabled, those @@ -551,6 +579,8 @@ menu "Wi-Fi" config ESP_WIFI_MBO_SUPPORT bool "Enable Multi Band Operation Certification Support" default n + select ESP_WIFI_RRM_SUPPORT + select ESP_WIFI_WNM_SUPPORT select ESP_WIFI_11KV_SUPPORT select ESP_WIFI_SCAN_CACHE help diff --git a/components/esp_wifi/include/esp_wifi_types.h b/components/esp_wifi/include/esp_wifi_types.h index ddaa3896c3..1baecee50f 100644 --- a/components/esp_wifi/include/esp_wifi_types.h +++ b/components/esp_wifi/include/esp_wifi_types.h @@ -297,20 +297,21 @@ typedef enum { /** @brief Soft-AP configuration settings for the device */ typedef struct { - uint8_t ssid[32]; /**< SSID of soft-AP. If ssid_len field is 0, this must be a Null terminated string. Otherwise, length is set according to ssid_len. */ - uint8_t password[64]; /**< Password of soft-AP. */ - uint8_t ssid_len; /**< Optional length of SSID field. */ - uint8_t channel; /**< Channel of soft-AP */ - wifi_auth_mode_t authmode; /**< Auth mode of soft-AP. Do not support AUTH_WEP, AUTH_WAPI_PSK and AUTH_OWE in soft-AP mode. When the auth mode is set to WPA2_PSK, WPA2_WPA3_PSK or WPA3_PSK, the pairwise cipher will be overwritten with WIFI_CIPHER_TYPE_CCMP. */ - uint8_t ssid_hidden; /**< Broadcast SSID or not, default 0, broadcast the SSID */ - uint8_t max_connection; /**< Max number of stations allowed to connect in */ - uint16_t beacon_interval; /**< Beacon interval which should be multiples of 100. Unit: TU(time unit, 1 TU = 1024 us). Range: 100 ~ 60000. Default value: 100 */ - uint8_t csa_count; /**< Channel Switch Announcement Count. Notify the station that the channel will switch after the csa_count beacon intervals. Range: 1 ~ 30. Default value: 3 */ - uint8_t dtim_period; /**< Dtim period of soft-AP. Range: 1 ~ 10. Default value: 1 */ - wifi_cipher_type_t pairwise_cipher; /**< Pairwise cipher of SoftAP, group cipher will be derived using this. Cipher values are valid starting from WIFI_CIPHER_TYPE_TKIP, enum values before that will be considered as invalid and default cipher suites(TKIP+CCMP) will be used. Valid cipher suites in softAP mode are WIFI_CIPHER_TYPE_TKIP, WIFI_CIPHER_TYPE_CCMP and WIFI_CIPHER_TYPE_TKIP_CCMP. */ - bool ftm_responder; /**< Enable FTM Responder mode */ - wifi_pmf_config_t pmf_cfg; /**< Configuration for Protected Management Frame */ - wifi_sae_pwe_method_t sae_pwe_h2e; /**< Configuration for SAE PWE derivation method */ + uint8_t ssid[32]; /**< SSID of soft-AP. If ssid_len field is 0, this must be a Null terminated string. Otherwise, length is set according to ssid_len. */ + uint8_t password[64]; /**< Password of soft-AP. */ + uint8_t ssid_len; /**< Optional length of SSID field. */ + uint8_t channel; /**< Channel of soft-AP */ + wifi_auth_mode_t authmode; /**< Auth mode of soft-AP. Do not support AUTH_WEP, AUTH_WAPI_PSK and AUTH_OWE in soft-AP mode. When the auth mode is set to WPA2_PSK, WPA2_WPA3_PSK or WPA3_PSK, the pairwise cipher will be overwritten with WIFI_CIPHER_TYPE_CCMP. */ + uint8_t ssid_hidden; /**< Broadcast SSID or not, default 0, broadcast the SSID */ + uint8_t max_connection; /**< Max number of stations allowed to connect in */ + uint16_t beacon_interval; /**< Beacon interval which should be multiples of 100. Unit: TU(time unit, 1 TU = 1024 us). Range: 100 ~ 60000. Default value: 100 */ + uint8_t csa_count; /**< Channel Switch Announcement Count. Notify the station that the channel will switch after the csa_count beacon intervals. Default value: 3 */ + uint8_t dtim_period; /**< Dtim period of soft-AP. Range: 1 ~ 10. Default value: 1 */ + wifi_cipher_type_t pairwise_cipher; /**< Pairwise cipher of SoftAP, group cipher will be derived using this. Cipher values are valid starting from WIFI_CIPHER_TYPE_TKIP, enum values before that will be considered as invalid and default cipher suites(TKIP+CCMP) will be used. Valid cipher suites in softAP mode are WIFI_CIPHER_TYPE_TKIP, WIFI_CIPHER_TYPE_CCMP and WIFI_CIPHER_TYPE_TKIP_CCMP. */ + bool ftm_responder; /**< Enable FTM Responder mode */ + wifi_pmf_config_t pmf_cfg; /**< Configuration for Protected Management Frame */ + wifi_sae_pwe_method_t sae_pwe_h2e; /**< Configuration for SAE PWE derivation method */ + uint8_t transition_disable; /**< Whether to enable transition disable feature */ } wifi_ap_config_t; #define SAE_H2E_IDENTIFIER_LEN 32 @@ -346,7 +347,7 @@ typedef struct { uint32_t he_trig_mu_bmforming_partial_feedback_disabled:1; /**< Whether to disable support the transmission of partial-bandwidth MU feedback in an HE TB sounding sequence. */ uint32_t he_trig_cqi_feedback_disabled:1; /**< Whether to disable support the transmission of CQI feedback in an HE TB sounding sequence. */ uint32_t he_reserved:22; /**< Reserved for future feature set */ - uint8_t sae_h2e_identifier[SAE_H2E_IDENTIFIER_LEN];/**< Password identifier for H2E. this needs to be null terminated string */ + uint8_t sae_h2e_identifier[SAE_H2E_IDENTIFIER_LEN]; /**< Password identifier for H2E. this needs to be null terminated string */ } wifi_sta_config_t; /** diff --git a/components/esp_wifi/lib b/components/esp_wifi/lib index 0141af07f1..42e89e07f1 160000 --- a/components/esp_wifi/lib +++ b/components/esp_wifi/lib @@ -1 +1 @@ -Subproject commit 0141af07f1ad0093a49943a741a9a84a2dff271d +Subproject commit 42e89e07f1b46a2cb37549d214481063f55a322c diff --git a/components/wpa_supplicant/CMakeLists.txt b/components/wpa_supplicant/CMakeLists.txt index 2627c8cb3d..1d66bf7137 100644 --- a/components/wpa_supplicant/CMakeLists.txt +++ b/components/wpa_supplicant/CMakeLists.txt @@ -174,8 +174,11 @@ endif() if(CONFIG_ESP_WIFI_11KV_SUPPORT OR CONFIG_ESP_WIFI_11R_SUPPORT) set(roaming_src "src/common/ieee802_11_common.c") - if(CONFIG_ESP_WIFI_11KV_SUPPORT) - set(roaming_src ${roaming_src} "src/common/rrm.c" "src/common/wnm_sta.c") + if(CONFIG_ESP_WIFI_RRM_SUPPORT) + set(roaming_src ${roaming_src} "src/common/rrm.c") + endif() + if(CONFIG_ESP_WIFI_WNM_SUPPORT) + set(roaming_src ${roaming_src} "src/common/wnm_sta.c") endif() if(CONFIG_ESP_WIFI_11R_SUPPORT) set(roaming_src ${roaming_src} "src/rsn_supp/wpa_ft.c") @@ -283,7 +286,13 @@ if(CONFIG_ESP_WIFI_DPP_SUPPORT) target_compile_definitions(${COMPONENT_LIB} PRIVATE CONFIG_DPP) endif() if(CONFIG_ESP_WIFI_11KV_SUPPORT) - target_compile_definitions(${COMPONENT_LIB} PRIVATE CONFIG_SUPPLICANT_TASK CONFIG_WNM CONFIG_RRM CONFIG_IEEE80211KV) + target_compile_definitions(${COMPONENT_LIB} PRIVATE CONFIG_IEEE80211KV) +endif() +if(CONFIG_ESP_WIFI_RRM_SUPPORT) + target_compile_definitions(${COMPONENT_LIB} PRIVATE CONFIG_RRM) +endif() +if(CONFIG_ESP_WIFI_WNM_SUPPORT) + target_compile_definitions(${COMPONENT_LIB} PRIVATE CONFIG_WNM) endif() if(CONFIG_ESP_WIFI_11R_SUPPORT) target_compile_definitions(${COMPONENT_LIB} PRIVATE CONFIG_IEEE80211R) diff --git a/components/wpa_supplicant/esp_supplicant/src/crypto/crypto_mbedtls-ec.c b/components/wpa_supplicant/esp_supplicant/src/crypto/crypto_mbedtls-ec.c index b69a68288c..cc7d6c6f02 100644 --- a/components/wpa_supplicant/esp_supplicant/src/crypto/crypto_mbedtls-ec.c +++ b/components/wpa_supplicant/esp_supplicant/src/crypto/crypto_mbedtls-ec.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -1151,6 +1151,10 @@ struct wpabuf * crypto_ecdh_set_peerkey(struct crypto_ecdh *ecdh, int inc_y, int secret_key = 0; mbedtls_ecdh_context *ctx = (mbedtls_ecdh_context *)ecdh; + if (!ctx) { + wpa_printf(MSG_ERROR, "ECDH Context is NULL"); + return 0; + } mbedtls_ctr_drbg_context ctr_drbg; mbedtls_entropy_context entropy; @@ -1205,7 +1209,7 @@ struct wpabuf * crypto_ecdh_set_peerkey(struct crypto_ecdh *ecdh, int inc_y, /* Setup ECDH context from EC key */ /* Call to mbedtls_ecdh_get_params() will initialize the context when not LEGACY context */ - if (ctx != NULL && peer != NULL) { + if (peer != NULL) { mbedtls_ecp_copy( ACCESS_ECDH(&ctx, Qp), &(mbedtls_pk_ec(*peer))->MBEDTLS_PRIVATE(Q) ); #ifndef CONFIG_MBEDTLS_ECDH_LEGACY_CONTEXT ctx->MBEDTLS_PRIVATE(var) = MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0; diff --git a/components/wpa_supplicant/esp_supplicant/src/esp_common.c b/components/wpa_supplicant/esp_supplicant/src/esp_common.c index 36b147b09c..f69d4802ca 100644 --- a/components/wpa_supplicant/esp_supplicant/src/esp_common.c +++ b/components/wpa_supplicant/esp_supplicant/src/esp_common.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -35,43 +35,8 @@ esp_err_t esp_supplicant_str_to_mac(const char *str, uint8_t dest[6]) } struct wpa_supplicant g_wpa_supp; -#if defined(CONFIG_IEEE80211KV) || defined(CONFIG_IEEE80211R) -#ifdef CONFIG_SUPPLICANT_TASK -static void *s_supplicant_task_hdl = NULL; -static void *s_supplicant_evt_queue = NULL; -static void *s_supplicant_api_lock = NULL; -static bool s_supplicant_task_init_done; -#define SUPPLICANT_API_LOCK() os_mutex_lock(s_supplicant_api_lock) -#define SUPPLICANT_API_UNLOCK() os_mutex_unlock(s_supplicant_api_lock) -#define SUPPLICANT_TASK_STACK_SIZE (6144 + TASK_STACK_SIZE_ADD) - -static int handle_action_frm(u8 *frame, size_t len, - u8 *sender, int8_t rssi, u8 channel) -{ - struct ieee_mgmt_frame *frm = os_malloc(sizeof(struct ieee_mgmt_frame) + len); - - if (!frm) { - wpa_printf(MSG_ERROR, "memory allocation failed"); - return -1; - } - - os_memcpy(frm->sender, sender, ETH_ALEN); - frm->len = len; - frm->channel = channel; - frm->rssi = rssi; - - os_memcpy(frm->payload, frame, len); - if (esp_supplicant_post_evt(SIG_SUPPLICANT_RX_ACTION, (u32)frm) != 0) { - os_free(frm); - return -1; - } - - return 0; -} -#endif /* CONFIG_SUPPLICANT_TASK */ - -#if defined(CONFIG_IEEE80211KV) +#ifdef CONFIG_RRM static void handle_rrm_frame(struct wpa_supplicant *wpa_s, u8 *sender, u8 *payload, size_t len, int8_t rssi) { @@ -88,9 +53,12 @@ static void handle_rrm_frame(struct wpa_supplicant *wpa_s, u8 *sender, payload + 1, len - 1, rssi); } } +#endif /* CONFIG_RRM */ +#if defined(CONFIG_IEEE80211KV) static int mgmt_rx_action(u8 *frame, size_t len, u8 *sender, int8_t rssi, u8 channel) { + #if defined(CONFIG_RRM) || defined(CONFIG_WNM) u8 category; u8 bssid[ETH_ALEN]; struct wpa_supplicant *wpa_s = &g_wpa_supp; @@ -103,102 +71,70 @@ static int mgmt_rx_action(u8 *frame, size_t len, u8 *sender, int8_t rssi, u8 cha category = *frame++; len--; +#if defined(CONFIG_WNM) if (category == WLAN_ACTION_WNM) { ieee802_11_rx_wnm_action(wpa_s, sender, frame, len); - } else if (category == WLAN_ACTION_RADIO_MEASUREMENT) { + } +#endif /* CONFIG_WNM */ +#if defined(CONFIG_RRM) + if (category == WLAN_ACTION_RADIO_MEASUREMENT) { handle_rrm_frame(wpa_s, sender, frame, len, rssi); } - +#endif /* CONFIG_RRM */ +#endif /* defined(CONFIG_RRM) || defined(CONFIG_WNM) */ return 0; } -#endif /* defined(CONFIG_IEEE80211KV) */ -#ifdef CONFIG_SUPPLICANT_TASK -static void btm_rrm_task(void *pvParameters) -{ - supplicant_event_t evt; - bool task_del = false; - - while(1) { - if (os_queue_recv(s_supplicant_evt_queue, &evt, OS_BLOCK) != TRUE) - continue; - - /* event validation failed */ - if (evt.id >= SIG_SUPPLICANT_MAX) { - continue; - } - - switch (evt.id) { - case SIG_SUPPLICANT_RX_ACTION: - { - struct ieee_mgmt_frame *frm = (struct ieee_mgmt_frame *)evt.data; - mgmt_rx_action(frm->payload, frm->len, frm->sender, frm->rssi, frm->channel); - os_free(frm); - break; - } - - case SIG_SUPPLICANT_SCAN_DONE: - esp_supplicant_handle_scan_done_evt(); - break; - case SIG_SUPPLICANT_DEL_TASK: - task_del = true; - break; - default: - break; - } - - if (task_del) - break; - } - - os_queue_delete(s_supplicant_evt_queue); - s_supplicant_evt_queue = NULL; - - /* At this point, we completed */ - os_task_delete(NULL); -} -#endif /* CONFIG_SUPPLICANT_TASK */ - -static void clear_bssid_flag(struct wpa_supplicant *wpa_s) +#if defined(CONFIG_WNM) +static void clear_bssid_flag_and_channel(struct wpa_supplicant *wpa_s) { wifi_config_t *config; /* Reset only if btm is enabled */ - if (esp_wifi_is_btm_enabled_internal(WIFI_IF_STA) == false) - return; - - config = os_zalloc(sizeof(wifi_config_t)); - - if (!config) { - wpa_printf(MSG_ERROR, "failed to allocate memory"); + if (esp_wifi_is_btm_enabled_internal(WIFI_IF_STA) == false) { return; } - esp_wifi_get_config(WIFI_IF_STA, config); - if (config->sta.bssid_set) { - config->sta.bssid_set = 0; - esp_wifi_set_config(WIFI_IF_STA, config); - } - os_free(config); - wpa_printf(MSG_DEBUG, "cleared bssid flag"); + config = os_zalloc(sizeof(wifi_config_t)); + + if (!config) { + wpa_printf(MSG_ERROR, "failed to allocate memory"); + return; + } + + esp_wifi_get_config(WIFI_IF_STA, config); + if (config->sta.bssid_set || config->sta.channel) { + config->sta.channel = 0; + config->sta.bssid_set = 0; + esp_wifi_set_config(WIFI_IF_STA, config); + } + os_free(config); + wpa_printf(MSG_DEBUG, "cleared bssid flag"); } +#endif /* CONFIG_WNM */ +#endif /* CONFIG_IEEE80211KV */ +#if defined(CONFIG_IEEE80211KV) || defined(CONFIG_IEEE80211R) static void register_mgmt_frames(struct wpa_supplicant *wpa_s) { wpa_s->type &= ~(1 << WLAN_FC_STYPE_ACTION); /* subtype is defined only for action frame */ wpa_s->subtype = 0; -#ifdef CONFIG_IEEE80211KV +#ifdef CONFIG_RRM /* current supported features in supplicant: rrm and btm */ - if (esp_wifi_is_rm_enabled_internal(WIFI_IF_STA)) + if (esp_wifi_is_rm_enabled_internal(WIFI_IF_STA)) { wpa_s->subtype = 1 << WLAN_ACTION_RADIO_MEASUREMENT; - if (esp_wifi_is_btm_enabled_internal(WIFI_IF_STA)) + } +#endif /* CONFIG_RRM */ +#ifdef CONFIG_WNM + if (esp_wifi_is_btm_enabled_internal(WIFI_IF_STA)) { wpa_s->subtype |= 1 << WLAN_ACTION_WNM; - - if (wpa_s->subtype) + } +#endif /* CONFIG_WNM */ + if (wpa_s->subtype) { wpa_s->type |= 1 << WLAN_FC_STYPE_ACTION; -#endif /* CONFIG_IEEE80211KV */ + } #ifdef CONFIG_IEEE80211R /* register auth/assoc frames if FT is enabled */ @@ -209,6 +145,7 @@ static void register_mgmt_frames(struct wpa_supplicant *wpa_s) #endif /* CONFIG_IEEE80211R */ esp_wifi_register_mgmt_frame_internal(wpa_s->type, wpa_s->subtype); } +#endif /* defined(CONFIG_IEEE80211KV) || defined(CONFIG_IEEE80211R) */ #ifdef CONFIG_IEEE80211R static int handle_auth_frame(u8 *frame, size_t len, @@ -240,8 +177,20 @@ static int handle_assoc_frame(u8 *frame, size_t len, } return 0; } + +void wpa_sta_clear_ft_auth_ie(void) +{ + struct wpa_sm *sm = &gWpaSm; + wpa_printf(MSG_DEBUG, "Clearing all FT IE parameters and keys"); + /* Reset FT parameters */ + wpa_sm_set_ft_params(sm, NULL, 0); + esp_wifi_unset_appie_internal(WIFI_APPIE_RAM_STA_AUTH); + sm->ft_reassoc_completed = 0; + sm->ft_protocol = 0; + /* Clear pmk and ptk */ + wpa_sm_drop_sa(sm); +} #endif /* CONFIG_IEEE80211R */ -#endif /* defined(CONFIG_IEEE80211KV) || defined(CONFIG_IEEE80211R) */ void esp_supplicant_unset_all_appie(void) { @@ -257,7 +206,7 @@ static int ieee80211_handle_rx_frm(u8 type, u8 *frame, size_t len, u8 *sender, int ret = 0; switch (type) { -#if defined(CONFIG_IEEE80211R) || defined(CONFIG_IEEE80211KV) +#if defined(CONFIG_IEEE80211KV) || defined(CONFIG_IEEE80211R) case WLAN_FC_STYPE_BEACON: case WLAN_FC_STYPE_PROBE_RESP: ret = esp_handle_beacon_probe(type, frame, len, sender, rssi, channel, current_tsf); @@ -270,18 +219,14 @@ static int ieee80211_handle_rx_frm(u8 type, u8 *frame, size_t len, u8 *sender, #endif /* CONFIG_IEEE80211R */ case WLAN_FC_STYPE_ASSOC_RESP: case WLAN_FC_STYPE_REASSOC_RESP: - wpa_sm_notify_assoc(&gWpaSm, sender); #ifdef CONFIG_IEEE80211R ret = handle_assoc_frame(frame, len, sender, rssi, channel); #endif /* CONFIG_IEEE80211R */ + wpa_sm_notify_assoc(&gWpaSm, sender); break; #if defined(CONFIG_IEEE80211KV) case WLAN_FC_STYPE_ACTION: -#ifdef CONFIG_SUPPLICANT_TASK - ret = handle_action_frm(frame, len, sender, rssi, channel); -#else /* CONFIG_SUPPLICANT_TASK */ - ret = mgmt_rx_action(frame, len, sender, rssi, channel); -#endif /* CONFIG_SUPPLICANT_TASK */ + mgmt_rx_action(frame, len, sender, rssi, channel); break; #endif /* defined(CONFIG_IEEE80211KV) */ default: @@ -326,36 +271,10 @@ int esp_supplicant_common_init(struct wpa_funcs *wpa_cb) int ret = 0; #if defined(CONFIG_IEEE80211KV) || defined(CONFIG_IEEE80211R) -#ifdef CONFIG_SUPPLICANT_TASK - if (!s_supplicant_api_lock) { - s_supplicant_api_lock = os_recursive_mutex_create(); - } - - if (!s_supplicant_api_lock) { - wpa_printf(MSG_ERROR, "%s: failed to create Supplicant API lock", __func__); - ret = -1; - goto err; - } - - s_supplicant_evt_queue = os_queue_create(3, sizeof(supplicant_event_t)); - - if (!s_supplicant_evt_queue) { - wpa_printf(MSG_ERROR, "%s: failed to create Supplicant event queue", __func__); - ret = -1; - goto err; - } - ret = os_task_create(btm_rrm_task, "btm_rrm_t", SUPPLICANT_TASK_STACK_SIZE, NULL, 2, &s_supplicant_task_hdl); - if (ret != TRUE) { - wpa_printf(MSG_ERROR, "btm: failed to create task"); - ret = -1; - goto err; - } - s_supplicant_task_init_done = true; -#endif /* CONFIG_SUPPLICANT_TASK */ -#ifdef CONFIG_IEEE80211KV +#if defined(CONFIG_RRM) wpas_rrm_reset(wpa_s); wpas_clear_beacon_rep_data(wpa_s); -#endif /* CONFIG_IEEE80211KV */ +#endif /* defined(CONFIG_RRM) */ esp_scan_init(wpa_s); #endif /* defined(CONFIG_IEEE80211KV) || defined(CONFIG_IEEE80211R) */ @@ -385,37 +304,15 @@ void esp_supplicant_common_deinit(void) #if defined(CONFIG_IEEE80211KV) || defined(CONFIG_IEEE80211R) esp_scan_deinit(wpa_s); -#ifdef CONFIG_IEEE80211KV +#if defined(CONFIG_RRM) wpas_rrm_reset(wpa_s); wpas_clear_beacon_rep_data(wpa_s); -#endif /* CONFIG_IEEE80211KV */ +#endif /* defined(CONFIG_RRM) */ #endif /* defined(CONFIG_IEEE80211KV) || defined(CONFIG_IEEE80211R) */ if (wpa_s->type) { wpa_s->type = 0; esp_wifi_register_mgmt_frame_internal(wpa_s->type, wpa_s->subtype); } -#if defined(CONFIG_IEEE80211KV) || defined(CONFIG_IEEE80211R) -#ifdef CONFIG_SUPPLICANT_TASK - /* We have failed to create task, delete queue and exit */ - if (!s_supplicant_task_hdl) { - if (s_supplicant_evt_queue) { - os_queue_delete(s_supplicant_evt_queue); - s_supplicant_evt_queue = NULL; - } - if (s_supplicant_api_lock) { - os_mutex_delete(s_supplicant_api_lock); - s_supplicant_api_lock = NULL; - } - } else if (esp_supplicant_post_evt(SIG_SUPPLICANT_DEL_TASK, 0) != 0) { - /* failed to post delete event, just delete event queue and exit */ - if (s_supplicant_evt_queue) { - os_queue_delete(s_supplicant_evt_queue); - s_supplicant_evt_queue = NULL; - } - } - s_supplicant_task_init_done = false; -#endif /* CONFIG_SUPPLICANT_TASK */ -#endif /* defined(CONFIG_IEEE80211KV) || defined(CONFIG_IEEE80211R) */ } void supplicant_sta_conn_handler(uint8_t *bssid) @@ -435,28 +332,37 @@ void supplicant_sta_conn_handler(uint8_t *bssid) wpa_bss_flush(wpa_s); /* Register for mgmt frames */ register_mgmt_frames(wpa_s); +#if defined(CONFIG_WNM) /* clear set bssid flag */ - clear_bssid_flag(wpa_s); + clear_bssid_flag_and_channel(wpa_s); +#endif /* CONFIG_WNM */ #endif /* defined(CONFIG_IEEE80211KV) || defined(CONFIG_IEEE80211R) */ } -void supplicant_sta_disconn_handler(void) +void supplicant_sta_disconn_handler(uint8_t reason_code) { -#if defined(CONFIG_IEEE80211KV) || defined(CONFIG_IEEE80211R) +#if defined(CONFIG_IEEE80211KV) struct wpa_supplicant *wpa_s = &g_wpa_supp; -#ifdef CONFIG_IEEE80211KV +#if defined(CONFIG_RRM) wpas_rrm_reset(wpa_s); wpas_clear_beacon_rep_data(wpa_s); -#endif /* CONFIG_IEEE80211KV */ +#endif /* defined(CONFIG_RRM) */ +#if defined(CONFIG_WNM) + /* Not clearing in case of roaming disconnect as BTM induced connection + * itself sets a specific bssid and channel to connect to before disconnection. + * Subsequent connections or disconnections will clear this flag */ + if (reason_code != WIFI_REASON_ROAMING) { + clear_bssid_flag_and_channel(wpa_s); + } +#endif /* CONFIG_WNM */ if (wpa_s->current_bss) { wpa_s->current_bss = NULL; } -#endif /* defined(CONFIG_IEEE80211KV) || defined(CONFIG_IEEE80211R) */ +#endif /* defined(CONFIG_IEEE80211KV) */ } -#if defined(CONFIG_IEEE80211KV) || defined(CONFIG_IEEE80211R) -#ifdef CONFIG_IEEE80211KV +#if defined(CONFIG_RRM) bool esp_rrm_is_rrm_supported_connection(void) { struct wpa_supplicant *wpa_s = &g_wpa_supp; @@ -500,6 +406,33 @@ int esp_rrm_send_neighbor_rep_request(neighbor_rep_request_cb cb, return wpas_rrm_send_neighbor_rep_request(wpa_s, &wpa_ssid, 0, 0, cb, cb_ctx); } +static size_t get_rm_enabled_ie(uint8_t *ie, size_t len) +{ + uint8_t rrm_ie[7] = {0}; + uint8_t rrm_ie_len = 5; + uint8_t *pos = rrm_ie; + + if (!esp_wifi_is_rm_enabled_internal(WIFI_IF_STA)) { + return 0; + } + + *pos++ = WLAN_EID_RRM_ENABLED_CAPABILITIES; + *pos++ = rrm_ie_len; + *pos |= WLAN_RRM_CAPS_LINK_MEASUREMENT; + + *pos |= WLAN_RRM_CAPS_BEACON_REPORT_PASSIVE | +#ifdef SCAN_CACHE_SUPPORTED + WLAN_RRM_CAPS_BEACON_REPORT_TABLE | +#endif /* SCAN_CACHE_SUPPORTED */ + WLAN_RRM_CAPS_BEACON_REPORT_ACTIVE; + + os_memcpy(ie, rrm_ie, sizeof(rrm_ie)); + + return rrm_ie_len + 2; +} +#endif /* defined(CONFIG_RRM) */ + +#if defined(CONFIG_WNM) bool esp_wnm_is_btm_supported_connection(void) { struct wpa_supplicant *wpa_s = &g_wpa_supp; @@ -535,62 +468,45 @@ int esp_wnm_send_bss_transition_mgmt_query(enum btm_query_reason query_reason, return wnm_send_bss_transition_mgmt_query(wpa_s, query_reason, btm_candidates, cand_list); } -#ifdef CONFIG_MBO -int esp_mbo_update_non_pref_chan(struct non_pref_chan_s *non_pref_chan) +static uint8_t get_extended_caps_ie(uint8_t *ie, size_t len) { - int ret = wpas_mbo_update_non_pref_chan(&g_wpa_supp, non_pref_chan); + uint8_t ext_caps_ie[5] = {0}; + uint8_t ext_caps_ie_len = 3; + uint8_t *pos = ext_caps_ie; + wifi_ioctl_config_t cfg = {0}; + esp_err_t err = 0; - return ret; -} -#endif /* CONFIG_MBO */ - -void wpa_supplicant_connect(struct wpa_supplicant *wpa_s, - struct wpa_bss *bss, char *ssid) -{ - wifi_config_t *config = os_zalloc(sizeof(wifi_config_t)); - - if (!config) { - wpa_printf(MSG_ERROR, "failed to allocate memory"); - return; - } - - esp_wifi_get_config(WIFI_IF_STA, config); - /* We only support roaming in same ESS, therefore only bssid setting is needed */ - os_memcpy(config->sta.bssid, bss->bssid, ETH_ALEN); - config->sta.bssid_set = 1; - /* supplicant connect will only be called in case of bss transition(roaming) */ - esp_wifi_internal_issue_disconnect(WIFI_REASON_BSS_TRANSITION_DISASSOC); - esp_wifi_set_config(WIFI_IF_STA, config); - os_free(config); - esp_wifi_connect(); -} - -static size_t get_rm_enabled_ie(uint8_t *ie, size_t len) -{ - uint8_t rrm_ie[7] = {0}; - uint8_t rrm_ie_len = 5; - uint8_t *pos = rrm_ie; - - if (!esp_wifi_is_rm_enabled_internal(WIFI_IF_STA)) { + if (!esp_wifi_is_btm_enabled_internal(WIFI_IF_STA)) { return 0; } - *pos++ = WLAN_EID_RRM_ENABLED_CAPABILITIES; - *pos++ = rrm_ie_len; - *pos |= WLAN_RRM_CAPS_LINK_MEASUREMENT; + *pos++ = WLAN_EID_EXT_CAPAB; + *pos++ = ext_caps_ie_len; - *pos |= WLAN_RRM_CAPS_BEACON_REPORT_PASSIVE | -#ifdef SCAN_CACHE_SUPPORTED - WLAN_RRM_CAPS_BEACON_REPORT_TABLE | -#endif /* SCAN_CACHE_SUPPORTED */ - WLAN_RRM_CAPS_BEACON_REPORT_ACTIVE; + err = esp_wifi_internal_ioctl(WIFI_IOCTL_GET_STA_HT2040_COEX, &cfg); + if (err == ESP_OK && cfg.data.ht2040_coex.enable) { + *pos++ |= BIT(WLAN_EXT_CAPAB_20_40_COEX); + } else { + *pos++ = 0; + } + *pos ++ = 0; +#define CAPAB_BSS_TRANSITION BIT(3) + *pos |= CAPAB_BSS_TRANSITION; +#undef CAPAB_BSS_TRANSITION + os_memcpy(ie, ext_caps_ie, sizeof(ext_caps_ie)); - os_memcpy(ie, rrm_ie, sizeof(rrm_ie)); - - return rrm_ie_len + 2; + return ext_caps_ie_len + 2; } +#endif /* defined(CONFIG_WNM) */ #ifdef CONFIG_MBO +int esp_mbo_update_non_pref_chan(struct non_pref_chan_s *non_pref_chan) +{ + int ret = wpas_mbo_update_non_pref_chan(&g_wpa_supp, non_pref_chan); + + return ret; +} + static size_t get_mbo_oce_scan_ie(uint8_t *ie, size_t len) { uint8_t mbo_ie[32] = {0}; @@ -647,41 +563,31 @@ static uint8_t get_operating_class_ie(uint8_t *ie, size_t len) } #endif /* CONFIG_MBO */ -static uint8_t get_extended_caps_ie(uint8_t *ie, size_t len) +void wpa_supplicant_connect(struct wpa_supplicant *wpa_s, + struct wpa_bss *bss, char *ssid) { - uint8_t ext_caps_ie[5] = {0}; - uint8_t ext_caps_ie_len = 3; - uint8_t *pos = ext_caps_ie; - wifi_ioctl_config_t cfg = {0}; - esp_err_t err = 0; + wifi_config_t *config = os_zalloc(sizeof(wifi_config_t)); - if (!esp_wifi_is_btm_enabled_internal(WIFI_IF_STA)) { - return 0; + if (!config) { + wpa_printf(MSG_ERROR, "failed to allocate memory"); + return; } - *pos++ = WLAN_EID_EXT_CAPAB; - *pos++ = ext_caps_ie_len; - - err = esp_wifi_internal_ioctl(WIFI_IOCTL_GET_STA_HT2040_COEX, &cfg); - if (err == ESP_OK && cfg.data.ht2040_coex.enable) { - *pos++ |= BIT(WLAN_EXT_CAPAB_20_40_COEX); - } else { - *pos++ = 0; - } - *pos ++ = 0; -#define CAPAB_BSS_TRANSITION BIT(3) - *pos |= CAPAB_BSS_TRANSITION; -#undef CAPAB_BSS_TRANSITION - os_memcpy(ie, ext_caps_ie, sizeof(ext_caps_ie)); - - return ext_caps_ie_len + 2; + esp_wifi_get_config(WIFI_IF_STA, config); + /* We only support roaming in same ESS, therefore only bssid setting is needed */ + os_memcpy(config->sta.bssid, bss->bssid, ETH_ALEN); + config->sta.bssid_set = 1; + config->sta.channel = bss->channel; + /* supplicant connect will only be called in case of bss transition(roaming) */ + esp_wifi_internal_issue_disconnect(WIFI_REASON_BSS_TRANSITION_DISASSOC); + esp_wifi_set_config(WIFI_IF_STA, config); + os_free(config); + esp_wifi_connect(); } -#endif /* CONFIG_IEEE80211KV */ - +#if defined(CONFIG_WNM) || defined(CONFIG_MBO) void esp_set_scan_ie(void) { -#ifdef CONFIG_IEEE80211KV #define SCAN_IE_LEN 64 uint8_t *ie, *pos; size_t len = SCAN_IE_LEN, ie_len; @@ -692,25 +598,29 @@ void esp_set_scan_ie(void) return; } pos = ie; +#ifdef CONFIG_WNM ie_len = get_extended_caps_ie(pos, len); pos += ie_len; len -= ie_len; +#endif /* defined(CONFIG_WNM) */ #ifdef CONFIG_MBO ie_len = get_mbo_oce_scan_ie(pos, len); pos += ie_len; len -= ie_len; #endif /* CONFIG_MBO */ - esp_wifi_unset_appie_internal(WIFI_APPIE_PROBEREQ); - esp_wifi_set_appie_internal(WIFI_APPIE_PROBEREQ, ie, SCAN_IE_LEN - len, 0); + if (SCAN_IE_LEN - len) { + esp_wifi_unset_appie_internal(WIFI_APPIE_PROBEREQ); + esp_wifi_set_appie_internal(WIFI_APPIE_PROBEREQ, ie, SCAN_IE_LEN - len, 0); + } os_free(ie); #undef SCAN_IE_LEN -#endif /* CONFIG_IEEE80211KV */ } +#endif /* defined(CONFIG_WNM) || defined(CONFIG_MBO) */ #ifdef CONFIG_IEEE80211R static size_t add_mdie(uint8_t *bssid, uint8_t *ie, size_t len) { - size_t mdie_len = 0; + size_t mdie_len = 0; struct wpa_sm *sm = &gWpaSm; /* Return if MBO IE is not enabled in driver */ @@ -738,14 +648,11 @@ static size_t add_mdie(uint8_t *bssid, uint8_t *ie, size_t len) return mdie_len; } -#endif /* CONFIG_IEEE80211R */ - -#ifdef CONFIG_IEEE80211R int wpa_sm_update_ft_ies(struct wpa_sm *sm, const u8 *md, const u8 *ies, size_t ies_len, bool auth_ie) { - wpa_printf(MSG_INFO, "Updating FT IEs (len=%d)", ies_len); + wpa_printf(MSG_INFO, "Updating FT IEs (len=%d), auth_ie %d ", ies_len, auth_ie); if (os_memcmp(sm->mobility_domain, md, MOBILITY_DOMAIN_ID_LEN) != 0) { return 0; } @@ -811,69 +718,58 @@ int wpa_drv_send_action(struct wpa_supplicant *wpa_s, return ret; } -#ifdef CONFIG_SUPPLICANT_TASK -int esp_supplicant_post_evt(uint32_t evt_id, uint32_t data) +#ifndef CONFIG_WNM +void esp_set_scan_ie(void) { } +bool esp_wnm_is_btm_supported_connection(void) { - supplicant_event_t evt; - evt.id = evt_id; - evt.data = data; - - /* Make sure lock exists before taking it */ - SUPPLICANT_API_LOCK(); - - /* Make sure no event can be sent when deletion event is sent or task not initialized */ - if (!s_supplicant_task_init_done) { - SUPPLICANT_API_UNLOCK(); - return -1; - } - - if (os_queue_send(s_supplicant_evt_queue, &evt, os_task_ms_to_tick(10)) != TRUE) { - SUPPLICANT_API_UNLOCK(); - return -1; - } - if (evt_id == SIG_SUPPLICANT_DEL_TASK) { - s_supplicant_task_init_done = false; - } - SUPPLICANT_API_UNLOCK(); - return 0; + return false; } -#endif /* CONFIG_SUPPLICANT_TASK */ -#else /* defined(CONFIG_IEEE80211KV) || defined(CONFIG_IEEE80211R) */ +int esp_wnm_send_bss_transition_mgmt_query(enum btm_query_reason query_reason, + const char *btm_candidates, + int cand_list) +{ + return -1; +} +#endif + +#ifndef CONFIG_RRM +bool esp_rrm_is_rrm_supported_connection(void) +{ + return false; +} + +int esp_rrm_send_neighbor_report_request(void) +{ + return -1; +} + int esp_rrm_send_neighbor_rep_request(neighbor_rep_request_cb cb, void *cb_ctx) { return -1; } +#endif -int esp_wnm_send_bss_transition_mgmt_query(enum btm_query_reason query_reason, - const char *btm_candidates, - int cand_list) -{ - return -1; -} - -void esp_set_scan_ie(void) { } -#endif /* defined(CONFIG_IEEE80211KV) || defined(CONFIG_IEEE80211R) */ - -#if defined(CONFIG_IEEE80211KV) || defined(CONFIG_IEEE80211R) || defined(CONFIG_WPA3_SAE) +#if defined(CONFIG_RRM) || defined(CONFIG_IEEE80211R) || defined(CONFIG_WPA3_SAE) void esp_set_assoc_ie(uint8_t *bssid, const u8 *ies, size_t ies_len, bool mdie) { #define ASSOC_IE_LEN 128 uint8_t *ie, *pos; size_t len = ASSOC_IE_LEN; -#if defined(CONFIG_IEEE80211KV) || defined(CONFIG_IEEE80211R) +#if defined(CONFIG_RRM) || defined(CONFIG_IEEE80211R) size_t ie_len; #endif /* defined(CONFIG_IEEE80211KV) || defined(CONFIG_IEEE80211R) */ ie = os_malloc(ASSOC_IE_LEN + ies_len); if (!ie) { wpa_printf(MSG_ERROR, "failed to allocate ie"); - return; - } + return; + } pos = ie; -#ifdef CONFIG_IEEE80211KV +#if defined(CONFIG_RRM) ie_len = get_rm_enabled_ie(pos, len); pos += ie_len; len -= ie_len; +#endif /* defined(CONFIG_RRM) */ #ifdef CONFIG_MBO ie_len = get_operating_class_ie(pos, len); pos += ie_len; @@ -882,7 +778,6 @@ void esp_set_assoc_ie(uint8_t *bssid, const u8 *ies, size_t ies_len, bool mdie) pos += ie_len; len -= ie_len; #endif /* CONFIG_MBO */ -#endif /* CONFIG_IEEE80211KV */ #ifdef CONFIG_IEEE80211R if (mdie) { ie_len = add_mdie(bssid, pos, len); @@ -901,4 +796,4 @@ void esp_set_assoc_ie(uint8_t *bssid, const u8 *ies, size_t ies_len, bool mdie) } #else void esp_set_assoc_ie(uint8_t *bssid, const u8 *ies, size_t ies_len, bool mdie) { } -#endif /* defined(CONFIG_IEEE80211KV) || defined(CONFIG_IEEE80211R) || defined(CONFIG_WPA3_SAE) */ +#endif /* defined(CONFIG_RRM) || defined(CONFIG_IEEE80211R) || defined(CONFIG_WPA3_SAE) */ diff --git a/components/wpa_supplicant/esp_supplicant/src/esp_common_i.h b/components/wpa_supplicant/esp_supplicant/src/esp_common_i.h index e6c1d23290..3c72395a48 100644 --- a/components/wpa_supplicant/esp_supplicant/src/esp_common_i.h +++ b/components/wpa_supplicant/esp_supplicant/src/esp_common_i.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2020-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -12,7 +12,7 @@ struct wpa_funcs; extern struct wpa_supplicant g_wpa_supp; -#ifdef CONFIG_IEEE80211KV +#if defined(CONFIG_RRM) || defined(CONFIG_WNM) struct ieee_mgmt_frame { u8 sender[ETH_ALEN]; u8 channel; @@ -21,30 +21,17 @@ struct ieee_mgmt_frame { u8 payload[0]; }; -int esp_supplicant_post_evt(uint32_t evt_id, uint32_t data); - -typedef struct { - uint32_t id; - uint32_t data; -} supplicant_event_t; - -enum SIG_SUPPLICANT { - SIG_SUPPLICANT_RX_ACTION, - SIG_SUPPLICANT_SCAN_DONE, - SIG_SUPPLICANT_DEL_TASK, - SIG_SUPPLICANT_MAX, -}; - void esp_get_tx_power(uint8_t *tx_power); #ifdef CONFIG_MBO bool mbo_bss_profile_match(u8 *bssid); #endif -#endif +#endif /* defined(CONFIG_RRM) || defined(CONFIG_WNM) */ int esp_supplicant_common_init(struct wpa_funcs *wpa_cb); void esp_supplicant_common_deinit(void); void esp_supplicant_unset_all_appie(void); void esp_set_scan_ie(void); void esp_set_assoc_ie(uint8_t *bssid, const u8 *ies, size_t ies_len, bool add_mdie); void supplicant_sta_conn_handler(uint8_t* bssid); -void supplicant_sta_disconn_handler(void); +void supplicant_sta_disconn_handler(uint8_t reason_code); #endif +void wpa_sta_clear_ft_auth_ie(void); diff --git a/components/wpa_supplicant/esp_supplicant/src/esp_hostap.c b/components/wpa_supplicant/esp_supplicant/src/esp_hostap.c index 5bc9f7fa31..f6c6ebb6a2 100644 --- a/components/wpa_supplicant/esp_supplicant/src/esp_hostap.c +++ b/components/wpa_supplicant/esp_supplicant/src/esp_hostap.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2019-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2019-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -162,6 +162,19 @@ void *hostap_init(void) os_memcpy(hapd->conf->ssid.wpa_passphrase, esp_wifi_ap_get_prof_password_internal(), strlen((char *)esp_wifi_ap_get_prof_password_internal())); hapd->conf->ssid.wpa_passphrase[WIFI_PASSWORD_LEN_MAX - 1] = '\0'; hapd->conf->max_num_sta = esp_wifi_ap_get_max_sta_conn(); + auth_conf->transition_disable = esp_wifi_ap_get_transition_disable_internal(); + if (authmode != WIFI_AUTH_WPA3_PSK && + authmode != WIFI_AUTH_WPA2_WPA3_PSK && auth_conf->transition_disable) { + auth_conf->transition_disable = 0; + wpa_printf(MSG_DEBUG, "overriding transition_disable config with 0 as authmode is not WPA3"); + } + +#ifdef CONFIG_SAE + auth_conf->sae_require_mfp = 1; +#endif /* CONFIG_SAE */ + + //TODO change it when AP support GCMP-PSK + auth_conf->group_mgmt_cipher = WPA_CIPHER_AES_128_CMAC; hapd->conf->ap_max_inactivity = 5 * 60; hostapd_setup_wpa_psk(hapd->conf); @@ -348,7 +361,7 @@ uint8_t wpa_status_to_reason_code(int status) } bool hostap_new_assoc_sta(struct sta_info *sta, uint8_t *bssid, uint8_t *wpa_ie, - uint8_t wpa_ie_len, uint8_t *rsnxe, uint8_t rsnxe_len, + uint8_t wpa_ie_len, uint8_t *rsnxe, uint16_t rsnxe_len, bool *pmf_enable, int subtype, uint8_t *pairwise_cipher, uint8_t *reason) { struct hostapd_data *hapd = (struct hostapd_data*)esp_wifi_get_hostap_private_internal(); diff --git a/components/wpa_supplicant/esp_supplicant/src/esp_scan.c b/components/wpa_supplicant/esp_supplicant/src/esp_scan.c index b0192bb94b..2e1ae8eed7 100644 --- a/components/wpa_supplicant/esp_supplicant/src/esp_scan.c +++ b/components/wpa_supplicant/esp_supplicant/src/esp_scan.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -35,16 +35,10 @@ static void scan_done_event_handler(void *arg, ETS_STATUS status) wpa_s->type &= ~(1 << WLAN_FC_STYPE_BEACON) & ~(1 << WLAN_FC_STYPE_PROBE_RESP); esp_wifi_register_mgmt_frame_internal(wpa_s->type, wpa_s->subtype); } -#ifdef CONFIG_SUPPLICANT_TASK - if (esp_supplicant_post_evt(SIG_SUPPLICANT_SCAN_DONE, 0) != 0) { - wpa_printf(MSG_ERROR, "Posting of scan done failed!"); - } -#else - esp_supplicant_handle_scan_done_evt(); -#endif /*CONFIG_SUPPLICANT_TASK*/ + esp_supplicant_handle_scan_done_evt(); } -#if defined(CONFIG_IEEE80211KV) +#if defined(CONFIG_WNM) static void handle_wnm_scan_done(struct wpa_supplicant *wpa_s) { struct wpa_bss *bss = wpa_bss_get_next_bss(wpa_s, wpa_s->current_bss); @@ -77,11 +71,14 @@ void esp_supplicant_handle_scan_done_evt(void) struct wpa_supplicant *wpa_s = &g_wpa_supp; wpa_printf(MSG_INFO, "scan done received"); -#if defined(CONFIG_IEEE80211KV) +#if defined(CONFIG_RRM) /* Check which module started this, call the respective function */ if (wpa_s->scan_reason == REASON_RRM_BEACON_REPORT) { wpas_beacon_rep_scan_process(wpa_s, wpa_s->scan_start_tsf); - } else if (wpa_s->scan_reason == REASON_WNM_BSS_TRANS_REQ) { + } +#endif +#if defined(CONFIG_WNM) + if (wpa_s->scan_reason == REASON_WNM_BSS_TRANS_REQ) { handle_wnm_scan_done(wpa_s); } #endif diff --git a/components/wpa_supplicant/esp_supplicant/src/esp_wifi_driver.h b/components/wpa_supplicant/esp_supplicant/src/esp_wifi_driver.h index 1203f09ddf..fd3b1019c6 100644 --- a/components/wpa_supplicant/esp_supplicant/src/esp_wifi_driver.h +++ b/components/wpa_supplicant/esp_supplicant/src/esp_wifi_driver.h @@ -127,7 +127,7 @@ struct wpa_funcs { bool (*wpa_sta_in_4way_handshake)(void); void *(*wpa_ap_init)(void); bool (*wpa_ap_deinit)(void *data); - bool (*wpa_ap_join)(void **sm, u8 *bssid, u8 *wpa_ie, u8 wpa_ie_len, u8* rsnxe, u8 rsnxe_len, bool *pmf_enable, int subtype, uint8_t *pairwise_cipher); + bool (*wpa_ap_join)(void **sm, u8 *bssid, u8 *wpa_ie, u8 wpa_ie_len, u8* rsnxe, u16 rsnxe_len, bool *pmf_enable, int subtype, uint8_t *pairwise_cipher); bool (*wpa_ap_remove)(u8 *bssid); uint8_t *(*wpa_ap_get_wpa_ie)(uint8_t *len); bool (*wpa_ap_rx_eapol)(void *hapd_data, void *sm, u8 *data, size_t data_len); @@ -303,5 +303,6 @@ bool esp_wifi_eb_tx_status_success_internal(void *eb); uint8_t* esp_wifi_sta_get_rsnxe(u8 *bssid); esp_err_t esp_wifi_sta_connect_internal(const uint8_t *bssid); void esp_wifi_enable_sae_pk_only_mode_internal(void); +uint8_t esp_wifi_ap_get_transition_disable_internal(void); #endif /* _ESP_WIFI_DRIVER_H_ */ diff --git a/components/wpa_supplicant/esp_supplicant/src/esp_wpa3.c b/components/wpa_supplicant/esp_supplicant/src/esp_wpa3.c index 27b8a1433e..aa858144b3 100644 --- a/components/wpa_supplicant/esp_supplicant/src/esp_wpa3.c +++ b/components/wpa_supplicant/esp_supplicant/src/esp_wpa3.c @@ -523,6 +523,11 @@ static void wpa3_process_rx_confirm(wpa3_hostap_auth_event_t *evt) goto done; } if (ret == WLAN_STATUS_SUCCESS) { + if (sta->sae_data && esp_send_sae_auth_reply(hapd, sta->addr, frm->bssid, WLAN_AUTH_SAE, 2, + WLAN_STATUS_SUCCESS, wpabuf_head(sta->sae_data), wpabuf_len(sta->sae_data)) != ESP_OK) { + ap_free_sta(hapd, sta); + goto done; + } if (esp_wifi_ap_notify_node_sae_auth_done(frm->bssid) != true) { ap_free_sta(hapd, sta); goto done; @@ -534,6 +539,11 @@ static void wpa3_process_rx_confirm(wpa3_hostap_auth_event_t *evt) esp_wifi_ap_get_sta_aid(frm->bssid, &aid); if (aid == 0) { esp_wifi_ap_deauth_internal(frm->bssid, ret); + } else { + if (sta && sta->sae_data) { + wpabuf_free(sta->sae_data); + sta->sae_data = NULL; + } } } } diff --git a/components/wpa_supplicant/esp_supplicant/src/esp_wpa_main.c b/components/wpa_supplicant/esp_supplicant/src/esp_wpa_main.c index 31734d110a..463fa33454 100644 --- a/components/wpa_supplicant/esp_supplicant/src/esp_wpa_main.c +++ b/components/wpa_supplicant/esp_supplicant/src/esp_wpa_main.c @@ -260,8 +260,14 @@ static void wpa_sta_disconnected_cb(uint8_t reason_code) case WIFI_REASON_ASSOC_FAIL: case WIFI_REASON_CONNECTION_FAIL: case WIFI_REASON_HANDSHAKE_TIMEOUT: + case WIFI_REASON_INVALID_MDE: + case WIFI_REASON_INVALID_FTE: wpa_sta_clear_curr_pmksa(); wpa_sm_notify_disassoc(&gWpaSm); +#if defined(CONFIG_IEEE80211R) + /* clear all ft auth related IEs so that next will be open auth */ + wpa_sta_clear_ft_auth_ie(); +#endif break; default: if (g_wpa_pmk_caching_disabled) { @@ -280,7 +286,7 @@ static void wpa_sta_disconnected_cb(uint8_t reason_code) #endif /* CONFIG_OWE_STA */ esp_wpa3_free_sae_data(); - supplicant_sta_disconn_handler(); + supplicant_sta_disconn_handler(reason_code); } #ifdef CONFIG_ESP_WIFI_SOFTAP_SUPPORT @@ -318,7 +324,7 @@ static int check_n_add_wps_sta(struct hostapd_data *hapd, struct sta_info *sta_i } #endif -static bool hostap_sta_join(void **sta, u8 *bssid, u8 *wpa_ie, u8 wpa_ie_len, u8 *rsnxe, u8 rsnxe_len, bool *pmf_enable, int subtype, uint8_t *pairwise_cipher) +static bool hostap_sta_join(void **sta, u8 *bssid, u8 *wpa_ie, u8 wpa_ie_len, u8 *rsnxe, u16 rsnxe_len, bool *pmf_enable, int subtype, uint8_t *pairwise_cipher) { struct sta_info *sta_info = NULL; struct hostapd_data *hapd = hostapd_get_hapd_data(); diff --git a/components/wpa_supplicant/src/ap/ap_config.h b/components/wpa_supplicant/src/ap/ap_config.h index 1d11dd4816..731b1da032 100644 --- a/components/wpa_supplicant/src/ap/ap_config.h +++ b/components/wpa_supplicant/src/ap/ap_config.h @@ -383,7 +383,7 @@ const u8 * hostapd_get_psk(const struct hostapd_bss_config *conf, int hostapd_setup_wpa_psk(struct hostapd_bss_config *conf); struct sta_info; bool hostap_new_assoc_sta(struct sta_info *sta, uint8_t *bssid, uint8_t *wpa_ie, - uint8_t wpa_ie_len,uint8_t *rsnxe, uint8_t rsnxe_len, + uint8_t wpa_ie_len, uint8_t *rsnxe, uint16_t rsnxe_len, bool *pmf_enable, int subtype, uint8_t *pairwise_cipher, uint8_t *reason); bool wpa_ap_remove(u8* bssid); diff --git a/components/wpa_supplicant/src/ap/ieee802_11.c b/components/wpa_supplicant/src/ap/ieee802_11.c index a2f5365a46..d0ac26c6ca 100644 --- a/components/wpa_supplicant/src/ap/ieee802_11.c +++ b/components/wpa_supplicant/src/ap/ieee802_11.c @@ -178,14 +178,18 @@ static int auth_sae_send_confirm(struct hostapd_data *hapd, #ifdef ESP_SUPPLICANT if (sta->remove_pending) { reply_res = -1; + wpabuf_free(data); } else { - reply_res = esp_send_sae_auth_reply(hapd, sta->addr, bssid, WLAN_AUTH_SAE, 2, - WLAN_STATUS_SUCCESS, wpabuf_head(data), - wpabuf_len(data)); + if (sta->sae_data) + wpabuf_free(sta->sae_data); + sta->sae_data = data; + reply_res = 0; + /* confirm is sent in later stage when all the required processing for a sta is done*/ } +#else + wpabuf_free(data); #endif /* ESP_SUPPLICANT */ - wpabuf_free(data); return reply_res; } @@ -675,7 +679,7 @@ int auth_sae_queue(struct hostapd_data *hapd, unsigned int queue_len; queue_len = dl_list_len(&hapd->sae_commit_queue); - if (queue_len >= 5) { + if (queue_len >= hapd->conf->max_num_sta) { wpa_printf(MSG_DEBUG, "SAE: No more room in message queue - drop the new frame from " MACSTR, MAC2STR(bssid)); diff --git a/components/wpa_supplicant/src/ap/sta_info.c b/components/wpa_supplicant/src/ap/sta_info.c index 66e856ebee..0894486373 100644 --- a/components/wpa_supplicant/src/ap/sta_info.c +++ b/components/wpa_supplicant/src/ap/sta_info.c @@ -113,6 +113,10 @@ void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta) os_mutex_delete(sta->lock); sta->lock = NULL; } + if (sta->sae_data) { + wpabuf_free(sta->sae_data); + sta->sae_data = NULL; + } #endif /* CONFIG_SAE */ wpa_auth_sta_deinit(sta->wpa_sm); #ifdef CONFIG_WPS_REGISTRAR diff --git a/components/wpa_supplicant/src/ap/sta_info.h b/components/wpa_supplicant/src/ap/sta_info.h index af475d09c0..3c3769dd1a 100644 --- a/components/wpa_supplicant/src/ap/sta_info.h +++ b/components/wpa_supplicant/src/ap/sta_info.h @@ -66,6 +66,7 @@ struct sta_info { * processing commit for that station */ bool remove_pending; /* Flag to indicate to free station when * whose mutex is taken by task */ + struct wpabuf *sae_data; #endif /* CONFIG_SAE */ #endif /* ESP_SUPPLICANT */ diff --git a/components/wpa_supplicant/src/ap/wpa_auth.c b/components/wpa_supplicant/src/ap/wpa_auth.c index 18a5069fb3..221098f1f5 100644 --- a/components/wpa_supplicant/src/ap/wpa_auth.c +++ b/components/wpa_supplicant/src/ap/wpa_auth.c @@ -1875,6 +1875,10 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING) } kde_len = wpa_ie_len + ieee80211w_kde_len(sm); + + if (sm->wpa_auth->conf.transition_disable) + kde_len += 2 + RSN_SELECTOR_LEN + 1; + if (gtk) kde_len += 2 + RSN_SELECTOR_LEN + 2 + gtk_len; #ifdef CONFIG_IEEE80211R_AP @@ -1911,6 +1915,9 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING) } pos = ieee80211w_kde_add(sm, pos); + if (sm->wpa_auth->conf.transition_disable) + pos = wpa_add_kde(pos, WFA_KEY_DATA_TRANSITION_DISABLE, + &sm->wpa_auth->conf.transition_disable, 1, NULL, 0); #ifdef CONFIG_IEEE80211R_AP if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) { int res; diff --git a/components/wpa_supplicant/src/ap/wpa_auth.h b/components/wpa_supplicant/src/ap/wpa_auth.h index e39c1425e4..057838ce87 100644 --- a/components/wpa_supplicant/src/ap/wpa_auth.h +++ b/components/wpa_supplicant/src/ap/wpa_auth.h @@ -144,6 +144,10 @@ struct wpa_auth_config { #ifdef CONFIG_IEEE80211W enum mfp_options ieee80211w; #endif /* CONFIG_IEEE80211W */ + int group_mgmt_cipher; +#ifdef CONFIG_SAE + int sae_require_mfp; +#endif /* CONFIG_SAE */ #ifdef CONFIG_IEEE80211R #define SSID_LEN 32 u8 ssid[SSID_LEN]; @@ -163,6 +167,7 @@ struct wpa_auth_config { int ap_mlme; enum sae_pwe sae_pwe; struct rsn_sppamsdu_sup spp_sup; + u8 transition_disable; }; typedef enum { diff --git a/components/wpa_supplicant/src/ap/wpa_auth_ie.c b/components/wpa_supplicant/src/ap/wpa_auth_ie.c index e25223d0fe..1eedb701c2 100644 --- a/components/wpa_supplicant/src/ap/wpa_auth_ie.c +++ b/components/wpa_supplicant/src/ap/wpa_auth_ie.c @@ -388,6 +388,7 @@ u8 * wpa_add_kde(u8 *pos, u32 kde, const u8 *data, size_t data_len, return pos; } + enum wpa_validate_result wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth, struct wpa_state_machine *sm, @@ -563,13 +564,25 @@ wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth, return WPA_MGMT_FRAME_PROTECTION_VIOLATION; } - if (data.mgmt_group_cipher != WPA_CIPHER_AES_128_CMAC) { - wpa_printf( MSG_DEBUG, "Unsupported management group " + if (data.mgmt_group_cipher != wpa_auth->conf.group_mgmt_cipher) + { + wpa_printf(MSG_DEBUG, "Unsupported management group " "cipher %d", data.mgmt_group_cipher); return WPA_INVALID_MGMT_GROUP_CIPHER; } } +#ifdef CONFIG_SAE + if (wpa_auth->conf.ieee80211w == MGMT_FRAME_PROTECTION_OPTIONAL && + wpa_auth->conf.sae_require_mfp && + wpa_key_mgmt_sae(sm->wpa_key_mgmt) && + !(data.capabilities & WPA_CAPABILITY_MFPC)) { + wpa_printf(MSG_DEBUG, + "Management frame protection required with SAE, but client did not enable it"); + return WPA_MGMT_FRAME_PROTECTION_VIOLATION; + } +#endif /* CONFIG_SAE */ + if (wpa_auth->conf.ieee80211w == NO_MGMT_FRAME_PROTECTION || !(data.capabilities & WPA_CAPABILITY_MFPC)) sm->mgmt_frame_prot = 0; diff --git a/components/wpa_supplicant/src/common/ieee802_11_common.c b/components/wpa_supplicant/src/common/ieee802_11_common.c index 61a753f442..129eed6671 100644 --- a/components/wpa_supplicant/src/common/ieee802_11_common.c +++ b/components/wpa_supplicant/src/common/ieee802_11_common.c @@ -268,7 +268,7 @@ static int ieee802_11_parse_extension(struct wpa_supplicant *wpa_s, const struct */ int ieee802_11_parse_elems(struct wpa_supplicant *wpa_s, const u8 *start, size_t len) { -#if defined(CONFIG_RRM) || defined(CONFIG_SAE_PK) +#if defined(CONFIG_RRM) || defined(CONFIG_WNM) || defined(CONFIG_SAE_PK) const struct element *elem; u8 unknown = 0; @@ -297,7 +297,7 @@ int ieee802_11_parse_elems(struct wpa_supplicant *wpa_s, const u8 *start, size_t } break; #endif /*CONFIG_SAE_PK*/ -#ifdef CONFIG_RRM +#ifdef CONFIG_WNM case WLAN_EID_EXT_CAPAB: /* extended caps can go beyond 8 octacts but we aren't using them now */ os_memcpy(wpa_s->extend_caps, pos, 5); @@ -311,7 +311,7 @@ int ieee802_11_parse_elems(struct wpa_supplicant *wpa_s, const u8 *start, size_t if (unknown) return -1; -#endif /* defined(CONFIG_RRM) || defined(CONFIG_SAE_PK) */ +#endif /* defined(CONFIG_RRM) || defined(CONFIG_WNM) || defined(CONFIG_SAE_PK) */ return 0; } diff --git a/components/wpa_supplicant/src/rsn_supp/wpa.c b/components/wpa_supplicant/src/rsn_supp/wpa.c index 208ecbbef0..0716521ac0 100644 --- a/components/wpa_supplicant/src/rsn_supp/wpa.c +++ b/components/wpa_supplicant/src/rsn_supp/wpa.c @@ -2718,8 +2718,6 @@ struct wpa_sm * get_wpa_sm(void) int wpa_sm_set_ap_rsnxe(const u8 *ie, size_t len) { struct wpa_sm *sm = &gWpaSm; - if (!sm) - return -1; os_free(sm->ap_rsnxe); if (!ie || len == 0) { diff --git a/examples/wifi/getting_started/station/sdkconfig.ci.ft b/examples/wifi/getting_started/station/sdkconfig.ci.ft new file mode 100644 index 0000000000..10169bbff2 --- /dev/null +++ b/examples/wifi/getting_started/station/sdkconfig.ci.ft @@ -0,0 +1 @@ +CONFIG_ESP_WIFI_11R_SUPPORT=y diff --git a/examples/wifi/getting_started/station/sdkconfig.ci.rrm b/examples/wifi/getting_started/station/sdkconfig.ci.rrm new file mode 100644 index 0000000000..61c172f523 --- /dev/null +++ b/examples/wifi/getting_started/station/sdkconfig.ci.rrm @@ -0,0 +1,2 @@ +CONFIG_ESP_WIFI_11KV_SUPPORT=y +CONFIG_ESP_WIFI_RRM_SUPPORT=y diff --git a/examples/wifi/getting_started/station/sdkconfig.ci.wnm b/examples/wifi/getting_started/station/sdkconfig.ci.wnm new file mode 100644 index 0000000000..9f87bf640e --- /dev/null +++ b/examples/wifi/getting_started/station/sdkconfig.ci.wnm @@ -0,0 +1,2 @@ +CONFIG_ESP_WIFI_11KV_SUPPORT=y +CONFIG_ESP_WIFI_WNM_SUPPORT=y diff --git a/examples/wifi/roaming/sdkconfig.defaults b/examples/wifi/roaming/sdkconfig.defaults index ff2266a0c3..9c28a30aed 100644 --- a/examples/wifi/roaming/sdkconfig.defaults +++ b/examples/wifi/roaming/sdkconfig.defaults @@ -2,3 +2,5 @@ CONFIG_ESP_WIFI_11KV_SUPPORT=y CONFIG_ESP_WIFI_SCAN_CACHE=y CONFIG_ESP_WIFI_MBO_SUPPORT=y CONFIG_ESP_WIFI_11R_SUPPORT=y +CONFIG_ESP_WIFI_RRM_SUPPORT=y +CONFIG_ESP_WIFI_WNM_SUPPORT=y