From 3a33ee7aa968419f87f993067e80ed11f7c51b6b Mon Sep 17 00:00:00 2001 From: "tarun.kumar" Date: Mon, 22 Jun 2026 21:49:48 +0530 Subject: [PATCH] fix(wifi) : Add scan only parser to show AP full compatibility --- components/esp_wifi/lib | 2 +- .../esp_supplicant/src/esp_wifi_driver.h | 1 + .../esp_supplicant/src/esp_wpa_main.c | 24 ++- .../wpa_supplicant/src/common/wpa_common.c | 141 +++++++++++++++--- .../wpa_supplicant/src/common/wpa_common.h | 6 + .../wpa_supplicant/src/rsn_supp/wpa_ie.c | 34 ++++- .../wpa_supplicant/src/rsn_supp/wpa_ie.h | 2 + 7 files changed, 187 insertions(+), 23 deletions(-) diff --git a/components/esp_wifi/lib b/components/esp_wifi/lib index 88d34920d85..5bf80801f75 160000 --- a/components/esp_wifi/lib +++ b/components/esp_wifi/lib @@ -1 +1 @@ -Subproject commit 88d34920d857540a19d0e46a03c702fbf0c37f68 +Subproject commit 5bf80801f750baff6f8c3c8cffea5788e7a2f7b7 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 4e9dcdeae94..cef94e6b28a 100644 --- a/components/wpa_supplicant/esp_supplicant/src/esp_wifi_driver.h +++ b/components/wpa_supplicant/esp_supplicant/src/esp_wifi_driver.h @@ -163,6 +163,7 @@ struct wpa_funcs { int (*owe_process_assoc_resp)(const u8 *rsn_ie, size_t rsn_len, const uint8_t *dh_ie, size_t dh_len); void (*wpa_sta_clear_curr_pmksa)(void); void (*wpa_config_reload)(void); + int (*wpa_parse_wpa_ie_scan_only)(const u8 *wpa_ie, size_t wpa_ie_len, wifi_wpa_ie_t *data); }; struct wpa2_funcs { 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 45e7d763f65..3a7473d8a16 100644 --- a/components/wpa_supplicant/esp_supplicant/src/esp_wpa_main.c +++ b/components/wpa_supplicant/esp_supplicant/src/esp_wpa_main.c @@ -277,12 +277,15 @@ void wpa_config_done(void) esp_set_scan_ie(); } -int wpa_parse_wpa_ie_wrapper(const u8 *wpa_ie, size_t wpa_ie_len, wifi_wpa_ie_t *data) +static int wpa_parse_wpa_ie_to_public(const u8 *wpa_ie, size_t wpa_ie_len, + wifi_wpa_ie_t *data, + int (*parse_fn)(const u8 *, size_t, + struct wpa_ie_data *)) { - struct wpa_ie_data ie; - int ret = 0; + struct wpa_ie_data ie = {0}; + int ret; - ret = wpa_parse_wpa_ie(wpa_ie, wpa_ie_len, &ie); + ret = parse_fn(wpa_ie, wpa_ie_len, &ie); data->proto = ie.proto; data->pairwise_cipher = cipher_type_map_supp_to_public(ie.pairwise_cipher); data->group_cipher = cipher_type_map_supp_to_public(ie.group_cipher); @@ -295,6 +298,18 @@ int wpa_parse_wpa_ie_wrapper(const u8 *wpa_ie, size_t wpa_ie_len, wifi_wpa_ie_t return ret; } +int wpa_parse_wpa_ie_wrapper(const u8 *wpa_ie, size_t wpa_ie_len, wifi_wpa_ie_t *data) +{ + return wpa_parse_wpa_ie_to_public(wpa_ie, wpa_ie_len, data, wpa_parse_wpa_ie); +} + +int wpa_parse_wpa_ie_scan_only_wrapper(const u8 *wpa_ie, size_t wpa_ie_len, + wifi_wpa_ie_t *data) +{ + return wpa_parse_wpa_ie_to_public(wpa_ie, wpa_ie_len, data, + wpa_parse_wpa_ie_scan_only); +} + static void wpa_sta_connected_cb(uint8_t *bssid) { supplicant_sta_conn_handler(bssid); @@ -539,6 +554,7 @@ int esp_supplicant_init(void) wpa_cb->wpa_config_parse_string = wpa_config_parse_string; wpa_cb->wpa_parse_wpa_ie = wpa_parse_wpa_ie_wrapper; + wpa_cb->wpa_parse_wpa_ie_scan_only = wpa_parse_wpa_ie_scan_only_wrapper; wpa_cb->wpa_config_bss = NULL;//wpa_config_bss; wpa_cb->wpa_michael_mic_failure = wpa_michael_mic_failure; wpa_cb->wpa_config_done = wpa_config_done; diff --git a/components/wpa_supplicant/src/common/wpa_common.c b/components/wpa_supplicant/src/common/wpa_common.c index 2e72886327e..c6ac9bc80ca 100644 --- a/components/wpa_supplicant/src/common/wpa_common.c +++ b/components/wpa_supplicant/src/common/wpa_common.c @@ -373,6 +373,72 @@ static int rsn_key_mgmt_to_bitfield(const u8 *s) return 0; } +static int rsn_selector_to_bitfield_scan_only(const u8 *s) +{ + u32 sel = RSN_SELECTOR_GET(s); + + if (sel == RSN_SELECTOR(0x00, 0x0f, 0xac, 0)) + return WPA_CIPHER_NONE; + if (sel == RSN_SELECTOR(0x00, 0x0f, 0xac, 1)) + return WPA_CIPHER_WEP40; + if (sel == RSN_SELECTOR(0x00, 0x0f, 0xac, 2)) + return WPA_CIPHER_TKIP; + if (sel == RSN_SELECTOR(0x00, 0x0f, 0xac, 4)) + return WPA_CIPHER_CCMP; + if (sel == RSN_SELECTOR(0x00, 0x0f, 0xac, 5)) + return WPA_CIPHER_WEP104; + if (sel == RSN_SELECTOR(0x00, 0x0f, 0xac, 6)) + return WPA_CIPHER_AES_128_CMAC; + if (sel == RSN_SELECTOR(0x00, 0x0f, 0xac, 7)) + return WPA_CIPHER_GTK_NOT_USED; + if (sel == RSN_SELECTOR(0x00, 0x0f, 0xac, 8)) + return WPA_CIPHER_GCMP; + if (sel == RSN_SELECTOR(0x00, 0x0f, 0xac, 9)) + return WPA_CIPHER_GCMP_256; + if (sel == RSN_SELECTOR(0x00, 0x0f, 0xac, 11)) + return WPA_CIPHER_BIP_GMAC_128; + if (sel == RSN_SELECTOR(0x00, 0x0f, 0xac, 12)) + return WPA_CIPHER_BIP_GMAC_256; + + return 0; +} + +static int rsn_key_mgmt_to_bitfield_scan_only(const u8 *s) +{ + u32 sel = RSN_SELECTOR_GET(s); + + if (sel == RSN_SELECTOR(0x00, 0x0f, 0xac, 1)) + return WPA_KEY_MGMT_IEEE8021X; + if (sel == RSN_SELECTOR(0x00, 0x0f, 0xac, 2)) + return WPA_KEY_MGMT_PSK; + if (sel == RSN_SELECTOR(0x00, 0x0f, 0xac, 3)) + return WPA_KEY_MGMT_FT_IEEE8021X; + if (sel == RSN_SELECTOR(0x00, 0x0f, 0xac, 4)) + return WPA_KEY_MGMT_FT_PSK; + if (sel == RSN_SELECTOR(0x00, 0x0f, 0xac, 5)) + return WPA_KEY_MGMT_IEEE8021X_SHA256; + if (sel == RSN_SELECTOR(0x00, 0x0f, 0xac, 6)) + return WPA_KEY_MGMT_PSK_SHA256; + if (sel == RSN_SELECTOR(0x00, 0x0f, 0xac, 8)) + return WPA_KEY_MGMT_SAE; + if (sel == RSN_SELECTOR(0x00, 0x0f, 0xac, 9)) + return WPA_KEY_MGMT_FT_SAE; + if (sel == RSN_SELECTOR(0x00, 0x0f, 0xac, 11)) + return WPA_KEY_MGMT_IEEE8021X_SUITE_B; + if (sel == RSN_SELECTOR(0x00, 0x0f, 0xac, 12)) + return WPA_KEY_MGMT_IEEE8021X_SUITE_B_192; + if (sel == RSN_SELECTOR(0x00, 0x0f, 0xac, 13)) + return WPA_KEY_MGMT_FT_IEEE8021X_SHA384; + if (sel == RSN_SELECTOR(0x00, 0x0f, 0xac, 18)) + return WPA_KEY_MGMT_OWE; + if (sel == RSN_SELECTOR(0x00, 0x0f, 0xac, 24)) + return WPA_KEY_MGMT_SAE_EXT_KEY; + if (sel == RSN_SELECTOR(0x50, 0x6f, 0x9a, 0x02)) + return WPA_KEY_MGMT_DPP; + + return 0; +} + static int wpa_selector_to_bitfield(const u8 *s) { if (RSN_SELECTOR_GET(s) == WPA_CIPHER_SUITE_NONE) @@ -431,15 +497,31 @@ int wpa_parse_wpa_ie_rsnxe(const u8 *rsnxe_ie, size_t rsnxe_ie_len, return 0; } -/** - * wpa_parse_wpa_ie_rsn - Parse RSN IE - * @rsn_ie: Buffer containing RSN IE - * @rsn_ie_len: RSN IE buffer length (including IE number and length octets) - * @data: Pointer to structure that will be filled in with parsed data - * Returns: 0 on success, <0 on failure - */ -int wpa_parse_wpa_ie_rsn(const u8 *rsn_ie, size_t rsn_ie_len, - struct wpa_ie_data *data) +int wpa_parse_wpa_ie_rsnxe_scan_only(const u8 *rsnxe_ie, size_t rsnxe_ie_len, + struct wpa_ie_data *data) +{ + uint8_t rsnxe_capa = 0; + + memset(data, 0, sizeof(*data)); + + if (rsnxe_ie_len < 3 || !rsnxe_ie) { + return -1; + } + if (rsnxe_ie[0] == WLAN_EID_VENDOR_SPECIFIC && + rsnxe_ie[1] >= 1 + 4) { + rsnxe_capa = rsnxe_ie[2 + 4]; + } else { + rsnxe_capa = rsnxe_ie[2]; + } + data->rsnxe_capa = rsnxe_capa; + return 0; +} + +static int wpa_parse_wpa_ie_rsn_common(const u8 *rsn_ie, size_t rsn_ie_len, + struct wpa_ie_data *data, + int (*selector_to_bitfield)(const u8 *), + int (*key_mgmt_to_bitfield)(const u8 *), + bool validate_mgmt_group) { const u8 *pos; int left; @@ -468,9 +550,9 @@ int wpa_parse_wpa_ie_rsn(const u8 *rsn_ie, size_t rsn_ie_len, } if (rsn_ie_len >= 2 + 4 + 2 && rsn_ie[1] >= 4 + 2 && - rsn_ie[1] == rsn_ie_len - 2 && - (WPA_GET_BE32(&rsn_ie[2]) == RSNE_OVERRIDE_IE_VENDOR_TYPE) && - WPA_GET_LE16(&rsn_ie[2 + 4]) == RSN_VERSION) { + rsn_ie[1] == rsn_ie_len - 2 && + (WPA_GET_BE32(&rsn_ie[2]) == RSNE_OVERRIDE_IE_VENDOR_TYPE) && + WPA_GET_LE16(&rsn_ie[2 + 4]) == RSN_VERSION) { pos = rsn_ie + 2 + 4 + 2; left = rsn_ie_len - 2 - 4 - 2; } else { @@ -491,7 +573,7 @@ int wpa_parse_wpa_ie_rsn(const u8 *rsn_ie, size_t rsn_ie_len, } if (left >= RSN_SELECTOR_LEN) { - data->group_cipher = rsn_selector_to_bitfield(pos); + data->group_cipher = selector_to_bitfield(pos); data->has_group = 1; pos += RSN_SELECTOR_LEN; left -= RSN_SELECTOR_LEN; @@ -514,7 +596,7 @@ int wpa_parse_wpa_ie_rsn(const u8 *rsn_ie, size_t rsn_ie_len, if (count) data->has_pairwise = 1; for (i = 0; i < count; i++) { - data->pairwise_cipher |= rsn_selector_to_bitfield(pos); + data->pairwise_cipher |= selector_to_bitfield(pos); pos += RSN_SELECTOR_LEN; left -= RSN_SELECTOR_LEN; } @@ -535,7 +617,7 @@ int wpa_parse_wpa_ie_rsn(const u8 *rsn_ie, size_t rsn_ie_len, return -6; } for (i = 0; i < count; i++) { - data->key_mgmt |= rsn_key_mgmt_to_bitfield(pos); + data->key_mgmt |= key_mgmt_to_bitfield(pos); pos += RSN_SELECTOR_LEN; left -= RSN_SELECTOR_LEN; } @@ -570,8 +652,9 @@ int wpa_parse_wpa_ie_rsn(const u8 *rsn_ie, size_t rsn_ie_len, } if (left >= 4) { - data->mgmt_group_cipher = rsn_selector_to_bitfield(pos); - if (!wpa_cipher_valid_mgmt_group(data->mgmt_group_cipher)) { + data->mgmt_group_cipher = selector_to_bitfield(pos); + if (validate_mgmt_group && + !wpa_cipher_valid_mgmt_group(data->mgmt_group_cipher)) { wpa_printf(MSG_DEBUG, "%s: Unsupported management group cipher 0x%x (%08x)", __func__, data->mgmt_group_cipher, @@ -590,6 +673,30 @@ int wpa_parse_wpa_ie_rsn(const u8 *rsn_ie, size_t rsn_ie_len, return 0; } +/** + * wpa_parse_wpa_ie_rsn - Parse RSN IE + * @rsn_ie: Buffer containing RSN IE + * @rsn_ie_len: RSN IE buffer length (including IE number and length octets) + * @data: Pointer to structure that will be filled in with parsed data + * Returns: 0 on success, <0 on failure + */ +int wpa_parse_wpa_ie_rsn(const u8 *rsn_ie, size_t rsn_ie_len, + struct wpa_ie_data *data) +{ + return wpa_parse_wpa_ie_rsn_common(rsn_ie, rsn_ie_len, data, + rsn_selector_to_bitfield, + rsn_key_mgmt_to_bitfield, true); +} + +int wpa_parse_wpa_ie_rsn_scan_only(const u8 *rsn_ie, size_t rsn_ie_len, + struct wpa_ie_data *data) +{ + return wpa_parse_wpa_ie_rsn_common(rsn_ie, rsn_ie_len, data, + rsn_selector_to_bitfield_scan_only, + rsn_key_mgmt_to_bitfield_scan_only, + false); +} + int wpa_parse_wpa_ie_wpa(const u8 *wpa_ie, size_t wpa_ie_len, struct wpa_ie_data *data) { diff --git a/components/wpa_supplicant/src/common/wpa_common.h b/components/wpa_supplicant/src/common/wpa_common.h index e5b2d345165..1c1ada6f91c 100644 --- a/components/wpa_supplicant/src/common/wpa_common.h +++ b/components/wpa_supplicant/src/common/wpa_common.h @@ -455,10 +455,16 @@ const char * wpa_cipher_txt(int cipher); int wpa_parse_wpa_ie_rsn(const u8 *rsn_ie, size_t rsn_ie_len, struct wpa_ie_data *data); +int wpa_parse_wpa_ie_rsn_scan_only(const u8 *rsn_ie, size_t rsn_ie_len, + struct wpa_ie_data *data); int wpa_parse_wpa_ie(const u8 *wpa_ie, size_t wpa_ie_len, struct wpa_ie_data *data); +int wpa_parse_wpa_ie_scan_only(const u8 *wpa_ie, size_t wpa_ie_len, + struct wpa_ie_data *data); int wpa_parse_wpa_ie_rsnxe(const u8 *rsnxe_ie, size_t rsnxe_ie_len, struct wpa_ie_data *data); +int wpa_parse_wpa_ie_rsnxe_scan_only(const u8 *rsnxe_ie, size_t rsnxe_ie_len, + struct wpa_ie_data *data); u32 wpa_akm_to_suite(int akm); int wpa_compare_rsn_ie(int ft_initial_assoc, const u8 *ie1, size_t ie1len, diff --git a/components/wpa_supplicant/src/rsn_supp/wpa_ie.c b/components/wpa_supplicant/src/rsn_supp/wpa_ie.c index 4e0d75ee050..1baa2cabda2 100644 --- a/components/wpa_supplicant/src/rsn_supp/wpa_ie.c +++ b/components/wpa_supplicant/src/rsn_supp/wpa_ie.c @@ -37,7 +37,7 @@ int wpa_parse_wpa_ie(const u8 *wpa_ie, size_t wpa_ie_len, return wpa_parse_wpa_ie_rsn(wpa_ie, wpa_ie_len, data); } else if (wpa_ie_len >=1 && wpa_ie[0] == WLAN_EID_RSNX){ return wpa_parse_wpa_ie_rsnxe(wpa_ie, wpa_ie_len, data); - } else if (wpa_ie[0] == WLAN_EID_WAPI) { + } else if (wpa_ie_len >= 1 && wpa_ie[0] == WLAN_EID_WAPI) { return 0; #ifdef CONFIG_WPA3_COMPAT } else if (wpa_ie_len >= 6 && wpa_ie[0] == WLAN_EID_VENDOR_SPECIFIC && @@ -54,6 +54,38 @@ int wpa_parse_wpa_ie(const u8 *wpa_ie, size_t wpa_ie_len, return wpa_parse_wpa_ie_wpa(wpa_ie, wpa_ie_len, data); } +/** + * wpa_parse_wpa_ie_scan_only - Parse WPA/RSN IE for scan result display + * @wpa_ie: Pointer to WPA or RSN IE + * @wpa_ie_len: Length of the WPA/RSN IE + * @data: Pointer to data area for parsing results + * Returns: 0 on success, -1 on failure + * + * Parse WPA/RSN IE without build-time feature restrictions so scan results + * can report all advertised ciphers and AKMs. + */ +int wpa_parse_wpa_ie_scan_only(const u8 *wpa_ie, size_t wpa_ie_len, + struct wpa_ie_data *data) +{ + if (wpa_ie_len >= 1 && wpa_ie[0] == WLAN_EID_RSN) { + return wpa_parse_wpa_ie_rsn_scan_only(wpa_ie, wpa_ie_len, data); + } else if (wpa_ie_len >= 1 && wpa_ie[0] == WLAN_EID_RSNX) { + return wpa_parse_wpa_ie_rsnxe_scan_only(wpa_ie, wpa_ie_len, data); + } else if (wpa_ie_len >= 1 && wpa_ie[0] == WLAN_EID_WAPI) { + return 0; + } else if (wpa_ie_len >= 6 && wpa_ie[0] == WLAN_EID_VENDOR_SPECIFIC && + wpa_ie[1] >= 4 && + WPA_GET_BE32(&wpa_ie[2]) == RSNE_OVERRIDE_IE_VENDOR_TYPE) { + return wpa_parse_wpa_ie_rsn_scan_only(wpa_ie, wpa_ie_len, data); + } else if (wpa_ie_len >= 6 && wpa_ie[0] == WLAN_EID_VENDOR_SPECIFIC && + wpa_ie[1] >= 4 && + WPA_GET_BE32(&wpa_ie[2]) == RSNXE_OVERRIDE_IE_VENDOR_TYPE) { + return wpa_parse_wpa_ie_rsnxe_scan_only(wpa_ie, wpa_ie_len, data); + } + + return wpa_parse_wpa_ie_wpa(wpa_ie, wpa_ie_len, data); +} + static int wpa_gen_wpa_ie_wpa(u8 *wpa_ie, size_t wpa_ie_len, int pairwise_cipher, int group_cipher, diff --git a/components/wpa_supplicant/src/rsn_supp/wpa_ie.h b/components/wpa_supplicant/src/rsn_supp/wpa_ie.h index 17089b9988e..d549e7e3ba6 100644 --- a/components/wpa_supplicant/src/rsn_supp/wpa_ie.h +++ b/components/wpa_supplicant/src/rsn_supp/wpa_ie.h @@ -19,5 +19,7 @@ int wpa_gen_wpa_ie(struct wpa_sm *sm, u8 *wpa_ie, size_t wpa_ie_len); int wpa_gen_rsnxe(struct wpa_sm *sm, u8 *rsnxe, size_t rsnxe_len); int wpa_parse_wpa_ie(const u8 *wpa_ie, size_t wpa_ie_len, struct wpa_ie_data *data); +int wpa_parse_wpa_ie_scan_only(const u8 *wpa_ie, size_t wpa_ie_len, + struct wpa_ie_data *data); #endif /* WPA_IE_H */