diff --git a/components/esp_wifi/Kconfig b/components/esp_wifi/Kconfig index 14547d9efe7..60a7943b125 100644 --- a/components/esp_wifi/Kconfig +++ b/components/esp_wifi/Kconfig @@ -348,7 +348,7 @@ menu "Wi-Fi" config ESP_WIFI_ENABLE_WPA3_OWE_SOFTAP bool "Enable OWE-ONLY SOFTAP" - default n + default y select ESP_WIFI_MBEDTLS_CRYPTO depends on ESP_WIFI_SOFTAP_SUPPORT help diff --git a/components/esp_wifi/include/esp_wifi.h b/components/esp_wifi/include/esp_wifi.h index 1419a3daf7a..f1727019ae2 100644 --- a/components/esp_wifi/include/esp_wifi.h +++ b/components/esp_wifi/include/esp_wifi.h @@ -291,7 +291,7 @@ extern wifi_osi_funcs_t g_wifi_osi_funcs; #endif #if CONFIG_ESP_WIFI_ENABLE_WPA3_OWE_SOFTAP -#define WIFI_ENABLE_OWE_SOFTAP (1<<9) +#define WIFI_ENABLE_OWE_SOFTAP (1<<10) #else #define WIFI_ENABLE_OWE_SOFTAP 0 #endif @@ -306,7 +306,7 @@ extern wifi_osi_funcs_t g_wifi_osi_funcs; #define CONFIG_FEATURE_WIFI_ENT_BIT (1<<7) #define CONFIG_FEATURE_BSS_MAX_IDLE_BIT (1<<8) #define CONFIG_FEATURE_WIFI_PASSIVE_HIDDEN_AP_BIT (1<<9) -#define CONFIG_FEATURE_OWE_SOFTAP_BIT (1<<9) +#define CONFIG_FEATURE_OWE_SOFTAP_BIT (1<<10) /* Set additional WiFi features and capabilities */ #define WIFI_FEATURE_CAPS (WIFI_ENABLE_WPA3_SAE | \ diff --git a/components/esp_wifi/remote/Kconfig.wifi.in b/components/esp_wifi/remote/Kconfig.wifi.in index ddc35664e05..fc257f9e302 100644 --- a/components/esp_wifi/remote/Kconfig.wifi.in +++ b/components/esp_wifi/remote/Kconfig.wifi.in @@ -325,6 +325,14 @@ config WIFI_RMT_WPA3_COMPATIBLE_SUPPORT help Select this option to support wpa3_compatible mode for station and AP +config WIFI_RMT_ENABLE_WPA3_OWE_SOFTAP + bool "Enable OWE-ONLY SOFTAP" + default y + select WIFI_RMT_MBEDTLS_CRYPTO + depends on WIFI_RMT_SOFTAP_SUPPORT + help + Select this option to allow the device to enable OWE Only mode for softap. + config WIFI_RMT_SLP_IRAM_OPT bool "WiFi SLP IRAM speed optimization" select PM_SLP_DEFAULT_PARAMS_OPT diff --git a/components/esp_wifi/remote/Kconfig.wifi_is_remote.in b/components/esp_wifi/remote/Kconfig.wifi_is_remote.in index e82fe9ecac5..ab26b4d464a 100644 --- a/components/esp_wifi/remote/Kconfig.wifi_is_remote.in +++ b/components/esp_wifi/remote/Kconfig.wifi_is_remote.in @@ -142,6 +142,13 @@ if WIFI_RMT_WPA3_COMPATIBLE_SUPPORT default WIFI_RMT_WPA3_COMPATIBLE_SUPPORT endif +if WIFI_RMT_ENABLE_WPA3_OWE_SOFTAP + config ESP_WIFI_ENABLE_WPA3_OWE_SOFTAP # ignore: multiple-definition + bool + depends on WIFI_RMT_SOFTAP_SUPPORT + default WIFI_RMT_ENABLE_WPA3_OWE_SOFTAP +endif + if WIFI_RMT_SLP_IRAM_OPT config ESP_WIFI_SLP_IRAM_OPT # ignore: multiple-definition bool diff --git a/components/esp_wifi/remote/include/injected/esp_wifi.h b/components/esp_wifi/remote/include/injected/esp_wifi.h index fc64202d62f..0010fa69efe 100644 --- a/components/esp_wifi/remote/include/injected/esp_wifi.h +++ b/components/esp_wifi/remote/include/injected/esp_wifi.h @@ -290,6 +290,12 @@ extern wifi_osi_funcs_t g_wifi_osi_funcs; #define WIFI_ENABLE_PASSIVE_HIDDEN_AP 0 #endif +#if CONFIG_WIFI_RMT_ENABLE_WPA3_OWE_SOFTAP +#define WIFI_ENABLE_OWE_SOFTAP (1<<10) +#else +#define WIFI_ENABLE_OWE_SOFTAP 0 +#endif + #define CONFIG_FEATURE_WPA3_SAE_BIT (1<<0) #define CONFIG_FEATURE_CACHE_TX_BUF_BIT (1<<1) #define CONFIG_FEATURE_FTM_INITIATOR_BIT (1<<2) @@ -300,6 +306,7 @@ extern wifi_osi_funcs_t g_wifi_osi_funcs; #define CONFIG_FEATURE_WIFI_ENT_BIT (1<<7) #define CONFIG_FEATURE_BSS_MAX_IDLE_BIT (1<<8) #define CONFIG_FEATURE_WIFI_PASSIVE_HIDDEN_AP_BIT (1<<9) +#define CONFIG_FEATURE_OWE_SOFTAP_BIT (1<<10) /* Set additional WiFi features and capabilities */ #define WIFI_FEATURE_CAPS (WIFI_ENABLE_WPA3_SAE | \ @@ -311,7 +318,8 @@ extern wifi_osi_funcs_t g_wifi_osi_funcs; WIFI_ENABLE_11R | \ WIFI_ENABLE_ENTERPRISE | \ WIFI_ENABLE_BSS_MAX_IDLE | \ - WIFI_ENABLE_PASSIVE_HIDDEN_AP) + WIFI_ENABLE_PASSIVE_HIDDEN_AP | \ + WIFI_ENABLE_OWE_SOFTAP) #define WIFI_INIT_CONFIG_DEFAULT() { \ .osi_funcs = &g_wifi_osi_funcs, \ diff --git a/components/wpa_supplicant/esp_supplicant/src/esp_hostap.c b/components/wpa_supplicant/esp_supplicant/src/esp_hostap.c index 0b43fa2f059..9e5e62f855f 100644 --- a/components/wpa_supplicant/esp_supplicant/src/esp_hostap.c +++ b/components/wpa_supplicant/esp_supplicant/src/esp_hostap.c @@ -201,7 +201,7 @@ void *hostap_init(void) esp_wifi_ap_set_group_mgmt_cipher_internal(cipher_type_map_supp_to_public(auth_conf->group_mgmt_cipher)); #ifdef CONFIG_OWE_SOFTAP - if (authmode == WIFI_AUTH_OWE && esp_wifi_ap_get_owe_config_internal()) { + if (authmode == WIFI_AUTH_OWE) { auth_conf->wpa_key_mgmt = WPA_KEY_MGMT_OWE; } #endif /* CONFIG_OWE_SOFTAP */ @@ -379,27 +379,33 @@ u16 esp_send_assoc_resp(struct hostapd_data *hapd, const u8 *addr, u8 buf[ASSOC_RESP_LENGTH]; wifi_mgmt_frm_req_t *reply = NULL; int send_len = 0; - +#ifdef CONFIG_OWE_SOFTAP + const bool owe_resp = (status_code == WLAN_STATUS_SUCCESS) && + (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_OWE) && + esp_wifi_ap_get_owe_config_internal(); +#else + const bool owe_resp = false; +#endif int res = WLAN_STATUS_SUCCESS; - if (!omit_rsnxe) { + if (!omit_rsnxe && !owe_resp) { send_len = esp_wifi_build_rsnxe(hapd, buf, ASSOC_RESP_LENGTH); } - esp_wifi_set_appie_internal(WIFI_APPIE_ASSOC_RESP, buf, send_len, 0); + if (!owe_resp) { + esp_wifi_set_appie_internal(WIFI_APPIE_ASSOC_RESP, buf, send_len, 0); + } #ifdef CONFIG_OWE_SOFTAP - if (status_code == WLAN_STATUS_SUCCESS) { - if ((hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_OWE) && esp_wifi_ap_get_owe_config_internal()) { - int owe_ie_len = 0; - struct wpabuf *owe_ie = esp_owe_build_assoc_resp_dhie(hapd, addr, &owe_ie_len); - if (owe_ie_len <= 0 || !owe_ie) { - wpa_printf(MSG_ERROR, "%s : error creating dhie for assoc resp %d ", __func__, owe_ie_len); - wpabuf_free(owe_ie); - return WLAN_STATUS_UNSPECIFIED_FAILURE; - } - esp_wifi_set_appie_internal(WIFI_APPIE_ASSOC_RESP, (uint8_t *)wpabuf_head(owe_ie), owe_ie_len, 0); + if (owe_resp) { + int owe_ie_len = 0; + struct wpabuf *owe_ie = esp_owe_build_assoc_resp_dhie(hapd, addr, &owe_ie_len); + if (owe_ie_len <= 0 || !owe_ie) { + wpa_printf(MSG_ERROR, "%s : error creating dhie for assoc resp %d ", __func__, owe_ie_len); wpabuf_free(owe_ie); + return WLAN_STATUS_UNSPECIFIED_FAILURE; } + esp_wifi_set_appie_internal(WIFI_APPIE_ASSOC_RESP, (uint8_t *)wpabuf_head(owe_ie), owe_ie_len, 0); + wpabuf_free(owe_ie); } #endif /* CONFIG_OWE_SOFTAP */ @@ -445,10 +451,9 @@ uint8_t wpa_status_to_reason_code(int status) } } -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, uint8_t *owe_dh, uint8_t owe_ie_len) +bool hostap_new_assoc_sta(struct sta_info *sta, uint8_t *bssid, + const struct hostap_assoc_sta_req *assoc_req, + bool *pmf_enable, u8 *pairwise_cipher, u8 *reason) { struct hostapd_data *hapd = (struct hostapd_data*)esp_wifi_get_hostap_private_internal(); enum wpa_validate_result res = WPA_IE_OK; @@ -460,7 +465,7 @@ bool hostap_new_assoc_sta(struct sta_info *sta, uint8_t *bssid, u8 *wpa_ie, uint8_t *rsn_selection_variant_ie = NULL; #endif - if (!sta || !bssid || !wpa_ie) { + if (!sta || !bssid || !assoc_req || !assoc_req->wpa_ie) { return false; } if (hapd) { @@ -479,15 +484,16 @@ 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] - RSN_SELECTION_IE_OUI_LEN; - rsn_selection_variant_ie = &rsn_selection_ie[RSN_SELECTION_IE_OUI_LEN + 2]; + if (assoc_req->rsn_selection_ie) { + rsn_selection_variant_len = assoc_req->rsn_selection_ie[1] - RSN_SELECTION_IE_OUI_LEN; + rsn_selection_variant_ie = &assoc_req->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); #endif - 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, assoc_req->wpa_ie, + assoc_req->wpa_ie_len, assoc_req->rsnxe, assoc_req->rsnxe_len); #ifdef CONFIG_SAE if (wpa_auth_uses_sae(sta->wpa_sm) && sta->sae && sta->sae->state == SAE_ACCEPTED) { @@ -503,8 +509,8 @@ bool hostap_new_assoc_sta(struct sta_info *sta, uint8_t *bssid, u8 *wpa_ie, if (status == WLAN_STATUS_SUCCESS && hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_OWE && sta->wpa_sm->wpa_key_mgmt == WPA_KEY_MGMT_OWE && - owe_dh && owe_enabled) { - status = owe_process_assoc_req(hapd, sta, owe_dh, owe_ie_len); + assoc_req->owe_dh && owe_enabled) { + status = owe_process_assoc_req(hapd, sta, assoc_req->owe_dh, assoc_req->owe_ie_len); if (status == WLAN_STATUS_UNSPECIFIED_FAILURE) { *reason = wpa_status_to_reason_code(status); wpa_printf(MSG_ERROR, "OWE : Failed to process assoc req status %d", status); @@ -514,7 +520,7 @@ bool hostap_new_assoc_sta(struct sta_info *sta, uint8_t *bssid, u8 *wpa_ie, #endif /* CONFIG_OWE_SOFTAP */ send_resp: - if (!rsnxe) { + if (!assoc_req->rsnxe) { omit_rsnxe = true; } @@ -524,7 +530,7 @@ send_resp: } #endif - if (esp_send_assoc_resp(hapd, bssid, status, omit_rsnxe, subtype) != WLAN_STATUS_SUCCESS) { + if (esp_send_assoc_resp(hapd, bssid, status, omit_rsnxe, assoc_req->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 f31638addf5..6760a9c204f 100644 --- a/components/wpa_supplicant/esp_supplicant/src/esp_wifi_driver.h +++ b/components/wpa_supplicant/esp_supplicant/src/esp_wifi_driver.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2019-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2019-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -120,6 +120,21 @@ typedef struct { uint8_t rsnxe_capa; } wifi_wpa_ie_t; +typedef struct { + void **sm; + u8 *bssid; + u8 *wpa_ie; + u8 *rsnxe; + bool *pmf_enable; + uint8_t *pairwise_cipher; + uint8_t *rsn_selection_ie; + uint8_t *owe_dhie; + int subtype; + u16 rsnxe_len; + u8 wpa_ie_len; + u8 owe_dh_len; +} wpa_station_join_param_t; + struct wpa_funcs { bool (*wpa_sta_init)(void); bool (*wpa_sta_deinit)(void); @@ -130,7 +145,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, uint8_t *rsn_selection_ie, uint8_t *owe_dhie, uint8_t owe_dh_len); + bool (*wpa_ap_join)(wpa_station_join_param_t *join); bool (*wpa_ap_remove)(u8 *bssid); uint8_t *(*wpa_ap_get_wpa_ie)(size_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_wpa_main.c b/components/wpa_supplicant/esp_supplicant/src/esp_wpa_main.c index 990be107e08..f34f4750c86 100644 --- a/components/wpa_supplicant/esp_supplicant/src/esp_wpa_main.c +++ b/components/wpa_supplicant/esp_supplicant/src/esp_wpa_main.c @@ -389,12 +389,29 @@ 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, uint8_t *rsn_selection_ie, uint8_t *owe_dh, uint8_t owe_ie_len) +static bool hostap_sta_join(wpa_station_join_param_t *join) { struct sta_info *sta_info = NULL; struct hostapd_data *hapd = hostapd_get_hapd_data(); uint8_t reason = WLAN_REASON_PREV_AUTH_NOT_VALID; + if (!join) { + return false; + } + + void **sta = join->sm; + u8 *bssid = join->bssid; + u8 *wpa_ie = join->wpa_ie; + u8 *rsnxe = join->rsnxe; + bool *pmf_enable = join->pmf_enable; + uint8_t *pairwise_cipher = join->pairwise_cipher; + uint8_t *rsn_selection_ie = join->rsn_selection_ie; + uint8_t *owe_dhie = join->owe_dhie; + int subtype = join->subtype; + u16 rsnxe_len = join->rsnxe_len; + u8 wpa_ie_len = join->wpa_ie_len; + u8 owe_dh_len = join->owe_dh_len; + if (!hapd) { goto fail; } @@ -452,7 +469,18 @@ process_old_sta: } #endif - 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, owe_dh, owe_ie_len)) { + struct hostap_assoc_sta_req assoc_req = { + .wpa_ie = wpa_ie, + .wpa_ie_len = wpa_ie_len, + .rsnxe = rsnxe, + .rsnxe_len = rsnxe_len, + .subtype = subtype, + .rsn_selection_ie = rsn_selection_ie, + .owe_dh = owe_dhie, + .owe_ie_len = owe_dh_len, + }; + if (hostap_new_assoc_sta(sta_info, bssid, &assoc_req, pmf_enable, + pairwise_cipher, &reason)) { goto done; } else { goto fail; diff --git a/components/wpa_supplicant/src/ap/ap_config.h b/components/wpa_supplicant/src/ap/ap_config.h index 87e6547b88a..cfc04f85fa6 100644 --- a/components/wpa_supplicant/src/ap/ap_config.h +++ b/components/wpa_supplicant/src/ap/ap_config.h @@ -395,10 +395,21 @@ 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, - 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, uint8_t *owe_dh, uint8_t owe_ie_len); + +struct hostap_assoc_sta_req { + u8 *wpa_ie; + u8 wpa_ie_len; + u8 *rsnxe; + u16 rsnxe_len; + int subtype; + u8 *rsn_selection_ie; + u8 *owe_dh; + u8 owe_ie_len; +}; + +bool hostap_new_assoc_sta(struct sta_info *sta, uint8_t *bssid, + const struct hostap_assoc_sta_req *assoc_req, + bool *pmf_enable, u8 *pairwise_cipher, u8 *reason); bool wpa_ap_remove(u8* bssid); #endif /* HOSTAPD_CONFIG_H */ diff --git a/components/wpa_supplicant/src/ap/ieee802_11.c b/components/wpa_supplicant/src/ap/ieee802_11.c index 2b8aa10da08..e59339e917c 100644 --- a/components/wpa_supplicant/src/ap/ieee802_11.c +++ b/components/wpa_supplicant/src/ap/ieee802_11.c @@ -7,6 +7,7 @@ */ #include "utils/includes.h" +#include "utils/common.h" #include "common/sae.h" #include "common/ieee802_11_defs.h" #include "esp_wifi_driver.h" @@ -907,25 +908,32 @@ uint16_t owe_process_assoc_req(struct hostapd_data *hapd, struct sta_info *sta, wpabuf_clear_free(secret); if (res < 0) { + os_memset(prk, 0, SHA256_MAC_LEN); wpa_printf(MSG_ERROR, "OWE: HMAC-SHA256 failed"); return WLAN_STATUS_UNSPECIFIED_FAILURE; } wpa_hexdump_key(MSG_DEBUG, "OWE: prk", prk, SHA256_MAC_LEN); /* PMK = HKDF-expand(prk, "OWE Key Generation", n) */ - os_free(sta->owe_pmk); - sta->owe_pmk = os_malloc(SHA256_MAC_LEN); - if (!sta->owe_pmk) { - os_memset(prk, 0, SHA256_MAC_LEN); - return WLAN_STATUS_UNSPECIFIED_FAILURE; + if (!sta->owe_pmk || sta->owe_pmk_len != SHA256_MAC_LEN) { + bin_clear_free(sta->owe_pmk, + sta->owe_pmk_len ? sta->owe_pmk_len : SHA256_MAC_LEN); + sta->owe_pmk = os_malloc(SHA256_MAC_LEN); + if (!sta->owe_pmk) { + os_memset(prk, 0, SHA256_MAC_LEN); + return WLAN_STATUS_UNSPECIFIED_FAILURE; + } + } else { + os_memset(sta->owe_pmk, 0, SHA256_MAC_LEN); } res = hmac_sha256_kdf(prk, SHA256_MAC_LEN, NULL, (const u8 *)info, os_strlen(info), sta->owe_pmk, SHA256_MAC_LEN); os_memset(prk, 0, SHA256_MAC_LEN); if (res < 0) { - os_free(sta->owe_pmk); + bin_clear_free(sta->owe_pmk, SHA256_MAC_LEN); sta->owe_pmk = NULL; + sta->owe_pmk_len = 0; wpa_printf(MSG_ERROR, "OWE: HMAC-SHA256 KDF failed"); return WLAN_STATUS_UNSPECIFIED_FAILURE; } @@ -938,8 +946,9 @@ uint16_t owe_process_assoc_req(struct hostapd_data *hapd, struct sta_info *sta, // Add the PMK to the PMKSA cache if (wpa_auth_pmksa_add2(hapd->wpa_auth, sta->addr, sta->owe_pmk, sta->owe_pmk_len, pmkid, 0, WPA_KEY_MGMT_OWE, NULL) < 0) { - os_free(sta->owe_pmk); + bin_clear_free(sta->owe_pmk, sta->owe_pmk_len); sta->owe_pmk = NULL; + sta->owe_pmk_len = 0; wpa_printf(MSG_ERROR, "OWE: Failed to add PMKSA cache entry"); return WLAN_STATUS_UNSPECIFIED_FAILURE; } diff --git a/components/wpa_supplicant/src/ap/wpa_auth.c b/components/wpa_supplicant/src/ap/wpa_auth.c index 5967cab302a..fa5fc7a851e 100644 --- a/components/wpa_supplicant/src/ap/wpa_auth.c +++ b/components/wpa_supplicant/src/ap/wpa_auth.c @@ -1805,8 +1805,7 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING) } if (!wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) || - wpa_key_mgmt_sae(sm->wpa_key_mgmt) || - sm->wpa_key_mgmt != WPA_KEY_MGMT_OWE) { + wpa_key_mgmt_sae(sm->wpa_key_mgmt)) { wpa_printf( MSG_DEBUG, "wpa_key_mgmt=%x", sm->wpa_key_mgmt); break; }