feat(wifi) : OWE softAP review follow ups

- OWE: clear PRK on HKDF failure; wipe PMK with bin_clear_free; reuse PMK
      buffer when size matches.
    - 4-way handshake: drop extra OWE check so WPA2-PSK can try the next passphrase.
    - SoftAP: simpler OWE key setup and assoc response IEs (skip useless RSNXE step).
This commit is contained in:
tarun.kumar
2026-04-23 16:53:16 +05:30
parent a5201bb8f4
commit d698d5345a
11 changed files with 139 additions and 48 deletions

View File

@@ -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

View File

@@ -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 | \

View File

@@ -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

View File

@@ -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

View File

@@ -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, \

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -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;

View File

@@ -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 */

View File

@@ -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;
}

View File

@@ -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;
}