Merge branch 'feature/softap_owe_support' into 'master'

Add support for OWE Only in SoftAP mode

Closes WIFI-4281 and IDFGH-12437

See merge request espressif/esp-idf!47341
This commit is contained in:
Jiang Jiang Jian
2026-05-06 19:38:29 +08:00
23 changed files with 601 additions and 37 deletions
+8
View File
@@ -346,6 +346,14 @@ menu "Wi-Fi"
help help
Select this option to support wpa3_compatible mode for station and AP Select this option to support wpa3_compatible mode for station and AP
config ESP_WIFI_ENABLE_WPA3_OWE_SOFTAP
bool "Enable OWE-ONLY SOFTAP"
default y
select ESP_WIFI_MBEDTLS_CRYPTO
depends on ESP_WIFI_SOFTAP_SUPPORT
help
Select this option to allow the device to enable OWE Only mode for softap.
config ESP_WIFI_SLP_IRAM_OPT config ESP_WIFI_SLP_IRAM_OPT
bool "WiFi SLP IRAM speed optimization" bool "WiFi SLP IRAM speed optimization"
select PM_SLP_DEFAULT_PARAMS_OPT select PM_SLP_DEFAULT_PARAMS_OPT
+9 -1
View File
@@ -290,6 +290,12 @@ extern wifi_osi_funcs_t g_wifi_osi_funcs;
#define WIFI_ENABLE_PASSIVE_HIDDEN_AP 0 #define WIFI_ENABLE_PASSIVE_HIDDEN_AP 0
#endif #endif
#if CONFIG_ESP_WIFI_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_WPA3_SAE_BIT (1<<0)
#define CONFIG_FEATURE_CACHE_TX_BUF_BIT (1<<1) #define CONFIG_FEATURE_CACHE_TX_BUF_BIT (1<<1)
#define CONFIG_FEATURE_FTM_INITIATOR_BIT (1<<2) #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_WIFI_ENT_BIT (1<<7)
#define CONFIG_FEATURE_BSS_MAX_IDLE_BIT (1<<8) #define CONFIG_FEATURE_BSS_MAX_IDLE_BIT (1<<8)
#define CONFIG_FEATURE_WIFI_PASSIVE_HIDDEN_AP_BIT (1<<9) #define CONFIG_FEATURE_WIFI_PASSIVE_HIDDEN_AP_BIT (1<<9)
#define CONFIG_FEATURE_OWE_SOFTAP_BIT (1<<10)
/* Set additional WiFi features and capabilities */ /* Set additional WiFi features and capabilities */
#define WIFI_FEATURE_CAPS (WIFI_ENABLE_WPA3_SAE | \ #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_11R | \
WIFI_ENABLE_ENTERPRISE | \ WIFI_ENABLE_ENTERPRISE | \
WIFI_ENABLE_BSS_MAX_IDLE | \ WIFI_ENABLE_BSS_MAX_IDLE | \
WIFI_ENABLE_PASSIVE_HIDDEN_AP) WIFI_ENABLE_PASSIVE_HIDDEN_AP | \
WIFI_ENABLE_OWE_SOFTAP)
#define WIFI_INIT_CONFIG_DEFAULT() { \ #define WIFI_INIT_CONFIG_DEFAULT() { \
.osi_funcs = &g_wifi_osi_funcs, \ .osi_funcs = &g_wifi_osi_funcs, \
@@ -325,6 +325,14 @@ config WIFI_RMT_WPA3_COMPATIBLE_SUPPORT
help help
Select this option to support wpa3_compatible mode for station and AP 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 config WIFI_RMT_SLP_IRAM_OPT
bool "WiFi SLP IRAM speed optimization" bool "WiFi SLP IRAM speed optimization"
select PM_SLP_DEFAULT_PARAMS_OPT select PM_SLP_DEFAULT_PARAMS_OPT
@@ -142,6 +142,13 @@ if WIFI_RMT_WPA3_COMPATIBLE_SUPPORT
default WIFI_RMT_WPA3_COMPATIBLE_SUPPORT default WIFI_RMT_WPA3_COMPATIBLE_SUPPORT
endif 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 if WIFI_RMT_SLP_IRAM_OPT
config ESP_WIFI_SLP_IRAM_OPT # ignore: multiple-definition config ESP_WIFI_SLP_IRAM_OPT # ignore: multiple-definition
bool bool
@@ -290,6 +290,12 @@ extern wifi_osi_funcs_t g_wifi_osi_funcs;
#define WIFI_ENABLE_PASSIVE_HIDDEN_AP 0 #define WIFI_ENABLE_PASSIVE_HIDDEN_AP 0
#endif #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_WPA3_SAE_BIT (1<<0)
#define CONFIG_FEATURE_CACHE_TX_BUF_BIT (1<<1) #define CONFIG_FEATURE_CACHE_TX_BUF_BIT (1<<1)
#define CONFIG_FEATURE_FTM_INITIATOR_BIT (1<<2) #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_WIFI_ENT_BIT (1<<7)
#define CONFIG_FEATURE_BSS_MAX_IDLE_BIT (1<<8) #define CONFIG_FEATURE_BSS_MAX_IDLE_BIT (1<<8)
#define CONFIG_FEATURE_WIFI_PASSIVE_HIDDEN_AP_BIT (1<<9) #define CONFIG_FEATURE_WIFI_PASSIVE_HIDDEN_AP_BIT (1<<9)
#define CONFIG_FEATURE_OWE_SOFTAP_BIT (1<<10)
/* Set additional WiFi features and capabilities */ /* Set additional WiFi features and capabilities */
#define WIFI_FEATURE_CAPS (WIFI_ENABLE_WPA3_SAE | \ #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_11R | \
WIFI_ENABLE_ENTERPRISE | \ WIFI_ENABLE_ENTERPRISE | \
WIFI_ENABLE_BSS_MAX_IDLE | \ WIFI_ENABLE_BSS_MAX_IDLE | \
WIFI_ENABLE_PASSIVE_HIDDEN_AP) WIFI_ENABLE_PASSIVE_HIDDEN_AP | \
WIFI_ENABLE_OWE_SOFTAP)
#define WIFI_INIT_CONFIG_DEFAULT() { \ #define WIFI_INIT_CONFIG_DEFAULT() { \
.osi_funcs = &g_wifi_osi_funcs, \ .osi_funcs = &g_wifi_osi_funcs, \
+3
View File
@@ -362,4 +362,7 @@ endif()
if(CONFIG_ESP_WIFI_NAN_USD_ENABLE) if(CONFIG_ESP_WIFI_NAN_USD_ENABLE)
target_compile_definitions(${COMPONENT_LIB} PRIVATE CONFIG_NAN_USD) target_compile_definitions(${COMPONENT_LIB} PRIVATE CONFIG_NAN_USD)
endif() endif()
if(CONFIG_ESP_WIFI_ENABLE_WPA3_OWE_SOFTAP)
target_compile_definitions(${COMPONENT_LIB} PRIVATE CONFIG_OWE_SOFTAP)
endif()
set_property(TARGET ${COMPONENT_LIB} APPEND PROPERTY LINK_INTERFACE_MULTIPLICITY 3) set_property(TARGET ${COMPONENT_LIB} APPEND PROPERTY LINK_INTERFACE_MULTIPLICITY 3)
@@ -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 * SPDX-License-Identifier: Apache-2.0
*/ */
@@ -28,6 +28,12 @@
#include "ap/ieee802_11.h" #include "ap/ieee802_11.h"
#define WIFI_PASSWORD_LEN_MAX 65 #define WIFI_PASSWORD_LEN_MAX 65
#ifdef CONFIG_OWE_SOFTAP
#include "crypto/crypto.h"
#include "ap/ieee802_11.h"
#include "esp_owe_i.h"
#endif
struct hostapd_data *global_hapd; struct hostapd_data *global_hapd;
#ifdef CONFIG_SAE #ifdef CONFIG_SAE
@@ -48,7 +54,8 @@ static bool authmode_has_rsn(uint8_t authmode)
return (authmode == WIFI_AUTH_WPA2_PSK || return (authmode == WIFI_AUTH_WPA2_PSK ||
authmode == WIFI_AUTH_WPA_WPA2_PSK || authmode == WIFI_AUTH_WPA_WPA2_PSK ||
authmode == WIFI_AUTH_WPA3_PSK || authmode == WIFI_AUTH_WPA3_PSK ||
authmode == WIFI_AUTH_WPA2_WPA3_PSK); authmode == WIFI_AUTH_WPA2_WPA3_PSK ||
authmode == WIFI_AUTH_OWE);
} }
void *hostap_init(void) void *hostap_init(void)
@@ -192,6 +199,13 @@ void *hostap_init(void)
#endif /* CONFIG_IEEE80211W */ #endif /* CONFIG_IEEE80211W */
esp_wifi_ap_set_group_mgmt_cipher_internal(cipher_type_map_supp_to_public(auth_conf->group_mgmt_cipher)); 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) {
auth_conf->wpa_key_mgmt = WPA_KEY_MGMT_OWE;
}
#endif /* CONFIG_OWE_SOFTAP */
spp_attrubute = esp_wifi_get_spp_attrubute_internal(WIFI_IF_AP); spp_attrubute = esp_wifi_get_spp_attrubute_internal(WIFI_IF_AP);
auth_conf->spp_sup.capable = ((spp_attrubute & WPA_CAPABILITY_SPP_CAPABLE) ? SPP_AMSDU_CAP_ENABLE : SPP_AMSDU_CAP_DISABLE); auth_conf->spp_sup.capable = ((spp_attrubute & WPA_CAPABILITY_SPP_CAPABLE) ? SPP_AMSDU_CAP_ENABLE : SPP_AMSDU_CAP_DISABLE);
auth_conf->spp_sup.require = ((spp_attrubute & WPA_CAPABILITY_SPP_REQUIRED) ? SPP_AMSDU_REQ_ENABLE : SPP_AMSDU_REQ_DISABLE); auth_conf->spp_sup.require = ((spp_attrubute & WPA_CAPABILITY_SPP_REQUIRED) ? SPP_AMSDU_REQ_ENABLE : SPP_AMSDU_REQ_DISABLE);
@@ -365,14 +379,35 @@ u16 esp_send_assoc_resp(struct hostapd_data *hapd, const u8 *addr,
u8 buf[ASSOC_RESP_LENGTH]; u8 buf[ASSOC_RESP_LENGTH];
wifi_mgmt_frm_req_t *reply = NULL; wifi_mgmt_frm_req_t *reply = NULL;
int send_len = 0; 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; int res = WLAN_STATUS_SUCCESS;
if (!omit_rsnxe) { if (!omit_rsnxe && !owe_resp) {
send_len = esp_wifi_build_rsnxe(hapd, buf, ASSOC_RESP_LENGTH); 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 (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 */
reply = os_zalloc(sizeof(wifi_mgmt_frm_req_t) + sizeof(uint16_t)); reply = os_zalloc(sizeof(wifi_mgmt_frm_req_t) + sizeof(uint16_t));
if (!reply) { if (!reply) {
@@ -416,9 +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, bool hostap_new_assoc_sta(struct sta_info *sta, uint8_t *bssid,
u8 wpa_ie_len, u8 *rsnxe, uint16_t rsnxe_len, const struct hostap_assoc_sta_req *assoc_req,
bool *pmf_enable, int subtype, uint8_t *pairwise_cipher, uint8_t *reason, uint8_t *rsn_selection_ie) bool *pmf_enable, u8 *pairwise_cipher, u8 *reason)
{ {
struct hostapd_data *hapd = (struct hostapd_data*)esp_wifi_get_hostap_private_internal(); struct hostapd_data *hapd = (struct hostapd_data*)esp_wifi_get_hostap_private_internal();
enum wpa_validate_result res = WPA_IE_OK; enum wpa_validate_result res = WPA_IE_OK;
@@ -430,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; uint8_t *rsn_selection_variant_ie = NULL;
#endif #endif
if (!sta || !bssid || !wpa_ie) { if (!sta || !bssid || !assoc_req || !assoc_req->wpa_ie) {
return false; return false;
} }
if (hapd) { if (hapd) {
@@ -449,15 +484,16 @@ bool hostap_new_assoc_sta(struct sta_info *sta, uint8_t *bssid, u8 *wpa_ie,
#ifdef CONFIG_WPA3_COMPAT #ifdef CONFIG_WPA3_COMPAT
#define RSN_SELECTION_IE_OUI_LEN 4 #define RSN_SELECTION_IE_OUI_LEN 4
if (rsn_selection_ie) { if (assoc_req->rsn_selection_ie) {
rsn_selection_variant_len = rsn_selection_ie[1] - RSN_SELECTION_IE_OUI_LEN; rsn_selection_variant_len = assoc_req->rsn_selection_ie[1] - RSN_SELECTION_IE_OUI_LEN;
rsn_selection_variant_ie = &rsn_selection_ie[RSN_SELECTION_IE_OUI_LEN + 2]; 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); wpa_auth_set_rsn_selection(sta->wpa_sm, rsn_selection_variant_ie, rsn_selection_variant_len);
#endif #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 #ifdef CONFIG_SAE
if (wpa_auth_uses_sae(sta->wpa_sm) && sta->sae && if (wpa_auth_uses_sae(sta->wpa_sm) && sta->sae &&
sta->sae->state == SAE_ACCEPTED) { sta->sae->state == SAE_ACCEPTED) {
@@ -468,8 +504,30 @@ bool hostap_new_assoc_sta(struct sta_info *sta, uint8_t *bssid, u8 *wpa_ie,
status = wpa_res_to_status_code(res); status = wpa_res_to_status_code(res);
#ifdef CONFIG_OWE_SOFTAP
uint8_t owe_enabled = esp_wifi_ap_get_owe_config_internal();
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_enabled) {
if (!assoc_req->owe_dh || assoc_req->owe_ie_len == 0) {
wpa_printf(MSG_ERROR,
"OWE: Association request missing DH Parameter element");
status = WLAN_STATUS_AKMP_NOT_VALID;
} else {
status = owe_process_assoc_req(hapd, sta, assoc_req->owe_dh,
assoc_req->owe_ie_len);
if (status != WLAN_STATUS_SUCCESS) {
wpa_printf(MSG_ERROR,
"OWE: Failed to process assoc req status %d",
status);
}
}
}
#endif /* CONFIG_OWE_SOFTAP */
send_resp: send_resp:
if (!rsnxe) { if (!assoc_req->rsnxe) {
omit_rsnxe = true; omit_rsnxe = true;
} }
@@ -479,7 +537,7 @@ send_resp:
} }
#endif #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; status = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
} }
@@ -1,14 +1,22 @@
/* /*
* SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2020-2026 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
#ifdef CONFIG_OWE_STA
#include "crypto/crypto.h" #include "crypto/crypto.h"
#include "esp_owe_i.h" #include "esp_owe_i.h"
#include "rsn_supp/wpa.h" #include "rsn_supp/wpa.h"
#ifdef CONFIG_OWE_SOFTAP
#include "ap/hostapd.h"
#include "ap/sta_info.h"
#include "ap/wpa_auth.h"
#include "ap/wpa_auth_i.h"
#include "common/ieee802_11_defs.h"
#endif
#ifdef CONFIG_OWE_STA
uint8_t *owe_build_dhie(uint16_t group) uint8_t *owe_build_dhie(uint16_t group)
{ {
struct wpa_sm *sm = NULL; struct wpa_sm *sm = NULL;
@@ -36,3 +44,100 @@ void esp_wifi_register_owe_cb(struct wpa_funcs *wpa_cb)
wpa_cb->owe_process_assoc_resp = owe_process_assoc_resp; wpa_cb->owe_process_assoc_resp = owe_process_assoc_resp;
} }
#endif /* CONFIG_OWE_STA */ #endif /* CONFIG_OWE_STA */
#ifdef CONFIG_OWE_SOFTAP
struct wpabuf *esp_owe_build_assoc_resp_dhie(struct hostapd_data *hapd, const u8 *bssid, int *owe_ie_len)
{
if (!hapd || !hapd->wpa_auth || !hapd->wpa_auth->wpa_ie) {
wpa_printf(MSG_ERROR, "Invalid hapd or WPA auth data");
return NULL;
}
struct wpabuf *pub;
struct sta_info *sta = ap_get_sta(hapd, bssid);
if (!sta) {
return NULL;
}
struct wpabuf *owe_buf = wpabuf_alloc(OWE_IE_INIT_LEN);
if (!owe_buf) {
wpa_printf(MSG_ERROR, "Memory allocation failed for OWE IE");
return NULL;
}
// If PMKSA caching is used, write and return only RSN IE with PMKID
if (sta->wpa_sm && sta->wpa_sm->pmksa) {
u8 *pos, buf[257];
pos = buf;
wpa_printf(MSG_DEBUG, "OWE: Using PMKSA caching for Assoc Resp");
pos = wpa_auth_write_assoc_resp_owe(hapd, sta->wpa_sm, pos,
buf + sizeof(buf) - pos);
if (wpabuf_resize(&owe_buf, pos - buf) < 0) {
wpa_printf(MSG_ERROR, "OWE: wpabuf_resize failed for PMKSA assoc resp");
wpabuf_free(owe_buf);
*owe_ie_len = 0;
return NULL;
}
wpabuf_put_data(owe_buf, buf, pos - buf);
*owe_ie_len = pos - buf;
return owe_buf;
}
if (sta->owe_ecdh) {
if (!sta->wpa_sm) {
wpa_printf(MSG_ERROR, "OWE: Missing WPA state machine for assoc resp");
wpabuf_free(owe_buf);
*owe_ie_len = 0;
return NULL;
}
u8 buf[257];
u8 *pos = buf;
pos = wpa_auth_write_assoc_resp_owe(hapd, sta->wpa_sm, pos,
buf + sizeof(buf) - pos);
size_t rsne_len = (size_t)(pos - buf);
if (rsne_len == 0 || pos > buf + sizeof(buf)) {
wpa_printf(MSG_ERROR, "OWE: Failed to write RSN IE for assoc resp");
wpabuf_free(owe_buf);
*owe_ie_len = 0;
return NULL;
}
pub = crypto_ecdh_get_pubkey(sta->owe_ecdh, 0);
if (!pub) {
wpabuf_free(owe_buf);
*owe_ie_len = 0;
return NULL;
}
wpa_hexdump_buf(MSG_DEBUG, "Own public key", pub);
size_t dh_len = 5 + wpabuf_len(pub);
if (wpabuf_resize(&owe_buf, rsne_len + dh_len) < 0) {
wpa_printf(MSG_ERROR, "OWE: wpabuf_resize failed for assoc resp IEs");
wpabuf_free(pub);
wpabuf_free(owe_buf);
*owe_ie_len = 0;
return NULL;
}
wpabuf_put_data(owe_buf, buf, rsne_len);
wpabuf_put_u8(owe_buf, WLAN_EID_EXTENSION);
wpabuf_put_u8(owe_buf, 1 + 2 + wpabuf_len(pub));
wpabuf_put_u8(owe_buf, WLAN_EID_EXT_OWE_DH_PARAM);
wpabuf_put_le16(owe_buf, IANA_SECP256R1);
wpabuf_put_buf(owe_buf, pub);
wpabuf_free(pub);
wpa_hexdump_buf(MSG_DEBUG, "OWE: Buffer", owe_buf);
}
*owe_ie_len = wpabuf_len(owe_buf);
return owe_buf;
}
#endif /* CONFIG_OWE_SOFTAP */
@@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2020-2026 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@@ -20,4 +20,26 @@ void owe_deinit(void);
void esp_wifi_register_owe_cb(struct wpa_funcs *wpa_cb); void esp_wifi_register_owe_cb(struct wpa_funcs *wpa_cb);
#endif /* CONFIG_OWE_STA */ #endif /* CONFIG_OWE_STA */
#ifdef CONFIG_OWE_SOFTAP
#include "ap/hostapd.h"
/*
* OWE_DHIE_LEN: DH Parameter element length for group 19 (secp256r1).
*
* Wire format (IEEE 802.11 Extension element):
* byte 1 WLAN_EID_EXTENSION
* byte 2 length of remainder (extension ID + group + pubkey), typically 35
* byte 3 WLAN_EID_EXT_OWE_DH_PARAM (extension element ID)
* bytes 4–5 DH group ID (little-endian), e.g. IANA_SECP256R1 (19)
* bytes 6–37 DH public key (32 octets for this group/key representation)
*
* Total = 2 + 35 = 37 octets.
*/
#define OWE_DHIE_LEN 37
#define OWE_IE_INIT_LEN (257 + OWE_DHIE_LEN) /* RSNE + DH IE */
struct wpabuf *esp_owe_build_assoc_resp_dhie(struct hostapd_data *hapd, const u8 *bssid, int *owe_ie_len);
#endif /* CONFIG_OWE_SOFTAP */
#endif /* ESP_OWE_H */ #endif /* ESP_OWE_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 * SPDX-License-Identifier: Apache-2.0
*/ */
@@ -120,6 +120,21 @@ typedef struct {
uint8_t rsnxe_capa; uint8_t rsnxe_capa;
} wifi_wpa_ie_t; } 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 { struct wpa_funcs {
bool (*wpa_sta_init)(void); bool (*wpa_sta_init)(void);
bool (*wpa_sta_deinit)(void); bool (*wpa_sta_deinit)(void);
@@ -130,7 +145,7 @@ struct wpa_funcs {
bool (*wpa_sta_in_4way_handshake)(void); bool (*wpa_sta_in_4way_handshake)(void);
void *(*wpa_ap_init)(void); void *(*wpa_ap_init)(void);
bool (*wpa_ap_deinit)(void *data); 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); bool (*wpa_ap_join)(wpa_station_join_param_t *join);
bool (*wpa_ap_remove)(u8 *bssid); bool (*wpa_ap_remove)(u8 *bssid);
uint8_t *(*wpa_ap_get_wpa_ie)(size_t *len); 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); bool (*wpa_ap_rx_eapol)(void *hapd_data, void *sm, u8 *data, size_t data_len);
@@ -312,4 +327,6 @@ void esp_wifi_set_sigma_internal(bool flag);
void esp_wifi_ap_set_group_mgmt_cipher_internal(wifi_cipher_type_t cipher); 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); 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_is_wpa3_compatible_mode_enabled(uint8_t if_index); bool esp_wifi_is_wpa3_compatible_mode_enabled(uint8_t if_index);
uint8_t esp_wifi_ap_get_owe_config_internal(void);
#endif /* _ESP_WIFI_DRIVER_H_ */ #endif /* _ESP_WIFI_DRIVER_H_ */
@@ -389,12 +389,29 @@ static int check_n_add_wps_sta(struct hostapd_data *hapd, struct sta_info *sta_i
} }
#endif #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) static bool hostap_sta_join(wpa_station_join_param_t *join)
{ {
struct sta_info *sta_info = NULL; struct sta_info *sta_info = NULL;
struct hostapd_data *hapd = hostapd_get_hapd_data(); struct hostapd_data *hapd = hostapd_get_hapd_data();
uint8_t reason = WLAN_REASON_PREV_AUTH_NOT_VALID; 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) { if (!hapd) {
goto fail; goto fail;
} }
@@ -451,7 +468,19 @@ process_old_sta:
goto fail; goto fail;
} }
#endif #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)) {
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; goto done;
} else { } else {
goto fail; goto fail;
+15 -3
View File
@@ -395,9 +395,21 @@ const u8 * hostapd_get_psk(const struct hostapd_bss_config *conf,
const u8 *addr, const u8 *prev_psk); const u8 *addr, const u8 *prev_psk);
int hostapd_setup_wpa_psk(struct hostapd_bss_config *conf); int hostapd_setup_wpa_psk(struct hostapd_bss_config *conf);
struct sta_info; struct sta_info;
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, struct hostap_assoc_sta_req {
bool *pmf_enable, int subtype, uint8_t *pairwise_cipher, uint8_t *reason, uint8_t *rsn_selection_ie); 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); bool wpa_ap_remove(u8* bssid);
#endif /* HOSTAPD_CONFIG_H */ #endif /* HOSTAPD_CONFIG_H */
@@ -7,6 +7,7 @@
*/ */
#include "utils/includes.h" #include "utils/includes.h"
#include "utils/common.h"
#include "common/sae.h" #include "common/sae.h"
#include "common/ieee802_11_defs.h" #include "common/ieee802_11_defs.h"
#include "esp_wifi_driver.h" #include "esp_wifi_driver.h"
@@ -20,6 +21,13 @@
#include "esp_wpa3_i.h" #include "esp_wpa3_i.h"
#include "esp_hostap.h" #include "esp_hostap.h"
#ifdef CONFIG_OWE_SOFTAP
#include "crypto/crypto.h"
#include "ap/wpa_auth_i.h"
#include "esp_owe_i.h"
#define OWE_DH_GRP19 19
#endif
#ifdef CONFIG_SAE #ifdef CONFIG_SAE
static void sae_set_state(struct sta_info *sta, enum sae_state state, static void sae_set_state(struct sta_info *sta, enum sae_state state,
@@ -773,3 +781,183 @@ u16 wpa_res_to_status_code(enum wpa_validate_result res)
} }
return WLAN_STATUS_INVALID_IE; return WLAN_STATUS_INVALID_IE;
} }
#ifdef CONFIG_OWE_SOFTAP
int wpa_auth_pmksa_add2(struct wpa_authenticator *wpa_auth, const u8 *addr,
const u8 *pmk, size_t pmk_len, const u8 *pmkid,
int session_timeout, int akmp, const u8 *dpp_pkhash)
{
if (!wpa_auth || wpa_auth->conf.disable_pmksa_caching)
return -1;
struct rsn_pmksa_cache_entry *entry;
wpa_hexdump_key(MSG_DEBUG, "RSN: Cache PMK (3)", pmk, pmk_len);
entry = pmksa_cache_auth_add(wpa_auth->pmksa, pmk, pmk_len, pmkid,
NULL, 0, wpa_auth->addr, addr, session_timeout,
NULL, akmp);
if (!entry)
return -1;
return 0;
}
uint16_t owe_process_assoc_req(struct hostapd_data *hapd, struct sta_info *sta, const u8 *owe_dh,
u8 owe_dh_len)
{
const u8 *addr[2];
size_t len[2];
struct wpabuf *hkey, *pub, *secret;
const char *info = "OWE Key Generation";
u8 prk[SHA256_MAC_LEN];
u8 pmkid[SHA256_MAC_LEN];
int res;
if (wpa_auth_sta_get_pmksa(sta->wpa_sm)) {
wpa_printf(MSG_DEBUG, "OWE: Using PMKSA caching");
return WLAN_STATUS_SUCCESS;
}
if (!owe_dh || owe_dh_len < 5) {
wpa_printf(MSG_ERROR, "OWE: Invalid DH data received (len=%u)", owe_dh_len);
return WLAN_STATUS_UNSPECIFIED_FAILURE;
}
/* Set the group ID from DH param (extension IE: group at offset 3) */
sta->owe_group = WPA_GET_LE16(owe_dh + 3);
if (sta->owe_group != OWE_DH_GRP19)
return WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED;
if (owe_dh_len < OWE_DHIE_LEN - 2) {
wpa_printf(MSG_ERROR, "OWE: Invalid DH data received (len=%u)", owe_dh_len);
return WLAN_STATUS_UNSPECIFIED_FAILURE;
}
if (sta->owe_ecdh) {
/* This is a workaround for mac80211 behavior of retransmitting
* the Association Request frames multiple times if the link
* layer retries (i.e., seq# remains same) fail. The mac80211
* initiated retransmission will use a different seq# and as
* such, will go through duplicate detection. If we were to
* change our DH key for that attempt, there would be two
* different DH shared secrets and the STA would likely select
* the wrong one. */
wpa_printf(MSG_DEBUG,
"OWE: Try to reuse own previous DH key since the STA tried to go through OWE association again");
} else {
sta->owe_ecdh = crypto_ecdh_init(OWE_DH_GRP19);
if (!sta->owe_ecdh) {
wpa_printf(MSG_ERROR, "OWE: Error initializing ECDH for STA");
return WLAN_STATUS_UNSPECIFIED_FAILURE;
}
}
// Set up the DH shared secret
secret = crypto_ecdh_set_peerkey(sta->owe_ecdh, 0, owe_dh + 5, owe_dh_len - 3);
// secret = wpabuf_zeropad(secret, OWE_PRIME_LEN);
if (!secret) {
wpa_printf(MSG_ERROR, "OWE: Invalid peer DH public key");
return WLAN_STATUS_UNSPECIFIED_FAILURE;
}
wpa_hexdump_buf_key(MSG_DEBUG, "OWE: DH shared secret", secret);
/* prk = HKDF-extract(C | A | group, z) */
pub = crypto_ecdh_get_pubkey(sta->owe_ecdh, 0);
pub = wpabuf_zeropad(pub, 32);
if (!pub) {
wpabuf_clear_free(secret);
wpa_printf(MSG_ERROR, "OWE: Failed to retrieve public key");
return WLAN_STATUS_UNSPECIFIED_FAILURE;
}
/* PMKID = Truncate-128(Hash(C | A)) */
addr[0] = owe_dh + 5;
addr[1] = wpabuf_head(pub);
len[0] = owe_dh_len - 3;
len[1] = wpabuf_len(pub);
res = sha256_vector(2, addr, len, pmkid);
if (res < 0) {
wpabuf_free(pub);
wpabuf_clear_free(secret);
wpa_printf(MSG_ERROR, "OWE: PMKID calculation failed");
return WLAN_STATUS_UNSPECIFIED_FAILURE;
}
hkey = wpabuf_alloc(owe_dh_len - 3 + wpabuf_len(pub) + 2);
if (!hkey) {
wpabuf_free(pub);
wpabuf_clear_free(secret);
wpa_printf(MSG_ERROR, "OWE: Memory allocation failed for hkey buffer");
return WLAN_STATUS_UNSPECIFIED_FAILURE;
}
wpa_hexdump(MSG_DEBUG, "Peer public key", owe_dh+5, owe_dh_len-3);
wpabuf_put_data(hkey, owe_dh + 5, owe_dh_len - 3); /* C */
wpabuf_put_buf(hkey, pub); /* A */
wpabuf_free(pub);
wpabuf_put_le16(hkey, sta->owe_group); /* group */
res = hmac_sha256(wpabuf_head(hkey), wpabuf_len(hkey),
wpabuf_head(secret), wpabuf_len(secret), prk);
wpabuf_clear_free(hkey);
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) */
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) {
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;
}
wpa_hexdump_key(MSG_DEBUG, "OWE: PMK", sta->owe_pmk, PMK_LEN);
wpa_hexdump(MSG_DEBUG, "OWE: PMKID", pmkid, PMKID_LEN);
sta->owe_pmk_len = SHA256_MAC_LEN;
// 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) {
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;
}
// Update the PMKID in the STA's WPA state machine
os_memcpy(sta->wpa_sm->pmkid, pmkid, PMKID_LEN);
sta->wpa_sm->pmkid_set = 1;
return WLAN_STATUS_SUCCESS;
}
#endif /* CONFIG_OWE_SOFTAP */
@@ -16,5 +16,9 @@ int handle_auth_sae(struct hostapd_data *hapd, struct sta_info *sta,
u8 *buf, size_t len, u8 *bssid, u8 *buf, size_t len, u8 *bssid,
u16 auth_transaction, u16 status); u16 auth_transaction, u16 status);
u16 wpa_res_to_status_code(enum wpa_validate_result res); u16 wpa_res_to_status_code(enum wpa_validate_result res);
#ifdef CONFIG_OWE_SOFTAP
uint16_t owe_process_assoc_req(struct hostapd_data *hapd, struct sta_info *sta, const u8 *owe_dh,
u8 owe_dh_len);
#endif /* CONFIG_OWE_SOFTAP */
#endif /* IEEE802_11_H */ #endif /* IEEE802_11_H */
@@ -127,6 +127,10 @@ void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta)
wpabuf_free(sta->wps_ie); wpabuf_free(sta->wps_ie);
#endif #endif
#ifdef CONFIG_OWE_SOFTAP
bin_clear_free(sta->owe_pmk, PMK_LEN);
crypto_ecdh_deinit(sta->owe_ecdh);
#endif /* CONFIG_OWE_SOFTAP */
os_free(sta); os_free(sta);
} }
@@ -69,6 +69,12 @@ struct sta_info {
struct wpabuf *sae_data; struct wpabuf *sae_data;
#endif /* CONFIG_SAE */ #endif /* CONFIG_SAE */
#endif /* ESP_SUPPLICANT */ #endif /* ESP_SUPPLICANT */
#ifdef CONFIG_OWE_SOFTAP
u16 owe_group;
u8 *owe_pmk;
size_t owe_pmk_len;
struct crypto_ecdh *owe_ecdh;
#endif /* CONFIG_OWE_SOFTAP */
}; };
+34 -3
View File
@@ -136,8 +136,9 @@ static inline const u8 * wpa_auth_get_psk(struct wpa_authenticator *wpa_auth,
return NULL; return NULL;
} }
#ifdef CONFIG_SAE #if defined(CONFIG_SAE) || defined(CONFIG_OWE_SOFTAP)
struct sta_info *sta = ap_get_sta(hapd, addr); struct sta_info *sta = ap_get_sta(hapd, addr);
#ifdef CONFIG_SAE
if (sta && sta->auth_alg == WLAN_AUTH_SAE) { if (sta && sta->auth_alg == WLAN_AUTH_SAE) {
if (!sta->sae || prev_psk) if (!sta->sae || prev_psk)
return NULL; return NULL;
@@ -150,6 +151,24 @@ static inline const u8 * wpa_auth_get_psk(struct wpa_authenticator *wpa_auth,
} }
#endif /*CONFIG_SAE*/ #endif /*CONFIG_SAE*/
#ifdef CONFIG_OWE_SOFTAP
if ((hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_OWE) &&
sta && sta->owe_pmk) {
return sta->owe_pmk;
}
if ((hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_OWE) && sta) {
struct rsn_pmksa_cache_entry *sa;
sa = wpa_auth_sta_get_pmksa(sta->wpa_sm);
if (sa && sa->akmp == WPA_KEY_MGMT_OWE) {
return sa->pmk;
}
}
#endif /* CONFIG_OWE_SOFTAP */
#endif /* defined(CONFIG_SAE) || defined(CONFIG_OWE_SOFTAP) */
return (u8*)hostapd_get_psk(hapd->conf, addr, prev_psk); return (u8*)hostapd_get_psk(hapd->conf, addr, prev_psk);
} }
@@ -1030,6 +1049,12 @@ void wpa_auth_add_sae_pmkid(struct wpa_state_machine *sm, const u8 *pmkid)
sm->pmkid_set = 1; sm->pmkid_set = 1;
} }
struct rsn_pmksa_cache_entry *
wpa_auth_sta_get_pmksa(struct wpa_state_machine *sm)
{
return sm ? sm->pmksa : NULL;
}
static int wpa_gmk_to_gtk(const u8 *gmk, const char *label, const u8 *addr, static int wpa_gmk_to_gtk(const u8 *gmk, const char *label, const u8 *addr,
const u8 *gnonce, u8 *gtk, size_t gtk_len) const u8 *gnonce, u8 *gtk, size_t gtk_len)
{ {
@@ -1465,7 +1490,8 @@ SM_STATE(WPA_PTK, INITIALIZE)
wpa_remove_ptk(sm); wpa_remove_ptk(sm);
wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_portValid, 0); wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_portValid, 0);
sm->TimeoutCtr = 0; sm->TimeoutCtr = 0;
if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt)) { if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) ||
sm->wpa_key_mgmt == WPA_KEY_MGMT_OWE) {
wpa_auth_set_eapol(sm->wpa_auth, sm->addr, wpa_auth_set_eapol(sm->wpa_auth, sm->addr,
WPA_EAPOL_authorized, 0); WPA_EAPOL_authorized, 0);
} }
@@ -1624,6 +1650,9 @@ SM_STATE(WPA_PTK, INITPSK)
psk = wpa_auth_get_psk(sm->wpa_auth, sm->addr, NULL); psk = wpa_auth_get_psk(sm->wpa_auth, sm->addr, NULL);
if (psk) { if (psk) {
memcpy(sm->PMK, psk, PMK_LEN); memcpy(sm->PMK, psk, PMK_LEN);
#ifdef CONFIG_OWE_SOFTAP
sm->pmk_len = PMK_LEN;
#endif
#ifdef CONFIG_IEEE80211R_AP #ifdef CONFIG_IEEE80211R_AP
memcpy(sm->xxkey, psk, PMK_LEN); memcpy(sm->xxkey, psk, PMK_LEN);
sm->xxkey_len = PMK_LEN; sm->xxkey_len = PMK_LEN;
@@ -1662,6 +1691,7 @@ SM_STATE(WPA_PTK, PTKSTART)
*/ */
if (sm->wpa == WPA_VERSION_WPA2 && if (sm->wpa == WPA_VERSION_WPA2 &&
(wpa_key_mgmt_wpa_ieee8021x(sm->wpa_key_mgmt) || (wpa_key_mgmt_wpa_ieee8021x(sm->wpa_key_mgmt) ||
(sm->wpa_key_mgmt == WPA_KEY_MGMT_OWE && sm->pmksa) ||
wpa_key_mgmt_sae(sm->wpa_key_mgmt))) { wpa_key_mgmt_sae(sm->wpa_key_mgmt))) {
pmkid = buf; pmkid = buf;
pmkid_len = 2 + RSN_SELECTOR_LEN + PMKID_LEN; pmkid_len = 2 + RSN_SELECTOR_LEN + PMKID_LEN;
@@ -2246,7 +2276,8 @@ SM_STEP(WPA_PTK)
wpa_auth_get_eapol(sm->wpa_auth, sm->addr, wpa_auth_get_eapol(sm->wpa_auth, sm->addr,
WPA_EAPOL_keyRun) > 0) WPA_EAPOL_keyRun) > 0)
SM_ENTER(WPA_PTK, INITPMK); SM_ENTER(WPA_PTK, INITPMK);
else if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) else if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) ||
(sm->wpa_key_mgmt == WPA_KEY_MGMT_OWE)
/* FIX: && 802.1X::keyRun */) /* FIX: && 802.1X::keyRun */)
SM_ENTER(WPA_PTK, INITPSK); SM_ENTER(WPA_PTK, INITPSK);
break; break;
@@ -12,6 +12,7 @@
#include "common/defs.h" #include "common/defs.h"
#include "common/eapol_common.h" #include "common/eapol_common.h"
#include "common/wpa_common.h" #include "common/wpa_common.h"
#include "ap/hostapd.h"
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma pack(push, 1) #pragma pack(push, 1)
@@ -327,5 +328,7 @@ static inline bool wpa_auth_pmf_enabled(struct wpa_auth_config *conf)
return conf->ieee80211w != NO_MGMT_FRAME_PROTECTION; return conf->ieee80211w != NO_MGMT_FRAME_PROTECTION;
#endif #endif
} }
uint8_t *wpa_auth_write_assoc_resp_owe(struct hostapd_data *hapd, struct wpa_state_machine *sm,
u8 *pos, size_t max_len);
#endif /* WPA_AUTH_H */ #endif /* WPA_AUTH_H */
@@ -234,6 +234,13 @@ static u8 * rsne_write_data(u8 *buf, size_t len, u8 *pos, int group,
num_suites++; num_suites++;
} }
#endif /* CONFIG_SAE */ #endif /* CONFIG_SAE */
#ifdef CONFIG_OWE_SOFTAP
if (key_mgmt & WPA_KEY_MGMT_OWE) {
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_OWE);
pos += RSN_SELECTOR_LEN;
num_suites++;
}
#endif /* CONFIG_OWE_SOFTAP */
#ifdef CONFIG_RSN_TESTING #ifdef CONFIG_RSN_TESTING
if (rsn_testing) { if (rsn_testing) {
@@ -611,6 +618,10 @@ wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth,
selector = RSN_AUTH_KEY_MGMT_UNSPEC_802_1X; selector = RSN_AUTH_KEY_MGMT_UNSPEC_802_1X;
else if (data.key_mgmt & WPA_KEY_MGMT_PSK) else if (data.key_mgmt & WPA_KEY_MGMT_PSK)
selector = RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X; selector = RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X;
#ifdef CONFIG_OWE_SOFTAP
else if (data.key_mgmt & WPA_KEY_MGMT_OWE)
selector = RSN_AUTH_KEY_MGMT_OWE;
#endif /* CONFIG_OWE_SOFTAP */
selector = wpa_cipher_to_suite(WPA_PROTO_RSN, selector = wpa_cipher_to_suite(WPA_PROTO_RSN,
data.pairwise_cipher); data.pairwise_cipher);
@@ -692,6 +703,10 @@ wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth,
#endif /* CONFIG_SAE */ #endif /* CONFIG_SAE */
else if (key_mgmt & WPA_KEY_MGMT_IEEE8021X) else if (key_mgmt & WPA_KEY_MGMT_IEEE8021X)
sm->wpa_key_mgmt = WPA_KEY_MGMT_IEEE8021X; sm->wpa_key_mgmt = WPA_KEY_MGMT_IEEE8021X;
#ifdef CONFIG_OWE_SOFTAP
else if (key_mgmt & WPA_KEY_MGMT_OWE)
sm->wpa_key_mgmt = WPA_KEY_MGMT_OWE;
#endif /* CONFIG_OWE_SOFTAP */
else else
sm->wpa_key_mgmt = WPA_KEY_MGMT_PSK; sm->wpa_key_mgmt = WPA_KEY_MGMT_PSK;
@@ -810,6 +825,12 @@ wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth,
os_memcpy(wpa_auth->dot11RSNAPMKIDUsed, pmkid, PMKID_LEN); os_memcpy(wpa_auth->dot11RSNAPMKIDUsed, pmkid, PMKID_LEN);
} }
#ifdef CONFIG_OWE_SOFTAP
if (sm->wpa_key_mgmt == WPA_KEY_MGMT_OWE && !sm->pmksa) {
wpa_printf(MSG_DEBUG, "No PMKSA cache entry found for OWE");
}
#endif /* CONFIG_OWE_SOFTAP */
#ifdef CONFIG_SAE #ifdef CONFIG_SAE
if ((sm->wpa_key_mgmt == WPA_KEY_MGMT_SAE || sm->wpa_key_mgmt == WPA_KEY_MGMT_SAE_EXT_KEY) && data.num_pmkid && if ((sm->wpa_key_mgmt == WPA_KEY_MGMT_SAE || sm->wpa_key_mgmt == WPA_KEY_MGMT_SAE_EXT_KEY) && data.num_pmkid &&
!sm->pmksa) { !sm->pmksa) {
@@ -847,3 +868,18 @@ int wpa_auth_uses_mfp(struct wpa_state_machine *sm)
{ {
return sm ? sm->mgmt_frame_prot : 0; return sm ? sm->mgmt_frame_prot : 0;
} }
#ifdef CONFIG_OWE_SOFTAP
uint8_t *wpa_auth_write_assoc_resp_owe(struct hostapd_data *hapd, struct wpa_state_machine *sm,
u8 *pos, size_t max_len)
{
int res;
res = wpa_write_rsn_ie(&hapd->wpa_auth->conf, pos, max_len,
sm->pmksa ? sm->pmksa->pmkid : NULL);
if (res < 0)
return pos;
return pos + res;
}
#endif /* CONFIG_OWE_SOFTAP */
@@ -358,10 +358,10 @@ static int rsn_key_mgmt_to_bitfield(const u8 *s)
if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_802_1X_SUITE_B_192) if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_802_1X_SUITE_B_192)
return WPA_KEY_MGMT_IEEE8021X_SUITE_B_192; return WPA_KEY_MGMT_IEEE8021X_SUITE_B_192;
#endif #endif
#ifdef CONFIG_OWE_STA #if defined(CONFIG_OWE_STA) || defined(CONFIG_OWE_SOFTAP)
if(RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_OWE) if(RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_OWE)
return WPA_KEY_MGMT_OWE; return WPA_KEY_MGMT_OWE;
#endif /* CONFIG_OWE_STA */ #endif /* CONFIG_OWE_STA || CONFIG_OWE_SOFTAP */
#ifdef CONFIG_DPP #ifdef CONFIG_DPP
if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_DPP) if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_DPP)
return WPA_KEY_MGMT_DPP; return WPA_KEY_MGMT_DPP;
@@ -987,7 +987,7 @@ int wpa_eapol_key_mic(const u8 *key, size_t key_len, int akmp, int ver,
os_memcpy(mic, hash, 24); os_memcpy(mic, hash, 24);
break; break;
#endif /* CONFIG_SUITEB192 */ #endif /* CONFIG_SUITEB192 */
#ifdef CONFIG_OWE_STA #if defined(CONFIG_OWE_STA) || defined(CONFIG_OWE_SOFTAP)
case WPA_KEY_MGMT_OWE: case WPA_KEY_MGMT_OWE:
wpa_printf(MSG_DEBUG, wpa_printf(MSG_DEBUG,
"WPA: EAPOL-Key MIC using HMAC-SHA%u (AKM-defined - OWE)", "WPA: EAPOL-Key MIC using HMAC-SHA%u (AKM-defined - OWE)",
@@ -1003,7 +1003,7 @@ int wpa_eapol_key_mic(const u8 *key, size_t key_len, int akmp, int ver,
os_memcpy(mic, hash, key_len); os_memcpy(mic, hash, key_len);
break; break;
#endif /* CONFIG_OWE_STA */ #endif /* CONFIG_OWE_STA || CONFIG_OWE_SOFTAP */
#ifdef CONFIG_DPP #ifdef CONFIG_DPP
case WPA_KEY_MGMT_DPP: case WPA_KEY_MGMT_DPP:
wpa_printf(MSG_DEBUG, wpa_printf(MSG_DEBUG,
+8 -1
View File
@@ -157,10 +157,17 @@ Enhanced Open™ is used for providing security and privacy to users connecting
.. note:: .. note::
{IDF_TARGET_NAME} supports Wi-Fi Enhanced Open™ only in station mode. {IDF_TARGET_NAME} supports Wi-Fi Enhanced Open™ in station mode for both OWE Transition Mode and OWE-only networks. In SoftAP mode, only **OWE-only** operation is supported; **OWE Transition Mode is not supported**.
Setting up OWE with {IDF_TARGET_NAME} Setting up OWE with {IDF_TARGET_NAME}
++++++++++++++++++++++++++++++++++++++ ++++++++++++++++++++++++++++++++++++++
For station mode :
A configuration option :ref:`CONFIG_ESP_WIFI_ENABLE_WPA3_OWE_STA` and configuration parameter :cpp:type:`owe_enabled` in :cpp:type:`wifi_sta_config_t` is provided to enable OWE support for the station. To use OWE transition mode, along with the configuration provided above, `authmode` from :cpp:type:`wifi_scan_threshold_t` should be set to ``WIFI_AUTH_OPEN``. A configuration option :ref:`CONFIG_ESP_WIFI_ENABLE_WPA3_OWE_STA` and configuration parameter :cpp:type:`owe_enabled` in :cpp:type:`wifi_sta_config_t` is provided to enable OWE support for the station. To use OWE transition mode, along with the configuration provided above, `authmode` from :cpp:type:`wifi_scan_threshold_t` should be set to ``WIFI_AUTH_OPEN``.
For softap mode :
A configuration option :ref:`CONFIG_ESP_WIFI_ENABLE_WPA3_OWE_SOFTAP` from menuconfig should be enabled and configuration parameter `authmode` from :cpp:type:`wifi_ap_config_t` should be set to ``WIFI_AUTH_OWE``. SoftAP does not support OWE Transition Mode; configure ``WIFI_AUTH_OWE`` only.
@@ -90,7 +90,7 @@ void wifi_init_softap(void)
.gtk_rekey_interval = EXAMPLE_GTK_REKEY_INTERVAL, .gtk_rekey_interval = EXAMPLE_GTK_REKEY_INTERVAL,
}, },
}; };
if (strlen(EXAMPLE_ESP_WIFI_PASS) == 0) { if (strlen(EXAMPLE_ESP_WIFI_PASS) == 0 && wifi_config.ap.authmode != WIFI_AUTH_OWE) {
wifi_config.ap.authmode = WIFI_AUTH_OPEN; wifi_config.ap.authmode = WIFI_AUTH_OPEN;
} }