From 67771bab3927fb670a36ea57f19df6d3a0008682 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Wed, 11 Oct 2023 12:43:11 +0300 Subject: [PATCH 01/33] Define WFA vendor specific element types for RSNE/RSNXE overriding Signed-off-by: Jouni Malinen --- components/wpa_supplicant/src/common/ieee802_11_defs.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/components/wpa_supplicant/src/common/ieee802_11_defs.h b/components/wpa_supplicant/src/common/ieee802_11_defs.h index 958bf5feeb..72c500c8fe 100644 --- a/components/wpa_supplicant/src/common/ieee802_11_defs.h +++ b/components/wpa_supplicant/src/common/ieee802_11_defs.h @@ -301,6 +301,12 @@ #define OUI_WFA 0x506f9a #define DPP_OUI_TYPE 0x1A +#define WFA_RSNE_OVERRIDE_OUI_TYPE 0x29 +#define WFA_RSNE_OVERRIDE_2_OUI_TYPE 0x2a +#define WFA_RSNXE_OVERRIDE_OUI_TYPE 0x2b +#define RSNE_OVERRIDE_IE_VENDOR_TYPE 0x506f9a29 +#define RSNE_OVERRIDE_2_IE_VENDOR_TYPE 0x506f9a2a +#define RSNXE_OVERRIDE_IE_VENDOR_TYPE 0x506f9a2b #ifdef _MSC_VER #pragma pack(push, 1) From 071bedda27fd833e73b041069752e9c1061b9c72 Mon Sep 17 00:00:00 2001 From: Shreyas Sheth Date: Wed, 29 Jan 2025 13:27:35 +0530 Subject: [PATCH 02/33] feat(wifi): restructure ieee802_11_parse_elems similar to upstream suppliant --- .../esp_supplicant/src/esp_common.c | 8 +- .../esp_supplicant/src/esp_wifi_driver.h | 2 +- .../src/common/ieee802_11_common.c | 129 +++++++++++------- .../src/common/ieee802_11_common.h | 26 +++- components/wpa_supplicant/src/common/sae_pk.c | 48 ++----- .../src/common/wpa_supplicant_i.h | 15 -- 6 files changed, 129 insertions(+), 99 deletions(-) diff --git a/components/wpa_supplicant/esp_supplicant/src/esp_common.c b/components/wpa_supplicant/esp_supplicant/src/esp_common.c index 9e7f3656fc..b95578035e 100644 --- a/components/wpa_supplicant/esp_supplicant/src/esp_common.c +++ b/components/wpa_supplicant/esp_supplicant/src/esp_common.c @@ -322,6 +322,8 @@ void supplicant_sta_conn_handler(uint8_t *bssid) u8 *ie; struct wpa_supplicant *wpa_s = &g_wpa_supp; struct wpa_bss *bss = wpa_bss_get_bssid(wpa_s, bssid); + struct ieee802_11_elems elems; + if (!bss) { wpa_printf(MSG_INFO, "connected bss entry not present in scan cache"); return; @@ -329,7 +331,11 @@ void supplicant_sta_conn_handler(uint8_t *bssid) wpa_s->current_bss = bss; ie = (u8 *)bss; ie += sizeof(struct wpa_bss); - ieee802_11_parse_elems(wpa_s, ie, bss->ie_len); + ieee802_11_parse_elems(ie, bss->ie_len, &elems, 0); + if (elems.rrm_enabled_len > 0 && elems.rrm_enabled != NULL) { + os_memcpy(wpa_s->rrm_ie, elems.rrm_enabled, 5); //TODO ask kapil about 5 + wpa_s->rrm.rrm_used = true; + } wpa_bss_flush(wpa_s); /* Register for mgmt frames */ register_mgmt_frames(wpa_s); 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 e99fd88dab..7541ee8151 100644 --- a/components/wpa_supplicant/esp_supplicant/src/esp_wifi_driver.h +++ b/components/wpa_supplicant/esp_supplicant/src/esp_wifi_driver.h @@ -129,7 +129,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, u16 rsnxe_len, bool *pmf_enable, int subtype, uint8_t *pairwise_cipher); + bool (*wpa_ap_join)(void **sm, u8 *bssid, u8 *assoc_req_ie, uint32_t assoc_req_ie_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); diff --git a/components/wpa_supplicant/src/common/ieee802_11_common.c b/components/wpa_supplicant/src/common/ieee802_11_common.c index e4c1f4a52d..7078604b91 100644 --- a/components/wpa_supplicant/src/common/ieee802_11_common.c +++ b/components/wpa_supplicant/src/common/ieee802_11_common.c @@ -191,66 +191,87 @@ int ieee802_11_parse_candidate_list(const char *pos, u8 *nei_rep, return nei_pos - nei_rep; } -#ifdef CONFIG_SAE_PK -static int ieee802_11_parse_vendor_specific(struct wpa_supplicant *wpa_s, const struct element *elem, const u8* pos) +#ifdef CONFIG_WPA3_SAE +static int ieee802_11_parse_vendor_specific(const u8 *pos, size_t elen, + struct ieee802_11_elems *elems, + int show_errors) { u32 oui; + + /* first 3 bytes in vendor specific information element are the IEEE + * OUI of the vendor. The following byte is used a vendor specific + * sub-type. */ + if (elen < 4) { + if (show_errors) { + wpa_printf(MSG_MSGDUMP, "short vendor specific " + "information element ignored (len=%lu)", + (unsigned long) elen); + } + return -1; + } + oui = WPA_GET_BE24(pos); switch (oui) { case OUI_WFA: switch (pos[3]) { +#ifdef CONFIG_SAE_PK case SAE_PK_OUI_TYPE: - wpa_s->sae_pk_elems.sae_pk_len = elem->datalen - 4; - wpa_s->sae_pk_elems.sae_pk = (u8*)os_zalloc(sizeof(u8)*(elem->datalen-4)); - if (!wpa_s->sae_pk_elems.sae_pk) { - wpa_printf(MSG_EXCESSIVE, "Can not allocate memory for sae_pk"); - return -1; - } - os_memcpy(wpa_s->sae_pk_elems.sae_pk, pos+4, elem->datalen-4); + elems->sae_pk = pos + 4; + elems->sae_pk_len = elen - 4; break; +#endif /* CONFIG_SAE_PK */ default: wpa_printf(MSG_EXCESSIVE, "Unknown WFA " "information element ignored " "(type=%d len=%lu)", - pos[3], (unsigned long) elem->datalen); + pos[3], (unsigned long) elen); return -1; } break; default: - wpa_printf(MSG_EXCESSIVE, "unknown vendor specific " + wpa_printf(MSG_EXCESSIVE, "unknown vendor specific " "information element ignored (vendor OUI " "%02x:%02x:%02x len=%lu)", - pos[0], pos[1], pos[2], (unsigned long) elem->datalen); + pos[0], pos[1], pos[2], (unsigned long) elen); return -1; } return 0; } +#endif /* CONFIG_WPA3_SAE */ -static int ieee802_11_parse_extension(struct wpa_supplicant *wpa_s, const struct element *elem, const u8* pos){ - // do not consider extension_id element len in datalen - if (elem->datalen < 1) { +#ifdef CONFIG_SAE_PK +static int ieee802_11_parse_extension(const u8 *pos, size_t elen, + struct ieee802_11_elems *elems, + const u8 *start, size_t len, + int show_errors) +{ + u8 ext_id; + + if (elen < 1) { wpa_printf(MSG_DEBUG, "short information element (Ext)"); return -1; } - u8 ext_id; + ext_id = *pos++; + elen--; + switch (ext_id) { case WLAN_EID_EXT_FILS_KEY_CONFIRM: - wpa_s->sae_pk_elems.fils_key_confirm_len = elem->datalen - 1; - wpa_s->sae_pk_elems.fils_key_confirm = (u8*)os_zalloc(sizeof(u8)*(elem->datalen - 1)); - os_memcpy(wpa_s->sae_pk_elems.fils_key_confirm, pos, elem->datalen - 1); + elems->fils_key_confirm = pos; + elems->fils_key_confirm_len = elen; break; case WLAN_EID_EXT_FILS_PUBLIC_KEY: - wpa_s->sae_pk_elems.fils_pk_len = elem->datalen - 1; - wpa_s->sae_pk_elems.fils_pk = (u8*)os_zalloc(sizeof(u8)*(elem->datalen - 1)); - os_memcpy(wpa_s->sae_pk_elems.fils_pk, pos, elem->datalen - 1); + if (elen < 1) + break; + elems->fils_pk = pos; + elems->fils_pk_len = elen; break; default: wpa_printf(MSG_EXCESSIVE, "IEEE 802.11 element parsing ignored unknown element extension (ext_id=%u elen=%u)", - ext_id, (unsigned int) elem->datalen-1); + ext_id, (unsigned int) elen); return -1; } @@ -258,49 +279,49 @@ static int ieee802_11_parse_extension(struct wpa_supplicant *wpa_s, const struct } #endif /* CONFIG_SAE_PK */ -/** - * ieee802_11_parse_elems - Parse information elements in management frames - * @start: Pointer to the start of IEs - * @len: Length of IE buffer in octets - * @elems: Data structure for parsed elements - * @show_errors: Whether to show parsing errors in debug log - * Returns: Parsing result - */ -int ieee802_11_parse_elems(struct wpa_supplicant *wpa_s, const u8 *start, size_t len) +static ParseRes __ieee802_11_parse_elems(const u8 *start, size_t len, + struct ieee802_11_elems *elems, + int show_errors) { -#if defined(CONFIG_RRM) || defined(CONFIG_WNM) || defined(CONFIG_SAE_PK) +#if defined(CONFIG_RRM) || defined(CONFIG_WNM) || defined(CONFIG_WPA3_SAE) || defined(CONFIG_SAE_PK) const struct element *elem; u8 unknown = 0; if (!start) - return 0; + return ParseOK; for_each_element(elem, start, len) { - u8 id = elem->id; + u8 id = elem->id, elen = elem->datalen; const u8 *pos = elem->data; switch (id) { #ifdef CONFIG_RRM case WLAN_EID_RRM_ENABLED_CAPABILITIES: - os_memcpy(wpa_s->rrm_ie, pos, 5); - wpa_s->rrm.rrm_used = true; + elems->rrm_enabled = pos; + elems->rrm_enabled_len = elen; break; #endif #ifdef CONFIG_SAE_PK case WLAN_EID_EXTENSION: - if(ieee802_11_parse_extension(wpa_s, elem, pos) != 0){ - unknown++; - } - break; - case WLAN_EID_VENDOR_SPECIFIC: - if(ieee802_11_parse_vendor_specific(wpa_s, elem, pos) != 0){ + if (ieee802_11_parse_extension(pos, elen, elems, start, + len, show_errors) != 0) { unknown++; } break; #endif /*CONFIG_SAE_PK*/ +#ifdef CONFIG_WPA3_SAE + case WLAN_EID_VENDOR_SPECIFIC: + if (ieee802_11_parse_vendor_specific(pos, elen, + elems, + show_errors) != 0) { + unknown++; + } + break; +#endif /* CONFIG_WPA3_SAE */ #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); + elems->ext_capab = pos; + elems->ext_capab_len = elen; break; #endif default: @@ -309,10 +330,24 @@ int ieee802_11_parse_elems(struct wpa_supplicant *wpa_s, const u8 *start, size_t } } if (unknown) - return -1; + return ParseFailed; -#endif /* defined(CONFIG_RRM) || defined(CONFIG_WNM) || defined(CONFIG_SAE_PK) */ - return 0; +#endif /* defined(CONFIG_RRM) || defined(CONFIG_WNM) || defined (CONFIG_WPA3_SAE) ||defined(CONFIG_SAE_PK) */ + return ParseOK; +} +/** + * ieee802_11_parse_elems - Parse information elements in management frames + * @start: Pointer to the start of IEs + * @len: Length of IE buffer in octets + * @elems: Data structure for parsed elements + * @show_errors: Whether to show parsing errors in debug log + * Returns: Parsing result + */ +ParseRes ieee802_11_parse_elems(const u8 *start, size_t len, struct ieee802_11_elems *elems, int show_errors) +{ + os_memset(elems, 0, sizeof(*elems)); + + return __ieee802_11_parse_elems(start, len, elems, show_errors); } struct wpabuf * ieee802_11_vendor_ie_concat(const u8 *ies, size_t ies_len, diff --git a/components/wpa_supplicant/src/common/ieee802_11_common.h b/components/wpa_supplicant/src/common/ieee802_11_common.h index 90cae7814d..9c4a6dc1f2 100644 --- a/components/wpa_supplicant/src/common/ieee802_11_common.h +++ b/components/wpa_supplicant/src/common/ieee802_11_common.h @@ -48,10 +48,34 @@ struct oper_class_map { extern const struct oper_class_map global_op_class[]; extern size_t global_op_class_size; +/* Parsed Information Elements */ +struct ieee802_11_elems { +#ifdef CONFIG_RRM + const u8 *rrm_enabled; + u8 rrm_enabled_len; +#endif +#ifdef CONFIG_WNM + const u8 *ext_capab; + u8 ext_capab_len; +#endif +#ifdef CONFIG_SAE_PK + const u8 *fils_pk; + u8 fils_pk_len; + const u8 *fils_key_confirm; + u8 fils_key_confirm_len; + const u8 *sae_pk; + u8 sae_pk_len; +#endif +}; + +typedef enum { ParseOK = 0, ParseUnknown = 1, ParseFailed = -1 } ParseRes; + int ieee802_11_parse_candidate_list(const char *pos, u8 *nei_rep, size_t nei_rep_len); const u8 * get_ie(const u8 *ies, size_t len, u8 eid); -int ieee802_11_parse_elems(struct wpa_supplicant *wpa_s, const u8 *start, size_t len); +ParseRes ieee802_11_parse_elems(const u8 *start, size_t len, + struct ieee802_11_elems *elems, + int show_errors); int ieee802_11_ext_capab(const u8 *ie, unsigned int capab); const u8 * get_vendor_ie(const u8 *ies, size_t len, u32 vendor_type); size_t mbo_add_ie(u8 *buf, size_t len, const u8 *attr, size_t attr_len); diff --git a/components/wpa_supplicant/src/common/sae_pk.c b/components/wpa_supplicant/src/common/sae_pk.c index 6361de2aa0..a1d88ac1ba 100644 --- a/components/wpa_supplicant/src/common/sae_pk.c +++ b/components/wpa_supplicant/src/common/sae_pk.c @@ -618,9 +618,7 @@ int sae_check_confirm_pk(struct sae_data *sae, const u8 *ies, size_t ies_len) u8 hash[SAE_MAX_HASH_LEN]; size_t hash_len; int group; - struct wpa_supplicant *wpa_s = &g_wpa_supp; - struct sae_pk_elems elems; - int ret = 0; + struct ieee802_11_elems elems; if (!tmp) { return -1; @@ -644,15 +642,16 @@ int sae_check_confirm_pk(struct sae_data *sae, const u8 *ies, size_t ies_len) } wpa_hexdump(MSG_DEBUG, "SAE-PK: Received confirm IEs", ies, ies_len); - ieee802_11_parse_elems(wpa_s, ies, ies_len); - elems = wpa_s->sae_pk_elems; + if (ieee802_11_parse_elems(ies, ies_len, &elems, 1) == ParseFailed) { + wpa_printf(MSG_INFO, "SAE-PK: Failed to parse confirm IEs"); + return -1; + } if (!elems.fils_pk || !elems.fils_key_confirm || !elems.sae_pk) { wpa_printf(MSG_INFO, "SAE-PK: Not all mandatory IEs included in confirm"); - ret = -1; - goto done; + return -1; } /* TODO: Fragment reassembly */ @@ -660,8 +659,7 @@ int sae_check_confirm_pk(struct sae_data *sae, const u8 *ies, size_t ies_len) if (elems.sae_pk_len < SAE_PK_M_LEN + AES_BLOCK_SIZE) { wpa_printf(MSG_INFO, "SAE-PK: No room for EncryptedModifier in SAE-PK element"); - ret = -1; - goto done; + return -1; } wpa_hexdump(MSG_DEBUG, "SAE-PK: EncryptedModifier", @@ -672,16 +670,14 @@ int sae_check_confirm_pk(struct sae_data *sae, const u8 *ies, size_t ies_len) 0, NULL, NULL, m) < 0) { wpa_printf(MSG_INFO, "SAE-PK: Failed to decrypt EncryptedModifier"); - ret = -1; - goto done; + return -1; } wpa_hexdump_key(MSG_DEBUG, "SAE-PK: Modifier M", m, SAE_PK_M_LEN); if (elems.fils_pk[0] != 2) { wpa_printf(MSG_INFO, "SAE-PK: Unsupported public key type %u", elems.fils_pk[0]); - ret = -1; - goto done; + return -1; } k_ap_len = elems.fils_pk_len - 1; k_ap = elems.fils_pk + 1; @@ -691,15 +687,13 @@ int sae_check_confirm_pk(struct sae_data *sae, const u8 *ies, size_t ies_len) key = crypto_ec_key_parse_pub(k_ap, k_ap_len); if (!key) { wpa_printf(MSG_INFO, "SAE-PK: Failed to parse K_AP"); - ret = -1; - goto done; + return -1; } group = crypto_ec_key_group(key); if (!sae_pk_valid_fingerprint(sae, m, SAE_PK_M_LEN, k_ap, k_ap_len, group)) { crypto_ec_key_deinit(key); - ret = -1; - goto done; + return -1; } wpa_hexdump(MSG_DEBUG, "SAE-PK: Received KeyAuth", @@ -709,8 +703,7 @@ int sae_check_confirm_pk(struct sae_data *sae, const u8 *ies, size_t ies_len) if (sae_pk_hash_sig_data(sae, hash_len, false, m, SAE_PK_M_LEN, k_ap, k_ap_len, hash) < 0) { crypto_ec_key_deinit(key); - ret = -1; - goto done; + return -1; } res = crypto_ec_key_verify_signature(key, hash, hash_len, @@ -721,25 +714,12 @@ int sae_check_confirm_pk(struct sae_data *sae, const u8 *ies, size_t ies_len) if (res != 1) { wpa_printf(MSG_INFO, "SAE-PK: Invalid or incorrect signature in KeyAuth"); - ret = -1; - goto done; + return -1; } wpa_printf(MSG_DEBUG, "SAE-PK: Valid KeyAuth signature received"); /* TODO: Store validated public key into network profile */ -done: - if (wpa_s->sae_pk_elems.fils_pk) { - os_free(wpa_s->sae_pk_elems.fils_pk); - } - if (wpa_s->sae_pk_elems.sae_pk) { - os_free(wpa_s->sae_pk_elems.sae_pk); - } - if (wpa_s->sae_pk_elems.fils_key_confirm) { - os_free(wpa_s->sae_pk_elems.fils_key_confirm); - } - os_memset(&wpa_s->sae_pk_elems, 0, sizeof(wpa_s->sae_pk_elems)); - - return ret; + return 0; } #endif /* CONFIG_SAE_PK */ diff --git a/components/wpa_supplicant/src/common/wpa_supplicant_i.h b/components/wpa_supplicant/src/common/wpa_supplicant_i.h index 581d1c1434..77907842fb 100644 --- a/components/wpa_supplicant/src/common/wpa_supplicant_i.h +++ b/components/wpa_supplicant/src/common/wpa_supplicant_i.h @@ -67,17 +67,6 @@ enum scan_trigger_reason { REASON_WNM_BSS_TRANS_REQ, }; -#ifdef CONFIG_SAE_PK -struct sae_pk_elems { - u8 *fils_pk; - u8 fils_pk_len; - u8 *fils_key_confirm; - u8 fils_key_confirm_len; - u8 *sae_pk; - u8 sae_pk_len; -}; -#endif - struct wpa_supplicant { int scanning; @@ -149,10 +138,6 @@ struct wpa_supplicant { struct beacon_rep_data beacon_rep_data; struct os_reltime beacon_rep_scan; #endif -#ifdef CONFIG_SAE_PK - struct sae_pk_elems sae_pk_elems; -#endif - }; struct non_pref_chan_s; From 25e0d46688f1d7cdb7a15ca45e16a6a47acfae0c Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Wed, 11 Oct 2023 12:45:09 +0300 Subject: [PATCH 03/33] Add RSN overriding elements into IE parsing Signed-off-by: Jouni Malinen --- components/wpa_supplicant/src/common/ieee802_11_common.c | 4 ++++ components/wpa_supplicant/src/common/ieee802_11_common.h | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/components/wpa_supplicant/src/common/ieee802_11_common.c b/components/wpa_supplicant/src/common/ieee802_11_common.c index 7078604b91..fd4ebf4dd4 100644 --- a/components/wpa_supplicant/src/common/ieee802_11_common.c +++ b/components/wpa_supplicant/src/common/ieee802_11_common.c @@ -220,6 +220,10 @@ static int ieee802_11_parse_vendor_specific(const u8 *pos, size_t elen, elems->sae_pk_len = elen - 4; break; #endif /* CONFIG_SAE_PK */ + case WFA_RSNE_OVERRIDE_OUI_TYPE: + elems->rsne_override = pos; + elems->rsne_override_len = elen; + break; default: wpa_printf(MSG_EXCESSIVE, "Unknown WFA " "information element ignored " diff --git a/components/wpa_supplicant/src/common/ieee802_11_common.h b/components/wpa_supplicant/src/common/ieee802_11_common.h index 9c4a6dc1f2..c13173e340 100644 --- a/components/wpa_supplicant/src/common/ieee802_11_common.h +++ b/components/wpa_supplicant/src/common/ieee802_11_common.h @@ -66,6 +66,10 @@ struct ieee802_11_elems { const u8 *sae_pk; u8 sae_pk_len; #endif +#ifdef CONFIG_WPA3_SAE + const u8 *rsne_override; + u8 rsne_override_len; +#endif }; typedef enum { ParseOK = 0, ParseUnknown = 1, ParseFailed = -1 } ParseRes; From 7ed2e8cf7e9d9f9267168f0da87e296476812112 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 10 Apr 2021 12:43:38 +0300 Subject: [PATCH 04/33] Add helper functions for parsing RSNXE capabilities Simplify the implementation by using shared functions for parsing the capabilities instead of using various similar but not exactly identical checks throughout the implementation. Signed-off-by: Jouni Malinen --- .../src/common/ieee802_11_common.c | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/components/wpa_supplicant/src/common/ieee802_11_common.c b/components/wpa_supplicant/src/common/ieee802_11_common.c index fd4ebf4dd4..4f08c34088 100644 --- a/components/wpa_supplicant/src/common/ieee802_11_common.c +++ b/components/wpa_supplicant/src/common/ieee802_11_common.c @@ -418,6 +418,34 @@ const struct oper_class_map global_op_class[] = { size_t global_op_class_size = ARRAY_SIZE(global_op_class); +bool ieee802_11_rsnx_capab_len(const u8 *rsnxe, size_t rsnxe_len, + unsigned int capab) +{ + const u8 *end; + size_t flen, i; + u32 capabs = 0; + + if (!rsnxe || rsnxe_len == 0) + return false; + end = rsnxe + rsnxe_len; + flen = (rsnxe[0] & 0x0f) + 1; + if (rsnxe + flen > end) + return false; + if (flen > 4) + flen = 4; + for (i = 0; i < flen; i++) + capabs |= rsnxe[i] << (8 * i); + + return capabs & BIT(capab); +} + + +bool ieee802_11_rsnx_capab(const u8 *rsnxe, unsigned int capab) +{ + return ieee802_11_rsnx_capab_len(rsnxe ? rsnxe + 2 : NULL, + rsnxe ? rsnxe[1] : 0, capab); +} + u8 get_operating_class(u8 chan, int sec_channel) { u8 op_class = 0; From 21ec067ef8e523bcd6c59aa793a2e19f573b893b Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Wed, 1 Nov 2023 15:27:31 +0200 Subject: [PATCH 05/33] Allow RSNXE Override element to override RSNXE contents during parsing Signed-off-by: Jouni Malinen --- components/wpa_supplicant/src/common/ieee802_11_common.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/components/wpa_supplicant/src/common/ieee802_11_common.c b/components/wpa_supplicant/src/common/ieee802_11_common.c index 4f08c34088..2af5c04f22 100644 --- a/components/wpa_supplicant/src/common/ieee802_11_common.c +++ b/components/wpa_supplicant/src/common/ieee802_11_common.c @@ -442,8 +442,12 @@ bool ieee802_11_rsnx_capab_len(const u8 *rsnxe, size_t rsnxe_len, bool ieee802_11_rsnx_capab(const u8 *rsnxe, unsigned int capab) { - return ieee802_11_rsnx_capab_len(rsnxe ? rsnxe + 2 : NULL, - rsnxe ? rsnxe[1] : 0, capab); + if (!rsnxe) + return false; + if (rsnxe[0] == WLAN_EID_VENDOR_SPECIFIC && rsnxe[1] >= 4 + 1) + return ieee802_11_rsnx_capab_len(rsnxe + 2 + 4, rsnxe[1] - 4, + capab); + return ieee802_11_rsnx_capab_len(rsnxe + 2, rsnxe[1], capab); } u8 get_operating_class(u8 chan, int sec_channel) From 86f8c88161e80fad1ea6446ab02cb66f430aecbd Mon Sep 17 00:00:00 2001 From: Shreyas Sheth Date: Sun, 16 Feb 2025 21:06:36 +0530 Subject: [PATCH 06/33] fix(wifi): Restructure esp supplicant for softap --- .../esp_supplicant/src/esp_hostap.c | 10 +-- .../esp_supplicant/src/esp_wpa_main.c | 30 ++++++-- components/wpa_supplicant/src/ap/ap_config.c | 4 +- components/wpa_supplicant/src/ap/ap_config.h | 4 +- components/wpa_supplicant/src/ap/wpa_auth.c | 1 + .../src/common/ieee802_11_common.c | 74 +++++++++++++++++-- .../src/common/ieee802_11_common.h | 12 +++ .../src/common/ieee802_11_defs.h | 8 ++ 8 files changed, 122 insertions(+), 21 deletions(-) diff --git a/components/wpa_supplicant/esp_supplicant/src/esp_hostap.c b/components/wpa_supplicant/esp_supplicant/src/esp_hostap.c index da162f0ee5..d88f59c3d7 100644 --- a/components/wpa_supplicant/esp_supplicant/src/esp_hostap.c +++ b/components/wpa_supplicant/esp_supplicant/src/esp_hostap.c @@ -10,6 +10,7 @@ #include "utils/eloop.h" #include "crypto/sha1.h" #include "common/ieee802_11_defs.h" +#include "common/ieee802_11_common.h" #include "common/eapol_common.h" #include "ap/wpa_auth.h" #include "ap/ap_config.h" @@ -396,8 +397,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, uint16_t rsnxe_len, +bool hostap_new_assoc_sta(struct sta_info *sta, uint8_t *bssid, struct ieee802_11_elems elems, 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(); @@ -405,7 +405,7 @@ bool hostap_new_assoc_sta(struct sta_info *sta, uint8_t *bssid, uint8_t *wpa_ie, int status = WLAN_STATUS_SUCCESS; bool omit_rsnxe = false; - if (!sta || !bssid || !wpa_ie) { + if (!sta || !bssid || !elems.rsn_ie) { return false; } if (hapd) { @@ -422,7 +422,7 @@ bool hostap_new_assoc_sta(struct sta_info *sta, uint8_t *bssid, uint8_t *wpa_ie, goto send_resp; } - res = wpa_validate_wpa_ie(hapd->wpa_auth, sta->wpa_sm, wpa_ie, wpa_ie_len, rsnxe, rsnxe_len); + res = wpa_validate_wpa_ie(hapd->wpa_auth, sta->wpa_sm, elems.rsn_ie, elems.rsn_ie_len, elems.rsnxe, elems.rsnxe_len); #ifdef CONFIG_SAE if (wpa_auth_uses_sae(sta->wpa_sm) && sta->sae && sta->sae->state == SAE_ACCEPTED) { @@ -434,7 +434,7 @@ bool hostap_new_assoc_sta(struct sta_info *sta, uint8_t *bssid, uint8_t *wpa_ie, status = wpa_res_to_status_code(res); send_resp: - if (!rsnxe) { + if (!elems.rsnxe) { omit_rsnxe = true; } 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 2490a4003a..f0bce5803a 100644 --- a/components/wpa_supplicant/esp_supplicant/src/esp_wpa_main.c +++ b/components/wpa_supplicant/esp_supplicant/src/esp_wpa_main.c @@ -345,7 +345,7 @@ static void wpa_sta_disconnected_cb(uint8_t reason_code) #ifdef CONFIG_ESP_WIFI_SOFTAP_SUPPORT #ifdef CONFIG_WPS_REGISTRAR -static int check_n_add_wps_sta(struct hostapd_data *hapd, struct sta_info *sta_info, u8 *ies, u8 ies_len, bool *pmf_enable, int subtype) +static int check_n_add_wps_sta(struct hostapd_data *hapd, struct sta_info *sta_info, const u8 *ies, u8 ies_len, bool *pmf_enable, int subtype) { struct wpabuf *wps_ie = ieee802_11_vendor_ie_concat(ies, ies_len, WPS_DEV_OUI_WFA); int wps_type = esp_wifi_get_wps_type_internal(); @@ -377,22 +377,39 @@ 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, u16 rsnxe_len, bool *pmf_enable, int subtype, uint8_t *pairwise_cipher) +static bool hostap_sta_join(void **sta, u8 *bssid, u8 *assoc_req_ie, uint32_t assoc_ie_len, bool *pmf_enable, int subtype, uint8_t *pairwise_cipher) { struct sta_info *sta_info = NULL; struct hostapd_data *hapd = hostapd_get_hapd_data(); uint8_t reason = WLAN_REASON_PREV_AUTH_NOT_VALID; + struct ieee802_11_elems elems; if (!hapd) { goto fail; } + if (ieee802_11_parse_elems(assoc_req_ie, assoc_ie_len, &elems, 1) == ParseFailed) { + wpa_printf(MSG_INFO, "Failed to parse assoc req IEs"); + return -1; + } + + if (elems.rsn_ie) { + elems.rsn_ie = elems.rsn_ie - 2; + elems.rsn_ie_len = elems.rsn_ie_len + 2; + wpa_printf(MSG_DEBUG, "STA included RSN IE in (Re)AssocReq"); + } + if (elems.rsnxe) { + elems.rsnxe = elems.rsnxe - 2; + elems.rsnxe_len = elems.rsnxe_len + 2; + wpa_printf(MSG_DEBUG, "STA included RSN IE in (Re)AssocReq"); + } + if (*sta) { struct sta_info *old_sta = *sta; #ifdef CONFIG_SAE if (old_sta->lock && os_semphr_take(old_sta->lock, 0) != TRUE) { wpa_printf(MSG_INFO, "Ignore assoc request as softap is busy with sae calculation for station "MACSTR, MAC2STR(bssid)); - if (esp_send_assoc_resp(hapd, bssid, WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY, rsnxe ? false : true, subtype) != WLAN_STATUS_SUCCESS) { + if (esp_send_assoc_resp(hapd, bssid, WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY, elems.rsnxe ? false : true, subtype) != WLAN_STATUS_SUCCESS) { goto fail; } return false; @@ -421,7 +438,7 @@ static bool hostap_sta_join(void **sta, u8 *bssid, u8 *wpa_ie, u8 wpa_ie_len, u8 #ifdef CONFIG_SAE if (sta_info->lock && os_semphr_take(sta_info->lock, 0) != TRUE) { wpa_printf(MSG_INFO, "Ignore assoc request as softap is busy with sae calculation for station "MACSTR, MAC2STR(bssid)); - if (esp_send_assoc_resp(hapd, bssid, WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY, rsnxe ? false : true, subtype) != WLAN_STATUS_SUCCESS) { + if (esp_send_assoc_resp(hapd, bssid, WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY, elems.rsnxe ? false : true, subtype) != WLAN_STATUS_SUCCESS) { goto fail; } return false; @@ -431,7 +448,7 @@ process_old_sta: #endif /* CONFIG_SAE */ #ifdef CONFIG_WPS_REGISTRAR - if (check_n_add_wps_sta(hapd, sta_info, wpa_ie, wpa_ie_len, pmf_enable, subtype) == 0) { + if (check_n_add_wps_sta(hapd, sta_info, elems.rsn_ie, elems.rsn_ie_len, pmf_enable, subtype) == 0) { if (sta_info->eapol_sm) { goto done; } @@ -439,7 +456,8 @@ process_old_sta: goto fail; } #endif - if (hostap_new_assoc_sta(sta_info, bssid, wpa_ie, wpa_ie_len, rsnxe, rsnxe_len, pmf_enable, subtype, pairwise_cipher, &reason)) { + + if (hostap_new_assoc_sta(sta_info, bssid, elems, pmf_enable, subtype, pairwise_cipher, &reason)) { goto done; } else { goto fail; diff --git a/components/wpa_supplicant/src/ap/ap_config.c b/components/wpa_supplicant/src/ap/ap_config.c index 5c613a0d37..2c59e5c247 100644 --- a/components/wpa_supplicant/src/ap/ap_config.c +++ b/components/wpa_supplicant/src/ap/ap_config.c @@ -149,8 +149,8 @@ int hostapd_setup_sae_pt(struct hostapd_bss_config *conf) { #ifdef CONFIG_SAE_H2E struct hostapd_ssid *ssid = &conf->ssid; - if ((conf->sae_pwe == SAE_PWE_HUNT_AND_PECK || - !wpa_key_mgmt_sae(conf->wpa_key_mgmt))) + if (conf->sae_pwe == SAE_PWE_HUNT_AND_PECK || + !wpa_key_mgmt_sae(conf->wpa_key_mgmt)) return 0; /* PT not needed */ sae_deinit_pt(ssid->pt); diff --git a/components/wpa_supplicant/src/ap/ap_config.h b/components/wpa_supplicant/src/ap/ap_config.h index 731b1da032..2be93937d9 100644 --- a/components/wpa_supplicant/src/ap/ap_config.h +++ b/components/wpa_supplicant/src/ap/ap_config.h @@ -11,6 +11,7 @@ #include "common/defs.h" #include "common/wpa_common.h" +#include "common/ieee802_11_common.h" #define MAX_STA_COUNT 10 #define MAX_VLAN_ID 4094 @@ -382,8 +383,7 @@ const u8 * hostapd_get_psk(const struct hostapd_bss_config *conf, const u8 *addr, const u8 *prev_psk); 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, uint16_t rsnxe_len, +bool hostap_new_assoc_sta(struct sta_info *sta, uint8_t *bssid, struct ieee802_11_elems elems, 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/wpa_auth.c b/components/wpa_supplicant/src/ap/wpa_auth.c index d38f6082a2..64cde98b5f 100644 --- a/components/wpa_supplicant/src/ap/wpa_auth.c +++ b/components/wpa_supplicant/src/ap/wpa_auth.c @@ -22,6 +22,7 @@ #include "ap/ap_config.h" #include "ap/sta_info.h" #include "common/wpa_common.h" +#include "common/ieee802_11_common.h" #include "ap/pmksa_cache_auth.h" #include "crypto/aes.h" diff --git a/components/wpa_supplicant/src/common/ieee802_11_common.c b/components/wpa_supplicant/src/common/ieee802_11_common.c index 2af5c04f22..e91cc178ff 100644 --- a/components/wpa_supplicant/src/common/ieee802_11_common.c +++ b/components/wpa_supplicant/src/common/ieee802_11_common.c @@ -191,7 +191,6 @@ int ieee802_11_parse_candidate_list(const char *pos, u8 *nei_rep, return nei_pos - nei_rep; } -#ifdef CONFIG_WPA3_SAE static int ieee802_11_parse_vendor_specific(const u8 *pos, size_t elen, struct ieee802_11_elems *elems, int show_errors) @@ -212,6 +211,62 @@ static int ieee802_11_parse_vendor_specific(const u8 *pos, size_t elen, oui = WPA_GET_BE24(pos); switch (oui) { + case OUI_MICROSOFT: + /* Microsoft/Wi-Fi information elements are further typed and + * subtyped */ + switch (pos[3]) { + case 1: + /* Microsoft OUI (00:50:F2) with OUI Type 1: + * real WPA information element */ + elems->wpa_ie = pos; + elems->wpa_ie_len = elen; + break; + case WMM_OUI_TYPE: + /* WMM information element */ + if (elen < 5) { + wpa_printf(MSG_MSGDUMP, "short WMM " + "information element ignored " + "(len=%lu)", + (unsigned long) elen); + return -1; + } + switch (pos[4]) { + case WMM_OUI_SUBTYPE_INFORMATION_ELEMENT: + case WMM_OUI_SUBTYPE_PARAMETER_ELEMENT: + /* + * Share same pointer since only one of these + * is used and they start with same data. + * Length field can be used to distinguish the + * IEs. + */ + elems->wmm = pos; + elems->wmm_len = elen; + break; + case WMM_OUI_SUBTYPE_TSPEC_ELEMENT: + elems->wmm_tspec = pos; + elems->wmm_tspec_len = elen; + break; + default: + wpa_printf(MSG_EXCESSIVE, "unknown WMM " + "information element ignored " + "(subtype=%d len=%lu)", + pos[4], (unsigned long) elen); + return -1; + } + break; + case 4: + /* Wi-Fi Protected Setup (WPS) IE */ + elems->wps_ie = pos; + elems->wps_ie_len = elen; + break; + default: + wpa_printf(MSG_EXCESSIVE, "Unknown Microsoft " + "information element ignored " + "(type=%d len=%lu)", + pos[3], (unsigned long) elen); + return -1; + } + break; case OUI_WFA: switch (pos[3]) { #ifdef CONFIG_SAE_PK @@ -220,10 +275,12 @@ static int ieee802_11_parse_vendor_specific(const u8 *pos, size_t elen, elems->sae_pk_len = elen - 4; break; #endif /* CONFIG_SAE_PK */ +#ifdef CONFIG_WPA3_SAE case WFA_RSNE_OVERRIDE_OUI_TYPE: elems->rsne_override = pos; elems->rsne_override_len = elen; break; +#endif default: wpa_printf(MSG_EXCESSIVE, "Unknown WFA " "information element ignored " @@ -242,7 +299,6 @@ static int ieee802_11_parse_vendor_specific(const u8 *pos, size_t elen, return 0; } -#endif /* CONFIG_WPA3_SAE */ #ifdef CONFIG_SAE_PK static int ieee802_11_parse_extension(const u8 *pos, size_t elen, @@ -287,7 +343,6 @@ static ParseRes __ieee802_11_parse_elems(const u8 *start, size_t len, struct ieee802_11_elems *elems, int show_errors) { -#if defined(CONFIG_RRM) || defined(CONFIG_WNM) || defined(CONFIG_WPA3_SAE) || defined(CONFIG_SAE_PK) const struct element *elem; u8 unknown = 0; @@ -312,7 +367,6 @@ static ParseRes __ieee802_11_parse_elems(const u8 *start, size_t len, } break; #endif /*CONFIG_SAE_PK*/ -#ifdef CONFIG_WPA3_SAE case WLAN_EID_VENDOR_SPECIFIC: if (ieee802_11_parse_vendor_specific(pos, elen, elems, @@ -320,7 +374,16 @@ static ParseRes __ieee802_11_parse_elems(const u8 *start, size_t len, unknown++; } break; -#endif /* CONFIG_WPA3_SAE */ + case WLAN_EID_RSN: + elems->rsn_ie = pos; + elems->rsn_ie_len = elen; + break; +#ifdef CONFIG_WPA3_SAE + case WLAN_EID_RSNX: + elems->rsnxe = pos; + elems->rsnxe_len = elen; + break; +#endif #ifdef CONFIG_WNM case WLAN_EID_EXT_CAPAB: /* extended caps can go beyond 8 octacts but we aren't using them now */ @@ -336,7 +399,6 @@ static ParseRes __ieee802_11_parse_elems(const u8 *start, size_t len, if (unknown) return ParseFailed; -#endif /* defined(CONFIG_RRM) || defined(CONFIG_WNM) || defined (CONFIG_WPA3_SAE) ||defined(CONFIG_SAE_PK) */ return ParseOK; } /** diff --git a/components/wpa_supplicant/src/common/ieee802_11_common.h b/components/wpa_supplicant/src/common/ieee802_11_common.h index c13173e340..ea36ff013e 100644 --- a/components/wpa_supplicant/src/common/ieee802_11_common.h +++ b/components/wpa_supplicant/src/common/ieee802_11_common.h @@ -50,6 +50,16 @@ extern size_t global_op_class_size; /* Parsed Information Elements */ struct ieee802_11_elems { + const u8 *rsn_ie; + u8 rsn_ie_len; + const u8 *wmm; + u8 wmm_len; + const u8 *wmm_tspec; + u8 wmm_tspec_len; + const u8 *wpa_ie; + u8 wpa_ie_len; + const u8 *wps_ie; + u8 wps_ie_len; #ifdef CONFIG_RRM const u8 *rrm_enabled; u8 rrm_enabled_len; @@ -67,6 +77,8 @@ struct ieee802_11_elems { u8 sae_pk_len; #endif #ifdef CONFIG_WPA3_SAE + const u8 *rsnxe; + u8 rsnxe_len; const u8 *rsne_override; u8 rsne_override_len; #endif diff --git a/components/wpa_supplicant/src/common/ieee802_11_defs.h b/components/wpa_supplicant/src/common/ieee802_11_defs.h index 72c500c8fe..1efb4d3857 100644 --- a/components/wpa_supplicant/src/common/ieee802_11_defs.h +++ b/components/wpa_supplicant/src/common/ieee802_11_defs.h @@ -308,6 +308,12 @@ #define RSNE_OVERRIDE_2_IE_VENDOR_TYPE 0x506f9a2a #define RSNXE_OVERRIDE_IE_VENDOR_TYPE 0x506f9a2b +#define WMM_OUI_TYPE 2 +#define WMM_OUI_SUBTYPE_INFORMATION_ELEMENT 0 +#define WMM_OUI_SUBTYPE_PARAMETER_ELEMENT 1 +#define WMM_OUI_SUBTYPE_TSPEC_ELEMENT 2 +#define WMM_VERSION 1 + #ifdef _MSC_VER #pragma pack(push, 1) #endif /* _MSC_VER */ @@ -566,6 +572,8 @@ struct ieee80211_ht_operation { /* 2 - Reserved */ #define WMM_TSPEC_DIRECTION_BI_DIRECTIONAL 3 +#define OUI_MICROSOFT 0x0050f2 /* Microsoft (also used in Wi-Fi specs) + * 00:50:F2 */ #define MBO_IE_VENDOR_TYPE 0x506f9a16 #define OSEN_IE_VENDOR_TYPE 0x506f9a12 #define SAE_PK_IE_VENDOR_TYPE 0x506f9a1f From 434671f5e635c0153c3b525df7931fa3171b63d5 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Wed, 11 Oct 2023 12:48:05 +0300 Subject: [PATCH 07/33] RSNE/RSNXE overriding for AP Allow hostapd to be configured to advertised two separate sets of RSNE/RSNXE parameters so that RSNE/RSNXE can use a reduced set of capabilities (e.g., WPA2-Personal only) for supporting deployed STAs that have issues with transition modes while the new override elements can use a newer security option (e.g., WPA3-Personal only) for STAs that support the new mechanism. Signed-off-by: Jouni Malinen --- .../esp_supplicant/src/esp_hostap.c | 1 + components/wpa_supplicant/src/ap/ap_config.c | 3 +- components/wpa_supplicant/src/ap/ap_config.h | 3 + components/wpa_supplicant/src/ap/wpa_auth.c | 60 +++- components/wpa_supplicant/src/ap/wpa_auth.h | 4 + components/wpa_supplicant/src/ap/wpa_auth_i.h | 6 +- .../wpa_supplicant/src/ap/wpa_auth_ie.c | 317 +++++++++++++----- .../src/common/ieee802_11_common.c | 18 +- .../src/common/ieee802_11_common.h | 12 +- 9 files changed, 320 insertions(+), 104 deletions(-) diff --git a/components/wpa_supplicant/esp_supplicant/src/esp_hostap.c b/components/wpa_supplicant/esp_supplicant/src/esp_hostap.c index d88f59c3d7..2451ab1e4f 100644 --- a/components/wpa_supplicant/esp_supplicant/src/esp_hostap.c +++ b/components/wpa_supplicant/esp_supplicant/src/esp_hostap.c @@ -422,6 +422,7 @@ bool hostap_new_assoc_sta(struct sta_info *sta, uint8_t *bssid, struct ieee802_1 goto send_resp; } + wpa_auth_set_rsn_override(sta->wpa_sm, elems.rsne_override != NULL); res = wpa_validate_wpa_ie(hapd->wpa_auth, sta->wpa_sm, elems.rsn_ie, elems.rsn_ie_len, elems.rsnxe, elems.rsnxe_len); #ifdef CONFIG_SAE if (wpa_auth_uses_sae(sta->wpa_sm) && sta->sae && diff --git a/components/wpa_supplicant/src/ap/ap_config.c b/components/wpa_supplicant/src/ap/ap_config.c index 2c59e5c247..e4e8b08f62 100644 --- a/components/wpa_supplicant/src/ap/ap_config.c +++ b/components/wpa_supplicant/src/ap/ap_config.c @@ -150,7 +150,8 @@ int hostapd_setup_sae_pt(struct hostapd_bss_config *conf) #ifdef CONFIG_SAE_H2E struct hostapd_ssid *ssid = &conf->ssid; if (conf->sae_pwe == SAE_PWE_HUNT_AND_PECK || - !wpa_key_mgmt_sae(conf->wpa_key_mgmt)) + !wpa_key_mgmt_sae(conf->wpa_key_mgmt | + conf->rsn_override_key_mgmt)) return 0; /* PT not needed */ sae_deinit_pt(ssid->pt); diff --git a/components/wpa_supplicant/src/ap/ap_config.h b/components/wpa_supplicant/src/ap/ap_config.h index 2be93937d9..9aff9d2a7e 100644 --- a/components/wpa_supplicant/src/ap/ap_config.h +++ b/components/wpa_supplicant/src/ap/ap_config.h @@ -200,8 +200,10 @@ struct hostapd_bss_config { int wpa; /* bitfield of WPA_PROTO_WPA, WPA_PROTO_RSN */ int wpa_key_mgmt; + int rsn_override_key_mgmt; #ifdef CONFIG_IEEE80211W enum mfp_options ieee80211w; + enum mfp_options rsn_override_mfp; /* dot11AssociationSAQueryMaximumTimeout (in TUs) */ unsigned int assoc_sa_query_max_timeout; /* dot11AssociationSAQueryRetryTimeout (in TUs) */ @@ -220,6 +222,7 @@ struct hostapd_bss_config { int wpa_ptk_rekey; int rsn_pairwise; int rsn_preauth; + int rsn_override_pairwise; char *rsn_preauth_interfaces; #ifdef CONFIG_IEEE80211R diff --git a/components/wpa_supplicant/src/ap/wpa_auth.c b/components/wpa_supplicant/src/ap/wpa_auth.c index 64cde98b5f..ff43e4547e 100644 --- a/components/wpa_supplicant/src/ap/wpa_auth.c +++ b/components/wpa_supplicant/src/ap/wpa_auth.c @@ -197,6 +197,12 @@ static inline int wpa_auth_get_seqnum(struct wpa_authenticator *wpa_auth, return -1; } +void wpa_auth_set_rsn_override(struct wpa_state_machine *sm, bool val) +{ + if (sm) + sm->rsn_override = val; +} + /* fix buf for tx for now */ #define WPA_TX_MSG_BUFF_MAXLEN 200 @@ -1833,11 +1839,12 @@ static u8 * ieee80211w_kde_add(struct wpa_state_machine *sm, u8 *pos) SM_STATE(WPA_PTK, PTKINITNEGOTIATING) { - u8 rsc[WPA_KEY_RSC_LEN], *_rsc, *gtk, *kde, *pos, dummy_gtk[32]; + u8 rsc[WPA_KEY_RSC_LEN], *_rsc, *gtk, *kde = NULL, *pos, dummy_gtk[32]; size_t gtk_len, kde_len; struct wpa_group *gsm = sm->group; u8 *wpa_ie; int wpa_ie_len, secure, keyidx, encr = 0; + u8 *wpa_ie_buf3 = NULL; SM_ENTRY_MA(WPA_PTK, PTKINITNEGOTIATING, wpa_ptk); sm->TimeoutEvt = FALSE; @@ -1866,6 +1873,49 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING) wpa_ie = wpa_ie + wpa_ie[1] + 2; wpa_ie_len = wpa_ie[1] + 2; } + if (sm->rsn_override && + get_vendor_ie(wpa_ie, wpa_ie_len, RSNE_OVERRIDE_IE_VENDOR_TYPE)) { + const u8 *override_rsne = NULL, *override_rsnxe = NULL; + const struct element *elem; + + wpa_printf(MSG_DEBUG,"RSN: Use RSNE/RSNXE override element contents"); + + for_each_element_id(elem, WLAN_EID_VENDOR_SPECIFIC, + wpa_ie, wpa_ie_len) { + if (elem->datalen >= 4) { + if (WPA_GET_BE32(elem->data) == + RSNE_OVERRIDE_IE_VENDOR_TYPE) + override_rsne = &elem->id; + if (WPA_GET_BE32(elem->data) == + RSNXE_OVERRIDE_IE_VENDOR_TYPE) + override_rsnxe = &elem->id; + } + } + wpa_hexdump(MSG_DEBUG, "EAPOL-Key msg 3/4 IEs before edits", + wpa_ie, wpa_ie_len); + wpa_ie_buf3 = os_malloc(wpa_ie_len); + if (!wpa_ie_buf3) + goto done; + pos = wpa_ie_buf3; + if (override_rsne) { + *pos++ = WLAN_EID_RSN; + *pos++ = override_rsne[1] - 4; + os_memcpy(pos, &override_rsne[2 + 4], + override_rsne[1] - 4); + pos += override_rsne[1] - 4; + } + if (override_rsnxe) { + *pos++ = WLAN_EID_RSNX; + *pos++ = override_rsnxe[1] - 4; + os_memcpy(pos, &override_rsnxe[2 + 4], + override_rsnxe[1] - 4); + pos += override_rsnxe[1] - 4; + } + wpa_ie = wpa_ie_buf3; + wpa_ie_len = pos - wpa_ie_buf3; + wpa_hexdump(MSG_DEBUG, "EAPOL-Key msg 3/4 IEs after edits", + wpa_ie, wpa_ie_len); + } if (sm->wpa == WPA_VERSION_WPA2) { /* WPA2 send GTK in the 4-way handshake */ secure = 1; @@ -1986,7 +2036,9 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING) WPA_KEY_INFO_ACK | WPA_KEY_INFO_INSTALL | WPA_KEY_INFO_KEY_TYPE, _rsc, sm->ANonce, kde, pos - kde, keyidx, encr); +done: os_free(kde); + os_free(wpa_ie_buf3); } @@ -2588,6 +2640,12 @@ void wpa_deinit(struct wpa_authenticator *wpa_auth) if (wpa_auth->wpa_ie != NULL) { os_free(wpa_auth->wpa_ie); } + if (wpa_auth->rsne_override != NULL) { + os_free(wpa_auth->rsne_override); + } + if (wpa_auth->rsnxe_override != NULL) { + os_free(wpa_auth->rsnxe_override); + } if (wpa_auth->group != NULL) { group = wpa_auth->group; while (group) { diff --git a/components/wpa_supplicant/src/ap/wpa_auth.h b/components/wpa_supplicant/src/ap/wpa_auth.h index e2886a9fee..9d7c64efc3 100644 --- a/components/wpa_supplicant/src/ap/wpa_auth.h +++ b/components/wpa_supplicant/src/ap/wpa_auth.h @@ -127,6 +127,7 @@ struct ft_remote_r1kh { struct wpa_auth_config { int wpa; int wpa_key_mgmt; + int rsn_override_key_mgmt; int wpa_pairwise; int wpa_group; int wpa_group_rekey; @@ -134,6 +135,7 @@ struct wpa_auth_config { int wpa_gmk_rekey; int wpa_ptk_rekey; int rsn_pairwise; + int rsn_override_pairwise; int rsn_preauth; int eapol_version; int wmm_enabled; @@ -143,6 +145,7 @@ struct wpa_auth_config { int tx_status; #ifdef CONFIG_IEEE80211W enum mfp_options ieee80211w; + enum mfp_options rsn_override_mfp; #endif /* CONFIG_IEEE80211W */ int group_mgmt_cipher; #ifdef CONFIG_SAE @@ -304,5 +307,6 @@ int wpa_auth_pmksa_add_sae(struct wpa_authenticator *wpa_auth, const u8 *addr, void wpa_auth_add_sae_pmkid(struct wpa_state_machine *sm, const u8 *pmkid); void wpa_auth_pmksa_remove(struct wpa_authenticator *wpa_auth, const u8 *sta_addr); +void wpa_auth_set_rsn_override(struct wpa_state_machine *sm, bool val); #endif /* WPA_AUTH_H */ diff --git a/components/wpa_supplicant/src/ap/wpa_auth_i.h b/components/wpa_supplicant/src/ap/wpa_auth_i.h index 09b254ca2d..ed0b3cfcb1 100644 --- a/components/wpa_supplicant/src/ap/wpa_auth_i.h +++ b/components/wpa_supplicant/src/ap/wpa_auth_i.h @@ -110,6 +110,8 @@ struct wpa_state_machine { int wpa_key_mgmt; /* the selected WPA_KEY_MGMT_* */ struct rsn_pmksa_cache_entry *pmksa; + bool rsn_override; + #ifdef CONFIG_IEEE80211R_AP u8 xxkey[PMK_LEN_MAX]; /* PSK or the second 256 bits of MSK, or the * first 384 bits of MSK */ @@ -184,6 +186,8 @@ struct wpa_authenticator { u8 *wpa_ie; size_t wpa_ie_len; + u8 *rsne_override; /* RSNE with overridden payload */ + u8 *rsnxe_override; /* RSNXE with overridden payload */ struct rsn_pmksa_cache *pmksa; u8 addr[ETH_ALEN]; @@ -195,7 +199,7 @@ struct wpa_authenticator { int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len, - const u8 *pmkid, int group_mgmt_cipher); + const u8 *pmkid); int wpa_write_rsnxe(struct wpa_auth_config *conf, u8 *buf, size_t len); void __wpa_send_eapol(struct wpa_authenticator *wpa_auth, struct wpa_state_machine *sm, int key_info, diff --git a/components/wpa_supplicant/src/ap/wpa_auth_ie.c b/components/wpa_supplicant/src/ap/wpa_auth_ie.c index 9453aa710d..d5b51dcdb0 100644 --- a/components/wpa_supplicant/src/ap/wpa_auth_ie.c +++ b/components/wpa_supplicant/src/ap/wpa_auth_ie.c @@ -85,25 +85,57 @@ static int wpa_write_wpa_ie(struct wpa_auth_config *conf, u8 *buf, size_t len) } -int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len, - const u8 *pmkid, int group_mgmt_cipher) +static u16 wpa_own_rsn_capab(struct wpa_auth_config *conf, + enum mfp_options mfp) +{ + u16 capab = 0; + + if (conf->rsn_preauth) + capab |= WPA_CAPABILITY_PREAUTH; + if (conf->wmm_enabled) { + /* 4 PTKSA replay counters when using WMM */ + capab |= (RSN_NUM_REPLAY_COUNTERS_16 << 2); + } + + if (conf->spp_sup.capable) { + capab |= WPA_CAPABILITY_SPP_CAPABLE; + } + + if (conf->spp_sup.require) { + capab |= WPA_CAPABILITY_SPP_REQUIRED; + } + + if (mfp != NO_MGMT_FRAME_PROTECTION) { + capab |= WPA_CAPABILITY_MFPC; + if (mfp == MGMT_FRAME_PROTECTION_REQUIRED) + capab |= WPA_CAPABILITY_MFPR; + } +#ifdef CONFIG_OCV + if (conf->ocv) + capab |= WPA_CAPABILITY_OCVC; +#endif /* CONFIG_OCV */ +#ifdef CONFIG_RSN_TESTING + if (rsn_testing) + capab |= BIT(8) | BIT(15); +#endif /* CONFIG_RSN_TESTING */ + + return capab; +} + + +static u8 * rsne_write_data(u8 *buf, size_t len, u8 *pos, int group, + int pairwise, int key_mgmt, u16 rsn_capab, + const u8 *pmkid, enum mfp_options mfp, + int group_mgmt_cipher) { - struct rsn_ie_hdr *hdr; int num_suites, res; - u8 *pos, *count; - u16 capab; + u8 *count; u32 suite; - hdr = (struct rsn_ie_hdr *) buf; - hdr->elem_id = WLAN_EID_RSN; - WPA_PUT_LE16(hdr->version, RSN_VERSION); - pos = (u8 *) (hdr + 1); - - suite = wpa_cipher_to_suite(WPA_PROTO_RSN, conf->wpa_group); + suite = wpa_cipher_to_suite(WPA_PROTO_RSN, group); if (suite == 0) { - wpa_printf( MSG_DEBUG, "Invalid group cipher (%d).", - conf->wpa_group); - return -1; + wpa_printf(MSG_DEBUG, "Invalid group cipher (%d).", group); + return NULL; } RSN_SELECTOR_PUT(pos, suite); pos += RSN_SELECTOR_LEN; @@ -120,7 +152,7 @@ int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len, } #endif /* CONFIG_RSN_TESTING */ - res = rsn_cipher_put_suites(pos, conf->rsn_pairwise); + res = rsn_cipher_put_suites(pos, pairwise); num_suites += res; pos += res * RSN_SELECTOR_LEN; @@ -134,8 +166,8 @@ int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len, if (num_suites == 0) { wpa_printf( MSG_DEBUG, "Invalid pairwise cipher (%d).", - conf->rsn_pairwise); - return -1; + pairwise); + return NULL; } WPA_PUT_LE16(count, num_suites); @@ -151,52 +183,52 @@ int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len, } #endif /* CONFIG_RSN_TESTING */ - if (conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X) { + if (key_mgmt & WPA_KEY_MGMT_IEEE8021X) { RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_UNSPEC_802_1X); pos += RSN_SELECTOR_LEN; num_suites++; } - if (conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK) { + if (key_mgmt & WPA_KEY_MGMT_PSK) { RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X); pos += RSN_SELECTOR_LEN; num_suites++; } #ifdef CONFIG_IEEE80211R_AP - if (conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) { + if (key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) { RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_802_1X); pos += RSN_SELECTOR_LEN; num_suites++; } - if (conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_PSK) { + if (key_mgmt & WPA_KEY_MGMT_FT_PSK) { RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_PSK); pos += RSN_SELECTOR_LEN; num_suites++; } #endif /* CONFIG_IEEE80211R_AP */ #ifdef CONFIG_IEEE80211W - if (conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) { + if (key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) { RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_802_1X_SHA256); pos += RSN_SELECTOR_LEN; num_suites++; } - if (conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK_SHA256) { + if (key_mgmt & WPA_KEY_MGMT_PSK_SHA256) { RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_PSK_SHA256); pos += RSN_SELECTOR_LEN; num_suites++; } #endif /* CONFIG_IEEE80211W */ #ifdef CONFIG_SAE - if (conf->wpa_key_mgmt & WPA_KEY_MGMT_SAE) { + if (key_mgmt & WPA_KEY_MGMT_SAE) { RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_SAE); pos += RSN_SELECTOR_LEN; num_suites++; } - if (conf->wpa_key_mgmt & WPA_KEY_MGMT_SAE_EXT_KEY) { - RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_SAE_EXT_KEY); - pos += RSN_SELECTOR_LEN; - num_suites++; + if (key_mgmt & WPA_KEY_MGMT_SAE_EXT_KEY) { + RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_SAE_EXT_KEY); + pos += RSN_SELECTOR_LEN; + num_suites++; } - if (conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_SAE) { + if (key_mgmt & WPA_KEY_MGMT_FT_SAE) { RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_SAE); pos += RSN_SELECTOR_LEN; num_suites++; @@ -212,46 +244,19 @@ int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len, #endif /* CONFIG_RSN_TESTING */ if (num_suites == 0) { - wpa_printf( MSG_DEBUG, "Invalid key management type (%d).", - conf->wpa_key_mgmt); - return -1; + wpa_printf(MSG_DEBUG, "Invalid key management type (%d).", + key_mgmt); + return NULL; } WPA_PUT_LE16(count, num_suites); /* RSN Capabilities */ - capab = 0; - if (conf->rsn_preauth) - capab |= WPA_CAPABILITY_PREAUTH; - if (conf->wmm_enabled) { - /* 4 PTKSA replay counters when using WMM */ - capab |= (RSN_NUM_REPLAY_COUNTERS_16 << 2); - } - - if (conf->spp_sup.capable) { - capab |= WPA_CAPABILITY_SPP_CAPABLE; - } - - if (conf->spp_sup.require) { - capab |= WPA_CAPABILITY_SPP_REQUIRED; - } - -#ifdef CONFIG_IEEE80211W - if (conf->ieee80211w != NO_MGMT_FRAME_PROTECTION) { - capab |= WPA_CAPABILITY_MFPC; - if (conf->ieee80211w == MGMT_FRAME_PROTECTION_REQUIRED) - capab |= WPA_CAPABILITY_MFPR; - } -#endif /* CONFIG_IEEE80211W */ -#ifdef CONFIG_RSN_TESTING - if (rsn_testing) - capab |= BIT(8) | BIT(14) | BIT(15); -#endif /* CONFIG_RSN_TESTING */ - WPA_PUT_LE16(pos, capab); + WPA_PUT_LE16(pos, rsn_capab); pos += 2; if (pmkid) { if (pos + 2 + PMKID_LEN > buf + len) - return -1; + return NULL; /* PMKID Count */ WPA_PUT_LE16(pos, 1); pos += 2; @@ -260,9 +265,9 @@ int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len, } #ifdef CONFIG_IEEE80211W - if (conf->ieee80211w != NO_MGMT_FRAME_PROTECTION) { + if (mfp != NO_MGMT_FRAME_PROTECTION) { if (pos + 2 + 4 > buf + len) - return -1; + return NULL; if (pmkid == NULL) { /* PMKID Count */ WPA_PUT_LE16(pos, 0); @@ -281,7 +286,10 @@ int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len, RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_BIP_GMAC_256); break; default: - RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_AES_128_CMAC); + wpa_printf(MSG_DEBUG, + "Invalid group management cipher (0x%x)", + group_mgmt_cipher); + return NULL; } pos += RSN_SELECTOR_LEN; } @@ -294,12 +302,12 @@ int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len, * the element. */ int pmkid_count_set = pmkid != NULL; - if (conf->ieee80211w != NO_MGMT_FRAME_PROTECTION) + if (mfp != NO_MGMT_FRAME_PROTECTION) pmkid_count_set = 1; /* PMKID Count */ WPA_PUT_LE16(pos, 0); pos += 2; - if (conf->ieee80211w == NO_MGMT_FRAME_PROTECTION) { + if (mfp == NO_MGMT_FRAME_PROTECTION) { /* Management Group Cipher Suite */ RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_AES_128_CMAC); pos += RSN_SELECTOR_LEN; @@ -309,6 +317,27 @@ int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len, pos += 17; } #endif /* CONFIG_RSN_TESTING */ + return pos; +} + + +int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len, + const u8 *pmkid) +{ + struct rsn_ie_hdr *hdr; + u8 *pos; + + hdr = (struct rsn_ie_hdr *) buf; + hdr->elem_id = WLAN_EID_RSN; + WPA_PUT_LE16(hdr->version, RSN_VERSION); + pos = (u8 *) (hdr + 1); + + pos = rsne_write_data(buf, len, pos, conf->wpa_group, + conf->rsn_pairwise, conf->wpa_key_mgmt, + wpa_own_rsn_capab(conf, conf->ieee80211w), pmkid, + conf->ieee80211w, conf->group_mgmt_cipher); + if (!pos) + return -1; hdr->len = (pos - buf) - 2; @@ -316,28 +345,105 @@ int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len, } -int wpa_write_rsnxe(struct wpa_auth_config *conf, u8 *buf, size_t len) -{ - u8 *pos = buf; - u16 capab = 0; - size_t flen; - if (wpa_key_mgmt_sae(conf->wpa_key_mgmt) && +static int wpa_write_rsne_override(struct wpa_auth_config *conf, u8 *buf, + size_t len) +{ + u8 *pos, *len_pos; + + pos = buf; + *pos++ = WLAN_EID_VENDOR_SPECIFIC; + len_pos = pos++; + + WPA_PUT_BE32(pos, RSNE_OVERRIDE_IE_VENDOR_TYPE); + pos += 4; + + WPA_PUT_LE16(pos, RSN_VERSION); + pos += 2; + + pos = rsne_write_data(buf, len, pos, conf->wpa_group, + conf->rsn_override_pairwise, + conf->rsn_override_key_mgmt, + wpa_own_rsn_capab(conf, conf->rsn_override_mfp), + NULL, conf->rsn_override_mfp, + conf->group_mgmt_cipher); + if (!pos) + return -1; + + *len_pos = (pos - buf) - 2; + + return pos - buf; +} + + +static u32 rsnxe_capab(struct wpa_auth_config *conf, int key_mgmt) +{ + u32 capab = 0; + + if (wpa_key_mgmt_sae(key_mgmt) && (conf->sae_pwe == SAE_PWE_HASH_TO_ELEMENT || conf->sae_pwe == SAE_PWE_BOTH)) { capab |= BIT(WLAN_RSNX_CAPAB_SAE_H2E); } - flen = 1; + return capab; +} + +int wpa_write_rsnxe(struct wpa_auth_config *conf, u8 *buf, size_t len) +{ + u8 *pos = buf; + u32 capab = 0, tmp; + size_t flen; + + capab = rsnxe_capab(conf, conf->wpa_key_mgmt); + if (!capab) return 0; /* no supported extended RSN capabilities */ + tmp = capab; + flen = 0; + while (tmp) { + flen++; + tmp >>= 8; + } if (len < 2 + flen) return -1; capab |= flen - 1; /* bit 0-3 = Field length (n - 1) */ *pos++ = WLAN_EID_RSNX; *pos++ = flen; + while (capab) { + *pos++ = capab & 0xff; + capab >>= 8; + } + + return pos - buf; +} + +static int wpa_write_rsnxe_override(struct wpa_auth_config *conf, u8 *buf, + size_t len) +{ + u8 *pos = buf; + u16 capab; + size_t flen; + + capab = rsnxe_capab(conf, conf->rsn_override_key_mgmt); + + flen = (capab & 0xff00) ? 2 : 1; + if (!capab) + return 0; /* no supported extended RSN capabilities */ + if (len < 2 + flen) + return -1; + capab |= flen - 1; /* bit 0-3 = Field length (n - 1) */ + + *pos++ = WLAN_EID_VENDOR_SPECIFIC; + *pos++ = 4 + flen; + WPA_PUT_BE32(pos, RSNXE_OVERRIDE_IE_VENDOR_TYPE); + pos += 4; + *pos++ = capab & 0x00ff; + capab >>= 8; + if (capab) + *pos++ = capab; return pos - buf; } @@ -345,14 +451,14 @@ int wpa_write_rsnxe(struct wpa_auth_config *conf, u8 *buf, size_t len) int wpa_auth_gen_wpa_ie(struct wpa_authenticator *wpa_auth) { - u8 *pos, buf[128]; + u8 *pos, buf[256]; int res; pos = buf; if (wpa_auth->conf.wpa & WPA_PROTO_RSN) { res = wpa_write_rsn_ie(&wpa_auth->conf, - pos, buf + sizeof(buf) - pos, NULL, wpa_auth->conf.group_mgmt_cipher); + pos, buf + sizeof(buf) - pos, NULL); if (res < 0) return res; pos += res; @@ -379,6 +485,24 @@ int wpa_auth_gen_wpa_ie(struct wpa_authenticator *wpa_auth) pos += res; } + if ((wpa_auth->conf.wpa & WPA_PROTO_RSN) && + wpa_auth->conf.rsn_override_key_mgmt) { + res = wpa_write_rsne_override(&wpa_auth->conf, + pos, buf + sizeof(buf) - pos); + if (res < 0) + return res; + pos += res; + } + + if ((wpa_auth->conf.wpa & WPA_PROTO_RSN) && + (wpa_auth->conf.rsn_override_key_mgmt)) { + res = wpa_write_rsnxe_override(&wpa_auth->conf, pos, + buf + sizeof(buf) - pos); + if (res < 0) + return res; + pos += res; + } + os_free(wpa_auth->wpa_ie); wpa_auth->wpa_ie = os_malloc(pos - buf); if (wpa_auth->wpa_ie == NULL) @@ -386,6 +510,42 @@ int wpa_auth_gen_wpa_ie(struct wpa_authenticator *wpa_auth) memcpy(wpa_auth->wpa_ie, buf, pos - buf); wpa_auth->wpa_ie_len = pos - buf; + if ((wpa_auth->conf.wpa & WPA_PROTO_RSN) && + wpa_auth->conf.rsn_override_key_mgmt) { + res = wpa_write_rsne_override(&wpa_auth->conf, buf, + sizeof(buf)); + if (res < 0) + return res; + os_free(wpa_auth->rsne_override); + wpa_auth->rsne_override = os_malloc(res - 4); + if (!wpa_auth->rsne_override) + return -1; + pos = wpa_auth->rsne_override; + *pos++ = WLAN_EID_RSN; + *pos++ = res - 2 - 4; + os_memcpy(pos, &buf[2 + 4], res - 2 - 4); + } + + if ((wpa_auth->conf.wpa & WPA_PROTO_RSN) && + (wpa_auth->conf.rsn_override_key_mgmt)) { + res = wpa_write_rsnxe_override(&wpa_auth->conf, buf, + sizeof(buf)); + if (res < 0) + return res; + os_free(wpa_auth->rsnxe_override); + if (res == 0) { + wpa_auth->rsnxe_override = NULL; + return 0; + } + wpa_auth->rsnxe_override = os_malloc(res - 4); + if (!wpa_auth->rsnxe_override) + return -1; + pos = wpa_auth->rsnxe_override; + *pos++ = WLAN_EID_RSNX; + *pos++ = res - 2 - 4; + os_memcpy(pos, &buf[2 + 4], res - 2 - 4); + } + return 0; } @@ -514,7 +674,8 @@ wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth, return WPA_INVALID_GROUP; } - key_mgmt = data.key_mgmt & wpa_auth->conf.wpa_key_mgmt; + key_mgmt = data.key_mgmt & (wpa_auth->conf.wpa_key_mgmt | + wpa_auth->conf.rsn_override_key_mgmt); if (!key_mgmt) { wpa_printf( MSG_DEBUG, "Invalid WPA key mgmt (0x%x) from " MACSTR, data.key_mgmt, MAC2STR(sm->addr)); @@ -548,7 +709,9 @@ wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth, sm->wpa_key_mgmt = WPA_KEY_MGMT_PSK; if (version == WPA_PROTO_RSN) - ciphers = data.pairwise_cipher & wpa_auth->conf.rsn_pairwise; + ciphers = data.pairwise_cipher & + (wpa_auth->conf.rsn_pairwise | + wpa_auth->conf.rsn_override_pairwise); else ciphers = data.pairwise_cipher & wpa_auth->conf.wpa_pairwise; if (!ciphers) { diff --git a/components/wpa_supplicant/src/common/ieee802_11_common.c b/components/wpa_supplicant/src/common/ieee802_11_common.c index e91cc178ff..64fbf945bd 100644 --- a/components/wpa_supplicant/src/common/ieee802_11_common.c +++ b/components/wpa_supplicant/src/common/ieee802_11_common.c @@ -191,6 +191,7 @@ int ieee802_11_parse_candidate_list(const char *pos, u8 *nei_rep, return nei_pos - nei_rep; } +#ifdef CONFIG_WPA3_SAE static int ieee802_11_parse_vendor_specific(const u8 *pos, size_t elen, struct ieee802_11_elems *elems, int show_errors) @@ -216,10 +217,6 @@ static int ieee802_11_parse_vendor_specific(const u8 *pos, size_t elen, * subtyped */ switch (pos[3]) { case 1: - /* Microsoft OUI (00:50:F2) with OUI Type 1: - * real WPA information element */ - elems->wpa_ie = pos; - elems->wpa_ie_len = elen; break; case WMM_OUI_TYPE: /* WMM information element */ @@ -239,12 +236,8 @@ static int ieee802_11_parse_vendor_specific(const u8 *pos, size_t elen, * Length field can be used to distinguish the * IEs. */ - elems->wmm = pos; - elems->wmm_len = elen; break; case WMM_OUI_SUBTYPE_TSPEC_ELEMENT: - elems->wmm_tspec = pos; - elems->wmm_tspec_len = elen; break; default: wpa_printf(MSG_EXCESSIVE, "unknown WMM " @@ -256,8 +249,6 @@ static int ieee802_11_parse_vendor_specific(const u8 *pos, size_t elen, break; case 4: /* Wi-Fi Protected Setup (WPS) IE */ - elems->wps_ie = pos; - elems->wps_ie_len = elen; break; default: wpa_printf(MSG_EXCESSIVE, "Unknown Microsoft " @@ -275,12 +266,10 @@ static int ieee802_11_parse_vendor_specific(const u8 *pos, size_t elen, elems->sae_pk_len = elen - 4; break; #endif /* CONFIG_SAE_PK */ -#ifdef CONFIG_WPA3_SAE case WFA_RSNE_OVERRIDE_OUI_TYPE: elems->rsne_override = pos; elems->rsne_override_len = elen; break; -#endif default: wpa_printf(MSG_EXCESSIVE, "Unknown WFA " "information element ignored " @@ -299,6 +288,7 @@ static int ieee802_11_parse_vendor_specific(const u8 *pos, size_t elen, return 0; } +#endif /* CONFIG_WPA3_SAE */ #ifdef CONFIG_SAE_PK static int ieee802_11_parse_extension(const u8 *pos, size_t elen, @@ -367,6 +357,7 @@ static ParseRes __ieee802_11_parse_elems(const u8 *start, size_t len, } break; #endif /*CONFIG_SAE_PK*/ +#ifdef CONFIG_WPA3_SAE case WLAN_EID_VENDOR_SPECIFIC: if (ieee802_11_parse_vendor_specific(pos, elen, elems, @@ -374,16 +365,15 @@ static ParseRes __ieee802_11_parse_elems(const u8 *start, size_t len, unknown++; } break; +#endif /* CONFIG_WPA3_SAE */ case WLAN_EID_RSN: elems->rsn_ie = pos; elems->rsn_ie_len = elen; break; -#ifdef CONFIG_WPA3_SAE case WLAN_EID_RSNX: elems->rsnxe = pos; elems->rsnxe_len = elen; break; -#endif #ifdef CONFIG_WNM case WLAN_EID_EXT_CAPAB: /* extended caps can go beyond 8 octacts but we aren't using them now */ diff --git a/components/wpa_supplicant/src/common/ieee802_11_common.h b/components/wpa_supplicant/src/common/ieee802_11_common.h index ea36ff013e..9a63a7b201 100644 --- a/components/wpa_supplicant/src/common/ieee802_11_common.h +++ b/components/wpa_supplicant/src/common/ieee802_11_common.h @@ -52,14 +52,8 @@ extern size_t global_op_class_size; struct ieee802_11_elems { const u8 *rsn_ie; u8 rsn_ie_len; - const u8 *wmm; - u8 wmm_len; - const u8 *wmm_tspec; - u8 wmm_tspec_len; - const u8 *wpa_ie; - u8 wpa_ie_len; - const u8 *wps_ie; - u8 wps_ie_len; + const u8 *rsnxe; + u8 rsnxe_len; #ifdef CONFIG_RRM const u8 *rrm_enabled; u8 rrm_enabled_len; @@ -77,8 +71,6 @@ struct ieee802_11_elems { u8 sae_pk_len; #endif #ifdef CONFIG_WPA3_SAE - const u8 *rsnxe; - u8 rsnxe_len; const u8 *rsne_override; u8 rsne_override_len; #endif From ee3723b922d2c2784437d8e2e9d4444e1734fe6f Mon Sep 17 00:00:00 2001 From: Shreyas Sheth Date: Mon, 17 Feb 2025 01:54:07 +0530 Subject: [PATCH 08/33] feat(wifi): Add support for wpa3 compatible flag for softap --- .../esp_wifi/include/esp_wifi_types_generic.h | 4 +++ .../esp_supplicant/src/esp_hostap.c | 9 +++++++ .../esp_supplicant/src/esp_wpa_main.c | 2 -- .../src/common/ieee802_11_common.c | 27 +++++++++++++++++++ .../src/common/ieee802_11_defs.h | 18 ++++++++++++- .../softAP/main/softap_example_main.c | 1 + 6 files changed, 58 insertions(+), 3 deletions(-) diff --git a/components/esp_wifi/include/esp_wifi_types_generic.h b/components/esp_wifi/include/esp_wifi_types_generic.h index fb7e7b6764..5557024eeb 100644 --- a/components/esp_wifi/include/esp_wifi_types_generic.h +++ b/components/esp_wifi/include/esp_wifi_types_generic.h @@ -535,6 +535,10 @@ typedef struct { wifi_sae_pwe_method_t sae_pwe_h2e; /**< Configuration for SAE PWE derivation method */ uint8_t transition_disable; /**< Whether to enable transition disable feature */ uint8_t sae_ext; /**< Enable SAE EXT feature. SOC_GCMP_SUPPORT is required for this feature. */ + uint8_t transition_disable: 1; /**< Whether to enable transition disable feature */ + uint8_t sae_ext: 1; /**< Enable SAE EXT feature. SOC_GCMP_SUPPORT is required for this feature. */ + uint8_t wpa3_compatible_mode: 1; /**< Whether to enable wpa3 compatible authmode feature */ + uint8_t reserved: 5; /**< Reserved for future feature set */ wifi_bss_max_idle_config_t bss_max_idle_cfg; /**< Configuration for bss max idle, effective if CONFIG_WIFI_BSS_MAX_IDLE_SUPPORT is enabled */ uint16_t gtk_rekey_interval; /**< GTK rekeying interval in seconds. If set to 0, GTK rekeying is disabled. Range: 60 ~ 65535 including 0. */ } wifi_ap_config_t; diff --git a/components/wpa_supplicant/esp_supplicant/src/esp_hostap.c b/components/wpa_supplicant/esp_supplicant/src/esp_hostap.c index 2451ab1e4f..f7caf531bf 100644 --- a/components/wpa_supplicant/esp_supplicant/src/esp_hostap.c +++ b/components/wpa_supplicant/esp_supplicant/src/esp_hostap.c @@ -111,6 +111,15 @@ void *hostap_init(void) } } #endif /* CONFIG_IEEE80211W */ +//TODO how to set values + if (true) { + hapd->conf->rsn_override_key_mgmt = WPA_KEY_MGMT_SAE; + hapd->conf->rsn_override_pairwise = WPA_CIPHER_CCMP; + hapd->conf->rsn_override_mfp = MGMT_FRAME_PROTECTION_REQUIRED; + auth_conf->rsn_override_key_mgmt = WPA_KEY_MGMT_SAE; + auth_conf->rsn_override_pairwise = WPA_CIPHER_CCMP; + auth_conf->rsn_override_mfp = MGMT_FRAME_PROTECTION_REQUIRED; + } /* TKIP is compulsory in WPA Mode */ if (auth_conf->wpa == WPA_PROTO_WPA && pairwise_cipher == WIFI_CIPHER_TYPE_CCMP) { pairwise_cipher = WIFI_CIPHER_TYPE_TKIP_CCMP; 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 f0bce5803a..c1df251ea5 100644 --- a/components/wpa_supplicant/esp_supplicant/src/esp_wpa_main.c +++ b/components/wpa_supplicant/esp_supplicant/src/esp_wpa_main.c @@ -396,12 +396,10 @@ static bool hostap_sta_join(void **sta, u8 *bssid, u8 *assoc_req_ie, uint32_t as if (elems.rsn_ie) { elems.rsn_ie = elems.rsn_ie - 2; elems.rsn_ie_len = elems.rsn_ie_len + 2; - wpa_printf(MSG_DEBUG, "STA included RSN IE in (Re)AssocReq"); } if (elems.rsnxe) { elems.rsnxe = elems.rsnxe - 2; elems.rsnxe_len = elems.rsnxe_len + 2; - wpa_printf(MSG_DEBUG, "STA included RSN IE in (Re)AssocReq"); } if (*sta) { diff --git a/components/wpa_supplicant/src/common/ieee802_11_common.c b/components/wpa_supplicant/src/common/ieee802_11_common.c index 64fbf945bd..1f76a92f8a 100644 --- a/components/wpa_supplicant/src/common/ieee802_11_common.c +++ b/components/wpa_supplicant/src/common/ieee802_11_common.c @@ -266,6 +266,33 @@ static int ieee802_11_parse_vendor_specific(const u8 *pos, size_t elen, elems->sae_pk_len = elen - 4; break; #endif /* CONFIG_SAE_PK */ +//TODO think of way to ignore these + case P2P_OUI_TYPE: + /* Wi-Fi Alliance - P2P IE */ + break; + case WFD_OUI_TYPE: + /* Wi-Fi Alliance - WFD IE */ + break; + case HS20_INDICATION_OUI_TYPE: + /* Hotspot 2.0 */ + break; + case HS20_OSEN_OUI_TYPE: + /* Hotspot 2.0 OSEN */ + break; + case MBO_OUI_TYPE: + /* MBO-OCE */ + break; + case HS20_ROAMING_CONS_SEL_OUI_TYPE: + /* Hotspot 2.0 Roaming Consortium Selection */ + break; + case MULTI_AP_OUI_TYPE: + break; + case OWE_OUI_TYPE: + /* OWE Transition Mode element */ + break; + case DPP_CC_OUI_TYPE: + /* DPP Configurator Connectivity element */ + break; case WFA_RSNE_OVERRIDE_OUI_TYPE: elems->rsne_override = pos; elems->rsne_override_len = elen; diff --git a/components/wpa_supplicant/src/common/ieee802_11_defs.h b/components/wpa_supplicant/src/common/ieee802_11_defs.h index 1efb4d3857..7b34269df6 100644 --- a/components/wpa_supplicant/src/common/ieee802_11_defs.h +++ b/components/wpa_supplicant/src/common/ieee802_11_defs.h @@ -299,8 +299,9 @@ #define WLAN_TIMEOUT_KEY_LIFETIME 2 #define WLAN_TIMEOUT_ASSOC_COMEBACK 3 -#define OUI_WFA 0x506f9a +/* DPP Public Action frame identifiers - OUI_WFA */ #define DPP_OUI_TYPE 0x1A +#define OUI_WFA 0x506f9a #define WFA_RSNE_OVERRIDE_OUI_TYPE 0x29 #define WFA_RSNE_OVERRIDE_2_OUI_TYPE 0x2a #define WFA_RSNXE_OVERRIDE_OUI_TYPE 0x2b @@ -308,6 +309,21 @@ #define RSNE_OVERRIDE_2_IE_VENDOR_TYPE 0x506f9a2a #define RSNXE_OVERRIDE_IE_VENDOR_TYPE 0x506f9a2b +#define WFD_OUI_TYPE 10 +#define NAN_OUI_TYPE 0x13 +#define MBO_OUI_TYPE 22 +#define OWE_OUI_TYPE 28 +#define MULTI_AP_OUI_TYPE 0x1B +#define DPP_CC_OUI_TYPE 0x1e +#define SAE_PK_OUI_TYPE 0x1f +#define QM_IE_OUI_TYPE 0x22 +#define WFA_CAPA_OUI_TYPE 0x23 + +#define P2P_OUI_TYPE 9 +#define HS20_INDICATION_OUI_TYPE 16 +#define HS20_OSEN_OUI_TYPE 18 +#define HS20_ROAMING_CONS_SEL_OUI_TYPE 29 + #define WMM_OUI_TYPE 2 #define WMM_OUI_SUBTYPE_INFORMATION_ELEMENT 0 #define WMM_OUI_SUBTYPE_PARAMETER_ELEMENT 1 diff --git a/examples/wifi/getting_started/softAP/main/softap_example_main.c b/examples/wifi/getting_started/softAP/main/softap_example_main.c index c2bca87431..f4baa2052a 100644 --- a/examples/wifi/getting_started/softAP/main/softap_example_main.c +++ b/examples/wifi/getting_started/softAP/main/softap_example_main.c @@ -78,6 +78,7 @@ void wifi_init_softap(void) #else /* CONFIG_ESP_WIFI_SOFTAP_SAE_SUPPORT */ .authmode = WIFI_AUTH_WPA2_PSK, #endif + .wpa3_compatible_mode = 1, .pmf_cfg = { .required = true, }, From 18db88ab4a1b83bb3732e5e4f033d573970e42e5 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Wed, 11 Oct 2023 12:50:05 +0300 Subject: [PATCH 09/33] RSNE/RSNXE overriding for STA Add support for RSNE/RSNXE Override elements. Use these elements to determine AP's extended RSN parameters. Signed-off-by: Jouni Malinen --- .../esp_supplicant/src/esp_wpa3.c | 7 +- components/wpa_supplicant/src/rsn_supp/wpa.c | 106 +++++++++++++++--- components/wpa_supplicant/src/rsn_supp/wpa.h | 4 +- .../wpa_supplicant/src/rsn_supp/wpa_ie.c | 5 +- 4 files changed, 101 insertions(+), 21 deletions(-) diff --git a/components/wpa_supplicant/esp_supplicant/src/esp_wpa3.c b/components/wpa_supplicant/esp_supplicant/src/esp_wpa3.c index c9b09881ee..8a4782d676 100644 --- a/components/wpa_supplicant/esp_supplicant/src/esp_wpa3.c +++ b/components/wpa_supplicant/esp_supplicant/src/esp_wpa3.c @@ -46,8 +46,11 @@ static esp_err_t wpa3_build_sae_commit(u8 *bssid, size_t *sae_msg_len) use_pt = 1; } - rsnxe = esp_wifi_sta_get_rsnxe(bssid); - if (rsnxe && rsnxe[1] >= 1) { + rsnxe = esp_wifi_sta_get_ie((u8*)bssid, WLAN_EID_RSNX); + if (rsnxe && rsnxe[0] == WLAN_EID_VENDOR_SPECIFIC && + rsnxe[1] >= 1 + 4) { + rsnxe_capa = rsnxe[2 + 4]; + } else if (rsnxe && rsnxe[1] >= 1) { rsnxe_capa = rsnxe[2]; } #endif /* CONFIG_SAE_H2E */ diff --git a/components/wpa_supplicant/src/rsn_supp/wpa.c b/components/wpa_supplicant/src/rsn_supp/wpa.c index 75fe1f5094..c2e7891983 100644 --- a/components/wpa_supplicant/src/rsn_supp/wpa.c +++ b/components/wpa_supplicant/src/rsn_supp/wpa.c @@ -2329,6 +2329,7 @@ int wpa_set_bss(char *macddr, char * bssid, u8 pairwise_cipher, u8 group_cipher, size_t assoc_rsnxe_len = sizeof(assoc_rsnxe); bool reassoc_same_ess = false; int try_opportunistic = 0; + const u8 *ie = NULL; /* Incase AP has changed it's SSID, don't try with PMK caching for SAE connection */ /* Ideally we should use network_ctx for this purpose however currently network profile block @@ -2447,9 +2448,10 @@ int wpa_set_bss(char *macddr, char * bssid, u8 pairwise_cipher, u8 group_cipher, return -1; sm->assoc_wpa_ie_len = res; - const u8 *rsnxe; - rsnxe = esp_wifi_sta_get_rsnxe((u8*)bssid); - wpa_sm_set_ap_rsnxe(rsnxe, rsnxe ? (rsnxe[1] + 2) : 0); + ie = esp_wifi_sta_get_ie((u8*)bssid, WLAN_EID_RSN); + wpa_sm_set_ap_rsn_ie(sm, ie, ie[1]+2); + ie = esp_wifi_sta_get_ie((u8*)bssid, WLAN_EID_RSNX); + wpa_sm_set_ap_rsnxe(sm, ie, ie ? (ie[1] + 2) : 0); res = wpa_gen_rsnxe(sm, assoc_rsnxe, assoc_rsnxe_len); if (res < 0) @@ -2740,23 +2742,93 @@ struct wpa_sm * get_wpa_sm(void) return &gWpaSm; } -int wpa_sm_set_ap_rsnxe(const u8 *ie, size_t len) +/** + * wpa_sm_set_ap_rsn_ie - Set AP RSN IE from Beacon/ProbeResp + * @sm: Pointer to WPA state machine data from wpa_sm_init() + * @ie: Pointer to IE data (starting from id) + * @len: IE length + * Returns: 0 on success, -1 on failure + * + * Inform WPA state machine about the RSN IE used in Beacon / Probe Response + * frame. + */ +int wpa_sm_set_ap_rsn_ie(struct wpa_sm *sm, const u8 *ie, size_t len) { - struct wpa_sm *sm = &gWpaSm; + if (sm == NULL) + return -1; - os_free(sm->ap_rsnxe); - if (!ie || len == 0) { - wpa_hexdump(MSG_DEBUG, "WPA: set AP RSNXE", ie, len); - sm->ap_rsnxe = NULL; - sm->ap_rsnxe_len = 0; - } else { - wpa_hexdump(MSG_DEBUG, "WPA: set AP RSNXE", ie, len); - sm->ap_rsnxe = os_memdup(ie, len); - if (!sm->ap_rsnxe) - return -1; + os_free(sm->ap_rsn_ie); + if (ie == NULL || len == 0) { + wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, + "WPA: clearing AP RSN IE"); + sm->ap_rsn_ie = NULL; + sm->ap_rsn_ie_len = 0; + } else { + wpa_hexdump(MSG_DEBUG, "WPA: set AP RSN IE", ie, len); + if (ie[0] == WLAN_EID_VENDOR_SPECIFIC && len > 2 + 4) { + sm->ap_rsn_ie = os_malloc(len - 4); + if (!sm->ap_rsn_ie) + return -1; + sm->ap_rsn_ie[0] = WLAN_EID_RSN; + sm->ap_rsn_ie[1] = len - 2 - 4; + os_memcpy(&sm->ap_rsn_ie[2], ie + 2 + 4, len - 2 - 4); + sm->ap_rsn_ie_len = len - 4; + wpa_hexdump(MSG_DEBUG, + "RSN: Converted RSNE override to RSNE", + sm->ap_rsn_ie, sm->ap_rsn_ie_len); + } else { + sm->ap_rsn_ie = os_memdup(ie, len); + if (sm->ap_rsn_ie == NULL) + return -1; - sm->ap_rsnxe_len = len; - } + sm->ap_rsn_ie_len = len; + } + } + + return 0; +} + +/** + * wpa_sm_set_ap_rsnxe - Set AP RSNXE from Beacon/ProbeResp + * @sm: Pointer to WPA state machine data from wpa_sm_init() + * @ie: Pointer to IE data (starting from id) + * @len: IE length + * Returns: 0 on success, -1 on failure + * + * Inform WPA state machine about the RSNXE used in Beacon / Probe Response + * frame. + */ +int wpa_sm_set_ap_rsnxe(struct wpa_sm *sm, const u8 *ie, size_t len) +{ + if (!sm) + return -1; + + os_free(sm->ap_rsnxe); + if (!ie || len == 0) { + wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: clearing AP RSNXE"); + sm->ap_rsnxe = NULL; + sm->ap_rsnxe_len = 0; + } else { + wpa_hexdump(MSG_DEBUG, "WPA: set AP RSNXE", ie, len); + if (ie[0] == WLAN_EID_VENDOR_SPECIFIC && len > 2 + 4) { + sm->ap_rsnxe = os_malloc(len - 4); + if (!sm->ap_rsnxe) + return -1; + sm->ap_rsnxe[0] = WLAN_EID_RSNX; + sm->ap_rsnxe[1] = len - 2 - 4; + os_memcpy(&sm->ap_rsnxe[2], ie + 2 + 4, len - 2 - 4); + sm->ap_rsnxe_len = len - 4; + wpa_hexdump(MSG_DEBUG, + "RSN: Converted RSNXE override to RSNXE", + sm->ap_rsnxe, sm->ap_rsnxe_len); + } else { + sm->ap_rsnxe = os_memdup(ie, len); + if (!sm->ap_rsnxe) + return -1; + + sm->ap_rsnxe_len = len; + } + } if (sm->ap_rsnxe != NULL) { sm->sae_pwe = esp_wifi_get_config_sae_pwe_h2e_internal(WIFI_IF_STA); diff --git a/components/wpa_supplicant/src/rsn_supp/wpa.h b/components/wpa_supplicant/src/rsn_supp/wpa.h index 12e0fd7f09..ab6653ea36 100644 --- a/components/wpa_supplicant/src/rsn_supp/wpa.h +++ b/components/wpa_supplicant/src/rsn_supp/wpa.h @@ -54,7 +54,9 @@ int wpa_sm_set_key(struct install_key *sm, enum wpa_alg alg, u8 *key, size_t key_len, enum key_flag key_flag); -int wpa_sm_set_ap_rsnxe(const u8 *ie, size_t len); +int wpa_sm_set_ap_rsn_ie(struct wpa_sm *sm, const u8 *ie, size_t len); + +int wpa_sm_set_ap_rsnxe(struct wpa_sm *sm, const u8 *ie, size_t len); int wpa_sm_set_assoc_rsnxe(struct wpa_sm *sm, const u8 *ie, size_t len); diff --git a/components/wpa_supplicant/src/rsn_supp/wpa_ie.c b/components/wpa_supplicant/src/rsn_supp/wpa_ie.c index 3b885af4ce..cf4566bd50 100644 --- a/components/wpa_supplicant/src/rsn_supp/wpa_ie.c +++ b/components/wpa_supplicant/src/rsn_supp/wpa_ie.c @@ -39,8 +39,11 @@ int wpa_parse_wpa_ie(const u8 *wpa_ie, size_t wpa_ie_len, return wpa_parse_wpa_ie_rsnxe(wpa_ie, wpa_ie_len, data); } else if (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(wpa_ie, wpa_ie_len, data); } - return wpa_parse_wpa_ie_wpa(wpa_ie, wpa_ie_len, data); } From 1e7dfd789642f806171f658e088e5fdaac5f1ef1 Mon Sep 17 00:00:00 2001 From: Shreyas Sheth Date: Thu, 27 Mar 2025 14:27:38 +0530 Subject: [PATCH 10/33] feat(esp_wifi): Restructure wpa_supplicant for wpa3_compatible mode --- .../esp_supplicant/src/esp_hostap.c | 4 +- .../esp_supplicant/src/esp_wifi_driver.h | 4 +- .../esp_supplicant/src/esp_wpa3.c | 9 +++- .../esp_supplicant/src/esp_wpa_main.c | 4 +- .../src/common/ieee802_11_common.c | 1 - components/wpa_supplicant/src/rsn_supp/wpa.c | 53 +++++++++++++------ .../wpa_supplicant/src/rsn_supp/wpa_i.h | 2 +- 7 files changed, 52 insertions(+), 25 deletions(-) diff --git a/components/wpa_supplicant/esp_supplicant/src/esp_hostap.c b/components/wpa_supplicant/esp_supplicant/src/esp_hostap.c index f7caf531bf..a9de639d77 100644 --- a/components/wpa_supplicant/esp_supplicant/src/esp_hostap.c +++ b/components/wpa_supplicant/esp_supplicant/src/esp_hostap.c @@ -10,7 +10,6 @@ #include "utils/eloop.h" #include "crypto/sha1.h" #include "common/ieee802_11_defs.h" -#include "common/ieee802_11_common.h" #include "common/eapol_common.h" #include "ap/wpa_auth.h" #include "ap/ap_config.h" @@ -111,8 +110,7 @@ void *hostap_init(void) } } #endif /* CONFIG_IEEE80211W */ -//TODO how to set values - if (true) { + if (esp_wifi_wpa3_compatible_mode_enabled(WIFI_IF_AP)) { hapd->conf->rsn_override_key_mgmt = WPA_KEY_MGMT_SAE; hapd->conf->rsn_override_pairwise = WPA_CIPHER_CCMP; hapd->conf->rsn_override_mfp = MGMT_FRAME_PROTECTION_REQUIRED; 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 7541ee8151..52ddae0473 100644 --- a/components/wpa_supplicant/esp_supplicant/src/esp_wifi_driver.h +++ b/components/wpa_supplicant/esp_supplicant/src/esp_wifi_driver.h @@ -302,7 +302,7 @@ bool esp_wifi_ap_notify_node_sae_auth_done(uint8_t *mac); bool esp_wifi_ap_is_sta_sae_reauth_node(uint8_t *mac); uint8_t* esp_wifi_sta_get_sae_identifier_internal(void); bool esp_wifi_eb_tx_status_success_internal(void *eb); -uint8_t* esp_wifi_sta_get_rsnxe(u8 *bssid); +uint8_t* esp_wifi_sta_get_ie(u8 *bssid, uint8_t elem_id); 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); @@ -310,4 +310,6 @@ int esp_wifi_softap_set_obss_overlap(bool overlap); void esp_wifi_set_sigma_internal(bool flag); void esp_wifi_ap_set_group_mgmt_cipher_internal(wifi_cipher_type_t cipher); uint8_t esp_wifi_op_class_supported_internal(uint8_t op_class, uint8_t min_chan, uint8_t max_chan, uint8_t inc, uint8_t bw, channel_bitmap_t *non_pref_channels); +bool esp_wifi_wpa3_compatible_mode_enabled(uint8_t if_index); + #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 8a4782d676..d3436684d1 100644 --- a/components/wpa_supplicant/esp_supplicant/src/esp_wpa3.c +++ b/components/wpa_supplicant/esp_supplicant/src/esp_wpa3.c @@ -37,7 +37,7 @@ static esp_err_t wpa3_build_sae_commit(u8 *bssid, size_t *sae_msg_len) bool valid_pwd_id = false; #ifdef CONFIG_SAE_H2E uint8_t sae_pwe = esp_wifi_get_config_sae_pwe_h2e_internal(WIFI_IF_STA); - const u8 *rsnxe; + const u8 *rsnxe = NULL; uint8_t use_pt = 0; struct wifi_ssid *ssid = esp_wifi_sta_get_prof_ssid_internal(); u8 rsnxe_capa = 0; @@ -46,7 +46,12 @@ static esp_err_t wpa3_build_sae_commit(u8 *bssid, size_t *sae_msg_len) use_pt = 1; } - rsnxe = esp_wifi_sta_get_ie((u8*)bssid, WLAN_EID_RSNX); + if (esp_wifi_wpa3_compatible_mode_enabled(WIFI_IF_STA)) { + rsnxe = esp_wifi_sta_get_ie((u8*)bssid, WFA_RSNXE_OVERRIDE_OUI_TYPE); + } + if (!rsnxe) { + rsnxe = esp_wifi_sta_get_ie((u8*)bssid, WLAN_EID_RSNX); + } if (rsnxe && rsnxe[0] == WLAN_EID_VENDOR_SPECIFIC && rsnxe[1] >= 1 + 4) { rsnxe_capa = rsnxe[2 + 4]; 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 c1df251ea5..827f331df9 100644 --- a/components/wpa_supplicant/esp_supplicant/src/esp_wpa_main.c +++ b/components/wpa_supplicant/esp_supplicant/src/esp_wpa_main.c @@ -113,7 +113,7 @@ int wpa_config_bss(uint8_t *bssid) u8 mac[6]; esp_wifi_get_macaddr_internal(0, mac); - ret = wpa_set_bss((char *)mac, (char *)bssid, esp_wifi_sta_get_pairwise_cipher_internal(), esp_wifi_sta_get_group_cipher_internal(), + ret = wpa_set_bss(mac, bssid, esp_wifi_sta_get_pairwise_cipher_internal(), esp_wifi_sta_get_group_cipher_internal(), (char *)esp_wifi_sta_get_prof_password_internal(), ssid->ssid, ssid->len); return ret; } @@ -391,7 +391,7 @@ static bool hostap_sta_join(void **sta, u8 *bssid, u8 *assoc_req_ie, uint32_t as if (ieee802_11_parse_elems(assoc_req_ie, assoc_ie_len, &elems, 1) == ParseFailed) { wpa_printf(MSG_INFO, "Failed to parse assoc req IEs"); return -1; - } + } if (elems.rsn_ie) { elems.rsn_ie = elems.rsn_ie - 2; diff --git a/components/wpa_supplicant/src/common/ieee802_11_common.c b/components/wpa_supplicant/src/common/ieee802_11_common.c index 1f76a92f8a..3acb14a583 100644 --- a/components/wpa_supplicant/src/common/ieee802_11_common.c +++ b/components/wpa_supplicant/src/common/ieee802_11_common.c @@ -266,7 +266,6 @@ static int ieee802_11_parse_vendor_specific(const u8 *pos, size_t elen, elems->sae_pk_len = elen - 4; break; #endif /* CONFIG_SAE_PK */ -//TODO think of way to ignore these case P2P_OUI_TYPE: /* Wi-Fi Alliance - P2P IE */ break; diff --git a/components/wpa_supplicant/src/rsn_supp/wpa.c b/components/wpa_supplicant/src/rsn_supp/wpa.c index c2e7891983..aa9cf1fb41 100644 --- a/components/wpa_supplicant/src/rsn_supp/wpa.c +++ b/components/wpa_supplicant/src/rsn_supp/wpa.c @@ -2320,16 +2320,17 @@ void wpa_set_pmk(uint8_t *pmk, size_t pmk_length, const u8 *pmkid, bool cache_pm } } -int wpa_set_bss(char *macddr, char * bssid, u8 pairwise_cipher, u8 group_cipher, char *passphrase, u8 *ssid, size_t ssid_len) +int wpa_set_bss(uint8_t *macddr, uint8_t *bssid, u8 pairwise_cipher, u8 group_cipher, char *passphrase, u8 *ssid, size_t ssid_len) { int res = 0; struct wpa_sm *sm = &gWpaSm; bool use_pmk_cache = !esp_wifi_skip_supp_pmkcaching(); - u8 assoc_rsnxe[20]; - size_t assoc_rsnxe_len = sizeof(assoc_rsnxe); + u8 assoc_ie[128]; + uint8_t assoc_ie_len = sizeof(assoc_ie); bool reassoc_same_ess = false; int try_opportunistic = 0; const u8 *ie = NULL; + uint8_t *pos = NULL; /* Incase AP has changed it's SSID, don't try with PMK caching for SAE connection */ /* Ideally we should use network_ctx for this purpose however currently network profile block @@ -2368,11 +2369,11 @@ int wpa_set_bss(char *macddr, char * bssid, u8 pairwise_cipher, u8 group_cipher, } } if (wpa_key_mgmt_supports_caching(sm->key_mgmt) && use_pmk_cache) { - if (reassoc_same_ess && wpa_key_mgmt_wpa_ieee8021x(sm->key_mgmt)) { + if (reassoc_same_ess && wpa_key_mgmt_wpa_ieee8021x(sm->key_mgmt)) { pmksa_cache_set_current(sm, NULL, (const u8*) bssid, (void*)sm->network_ctx, try_opportunistic); - } else { + } else { pmksa_cache_set_current(sm, NULL, (const u8*) bssid, 0, try_opportunistic); - } + } wpa_sm_set_pmk_from_pmksa(sm); } else { if (pmksa) { @@ -2421,7 +2422,7 @@ int wpa_set_bss(char *macddr, char * bssid, u8 pairwise_cipher, u8 group_cipher, #ifdef CONFIG_IEEE80211R if (sm->key_mgmt == WPA_KEY_MGMT_FT_PSK) { const u8 *ie, *md = NULL; - struct wpa_bss *bss = wpa_bss_get_bssid(&g_wpa_supp, (uint8_t *)bssid); + struct wpa_bss *bss = wpa_bss_get_bssid(&g_wpa_supp, bssid); if (!bss) { return -1; } @@ -2448,25 +2449,47 @@ int wpa_set_bss(char *macddr, char * bssid, u8 pairwise_cipher, u8 group_cipher, return -1; sm->assoc_wpa_ie_len = res; - ie = esp_wifi_sta_get_ie((u8*)bssid, WLAN_EID_RSN); + ie = esp_wifi_sta_get_ie(bssid, WLAN_EID_RSN); wpa_sm_set_ap_rsn_ie(sm, ie, ie[1]+2); - ie = esp_wifi_sta_get_ie((u8*)bssid, WLAN_EID_RSNX); + ie = esp_wifi_sta_get_ie(bssid, WLAN_EID_RSNX); wpa_sm_set_ap_rsnxe(sm, ie, ie ? (ie[1] + 2) : 0); - res = wpa_gen_rsnxe(sm, assoc_rsnxe, assoc_rsnxe_len); + pos = assoc_ie; + res = wpa_gen_rsnxe(sm, pos, assoc_ie_len); if (res < 0) return -1; - assoc_rsnxe_len = res; - res = wpa_sm_set_assoc_rsnxe(sm, assoc_rsnxe, assoc_rsnxe_len); - if (res < 0) + + assoc_ie_len = res; + res = wpa_sm_set_assoc_rsnxe(sm, pos, assoc_ie_len); + if (res < 0) { return -1; - esp_set_assoc_ie((uint8_t *)bssid, assoc_rsnxe, assoc_rsnxe_len, true); + } + pos += assoc_ie_len; + + ie = esp_wifi_sta_get_ie(bssid, WLAN_EID_RSN); + + if (esp_wifi_wpa3_compatible_mode_enabled(WIFI_IF_STA) && + ie) { + u32 type = 0; + if (ie && ie[0] == WLAN_EID_VENDOR_SPECIFIC && ie[1] >= 4) + type = WPA_GET_BE32(&ie[2]); + + if (type) { + /* Indicate support for RSN overriding */ + *pos++ = WLAN_EID_VENDOR_SPECIFIC; + *pos++ = 4; + WPA_PUT_BE32(pos, type); + assoc_ie_len += 2 + 4; + } + } + + esp_set_assoc_ie(bssid, assoc_ie, assoc_ie_len, true); os_memset(sm->ssid, 0, sizeof(sm->ssid)); os_memcpy(sm->ssid, ssid, ssid_len); sm->ssid_len = ssid_len; wpa_set_passphrase(passphrase, ssid, ssid_len); #ifdef CONFIG_MBO - if (!mbo_bss_profile_match((u8 *)bssid)) + if (!mbo_bss_profile_match(bssid)) return -1; #endif diff --git a/components/wpa_supplicant/src/rsn_supp/wpa_i.h b/components/wpa_supplicant/src/rsn_supp/wpa_i.h index b31aeb1e1a..e1c63fe539 100644 --- a/components/wpa_supplicant/src/rsn_supp/wpa_i.h +++ b/components/wpa_supplicant/src/rsn_supp/wpa_i.h @@ -204,7 +204,7 @@ void eapol_txcb(uint8_t *eapol_payload, size_t len, bool tx_failure); void wpa_set_profile(u32 wpa_proto, u8 auth_mode); -int wpa_set_bss(char *macddr, char * bssid, u8 pairwise_cipher, u8 group_cipher, char *passphrase, u8 *ssid, size_t ssid_len); +int wpa_set_bss(uint8_t *macddr, uint8_t *bssid, u8 pairwise_cipher, u8 group_cipher, char *passphrase, u8 *ssid, size_t ssid_len); int wpa_sm_rx_eapol(u8 *src_addr, u8 *buf, u32 len); From 5a713f89d754cb855afba568e621c08abaf118b9 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Tue, 23 Jul 2024 21:20:45 +0000 Subject: [PATCH 11/33] RSNO: Allow RSNXE to be omitted Add an explicit rsn_override_omit_rsnxe=1 configuration parameter to allow the RSNXE to be omitted when using the RSNXOE and wanting to minimize interoperability issues with STAs that might recognize the RSNXE, but not handle it correctly, e.g., when multiple octets of payload is included. Signed-off-by: Jouni Malinen --- components/wpa_supplicant/esp_supplicant/src/esp_hostap.c | 1 + components/wpa_supplicant/src/ap/wpa_auth.h | 1 + components/wpa_supplicant/src/ap/wpa_auth_ie.c | 7 +++++++ 3 files changed, 9 insertions(+) diff --git a/components/wpa_supplicant/esp_supplicant/src/esp_hostap.c b/components/wpa_supplicant/esp_supplicant/src/esp_hostap.c index a9de639d77..babacc5c92 100644 --- a/components/wpa_supplicant/esp_supplicant/src/esp_hostap.c +++ b/components/wpa_supplicant/esp_supplicant/src/esp_hostap.c @@ -220,6 +220,7 @@ void *hostap_init(void) #ifdef CONFIG_SAE auth_conf->sae_require_mfp = 1; #endif /* CONFIG_SAE */ + auth_conf->rsn_override_omit_rsnxe = 1; hapd->conf->ap_max_inactivity = 5 * 60; hostapd_setup_wpa_psk(hapd->conf); diff --git a/components/wpa_supplicant/src/ap/wpa_auth.h b/components/wpa_supplicant/src/ap/wpa_auth.h index 9d7c64efc3..432f8aca43 100644 --- a/components/wpa_supplicant/src/ap/wpa_auth.h +++ b/components/wpa_supplicant/src/ap/wpa_auth.h @@ -171,6 +171,7 @@ struct wpa_auth_config { enum sae_pwe sae_pwe; struct rsn_sppamsdu_sup spp_sup; u8 transition_disable; + int rsn_override_omit_rsnxe; }; 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 d5b51dcdb0..005e98cee7 100644 --- a/components/wpa_supplicant/src/ap/wpa_auth_ie.c +++ b/components/wpa_supplicant/src/ap/wpa_auth_ie.c @@ -462,6 +462,13 @@ int wpa_auth_gen_wpa_ie(struct wpa_authenticator *wpa_auth) if (res < 0) return res; pos += res; + + if (wpa_auth->conf.rsn_override_omit_rsnxe) + res = 0; + else + res = wpa_write_rsnxe(&wpa_auth->conf, pos, + buf + sizeof(buf) - pos); + res = wpa_write_rsnxe(&wpa_auth->conf, pos, buf + sizeof(buf) - pos); if (res < 0) From 34336d28b9f0257fda8badcceae79743664bc931 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Tue, 23 Jul 2024 21:36:46 +0000 Subject: [PATCH 12/33] RSNO: Support over two octets of RSNXOE capabilities The RSNXE generation function was extended to support this earlier, but that update was missed from the RSNXOE variant. Signed-off-by: Jouni Malinen --- components/wpa_supplicant/src/ap/wpa_auth_ie.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/components/wpa_supplicant/src/ap/wpa_auth_ie.c b/components/wpa_supplicant/src/ap/wpa_auth_ie.c index 005e98cee7..10646cdf19 100644 --- a/components/wpa_supplicant/src/ap/wpa_auth_ie.c +++ b/components/wpa_supplicant/src/ap/wpa_auth_ie.c @@ -423,7 +423,7 @@ static int wpa_write_rsnxe_override(struct wpa_auth_config *conf, u8 *buf, size_t len) { u8 *pos = buf; - u16 capab; + u32 capab, tmp; size_t flen; capab = rsnxe_capab(conf, conf->rsn_override_key_mgmt); @@ -431,6 +431,12 @@ static int wpa_write_rsnxe_override(struct wpa_auth_config *conf, u8 *buf, flen = (capab & 0xff00) ? 2 : 1; if (!capab) return 0; /* no supported extended RSN capabilities */ + tmp = capab; + flen = 0; + while (tmp) { + flen++; + tmp >>= 8; + } if (len < 2 + flen) return -1; capab |= flen - 1; /* bit 0-3 = Field length (n - 1) */ @@ -440,10 +446,10 @@ static int wpa_write_rsnxe_override(struct wpa_auth_config *conf, u8 *buf, WPA_PUT_BE32(pos, RSNXE_OVERRIDE_IE_VENDOR_TYPE); pos += 4; - *pos++ = capab & 0x00ff; - capab >>= 8; - if (capab) - *pos++ = capab; + while (capab) { + *pos++ = capab & 0xff; + capab >>= 8; + } return pos - buf; } From b347db7af780bfbfedc6d92bbb4bce37402c4489 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Thu, 25 Jul 2024 19:22:00 +0000 Subject: [PATCH 13/33] RSNO: Remove override elements from EAPOL-Key msg 3/4 This was not done in case the STA did not use RSN overriding. Signed-off-by: Jouni Malinen --- components/wpa_supplicant/src/ap/wpa_auth.c | 32 +++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/components/wpa_supplicant/src/ap/wpa_auth.c b/components/wpa_supplicant/src/ap/wpa_auth.c index ff43e4547e..2bac852213 100644 --- a/components/wpa_supplicant/src/ap/wpa_auth.c +++ b/components/wpa_supplicant/src/ap/wpa_auth.c @@ -1845,6 +1845,7 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING) u8 *wpa_ie; int wpa_ie_len, secure, keyidx, encr = 0; u8 *wpa_ie_buf3 = NULL; + struct wpa_auth_config *conf = &sm->wpa_auth->conf; SM_ENTRY_MA(WPA_PTK, PTKINITNEGOTIATING, wpa_ptk); sm->TimeoutEvt = FALSE; @@ -1916,6 +1917,37 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING) wpa_hexdump(MSG_DEBUG, "EAPOL-Key msg 3/4 IEs after edits", wpa_ie, wpa_ie_len); } + if (conf->rsn_override_key_mgmt && !sm->rsn_override) { + u8 *ie; + size_t ie_len; + u32 ids[] = { + RSNE_OVERRIDE_IE_VENDOR_TYPE, + RSNXE_OVERRIDE_IE_VENDOR_TYPE, + 0 + }; + int i; + + wpa_printf(MSG_DEBUG, + "RSN: Remove RSNE/RSNXE override elements"); + wpa_hexdump(MSG_DEBUG, "EAPOL-Key msg 3/4 IEs before edits", + wpa_ie, wpa_ie_len); + wpa_ie_buf3 = os_memdup(wpa_ie, wpa_ie_len); + if (!wpa_ie_buf3) + goto done; + wpa_ie = wpa_ie_buf3; + + for (i = 0; ids[i]; i++) { + ie = (u8 *) get_vendor_ie(wpa_ie, wpa_ie_len, ids[i]); + if (ie) { + ie_len = 2 + ie[1]; + os_memmove(ie, ie + ie_len, + wpa_ie_len - (ie + ie_len - wpa_ie)); + wpa_ie_len -= ie_len; + } + } + wpa_hexdump(MSG_DEBUG, "EAPOL-Key msg 3/4 IEs after edits", + wpa_ie, wpa_ie_len); + } if (sm->wpa == WPA_VERSION_WPA2) { /* WPA2 send GTK in the 4-way handshake */ secure = 1; From c5161c40129dd6ab3fda8795ec2a69cbf26ec5cc Mon Sep 17 00:00:00 2001 From: Adil Saeed Musthafa Date: Thu, 25 Jul 2024 12:51:07 -0700 Subject: [PATCH 14/33] RSNO: Protect wpa_ie_buf3 from reuse explicitly Use else-if check for better clarity regarding usage of wpa_ie_buf3 to make it explicit that memory is allocated for this pointer only once. Signed-off-by: Adil Saeed Musthafa --- components/wpa_supplicant/src/ap/wpa_auth.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/components/wpa_supplicant/src/ap/wpa_auth.c b/components/wpa_supplicant/src/ap/wpa_auth.c index 2bac852213..49a97f1170 100644 --- a/components/wpa_supplicant/src/ap/wpa_auth.c +++ b/components/wpa_supplicant/src/ap/wpa_auth.c @@ -1916,8 +1916,7 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING) wpa_ie_len = pos - wpa_ie_buf3; wpa_hexdump(MSG_DEBUG, "EAPOL-Key msg 3/4 IEs after edits", wpa_ie, wpa_ie_len); - } - if (conf->rsn_override_key_mgmt && !sm->rsn_override) { + } else if (conf->rsn_override_key_mgmt && !sm->rsn_override) { u8 *ie; size_t ie_len; u32 ids[] = { From 8e71c23a0e19eac91d9dd0998b2030da7b9c4861 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Tue, 30 Jul 2024 12:15:02 +0300 Subject: [PATCH 15/33] RSNO: Remove unused override element generation The separate RSNOE/RSNO2E/RSNXOE buffers were not actually used on the Authenticator, so remove them. Signed-off-by: Jouni Malinen --- components/wpa_supplicant/src/ap/wpa_auth.c | 6 ---- components/wpa_supplicant/src/ap/wpa_auth_i.h | 2 -- .../wpa_supplicant/src/ap/wpa_auth_ie.c | 36 ------------------- 3 files changed, 44 deletions(-) diff --git a/components/wpa_supplicant/src/ap/wpa_auth.c b/components/wpa_supplicant/src/ap/wpa_auth.c index 49a97f1170..2fb3cff602 100644 --- a/components/wpa_supplicant/src/ap/wpa_auth.c +++ b/components/wpa_supplicant/src/ap/wpa_auth.c @@ -2671,12 +2671,6 @@ void wpa_deinit(struct wpa_authenticator *wpa_auth) if (wpa_auth->wpa_ie != NULL) { os_free(wpa_auth->wpa_ie); } - if (wpa_auth->rsne_override != NULL) { - os_free(wpa_auth->rsne_override); - } - if (wpa_auth->rsnxe_override != NULL) { - os_free(wpa_auth->rsnxe_override); - } if (wpa_auth->group != NULL) { group = wpa_auth->group; while (group) { diff --git a/components/wpa_supplicant/src/ap/wpa_auth_i.h b/components/wpa_supplicant/src/ap/wpa_auth_i.h index ed0b3cfcb1..3e5c556351 100644 --- a/components/wpa_supplicant/src/ap/wpa_auth_i.h +++ b/components/wpa_supplicant/src/ap/wpa_auth_i.h @@ -186,8 +186,6 @@ struct wpa_authenticator { u8 *wpa_ie; size_t wpa_ie_len; - u8 *rsne_override; /* RSNE with overridden payload */ - u8 *rsnxe_override; /* RSNXE with overridden payload */ struct rsn_pmksa_cache *pmksa; u8 addr[ETH_ALEN]; diff --git a/components/wpa_supplicant/src/ap/wpa_auth_ie.c b/components/wpa_supplicant/src/ap/wpa_auth_ie.c index 10646cdf19..9d7e7ac0a2 100644 --- a/components/wpa_supplicant/src/ap/wpa_auth_ie.c +++ b/components/wpa_supplicant/src/ap/wpa_auth_ie.c @@ -523,42 +523,6 @@ int wpa_auth_gen_wpa_ie(struct wpa_authenticator *wpa_auth) memcpy(wpa_auth->wpa_ie, buf, pos - buf); wpa_auth->wpa_ie_len = pos - buf; - if ((wpa_auth->conf.wpa & WPA_PROTO_RSN) && - wpa_auth->conf.rsn_override_key_mgmt) { - res = wpa_write_rsne_override(&wpa_auth->conf, buf, - sizeof(buf)); - if (res < 0) - return res; - os_free(wpa_auth->rsne_override); - wpa_auth->rsne_override = os_malloc(res - 4); - if (!wpa_auth->rsne_override) - return -1; - pos = wpa_auth->rsne_override; - *pos++ = WLAN_EID_RSN; - *pos++ = res - 2 - 4; - os_memcpy(pos, &buf[2 + 4], res - 2 - 4); - } - - if ((wpa_auth->conf.wpa & WPA_PROTO_RSN) && - (wpa_auth->conf.rsn_override_key_mgmt)) { - res = wpa_write_rsnxe_override(&wpa_auth->conf, buf, - sizeof(buf)); - if (res < 0) - return res; - os_free(wpa_auth->rsnxe_override); - if (res == 0) { - wpa_auth->rsnxe_override = NULL; - return 0; - } - wpa_auth->rsnxe_override = os_malloc(res - 4); - if (!wpa_auth->rsnxe_override) - return -1; - pos = wpa_auth->rsnxe_override; - *pos++ = WLAN_EID_RSNX; - *pos++ = res - 2 - 4; - os_memcpy(pos, &buf[2 + 4], res - 2 - 4); - } - return 0; } From a743612f6c0cba45b6271043daa11cf1ed9728c3 Mon Sep 17 00:00:00 2001 From: Shreyas Sheth Date: Mon, 10 Mar 2025 10:06:20 +0530 Subject: [PATCH 16/33] fix(wifi): Restructure wpa_parse_kde_ies same as upstream --- .../wpa_supplicant/src/ap/wpa_auth_ie.c | 116 --------------- .../wpa_supplicant/src/ap/wpa_auth_ie.h | 26 ---- .../wpa_supplicant/src/common/wpa_common.c | 138 ++++++++++++++++++ .../wpa_supplicant/src/common/wpa_common.h | 34 +++++ components/wpa_supplicant/src/rsn_supp/wpa.c | 25 +++- components/wpa_supplicant/src/rsn_supp/wpa.h | 3 + .../wpa_supplicant/src/rsn_supp/wpa_ie.c | 130 ----------------- .../wpa_supplicant/src/rsn_supp/wpa_ie.h | 30 ---- 8 files changed, 199 insertions(+), 303 deletions(-) diff --git a/components/wpa_supplicant/src/ap/wpa_auth_ie.c b/components/wpa_supplicant/src/ap/wpa_auth_ie.c index 9d7e7ac0a2..e82c18264b 100644 --- a/components/wpa_supplicant/src/ap/wpa_auth_ie.c +++ b/components/wpa_supplicant/src/ap/wpa_auth_ie.c @@ -829,122 +829,6 @@ wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth, return WPA_IE_OK; } -/** - * wpa_parse_generic - Parse EAPOL-Key Key Data Generic IEs - * @pos: Pointer to the IE header - * @end: Pointer to the end of the Key Data buffer - * @ie: Pointer to parsed IE data - * Returns: 0 on success, 1 if end mark is found, -1 on failure - */ -static int wpa_parse_generic(const u8 *pos, const u8 *end, - struct wpa_eapol_ie_parse *ie) -{ - if (pos[1] == 0) - return 1; - - if (pos[1] >= 6 && - RSN_SELECTOR_GET(pos + 2) == WPA_OUI_TYPE && - pos[2 + WPA_SELECTOR_LEN] == 1 && - pos[2 + WPA_SELECTOR_LEN + 1] == 0) { - ie->wpa_ie = pos; - ie->wpa_ie_len = pos[1] + 2; - return 0; - } - - if (pos + 1 + RSN_SELECTOR_LEN < end && - pos[1] >= RSN_SELECTOR_LEN + PMKID_LEN && - RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_PMKID) { - ie->pmkid = pos + 2 + RSN_SELECTOR_LEN; - return 0; - } - - if (pos[1] > RSN_SELECTOR_LEN + 2 && - RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_GROUPKEY) { - ie->gtk = pos + 2 + RSN_SELECTOR_LEN; - ie->gtk_len = pos[1] - RSN_SELECTOR_LEN; - return 0; - } - - if (pos[1] > RSN_SELECTOR_LEN + 2 && - RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_MAC_ADDR) { - ie->mac_addr = pos + 2 + RSN_SELECTOR_LEN; - ie->mac_addr_len = pos[1] - RSN_SELECTOR_LEN; - return 0; - } - -#ifdef CONFIG_IEEE80211W - if (pos[1] > RSN_SELECTOR_LEN + 2 && - RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_IGTK) { - ie->igtk = pos + 2 + RSN_SELECTOR_LEN; - ie->igtk_len = pos[1] - RSN_SELECTOR_LEN; - return 0; - } -#endif /* CONFIG_IEEE80211W */ - - return 0; -} - - -/** - * wpa_parse_kde_ies - Parse EAPOL-Key Key Data IEs - * @buf: Pointer to the Key Data buffer - * @len: Key Data Length - * @ie: Pointer to parsed IE data - * Returns: 0 on success, -1 on failure - */ -int wpa_parse_kde_ies(const u8 *buf, size_t len, struct wpa_eapol_ie_parse *ie) -{ - const u8 *pos, *end; - int ret = 0; - - memset(ie, 0, sizeof(*ie)); - for (pos = buf, end = pos + len; pos + 1 < end; pos += 2 + pos[1]) { - if (pos[0] == 0xdd && - ((pos == buf + len - 1) || pos[1] == 0)) { - /* Ignore padding */ - break; - } - if (pos + 2 + pos[1] > end) { - wpa_printf( MSG_DEBUG, "WPA: EAPOL-Key Key Data " - "underflow (ie=%d len=%d pos=%d)", - pos[0], pos[1], (int) (pos - buf)); - wpa_hexdump_key(MSG_DEBUG, "WPA: Key Data", - buf, len); - ret = -1; - break; - } - if (*pos == WLAN_EID_RSN) { - ie->rsn_ie = pos; - ie->rsn_ie_len = pos[1] + 2; -#ifdef CONFIG_IEEE80211R_AP - } else if (*pos == WLAN_EID_MOBILITY_DOMAIN) { - ie->mdie = pos; - ie->mdie_len = pos[1] + 2; - } else if (*pos == WLAN_EID_FAST_BSS_TRANSITION) { - ie->ftie = pos; - ie->ftie_len = pos[1] + 2; -#endif /* CONFIG_IEEE80211R_AP */ - } else if (*pos == WLAN_EID_RSNX) { - ie->rsnxe = pos; - ie->rsnxe_len = pos[1] + 2; - wpa_hexdump(MSG_DEBUG, "WPA: RSNXE in EAPOL-Key", - ie->rsnxe, ie->rsnxe_len); - } else if (*pos == WLAN_EID_VENDOR_SPECIFIC) { - ret = wpa_parse_generic(pos, end, ie); - if (ret < 0) - break; - if (ret > 0) { - ret = 0; - break; - } - } else { - wpa_hexdump(MSG_DEBUG, "WPA: Unrecognized EAPOL-Key " - "Key Data IE", pos, 2 + pos[1]); - } - } - - return ret; -} int wpa_auth_uses_mfp(struct wpa_state_machine *sm) diff --git a/components/wpa_supplicant/src/ap/wpa_auth_ie.h b/components/wpa_supplicant/src/ap/wpa_auth_ie.h index f342e3dda9..dd44b9efe2 100644 --- a/components/wpa_supplicant/src/ap/wpa_auth_ie.h +++ b/components/wpa_supplicant/src/ap/wpa_auth_ie.h @@ -9,32 +9,6 @@ #ifndef WPA_AUTH_IE_H #define WPA_AUTH_IE_H -struct wpa_eapol_ie_parse { - const u8 *wpa_ie; - size_t wpa_ie_len; - const u8 *rsn_ie; - size_t rsn_ie_len; - const u8 *pmkid; - const u8 *gtk; - size_t gtk_len; - const u8 *mac_addr; - size_t mac_addr_len; -#ifdef CONFIG_IEEE80211W - const u8 *igtk; - size_t igtk_len; -#endif /* CONFIG_IEEE80211W */ -#ifdef CONFIG_IEEE80211R - const u8 *mdie; - size_t mdie_len; - const u8 *ftie; - size_t ftie_len; -#endif /* CONFIG_IEEE80211R */ - const u8 *rsnxe; - size_t rsnxe_len; -}; - -int wpa_parse_kde_ies(const u8 *buf, size_t len, - struct wpa_eapol_ie_parse *ie); u8 * wpa_add_kde(u8 *pos, u32 kde, const u8 *data, size_t data_len, const u8 *data2, size_t data2_len); int wpa_auth_gen_wpa_ie(struct wpa_authenticator *wpa_auth); diff --git a/components/wpa_supplicant/src/common/wpa_common.c b/components/wpa_supplicant/src/common/wpa_common.c index 6f9485760b..34b95f30cf 100644 --- a/components/wpa_supplicant/src/common/wpa_common.c +++ b/components/wpa_supplicant/src/common/wpa_common.c @@ -1580,4 +1580,142 @@ int wpa_cipher_put_suites(u8 *pos, int ciphers) return num_suites; } +/** + * wpa_parse_generic - Parse EAPOL-Key Key Data Generic IEs + * @pos: Pointer to the IE header + * @end: Pointer to the end of the Key Data buffer + * @ie: Pointer to parsed IE data + * Returns: 0 on success, 1 if end mark is found, -1 on failure + */ +static int wpa_parse_generic(const u8 *pos, const u8 *end, + struct wpa_eapol_ie_parse *ie) +{ + u8 len = pos[1]; + size_t dlen = 2 + len; + u32 selector; + const u8 *p; + size_t left; + + if (len == 0) + return 1; + + if (len < RSN_SELECTOR_LEN) + return 2; + + p = pos + 2; + selector = RSN_SELECTOR_GET(p); + p += RSN_SELECTOR_LEN; + left = len - RSN_SELECTOR_LEN; + + if (left >= 2 && selector == WPA_OUI_TYPE && p[0] == 1 && p[1] == 0) { + ie->wpa_ie = pos; + ie->wpa_ie_len = dlen; + wpa_hexdump(MSG_DEBUG, "WPA: WPA IE in EAPOL-Key", + ie->wpa_ie, ie->wpa_ie_len); + return 0; + } + + if (left >= PMKID_LEN && selector == RSN_KEY_DATA_PMKID) { + ie->pmkid = p; + wpa_hexdump(MSG_DEBUG, "WPA: PMKID in EAPOL-Key", pos, dlen); + return 0; + } + + if (left > 2 && selector == RSN_KEY_DATA_GROUPKEY) { + ie->gtk = p; + ie->gtk_len = left; + wpa_hexdump_key(MSG_DEBUG, "WPA: GTK in EAPOL-Key", pos, dlen); + return 0; + } + + if (left >= ETH_ALEN && selector == RSN_KEY_DATA_MAC_ADDR) { + ie->mac_addr = p; + wpa_printf(MSG_DEBUG, "WPA: MAC Address in EAPOL-Key: " MACSTR, + MAC2STR(ie->mac_addr)); + return 0; + } + +#ifdef CONFIG_IEEE80211W + if (left > 2 && selector == RSN_KEY_DATA_IGTK) { + ie->igtk = p; + ie->igtk_len = left; + wpa_hexdump_key(MSG_DEBUG, "WPA: IGTK in EAPOL-Key", + pos, dlen); + return 0; + } +#endif /* CONFIG_IEEE80211W */ + + if (left >= 1 && selector == WFA_KEY_DATA_TRANSITION_DISABLE) { + ie->transition_disable = p; + ie->transition_disable_len = left; + wpa_hexdump(MSG_DEBUG, + "WPA: Transition Disable KDE in EAPOL-Key", + pos, dlen); + return 0; + } + + return 2; +} + +/** + * wpa_parse_kde_ies - Parse EAPOL-Key Key Data IEs + * @buf: Pointer to the Key Data buffer + * @len: Key Data Length + * @ie: Pointer to parsed IE data + * Returns: 0 on success, -1 on failure + */ +int wpa_parse_kde_ies(const u8 *buf, size_t len, struct wpa_eapol_ie_parse *ie) +{ + const u8 *pos, *end; + int ret = 0; + + memset(ie, 0, sizeof(*ie)); + for (pos = buf, end = pos + len; pos + 1 < end; pos += 2 + pos[1]) { + if (pos[0] == 0xdd && + ((pos == buf + len - 1) || pos[1] == 0)) { + /* Ignore padding */ + break; + } + if (pos + 2 + pos[1] > end) { + wpa_printf( MSG_DEBUG, "WPA: EAPOL-Key Key Data " + "underflow (ie=%d len=%d pos=%d)", + pos[0], pos[1], (int) (pos - buf)); + wpa_hexdump_key(MSG_DEBUG, "WPA: Key Data", + buf, len); + ret = -1; + break; + } + if (*pos == WLAN_EID_RSN) { + ie->rsn_ie = pos; + ie->rsn_ie_len = pos[1] + 2; +#ifdef CONFIG_IEEE80211R_AP + } else if (*pos == WLAN_EID_MOBILITY_DOMAIN) { + ie->mdie = pos; + ie->mdie_len = pos[1] + 2; + } else if (*pos == WLAN_EID_FAST_BSS_TRANSITION) { + ie->ftie = pos; + ie->ftie_len = pos[1] + 2; +#endif /* CONFIG_IEEE80211R_AP */ + } else if (*pos == WLAN_EID_RSNX) { + ie->rsnxe = pos; + ie->rsnxe_len = pos[1] + 2; + wpa_hexdump(MSG_DEBUG, "WPA: RSNXE in EAPOL-Key", + ie->rsnxe, ie->rsnxe_len); + } else if (*pos == WLAN_EID_VENDOR_SPECIFIC) { + ret = wpa_parse_generic(pos, end, ie); + if (ret < 0) + break; + if (ret > 0) { + ret = 0; + break; + } + } else { + wpa_hexdump(MSG_DEBUG, "WPA: Unrecognized EAPOL-Key " + "Key Data IE", pos, 2 + pos[1]); + } + } + + return ret; +} + #endif // ESP_SUPPLICANT diff --git a/components/wpa_supplicant/src/common/wpa_common.h b/components/wpa_supplicant/src/common/wpa_common.h index d4d164db0c..ce2e4d602b 100644 --- a/components/wpa_supplicant/src/common/wpa_common.h +++ b/components/wpa_supplicant/src/common/wpa_common.h @@ -439,6 +439,40 @@ int wpa_pmk_to_ptk(const u8 *pmk, size_t pmk_len, const char *label, void rsn_pmkid(const u8 *pmk, size_t pmk_len, const u8 *aa, const u8 *spa, u8 *pmkid, int akmp); +struct wpa_eapol_ie_parse { + const u8 *wpa_ie; + size_t wpa_ie_len; + const u8 *rsn_ie; + size_t rsn_ie_len; + const u8 *pmkid; + const u8 *gtk; + size_t gtk_len; + const u8 *mac_addr; + size_t mac_addr_len; +#ifdef CONFIG_IEEE80211W + const u8 *igtk; + size_t igtk_len; +#endif /* CONFIG_IEEE80211W */ +#ifdef CONFIG_IEEE80211R + const u8 *mdie; + size_t mdie_len; + const u8 *ftie; + size_t ftie_len; + const u8 *reassoc_deadline; + const u8 *key_lifetime; +#endif /* CONFIG_IEEE80211R */ + const u8 *transition_disable; + size_t transition_disable_len; + const u8 *rsnxe; + size_t rsnxe_len; +}; +int wpa_parse_kde_ies(const u8 *buf, size_t len, struct wpa_eapol_ie_parse *ie); +static inline int wpa_supplicant_parse_ies(const u8 *buf, size_t len, + struct wpa_eapol_ie_parse *ie) +{ + return wpa_parse_kde_ies(buf, len, ie); +} + int wpa_cipher_key_len(int cipher); int wpa_cipher_rsc_len(int cipher); int wpa_cipher_to_alg(int cipher); diff --git a/components/wpa_supplicant/src/rsn_supp/wpa.c b/components/wpa_supplicant/src/rsn_supp/wpa.c index aa9cf1fb41..674be39c88 100644 --- a/components/wpa_supplicant/src/rsn_supp/wpa.c +++ b/components/wpa_supplicant/src/rsn_supp/wpa.c @@ -2180,14 +2180,37 @@ void wpa_sm_deinit(void) struct wpa_sm *sm = &gWpaSm; pmksa_cache_deinit(sm->pmksa); sm->pmksa = NULL; + os_free(sm->assoc_rsnxe); + sm->assoc_rsnxe = NULL; + os_free(sm->ap_rsn_ie); + sm->ap_rsn_ie = NULL; os_free(sm->ap_rsnxe); sm->ap_rsnxe = NULL; - os_free(sm->assoc_rsnxe); wpa_sm_drop_sa(sm); sm->assoc_rsnxe = NULL; memset(sm, 0, sizeof(*sm)); } +/** + * wpa_sm_set_param - Set WPA state machine parameters + * @sm: Pointer to WPA state machine data from wpa_sm_init() + * @param: Parameter field + * @value: Parameter value + * Returns: 0 on success, -1 on failure + */ +int wpa_sm_set_param(struct wpa_sm *sm, enum wpa_sm_conf_params param, + unsigned int value) +{ + int ret = 0; + + if (sm == NULL) + return -1; + switch (param) { + default: + break; + } + return ret; +} #ifdef ESP_SUPPLICANT /** diff --git a/components/wpa_supplicant/src/rsn_supp/wpa.h b/components/wpa_supplicant/src/rsn_supp/wpa.h index ab6653ea36..75f4bb6694 100644 --- a/components/wpa_supplicant/src/rsn_supp/wpa.h +++ b/components/wpa_supplicant/src/rsn_supp/wpa.h @@ -35,6 +35,9 @@ struct l2_ethhdr { be16 h_proto; } STRUCT_PACKED; +enum wpa_sm_conf_params { + WPA_PARAM_RSN_OVERRIDE, +}; void wpa_sm_set_state(enum wpa_states state); diff --git a/components/wpa_supplicant/src/rsn_supp/wpa_ie.c b/components/wpa_supplicant/src/rsn_supp/wpa_ie.c index cf4566bd50..f1e056cf81 100644 --- a/components/wpa_supplicant/src/rsn_supp/wpa_ie.c +++ b/components/wpa_supplicant/src/rsn_supp/wpa_ie.c @@ -337,134 +337,4 @@ int wpa_gen_rsnxe(struct wpa_sm *sm, u8 *rsnxe, size_t rsnxe_len) return pos - rsnxe; } -/** - * wpa_parse_generic - Parse EAPOL-Key Key Data Generic IEs - * @pos: Pointer to the IE header - * @end: Pointer to the end of the Key Data buffer - * @ie: Pointer to parsed IE data - * Returns: 0 on success, 1 if end mark is found, -1 on failure - */ -static int wpa_parse_generic(const u8 *pos, const u8 *end, - struct wpa_eapol_ie_parse *ie) -{ - if (pos[1] == 0) - return 1; - - if (pos[1] >= 6 && - RSN_SELECTOR_GET(pos + 2) == WPA_OUI_TYPE && - pos[2 + WPA_SELECTOR_LEN] == 1 && - pos[2 + WPA_SELECTOR_LEN + 1] == 0) { - ie->wpa_ie = pos; - ie->wpa_ie_len = pos[1] + 2; - wpa_hexdump(MSG_DEBUG, "WPA: WPA IE in EAPOL-Key", - ie->wpa_ie, ie->wpa_ie_len); - return 0; - } - - if (pos + 1 + RSN_SELECTOR_LEN < end && - pos[1] >= RSN_SELECTOR_LEN + PMKID_LEN && - RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_PMKID) { - ie->pmkid = pos + 2 + RSN_SELECTOR_LEN; - wpa_hexdump(MSG_DEBUG, "WPA: PMKID in EAPOL-Key", - pos, pos[1] + 2); - return 0; - } - - if (pos[1] > RSN_SELECTOR_LEN + 2 && - RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_GROUPKEY) { - ie->gtk = pos + 2 + RSN_SELECTOR_LEN; - ie->gtk_len = pos[1] - RSN_SELECTOR_LEN; - wpa_hexdump(MSG_DEBUG, "WPA: GTK in EAPOL-Key", - pos, pos[1] + 2); - return 0; - } - - if (pos[1] > RSN_SELECTOR_LEN + 2 && - RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_MAC_ADDR) { - ie->mac_addr = pos + 2 + RSN_SELECTOR_LEN; - ie->mac_addr_len = pos[1] - RSN_SELECTOR_LEN; - wpa_hexdump(MSG_DEBUG, "WPA: MAC Address in EAPOL-Key", - pos, pos[1] + 2); - return 0; - } -#ifdef CONFIG_IEEE80211W - if (pos[1] > RSN_SELECTOR_LEN + 2 && - RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_IGTK) { - ie->igtk = pos + 2 + RSN_SELECTOR_LEN; - ie->igtk_len = pos[1] - RSN_SELECTOR_LEN; - wpa_hexdump(MSG_DEBUG, "WPA: IGTK in EAPOL-Key", - pos, pos[1] + 2); - return 0; - } -#endif - if (pos[1] >= RSN_SELECTOR_LEN + 1 && - RSN_SELECTOR_GET(pos + 2) == WFA_KEY_DATA_TRANSITION_DISABLE) { - ie->transition_disable = pos + 2 + RSN_SELECTOR_LEN; - ie->transition_disable_len = pos[1] - RSN_SELECTOR_LEN; - wpa_hexdump(MSG_DEBUG, - "WPA: Transition Disable KDE in EAPOL-Key", - pos, pos[1] + 2); - return 0; - } - return 0; -} - - -/** - * wpa_supplicant_parse_ies - Parse EAPOL-Key Key Data IEs - * @buf: Pointer to the Key Data buffer - * @len: Key Data Length - * @ie: Pointer to parsed IE data - * Returns: 0 on success, -1 on failure - */ -int wpa_supplicant_parse_ies(const u8 *buf, size_t len, - struct wpa_eapol_ie_parse *ie) -{ - const u8 *pos, *end; - int ret = 0; - - memset(ie, 0, sizeof(*ie)); - for (pos = buf, end = pos + len; pos + 1 < end; pos += 2 + pos[1]) { - if (pos[0] == 0xdd && - ((pos == buf + len - 1) || pos[1] == 0)) { - /* Ignore padding */ - break; - } - if (pos + 2 + pos[1] > end) { - wpa_printf(MSG_DEBUG, "WPA: EAPOL-Key Key Data " - "underflow (ie=%d len=%d pos=%d)", - pos[0], pos[1], (int) (pos - buf)); - wpa_hexdump(MSG_DEBUG, "WPA: Key Data", - buf, len); - ret = -1; - break; - } - if (*pos == WLAN_EID_RSN) { - ie->rsn_ie = pos; - ie->rsn_ie_len = pos[1] + 2; - wpa_hexdump(MSG_DEBUG, "WPA: RSN IE in EAPOL-Key", - ie->rsn_ie, ie->rsn_ie_len); - } else if (*pos == WLAN_EID_RSNX) { - ie->rsnxe = pos; - ie->rsnxe_len = pos[1] + 2; - wpa_hexdump(MSG_DEBUG, "WPA: RSNXE in EAPOL-Key", - ie->rsnxe, ie->rsnxe_len); - } else if (*pos == WLAN_EID_VENDOR_SPECIFIC) { - ret = wpa_parse_generic(pos, end, ie); - if (ret < 0) - break; - if (ret > 0) { - ret = 0; - break; - } - } else { - wpa_hexdump(MSG_DEBUG, "WPA: Unrecognized EAPOL-Key " - "Key Data IE", pos, 2 + pos[1]); - } - } - - return ret; -} - - #endif // ESP_SUPPLICANT diff --git a/components/wpa_supplicant/src/rsn_supp/wpa_ie.h b/components/wpa_supplicant/src/rsn_supp/wpa_ie.h index b799064635..17089b9988 100644 --- a/components/wpa_supplicant/src/rsn_supp/wpa_ie.h +++ b/components/wpa_supplicant/src/rsn_supp/wpa_ie.h @@ -15,36 +15,6 @@ #ifndef WPA_IE_H #define WPA_IE_H -struct wpa_eapol_ie_parse { - const u8 *wpa_ie; - size_t wpa_ie_len; - const u8 *rsn_ie; - size_t rsn_ie_len; - const u8 *pmkid; - const u8 *gtk; - size_t gtk_len; - const u8 *mac_addr; - size_t mac_addr_len; -#ifdef CONFIG_IEEE80211W - const u8 *igtk; - size_t igtk_len; -#endif /* CONFIG_IEEE80211W */ -#ifdef CONFIG_IEEE80211R - const u8 *mdie; - size_t mdie_len; - const u8 *ftie; - size_t ftie_len; - const u8 *reassoc_deadline; - const u8 *key_lifetime; -#endif /* CONFIG_IEEE80211R */ - const u8 *transition_disable; - size_t transition_disable_len; - const u8 *rsnxe; - size_t rsnxe_len; -}; - -int wpa_supplicant_parse_ies(const u8 *buf, size_t len, - struct wpa_eapol_ie_parse *ie); 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, From 7ec6fbd49a9a51c99cf357701a050857dab5e04e Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 29 Jul 2024 15:41:59 +0300 Subject: [PATCH 17/33] RSNO: Use the RSN Selection element to indicate which variant was used This replaces the use of the RSNE Override and RSNE Override 2 elements with empty payload to indicate which RSNE variant was used. In addition, this adds stricter validation of the RSNE in (Re)Association Request frame to allow only the pairwise cipher suites and AKMs listed in the indicated RSNE variant to be used. Signed-off-by: Jouni Malinen --- .../esp_supplicant/src/esp_hostap.c | 2 +- components/wpa_supplicant/src/ap/wpa_auth.c | 41 ++++++++- components/wpa_supplicant/src/ap/wpa_auth.h | 3 +- components/wpa_supplicant/src/ap/wpa_auth_i.h | 2 + .../wpa_supplicant/src/ap/wpa_auth_ie.c | 23 +++-- .../src/common/ieee802_11_common.c | 9 ++ .../src/common/ieee802_11_common.h | 4 +- .../src/common/ieee802_11_defs.h | 2 + .../wpa_supplicant/src/common/wpa_common.c | 6 +- .../wpa_supplicant/src/common/wpa_common.h | 9 ++ components/wpa_supplicant/src/rsn_supp/wpa.c | 87 ++++++++++++++----- components/wpa_supplicant/src/rsn_supp/wpa.h | 2 + .../wpa_supplicant/src/rsn_supp/wpa_i.h | 8 ++ 13 files changed, 162 insertions(+), 36 deletions(-) diff --git a/components/wpa_supplicant/esp_supplicant/src/esp_hostap.c b/components/wpa_supplicant/esp_supplicant/src/esp_hostap.c index babacc5c92..b22c02944f 100644 --- a/components/wpa_supplicant/esp_supplicant/src/esp_hostap.c +++ b/components/wpa_supplicant/esp_supplicant/src/esp_hostap.c @@ -430,7 +430,7 @@ bool hostap_new_assoc_sta(struct sta_info *sta, uint8_t *bssid, struct ieee802_1 goto send_resp; } - wpa_auth_set_rsn_override(sta->wpa_sm, elems.rsne_override != NULL); + wpa_auth_set_rsn_selection(sta->wpa_sm, elems.rsn_selection, elems.rsn_selection_len); res = wpa_validate_wpa_ie(hapd->wpa_auth, sta->wpa_sm, elems.rsn_ie, elems.rsn_ie_len, elems.rsnxe, elems.rsnxe_len); #ifdef CONFIG_SAE if (wpa_auth_uses_sae(sta->wpa_sm) && sta->sae && diff --git a/components/wpa_supplicant/src/ap/wpa_auth.c b/components/wpa_supplicant/src/ap/wpa_auth.c index 2fb3cff602..e00fe390e0 100644 --- a/components/wpa_supplicant/src/ap/wpa_auth.c +++ b/components/wpa_supplicant/src/ap/wpa_auth.c @@ -197,10 +197,24 @@ static inline int wpa_auth_get_seqnum(struct wpa_authenticator *wpa_auth, return -1; } -void wpa_auth_set_rsn_override(struct wpa_state_machine *sm, bool val) +void wpa_auth_set_rsn_selection(struct wpa_state_machine *sm, const u8 *ie, + size_t len) { - if (sm) - sm->rsn_override = val; + if (!sm) + return; + os_free(sm->rsn_selection); + sm->rsn_selection = NULL; + sm->rsn_selection_len = 0; + sm->rsn_override = false; + if (ie) { + if (len >= 1) { + if (ie[0] == RSN_SELECTION_RSNE_OVERRIDE) + sm->rsn_override = true; + } + sm->rsn_selection = os_memdup(ie, len); + if (sm->rsn_selection) + sm->rsn_selection_len = len; + } } /* fix buf for tx for now */ @@ -508,6 +522,7 @@ static void wpa_free_sta_sm(struct wpa_state_machine *sm) os_free(sm->last_rx_eapol_key); os_free(sm->wpa_ie); os_free(sm->rsnxe); + os_free(sm->rsn_selection); os_free(sm); } @@ -1748,6 +1763,26 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING) return; } + /* Verify RSN Selection element for RSN overriding */ + if ((sm->rsn_selection && !kde.rsn_selection) || + (!sm->rsn_selection && kde.rsn_selection) || + (sm->rsn_selection && kde.rsn_selection && + (sm->rsn_selection_len != kde.rsn_selection_len || + os_memcmp(sm->rsn_selection, kde.rsn_selection, + sm->rsn_selection_len) != 0))) { + wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm), LOGGER_INFO, + "RSN Selection element from (Re)AssocReq did not match the one in EAPOL-Key msg 2/4"); + wpa_hexdump(MSG_DEBUG, "RSN Selection in AssocReq", + sm->rsn_selection, sm->rsn_selection_len); + wpa_hexdump(MSG_DEBUG, "RSN Selection in EAPOL-Key msg 2/4", + kde.rsn_selection, kde.rsn_selection_len); + /* MLME-DEAUTHENTICATE.request */ + wpa_sta_disconnect(sm->wpa_auth, sm->addr, + WLAN_REASON_PREV_AUTH_NOT_VALID); + return; + + } + sm->pending_1_of_4_timeout = 0; eloop_cancel_timeout(resend_eapol_handle, (void*)(sm->index), NULL); diff --git a/components/wpa_supplicant/src/ap/wpa_auth.h b/components/wpa_supplicant/src/ap/wpa_auth.h index 432f8aca43..7a27fd3675 100644 --- a/components/wpa_supplicant/src/ap/wpa_auth.h +++ b/components/wpa_supplicant/src/ap/wpa_auth.h @@ -308,6 +308,7 @@ int wpa_auth_pmksa_add_sae(struct wpa_authenticator *wpa_auth, const u8 *addr, void wpa_auth_add_sae_pmkid(struct wpa_state_machine *sm, const u8 *pmkid); void wpa_auth_pmksa_remove(struct wpa_authenticator *wpa_auth, const u8 *sta_addr); -void wpa_auth_set_rsn_override(struct wpa_state_machine *sm, bool val); +void wpa_auth_set_rsn_selection(struct wpa_state_machine *sm, const u8 *ie, + size_t len); #endif /* WPA_AUTH_H */ diff --git a/components/wpa_supplicant/src/ap/wpa_auth_i.h b/components/wpa_supplicant/src/ap/wpa_auth_i.h index 3e5c556351..745c32d431 100644 --- a/components/wpa_supplicant/src/ap/wpa_auth_i.h +++ b/components/wpa_supplicant/src/ap/wpa_auth_i.h @@ -100,6 +100,8 @@ struct wpa_state_machine { size_t wpa_ie_len; u8 *rsnxe; size_t rsnxe_len; + u8 *rsn_selection; + size_t rsn_selection_len; enum { WPA_VERSION_NO_WPA = 0 /* WPA not used */, diff --git a/components/wpa_supplicant/src/ap/wpa_auth_ie.c b/components/wpa_supplicant/src/ap/wpa_auth_ie.c index e82c18264b..9e85b801ad 100644 --- a/components/wpa_supplicant/src/ap/wpa_auth_ie.c +++ b/components/wpa_supplicant/src/ap/wpa_auth_ie.c @@ -651,8 +651,16 @@ wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth, return WPA_INVALID_GROUP; } - key_mgmt = data.key_mgmt & (wpa_auth->conf.wpa_key_mgmt | - wpa_auth->conf.rsn_override_key_mgmt); + if (sm->rsn_override) + key_mgmt = data.key_mgmt & wpa_auth->conf.rsn_override_key_mgmt; + else + key_mgmt = data.key_mgmt & wpa_auth->conf.wpa_key_mgmt; + if (!key_mgmt) { + wpa_printf(MSG_DEBUG, "Invalid WPA key mgmt (0x%x) from " + MACSTR, data.key_mgmt, MAC2STR(sm->addr)); + return WPA_INVALID_AKMP; + } + if (!key_mgmt) { wpa_printf( MSG_DEBUG, "Invalid WPA key mgmt (0x%x) from " MACSTR, data.key_mgmt, MAC2STR(sm->addr)); @@ -685,14 +693,15 @@ wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth, else sm->wpa_key_mgmt = WPA_KEY_MGMT_PSK; - if (version == WPA_PROTO_RSN) + if (version == WPA_PROTO_RSN && sm->rsn_override) ciphers = data.pairwise_cipher & - (wpa_auth->conf.rsn_pairwise | - wpa_auth->conf.rsn_override_pairwise); + wpa_auth->conf.rsn_override_pairwise; + else if (version == WPA_PROTO_RSN) + ciphers = data.pairwise_cipher & wpa_auth->conf.rsn_pairwise; else ciphers = data.pairwise_cipher & wpa_auth->conf.wpa_pairwise; if (!ciphers) { - wpa_printf( MSG_DEBUG, "Invalid %s pairwise cipher (0x%x) " + wpa_printf(MSG_DEBUG, "Invalid %s pairwise cipher (0x%x) " "from " MACSTR, version == WPA_PROTO_RSN ? "RSN" : "WPA", data.pairwise_cipher, MAC2STR(sm->addr)); @@ -829,8 +838,6 @@ wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth, return WPA_IE_OK; } - - int wpa_auth_uses_mfp(struct wpa_state_machine *sm) { return sm ? 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 3acb14a583..cc3e8ff1af 100644 --- a/components/wpa_supplicant/src/common/ieee802_11_common.c +++ b/components/wpa_supplicant/src/common/ieee802_11_common.c @@ -296,6 +296,15 @@ static int ieee802_11_parse_vendor_specific(const u8 *pos, size_t elen, elems->rsne_override = pos; elems->rsne_override_len = elen; break; + case WFA_RSN_SELECTION_OUI_TYPE: + if (elen < 4 + 1) { + wpa_printf(MSG_DEBUG, + "Too short RSN Selection element ignored"); + return -1; + } + elems->rsn_selection = pos + 4; + elems->rsn_selection_len = elen - 4; + break; default: wpa_printf(MSG_EXCESSIVE, "Unknown WFA " "information element ignored " diff --git a/components/wpa_supplicant/src/common/ieee802_11_common.h b/components/wpa_supplicant/src/common/ieee802_11_common.h index 9a63a7b201..50ff9223ad 100644 --- a/components/wpa_supplicant/src/common/ieee802_11_common.h +++ b/components/wpa_supplicant/src/common/ieee802_11_common.h @@ -72,7 +72,9 @@ struct ieee802_11_elems { #endif #ifdef CONFIG_WPA3_SAE const u8 *rsne_override; - u8 rsne_override_len; + size_t rsne_override_len; + const u8 *rsn_selection; + size_t rsn_selection_len; #endif }; diff --git a/components/wpa_supplicant/src/common/ieee802_11_defs.h b/components/wpa_supplicant/src/common/ieee802_11_defs.h index 7b34269df6..019a929fbf 100644 --- a/components/wpa_supplicant/src/common/ieee802_11_defs.h +++ b/components/wpa_supplicant/src/common/ieee802_11_defs.h @@ -305,9 +305,11 @@ #define WFA_RSNE_OVERRIDE_OUI_TYPE 0x29 #define WFA_RSNE_OVERRIDE_2_OUI_TYPE 0x2a #define WFA_RSNXE_OVERRIDE_OUI_TYPE 0x2b +#define WFA_RSN_SELECTION_OUI_TYPE 0x2c #define RSNE_OVERRIDE_IE_VENDOR_TYPE 0x506f9a29 #define RSNE_OVERRIDE_2_IE_VENDOR_TYPE 0x506f9a2a #define RSNXE_OVERRIDE_IE_VENDOR_TYPE 0x506f9a2b +#define RSN_SELECTION_IE_VENDOR_TYPE 0x506f9a2c #define WFD_OUI_TYPE 10 #define NAN_OUI_TYPE 0x13 diff --git a/components/wpa_supplicant/src/common/wpa_common.c b/components/wpa_supplicant/src/common/wpa_common.c index 34b95f30cf..388cad31c4 100644 --- a/components/wpa_supplicant/src/common/wpa_common.c +++ b/components/wpa_supplicant/src/common/wpa_common.c @@ -1653,7 +1653,11 @@ static int wpa_parse_generic(const u8 *pos, const u8 *end, pos, dlen); return 0; } - + if (selector == RSN_SELECTION_IE_VENDOR_TYPE) { + ie->rsn_selection = p; + ie->rsn_selection_len = left; + return 0; + } return 2; } diff --git a/components/wpa_supplicant/src/common/wpa_common.h b/components/wpa_supplicant/src/common/wpa_common.h index ce2e4d602b..b7f8d0ca95 100644 --- a/components/wpa_supplicant/src/common/wpa_common.h +++ b/components/wpa_supplicant/src/common/wpa_common.h @@ -427,6 +427,13 @@ struct wpa_ft_ies { size_t ric_len; }; +/* WPA3 specification - RSN Selection element */ +enum rsn_selection_variant { + RSN_SELECTION_RSNE = 0, + RSN_SELECTION_RSNE_OVERRIDE = 1, +}; + + int wpa_ft_parse_ies(const u8 *ies, size_t ies_len, struct wpa_ft_ies *parse); int wpa_eapol_key_mic(const u8 *key, size_t key_len, int akmp, int ver, @@ -465,6 +472,8 @@ struct wpa_eapol_ie_parse { size_t transition_disable_len; const u8 *rsnxe; size_t rsnxe_len; + const u8 *rsn_selection; + size_t rsn_selection_len; }; int wpa_parse_kde_ies(const u8 *buf, size_t len, struct wpa_eapol_ie_parse *ie); static inline int wpa_supplicant_parse_ies(const u8 *buf, size_t len, diff --git a/components/wpa_supplicant/src/rsn_supp/wpa.c b/components/wpa_supplicant/src/rsn_supp/wpa.c index 674be39c88..40e5c9fcb3 100644 --- a/components/wpa_supplicant/src/rsn_supp/wpa.c +++ b/components/wpa_supplicant/src/rsn_supp/wpa.c @@ -536,7 +536,7 @@ int wpa_supplicant_send_2_of_4(struct wpa_sm *sm, const unsigned char *dst, size_t mic_len, hdrlen, rlen; struct wpa_eapol_key *reply; struct wpa_eapol_key_192 *reply192; - u8 *rsn_ie_buf = NULL; + u8 *rsn_ie_buf = NULL, *buf2 = NULL; u8 *rbuf, *key_mic; if (wpa_ie == NULL) { @@ -582,6 +582,35 @@ int wpa_supplicant_send_2_of_4(struct wpa_sm *sm, const unsigned char *dst, wpa_ie = rsn_ie_buf; } #endif /* CONFIG_IEEE80211R */ + if (sm->rsn_override != RSN_OVERRIDE_NOT_USED) { + u8 *pos; + + buf2 = os_malloc(wpa_ie_len + 2 + 4 + 1); + if (!buf2) { + os_free(rsn_ie_buf); + return -1; + } + os_memcpy(buf2, wpa_ie, wpa_ie_len); + pos = buf2 + wpa_ie_len; + *pos++ = WLAN_EID_VENDOR_SPECIFIC; + *pos++ = 4 + 1; + WPA_PUT_BE32(pos, RSN_SELECTION_IE_VENDOR_TYPE); + pos += 4; + if (sm->rsn_override == RSN_OVERRIDE_RSNE) { + *pos++ = RSN_SELECTION_RSNE; + } else if (sm->rsn_override == RSN_OVERRIDE_RSNE_OVERRIDE) { + *pos++ = RSN_SELECTION_RSNE_OVERRIDE; + } else { + os_free(rsn_ie_buf); + os_free(buf2); + return -1; + } + + wpa_ie = buf2; + wpa_ie_len += 2 + 4 + 1; + + } + wpa_hexdump(MSG_MSGDUMP, "WPA: WPA IE for msg 2/4\n", wpa_ie, wpa_ie_len); mic_len = wpa_mic_len(sm->key_mgmt, sm->pmk_len); @@ -591,6 +620,7 @@ int wpa_supplicant_send_2_of_4(struct wpa_sm *sm, const unsigned char *dst, &rlen, (void *) &reply); if (rbuf == NULL) { os_free(rsn_ie_buf); + os_free(buf2); return -1; } reply192 = (struct wpa_eapol_key_192 *) reply; @@ -617,6 +647,7 @@ int wpa_supplicant_send_2_of_4(struct wpa_sm *sm, const unsigned char *dst, } os_free(rsn_ie_buf); + os_free(buf2); os_memcpy(reply->key_nonce, nonce, WPA_NONCE_LEN); wpa_printf(MSG_DEBUG, "WPA Send EAPOL-Key 2/4"); @@ -2199,17 +2230,21 @@ void wpa_sm_deinit(void) * Returns: 0 on success, -1 on failure */ int wpa_sm_set_param(struct wpa_sm *sm, enum wpa_sm_conf_params param, - unsigned int value) + unsigned int value) { - int ret = 0; + int ret = 0; - if (sm == NULL) - return -1; - switch (param) { - default: - break; - } - return ret; + if (sm == NULL) + return -1; + + switch (param) { + case WPA_PARAM_RSN_OVERRIDE: + sm->rsn_override = value; + break; + default: + break; + } + return ret; } #ifdef ESP_SUPPLICANT @@ -2488,22 +2523,32 @@ int wpa_set_bss(uint8_t *macddr, uint8_t *bssid, u8 pairwise_cipher, u8 group_ci return -1; } pos += assoc_ie_len; - + wpa_sm_set_param(sm, WPA_PARAM_RSN_OVERRIDE, + RSN_OVERRIDE_NOT_USED); ie = esp_wifi_sta_get_ie(bssid, WLAN_EID_RSN); if (esp_wifi_wpa3_compatible_mode_enabled(WIFI_IF_STA) && - ie) { - u32 type = 0; - if (ie && ie[0] == WLAN_EID_VENDOR_SPECIFIC && ie[1] >= 4) - type = WPA_GET_BE32(&ie[2]); + ie && ie[0] != WLAN_EID_RSN) { + enum rsn_selection_variant variant = RSN_SELECTION_RSNE; - if (type) { - /* Indicate support for RSN overriding */ - *pos++ = WLAN_EID_VENDOR_SPECIFIC; - *pos++ = 4; - WPA_PUT_BE32(pos, type); - assoc_ie_len += 2 + 4; + if (ie && ie[0] == WLAN_EID_VENDOR_SPECIFIC && ie[1] >= 4) { + u32 type; + + type = WPA_GET_BE32(&ie[2]); + if (type == RSNE_OVERRIDE_IE_VENDOR_TYPE) { + variant = RSN_SELECTION_RSNE_OVERRIDE; + wpa_sm_set_param(sm, + WPA_PARAM_RSN_OVERRIDE, + RSN_OVERRIDE_RSNE_OVERRIDE); + } } + /* Indicate support for RSN overriding */ + *pos++ = WLAN_EID_VENDOR_SPECIFIC; + *pos++ = 4 + 1; + WPA_PUT_BE32(pos, RSN_SELECTION_IE_VENDOR_TYPE); + pos += 4; + *pos = variant; + assoc_ie_len += 2 + 4 + 1; } esp_set_assoc_ie(bssid, assoc_ie, assoc_ie_len, true); diff --git a/components/wpa_supplicant/src/rsn_supp/wpa.h b/components/wpa_supplicant/src/rsn_supp/wpa.h index 75f4bb6694..a9c35c2def 100644 --- a/components/wpa_supplicant/src/rsn_supp/wpa.h +++ b/components/wpa_supplicant/src/rsn_supp/wpa.h @@ -65,6 +65,8 @@ int wpa_sm_set_assoc_rsnxe(struct wpa_sm *sm, const u8 *ie, size_t len); void wpa_sm_drop_sa(struct wpa_sm *sm); +int wpa_sm_set_param(struct wpa_sm *sm, enum wpa_sm_conf_params param, + unsigned int value); #ifdef CONFIG_IEEE80211R int wpa_sm_set_ft_params(struct wpa_sm *sm, const u8 *ies, size_t ies_len); diff --git a/components/wpa_supplicant/src/rsn_supp/wpa_i.h b/components/wpa_supplicant/src/rsn_supp/wpa_i.h index e1c63fe539..7497a9d1dc 100644 --- a/components/wpa_supplicant/src/rsn_supp/wpa_i.h +++ b/components/wpa_supplicant/src/rsn_supp/wpa_i.h @@ -22,6 +22,12 @@ struct install_key { u8 key[32]; }; +enum wpa_rsn_override { + RSN_OVERRIDE_NOT_USED, + RSN_OVERRIDE_RSNE, + RSN_OVERRIDE_RSNE_OVERRIDE, +}; + /** * struct wpa_sm - Internal WPA state machine data */ @@ -119,6 +125,8 @@ struct wpa_sm { #endif /* CONFIG_OWE_STA */ int (*wpa_sm_wps_disable)(void); esp_err_t (*wpa_sm_eap_disable)(void); + + enum wpa_rsn_override rsn_override; }; /** From 8b8d5ebfc9a13e8d8959f74f2198bb51bda7e359 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 29 Jul 2024 16:43:50 +0300 Subject: [PATCH 18/33] RSNO: Use SNonce cookie to indicate support for RSN overriding This provides an implicitly protected (SNonce is used as an input to PTK derivation) mechanism for a STA to indicate support for RSN overriding in a manner that does not cause interopability issues with deployed APs. In addition, update sm->SNonce on the Authenticator only based on message 2/4 since that is the only EAPOL-Key message that is defined to provide the actual SNonce value. While clearing of this internal buffer on message 4/4 might not cause issues, it is better to keep the actual SNonce value here since the SNonce cookie can be used at a later point in the sequence. Signed-off-by: Jouni Malinen --- components/wpa_supplicant/src/ap/wpa_auth.c | 10 ++++++++-- .../wpa_supplicant/src/common/wpa_common.c | 19 +++++++++++++++++++ .../wpa_supplicant/src/common/wpa_common.h | 3 +++ components/wpa_supplicant/src/rsn_supp/wpa.c | 3 ++- 4 files changed, 32 insertions(+), 3 deletions(-) diff --git a/components/wpa_supplicant/src/ap/wpa_auth.c b/components/wpa_supplicant/src/ap/wpa_auth.c index e00fe390e0..61fca7457d 100644 --- a/components/wpa_supplicant/src/ap/wpa_auth.c +++ b/components/wpa_supplicant/src/ap/wpa_auth.c @@ -980,7 +980,8 @@ continue_processing: sm->EAPOLKeyReceived = TRUE; sm->EAPOLKeyPairwise = !!(key_info & WPA_KEY_INFO_KEY_TYPE); sm->EAPOLKeyRequest = !!(key_info & WPA_KEY_INFO_REQUEST); - memcpy(sm->SNonce, key->key_nonce, WPA_NONCE_LEN); + if (msg == PAIRWISE_2) + os_memcpy(sm->SNonce, key->key_nonce, WPA_NONCE_LEN); wpa_sm_step(sm); } @@ -1764,7 +1765,9 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING) } /* Verify RSN Selection element for RSN overriding */ - if ((sm->rsn_selection && !kde.rsn_selection) || + if ((rsn_is_snonce_cookie(sm->SNonce) && !kde.rsn_selection) || + (!rsn_is_snonce_cookie(sm->SNonce) && kde.rsn_selection) || + (sm->rsn_selection && !kde.rsn_selection) || (!sm->rsn_selection && kde.rsn_selection) || (sm->rsn_selection && kde.rsn_selection && (sm->rsn_selection_len != kde.rsn_selection_len || @@ -1772,6 +1775,9 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING) sm->rsn_selection_len) != 0))) { wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm), LOGGER_INFO, "RSN Selection element from (Re)AssocReq did not match the one in EAPOL-Key msg 2/4"); + wpa_printf(MSG_DEBUG, + "SNonce cookie for RSN overriding %sused", + rsn_is_snonce_cookie(sm->SNonce) ? "" : "not "); wpa_hexdump(MSG_DEBUG, "RSN Selection in AssocReq", sm->rsn_selection, sm->rsn_selection_len); wpa_hexdump(MSG_DEBUG, "RSN Selection in EAPOL-Key msg 2/4", diff --git a/components/wpa_supplicant/src/common/wpa_common.c b/components/wpa_supplicant/src/common/wpa_common.c index 388cad31c4..592840533c 100644 --- a/components/wpa_supplicant/src/common/wpa_common.c +++ b/components/wpa_supplicant/src/common/wpa_common.c @@ -1722,4 +1722,23 @@ int wpa_parse_kde_ies(const u8 *buf, size_t len, struct wpa_eapol_ie_parse *ie) return ret; } +void rsn_set_snonce_cookie(u8 *snonce) +{ + u8 *pos; + + pos = snonce + WPA_NONCE_LEN - 6; + WPA_PUT_BE24(pos, OUI_WFA); + pos += 3; + WPA_PUT_BE24(pos, 0x000029); +} + + +bool rsn_is_snonce_cookie(const u8 *snonce) +{ + const u8 *pos; + + pos = snonce + WPA_NONCE_LEN - 6; + return WPA_GET_BE24(pos) == OUI_WFA && + WPA_GET_BE24(pos + 3) == 0x000029; +} #endif // ESP_SUPPLICANT diff --git a/components/wpa_supplicant/src/common/wpa_common.h b/components/wpa_supplicant/src/common/wpa_common.h index b7f8d0ca95..d31c147227 100644 --- a/components/wpa_supplicant/src/common/wpa_common.h +++ b/components/wpa_supplicant/src/common/wpa_common.h @@ -499,4 +499,7 @@ unsigned int wpa_mic_len(int akmp, size_t pmk_len); int wpa_use_akm_defined(int akmp); int wpa_use_aes_key_wrap(int akmp); +void rsn_set_snonce_cookie(u8 *snonce); +bool rsn_is_snonce_cookie(const u8 *snonce); + #endif /* WPA_COMMON_H */ diff --git a/components/wpa_supplicant/src/rsn_supp/wpa.c b/components/wpa_supplicant/src/rsn_supp/wpa.c index 40e5c9fcb3..e4c86ae887 100644 --- a/components/wpa_supplicant/src/rsn_supp/wpa.c +++ b/components/wpa_supplicant/src/rsn_supp/wpa.c @@ -733,7 +733,8 @@ void wpa_supplicant_process_1_of_4(struct wpa_sm *sm, wpa_printf(MSG_DEBUG, "WPA: Failed to get random data for SNonce"); goto failed; } - + if (sm->rsn_override != RSN_OVERRIDE_NOT_USED) + rsn_set_snonce_cookie(sm->snonce); sm->renew_snonce = 0; wpa_hexdump(MSG_DEBUG, "WPA: Renewed SNonce", sm->snonce, WPA_NONCE_LEN); From f7e886bfed329ee10f21990eb5d2b5db6e9493e1 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 29 Jul 2024 17:20:22 +0300 Subject: [PATCH 19/33] RSNO: Include all RSNE/RSNXE variants in EAPOL-Key message 3/4 This allows all variants to be verified based on a protected frame to achieve robust downgrade protection. Signed-off-by: Jouni Malinen --- components/wpa_supplicant/src/ap/wpa_auth.c | 45 +--- .../wpa_supplicant/src/common/wpa_common.c | 13 ++ .../wpa_supplicant/src/common/wpa_common.h | 5 + components/wpa_supplicant/src/rsn_supp/wpa.c | 201 ++++++++++++------ components/wpa_supplicant/src/rsn_supp/wpa.h | 4 + .../wpa_supplicant/src/rsn_supp/wpa_i.h | 2 + 6 files changed, 159 insertions(+), 111 deletions(-) diff --git a/components/wpa_supplicant/src/ap/wpa_auth.c b/components/wpa_supplicant/src/ap/wpa_auth.c index 61fca7457d..c9fe428e57 100644 --- a/components/wpa_supplicant/src/ap/wpa_auth.c +++ b/components/wpa_supplicant/src/ap/wpa_auth.c @@ -1915,49 +1915,8 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING) wpa_ie = wpa_ie + wpa_ie[1] + 2; wpa_ie_len = wpa_ie[1] + 2; } - if (sm->rsn_override && - get_vendor_ie(wpa_ie, wpa_ie_len, RSNE_OVERRIDE_IE_VENDOR_TYPE)) { - const u8 *override_rsne = NULL, *override_rsnxe = NULL; - const struct element *elem; - - wpa_printf(MSG_DEBUG,"RSN: Use RSNE/RSNXE override element contents"); - - for_each_element_id(elem, WLAN_EID_VENDOR_SPECIFIC, - wpa_ie, wpa_ie_len) { - if (elem->datalen >= 4) { - if (WPA_GET_BE32(elem->data) == - RSNE_OVERRIDE_IE_VENDOR_TYPE) - override_rsne = &elem->id; - if (WPA_GET_BE32(elem->data) == - RSNXE_OVERRIDE_IE_VENDOR_TYPE) - override_rsnxe = &elem->id; - } - } - wpa_hexdump(MSG_DEBUG, "EAPOL-Key msg 3/4 IEs before edits", - wpa_ie, wpa_ie_len); - wpa_ie_buf3 = os_malloc(wpa_ie_len); - if (!wpa_ie_buf3) - goto done; - pos = wpa_ie_buf3; - if (override_rsne) { - *pos++ = WLAN_EID_RSN; - *pos++ = override_rsne[1] - 4; - os_memcpy(pos, &override_rsne[2 + 4], - override_rsne[1] - 4); - pos += override_rsne[1] - 4; - } - if (override_rsnxe) { - *pos++ = WLAN_EID_RSNX; - *pos++ = override_rsnxe[1] - 4; - os_memcpy(pos, &override_rsnxe[2 + 4], - override_rsnxe[1] - 4); - pos += override_rsnxe[1] - 4; - } - wpa_ie = wpa_ie_buf3; - wpa_ie_len = pos - wpa_ie_buf3; - wpa_hexdump(MSG_DEBUG, "EAPOL-Key msg 3/4 IEs after edits", - wpa_ie, wpa_ie_len); - } else if (conf->rsn_override_key_mgmt && !sm->rsn_override) { + if (conf->rsn_override_key_mgmt && + !rsn_is_snonce_cookie(sm->SNonce)) { u8 *ie; size_t ie_len; u32 ids[] = { diff --git a/components/wpa_supplicant/src/common/wpa_common.c b/components/wpa_supplicant/src/common/wpa_common.c index 592840533c..9bc07afe31 100644 --- a/components/wpa_supplicant/src/common/wpa_common.c +++ b/components/wpa_supplicant/src/common/wpa_common.c @@ -1653,6 +1653,19 @@ static int wpa_parse_generic(const u8 *pos, const u8 *end, pos, dlen); return 0; } + + if (selector == RSNE_OVERRIDE_IE_VENDOR_TYPE) { + ie->rsne_override = pos; + ie->rsne_override_len = dlen; + return 0; + } + + if (selector == RSNXE_OVERRIDE_IE_VENDOR_TYPE) { + ie->rsnxe_override = pos; + ie->rsnxe_override_len = dlen; + return 0; + } + if (selector == RSN_SELECTION_IE_VENDOR_TYPE) { ie->rsn_selection = p; ie->rsn_selection_len = left; diff --git a/components/wpa_supplicant/src/common/wpa_common.h b/components/wpa_supplicant/src/common/wpa_common.h index d31c147227..92d7abf8c3 100644 --- a/components/wpa_supplicant/src/common/wpa_common.h +++ b/components/wpa_supplicant/src/common/wpa_common.h @@ -474,6 +474,11 @@ struct wpa_eapol_ie_parse { size_t rsnxe_len; const u8 *rsn_selection; size_t rsn_selection_len; + const u8 *rsne_override; + size_t rsne_override_len; + const u8 *rsnxe_override; + size_t rsnxe_override_len; + }; int wpa_parse_kde_ies(const u8 *buf, size_t len, struct wpa_eapol_ie_parse *ie); static inline int wpa_supplicant_parse_ies(const u8 *buf, size_t len, diff --git a/components/wpa_supplicant/src/rsn_supp/wpa.c b/components/wpa_supplicant/src/rsn_supp/wpa.c index e4c86ae887..3011e974db 100644 --- a/components/wpa_supplicant/src/rsn_supp/wpa.c +++ b/components/wpa_supplicant/src/rsn_supp/wpa.c @@ -1215,6 +1215,48 @@ static int wpa_supplicant_validate_ie(struct wpa_sm *sm, return -1; } + if (sm->proto == WPA_PROTO_RSN && + sm->rsn_override != RSN_OVERRIDE_NOT_USED) { + if ((sm->ap_rsne_override && !ie->rsne_override) || + (!sm->ap_rsne_override && ie->rsne_override) || + (sm->ap_rsne_override && ie->rsne_override && + (sm->ap_rsne_override_len != ie->rsne_override_len || + os_memcmp(sm->ap_rsne_override, ie->rsne_override, + sm->ap_rsne_override_len) != 0))) { + wpa_msg(sm->ctx->msg_ctx, MSG_INFO, + "RSN: RSNE Override element mismatch between Beacon/ProbeResp and EAPOL-Key msg 3/4"); + wpa_hexdump(MSG_INFO, + "RSNE Override element in Beacon/ProbeResp", + sm->ap_rsne_override, + sm->ap_rsne_override_len); + wpa_hexdump(MSG_INFO, + "RSNE Override element in EAPOL-Key msg 3/4", + ie->rsne_override, ie->rsne_override_len); + wpa_sm_deauthenticate(sm, + WLAN_REASON_IE_IN_4WAY_DIFFERS); + return -1; + } + + if ((sm->ap_rsnxe_override && !ie->rsnxe_override) || + (!sm->ap_rsnxe_override && ie->rsnxe_override) || + (sm->ap_rsnxe_override && ie->rsnxe_override && + (sm->ap_rsnxe_override_len != ie->rsnxe_override_len || + os_memcmp(sm->ap_rsnxe_override, ie->rsnxe_override, + sm->ap_rsnxe_override_len) != 0))) { + wpa_msg(sm->ctx->msg_ctx, MSG_INFO, + "RSN: RSNXE Override element mismatch between Beacon/ProbeResp and EAPOL-Key msg 3/4"); + wpa_hexdump(MSG_INFO, + "RSNXE Override element in Beacon/ProbeResp", + sm->ap_rsnxe_override, + sm->ap_rsnxe_override_len); + wpa_hexdump(MSG_INFO, + "RSNXE Override element in EAPOL-Key msg 3/4", + ie->rsnxe_override, ie->rsnxe_override_len); + wpa_sm_deauthenticate(sm, + WLAN_REASON_IE_IN_4WAY_DIFFERS); + return -1; + } + } return 0; } @@ -2218,8 +2260,11 @@ void wpa_sm_deinit(void) sm->ap_rsn_ie = NULL; os_free(sm->ap_rsnxe); sm->ap_rsnxe = NULL; + os_free(sm->ap_rsne_override); + sm->ap_rsne_override = NULL; + os_free(sm->ap_rsnxe_override); + sm->ap_rsnxe_override = NULL; wpa_sm_drop_sa(sm); - sm->assoc_rsnxe = NULL; memset(sm, 0, sizeof(*sm)); } @@ -2509,9 +2554,15 @@ int wpa_set_bss(uint8_t *macddr, uint8_t *bssid, u8 pairwise_cipher, u8 group_ci sm->assoc_wpa_ie_len = res; ie = esp_wifi_sta_get_ie(bssid, WLAN_EID_RSN); - wpa_sm_set_ap_rsn_ie(sm, ie, ie[1]+2); + wpa_sm_set_ap_rsn_ie(sm, ie, ie ? (ie[1] + 2) : 0); ie = esp_wifi_sta_get_ie(bssid, WLAN_EID_RSNX); wpa_sm_set_ap_rsnxe(sm, ie, ie ? (ie[1] + 2) : 0); + if (esp_wifi_wpa3_compatible_mode_enabled(WIFI_IF_STA)) { + ie = esp_wifi_sta_get_ie(bssid, WFA_RSNE_OVERRIDE_OUI_TYPE); + wpa_sm_set_ap_rsne_override(sm, ie, ie ? (ie[1] + 2) : 0); + ie = esp_wifi_sta_get_ie(bssid, WFA_RSNXE_OVERRIDE_OUI_TYPE); + wpa_sm_set_ap_rsnxe_override(sm, ie, ie ? (ie[1] + 2) : 0); + } pos = assoc_ie; res = wpa_gen_rsnxe(sm, pos, assoc_ie_len); @@ -2846,38 +2897,25 @@ struct wpa_sm * get_wpa_sm(void) */ int wpa_sm_set_ap_rsn_ie(struct wpa_sm *sm, const u8 *ie, size_t len) { - if (sm == NULL) - return -1; + if (sm == NULL) + return -1; - os_free(sm->ap_rsn_ie); - if (ie == NULL || len == 0) { - wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, - "WPA: clearing AP RSN IE"); - sm->ap_rsn_ie = NULL; - sm->ap_rsn_ie_len = 0; - } else { - wpa_hexdump(MSG_DEBUG, "WPA: set AP RSN IE", ie, len); - if (ie[0] == WLAN_EID_VENDOR_SPECIFIC && len > 2 + 4) { - sm->ap_rsn_ie = os_malloc(len - 4); - if (!sm->ap_rsn_ie) - return -1; - sm->ap_rsn_ie[0] = WLAN_EID_RSN; - sm->ap_rsn_ie[1] = len - 2 - 4; - os_memcpy(&sm->ap_rsn_ie[2], ie + 2 + 4, len - 2 - 4); - sm->ap_rsn_ie_len = len - 4; - wpa_hexdump(MSG_DEBUG, - "RSN: Converted RSNE override to RSNE", - sm->ap_rsn_ie, sm->ap_rsn_ie_len); - } else { - sm->ap_rsn_ie = os_memdup(ie, len); - if (sm->ap_rsn_ie == NULL) - return -1; + os_free(sm->ap_rsn_ie); + if (ie == NULL || len == 0) { + wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, + "WPA: clearing AP RSN IE"); + sm->ap_rsn_ie = NULL; + sm->ap_rsn_ie_len = 0; + } else { + wpa_hexdump(MSG_DEBUG, "WPA: set AP RSN IE", ie, len); + sm->ap_rsn_ie = os_memdup(ie, len); + if (sm->ap_rsn_ie == NULL) + return -1; - sm->ap_rsn_ie_len = len; - } - } + sm->ap_rsn_ie_len = len; + } - return 0; + return 0; } /** @@ -2892,46 +2930,73 @@ int wpa_sm_set_ap_rsn_ie(struct wpa_sm *sm, const u8 *ie, size_t len) */ int wpa_sm_set_ap_rsnxe(struct wpa_sm *sm, const u8 *ie, size_t len) { - if (!sm) - return -1; + if (!sm) + return -1; - os_free(sm->ap_rsnxe); - if (!ie || len == 0) { - wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: clearing AP RSNXE"); - sm->ap_rsnxe = NULL; - sm->ap_rsnxe_len = 0; - } else { - wpa_hexdump(MSG_DEBUG, "WPA: set AP RSNXE", ie, len); - if (ie[0] == WLAN_EID_VENDOR_SPECIFIC && len > 2 + 4) { - sm->ap_rsnxe = os_malloc(len - 4); - if (!sm->ap_rsnxe) - return -1; - sm->ap_rsnxe[0] = WLAN_EID_RSNX; - sm->ap_rsnxe[1] = len - 2 - 4; - os_memcpy(&sm->ap_rsnxe[2], ie + 2 + 4, len - 2 - 4); - sm->ap_rsnxe_len = len - 4; - wpa_hexdump(MSG_DEBUG, - "RSN: Converted RSNXE override to RSNXE", - sm->ap_rsnxe, sm->ap_rsnxe_len); - } else { - sm->ap_rsnxe = os_memdup(ie, len); - if (!sm->ap_rsnxe) - return -1; + os_free(sm->ap_rsnxe); + if (!ie || len == 0) { + wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: clearing AP RSNXE"); + sm->ap_rsnxe = NULL; + sm->ap_rsnxe_len = 0; + } else { + wpa_hexdump(MSG_DEBUG, "WPA: set AP RSNXE", ie, len); + sm->ap_rsnxe = os_memdup(ie, len); + if (!sm->ap_rsnxe) + return -1; - sm->ap_rsnxe_len = len; - } - } - - if (sm->ap_rsnxe != NULL) { - sm->sae_pwe = esp_wifi_get_config_sae_pwe_h2e_internal(WIFI_IF_STA); -#ifdef CONFIG_SAE_PK - const u8 *pw = (const u8 *)esp_wifi_sta_get_prof_password_internal(); - if (esp_wifi_sta_get_config_sae_pk_internal() != WPA3_SAE_PK_MODE_DISABLED && - sae_pk_valid_password((const char*)pw)) { - sm->sae_pk = true; - } -#endif /* CONFIG_SAE_PK */ + sm->ap_rsnxe_len = len; } + + return 0; +} + + +int wpa_sm_set_ap_rsne_override(struct wpa_sm *sm, const u8 *ie, size_t len) +{ + if (!sm) + return -1; + + os_free(sm->ap_rsne_override); + if (!ie || len == 0) { + wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, + "RSN: Clearing AP RSNE Override element"); + sm->ap_rsne_override = NULL; + sm->ap_rsne_override_len = 0; + } else { + wpa_hexdump(MSG_DEBUG, "RSN: Set AP RSNE Override element", + ie, len); + sm->ap_rsne_override = os_memdup(ie, len); + if (!sm->ap_rsne_override) + return -1; + + sm->ap_rsne_override_len = len; + } + + return 0; +} + + +int wpa_sm_set_ap_rsnxe_override(struct wpa_sm *sm, const u8 *ie, size_t len) +{ + if (!sm) + return -1; + + os_free(sm->ap_rsnxe_override); + if (!ie || len == 0) { + wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, + "RSN: Clearing AP RSNXE Override element"); + sm->ap_rsnxe_override = NULL; + sm->ap_rsnxe_override_len = 0; + } else { + wpa_hexdump(MSG_DEBUG, "RSN: Set AP RSNXE Override element", + ie, len); + sm->ap_rsnxe_override = os_memdup(ie, len); + if (!sm->ap_rsnxe_override) + return -1; + + sm->ap_rsnxe_override_len = len; + } + return 0; } diff --git a/components/wpa_supplicant/src/rsn_supp/wpa.h b/components/wpa_supplicant/src/rsn_supp/wpa.h index a9c35c2def..ca160ca74c 100644 --- a/components/wpa_supplicant/src/rsn_supp/wpa.h +++ b/components/wpa_supplicant/src/rsn_supp/wpa.h @@ -61,6 +61,10 @@ int wpa_sm_set_ap_rsn_ie(struct wpa_sm *sm, const u8 *ie, size_t len); int wpa_sm_set_ap_rsnxe(struct wpa_sm *sm, const u8 *ie, size_t len); +int wpa_sm_set_ap_rsne_override(struct wpa_sm *sm, const u8 *ie, size_t len); + +int wpa_sm_set_ap_rsnxe_override(struct wpa_sm *sm, const u8 *ie, size_t len); + int wpa_sm_set_assoc_rsnxe(struct wpa_sm *sm, const u8 *ie, size_t len); void wpa_sm_drop_sa(struct wpa_sm *sm); diff --git a/components/wpa_supplicant/src/rsn_supp/wpa_i.h b/components/wpa_supplicant/src/rsn_supp/wpa_i.h index 7497a9d1dc..1cf50a2be2 100644 --- a/components/wpa_supplicant/src/rsn_supp/wpa_i.h +++ b/components/wpa_supplicant/src/rsn_supp/wpa_i.h @@ -82,6 +82,8 @@ struct wpa_sm { u8 *ap_wpa_ie, *ap_rsn_ie, *ap_rsnxe; size_t ap_wpa_ie_len, ap_rsn_ie_len, ap_rsnxe_len; + u8 *ap_rsne_override, *ap_rsnxe_override; + size_t ap_rsne_override_len, ap_rsnxe_override_len; bool key_install; From 35e73c0147c5c89eb2c1eb4ebcebbcad0e33cd7c Mon Sep 17 00:00:00 2001 From: Shreyas Sheth Date: Wed, 19 Mar 2025 15:36:12 +0530 Subject: [PATCH 20/33] fix(esp_wifi): Cosmetic changes for wpa_supplicant --- components/wpa_supplicant/src/rsn_supp/wpa.c | 50 ++++++++++++-------- 1 file changed, 29 insertions(+), 21 deletions(-) diff --git a/components/wpa_supplicant/src/rsn_supp/wpa.c b/components/wpa_supplicant/src/rsn_supp/wpa.c index 3011e974db..8b213af907 100644 --- a/components/wpa_supplicant/src/rsn_supp/wpa.c +++ b/components/wpa_supplicant/src/rsn_supp/wpa.c @@ -1400,10 +1400,10 @@ static void wpa_supplicant_process_3_of_4(struct wpa_sm *sm, (sm->gd).gtk_len=0; //used as flag if gtk is installed in callback if (ie.gtk) { wpa_sm_set_seq(sm, key, 0); - if (wpa_supplicant_pairwise_gtk(sm, + if (wpa_supplicant_pairwise_gtk(sm, ie.gtk, ie.gtk_len, key_info) < 0) { - wpa_printf(MSG_DEBUG, "RSN: Failed to configure GTK"); - goto failed; + wpa_printf(MSG_DEBUG, "RSN: Failed to configure GTK"); + goto failed; } } @@ -1462,7 +1462,7 @@ static int wpa_supplicant_activate_ptk(struct wpa_sm *sm) static int wpa_supplicant_send_4_of_4_txcallback(struct wpa_sm *sm) { - u16 key_info=sm->key_info; + u16 key_info = sm->key_info; if (sm->key_install && key_info & WPA_KEY_INFO_INSTALL) { if (sm->use_ext_key_id) { @@ -1521,7 +1521,7 @@ static int wpa_supplicant_send_4_of_4_txcallback(struct wpa_sm *sm) return 0; failed: - return WLAN_REASON_UNSPECIFIED; + return WLAN_REASON_UNSPECIFIED; } static int wpa_supplicant_process_1_of_2_rsn(struct wpa_sm *sm, @@ -1840,7 +1840,7 @@ static int wpa_supplicant_decrypt_key_data(struct wpa_sm *sm, *key_data_len -= 8; /* AES-WRAP adds 8 bytes */ /*replaced by xxx to remove malloc*/ buf = ((u8 *) (key+1))+ 8; - /* + /* buf = os_wifi_malloc(keydatalen); if (buf == NULL) { wpa_printf(MSG_DEBUG, "WPA: No memory for " @@ -1947,8 +1947,7 @@ int wpa_sm_rx_eapol(u8 *src_addr, u8 *buf, u32 len) hdr = (struct ieee802_1x_hdr *) tmp; key = (struct wpa_eapol_key *) (hdr + 1); - key192 = (struct wpa_eapol_key_192 *) - (tmp + sizeof(struct ieee802_1x_hdr)); + key192 = (struct wpa_eapol_key_192 *)(tmp + sizeof(struct ieee802_1x_hdr)); if (mic_len == 24) key_data = (u8 *) (key192 + 1); else @@ -2163,7 +2162,7 @@ void wpa_sm_set_state(enum wpa_states state) { struct wpa_sm *sm = &gWpaSm; if(WPA_MIC_FAILURE==WPA_SM_STATE(sm)) - eloop_cancel_timeout(wpa_supplicant_stop_countermeasures, NULL, NULL); + eloop_cancel_timeout(wpa_supplicant_stop_countermeasures, NULL, NULL); sm->wpa_state= state; } @@ -2494,9 +2493,9 @@ int wpa_set_bss(uint8_t *macddr, uint8_t *bssid, u8 pairwise_cipher, u8 group_ci sm->pmf_cfg = wifi_cfg.sta.pmf_cfg; sm->mgmt_group_cipher = cipher_type_map_public_to_supp(mgmt_cipher); if (sm->mgmt_group_cipher == WPA_CIPHER_NONE) { - wpa_printf(MSG_ERROR, "mgmt_cipher %d not supported", mgmt_cipher); - return -1; - } + wpa_printf(MSG_ERROR, "mgmt_cipher %d not supported", mgmt_cipher); + return -1; + } #ifdef CONFIG_SUITEB192 extern bool g_wpa_suiteb_certification; if (is_wpa2_enterprise_connection() && g_wpa_suiteb_certification) { @@ -2604,6 +2603,17 @@ int wpa_set_bss(uint8_t *macddr, uint8_t *bssid, u8 pairwise_cipher, u8 group_ci } esp_set_assoc_ie(bssid, assoc_ie, assoc_ie_len, true); + + if (sm->ap_rsnxe != NULL) { +#ifdef CONFIG_SAE_PK + const u8 *pw = (const u8 *)esp_wifi_sta_get_prof_password_internal(); + if (esp_wifi_sta_get_config_sae_pk_internal() != WPA3_SAE_PK_MODE_DISABLED && + sae_pk_valid_password((const char*)pw)) { + sm->sae_pk = true; + } +#endif /* CONFIG_SAE_PK */ + } + os_memset(sm->ssid, 0, sizeof(sm->ssid)); os_memcpy(sm->ssid, ssid, ssid_len); sm->ssid_len = ssid_len; @@ -2622,8 +2632,7 @@ int wpa_set_bss(uint8_t *macddr, uint8_t *bssid, u8 pairwise_cipher, u8 group_ci /* * Call after set ssid since we calc pmk inside this routine directly */ - void -wpa_set_passphrase(char * passphrase, u8 *ssid, size_t ssid_len) +void wpa_set_passphrase(char * passphrase, u8 *ssid, size_t ssid_len) { struct wifi_ssid *sta_ssid = esp_wifi_sta_get_prof_ssid_internal(); struct wpa_sm *sm = &gWpaSm; @@ -2656,7 +2665,7 @@ wpa_set_passphrase(char * passphrase, u8 *ssid, size_t ssid_len) } if (sm->key_mgmt == WPA_KEY_MGMT_IEEE8021X) { - /* TODO nothing */ + /* TODO nothing */ } else { memcpy(sm->pmk, esp_wifi_sta_get_ap_info_prof_pmk_internal(), PMK_LEN); sm->pmk_len = PMK_LEN; @@ -2668,18 +2677,17 @@ wpa_set_passphrase(char * passphrase, u8 *ssid, size_t ssid_len) #endif /* CONFIG_IEEE80211R */ } - void -set_assoc_ie(u8 * assoc_buf) +void set_assoc_ie(u8 * assoc_buf) { struct wpa_sm *sm = &gWpaSm; sm->assoc_wpa_ie = assoc_buf + 2; //wpa_ie insert OUI 4 byte before ver, but RSN have 2 bytes of RSN capability, // so wpa_ie have two more bytes than rsn_ie - if ( sm->proto == WPA_PROTO_WPA) - sm->assoc_wpa_ie_len = ASSOC_IE_LEN; + if (sm->proto == WPA_PROTO_WPA) + sm->assoc_wpa_ie_len = ASSOC_IE_LEN; else - sm->assoc_wpa_ie_len = ASSOC_IE_LEN - 2; + sm->assoc_wpa_ie_len = ASSOC_IE_LEN - 2; wpa_config_assoc_ie(sm->proto, assoc_buf, sm->assoc_wpa_ie_len); } @@ -2761,7 +2769,7 @@ int wpa_michael_mic_failure(u16 isunicast) * Need to wait for completion of request frame. We do not get * any callback for the message completion, so just wait a * short while and hope for the best. */ - os_sleep(0, 10000); + os_sleep(0, 10000); /*deauthenticate AP*/ From 60643b71e7e64b13e11cde73ebec340e75831f46 Mon Sep 17 00:00:00 2001 From: Veerendranath Jakkam Date: Wed, 7 Aug 2024 14:36:30 +0530 Subject: [PATCH 21/33] RSNO: Add debug prints for RSN override elements in EAPOL frames Signed-off-by: Veerendranath Jakkam --- components/wpa_supplicant/src/common/wpa_common.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/components/wpa_supplicant/src/common/wpa_common.c b/components/wpa_supplicant/src/common/wpa_common.c index 9bc07afe31..c33d01da96 100644 --- a/components/wpa_supplicant/src/common/wpa_common.c +++ b/components/wpa_supplicant/src/common/wpa_common.c @@ -1657,18 +1657,27 @@ static int wpa_parse_generic(const u8 *pos, const u8 *end, if (selector == RSNE_OVERRIDE_IE_VENDOR_TYPE) { ie->rsne_override = pos; ie->rsne_override_len = dlen; + wpa_hexdump(MSG_DEBUG, + "RSN: RSNE Override element in EAPOL-Key", + ie->rsne_override, ie->rsne_override_len); return 0; } if (selector == RSNXE_OVERRIDE_IE_VENDOR_TYPE) { ie->rsnxe_override = pos; ie->rsnxe_override_len = dlen; + wpa_hexdump(MSG_DEBUG, + "RSN: RSNXE Override element in EAPOL-Key", + ie->rsnxe_override, ie->rsnxe_override_len); return 0; } if (selector == RSN_SELECTION_IE_VENDOR_TYPE) { ie->rsn_selection = p; ie->rsn_selection_len = left; + wpa_hexdump(MSG_DEBUG, + "RSN: RSN Selection element in EAPOL-Key", + ie->rsn_selection, ie->rsn_selection_len); return 0; } return 2; From 5e1e2cd4eadc8c3582a9eb721858ede1fbdca24a Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Thu, 15 Aug 2024 20:39:03 +0300 Subject: [PATCH 22/33] RSNO: Do not enforce SNonce cookie and RSN Selection match if RSNO not used A STA that supports RSN overriding will always use the SNonce cookie. An AP that does not advertise RSN overriding elements must not enforce that SNonce cookie is used with RSN Selection element since a STA includes the latter only when it sees the AP advertising RSN overriding elements. Signed-off-by: Jouni Malinen --- components/wpa_supplicant/src/ap/wpa_auth.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/components/wpa_supplicant/src/ap/wpa_auth.c b/components/wpa_supplicant/src/ap/wpa_auth.c index c9fe428e57..d1b40bb1c8 100644 --- a/components/wpa_supplicant/src/ap/wpa_auth.c +++ b/components/wpa_supplicant/src/ap/wpa_auth.c @@ -1765,14 +1765,15 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING) } /* Verify RSN Selection element for RSN overriding */ - if ((rsn_is_snonce_cookie(sm->SNonce) && !kde.rsn_selection) || + if (sm->wpa_auth->conf.rsn_override_key_mgmt && + ((rsn_is_snonce_cookie(sm->SNonce) && !kde.rsn_selection) || (!rsn_is_snonce_cookie(sm->SNonce) && kde.rsn_selection) || (sm->rsn_selection && !kde.rsn_selection) || (!sm->rsn_selection && kde.rsn_selection) || (sm->rsn_selection && kde.rsn_selection && (sm->rsn_selection_len != kde.rsn_selection_len || os_memcmp(sm->rsn_selection, kde.rsn_selection, - sm->rsn_selection_len) != 0))) { + sm->rsn_selection_len) != 0)))) { wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm), LOGGER_INFO, "RSN Selection element from (Re)AssocReq did not match the one in EAPOL-Key msg 2/4"); wpa_printf(MSG_DEBUG, From 1848be2f068c4e697bc8ef7c6912da58abc10543 Mon Sep 17 00:00:00 2001 From: Veerendranath Jakkam Date: Tue, 13 Aug 2024 23:42:48 +0530 Subject: [PATCH 23/33] RSNO: Always enable SNonce cookie and RSN Override elements validation Always set SNonce cookie and enable RSN Override elements validation irrespective of the RSN Selection element usage in (Re)Association Request frame when RSN overriding supported. Signed-off-by: Veerendranath Jakkam --- components/wpa_supplicant/src/rsn_supp/wpa.c | 33 ++++++++++++++++--- components/wpa_supplicant/src/rsn_supp/wpa.h | 1 + .../wpa_supplicant/src/rsn_supp/wpa_i.h | 3 ++ 3 files changed, 33 insertions(+), 4 deletions(-) diff --git a/components/wpa_supplicant/src/rsn_supp/wpa.c b/components/wpa_supplicant/src/rsn_supp/wpa.c index 8b213af907..f7392a54c6 100644 --- a/components/wpa_supplicant/src/rsn_supp/wpa.c +++ b/components/wpa_supplicant/src/rsn_supp/wpa.c @@ -733,7 +733,7 @@ void wpa_supplicant_process_1_of_4(struct wpa_sm *sm, wpa_printf(MSG_DEBUG, "WPA: Failed to get random data for SNonce"); goto failed; } - if (sm->rsn_override != RSN_OVERRIDE_NOT_USED) + if (wpa_sm_rsn_overriding_supported(sm)) rsn_set_snonce_cookie(sm->snonce); sm->renew_snonce = 0; wpa_hexdump(MSG_DEBUG, "WPA: Renewed SNonce", @@ -1215,8 +1215,7 @@ static int wpa_supplicant_validate_ie(struct wpa_sm *sm, return -1; } - if (sm->proto == WPA_PROTO_RSN && - sm->rsn_override != RSN_OVERRIDE_NOT_USED) { + if (sm->proto == WPA_PROTO_RSN && wpa_sm_rsn_overriding_supported(sm)) { if ((sm->ap_rsne_override && !ie->rsne_override) || (!sm->ap_rsne_override && ie->rsne_override) || (sm->ap_rsne_override && ie->rsne_override && @@ -2286,12 +2285,36 @@ int wpa_sm_set_param(struct wpa_sm *sm, enum wpa_sm_conf_params param, case WPA_PARAM_RSN_OVERRIDE: sm->rsn_override = value; break; + case WPA_PARAM_RSN_OVERRIDE_SUPPORT: + sm->rsn_override_support = value; + break; default: break; } return ret; } +static const u8 * wpa_sm_get_ap_rsne(struct wpa_sm *sm, size_t *len) +{ + if (sm->rsn_override == RSN_OVERRIDE_RSNE_OVERRIDE) { + *len = sm->ap_rsne_override_len; + return sm->ap_rsne_override; + } + + *len = sm->ap_rsn_ie_len; + return sm->ap_rsn_ie; +} + +bool wpa_sm_rsn_overriding_supported(struct wpa_sm *sm) +{ + const u8 *rsne; + size_t rsne_len; + + rsne = wpa_sm_get_ap_rsne(sm, &rsne_len); + + return sm->rsn_override_support && rsne; +} + #ifdef ESP_SUPPLICANT /** * wpa_sm_notify_assoc - Notify WPA state machine about association @@ -2574,6 +2597,8 @@ int wpa_set_bss(uint8_t *macddr, uint8_t *bssid, u8 pairwise_cipher, u8 group_ci return -1; } pos += assoc_ie_len; + wpa_sm_set_param(sm, WPA_PARAM_RSN_OVERRIDE_SUPPORT, + esp_wifi_wpa3_compatible_mode_enabled(WIFI_IF_STA)); wpa_sm_set_param(sm, WPA_PARAM_RSN_OVERRIDE, RSN_OVERRIDE_NOT_USED); ie = esp_wifi_sta_get_ie(bssid, WLAN_EID_RSN); @@ -2601,7 +2626,7 @@ int wpa_set_bss(uint8_t *macddr, uint8_t *bssid, u8 pairwise_cipher, u8 group_ci *pos = variant; assoc_ie_len += 2 + 4 + 1; } - + wpa_hexdump(MSG_DEBUG, "WPA: ASSOC IE LEN", assoc_ie, assoc_ie_len); esp_set_assoc_ie(bssid, assoc_ie, assoc_ie_len, true); if (sm->ap_rsnxe != NULL) { diff --git a/components/wpa_supplicant/src/rsn_supp/wpa.h b/components/wpa_supplicant/src/rsn_supp/wpa.h index ca160ca74c..3968184ee1 100644 --- a/components/wpa_supplicant/src/rsn_supp/wpa.h +++ b/components/wpa_supplicant/src/rsn_supp/wpa.h @@ -37,6 +37,7 @@ struct l2_ethhdr { enum wpa_sm_conf_params { WPA_PARAM_RSN_OVERRIDE, + WPA_PARAM_RSN_OVERRIDE_SUPPORT, }; void wpa_sm_set_state(enum wpa_states state); diff --git a/components/wpa_supplicant/src/rsn_supp/wpa_i.h b/components/wpa_supplicant/src/rsn_supp/wpa_i.h index 1cf50a2be2..1f272ea262 100644 --- a/components/wpa_supplicant/src/rsn_supp/wpa_i.h +++ b/components/wpa_supplicant/src/rsn_supp/wpa_i.h @@ -128,6 +128,7 @@ struct wpa_sm { int (*wpa_sm_wps_disable)(void); esp_err_t (*wpa_sm_eap_disable)(void); + bool rsn_override_support; enum wpa_rsn_override rsn_override; }; @@ -220,4 +221,6 @@ int wpa_sm_rx_eapol(u8 *src_addr, u8 *buf, u32 len); int wpa_derive_ptk_ft(struct wpa_sm *sm, const unsigned char *src_addr, const struct wpa_eapol_key *key, struct wpa_ptk *ptk); + +bool wpa_sm_rsn_overriding_supported(struct wpa_sm *sm); #endif /* WPA_I_H */ From 22a15585fdf406018b048939ad8d5c775b962599 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Thu, 10 Oct 2024 11:53:29 +0300 Subject: [PATCH 24/33] RSNO: Omit RSNXE in (Re)Association Response frame like in Beacon frame When rsn_override_omit_rsnxe=1 is used to omit the RSNXE from Beacon and Probe Response frames, it should also be omitted from (Re)Association Response frames since there is a general expectation on the RSNXE being used consistently between these frames. This is unlikely to have much of a difference for most use cases in practice, but this could impact FILS association if the non-AP STA were to confirm that the unprotected and protected version of the RSNXE from the AP were identical. Fixes: 8b2ddfdbb688 ("RSNO: Allow RSNXE to be omitted") Signed-off-by: Jouni Malinen --- components/wpa_supplicant/esp_supplicant/src/esp_hostap.c | 4 ++++ components/wpa_supplicant/src/ap/ap_config.h | 1 + 2 files changed, 5 insertions(+) diff --git a/components/wpa_supplicant/esp_supplicant/src/esp_hostap.c b/components/wpa_supplicant/esp_supplicant/src/esp_hostap.c index b22c02944f..44dba7071b 100644 --- a/components/wpa_supplicant/esp_supplicant/src/esp_hostap.c +++ b/components/wpa_supplicant/esp_supplicant/src/esp_hostap.c @@ -447,6 +447,10 @@ send_resp: omit_rsnxe = true; } + if (hapd->conf->rsn_override_omit_rsnxe) { + omit_rsnxe = 1; + } + if (esp_send_assoc_resp(hapd, bssid, status, omit_rsnxe, subtype) != WLAN_STATUS_SUCCESS) { status = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA; } diff --git a/components/wpa_supplicant/src/ap/ap_config.h b/components/wpa_supplicant/src/ap/ap_config.h index 9aff9d2a7e..5d848d9421 100644 --- a/components/wpa_supplicant/src/ap/ap_config.h +++ b/components/wpa_supplicant/src/ap/ap_config.h @@ -310,6 +310,7 @@ struct hostapd_bss_config { int *sae_groups; #define SAE_ANTI_CLOGGING_THRESHOLD 2 /* max number of commit msg allowed to queue without anti-clogging token request */ + int rsn_override_omit_rsnxe; }; From c3d6a1ce73f7d708ce7a0e6902619cebb754011a Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 1 Nov 2024 21:58:07 +0200 Subject: [PATCH 25/33] Avoid undefined behavior in RSNXE capability bit checker Integer promotion converts u8 rsnxe[i] to an int which is not sufficiently large to be able to handle the maximum shift left of 24 bits here. Type cast rsnxe[i] to u32 explicitly to get rid of the sign bit and avoid this undefined behavior from the shift operation. Credit to OSS-Fuzz: https://issues.oss-fuzz.com/issues/376786400 Fixes: d675d3b15b40 ("Add helper functions for parsing RSNXE capabilities") Signed-off-by: Jouni Malinen --- components/wpa_supplicant/src/common/ieee802_11_common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/wpa_supplicant/src/common/ieee802_11_common.c b/components/wpa_supplicant/src/common/ieee802_11_common.c index cc3e8ff1af..0487dc7f63 100644 --- a/components/wpa_supplicant/src/common/ieee802_11_common.c +++ b/components/wpa_supplicant/src/common/ieee802_11_common.c @@ -521,7 +521,7 @@ bool ieee802_11_rsnx_capab_len(const u8 *rsnxe, size_t rsnxe_len, if (flen > 4) flen = 4; for (i = 0; i < flen; i++) - capabs |= rsnxe[i] << (8 * i); + capabs |= (u32) rsnxe[i] << (8 * i); return capabs & BIT(capab); } From e8a19841f4d252bf208ac79de8f92fa3dbb24f7d Mon Sep 17 00:00:00 2001 From: Sai Pratyusha Magam Date: Fri, 3 Jan 2025 11:23:22 +0530 Subject: [PATCH 26/33] RSNO: Generate IGTK if any of the RSN variants has PMF enabled With RSN overriding enabled, AP can be configured to set MFPC to 0 and MFPR to 0 in the RSNE and MFPC to 1 and MFPR to 1 in the RSNOE and RSNO2E. IGTK generation, configuration to the driver, and inclusion of the IGTK KDE in 4-way handshake should also take into account the management frame protection settings in the override variants. Signed-off-by: Sai Pratyusha Magam --- components/wpa_supplicant/src/ap/wpa_auth.c | 4 ++-- components/wpa_supplicant/src/ap/wpa_auth.h | 5 +++++ components/wpa_supplicant/src/ap/wpa_auth_ie.c | 2 +- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/components/wpa_supplicant/src/ap/wpa_auth.c b/components/wpa_supplicant/src/ap/wpa_auth.c index d1b40bb1c8..19a73246f9 100644 --- a/components/wpa_supplicant/src/ap/wpa_auth.c +++ b/components/wpa_supplicant/src/ap/wpa_auth.c @@ -2381,7 +2381,7 @@ static int wpa_gtk_update(struct wpa_authenticator *wpa_auth, group->GTK[group->GN - 1], group->GTK_len); #ifdef CONFIG_IEEE80211W - if (wpa_auth->conf.ieee80211w != NO_MGMT_FRAME_PROTECTION) { + if (wpa_auth_pmf_enabled(&wpa_auth->conf)) { len = wpa_cipher_key_len(wpa_auth->conf.group_mgmt_cipher); memcpy(group->GNonce, group->Counter, WPA_NONCE_LEN); inc_byte_array(group->Counter, WPA_NONCE_LEN); @@ -2577,7 +2577,7 @@ static int wpa_group_config_group_keys(struct wpa_authenticator *wpa_auth, ret = -1; #ifdef CONFIG_IEEE80211W - if (wpa_auth->conf.ieee80211w != NO_MGMT_FRAME_PROTECTION && + if (wpa_auth_pmf_enabled(&wpa_auth->conf) && wpa_auth_set_key(wpa_auth, group->vlan_id, WIFI_WPA_ALG_IGTK, broadcast_ether_addr, group->GN_igtk, group->IGTK[group->GN_igtk - 4], diff --git a/components/wpa_supplicant/src/ap/wpa_auth.h b/components/wpa_supplicant/src/ap/wpa_auth.h index 7a27fd3675..000f93cbb1 100644 --- a/components/wpa_supplicant/src/ap/wpa_auth.h +++ b/components/wpa_supplicant/src/ap/wpa_auth.h @@ -310,5 +310,10 @@ void wpa_auth_pmksa_remove(struct wpa_authenticator *wpa_auth, const u8 *sta_addr); void wpa_auth_set_rsn_selection(struct wpa_state_machine *sm, const u8 *ie, size_t len); +static inline bool wpa_auth_pmf_enabled(struct wpa_auth_config *conf) +{ + return conf->ieee80211w != NO_MGMT_FRAME_PROTECTION || + conf->rsn_override_mfp != NO_MGMT_FRAME_PROTECTION; +} #endif /* WPA_AUTH_H */ diff --git a/components/wpa_supplicant/src/ap/wpa_auth_ie.c b/components/wpa_supplicant/src/ap/wpa_auth_ie.c index 9e85b801ad..45f7593110 100644 --- a/components/wpa_supplicant/src/ap/wpa_auth_ie.c +++ b/components/wpa_supplicant/src/ap/wpa_auth_ie.c @@ -751,7 +751,7 @@ wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth, } #endif /* CONFIG_SAE */ - if (wpa_auth->conf.ieee80211w == NO_MGMT_FRAME_PROTECTION || + if (!wpa_auth_pmf_enabled(&wpa_auth->conf) || !(data.capabilities & WPA_CAPABILITY_MFPC)) sm->mgmt_frame_prot = 0; else From fbfa3aa0e0afb1b3e8eddb2b1fe67975b90f3cf7 Mon Sep 17 00:00:00 2001 From: Shreyas Sheth Date: Wed, 2 Apr 2025 10:36:27 +0530 Subject: [PATCH 27/33] feat(esp_wifi): Add support of wpa3 compatible more for ap and sta --- components/esp_wifi/include/esp_wifi_types_generic.h | 5 ++--- .../wpa_supplicant/esp_supplicant/src/esp_common.c | 6 +++++- .../wpa_supplicant/esp_supplicant/src/esp_hostap.c | 8 ++++++-- .../esp_supplicant/src/esp_wifi_driver.h | 2 +- .../wpa_supplicant/esp_supplicant/src/esp_wpa3.c | 2 +- .../wpa_supplicant/esp_supplicant/src/esp_wpa_main.c | 12 ++++++------ components/wpa_supplicant/src/ap/wpa_auth_ie.c | 7 +------ components/wpa_supplicant/src/common/wpa_common.c | 7 ++++++- components/wpa_supplicant/src/rsn_supp/wpa.c | 2 +- components/wpa_supplicant/src/rsn_supp/wpa_ie.c | 4 ++++ 10 files changed, 33 insertions(+), 22 deletions(-) diff --git a/components/esp_wifi/include/esp_wifi_types_generic.h b/components/esp_wifi/include/esp_wifi_types_generic.h index 5557024eeb..c82809d8a4 100644 --- a/components/esp_wifi/include/esp_wifi_types_generic.h +++ b/components/esp_wifi/include/esp_wifi_types_generic.h @@ -533,8 +533,6 @@ typedef struct { 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 */ - uint8_t sae_ext; /**< Enable SAE EXT feature. SOC_GCMP_SUPPORT is required for this feature. */ uint8_t transition_disable: 1; /**< Whether to enable transition disable feature */ uint8_t sae_ext: 1; /**< Enable SAE EXT feature. SOC_GCMP_SUPPORT is required for this feature. */ uint8_t wpa3_compatible_mode: 1; /**< Whether to enable wpa3 compatible authmode feature */ @@ -565,7 +563,8 @@ typedef struct { uint32_t ft_enabled: 1; /**< Whether FT is enabled for the connection */ uint32_t owe_enabled: 1; /**< Whether OWE is enabled for the connection */ uint32_t transition_disable: 1; /**< Whether to enable transition disable feature */ - uint32_t reserved1: 26; /**< Reserved for future feature set */ + uint32_t wpa3_compatible_mode: 1; /**< Whether to enable wpa3 compatible authmode feature */ + uint32_t reserved1: 25; /**< Reserved for future feature set */ wifi_sae_pwe_method_t sae_pwe_h2e; /**< Configuration for SAE PWE derivation method */ wifi_sae_pk_mode_t sae_pk_mode; /**< Configuration for SAE-PK (Public Key) Authentication method */ uint8_t failure_retry_cnt; /**< Number of connection retries station will do before moving to next AP. scan_method should be set as WIFI_ALL_CHANNEL_SCAN to use this config. diff --git a/components/wpa_supplicant/esp_supplicant/src/esp_common.c b/components/wpa_supplicant/esp_supplicant/src/esp_common.c index b95578035e..60e5cc0e5c 100644 --- a/components/wpa_supplicant/esp_supplicant/src/esp_common.c +++ b/components/wpa_supplicant/esp_supplicant/src/esp_common.c @@ -322,7 +322,9 @@ void supplicant_sta_conn_handler(uint8_t *bssid) u8 *ie; struct wpa_supplicant *wpa_s = &g_wpa_supp; struct wpa_bss *bss = wpa_bss_get_bssid(wpa_s, bssid); +#ifdef CONFIG_RRM struct ieee802_11_elems elems; +#endif if (!bss) { wpa_printf(MSG_INFO, "connected bss entry not present in scan cache"); @@ -331,11 +333,13 @@ void supplicant_sta_conn_handler(uint8_t *bssid) wpa_s->current_bss = bss; ie = (u8 *)bss; ie += sizeof(struct wpa_bss); +#ifdef CONFIG_RRM ieee802_11_parse_elems(ie, bss->ie_len, &elems, 0); if (elems.rrm_enabled_len > 0 && elems.rrm_enabled != NULL) { - os_memcpy(wpa_s->rrm_ie, elems.rrm_enabled, 5); //TODO ask kapil about 5 + os_memcpy(wpa_s->rrm_ie, elems.rrm_enabled, 5); wpa_s->rrm.rrm_used = true; } +#endif wpa_bss_flush(wpa_s); /* Register for mgmt frames */ register_mgmt_frames(wpa_s); diff --git a/components/wpa_supplicant/esp_supplicant/src/esp_hostap.c b/components/wpa_supplicant/esp_supplicant/src/esp_hostap.c index 44dba7071b..df9da91253 100644 --- a/components/wpa_supplicant/esp_supplicant/src/esp_hostap.c +++ b/components/wpa_supplicant/esp_supplicant/src/esp_hostap.c @@ -84,7 +84,6 @@ void *hostap_init(void) } hapd->conf->sae_pwe = esp_wifi_get_config_sae_pwe_h2e_internal(WIFI_IF_AP); - auth_conf->sae_pwe = hapd->conf->sae_pwe; auth_conf->wpa_group_rekey = esp_wifi_ap_get_gtk_rekeying_config_internal(); #define MIN_GTK_REKEYING_INTERVAL 60 if (auth_conf->wpa_group_rekey && auth_conf->wpa_group_rekey < MIN_GTK_REKEYING_INTERVAL) { @@ -111,6 +110,9 @@ void *hostap_init(void) } #endif /* CONFIG_IEEE80211W */ if (esp_wifi_wpa3_compatible_mode_enabled(WIFI_IF_AP)) { + //TODO check sae_pwe + hapd->conf->sae_pwe = SAE_PWE_HASH_TO_ELEMENT; + auth_conf->rsn_override_omit_rsnxe = 1; hapd->conf->rsn_override_key_mgmt = WPA_KEY_MGMT_SAE; hapd->conf->rsn_override_pairwise = WPA_CIPHER_CCMP; hapd->conf->rsn_override_mfp = MGMT_FRAME_PROTECTION_REQUIRED; @@ -144,6 +146,7 @@ void *hostap_init(void) auth_conf->rsn_pairwise = WPA_CIPHER_CCMP | WPA_CIPHER_TKIP; } + auth_conf->sae_pwe = hapd->conf->sae_pwe; auth_conf->wpa_key_mgmt = WPA_KEY_MGMT_PSK; auth_conf->eapol_version = EAPOL_VERSION; @@ -200,7 +203,8 @@ void *hostap_init(void) #ifdef CONFIG_SAE if (authmode == WIFI_AUTH_WPA3_PSK || - authmode == WIFI_AUTH_WPA2_WPA3_PSK) { + authmode == WIFI_AUTH_WPA2_WPA3_PSK || + esp_wifi_wpa3_compatible_mode_enabled(WIFI_IF_AP)) { if (wpa3_hostap_auth_init(hapd) != 0) { goto fail; } 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 52ddae0473..1bfdc2ccd2 100644 --- a/components/wpa_supplicant/esp_supplicant/src/esp_wifi_driver.h +++ b/components/wpa_supplicant/esp_supplicant/src/esp_wifi_driver.h @@ -129,7 +129,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 *assoc_req_ie, uint32_t assoc_req_ie_len, bool *pmf_enable, int subtype, uint8_t *pairwise_cipher); + bool (*wpa_ap_join)(void **sm, u8 *bssid, u8 *assoc_req_ie, uint32_t 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); diff --git a/components/wpa_supplicant/esp_supplicant/src/esp_wpa3.c b/components/wpa_supplicant/esp_supplicant/src/esp_wpa3.c index d3436684d1..15f138cac3 100644 --- a/components/wpa_supplicant/esp_supplicant/src/esp_wpa3.c +++ b/components/wpa_supplicant/esp_supplicant/src/esp_wpa3.c @@ -53,7 +53,7 @@ static esp_err_t wpa3_build_sae_commit(u8 *bssid, size_t *sae_msg_len) rsnxe = esp_wifi_sta_get_ie((u8*)bssid, WLAN_EID_RSNX); } if (rsnxe && rsnxe[0] == WLAN_EID_VENDOR_SPECIFIC && - rsnxe[1] >= 1 + 4) { + rsnxe[1] >= 1 + 4) { rsnxe_capa = rsnxe[2 + 4]; } else if (rsnxe && rsnxe[1] >= 1) { rsnxe_capa = rsnxe[2]; 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 827f331df9..f71d0f69b8 100644 --- a/components/wpa_supplicant/esp_supplicant/src/esp_wpa_main.c +++ b/components/wpa_supplicant/esp_supplicant/src/esp_wpa_main.c @@ -389,17 +389,17 @@ static bool hostap_sta_join(void **sta, u8 *bssid, u8 *assoc_req_ie, uint32_t as } if (ieee802_11_parse_elems(assoc_req_ie, assoc_ie_len, &elems, 1) == ParseFailed) { - wpa_printf(MSG_INFO, "Failed to parse assoc req IEs"); - return -1; + wpa_printf(MSG_INFO, "Failed to parse assoc req IEs"); + return -1; } if (elems.rsn_ie) { - elems.rsn_ie = elems.rsn_ie - 2; - elems.rsn_ie_len = elems.rsn_ie_len + 2; + elems.rsn_ie = elems.rsn_ie - 2; + elems.rsn_ie_len = elems.rsn_ie_len + 2; } if (elems.rsnxe) { - elems.rsnxe = elems.rsnxe - 2; - elems.rsnxe_len = elems.rsnxe_len + 2; + elems.rsnxe = elems.rsnxe - 2; + elems.rsnxe_len = elems.rsnxe_len + 2; } if (*sta) { diff --git a/components/wpa_supplicant/src/ap/wpa_auth_ie.c b/components/wpa_supplicant/src/ap/wpa_auth_ie.c index 45f7593110..ed34241985 100644 --- a/components/wpa_supplicant/src/ap/wpa_auth_ie.c +++ b/components/wpa_supplicant/src/ap/wpa_auth_ie.c @@ -506,7 +506,7 @@ int wpa_auth_gen_wpa_ie(struct wpa_authenticator *wpa_auth) return res; pos += res; } - + if ((wpa_auth->conf.wpa & WPA_PROTO_RSN) && (wpa_auth->conf.rsn_override_key_mgmt)) { res = wpa_write_rsnxe_override(&wpa_auth->conf, pos, @@ -661,11 +661,6 @@ wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth, return WPA_INVALID_AKMP; } - if (!key_mgmt) { - wpa_printf( MSG_DEBUG, "Invalid WPA key mgmt (0x%x) from " - MACSTR, data.key_mgmt, MAC2STR(sm->addr)); - return WPA_INVALID_AKMP; - } if (0) { } #ifdef CONFIG_IEEE80211R_AP diff --git a/components/wpa_supplicant/src/common/wpa_common.c b/components/wpa_supplicant/src/common/wpa_common.c index c33d01da96..1aa4db2dca 100644 --- a/components/wpa_supplicant/src/common/wpa_common.c +++ b/components/wpa_supplicant/src/common/wpa_common.c @@ -402,7 +402,12 @@ int wpa_parse_wpa_ie_rsnxe(const u8 *rsnxe_ie, size_t rsnxe_ie_len, if (rsnxe_ie_len < 1) { return -1; } - rsnxe_capa = rsnxe_ie[2]; + if (rsnxe_ie && rsnxe_ie[0] == WLAN_EID_VENDOR_SPECIFIC && + rsnxe_ie[1] >= 1 + 4) { + rsnxe_capa = rsnxe_ie[2 + 4]; + } else { + rsnxe_capa = rsnxe_ie[2]; + } if (sae_pwe == 1 && !(rsnxe_capa & BIT(WLAN_RSNX_CAPAB_SAE_H2E))){ wpa_printf(MSG_ERROR, "SAE H2E required, but not supported by the AP"); return -1; diff --git a/components/wpa_supplicant/src/rsn_supp/wpa.c b/components/wpa_supplicant/src/rsn_supp/wpa.c index f7392a54c6..5161327c8a 100644 --- a/components/wpa_supplicant/src/rsn_supp/wpa.c +++ b/components/wpa_supplicant/src/rsn_supp/wpa.c @@ -2601,7 +2601,7 @@ int wpa_set_bss(uint8_t *macddr, uint8_t *bssid, u8 pairwise_cipher, u8 group_ci esp_wifi_wpa3_compatible_mode_enabled(WIFI_IF_STA)); wpa_sm_set_param(sm, WPA_PARAM_RSN_OVERRIDE, RSN_OVERRIDE_NOT_USED); - ie = esp_wifi_sta_get_ie(bssid, WLAN_EID_RSN); + ie = esp_wifi_sta_get_ie(bssid, WFA_RSNE_OVERRIDE_OUI_TYPE); if (esp_wifi_wpa3_compatible_mode_enabled(WIFI_IF_STA) && ie && ie[0] != WLAN_EID_RSN) { diff --git a/components/wpa_supplicant/src/rsn_supp/wpa_ie.c b/components/wpa_supplicant/src/rsn_supp/wpa_ie.c index f1e056cf81..0edbaad862 100644 --- a/components/wpa_supplicant/src/rsn_supp/wpa_ie.c +++ b/components/wpa_supplicant/src/rsn_supp/wpa_ie.c @@ -43,6 +43,10 @@ int wpa_parse_wpa_ie(const u8 *wpa_ie, size_t wpa_ie_len, wpa_ie[1] >= 4 && WPA_GET_BE32(&wpa_ie[2]) == RSNE_OVERRIDE_IE_VENDOR_TYPE) { return wpa_parse_wpa_ie_rsn(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(wpa_ie, wpa_ie_len, data); } return wpa_parse_wpa_ie_wpa(wpa_ie, wpa_ie_len, data); } From 1b33c9daae3a2d0499a4fa3d649d2a57ae742318 Mon Sep 17 00:00:00 2001 From: Shreyas Sheth Date: Thu, 17 Apr 2025 18:24:26 +0530 Subject: [PATCH 28/33] fix(esp_wifi): Resolve comments for wpa3 compatible mode --- .../esp_wifi/include/esp_wifi_types_generic.h | 2 +- components/wpa_supplicant/src/ap/ap_config.h | 2 +- components/wpa_supplicant/src/ap/wpa_auth_ie.c | 6 ++---- .../wpa_supplicant/src/common/wpa_common.c | 2 +- components/wpa_supplicant/src/rsn_supp/wpa.c | 16 ++++++++-------- .../softAP/main/softap_example_main.c | 2 +- 6 files changed, 14 insertions(+), 16 deletions(-) diff --git a/components/esp_wifi/include/esp_wifi_types_generic.h b/components/esp_wifi/include/esp_wifi_types_generic.h index c82809d8a4..2fb7404771 100644 --- a/components/esp_wifi/include/esp_wifi_types_generic.h +++ b/components/esp_wifi/include/esp_wifi_types_generic.h @@ -535,7 +535,7 @@ typedef struct { wifi_sae_pwe_method_t sae_pwe_h2e; /**< Configuration for SAE PWE derivation method */ uint8_t transition_disable: 1; /**< Whether to enable transition disable feature */ uint8_t sae_ext: 1; /**< Enable SAE EXT feature. SOC_GCMP_SUPPORT is required for this feature. */ - uint8_t wpa3_compatible_mode: 1; /**< Whether to enable wpa3 compatible authmode feature */ + uint8_t wpa3_compatible_mode: 1; /**< Enable WPA3 compatible authmode feature. Note: Enabling this will override the AP configuration's authmode and pairwise_cipher. The AP will operate as a WPA2 access point for legacy stations and as a WPA3 access point for WPA3 compatible stations. */ uint8_t reserved: 5; /**< Reserved for future feature set */ wifi_bss_max_idle_config_t bss_max_idle_cfg; /**< Configuration for bss max idle, effective if CONFIG_WIFI_BSS_MAX_IDLE_SUPPORT is enabled */ uint16_t gtk_rekey_interval; /**< GTK rekeying interval in seconds. If set to 0, GTK rekeying is disabled. Range: 60 ~ 65535 including 0. */ diff --git a/components/wpa_supplicant/src/ap/ap_config.h b/components/wpa_supplicant/src/ap/ap_config.h index 5d848d9421..6ee3d5729c 100644 --- a/components/wpa_supplicant/src/ap/ap_config.h +++ b/components/wpa_supplicant/src/ap/ap_config.h @@ -310,7 +310,7 @@ struct hostapd_bss_config { int *sae_groups; #define SAE_ANTI_CLOGGING_THRESHOLD 2 /* max number of commit msg allowed to queue without anti-clogging token request */ - int rsn_override_omit_rsnxe; + int rsn_override_omit_rsnxe; }; diff --git a/components/wpa_supplicant/src/ap/wpa_auth_ie.c b/components/wpa_supplicant/src/ap/wpa_auth_ie.c index ed34241985..d7ccf86a0c 100644 --- a/components/wpa_supplicant/src/ap/wpa_auth_ie.c +++ b/components/wpa_supplicant/src/ap/wpa_auth_ie.c @@ -457,7 +457,7 @@ static int wpa_write_rsnxe_override(struct wpa_auth_config *conf, u8 *buf, int wpa_auth_gen_wpa_ie(struct wpa_authenticator *wpa_auth) { - u8 *pos, buf[256]; + u8 *pos, buf[128]; int res; pos = buf; @@ -475,8 +475,6 @@ int wpa_auth_gen_wpa_ie(struct wpa_authenticator *wpa_auth) res = wpa_write_rsnxe(&wpa_auth->conf, pos, buf + sizeof(buf) - pos); - res = wpa_write_rsnxe(&wpa_auth->conf, pos, - buf + sizeof(buf) - pos); if (res < 0) return res; pos += res; @@ -507,7 +505,7 @@ int wpa_auth_gen_wpa_ie(struct wpa_authenticator *wpa_auth) pos += res; } - if ((wpa_auth->conf.wpa & WPA_PROTO_RSN) && + if ((wpa_auth->conf.wpa & WPA_PROTO_RSN) && (wpa_auth->conf.rsn_override_key_mgmt)) { res = wpa_write_rsnxe_override(&wpa_auth->conf, pos, buf + sizeof(buf) - pos); diff --git a/components/wpa_supplicant/src/common/wpa_common.c b/components/wpa_supplicant/src/common/wpa_common.c index 1aa4db2dca..b4cc3f58b2 100644 --- a/components/wpa_supplicant/src/common/wpa_common.c +++ b/components/wpa_supplicant/src/common/wpa_common.c @@ -1700,7 +1700,7 @@ int wpa_parse_kde_ies(const u8 *buf, size_t len, struct wpa_eapol_ie_parse *ie) const u8 *pos, *end; int ret = 0; - memset(ie, 0, sizeof(*ie)); + os_memset(ie, 0, sizeof(*ie)); for (pos = buf, end = pos + len; pos + 1 < end; pos += 2 + pos[1]) { if (pos[0] == 0xdd && ((pos == buf + len - 1) || pos[1] == 0)) { diff --git a/components/wpa_supplicant/src/rsn_supp/wpa.c b/components/wpa_supplicant/src/rsn_supp/wpa.c index 5161327c8a..e6363fc3b2 100644 --- a/components/wpa_supplicant/src/rsn_supp/wpa.c +++ b/components/wpa_supplicant/src/rsn_supp/wpa.c @@ -2282,14 +2282,14 @@ int wpa_sm_set_param(struct wpa_sm *sm, enum wpa_sm_conf_params param, return -1; switch (param) { - case WPA_PARAM_RSN_OVERRIDE: - sm->rsn_override = value; - break; - case WPA_PARAM_RSN_OVERRIDE_SUPPORT: - sm->rsn_override_support = value; - break; - default: - break; + case WPA_PARAM_RSN_OVERRIDE: + sm->rsn_override = value; + break; + case WPA_PARAM_RSN_OVERRIDE_SUPPORT: + sm->rsn_override_support = value; + break; + default: + break; } return ret; } diff --git a/examples/wifi/getting_started/softAP/main/softap_example_main.c b/examples/wifi/getting_started/softAP/main/softap_example_main.c index f4baa2052a..3543538693 100644 --- a/examples/wifi/getting_started/softAP/main/softap_example_main.c +++ b/examples/wifi/getting_started/softAP/main/softap_example_main.c @@ -78,7 +78,7 @@ void wifi_init_softap(void) #else /* CONFIG_ESP_WIFI_SOFTAP_SAE_SUPPORT */ .authmode = WIFI_AUTH_WPA2_PSK, #endif - .wpa3_compatible_mode = 1, + .wpa3_compatible_mode = 0, .pmf_cfg = { .required = true, }, From a7f32f5a2a3cd0e08d8ed0706ecf01ebffaec810 Mon Sep 17 00:00:00 2001 From: Shreyas Sheth Date: Tue, 29 Apr 2025 11:38:39 +0530 Subject: [PATCH 29/33] feat(esp_wifi): Add compile flag for wpa3 compatible mode --- components/esp_wifi/Kconfig | 8 +- .../esp_wifi/include/esp_wifi_types_generic.h | 2 +- components/wpa_supplicant/CMakeLists.txt | 3 + .../esp_supplicant/src/esp_hostap.c | 37 ++++-- .../esp_supplicant/src/esp_wifi_driver.h | 2 +- .../esp_supplicant/src/esp_wpa3.c | 14 +- .../esp_supplicant/src/esp_wpa_main.c | 26 +--- components/wpa_supplicant/src/ap/ap_config.c | 7 +- components/wpa_supplicant/src/ap/ap_config.h | 13 +- components/wpa_supplicant/src/ap/wpa_auth.c | 30 +++-- components/wpa_supplicant/src/ap/wpa_auth.h | 12 ++ components/wpa_supplicant/src/ap/wpa_auth_i.h | 4 + .../wpa_supplicant/src/ap/wpa_auth_ie.c | 16 ++- .../src/common/ieee802_11_common.c | 120 +++--------------- .../src/common/ieee802_11_common.h | 6 - .../src/common/ieee802_11_defs.h | 25 ---- .../wpa_supplicant/src/common/wpa_common.c | 2 + .../wpa_supplicant/src/common/wpa_common.h | 3 +- components/wpa_supplicant/src/rsn_supp/wpa.c | 68 +++++++--- components/wpa_supplicant/src/rsn_supp/wpa.h | 6 + .../wpa_supplicant/src/rsn_supp/wpa_i.h | 13 +- .../wpa_supplicant/src/rsn_supp/wpa_ie.c | 14 +- .../softAP/main/softap_example_main.c | 4 +- .../station/main/station_example_main.c | 3 + 24 files changed, 222 insertions(+), 216 deletions(-) diff --git a/components/esp_wifi/Kconfig b/components/esp_wifi/Kconfig index c807cd3a73..48dccc2157 100644 --- a/components/esp_wifi/Kconfig +++ b/components/esp_wifi/Kconfig @@ -1,4 +1,3 @@ - menu "Wi-Fi" visible if (SOC_WIFI_SUPPORTED || SOC_WIRELESS_HOST_SUPPORTED) @@ -340,6 +339,13 @@ menu "Wi-Fi" explicitly configured before attempting connection. Please refer to the Wi-Fi Driver API Guide for details. + config ESP_WIFI_WPA3_COMPATIBLE_SUPPORT + bool "Enable WPA3 Compatible support" + default y + depends on ESP_WIFI_ENABLE_SAE_H2E + help + Select this option to enable WPA3 Compatible support in softap mode. + config ESP_WIFI_SLP_IRAM_OPT bool "WiFi SLP IRAM speed optimization" select PM_SLP_DEFAULT_PARAMS_OPT diff --git a/components/esp_wifi/include/esp_wifi_types_generic.h b/components/esp_wifi/include/esp_wifi_types_generic.h index 2fb7404771..acb21d0b5f 100644 --- a/components/esp_wifi/include/esp_wifi_types_generic.h +++ b/components/esp_wifi/include/esp_wifi_types_generic.h @@ -564,7 +564,7 @@ typedef struct { uint32_t owe_enabled: 1; /**< Whether OWE is enabled for the connection */ uint32_t transition_disable: 1; /**< Whether to enable transition disable feature */ uint32_t wpa3_compatible_mode: 1; /**< Whether to enable wpa3 compatible authmode feature */ - uint32_t reserved1: 25; /**< Reserved for future feature set */ + uint32_t reserved1: 25; /**< Reserved for future feature set */ wifi_sae_pwe_method_t sae_pwe_h2e; /**< Configuration for SAE PWE derivation method */ wifi_sae_pk_mode_t sae_pk_mode; /**< Configuration for SAE-PK (Public Key) Authentication method */ uint8_t failure_retry_cnt; /**< Number of connection retries station will do before moving to next AP. scan_method should be set as WIFI_ALL_CHANNEL_SCAN to use this config. diff --git a/components/wpa_supplicant/CMakeLists.txt b/components/wpa_supplicant/CMakeLists.txt index cafc14a27b..07d0f9566b 100644 --- a/components/wpa_supplicant/CMakeLists.txt +++ b/components/wpa_supplicant/CMakeLists.txt @@ -287,6 +287,9 @@ endif() if(CONFIG_ESP_WIFI_SOFTAP_SAE_SUPPORT) target_compile_definitions(${COMPONENT_LIB} PRIVATE CONFIG_SAE) endif() +if(CONFIG_ESP_WIFI_WPA3_COMPATIBLE_SUPPORT) + target_compile_definitions(${COMPONENT_LIB} PRIVATE CONFIG_WPA3_COMPAT) +endif() if(CONFIG_ESP_WIFI_WPS_STRICT) target_compile_definitions(${COMPONENT_LIB} PRIVATE CONFIG_WPS_STRICT) endif() diff --git a/components/wpa_supplicant/esp_supplicant/src/esp_hostap.c b/components/wpa_supplicant/esp_supplicant/src/esp_hostap.c index df9da91253..4eaaa50af4 100644 --- a/components/wpa_supplicant/esp_supplicant/src/esp_hostap.c +++ b/components/wpa_supplicant/esp_supplicant/src/esp_hostap.c @@ -110,15 +110,19 @@ void *hostap_init(void) } #endif /* CONFIG_IEEE80211W */ if (esp_wifi_wpa3_compatible_mode_enabled(WIFI_IF_AP)) { - //TODO check sae_pwe +#ifdef CONFIG_WPA3_COMPAT hapd->conf->sae_pwe = SAE_PWE_HASH_TO_ELEMENT; auth_conf->rsn_override_omit_rsnxe = 1; + hapd->conf->rsn_override_omit_rsnxe = 1; hapd->conf->rsn_override_key_mgmt = WPA_KEY_MGMT_SAE; hapd->conf->rsn_override_pairwise = WPA_CIPHER_CCMP; hapd->conf->rsn_override_mfp = MGMT_FRAME_PROTECTION_REQUIRED; auth_conf->rsn_override_key_mgmt = WPA_KEY_MGMT_SAE; auth_conf->rsn_override_pairwise = WPA_CIPHER_CCMP; auth_conf->rsn_override_mfp = MGMT_FRAME_PROTECTION_REQUIRED; +#else + wpa_printf(MSG_ERROR, "ESP_WIFI_WPA3_COMPATIBLE_SUPPORT disabled ignoring wpa3_compatible configuration"); +#endif } /* TKIP is compulsory in WPA Mode */ if (auth_conf->wpa == WPA_PROTO_WPA && pairwise_cipher == WIFI_CIPHER_TYPE_CCMP) { @@ -224,7 +228,6 @@ void *hostap_init(void) #ifdef CONFIG_SAE auth_conf->sae_require_mfp = 1; #endif /* CONFIG_SAE */ - auth_conf->rsn_override_omit_rsnxe = 1; hapd->conf->ap_max_inactivity = 5 * 60; hostapd_setup_wpa_psk(hapd->conf); @@ -409,15 +412,21 @@ uint8_t wpa_status_to_reason_code(int status) } } -bool hostap_new_assoc_sta(struct sta_info *sta, uint8_t *bssid, struct ieee802_11_elems elems, - bool *pmf_enable, int subtype, uint8_t *pairwise_cipher, uint8_t *reason) +bool hostap_new_assoc_sta(struct sta_info *sta, uint8_t *bssid, u8 *wpa_ie, + u8 wpa_ie_len, u8 *rsnxe, uint16_t rsnxe_len, + bool *pmf_enable, int subtype, uint8_t *pairwise_cipher, uint8_t *reason, uint8_t *rsn_selection_ie) { struct hostapd_data *hapd = (struct hostapd_data*)esp_wifi_get_hostap_private_internal(); enum wpa_validate_result res = WPA_IE_OK; int status = WLAN_STATUS_SUCCESS; bool omit_rsnxe = false; - if (!sta || !bssid || !elems.rsn_ie) { +#ifdef CONFIG_WPA3_COMPAT + uint8_t rsn_selection_variant_len = 0; + uint8_t *rsn_selection_variant_ie = NULL; +#endif + + if (!sta || !bssid || !wpa_ie) { return false; } if (hapd) { @@ -434,8 +443,16 @@ bool hostap_new_assoc_sta(struct sta_info *sta, uint8_t *bssid, struct ieee802_1 goto send_resp; } - wpa_auth_set_rsn_selection(sta->wpa_sm, elems.rsn_selection, elems.rsn_selection_len); - res = wpa_validate_wpa_ie(hapd->wpa_auth, sta->wpa_sm, elems.rsn_ie, elems.rsn_ie_len, elems.rsnxe, elems.rsnxe_len); +#ifdef CONFIG_WPA3_COMPAT + if (rsn_selection_ie) { + rsn_selection_variant_len = rsn_selection_ie[1] - 4; + rsn_selection_variant_ie = &rsn_selection_ie[6]; + } + + wpa_auth_set_rsn_selection(sta->wpa_sm, rsn_selection_variant_ie, rsn_selection_variant_len); +#endif + + res = wpa_validate_wpa_ie(hapd->wpa_auth, sta->wpa_sm, wpa_ie, wpa_ie_len, rsnxe, rsnxe_len); #ifdef CONFIG_SAE if (wpa_auth_uses_sae(sta->wpa_sm) && sta->sae && sta->sae->state == SAE_ACCEPTED) { @@ -447,13 +464,15 @@ bool hostap_new_assoc_sta(struct sta_info *sta, uint8_t *bssid, struct ieee802_1 status = wpa_res_to_status_code(res); send_resp: - if (!elems.rsnxe) { + if (!rsnxe) { omit_rsnxe = true; } +#ifdef CONFIG_WPA3_COMPAT if (hapd->conf->rsn_override_omit_rsnxe) { - omit_rsnxe = 1; + omit_rsnxe = false; } +#endif if (esp_send_assoc_resp(hapd, bssid, status, omit_rsnxe, subtype) != WLAN_STATUS_SUCCESS) { status = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA; 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 1bfdc2ccd2..874f32c97f 100644 --- a/components/wpa_supplicant/esp_supplicant/src/esp_wifi_driver.h +++ b/components/wpa_supplicant/esp_supplicant/src/esp_wifi_driver.h @@ -129,7 +129,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 *assoc_req_ie, uint32_t 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, uint8_t *rsn_selection_ie); 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); diff --git a/components/wpa_supplicant/esp_supplicant/src/esp_wpa3.c b/components/wpa_supplicant/esp_supplicant/src/esp_wpa3.c index 15f138cac3..c5ef241f94 100644 --- a/components/wpa_supplicant/esp_supplicant/src/esp_wpa3.c +++ b/components/wpa_supplicant/esp_supplicant/src/esp_wpa3.c @@ -46,17 +46,19 @@ static esp_err_t wpa3_build_sae_commit(u8 *bssid, size_t *sae_msg_len) use_pt = 1; } +#ifdef CONFIG_WPA3_COMPAT if (esp_wifi_wpa3_compatible_mode_enabled(WIFI_IF_STA)) { rsnxe = esp_wifi_sta_get_ie((u8*)bssid, WFA_RSNXE_OVERRIDE_OUI_TYPE); + if (rsnxe) { + rsnxe_capa = rsnxe[2 + 4]; + } } +#endif if (!rsnxe) { rsnxe = esp_wifi_sta_get_ie((u8*)bssid, WLAN_EID_RSNX); - } - if (rsnxe && rsnxe[0] == WLAN_EID_VENDOR_SPECIFIC && - rsnxe[1] >= 1 + 4) { - rsnxe_capa = rsnxe[2 + 4]; - } else if (rsnxe && rsnxe[1] >= 1) { - rsnxe_capa = rsnxe[2]; + if (rsnxe) { + rsnxe_capa = rsnxe[2]; + } } #endif /* CONFIG_SAE_H2E */ 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 f71d0f69b8..f8812b780b 100644 --- a/components/wpa_supplicant/esp_supplicant/src/esp_wpa_main.c +++ b/components/wpa_supplicant/esp_supplicant/src/esp_wpa_main.c @@ -377,37 +377,22 @@ 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 *assoc_req_ie, uint32_t assoc_ie_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, uint8_t *rsn_selection_ie) { struct sta_info *sta_info = NULL; struct hostapd_data *hapd = hostapd_get_hapd_data(); uint8_t reason = WLAN_REASON_PREV_AUTH_NOT_VALID; - struct ieee802_11_elems elems; if (!hapd) { goto fail; } - if (ieee802_11_parse_elems(assoc_req_ie, assoc_ie_len, &elems, 1) == ParseFailed) { - wpa_printf(MSG_INFO, "Failed to parse assoc req IEs"); - return -1; - } - - if (elems.rsn_ie) { - elems.rsn_ie = elems.rsn_ie - 2; - elems.rsn_ie_len = elems.rsn_ie_len + 2; - } - if (elems.rsnxe) { - elems.rsnxe = elems.rsnxe - 2; - elems.rsnxe_len = elems.rsnxe_len + 2; - } - if (*sta) { struct sta_info *old_sta = *sta; #ifdef CONFIG_SAE if (old_sta->lock && os_semphr_take(old_sta->lock, 0) != TRUE) { wpa_printf(MSG_INFO, "Ignore assoc request as softap is busy with sae calculation for station "MACSTR, MAC2STR(bssid)); - if (esp_send_assoc_resp(hapd, bssid, WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY, elems.rsnxe ? false : true, subtype) != WLAN_STATUS_SUCCESS) { + if (esp_send_assoc_resp(hapd, bssid, WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY, rsnxe ? false : true, subtype) != WLAN_STATUS_SUCCESS) { goto fail; } return false; @@ -436,7 +421,7 @@ static bool hostap_sta_join(void **sta, u8 *bssid, u8 *assoc_req_ie, uint32_t as #ifdef CONFIG_SAE if (sta_info->lock && os_semphr_take(sta_info->lock, 0) != TRUE) { wpa_printf(MSG_INFO, "Ignore assoc request as softap is busy with sae calculation for station "MACSTR, MAC2STR(bssid)); - if (esp_send_assoc_resp(hapd, bssid, WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY, elems.rsnxe ? false : true, subtype) != WLAN_STATUS_SUCCESS) { + if (esp_send_assoc_resp(hapd, bssid, WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY, rsnxe ? false : true, subtype) != WLAN_STATUS_SUCCESS) { goto fail; } return false; @@ -446,7 +431,7 @@ process_old_sta: #endif /* CONFIG_SAE */ #ifdef CONFIG_WPS_REGISTRAR - if (check_n_add_wps_sta(hapd, sta_info, elems.rsn_ie, elems.rsn_ie_len, pmf_enable, subtype) == 0) { + if (check_n_add_wps_sta(hapd, sta_info, wpa_ie, wpa_ie_len, pmf_enable, subtype) == 0) { if (sta_info->eapol_sm) { goto done; } @@ -454,8 +439,7 @@ process_old_sta: goto fail; } #endif - - if (hostap_new_assoc_sta(sta_info, bssid, elems, pmf_enable, subtype, pairwise_cipher, &reason)) { + if (hostap_new_assoc_sta(sta_info, bssid, wpa_ie, wpa_ie_len, rsnxe, rsnxe_len, pmf_enable, subtype, pairwise_cipher, &reason, rsn_selection_ie)) { goto done; } else { goto fail; diff --git a/components/wpa_supplicant/src/ap/ap_config.c b/components/wpa_supplicant/src/ap/ap_config.c index e4e8b08f62..de1e392ab6 100644 --- a/components/wpa_supplicant/src/ap/ap_config.c +++ b/components/wpa_supplicant/src/ap/ap_config.c @@ -150,8 +150,11 @@ int hostapd_setup_sae_pt(struct hostapd_bss_config *conf) #ifdef CONFIG_SAE_H2E struct hostapd_ssid *ssid = &conf->ssid; if (conf->sae_pwe == SAE_PWE_HUNT_AND_PECK || - !wpa_key_mgmt_sae(conf->wpa_key_mgmt | - conf->rsn_override_key_mgmt)) + !wpa_key_mgmt_sae(conf->wpa_key_mgmt +#ifdef CONFIG_WPA3_COMPAT + | conf->rsn_override_key_mgmt +#endif + )) return 0; /* PT not needed */ sae_deinit_pt(ssid->pt); diff --git a/components/wpa_supplicant/src/ap/ap_config.h b/components/wpa_supplicant/src/ap/ap_config.h index 6ee3d5729c..49aa678c82 100644 --- a/components/wpa_supplicant/src/ap/ap_config.h +++ b/components/wpa_supplicant/src/ap/ap_config.h @@ -200,10 +200,14 @@ struct hostapd_bss_config { int wpa; /* bitfield of WPA_PROTO_WPA, WPA_PROTO_RSN */ int wpa_key_mgmt; +#ifdef CONFIG_WPA3_COMPAT int rsn_override_key_mgmt; +#endif #ifdef CONFIG_IEEE80211W enum mfp_options ieee80211w; +#ifdef CONFIG_WPA3_COMPAT enum mfp_options rsn_override_mfp; +#endif /* dot11AssociationSAQueryMaximumTimeout (in TUs) */ unsigned int assoc_sa_query_max_timeout; /* dot11AssociationSAQueryRetryTimeout (in TUs) */ @@ -222,7 +226,9 @@ struct hostapd_bss_config { int wpa_ptk_rekey; int rsn_pairwise; int rsn_preauth; +#ifdef CONFIG_WPA3_COMPAT int rsn_override_pairwise; +#endif char *rsn_preauth_interfaces; #ifdef CONFIG_IEEE80211R @@ -310,7 +316,9 @@ struct hostapd_bss_config { int *sae_groups; #define SAE_ANTI_CLOGGING_THRESHOLD 2 /* max number of commit msg allowed to queue without anti-clogging token request */ +#ifdef CONFIG_WPA3_COMPAT int rsn_override_omit_rsnxe; +#endif }; @@ -387,8 +395,9 @@ const u8 * hostapd_get_psk(const struct hostapd_bss_config *conf, const u8 *addr, const u8 *prev_psk); 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, struct ieee802_11_elems elems, - bool *pmf_enable, int subtype, uint8_t *pairwise_cipher, uint8_t *reason); +bool hostap_new_assoc_sta(struct sta_info *sta, uint8_t *bssid, u8 *wpa_ie, + u8 wpa_ie_len, u8 *rsnxe, uint16_t rsnxe_len, + bool *pmf_enable, int subtype, uint8_t *pairwise_cipher, uint8_t *reason, uint8_t *rsn_selection_ie); bool wpa_ap_remove(u8* bssid); #endif /* HOSTAPD_CONFIG_H */ diff --git a/components/wpa_supplicant/src/ap/wpa_auth.c b/components/wpa_supplicant/src/ap/wpa_auth.c index 19a73246f9..c7c7212ead 100644 --- a/components/wpa_supplicant/src/ap/wpa_auth.c +++ b/components/wpa_supplicant/src/ap/wpa_auth.c @@ -197,13 +197,16 @@ static inline int wpa_auth_get_seqnum(struct wpa_authenticator *wpa_auth, return -1; } +#ifdef CONFIG_WPA3_COMPAT void wpa_auth_set_rsn_selection(struct wpa_state_machine *sm, const u8 *ie, size_t len) { if (!sm) return; - os_free(sm->rsn_selection); - sm->rsn_selection = NULL; + if (sm->rsn_selection) { + os_free(sm->rsn_selection); + sm->rsn_selection = NULL; + } sm->rsn_selection_len = 0; sm->rsn_override = false; if (ie) { @@ -216,6 +219,7 @@ void wpa_auth_set_rsn_selection(struct wpa_state_machine *sm, const u8 *ie, sm->rsn_selection_len = len; } } +#endif /* fix buf for tx for now */ #define WPA_TX_MSG_BUFF_MAXLEN 200 @@ -522,7 +526,9 @@ static void wpa_free_sta_sm(struct wpa_state_machine *sm) os_free(sm->last_rx_eapol_key); os_free(sm->wpa_ie); os_free(sm->rsnxe); +#ifdef CONFIG_WPA3_COMPAT os_free(sm->rsn_selection); +#endif os_free(sm); } @@ -1764,6 +1770,7 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING) return; } +#ifdef CONFIG_WPA3_COMPAT /* Verify RSN Selection element for RSN overriding */ if (sm->wpa_auth->conf.rsn_override_key_mgmt && ((rsn_is_snonce_cookie(sm->SNonce) && !kde.rsn_selection) || @@ -1789,6 +1796,7 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING) return; } +#endif sm->pending_1_of_4_timeout = 0; eloop_cancel_timeout(resend_eapol_handle, (void*)(sm->index), NULL); @@ -1886,8 +1894,10 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING) struct wpa_group *gsm = sm->group; u8 *wpa_ie; int wpa_ie_len, secure, keyidx, encr = 0; +#ifdef CONFIG_WPA3_COMPAT u8 *wpa_ie_buf3 = NULL; struct wpa_auth_config *conf = &sm->wpa_auth->conf; +#endif SM_ENTRY_MA(WPA_PTK, PTKINITNEGOTIATING, wpa_ptk); sm->TimeoutEvt = FALSE; @@ -1916,6 +1926,7 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING) wpa_ie = wpa_ie + wpa_ie[1] + 2; wpa_ie_len = wpa_ie[1] + 2; } +#ifdef CONFIG_WPA3_COMPAT if (conf->rsn_override_key_mgmt && !rsn_is_snonce_cookie(sm->SNonce)) { u8 *ie; @@ -1948,6 +1959,7 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING) wpa_hexdump(MSG_DEBUG, "EAPOL-Key msg 3/4 IEs after edits", wpa_ie, wpa_ie_len); } +#endif if (sm->wpa == WPA_VERSION_WPA2) { /* WPA2 send GTK in the 4-way handshake */ secure = 1; @@ -1959,7 +1971,7 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING) * of GTK in the BSS. */ if (os_get_random(dummy_gtk, gtk_len) < 0) - return; + goto done; gtk = dummy_gtk; } keyidx = gsm->GN; @@ -1999,8 +2011,8 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING) } #endif /* CONFIG_IEEE80211R_AP */ kde = (u8 *)os_malloc(kde_len); - if (kde == NULL) - return; + if (!kde) + goto done; pos = kde; memcpy(pos, wpa_ie, wpa_ie_len); @@ -2011,8 +2023,7 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING) if (res < 0) { wpa_printf( MSG_ERROR, "FT: Failed to insert " "PMKR1Name into RSN IE in EAPOL-Key data"); - os_free(kde); - return; + goto done; } pos += res; } @@ -2042,8 +2053,7 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING) if (res < 0) { wpa_printf( MSG_ERROR, "FT: Failed to insert FTIE " "into EAPOL-Key Key Data"); - os_free(kde); - return; + goto done; } pos += res; @@ -2070,7 +2080,9 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING) _rsc, sm->ANonce, kde, pos - kde, keyidx, encr); done: os_free(kde); +#ifdef CONFIG_WPA3_COMPAT os_free(wpa_ie_buf3); +#endif } diff --git a/components/wpa_supplicant/src/ap/wpa_auth.h b/components/wpa_supplicant/src/ap/wpa_auth.h index 000f93cbb1..34ae7bc54d 100644 --- a/components/wpa_supplicant/src/ap/wpa_auth.h +++ b/components/wpa_supplicant/src/ap/wpa_auth.h @@ -127,7 +127,9 @@ struct ft_remote_r1kh { struct wpa_auth_config { int wpa; int wpa_key_mgmt; +#ifdef CONFIG_WPA3_COMPAT int rsn_override_key_mgmt; +#endif int wpa_pairwise; int wpa_group; int wpa_group_rekey; @@ -135,7 +137,9 @@ struct wpa_auth_config { int wpa_gmk_rekey; int wpa_ptk_rekey; int rsn_pairwise; +#ifdef CONFIG_WPA3_COMPAT int rsn_override_pairwise; +#endif int rsn_preauth; int eapol_version; int wmm_enabled; @@ -145,7 +149,9 @@ struct wpa_auth_config { int tx_status; #ifdef CONFIG_IEEE80211W enum mfp_options ieee80211w; +#ifdef CONFIG_WPA3_COMPAT enum mfp_options rsn_override_mfp; +#endif #endif /* CONFIG_IEEE80211W */ int group_mgmt_cipher; #ifdef CONFIG_SAE @@ -171,7 +177,9 @@ struct wpa_auth_config { enum sae_pwe sae_pwe; struct rsn_sppamsdu_sup spp_sup; u8 transition_disable; +#ifdef CONFIG_WPA3_COMPAT int rsn_override_omit_rsnxe; +#endif }; typedef enum { @@ -312,8 +320,12 @@ void wpa_auth_set_rsn_selection(struct wpa_state_machine *sm, const u8 *ie, size_t len); static inline bool wpa_auth_pmf_enabled(struct wpa_auth_config *conf) { +#ifdef CONFIG_WPA3_COMPAT return conf->ieee80211w != NO_MGMT_FRAME_PROTECTION || conf->rsn_override_mfp != NO_MGMT_FRAME_PROTECTION; +#else + return conf->ieee80211w != NO_MGMT_FRAME_PROTECTION; +#endif } #endif /* WPA_AUTH_H */ diff --git a/components/wpa_supplicant/src/ap/wpa_auth_i.h b/components/wpa_supplicant/src/ap/wpa_auth_i.h index 745c32d431..c66428b1c3 100644 --- a/components/wpa_supplicant/src/ap/wpa_auth_i.h +++ b/components/wpa_supplicant/src/ap/wpa_auth_i.h @@ -100,8 +100,10 @@ struct wpa_state_machine { size_t wpa_ie_len; u8 *rsnxe; size_t rsnxe_len; +#ifdef CONFIG_WPA3_COMPAT u8 *rsn_selection; size_t rsn_selection_len; +#endif enum { WPA_VERSION_NO_WPA = 0 /* WPA not used */, @@ -112,7 +114,9 @@ struct wpa_state_machine { int wpa_key_mgmt; /* the selected WPA_KEY_MGMT_* */ struct rsn_pmksa_cache_entry *pmksa; +#ifdef CONFIG_WPA3_COMPAT bool rsn_override; +#endif #ifdef CONFIG_IEEE80211R_AP u8 xxkey[PMK_LEN_MAX]; /* PSK or the second 256 bits of MSK, or the diff --git a/components/wpa_supplicant/src/ap/wpa_auth_ie.c b/components/wpa_supplicant/src/ap/wpa_auth_ie.c index d7ccf86a0c..60a92a5cc8 100644 --- a/components/wpa_supplicant/src/ap/wpa_auth_ie.c +++ b/components/wpa_supplicant/src/ap/wpa_auth_ie.c @@ -346,6 +346,7 @@ int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len, +#ifdef CONFIG_WPA3_COMPAT static int wpa_write_rsne_override(struct wpa_auth_config *conf, u8 *buf, size_t len) { @@ -374,6 +375,7 @@ static int wpa_write_rsne_override(struct wpa_auth_config *conf, u8 *buf, return pos - buf; } +#endif static u32 rsnxe_capab(struct wpa_auth_config *conf, int key_mgmt) @@ -419,6 +421,7 @@ int wpa_write_rsnxe(struct wpa_auth_config *conf, u8 *buf, size_t len) return pos - buf; } +#ifdef CONFIG_WPA3_COMPAT static int wpa_write_rsnxe_override(struct wpa_auth_config *conf, u8 *buf, size_t len) { @@ -428,7 +431,6 @@ static int wpa_write_rsnxe_override(struct wpa_auth_config *conf, u8 *buf, capab = rsnxe_capab(conf, conf->rsn_override_key_mgmt); - flen = (capab & 0xff00) ? 2 : 1; if (!capab) return 0; /* no supported extended RSN capabilities */ tmp = capab; @@ -453,6 +455,7 @@ static int wpa_write_rsnxe_override(struct wpa_auth_config *conf, u8 *buf, return pos - buf; } +#endif int wpa_auth_gen_wpa_ie(struct wpa_authenticator *wpa_auth) @@ -469,9 +472,11 @@ int wpa_auth_gen_wpa_ie(struct wpa_authenticator *wpa_auth) return res; pos += res; +#ifdef CONFIG_WPA3_COMPAT if (wpa_auth->conf.rsn_override_omit_rsnxe) res = 0; else +#endif res = wpa_write_rsnxe(&wpa_auth->conf, pos, buf + sizeof(buf) - pos); @@ -496,6 +501,7 @@ int wpa_auth_gen_wpa_ie(struct wpa_authenticator *wpa_auth) pos += res; } +#ifdef CONFIG_WPA3_COMPAT if ((wpa_auth->conf.wpa & WPA_PROTO_RSN) && wpa_auth->conf.rsn_override_key_mgmt) { res = wpa_write_rsne_override(&wpa_auth->conf, @@ -513,6 +519,7 @@ int wpa_auth_gen_wpa_ie(struct wpa_authenticator *wpa_auth) return res; pos += res; } +#endif os_free(wpa_auth->wpa_ie); wpa_auth->wpa_ie = os_malloc(pos - buf); @@ -649,9 +656,11 @@ wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth, return WPA_INVALID_GROUP; } +#ifdef CONFIG_WPA3_COMPAT if (sm->rsn_override) key_mgmt = data.key_mgmt & wpa_auth->conf.rsn_override_key_mgmt; else +#endif key_mgmt = data.key_mgmt & wpa_auth->conf.wpa_key_mgmt; if (!key_mgmt) { wpa_printf(MSG_DEBUG, "Invalid WPA key mgmt (0x%x) from " @@ -686,10 +695,13 @@ wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth, else sm->wpa_key_mgmt = WPA_KEY_MGMT_PSK; +#ifdef CONFIG_WPA3_COMPAT if (version == WPA_PROTO_RSN && sm->rsn_override) ciphers = data.pairwise_cipher & wpa_auth->conf.rsn_override_pairwise; - else if (version == WPA_PROTO_RSN) + else +#endif + if (version == WPA_PROTO_RSN) ciphers = data.pairwise_cipher & wpa_auth->conf.rsn_pairwise; else ciphers = data.pairwise_cipher & wpa_auth->conf.wpa_pairwise; diff --git a/components/wpa_supplicant/src/common/ieee802_11_common.c b/components/wpa_supplicant/src/common/ieee802_11_common.c index 0487dc7f63..6098dd469e 100644 --- a/components/wpa_supplicant/src/common/ieee802_11_common.c +++ b/components/wpa_supplicant/src/common/ieee802_11_common.c @@ -191,7 +191,7 @@ int ieee802_11_parse_candidate_list(const char *pos, u8 *nei_rep, return nei_pos - nei_rep; } -#ifdef CONFIG_WPA3_SAE +#ifdef CONFIG_SAE_PK static int ieee802_11_parse_vendor_specific(const u8 *pos, size_t elen, struct ieee802_11_elems *elems, int show_errors) @@ -212,105 +212,20 @@ static int ieee802_11_parse_vendor_specific(const u8 *pos, size_t elen, oui = WPA_GET_BE24(pos); switch (oui) { - case OUI_MICROSOFT: - /* Microsoft/Wi-Fi information elements are further typed and - * subtyped */ - switch (pos[3]) { - case 1: - break; - case WMM_OUI_TYPE: - /* WMM information element */ - if (elen < 5) { - wpa_printf(MSG_MSGDUMP, "short WMM " - "information element ignored " - "(len=%lu)", - (unsigned long) elen); - return -1; - } - switch (pos[4]) { - case WMM_OUI_SUBTYPE_INFORMATION_ELEMENT: - case WMM_OUI_SUBTYPE_PARAMETER_ELEMENT: - /* - * Share same pointer since only one of these - * is used and they start with same data. - * Length field can be used to distinguish the - * IEs. - */ - break; - case WMM_OUI_SUBTYPE_TSPEC_ELEMENT: - break; - default: - wpa_printf(MSG_EXCESSIVE, "unknown WMM " - "information element ignored " - "(subtype=%d len=%lu)", - pos[4], (unsigned long) elen); - return -1; - } - break; - case 4: - /* Wi-Fi Protected Setup (WPS) IE */ - break; - default: - wpa_printf(MSG_EXCESSIVE, "Unknown Microsoft " - "information element ignored " - "(type=%d len=%lu)", - pos[3], (unsigned long) elen); - return -1; - } - break; case OUI_WFA: switch (pos[3]) { -#ifdef CONFIG_SAE_PK case SAE_PK_OUI_TYPE: elems->sae_pk = pos + 4; elems->sae_pk_len = elen - 4; break; -#endif /* CONFIG_SAE_PK */ - case P2P_OUI_TYPE: - /* Wi-Fi Alliance - P2P IE */ - break; - case WFD_OUI_TYPE: - /* Wi-Fi Alliance - WFD IE */ - break; - case HS20_INDICATION_OUI_TYPE: - /* Hotspot 2.0 */ - break; - case HS20_OSEN_OUI_TYPE: - /* Hotspot 2.0 OSEN */ - break; - case MBO_OUI_TYPE: - /* MBO-OCE */ - break; - case HS20_ROAMING_CONS_SEL_OUI_TYPE: - /* Hotspot 2.0 Roaming Consortium Selection */ - break; - case MULTI_AP_OUI_TYPE: - break; - case OWE_OUI_TYPE: - /* OWE Transition Mode element */ - break; - case DPP_CC_OUI_TYPE: - /* DPP Configurator Connectivity element */ - break; - case WFA_RSNE_OVERRIDE_OUI_TYPE: - elems->rsne_override = pos; - elems->rsne_override_len = elen; - break; - case WFA_RSN_SELECTION_OUI_TYPE: - if (elen < 4 + 1) { - wpa_printf(MSG_DEBUG, - "Too short RSN Selection element ignored"); - return -1; - } - elems->rsn_selection = pos + 4; - elems->rsn_selection_len = elen - 4; - break; default: wpa_printf(MSG_EXCESSIVE, "Unknown WFA " "information element ignored " "(type=%d len=%lu)", pos[3], (unsigned long) elen); - return -1; + //TODO discuss if to ignore it + break; + //return -1; } break; default: @@ -318,12 +233,14 @@ static int ieee802_11_parse_vendor_specific(const u8 *pos, size_t elen, "information element ignored (vendor OUI " "%02x:%02x:%02x len=%lu)", pos[0], pos[1], pos[2], (unsigned long) elen); - return -1; + //TODO discuss if to ignore it + break; + //return -1; } return 0; } -#endif /* CONFIG_WPA3_SAE */ +#endif /* CONFIG_SAE_PK */ #ifdef CONFIG_SAE_PK static int ieee802_11_parse_extension(const u8 *pos, size_t elen, @@ -357,13 +274,16 @@ static int ieee802_11_parse_extension(const u8 *pos, size_t elen, wpa_printf(MSG_EXCESSIVE, "IEEE 802.11 element parsing ignored unknown element extension (ext_id=%u elen=%u)", ext_id, (unsigned int) elen); - return -1; + //TODO discuss if to ignore it + break; + //return -1; } return 0; } #endif /* CONFIG_SAE_PK */ +#if defined(CONFIG_RRM) || defined(CONFIG_WMM) || defined(CONFIG_SAE_PK) static ParseRes __ieee802_11_parse_elems(const u8 *start, size_t len, struct ieee802_11_elems *elems, int show_errors) @@ -391,8 +311,6 @@ static ParseRes __ieee802_11_parse_elems(const u8 *start, size_t len, unknown++; } break; -#endif /*CONFIG_SAE_PK*/ -#ifdef CONFIG_WPA3_SAE case WLAN_EID_VENDOR_SPECIFIC: if (ieee802_11_parse_vendor_specific(pos, elen, elems, @@ -400,15 +318,7 @@ static ParseRes __ieee802_11_parse_elems(const u8 *start, size_t len, unknown++; } break; -#endif /* CONFIG_WPA3_SAE */ - case WLAN_EID_RSN: - elems->rsn_ie = pos; - elems->rsn_ie_len = elen; - break; - case WLAN_EID_RSNX: - elems->rsnxe = pos; - elems->rsnxe_len = elen; - break; +#endif /*CONFIG_SAE_PK*/ #ifdef CONFIG_WNM case WLAN_EID_EXT_CAPAB: /* extended caps can go beyond 8 octacts but we aren't using them now */ @@ -426,6 +336,8 @@ static ParseRes __ieee802_11_parse_elems(const u8 *start, size_t len, return ParseOK; } +#endif + /** * ieee802_11_parse_elems - Parse information elements in management frames * @start: Pointer to the start of IEs @@ -434,12 +346,14 @@ static ParseRes __ieee802_11_parse_elems(const u8 *start, size_t len, * @show_errors: Whether to show parsing errors in debug log * Returns: Parsing result */ +#if defined(CONFIG_RRM) || defined(CONFIG_WMM) || defined(CONFIG_SAE_PK) ParseRes ieee802_11_parse_elems(const u8 *start, size_t len, struct ieee802_11_elems *elems, int show_errors) { os_memset(elems, 0, sizeof(*elems)); return __ieee802_11_parse_elems(start, len, elems, show_errors); } +#endif struct wpabuf * ieee802_11_vendor_ie_concat(const u8 *ies, size_t ies_len, u32 oui_type) diff --git a/components/wpa_supplicant/src/common/ieee802_11_common.h b/components/wpa_supplicant/src/common/ieee802_11_common.h index 50ff9223ad..43e5a0b43b 100644 --- a/components/wpa_supplicant/src/common/ieee802_11_common.h +++ b/components/wpa_supplicant/src/common/ieee802_11_common.h @@ -70,12 +70,6 @@ struct ieee802_11_elems { const u8 *sae_pk; u8 sae_pk_len; #endif -#ifdef CONFIG_WPA3_SAE - const u8 *rsne_override; - size_t rsne_override_len; - const u8 *rsn_selection; - size_t rsn_selection_len; -#endif }; typedef enum { ParseOK = 0, ParseUnknown = 1, ParseFailed = -1 } ParseRes; diff --git a/components/wpa_supplicant/src/common/ieee802_11_defs.h b/components/wpa_supplicant/src/common/ieee802_11_defs.h index 019a929fbf..e8adaeef0c 100644 --- a/components/wpa_supplicant/src/common/ieee802_11_defs.h +++ b/components/wpa_supplicant/src/common/ieee802_11_defs.h @@ -303,35 +303,12 @@ #define DPP_OUI_TYPE 0x1A #define OUI_WFA 0x506f9a #define WFA_RSNE_OVERRIDE_OUI_TYPE 0x29 -#define WFA_RSNE_OVERRIDE_2_OUI_TYPE 0x2a #define WFA_RSNXE_OVERRIDE_OUI_TYPE 0x2b #define WFA_RSN_SELECTION_OUI_TYPE 0x2c #define RSNE_OVERRIDE_IE_VENDOR_TYPE 0x506f9a29 -#define RSNE_OVERRIDE_2_IE_VENDOR_TYPE 0x506f9a2a #define RSNXE_OVERRIDE_IE_VENDOR_TYPE 0x506f9a2b #define RSN_SELECTION_IE_VENDOR_TYPE 0x506f9a2c -#define WFD_OUI_TYPE 10 -#define NAN_OUI_TYPE 0x13 -#define MBO_OUI_TYPE 22 -#define OWE_OUI_TYPE 28 -#define MULTI_AP_OUI_TYPE 0x1B -#define DPP_CC_OUI_TYPE 0x1e -#define SAE_PK_OUI_TYPE 0x1f -#define QM_IE_OUI_TYPE 0x22 -#define WFA_CAPA_OUI_TYPE 0x23 - -#define P2P_OUI_TYPE 9 -#define HS20_INDICATION_OUI_TYPE 16 -#define HS20_OSEN_OUI_TYPE 18 -#define HS20_ROAMING_CONS_SEL_OUI_TYPE 29 - -#define WMM_OUI_TYPE 2 -#define WMM_OUI_SUBTYPE_INFORMATION_ELEMENT 0 -#define WMM_OUI_SUBTYPE_PARAMETER_ELEMENT 1 -#define WMM_OUI_SUBTYPE_TSPEC_ELEMENT 2 -#define WMM_VERSION 1 - #ifdef _MSC_VER #pragma pack(push, 1) #endif /* _MSC_VER */ @@ -590,8 +567,6 @@ struct ieee80211_ht_operation { /* 2 - Reserved */ #define WMM_TSPEC_DIRECTION_BI_DIRECTIONAL 3 -#define OUI_MICROSOFT 0x0050f2 /* Microsoft (also used in Wi-Fi specs) - * 00:50:F2 */ #define MBO_IE_VENDOR_TYPE 0x506f9a16 #define OSEN_IE_VENDOR_TYPE 0x506f9a12 #define SAE_PK_IE_VENDOR_TYPE 0x506f9a1f diff --git a/components/wpa_supplicant/src/common/wpa_common.c b/components/wpa_supplicant/src/common/wpa_common.c index b4cc3f58b2..4cd49d3d2f 100644 --- a/components/wpa_supplicant/src/common/wpa_common.c +++ b/components/wpa_supplicant/src/common/wpa_common.c @@ -1659,6 +1659,7 @@ static int wpa_parse_generic(const u8 *pos, const u8 *end, return 0; } +#ifdef CONFIG_WPA3_COMPAT if (selector == RSNE_OVERRIDE_IE_VENDOR_TYPE) { ie->rsne_override = pos; ie->rsne_override_len = dlen; @@ -1685,6 +1686,7 @@ static int wpa_parse_generic(const u8 *pos, const u8 *end, ie->rsn_selection, ie->rsn_selection_len); return 0; } +#endif return 2; } diff --git a/components/wpa_supplicant/src/common/wpa_common.h b/components/wpa_supplicant/src/common/wpa_common.h index 92d7abf8c3..5069ec7730 100644 --- a/components/wpa_supplicant/src/common/wpa_common.h +++ b/components/wpa_supplicant/src/common/wpa_common.h @@ -472,13 +472,14 @@ struct wpa_eapol_ie_parse { size_t transition_disable_len; const u8 *rsnxe; size_t rsnxe_len; +#ifdef CONFIG_WPA3_COMPAT const u8 *rsn_selection; size_t rsn_selection_len; const u8 *rsne_override; size_t rsne_override_len; const u8 *rsnxe_override; size_t rsnxe_override_len; - +#endif }; int wpa_parse_kde_ies(const u8 *buf, size_t len, struct wpa_eapol_ie_parse *ie); static inline int wpa_supplicant_parse_ies(const u8 *buf, size_t len, diff --git a/components/wpa_supplicant/src/rsn_supp/wpa.c b/components/wpa_supplicant/src/rsn_supp/wpa.c index e6363fc3b2..d2a8d7140f 100644 --- a/components/wpa_supplicant/src/rsn_supp/wpa.c +++ b/components/wpa_supplicant/src/rsn_supp/wpa.c @@ -536,7 +536,10 @@ int wpa_supplicant_send_2_of_4(struct wpa_sm *sm, const unsigned char *dst, size_t mic_len, hdrlen, rlen; struct wpa_eapol_key *reply; struct wpa_eapol_key_192 *reply192; - u8 *rsn_ie_buf = NULL, *buf2 = NULL; + u8 *rsn_ie_buf = NULL; +#ifdef CONFIG_WPA3_COMPAT + u8 *buf2 = NULL; +#endif u8 *rbuf, *key_mic; if (wpa_ie == NULL) { @@ -582,6 +585,7 @@ int wpa_supplicant_send_2_of_4(struct wpa_sm *sm, const unsigned char *dst, wpa_ie = rsn_ie_buf; } #endif /* CONFIG_IEEE80211R */ +#ifdef CONFIG_WPA3_COMPAT if (sm->rsn_override != RSN_OVERRIDE_NOT_USED) { u8 *pos; @@ -610,7 +614,7 @@ int wpa_supplicant_send_2_of_4(struct wpa_sm *sm, const unsigned char *dst, wpa_ie_len += 2 + 4 + 1; } - +#endif wpa_hexdump(MSG_MSGDUMP, "WPA: WPA IE for msg 2/4\n", wpa_ie, wpa_ie_len); mic_len = wpa_mic_len(sm->key_mgmt, sm->pmk_len); @@ -620,7 +624,9 @@ int wpa_supplicant_send_2_of_4(struct wpa_sm *sm, const unsigned char *dst, &rlen, (void *) &reply); if (rbuf == NULL) { os_free(rsn_ie_buf); +#ifdef CONFIG_WPA3_COMPAT os_free(buf2); +#endif return -1; } reply192 = (struct wpa_eapol_key_192 *) reply; @@ -647,7 +653,9 @@ int wpa_supplicant_send_2_of_4(struct wpa_sm *sm, const unsigned char *dst, } os_free(rsn_ie_buf); +#ifdef CONFIG_WPA3_COMPAT os_free(buf2); +#endif os_memcpy(reply->key_nonce, nonce, WPA_NONCE_LEN); wpa_printf(MSG_DEBUG, "WPA Send EAPOL-Key 2/4"); @@ -733,8 +741,10 @@ void wpa_supplicant_process_1_of_4(struct wpa_sm *sm, wpa_printf(MSG_DEBUG, "WPA: Failed to get random data for SNonce"); goto failed; } +#ifdef CONFIG_WPA3_COMPAT if (wpa_sm_rsn_overriding_supported(sm)) rsn_set_snonce_cookie(sm->snonce); +#endif sm->renew_snonce = 0; wpa_hexdump(MSG_DEBUG, "WPA: Renewed SNonce", sm->snonce, WPA_NONCE_LEN); @@ -1215,6 +1225,7 @@ static int wpa_supplicant_validate_ie(struct wpa_sm *sm, return -1; } +#ifdef CONFIG_WPA3_COMPAT if (sm->proto == WPA_PROTO_RSN && wpa_sm_rsn_overriding_supported(sm)) { if ((sm->ap_rsne_override && !ie->rsne_override) || (!sm->ap_rsne_override && ie->rsne_override) || @@ -1256,6 +1267,7 @@ static int wpa_supplicant_validate_ie(struct wpa_sm *sm, return -1; } } +#endif return 0; } @@ -1349,10 +1361,19 @@ static void wpa_supplicant_process_3_of_4(struct wpa_sm *sm, key_info = WPA_GET_BE16(key->key_info); - if (wpa_supplicant_parse_ies(key_data, key_data_len, &ie) < 0) + if (wpa_supplicant_parse_ies(key_data, key_data_len, &ie) < 0) { goto failed; - if (wpa_supplicant_validate_ie(sm, sm->bssid, &ie) < 0) + } + if (wpa_supplicant_validate_ie(sm, sm->bssid, &ie) < 0) { goto failed; + } + + if (os_memcmp(sm->anonce, key->key_nonce, WPA_NONCE_LEN) != 0) { + wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, + "WPA: ANonce from message 1 of 4-Way Handshake differs from 3 of 4-Way Handshake - drop packet (src=" + MACSTR ")", MAC2STR(sm->bssid)); + goto failed; + } if (ie.gtk && !(key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) { wpa_printf(MSG_DEBUG, "WPA: GTK IE in unencrypted key data"); @@ -2258,10 +2279,12 @@ void wpa_sm_deinit(void) sm->ap_rsn_ie = NULL; os_free(sm->ap_rsnxe); sm->ap_rsnxe = NULL; +#ifdef CONFIG_WPA3_COMPAT os_free(sm->ap_rsne_override); sm->ap_rsne_override = NULL; os_free(sm->ap_rsnxe_override); sm->ap_rsnxe_override = NULL; +#endif wpa_sm_drop_sa(sm); memset(sm, 0, sizeof(*sm)); } @@ -2273,6 +2296,7 @@ void wpa_sm_deinit(void) * @value: Parameter value * Returns: 0 on success, -1 on failure */ +#ifdef CONFIG_WPA3_COMPAT int wpa_sm_set_param(struct wpa_sm *sm, enum wpa_sm_conf_params param, unsigned int value) { @@ -2293,18 +2317,21 @@ int wpa_sm_set_param(struct wpa_sm *sm, enum wpa_sm_conf_params param, } return ret; } +#endif +#ifdef CONFIG_WPA3_COMPAT static const u8 * wpa_sm_get_ap_rsne(struct wpa_sm *sm, size_t *len) { if (sm->rsn_override == RSN_OVERRIDE_RSNE_OVERRIDE) { *len = sm->ap_rsne_override_len; return sm->ap_rsne_override; } - *len = sm->ap_rsn_ie_len; return sm->ap_rsn_ie; } +#endif +#ifdef CONFIG_WPA3_COMPAT bool wpa_sm_rsn_overriding_supported(struct wpa_sm *sm) { const u8 *rsne; @@ -2314,6 +2341,7 @@ bool wpa_sm_rsn_overriding_supported(struct wpa_sm *sm) return sm->rsn_override_support && rsne; } +#endif #ifdef ESP_SUPPLICANT /** @@ -2446,13 +2474,13 @@ void wpa_set_pmk(uint8_t *pmk, size_t pmk_length, const u8 *pmkid, bool cache_pm } } -int wpa_set_bss(uint8_t *macddr, uint8_t *bssid, u8 pairwise_cipher, u8 group_cipher, char *passphrase, u8 *ssid, size_t ssid_len) +int wpa_set_bss(uint8_t *macddr, uint8_t *bssid, uint8_t pairwise_cipher, uint8_t group_cipher, char *passphrase, uint8_t *ssid, int ssid_len) { int res = 0; struct wpa_sm *sm = &gWpaSm; bool use_pmk_cache = !esp_wifi_skip_supp_pmkcaching(); - u8 assoc_ie[128]; - uint8_t assoc_ie_len = sizeof(assoc_ie); + uint8_t assoc_ie[128]; + uint16_t assoc_ie_len = sizeof(assoc_ie); bool reassoc_same_ess = false; int try_opportunistic = 0; const u8 *ie = NULL; @@ -2579,12 +2607,13 @@ int wpa_set_bss(uint8_t *macddr, uint8_t *bssid, u8 pairwise_cipher, u8 group_ci wpa_sm_set_ap_rsn_ie(sm, ie, ie ? (ie[1] + 2) : 0); ie = esp_wifi_sta_get_ie(bssid, WLAN_EID_RSNX); wpa_sm_set_ap_rsnxe(sm, ie, ie ? (ie[1] + 2) : 0); - if (esp_wifi_wpa3_compatible_mode_enabled(WIFI_IF_STA)) { - ie = esp_wifi_sta_get_ie(bssid, WFA_RSNE_OVERRIDE_OUI_TYPE); - wpa_sm_set_ap_rsne_override(sm, ie, ie ? (ie[1] + 2) : 0); - ie = esp_wifi_sta_get_ie(bssid, WFA_RSNXE_OVERRIDE_OUI_TYPE); - wpa_sm_set_ap_rsnxe_override(sm, ie, ie ? (ie[1] + 2) : 0); - } + +#ifdef CONFIG_WPA3_COMPAT + ie = esp_wifi_sta_get_ie(bssid, WFA_RSNE_OVERRIDE_OUI_TYPE); + wpa_sm_set_ap_rsne_override(sm, ie, ie ? (ie[1] + 2) : 0); + ie = esp_wifi_sta_get_ie(bssid, WFA_RSNXE_OVERRIDE_OUI_TYPE); + wpa_sm_set_ap_rsnxe_override(sm, ie, ie ? (ie[1] + 2) : 0); +#endif pos = assoc_ie; res = wpa_gen_rsnxe(sm, pos, assoc_ie_len); @@ -2597,14 +2626,15 @@ int wpa_set_bss(uint8_t *macddr, uint8_t *bssid, u8 pairwise_cipher, u8 group_ci return -1; } pos += assoc_ie_len; + +#ifdef CONFIG_WPA3_COMPAT wpa_sm_set_param(sm, WPA_PARAM_RSN_OVERRIDE_SUPPORT, esp_wifi_wpa3_compatible_mode_enabled(WIFI_IF_STA)); wpa_sm_set_param(sm, WPA_PARAM_RSN_OVERRIDE, RSN_OVERRIDE_NOT_USED); ie = esp_wifi_sta_get_ie(bssid, WFA_RSNE_OVERRIDE_OUI_TYPE); - if (esp_wifi_wpa3_compatible_mode_enabled(WIFI_IF_STA) && - ie && ie[0] != WLAN_EID_RSN) { + if (esp_wifi_wpa3_compatible_mode_enabled(WIFI_IF_STA) && ie) { enum rsn_selection_variant variant = RSN_SELECTION_RSNE; if (ie && ie[0] == WLAN_EID_VENDOR_SPECIFIC && ie[1] >= 4) { @@ -2626,6 +2656,8 @@ int wpa_set_bss(uint8_t *macddr, uint8_t *bssid, u8 pairwise_cipher, u8 group_ci *pos = variant; assoc_ie_len += 2 + 4 + 1; } +#endif + wpa_hexdump(MSG_DEBUG, "WPA: ASSOC IE LEN", assoc_ie, assoc_ie_len); esp_set_assoc_ie(bssid, assoc_ie, assoc_ie_len, true); @@ -2984,6 +3016,7 @@ int wpa_sm_set_ap_rsnxe(struct wpa_sm *sm, const u8 *ie, size_t len) } +#ifdef CONFIG_WPA3_COMPAT int wpa_sm_set_ap_rsne_override(struct wpa_sm *sm, const u8 *ie, size_t len) { if (!sm) @@ -3007,8 +3040,10 @@ int wpa_sm_set_ap_rsne_override(struct wpa_sm *sm, const u8 *ie, size_t len) return 0; } +#endif +#ifdef CONFIG_WPA3_COMPAT int wpa_sm_set_ap_rsnxe_override(struct wpa_sm *sm, const u8 *ie, size_t len) { if (!sm) @@ -3032,6 +3067,7 @@ int wpa_sm_set_ap_rsnxe_override(struct wpa_sm *sm, const u8 *ie, size_t len) return 0; } +#endif int wpa_sm_set_assoc_rsnxe(struct wpa_sm *sm, const u8 *ie, size_t len) diff --git a/components/wpa_supplicant/src/rsn_supp/wpa.h b/components/wpa_supplicant/src/rsn_supp/wpa.h index 3968184ee1..bff1c19216 100644 --- a/components/wpa_supplicant/src/rsn_supp/wpa.h +++ b/components/wpa_supplicant/src/rsn_supp/wpa.h @@ -35,10 +35,12 @@ struct l2_ethhdr { be16 h_proto; } STRUCT_PACKED; +#ifdef CONFIG_WPA3_COMPAT enum wpa_sm_conf_params { WPA_PARAM_RSN_OVERRIDE, WPA_PARAM_RSN_OVERRIDE_SUPPORT, }; +#endif void wpa_sm_set_state(enum wpa_states state); @@ -62,16 +64,20 @@ int wpa_sm_set_ap_rsn_ie(struct wpa_sm *sm, const u8 *ie, size_t len); int wpa_sm_set_ap_rsnxe(struct wpa_sm *sm, const u8 *ie, size_t len); +#ifdef CONFIG_WPA3_COMPAT int wpa_sm_set_ap_rsne_override(struct wpa_sm *sm, const u8 *ie, size_t len); int wpa_sm_set_ap_rsnxe_override(struct wpa_sm *sm, const u8 *ie, size_t len); +#endif int wpa_sm_set_assoc_rsnxe(struct wpa_sm *sm, const u8 *ie, size_t len); void wpa_sm_drop_sa(struct wpa_sm *sm); +#ifdef CONFIG_WPA3_COMPAT int wpa_sm_set_param(struct wpa_sm *sm, enum wpa_sm_conf_params param, unsigned int value); +#endif #ifdef CONFIG_IEEE80211R int wpa_sm_set_ft_params(struct wpa_sm *sm, const u8 *ies, size_t ies_len); diff --git a/components/wpa_supplicant/src/rsn_supp/wpa_i.h b/components/wpa_supplicant/src/rsn_supp/wpa_i.h index 1f272ea262..42fcbc2e49 100644 --- a/components/wpa_supplicant/src/rsn_supp/wpa_i.h +++ b/components/wpa_supplicant/src/rsn_supp/wpa_i.h @@ -22,12 +22,13 @@ struct install_key { u8 key[32]; }; +#ifdef CONFIG_WPA3_COMPAT enum wpa_rsn_override { RSN_OVERRIDE_NOT_USED, RSN_OVERRIDE_RSNE, RSN_OVERRIDE_RSNE_OVERRIDE, }; - +#endif /** * struct wpa_sm - Internal WPA state machine data */ @@ -82,8 +83,10 @@ struct wpa_sm { u8 *ap_wpa_ie, *ap_rsn_ie, *ap_rsnxe; size_t ap_wpa_ie_len, ap_rsn_ie_len, ap_rsnxe_len; +#ifdef CONFIG_WPA3_COMPAT u8 *ap_rsne_override, *ap_rsnxe_override; size_t ap_rsne_override_len, ap_rsnxe_override_len; +#endif bool key_install; @@ -127,9 +130,10 @@ struct wpa_sm { #endif /* CONFIG_OWE_STA */ int (*wpa_sm_wps_disable)(void); esp_err_t (*wpa_sm_eap_disable)(void); - +#ifdef CONFIG_WPA3_COMPAT bool rsn_override_support; enum wpa_rsn_override rsn_override; +#endif }; /** @@ -215,12 +219,13 @@ void eapol_txcb(uint8_t *eapol_payload, size_t len, bool tx_failure); void wpa_set_profile(u32 wpa_proto, u8 auth_mode); -int wpa_set_bss(uint8_t *macddr, uint8_t *bssid, u8 pairwise_cipher, u8 group_cipher, char *passphrase, u8 *ssid, size_t ssid_len); +int wpa_set_bss(uint8_t *macddr, uint8_t *bssid, uint8_t pairwise_cipher, uint8_t group_cipher, char *passphrase, uint8_t *ssid, int ssid_len); int wpa_sm_rx_eapol(u8 *src_addr, u8 *buf, u32 len); int wpa_derive_ptk_ft(struct wpa_sm *sm, const unsigned char *src_addr, const struct wpa_eapol_key *key, struct wpa_ptk *ptk); - +#ifdef CONFIG_WPA3_COMPAT bool wpa_sm_rsn_overriding_supported(struct wpa_sm *sm); +#endif #endif /* WPA_I_H */ diff --git a/components/wpa_supplicant/src/rsn_supp/wpa_ie.c b/components/wpa_supplicant/src/rsn_supp/wpa_ie.c index 0edbaad862..8bafca9653 100644 --- a/components/wpa_supplicant/src/rsn_supp/wpa_ie.c +++ b/components/wpa_supplicant/src/rsn_supp/wpa_ie.c @@ -39,6 +39,7 @@ int wpa_parse_wpa_ie(const u8 *wpa_ie, size_t wpa_ie_len, return wpa_parse_wpa_ie_rsnxe(wpa_ie, wpa_ie_len, data); } else if (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 && wpa_ie[1] >= 4 && WPA_GET_BE32(&wpa_ie[2]) == RSNE_OVERRIDE_IE_VENDOR_TYPE) { @@ -47,7 +48,9 @@ int wpa_parse_wpa_ie(const u8 *wpa_ie, size_t wpa_ie_len, wpa_ie[1] >= 4 && WPA_GET_BE32(&wpa_ie[2]) == RSNXE_OVERRIDE_IE_VENDOR_TYPE) { return wpa_parse_wpa_ie_rsnxe(wpa_ie, wpa_ie_len, data); +#endif } + return wpa_parse_wpa_ie_wpa(wpa_ie, wpa_ie_len, data); } @@ -304,7 +307,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) { u8 *pos = rsnxe; - u16 capab = 0, tmp; + u32 capab = 0, tmp; size_t flen; if (wpa_key_mgmt_sae(sm->key_mgmt) && @@ -333,12 +336,11 @@ int wpa_gen_rsnxe(struct wpa_sm *sm, u8 *rsnxe, size_t rsnxe_len) *pos++ = WLAN_EID_RSNX; *pos++ = flen; - *pos++ = capab & 0x00ff; - capab >>= 8; - if (capab) - *pos++ = capab; + while (capab) { + *pos++ = capab & 0xff; + capab >>= 8; + } return pos - rsnxe; } - #endif // ESP_SUPPLICANT diff --git a/examples/wifi/getting_started/softAP/main/softap_example_main.c b/examples/wifi/getting_started/softAP/main/softap_example_main.c index 3543538693..a19978070b 100644 --- a/examples/wifi/getting_started/softAP/main/softap_example_main.c +++ b/examples/wifi/getting_started/softAP/main/softap_example_main.c @@ -78,7 +78,9 @@ void wifi_init_softap(void) #else /* CONFIG_ESP_WIFI_SOFTAP_SAE_SUPPORT */ .authmode = WIFI_AUTH_WPA2_PSK, #endif - .wpa3_compatible_mode = 0, +#ifdef CONFIG_ESP_WIFI_WPA3_COMPATIBLE_SUPPORT + .wpa3_compatible_mode = 1, +#endif .pmf_cfg = { .required = true, }, diff --git a/examples/wifi/getting_started/station/main/station_example_main.c b/examples/wifi/getting_started/station/main/station_example_main.c index d5ed5eb1a1..45c9a14a93 100644 --- a/examples/wifi/getting_started/station/main/station_example_main.c +++ b/examples/wifi/getting_started/station/main/station_example_main.c @@ -129,6 +129,9 @@ void wifi_init_sta(void) .threshold.authmode = ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD, .sae_pwe_h2e = ESP_WIFI_SAE_MODE, .sae_h2e_identifier = EXAMPLE_H2E_IDENTIFIER, +#ifdef CONFIG_ESP_WIFI_WPA3_COMPATIBLE_SUPPORT + .wpa3_compatible_mode = 1, +#endif }, }; ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA) ); From 3eca66cc0d02e964fcc74994ad4eb4b618042b41 Mon Sep 17 00:00:00 2001 From: Shreyas Sheth Date: Wed, 17 Sep 2025 17:26:25 +0530 Subject: [PATCH 30/33] fix(esp_wifi): Resolve comments for wpa3_compatible_mode --- components/esp_wifi/include/esp_wifi_types_generic.h | 2 +- .../wpa_supplicant/esp_supplicant/src/esp_hostap.c | 11 ++++++----- .../esp_supplicant/src/esp_wifi_driver.h | 3 +-- .../wpa_supplicant/esp_supplicant/src/esp_wpa3.c | 2 +- components/wpa_supplicant/src/rsn_supp/wpa.c | 4 ++-- .../getting_started/softAP/main/softap_example_main.c | 5 ++--- .../station/main/station_example_main.c | 2 +- 7 files changed, 14 insertions(+), 15 deletions(-) diff --git a/components/esp_wifi/include/esp_wifi_types_generic.h b/components/esp_wifi/include/esp_wifi_types_generic.h index acb21d0b5f..755a85925a 100644 --- a/components/esp_wifi/include/esp_wifi_types_generic.h +++ b/components/esp_wifi/include/esp_wifi_types_generic.h @@ -563,7 +563,7 @@ typedef struct { uint32_t ft_enabled: 1; /**< Whether FT is enabled for the connection */ uint32_t owe_enabled: 1; /**< Whether OWE is enabled for the connection */ uint32_t transition_disable: 1; /**< Whether to enable transition disable feature */ - uint32_t wpa3_compatible_mode: 1; /**< Whether to enable wpa3 compatible authmode feature */ + uint32_t disable_wpa3_compatible_mode: 1; /**< Whether to enable wpa3 compatible authmode feature */ uint32_t reserved1: 25; /**< Reserved for future feature set */ wifi_sae_pwe_method_t sae_pwe_h2e; /**< Configuration for SAE PWE derivation method */ wifi_sae_pk_mode_t sae_pk_mode; /**< Configuration for SAE-PK (Public Key) Authentication method */ diff --git a/components/wpa_supplicant/esp_supplicant/src/esp_hostap.c b/components/wpa_supplicant/esp_supplicant/src/esp_hostap.c index 4eaaa50af4..b2eb14c324 100644 --- a/components/wpa_supplicant/esp_supplicant/src/esp_hostap.c +++ b/components/wpa_supplicant/esp_supplicant/src/esp_hostap.c @@ -109,7 +109,7 @@ void *hostap_init(void) } } #endif /* CONFIG_IEEE80211W */ - if (esp_wifi_wpa3_compatible_mode_enabled(WIFI_IF_AP)) { + if (esp_wifi_is_wpa3_compatible_mode_enabled(WIFI_IF_AP)) { #ifdef CONFIG_WPA3_COMPAT hapd->conf->sae_pwe = SAE_PWE_HASH_TO_ELEMENT; auth_conf->rsn_override_omit_rsnxe = 1; @@ -121,7 +121,7 @@ void *hostap_init(void) auth_conf->rsn_override_pairwise = WPA_CIPHER_CCMP; auth_conf->rsn_override_mfp = MGMT_FRAME_PROTECTION_REQUIRED; #else - wpa_printf(MSG_ERROR, "ESP_WIFI_WPA3_COMPATIBLE_SUPPORT disabled ignoring wpa3_compatible configuration"); + wpa_printf(MSG_ERROR, "ESP_WIFI_WPA3_COMPATIBLE_SUPPORT disabled, ignoring wpa3_compatible configuration"); #endif } /* TKIP is compulsory in WPA Mode */ @@ -208,7 +208,7 @@ void *hostap_init(void) #ifdef CONFIG_SAE if (authmode == WIFI_AUTH_WPA3_PSK || authmode == WIFI_AUTH_WPA2_WPA3_PSK || - esp_wifi_wpa3_compatible_mode_enabled(WIFI_IF_AP)) { + esp_wifi_is_wpa3_compatible_mode_enabled(WIFI_IF_AP)) { if (wpa3_hostap_auth_init(hapd) != 0) { goto fail; } @@ -444,9 +444,10 @@ bool hostap_new_assoc_sta(struct sta_info *sta, uint8_t *bssid, u8 *wpa_ie, } #ifdef CONFIG_WPA3_COMPAT +#define RSN_SELECTION_IE_OUI_LEN 4 if (rsn_selection_ie) { - rsn_selection_variant_len = rsn_selection_ie[1] - 4; - rsn_selection_variant_ie = &rsn_selection_ie[6]; + rsn_selection_variant_len = rsn_selection_ie[1] - RSN_SELECTION_IE_OUI_LEN; + rsn_selection_variant_ie = &rsn_selection_ie[RSN_SELECTION_IE_OUI_LEN + 2]; } wpa_auth_set_rsn_selection(sta->wpa_sm, rsn_selection_variant_ie, rsn_selection_variant_len); 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 874f32c97f..348a48c500 100644 --- a/components/wpa_supplicant/esp_supplicant/src/esp_wifi_driver.h +++ b/components/wpa_supplicant/esp_supplicant/src/esp_wifi_driver.h @@ -310,6 +310,5 @@ int esp_wifi_softap_set_obss_overlap(bool overlap); void esp_wifi_set_sigma_internal(bool flag); void esp_wifi_ap_set_group_mgmt_cipher_internal(wifi_cipher_type_t cipher); uint8_t esp_wifi_op_class_supported_internal(uint8_t op_class, uint8_t min_chan, uint8_t max_chan, uint8_t inc, uint8_t bw, channel_bitmap_t *non_pref_channels); -bool esp_wifi_wpa3_compatible_mode_enabled(uint8_t if_index); - +bool esp_wifi_is_wpa3_compatible_mode_enabled(uint8_t if_index); #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 c5ef241f94..153fc63334 100644 --- a/components/wpa_supplicant/esp_supplicant/src/esp_wpa3.c +++ b/components/wpa_supplicant/esp_supplicant/src/esp_wpa3.c @@ -47,7 +47,7 @@ static esp_err_t wpa3_build_sae_commit(u8 *bssid, size_t *sae_msg_len) } #ifdef CONFIG_WPA3_COMPAT - if (esp_wifi_wpa3_compatible_mode_enabled(WIFI_IF_STA)) { + if (esp_wifi_is_wpa3_compatible_mode_enabled(WIFI_IF_STA)) { rsnxe = esp_wifi_sta_get_ie((u8*)bssid, WFA_RSNXE_OVERRIDE_OUI_TYPE); if (rsnxe) { rsnxe_capa = rsnxe[2 + 4]; diff --git a/components/wpa_supplicant/src/rsn_supp/wpa.c b/components/wpa_supplicant/src/rsn_supp/wpa.c index d2a8d7140f..19d760e95e 100644 --- a/components/wpa_supplicant/src/rsn_supp/wpa.c +++ b/components/wpa_supplicant/src/rsn_supp/wpa.c @@ -2629,12 +2629,12 @@ int wpa_set_bss(uint8_t *macddr, uint8_t *bssid, uint8_t pairwise_cipher, uint8_ #ifdef CONFIG_WPA3_COMPAT wpa_sm_set_param(sm, WPA_PARAM_RSN_OVERRIDE_SUPPORT, - esp_wifi_wpa3_compatible_mode_enabled(WIFI_IF_STA)); + esp_wifi_is_wpa3_compatible_mode_enabled(WIFI_IF_STA)); wpa_sm_set_param(sm, WPA_PARAM_RSN_OVERRIDE, RSN_OVERRIDE_NOT_USED); ie = esp_wifi_sta_get_ie(bssid, WFA_RSNE_OVERRIDE_OUI_TYPE); - if (esp_wifi_wpa3_compatible_mode_enabled(WIFI_IF_STA) && ie) { + if (esp_wifi_is_wpa3_compatible_mode_enabled(WIFI_IF_STA) && ie) { enum rsn_selection_variant variant = RSN_SELECTION_RSNE; if (ie && ie[0] == WLAN_EID_VENDOR_SPECIFIC && ie[1] >= 4) { diff --git a/examples/wifi/getting_started/softAP/main/softap_example_main.c b/examples/wifi/getting_started/softAP/main/softap_example_main.c index a19978070b..e9a9d03f45 100644 --- a/examples/wifi/getting_started/softAP/main/softap_example_main.c +++ b/examples/wifi/getting_started/softAP/main/softap_example_main.c @@ -75,11 +75,10 @@ void wifi_init_softap(void) #ifdef CONFIG_ESP_WIFI_SOFTAP_SAE_SUPPORT .authmode = WIFI_AUTH_WPA3_PSK, .sae_pwe_h2e = WPA3_SAE_PWE_BOTH, + .pairwise_cipher = WIFI_CIPHER_TYPE_GCMP256, + .sae_ext = 1, #else /* CONFIG_ESP_WIFI_SOFTAP_SAE_SUPPORT */ .authmode = WIFI_AUTH_WPA2_PSK, -#endif -#ifdef CONFIG_ESP_WIFI_WPA3_COMPATIBLE_SUPPORT - .wpa3_compatible_mode = 1, #endif .pmf_cfg = { .required = true, diff --git a/examples/wifi/getting_started/station/main/station_example_main.c b/examples/wifi/getting_started/station/main/station_example_main.c index 45c9a14a93..1cc82b0b83 100644 --- a/examples/wifi/getting_started/station/main/station_example_main.c +++ b/examples/wifi/getting_started/station/main/station_example_main.c @@ -130,7 +130,7 @@ void wifi_init_sta(void) .sae_pwe_h2e = ESP_WIFI_SAE_MODE, .sae_h2e_identifier = EXAMPLE_H2E_IDENTIFIER, #ifdef CONFIG_ESP_WIFI_WPA3_COMPATIBLE_SUPPORT - .wpa3_compatible_mode = 1, + .disable_wpa3_compatible_mode = 0, #endif }, }; From 1753f5ee63f8a6ff62193f34870c0b2f89394dcf Mon Sep 17 00:00:00 2001 From: Shreyas Sheth Date: Fri, 26 Sep 2025 11:20:13 +0530 Subject: [PATCH 31/33] fix(esp_wifi): Resolve some comments for wpa3_compatible_mode support --- components/esp_wifi/Kconfig | 16 +++++----- components/esp_wifi/lib | 2 +- .../esp_supplicant/src/esp_hostap.c | 8 +++-- .../wpa_supplicant/src/ap/wpa_auth_ie.c | 4 +-- .../wpa_supplicant/src/common/wpa_common.c | 31 ++++++++++++------- components/wpa_supplicant/src/rsn_supp/wpa.c | 2 +- .../softAP/main/softap_example_main.c | 2 -- 7 files changed, 37 insertions(+), 28 deletions(-) diff --git a/components/esp_wifi/Kconfig b/components/esp_wifi/Kconfig index 48dccc2157..0053e942d9 100644 --- a/components/esp_wifi/Kconfig +++ b/components/esp_wifi/Kconfig @@ -307,13 +307,6 @@ menu "Wi-Fi" explicitly configured before attempting connection. Please refer to the Wi-Fi Driver API Guide for details. - config ESP_WIFI_ENABLE_SAE_PK - bool "Enable SAE-PK" - default y - depends on (ESP_WIFI_ENABLE_WPA3_SAE && ESP_WIFI_ENABLE_SAE_H2E) - help - Select this option to enable SAE-PK - config ESP_WIFI_ENABLE_SAE_H2E bool "Enable SAE-H2E" default y @@ -321,6 +314,13 @@ menu "Wi-Fi" help Select this option to enable SAE-H2E + config ESP_WIFI_ENABLE_SAE_PK + bool "Enable SAE-PK" + default y + depends on (ESP_WIFI_ENABLE_WPA3_SAE && ESP_WIFI_ENABLE_SAE_H2E) + help + Select this option to enable SAE-PK + config ESP_WIFI_SOFTAP_SAE_SUPPORT bool "Enable WPA3 Personal(SAE) SoftAP" default y @@ -344,7 +344,7 @@ menu "Wi-Fi" default y depends on ESP_WIFI_ENABLE_SAE_H2E help - Select this option to enable WPA3 Compatible support in softap mode. + Select this option to support wpa3_compatible mode for station and AP config ESP_WIFI_SLP_IRAM_OPT bool "WiFi SLP IRAM speed optimization" diff --git a/components/esp_wifi/lib b/components/esp_wifi/lib index 5bcb2be0dd..0b719267d4 160000 --- a/components/esp_wifi/lib +++ b/components/esp_wifi/lib @@ -1 +1 @@ -Subproject commit 5bcb2be0dd10ad0da56cba95e8a1a6f16732c5b3 +Subproject commit 0b719267d459d9005e352e22a9c2dfcdf2d3f552 diff --git a/components/wpa_supplicant/esp_supplicant/src/esp_hostap.c b/components/wpa_supplicant/esp_supplicant/src/esp_hostap.c index b2eb14c324..007a3e928b 100644 --- a/components/wpa_supplicant/esp_supplicant/src/esp_hostap.c +++ b/components/wpa_supplicant/esp_supplicant/src/esp_hostap.c @@ -111,7 +111,6 @@ void *hostap_init(void) #endif /* CONFIG_IEEE80211W */ if (esp_wifi_is_wpa3_compatible_mode_enabled(WIFI_IF_AP)) { #ifdef CONFIG_WPA3_COMPAT - hapd->conf->sae_pwe = SAE_PWE_HASH_TO_ELEMENT; auth_conf->rsn_override_omit_rsnxe = 1; hapd->conf->rsn_override_omit_rsnxe = 1; hapd->conf->rsn_override_key_mgmt = WPA_KEY_MGMT_SAE; @@ -219,10 +218,13 @@ void *hostap_init(void) 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) { + authmode != WIFI_AUTH_WPA2_WPA3_PSK && + !esp_wifi_is_wpa3_compatible_mode_enabled(WIFI_IF_AP) && + auth_conf->transition_disable) { auth_conf->transition_disable = 0; - wpa_printf(MSG_DEBUG, "overriding transition_disable config with 0 as authmode is not WPA3"); + wpa_printf(MSG_DEBUG, "overriding transition_disable config with 0 as authmode is not WPA3/WPA2-WPA3/compatible"); } #ifdef CONFIG_SAE diff --git a/components/wpa_supplicant/src/ap/wpa_auth_ie.c b/components/wpa_supplicant/src/ap/wpa_auth_ie.c index 60a92a5cc8..7d01d002ef 100644 --- a/components/wpa_supplicant/src/ap/wpa_auth_ie.c +++ b/components/wpa_supplicant/src/ap/wpa_auth_ie.c @@ -602,8 +602,8 @@ wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth, #ifdef CONFIG_SAE else if (data.key_mgmt & WPA_KEY_MGMT_SAE) selector = RSN_AUTH_KEY_MGMT_SAE; - else if (data.key_mgmt & WPA_KEY_MGMT_SAE_EXT_KEY) - selector = RSN_AUTH_KEY_MGMT_SAE_EXT_KEY; + else if (data.key_mgmt & WPA_KEY_MGMT_SAE_EXT_KEY) + selector = RSN_AUTH_KEY_MGMT_SAE_EXT_KEY; else if (data.key_mgmt & WPA_KEY_MGMT_FT_SAE) selector = RSN_AUTH_KEY_MGMT_FT_SAE; #endif /* CONFIG_SAE */ diff --git a/components/wpa_supplicant/src/common/wpa_common.c b/components/wpa_supplicant/src/common/wpa_common.c index 4cd49d3d2f..5e5655cfdd 100644 --- a/components/wpa_supplicant/src/common/wpa_common.c +++ b/components/wpa_supplicant/src/common/wpa_common.c @@ -426,7 +426,6 @@ int wpa_parse_wpa_ie_rsnxe(const u8 *rsnxe_ie, size_t rsnxe_ie_len, int wpa_parse_wpa_ie_rsn(const u8 *rsn_ie, size_t rsn_ie_len, struct wpa_ie_data *data) { - const struct rsn_ie_hdr *hdr; const u8 *pos; int left; int i, count; @@ -453,19 +452,29 @@ int wpa_parse_wpa_ie_rsn(const u8 *rsn_ie, size_t rsn_ie_len, return -1; } - hdr = (const struct rsn_ie_hdr *) rsn_ie; + 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) { + pos = rsn_ie + 2 + 4 + 2; + left = rsn_ie_len - 2 - 4 - 2; + } else { + const struct rsn_ie_hdr *hdr; - if (hdr->elem_id != WLAN_EID_RSN || - hdr->len != rsn_ie_len - 2 || - WPA_GET_LE16(hdr->version) != RSN_VERSION) { - wpa_printf(MSG_DEBUG, "%s: malformed ie or unknown version", - __func__); - return -2; + hdr = (const struct rsn_ie_hdr *) rsn_ie; + + if (hdr->elem_id != WLAN_EID_RSN || + hdr->len != rsn_ie_len - 2 || + WPA_GET_LE16(hdr->version) != RSN_VERSION) { + wpa_printf(MSG_DEBUG, "%s: malformed ie or unknown version", + __func__); + return -2; + } + + pos = (const u8 *) (hdr + 1); + left = rsn_ie_len - sizeof(*hdr); } - pos = (const u8 *) (hdr + 1); - left = rsn_ie_len - sizeof(*hdr); - if (left >= RSN_SELECTOR_LEN) { data->group_cipher = rsn_selector_to_bitfield(pos); pos += RSN_SELECTOR_LEN; diff --git a/components/wpa_supplicant/src/rsn_supp/wpa.c b/components/wpa_supplicant/src/rsn_supp/wpa.c index 19d760e95e..ff260dee9e 100644 --- a/components/wpa_supplicant/src/rsn_supp/wpa.c +++ b/components/wpa_supplicant/src/rsn_supp/wpa.c @@ -2479,7 +2479,7 @@ int wpa_set_bss(uint8_t *macddr, uint8_t *bssid, uint8_t pairwise_cipher, uint8_ int res = 0; struct wpa_sm *sm = &gWpaSm; bool use_pmk_cache = !esp_wifi_skip_supp_pmkcaching(); - uint8_t assoc_ie[128]; + uint8_t assoc_ie[128] = {0}; uint16_t assoc_ie_len = sizeof(assoc_ie); bool reassoc_same_ess = false; int try_opportunistic = 0; diff --git a/examples/wifi/getting_started/softAP/main/softap_example_main.c b/examples/wifi/getting_started/softAP/main/softap_example_main.c index e9a9d03f45..c2bca87431 100644 --- a/examples/wifi/getting_started/softAP/main/softap_example_main.c +++ b/examples/wifi/getting_started/softAP/main/softap_example_main.c @@ -75,8 +75,6 @@ void wifi_init_softap(void) #ifdef CONFIG_ESP_WIFI_SOFTAP_SAE_SUPPORT .authmode = WIFI_AUTH_WPA3_PSK, .sae_pwe_h2e = WPA3_SAE_PWE_BOTH, - .pairwise_cipher = WIFI_CIPHER_TYPE_GCMP256, - .sae_ext = 1, #else /* CONFIG_ESP_WIFI_SOFTAP_SAE_SUPPORT */ .authmode = WIFI_AUTH_WPA2_PSK, #endif From 28219461eec764b0b180884f944470d1ea82a887 Mon Sep 17 00:00:00 2001 From: Shreyas Sheth Date: Sat, 27 Sep 2025 15:06:25 +0530 Subject: [PATCH 32/33] fix(esp_wifi): Resolve comments for wpa3_compat mode documentation --- components/esp_wifi/Kconfig | 2 +- components/esp_wifi/include/esp_wifi_types_generic.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/components/esp_wifi/Kconfig b/components/esp_wifi/Kconfig index 0053e942d9..c2fe6a2aee 100644 --- a/components/esp_wifi/Kconfig +++ b/components/esp_wifi/Kconfig @@ -317,7 +317,7 @@ menu "Wi-Fi" config ESP_WIFI_ENABLE_SAE_PK bool "Enable SAE-PK" default y - depends on (ESP_WIFI_ENABLE_WPA3_SAE && ESP_WIFI_ENABLE_SAE_H2E) + depends on ESP_WIFI_ENABLE_SAE_H2E help Select this option to enable SAE-PK diff --git a/components/esp_wifi/include/esp_wifi_types_generic.h b/components/esp_wifi/include/esp_wifi_types_generic.h index 755a85925a..3f6fd70055 100644 --- a/components/esp_wifi/include/esp_wifi_types_generic.h +++ b/components/esp_wifi/include/esp_wifi_types_generic.h @@ -535,7 +535,7 @@ typedef struct { wifi_sae_pwe_method_t sae_pwe_h2e; /**< Configuration for SAE PWE derivation method */ uint8_t transition_disable: 1; /**< Whether to enable transition disable feature */ uint8_t sae_ext: 1; /**< Enable SAE EXT feature. SOC_GCMP_SUPPORT is required for this feature. */ - uint8_t wpa3_compatible_mode: 1; /**< Enable WPA3 compatible authmode feature. Note: Enabling this will override the AP configuration's authmode and pairwise_cipher. The AP will operate as a WPA2 access point for legacy stations and as a WPA3 access point for WPA3 compatible stations. */ + uint8_t wpa3_compatible_mode: 1; /**< Enable WPA3 compatible authmode feature. Note: Enabling this will override the AP configuration's authmode and pairwise_cipher. The AP will operate as a WPA2 access point for all stations except for those that support WPA3 compatible mode. Only WPA3 compatibility mode stations will be able to use WPA3-SAE */ uint8_t reserved: 5; /**< Reserved for future feature set */ wifi_bss_max_idle_config_t bss_max_idle_cfg; /**< Configuration for bss max idle, effective if CONFIG_WIFI_BSS_MAX_IDLE_SUPPORT is enabled */ uint16_t gtk_rekey_interval; /**< GTK rekeying interval in seconds. If set to 0, GTK rekeying is disabled. Range: 60 ~ 65535 including 0. */ @@ -563,7 +563,7 @@ typedef struct { uint32_t ft_enabled: 1; /**< Whether FT is enabled for the connection */ uint32_t owe_enabled: 1; /**< Whether OWE is enabled for the connection */ uint32_t transition_disable: 1; /**< Whether to enable transition disable feature */ - uint32_t disable_wpa3_compatible_mode: 1; /**< Whether to enable wpa3 compatible authmode feature */ + uint32_t disable_wpa3_compatible_mode: 1; /**< Whether to disable wpa3 compatible authmode feature. Disabling this prevents connecting to WPA3-Personal RSN override (compatibility mode) APs; connection falls back to WPA2 only. */ uint32_t reserved1: 25; /**< Reserved for future feature set */ wifi_sae_pwe_method_t sae_pwe_h2e; /**< Configuration for SAE PWE derivation method */ wifi_sae_pk_mode_t sae_pk_mode; /**< Configuration for SAE-PK (Public Key) Authentication method */ From 0b0b38ea4cae8b7dc466846a268fee9f6646a205 Mon Sep 17 00:00:00 2001 From: Shreyas Sheth Date: Tue, 23 Sep 2025 15:08:04 +0530 Subject: [PATCH 33/33] fix(esp_wifi): Set default nvs value for sae identifier to NULL Resolves regression introduced in 6f7cf98ffe849c364c534d09fbce9024f56e1e19 which may impact WPA3 station connection in certain conditions --- components/esp_wifi/include/esp_wifi_types_generic.h | 2 +- components/esp_wifi/lib | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/components/esp_wifi/include/esp_wifi_types_generic.h b/components/esp_wifi/include/esp_wifi_types_generic.h index 3f6fd70055..1c4bb7b213 100644 --- a/components/esp_wifi/include/esp_wifi_types_generic.h +++ b/components/esp_wifi/include/esp_wifi_types_generic.h @@ -581,7 +581,7 @@ typedef struct { uint32_t vht_mu_beamformee_disabled: 1; /**< Whether to disable support for operation as an VHT MU beamformee. */ uint32_t vht_mcs8_enabled: 1; /**< Whether to support VHT-MCS8. The default value is 0. */ uint32_t reserved2: 19; /**< 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. Strings null-terminated (length < SAE_H2E_IDENTIFIER_LEN) or non-null terminated (length = SAE_H2E_IDENTIFIER_LEN) are accepted. Non-null terminated string with 0xFF for full length of SAE_H2E_IDENTIFIER_LEN is not considered a valid identifier */ } wifi_sta_config_t; /** diff --git a/components/esp_wifi/lib b/components/esp_wifi/lib index 0b719267d4..0e7080ea59 160000 --- a/components/esp_wifi/lib +++ b/components/esp_wifi/lib @@ -1 +1 @@ -Subproject commit 0b719267d459d9005e352e22a9c2dfcdf2d3f552 +Subproject commit 0e7080ea59152258608522876ac91b227e1883e9