mirror of
https://github.com/espressif/esp-idf.git
synced 2025-10-03 10:30:58 +02:00
feat(roaming): ignore WPA2-only APs on transition disable
This commit introduces a new feature to the roaming logic. If the currently connected AP has the 'transition disable' bit set in its RSN IE, the roaming logic will now ignore any scanned APs that only support WPA2-PSK. This prevents a security downgrade when roaming in a mixed WPA2/WPA3 environment. A new Kconfig option, CONFIG_ESP_WIFI_IGNORE_WPA2_ONLY_ON_TRANSITION_DISABLE, has been added to control this feature. It is disabled by default.
This commit is contained in:
@@ -219,4 +219,13 @@ menu "Blacklist Configuration"
|
|||||||
default 5
|
default 5
|
||||||
help
|
help
|
||||||
Maximum number of roaming candidates to consider. This also defines the size of the blacklist.
|
Maximum number of roaming candidates to consider. This also defines the size of the blacklist.
|
||||||
|
|
||||||
|
config ESP_WIFI_ROAMING_PREVENT_DOWNGRADE
|
||||||
|
bool "Prevent security downgrade when roaming"
|
||||||
|
default n
|
||||||
|
help
|
||||||
|
If the currently connected AP sends a "transition disable" bit,
|
||||||
|
this option will make the roaming logic ignore less secure APs.
|
||||||
|
This helps prevent security downgrades when roaming in a mixed
|
||||||
|
security environment (e.g., WPA2/WPA3).
|
||||||
endmenu # "Blacklist Configuration"
|
endmenu # "Blacklist Configuration"
|
||||||
|
@@ -605,8 +605,40 @@ static bool candidate_security_match(wifi_ap_record_t candidate)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#include "esp_wpas_glue.h"
|
||||||
|
|
||||||
static bool candidate_profile_match(wifi_ap_record_t candidate)
|
static bool candidate_profile_match(wifi_ap_record_t candidate)
|
||||||
{
|
{
|
||||||
|
u8 transition_disable = wpa_supplicant_get_transition_disable();
|
||||||
|
|
||||||
|
#if CONFIG_ESP_WIFI_ROAMING_PREVENT_DOWNGRADE
|
||||||
|
if (transition_disable & TRANSITION_DISABLE_WPA3_PERSONAL) {
|
||||||
|
if (candidate.authmode == WIFI_AUTH_WPA2_PSK) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (transition_disable & TRANSITION_DISABLE_ENHANCED_OPEN) {
|
||||||
|
if (candidate.authmode == WIFI_AUTH_OPEN) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (transition_disable & TRANSITION_DISABLE_WPA3_ENTERPRISE) {
|
||||||
|
if (candidate.authmode == WIFI_AUTH_WPA2_ENTERPRISE) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#if TODO // application doesn't have a way to know SAE-PK enabled AP atm
|
||||||
|
if (transition_disable & TRANSITION_DISABLE_SAE_PK) {
|
||||||
|
/* This is a simplification. A more accurate check would involve
|
||||||
|
* parsing the candidate's RSN IE to see if it supports SAE-PK.
|
||||||
|
* For now, we reject all SAE APs if SAE-PK is enforced. */
|
||||||
|
if (candidate.authmode == WIFI_AUTH_WPA3_PSK) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
return candidate_security_match(candidate);
|
return candidate_security_match(candidate);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -189,4 +189,9 @@ void wpa_sm_disassociate(struct wpa_sm *sm, int reason_code)
|
|||||||
{
|
{
|
||||||
/*check if need clear internal state and data value*/
|
/*check if need clear internal state and data value*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u8 wpa_supplicant_get_transition_disable(void)
|
||||||
|
{
|
||||||
|
return wpa_sm_get_transition_disable(&gWpaSm);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 2019-2021 Espressif Systems (Shanghai) CO LTD
|
* SPDX-FileCopyrightText: 2019-2025 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
@@ -35,4 +35,6 @@ void wpa_supplicant_transition_disable(struct wpa_sm *sm, u8 bitmap);
|
|||||||
|
|
||||||
int hostapd_send_eapol(const u8 *source, const u8 *sta_addr,
|
int hostapd_send_eapol(const u8 *source, const u8 *sta_addr,
|
||||||
const u8 *data, size_t data_len);
|
const u8 *data, size_t data_len);
|
||||||
|
|
||||||
|
u8 wpa_supplicant_get_transition_disable(void);
|
||||||
#endif /* WPAS_GLUE_H */
|
#endif /* WPAS_GLUE_H */
|
||||||
|
@@ -1340,6 +1340,7 @@ static void wpa_supplicant_process_3_of_4(struct wpa_sm *sm,
|
|||||||
|
|
||||||
if (ie.transition_disable) {
|
if (ie.transition_disable) {
|
||||||
wpa_supplicant_transition_disable(sm, ie.transition_disable[0]);
|
wpa_supplicant_transition_disable(sm, ie.transition_disable[0]);
|
||||||
|
sm->transition_disable = ie.transition_disable[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sm->key_install && sm->key_info & WPA_KEY_INFO_INSTALL && sm->use_ext_key_id) {
|
if (sm->key_install && sm->key_info & WPA_KEY_INFO_INSTALL && sm->use_ext_key_id) {
|
||||||
@@ -1357,6 +1358,11 @@ failed:
|
|||||||
wpa_sm_deauthenticate(sm, WLAN_REASON_UNSPECIFIED);
|
wpa_sm_deauthenticate(sm, WLAN_REASON_UNSPECIFIED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u8 wpa_sm_get_transition_disable(struct wpa_sm *sm)
|
||||||
|
{
|
||||||
|
return sm->transition_disable;
|
||||||
|
}
|
||||||
|
|
||||||
static int wpa_supplicant_activate_ptk(struct wpa_sm *sm)
|
static int wpa_supplicant_activate_ptk(struct wpa_sm *sm)
|
||||||
{
|
{
|
||||||
int keylen;
|
int keylen;
|
||||||
|
@@ -86,6 +86,7 @@ struct wpa_sm {
|
|||||||
struct wpa_gtk_data gd; //used for calllback save param
|
struct wpa_gtk_data gd; //used for calllback save param
|
||||||
u16 key_info; //used for txcallback param
|
u16 key_info; //used for txcallback param
|
||||||
u16 txcb_flags;
|
u16 txcb_flags;
|
||||||
|
u8 transition_disable;
|
||||||
bool ap_notify_completed_rsne;
|
bool ap_notify_completed_rsne;
|
||||||
wifi_pmf_config_t pmf_cfg;
|
wifi_pmf_config_t pmf_cfg;
|
||||||
u8 eapol1_count;
|
u8 eapol1_count;
|
||||||
@@ -208,6 +209,8 @@ int wpa_set_bss(char *macddr, char * bssid, u8 pairwise_cipher, u8 group_cipher,
|
|||||||
|
|
||||||
int wpa_sm_rx_eapol(u8 *src_addr, u8 *buf, u32 len);
|
int wpa_sm_rx_eapol(u8 *src_addr, u8 *buf, u32 len);
|
||||||
|
|
||||||
|
u8 wpa_sm_get_transition_disable(struct wpa_sm *sm);
|
||||||
|
|
||||||
int wpa_derive_ptk_ft(struct wpa_sm *sm, const unsigned char *src_addr,
|
int wpa_derive_ptk_ft(struct wpa_sm *sm, const unsigned char *src_addr,
|
||||||
const struct wpa_eapol_key *key, struct wpa_ptk *ptk);
|
const struct wpa_eapol_key *key, struct wpa_ptk *ptk);
|
||||||
#endif /* WPA_I_H */
|
#endif /* WPA_I_H */
|
||||||
|
Reference in New Issue
Block a user