From e83d0debf1f32f04928cabe91062ff2c42175a72 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 12 Mar 2017 00:32:23 +0200 Subject: [PATCH 01/13] OWE: Define and parse OWE AKM selector This adds a new RSN AKM "OWE". Signed-off-by: Jouni Malinen --- .../esp_supplicant/src/esp_hostap.c | 10 ++++++++- .../wpa_supplicant/src/ap/wpa_auth_ie.c | 21 +++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/components/wpa_supplicant/esp_supplicant/src/esp_hostap.c b/components/wpa_supplicant/esp_supplicant/src/esp_hostap.c index 550f35ca2b7..300b14c42a9 100644 --- a/components/wpa_supplicant/esp_supplicant/src/esp_hostap.c +++ b/components/wpa_supplicant/esp_supplicant/src/esp_hostap.c @@ -48,7 +48,8 @@ static bool authmode_has_rsn(uint8_t authmode) return (authmode == WIFI_AUTH_WPA2_PSK || authmode == WIFI_AUTH_WPA_WPA2_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) @@ -192,6 +193,13 @@ void *hostap_init(void) #endif /* CONFIG_IEEE80211W */ 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); 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); diff --git a/components/wpa_supplicant/src/ap/wpa_auth_ie.c b/components/wpa_supplicant/src/ap/wpa_auth_ie.c index 7d01d002efe..79a836443f5 100644 --- a/components/wpa_supplicant/src/ap/wpa_auth_ie.c +++ b/components/wpa_supplicant/src/ap/wpa_auth_ie.c @@ -234,6 +234,13 @@ static u8 * rsne_write_data(u8 *buf, size_t len, u8 *pos, int group, num_suites++; } #endif /* CONFIG_SAE */ +#ifdef CONFIG_OWE_SOFTAP + if (conf->wpa_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 if (rsn_testing) { @@ -611,6 +618,10 @@ wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth, selector = RSN_AUTH_KEY_MGMT_UNSPEC_802_1X; else if (data.key_mgmt & WPA_KEY_MGMT_PSK) 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, data.pairwise_cipher); @@ -692,6 +703,10 @@ wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth, #endif /* CONFIG_SAE */ else if (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 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); } +#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 if ((sm->wpa_key_mgmt == WPA_KEY_MGMT_SAE || sm->wpa_key_mgmt == WPA_KEY_MGMT_SAE_EXT_KEY) && data.num_pmkid && !sm->pmksa) { From 5df40634965d07dec13104adf11af7646526c8ed Mon Sep 17 00:00:00 2001 From: Aditi Date: Thu, 27 Mar 2025 11:17:43 +0530 Subject: [PATCH 02/13] feat(esp_wifi): Add CONFIG option for CONFIG_OWE_SOFTAP --- components/esp_wifi/Kconfig | 10 ++++++++++ components/wpa_supplicant/CMakeLists.txt | 3 +++ 2 files changed, 13 insertions(+) diff --git a/components/esp_wifi/Kconfig b/components/esp_wifi/Kconfig index 66b8ac6b07e..5f57d67ad07 100644 --- a/components/esp_wifi/Kconfig +++ b/components/esp_wifi/Kconfig @@ -346,6 +346,16 @@ menu "Wi-Fi" help 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 n + 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. + PMF (Protected Management Frames) is a prerequisite feature, it needs to be explicitly configured + before attempting connection. Please refer to the Wi-Fi Driver API Guide for details. + config ESP_WIFI_SLP_IRAM_OPT bool "WiFi SLP IRAM speed optimization" select PM_SLP_DEFAULT_PARAMS_OPT diff --git a/components/wpa_supplicant/CMakeLists.txt b/components/wpa_supplicant/CMakeLists.txt index 6028a2b9238..61a95b95987 100644 --- a/components/wpa_supplicant/CMakeLists.txt +++ b/components/wpa_supplicant/CMakeLists.txt @@ -362,4 +362,7 @@ endif() if(CONFIG_ESP_WIFI_NAN_USD_ENABLE) target_compile_definitions(${COMPONENT_LIB} PRIVATE CONFIG_NAN_USD) 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) From acfebf2a756452544d033eb6094722ff5c61619b Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 12 Mar 2017 01:26:43 +0200 Subject: [PATCH 03/13] OWE: Process Diffie-Hellman Parameter element in AP mode This adds AP side processing for OWE Diffie-Hellman Parameter element in (Re)Association Request frame and adding it in (Re)Association Response frame. Signed-off-by: Jouni Malinen --- .../esp_supplicant/src/esp_hostap.c | 55 ++++++++++- .../esp_supplicant/src/esp_wifi_driver.h | 2 +- .../esp_supplicant/src/esp_wpa_main.c | 5 +- components/wpa_supplicant/src/ap/ap_config.h | 4 +- components/wpa_supplicant/src/ap/ieee802_11.c | 95 +++++++++++++++++++ components/wpa_supplicant/src/ap/ieee802_11.h | 5 +- components/wpa_supplicant/src/ap/sta_info.c | 4 + components/wpa_supplicant/src/ap/sta_info.h | 4 + components/wpa_supplicant/src/ap/wpa_auth.c | 7 ++ 9 files changed, 174 insertions(+), 7 deletions(-) diff --git a/components/wpa_supplicant/esp_supplicant/src/esp_hostap.c b/components/wpa_supplicant/esp_supplicant/src/esp_hostap.c index 300b14c42a9..3ce012b32a3 100644 --- a/components/wpa_supplicant/esp_supplicant/src/esp_hostap.c +++ b/components/wpa_supplicant/esp_supplicant/src/esp_hostap.c @@ -28,6 +28,11 @@ #include "ap/ieee802_11.h" #define WIFI_PASSWORD_LEN_MAX 65 +#ifdef CONFIG_OWE_SOFTAP +#include "crypto/crypto.h" +#include "ap/ieee802_11.h" +#endif + struct hostapd_data *global_hapd; #ifdef CONFIG_SAE @@ -379,8 +384,46 @@ u16 esp_send_assoc_resp(struct hostapd_data *hapd, const u8 *addr, if (!omit_rsnxe) { send_len = esp_wifi_build_rsnxe(hapd, buf, ASSOC_RESP_LENGTH); } +#ifdef CONFIG_OWE_SOFTAP +#define OWE_DH_GROUP 19 + if ((hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_OWE)) { + struct wpabuf *pub; + struct sta_info *sta = ap_get_sta(hapd, addr); + if (!sta) { + return WLAN_STATUS_UNSPECIFIED_FAILURE; + } + pub = crypto_ecdh_get_pubkey(sta->owe_ecdh, 0); + if (!pub) { + res = WLAN_STATUS_UNSPECIFIED_FAILURE; + return res; + } + + struct wpabuf *owe_buf = wpabuf_alloc(37); + if (!owe_buf) { + wpa_printf(MSG_ERROR, "Memory allocation failed for OWE IE"); + return WLAN_STATUS_UNSPECIFIED_FAILURE; + } + + + wpa_hexdump_buf(MSG_DEBUG, "Own public key", pub); + + // wpabuf_resize(&owe_buf, OWE_DHIE_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); + int owe_ie_len = wpabuf_len(owe_buf); + + esp_wifi_set_appie_internal(WIFI_APPIE_ASSOC_RESP, (uint8_t *)wpabuf_head(owe_buf), owe_ie_len, 0); + } +#else esp_wifi_set_appie_internal(WIFI_APPIE_ASSOC_RESP, buf, send_len, 0); +#endif /* CONFIG_OWE_SOFTAP */ reply = os_zalloc(sizeof(wifi_mgmt_frm_req_t) + sizeof(uint16_t)); if (!reply) { @@ -426,7 +469,7 @@ 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) + 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 hostapd_data *hapd = (struct hostapd_data*)esp_wifi_get_hostap_private_internal(); enum wpa_validate_result res = WPA_IE_OK; @@ -476,6 +519,16 @@ bool hostap_new_assoc_sta(struct sta_info *sta, uint8_t *bssid, u8 *wpa_ie, status = wpa_res_to_status_code(res); +#ifdef CONFIG_OWE_SOFTAP + if (hapd->conf->wpa_key_mgmt == WPA_KEY_MGMT_OWE) { + status = owe_process_assoc_req(sta, owe_dh, owe_ie_len); + if (status != WLAN_STATUS_SUCCESS) { + return status; + } + } +#endif /* CONFIG_OWE_SOFTAP */ + + send_resp: if (!rsnxe) { omit_rsnxe = true; 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 e1361ab5f2d..199c4c03754 100644 --- a/components/wpa_supplicant/esp_supplicant/src/esp_wifi_driver.h +++ b/components/wpa_supplicant/esp_supplicant/src/esp_wifi_driver.h @@ -130,7 +130,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); + 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_dh, uint8_t owe_ie_len); 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 0e481718e96..990be107e08 100644 --- a/components/wpa_supplicant/esp_supplicant/src/esp_wpa_main.c +++ b/components/wpa_supplicant/esp_supplicant/src/esp_wpa_main.c @@ -389,7 +389,7 @@ 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) +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) { struct sta_info *sta_info = NULL; struct hostapd_data *hapd = hostapd_get_hapd_data(); @@ -451,7 +451,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, rsn_selection_ie)) { + + 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)) { 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 49aa678c82c..65d5dc7c386 100644 --- a/components/wpa_supplicant/src/ap/ap_config.h +++ b/components/wpa_supplicant/src/ap/ap_config.h @@ -395,9 +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, u8 *wpa_ie, +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); + 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 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 786987eb80f..9c8493faf4d 100644 --- a/components/wpa_supplicant/src/ap/ieee802_11.c +++ b/components/wpa_supplicant/src/ap/ieee802_11.c @@ -773,3 +773,98 @@ u16 wpa_res_to_status_code(enum wpa_validate_result res) } return WLAN_STATUS_INVALID_IE; } + +#ifdef CONFIG_OWE_SOFTAP +#include "crypto/crypto.h" +#define OWE_DH_GROUP 19 +uint16_t owe_process_assoc_req(struct sta_info *sta, const uint8_t *owe_dh, + uint8_t owe_dh_len) +{ + struct wpabuf *secret, *pub, *hkey; + int res; + u8 prk[SHA256_MAC_LEN], pmkid[SHA256_MAC_LEN]; + const char *info = "OWE Key Generation"; + const u8 *addr[2]; + size_t len[2]; + + if (WPA_GET_LE16(owe_dh + 3) != OWE_DH_GROUP) + return WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED; + + crypto_ecdh_deinit(sta->owe_ecdh); + sta->owe_ecdh = crypto_ecdh_init(OWE_DH_GROUP); + if (!sta->owe_ecdh) + return WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED; + + secret = crypto_ecdh_set_peerkey(sta->owe_ecdh, 0, owe_dh + 5, + owe_dh_len - 3); + if (!secret) { + wpa_printf(MSG_DEBUG, "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); + if (!pub) { + wpabuf_clear_free(secret); + return WLAN_STATUS_UNSPECIFIED_FAILURE; + } + + /* PMKID = Truncate-128(Hash(C | A)) */ + addr[0] = owe_dh + 5; + len[0] = owe_dh_len - 3; + addr[1] = wpabuf_head(pub); + len[1] = wpabuf_len(pub); + res = sha256_vector(2, addr, len, pmkid); + if (res < 0) { + wpabuf_free(pub); + wpabuf_clear_free(secret); + 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); + return WLAN_STATUS_UNSPECIFIED_FAILURE; + } + + 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, OWE_DH_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) + 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(PMK_LEN); + if (!sta->owe_pmk) { + os_memset(prk, 0, SHA256_MAC_LEN); + return WLAN_STATUS_UNSPECIFIED_FAILURE; + } + + res = hmac_sha256_kdf(prk, SHA256_MAC_LEN, NULL, (const u8 *) info, + os_strlen(info), sta->owe_pmk, PMK_LEN); + os_memset(prk, 0, SHA256_MAC_LEN); + if (res < 0) { + os_free(sta->owe_pmk); + sta->owe_pmk = NULL; + 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); + /* TODO: Add PMKSA cache entry */ + + return WLAN_STATUS_SUCCESS; +} +#endif /* CONFIG_OWE_SOFTAP */ diff --git a/components/wpa_supplicant/src/ap/ieee802_11.h b/components/wpa_supplicant/src/ap/ieee802_11.h index 2136a1e2c32..7c59f84ceac 100644 --- a/components/wpa_supplicant/src/ap/ieee802_11.h +++ b/components/wpa_supplicant/src/ap/ieee802_11.h @@ -16,5 +16,8 @@ int handle_auth_sae(struct hostapd_data *hapd, struct sta_info *sta, u8 *buf, size_t len, u8 *bssid, u16 auth_transaction, u16 status); u16 wpa_res_to_status_code(enum wpa_validate_result res); - +#ifdef CONFIG_OWE_SOFTAP +uint16_t owe_process_assoc_req(struct sta_info *sta, const uint8_t *owe_dh, + uint8_t owe_dh_len); +#endif #endif /* IEEE802_11_H */ diff --git a/components/wpa_supplicant/src/ap/sta_info.c b/components/wpa_supplicant/src/ap/sta_info.c index 28daefb5479..dde4cbb94c8 100644 --- a/components/wpa_supplicant/src/ap/sta_info.c +++ b/components/wpa_supplicant/src/ap/sta_info.c @@ -127,6 +127,10 @@ void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta) wpabuf_free(sta->wps_ie); #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); } diff --git a/components/wpa_supplicant/src/ap/sta_info.h b/components/wpa_supplicant/src/ap/sta_info.h index 3c3769dd1af..38906c3112f 100644 --- a/components/wpa_supplicant/src/ap/sta_info.h +++ b/components/wpa_supplicant/src/ap/sta_info.h @@ -69,6 +69,10 @@ struct sta_info { struct wpabuf *sae_data; #endif /* CONFIG_SAE */ #endif /* ESP_SUPPLICANT */ +#ifdef CONFIG_OWE_SOFTAP + u8 *owe_pmk; + struct crypto_ecdh *owe_ecdh; +#endif /* CONFIG_OWE_SOFTAP */ }; diff --git a/components/wpa_supplicant/src/ap/wpa_auth.c b/components/wpa_supplicant/src/ap/wpa_auth.c index da60b9d23e0..54fbeb1444e 100644 --- a/components/wpa_supplicant/src/ap/wpa_auth.c +++ b/components/wpa_supplicant/src/ap/wpa_auth.c @@ -150,6 +150,13 @@ static inline const u8 * wpa_auth_get_psk(struct wpa_authenticator *wpa_auth, } #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; + } +#endif /* CONFIG_OWE_SOFTAP */ + + return (u8*)hostapd_get_psk(hapd->conf, addr, prev_psk); } From c8b6ff88de72d4106dde0778f862ba2874b7a511 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 8 Oct 2017 13:49:45 +0300 Subject: [PATCH 04/13] OWE: Include RSNE in (Re)Association Response frame This is not normally done in RSN, but RFC 8110 seems to imply that AP has to include OWE AKM in the RSNE within these frames. So, add the RSNE to (Re)Association Response frames when OWE is being negotiated. Signed-off-by: Jouni Malinen --- .../esp_supplicant/src/esp_hostap.c | 33 +++++++++++++------ components/wpa_supplicant/src/ap/wpa_auth.h | 2 ++ .../wpa_supplicant/src/ap/wpa_auth_ie.c | 14 ++++++++ 3 files changed, 39 insertions(+), 10 deletions(-) diff --git a/components/wpa_supplicant/esp_supplicant/src/esp_hostap.c b/components/wpa_supplicant/esp_supplicant/src/esp_hostap.c index 3ce012b32a3..1f3ebd9e617 100644 --- a/components/wpa_supplicant/esp_supplicant/src/esp_hostap.c +++ b/components/wpa_supplicant/esp_supplicant/src/esp_hostap.c @@ -385,7 +385,8 @@ u16 esp_send_assoc_resp(struct hostapd_data *hapd, const u8 *addr, send_len = esp_wifi_build_rsnxe(hapd, buf, ASSOC_RESP_LENGTH); } #ifdef CONFIG_OWE_SOFTAP -#define OWE_DH_GROUP 19 +#define OWE_DH_GROUP 19 +#define OWE_DHIE_LEN 37 if ((hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_OWE)) { struct wpabuf *pub; struct sta_info *sta = ap_get_sta(hapd, addr); @@ -393,22 +394,35 @@ u16 esp_send_assoc_resp(struct hostapd_data *hapd, const u8 *addr, return WLAN_STATUS_UNSPECIFIED_FAILURE; } + struct wpabuf *owe_buf = wpabuf_alloc(hapd->wpa_auth->wpa_ie_len); + if (!owe_buf) { + wpa_printf(MSG_ERROR, "Memory allocation failed for OWE IE"); + return WLAN_STATUS_UNSPECIFIED_FAILURE; + } + + u8 *pos, buf[128]; + int res; + int owe_ie_len = 0; + + pos = buf; + + pos = wpa_auth_write_assoc_resp_owe(sta->wpa_sm, pos, + buf + sizeof(buf) - pos); + + wpabuf_resize(&owe_buf, pos - buf); + wpabuf_put_data(owe_buf, buf, pos - buf); + owe_ie_len = pos - buf; + pub = crypto_ecdh_get_pubkey(sta->owe_ecdh, 0); if (!pub) { res = WLAN_STATUS_UNSPECIFIED_FAILURE; return res; } - struct wpabuf *owe_buf = wpabuf_alloc(37); - if (!owe_buf) { - wpa_printf(MSG_ERROR, "Memory allocation failed for OWE IE"); - return WLAN_STATUS_UNSPECIFIED_FAILURE; - } - wpa_hexdump_buf(MSG_DEBUG, "Own public key", pub); - // wpabuf_resize(&owe_buf, OWE_DHIE_LEN); + wpabuf_resize(&owe_buf, OWE_DHIE_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); @@ -417,7 +431,7 @@ u16 esp_send_assoc_resp(struct hostapd_data *hapd, const u8 *addr, wpabuf_free(pub); wpa_hexdump_buf(MSG_DEBUG, "OWE: Buffer", owe_buf); - int owe_ie_len = wpabuf_len(owe_buf); + owe_ie_len = wpabuf_len(owe_buf); esp_wifi_set_appie_internal(WIFI_APPIE_ASSOC_RESP, (uint8_t *)wpabuf_head(owe_buf), owe_ie_len, 0); } @@ -528,7 +542,6 @@ bool hostap_new_assoc_sta(struct sta_info *sta, uint8_t *bssid, u8 *wpa_ie, } #endif /* CONFIG_OWE_SOFTAP */ - send_resp: if (!rsnxe) { omit_rsnxe = true; diff --git a/components/wpa_supplicant/src/ap/wpa_auth.h b/components/wpa_supplicant/src/ap/wpa_auth.h index 34ae7bc54df..1f8abe71300 100644 --- a/components/wpa_supplicant/src/ap/wpa_auth.h +++ b/components/wpa_supplicant/src/ap/wpa_auth.h @@ -327,5 +327,7 @@ static inline bool wpa_auth_pmf_enabled(struct wpa_auth_config *conf) return conf->ieee80211w != NO_MGMT_FRAME_PROTECTION; #endif } +u8 * wpa_auth_write_assoc_resp_owe(struct wpa_state_machine *sm, + u8 *pos, size_t max_len); #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 79a836443f5..0727191b41a 100644 --- a/components/wpa_supplicant/src/ap/wpa_auth_ie.c +++ b/components/wpa_supplicant/src/ap/wpa_auth_ie.c @@ -868,3 +868,17 @@ int wpa_auth_uses_mfp(struct wpa_state_machine *sm) { return sm ? sm->mgmt_frame_prot : 0; } + + +#ifdef CONFIG_OWE_SOFTAP +u8 * wpa_auth_write_assoc_resp_owe(struct wpa_state_machine *sm, + u8 *pos, size_t max_len) +{ + int res; + + res = wpa_write_rsn_ie(&sm->wpa_auth->conf, pos, max_len, NULL); + if (res < 0) + return pos; + return pos + res; +} +#endif /* CONFIG_OWE_SOFTAP */ From 01380bd7d99d1a5185986def596807cf5b8dc804 Mon Sep 17 00:00:00 2001 From: Aditi Date: Tue, 25 Mar 2025 15:03:34 +0530 Subject: [PATCH 05/13] feat(esp_wifi): Add ESP-IDF specific changes for OWE-Only SoftAP 1) Add Support for OWE in wifi driver for SoftAP mode. 2) Add some changes in 4-Way Handshake to support OWE in softAP. 3) Add some restructuring changes. --- .../esp_supplicant/src/esp_hostap.c | 87 +++---- .../esp_supplicant/src/esp_wifi_driver.h | 2 + components/wpa_supplicant/src/ap/ap_config.h | 3 +- components/wpa_supplicant/src/ap/ieee802_11.c | 219 ++++++++++++------ components/wpa_supplicant/src/ap/ieee802_11.h | 8 +- components/wpa_supplicant/src/ap/sta_info.h | 5 +- components/wpa_supplicant/src/ap/wpa_auth.c | 14 +- components/wpa_supplicant/src/ap/wpa_auth.h | 3 + .../wpa_supplicant/src/ap/wpa_auth_ie.c | 7 +- .../wpa_supplicant/src/common/wpa_common.c | 4 +- 10 files changed, 201 insertions(+), 151 deletions(-) diff --git a/components/wpa_supplicant/esp_supplicant/src/esp_hostap.c b/components/wpa_supplicant/esp_supplicant/src/esp_hostap.c index 1f3ebd9e617..498280842da 100644 --- a/components/wpa_supplicant/esp_supplicant/src/esp_hostap.c +++ b/components/wpa_supplicant/esp_supplicant/src/esp_hostap.c @@ -200,7 +200,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) { + if (authmode == WIFI_AUTH_OWE && esp_wifi_ap_get_owe_config_internal()) { auth_conf->wpa_key_mgmt = WPA_KEY_MGMT_OWE; } #endif /* CONFIG_OWE_SOFTAP */ @@ -375,67 +375,27 @@ u16 esp_send_assoc_resp(struct hostapd_data *hapd, const u8 *addr, u16 status_code, bool omit_rsnxe, int subtype) { #define ASSOC_RESP_LENGTH 20 - u8 buf[ASSOC_RESP_LENGTH]; wifi_mgmt_frm_req_t *reply = NULL; - int send_len = 0; - int res = WLAN_STATUS_SUCCESS; +#ifdef CONFIG_OWE_SOFTAP + if ((hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_OWE) && esp_wifi_ap_get_owe_config_internal()) { + int owe_ie_len = 0; + u8 *owe_ie = NULL; + owe_ie = 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); + } + esp_wifi_set_appie_internal(WIFI_APPIE_ASSOC_RESP, owe_ie, owe_ie_len, 0); + } +#else + u8 buf[ASSOC_RESP_LENGTH]; + int send_len = 0; + if (!omit_rsnxe) { send_len = esp_wifi_build_rsnxe(hapd, buf, ASSOC_RESP_LENGTH); } -#ifdef CONFIG_OWE_SOFTAP -#define OWE_DH_GROUP 19 -#define OWE_DHIE_LEN 37 - if ((hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_OWE)) { - struct wpabuf *pub; - struct sta_info *sta = ap_get_sta(hapd, addr); - if (!sta) { - return WLAN_STATUS_UNSPECIFIED_FAILURE; - } - struct wpabuf *owe_buf = wpabuf_alloc(hapd->wpa_auth->wpa_ie_len); - if (!owe_buf) { - wpa_printf(MSG_ERROR, "Memory allocation failed for OWE IE"); - return WLAN_STATUS_UNSPECIFIED_FAILURE; - } - - u8 *pos, buf[128]; - int res; - int owe_ie_len = 0; - - pos = buf; - - pos = wpa_auth_write_assoc_resp_owe(sta->wpa_sm, pos, - buf + sizeof(buf) - pos); - - wpabuf_resize(&owe_buf, pos - buf); - wpabuf_put_data(owe_buf, buf, pos - buf); - owe_ie_len = pos - buf; - - pub = crypto_ecdh_get_pubkey(sta->owe_ecdh, 0); - if (!pub) { - res = WLAN_STATUS_UNSPECIFIED_FAILURE; - return res; - } - - - wpa_hexdump_buf(MSG_DEBUG, "Own public key", pub); - - wpabuf_resize(&owe_buf, OWE_DHIE_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); - - esp_wifi_set_appie_internal(WIFI_APPIE_ASSOC_RESP, (uint8_t *)wpabuf_head(owe_buf), owe_ie_len, 0); - } -#else esp_wifi_set_appie_internal(WIFI_APPIE_ASSOC_RESP, buf, send_len, 0); #endif /* CONFIG_OWE_SOFTAP */ @@ -483,7 +443,8 @@ 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 *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 hostapd_data *hapd = (struct hostapd_data*)esp_wifi_get_hostap_private_internal(); enum wpa_validate_result res = WPA_IE_OK; @@ -534,12 +495,16 @@ bool hostap_new_assoc_sta(struct sta_info *sta, uint8_t *bssid, u8 *wpa_ie, status = wpa_res_to_status_code(res); #ifdef CONFIG_OWE_SOFTAP - if (hapd->conf->wpa_key_mgmt == WPA_KEY_MGMT_OWE) { - status = owe_process_assoc_req(sta, owe_dh, owe_ie_len); - if (status != WLAN_STATUS_SUCCESS) { - return status; + uint8_t owe_enabled = esp_wifi_ap_get_owe_config_internal(); + if (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); + if (status != WLAN_STATUS_SUCCESS) { + wpa_printf(MSG_ERROR, "OWE : Failed to process assoc req status %d", status); + return false; + } } - } #endif /* CONFIG_OWE_SOFTAP */ send_resp: 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 199c4c03754..5844560c1d1 100644 --- a/components/wpa_supplicant/esp_supplicant/src/esp_wifi_driver.h +++ b/components/wpa_supplicant/esp_supplicant/src/esp_wifi_driver.h @@ -312,4 +312,6 @@ 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_is_wpa3_compatible_mode_enabled(uint8_t if_index); +uint8_t esp_wifi_ap_get_owe_config_internal(); + #endif /* _ESP_WIFI_DRIVER_H_ */ diff --git a/components/wpa_supplicant/src/ap/ap_config.h b/components/wpa_supplicant/src/ap/ap_config.h index 65d5dc7c386..87e6547b88a 100644 --- a/components/wpa_supplicant/src/ap/ap_config.h +++ b/components/wpa_supplicant/src/ap/ap_config.h @@ -397,7 +397,8 @@ 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); + 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 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 9c8493faf4d..a6f74183485 100644 --- a/components/wpa_supplicant/src/ap/ieee802_11.c +++ b/components/wpa_supplicant/src/ap/ieee802_11.c @@ -775,96 +775,169 @@ u16 wpa_res_to_status_code(enum wpa_validate_result res) } #ifdef CONFIG_OWE_SOFTAP +#include "ap/wpa_auth_i.h" #include "crypto/crypto.h" -#define OWE_DH_GROUP 19 +#define OWE_DH_GRP19 19 +#define OWE_DHIE_LEN 37 uint16_t owe_process_assoc_req(struct sta_info *sta, const uint8_t *owe_dh, uint8_t owe_dh_len) { - struct wpabuf *secret, *pub, *hkey; - int res; - u8 prk[SHA256_MAC_LEN], pmkid[SHA256_MAC_LEN]; - const char *info = "OWE Key Generation"; - const u8 *addr[2]; - size_t len[2]; - if (WPA_GET_LE16(owe_dh + 3) != OWE_DH_GROUP) - return WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED; + 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; - crypto_ecdh_deinit(sta->owe_ecdh); - sta->owe_ecdh = crypto_ecdh_init(OWE_DH_GROUP); - if (!sta->owe_ecdh) - return WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED; + if (!owe_dh) { + wpa_printf(MSG_ERROR, "OWE: Invalid DH data received"); + return WLAN_STATUS_UNSPECIFIED_FAILURE; + } - secret = crypto_ecdh_set_peerkey(sta->owe_ecdh, 0, owe_dh + 5, - owe_dh_len - 3); - if (!secret) { - wpa_printf(MSG_DEBUG, "OWE: Invalid peer DH public key"); - return WLAN_STATUS_UNSPECIFIED_FAILURE; - } - wpa_hexdump_buf_key(MSG_DEBUG, "OWE: DH shared secret", secret); + // Set the group ID from DH param + sta->owe_group = WPA_GET_LE16(owe_dh + 3); + if (sta->owe_group != OWE_DH_GRP19) + return WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED; - /* prk = HKDF-extract(C | A | group, z) */ + crypto_ecdh_deinit(sta->owe_ecdh); + 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; + } - pub = crypto_ecdh_get_pubkey(sta->owe_ecdh, 0); - if (!pub) { - wpabuf_clear_free(secret); - 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); - /* PMKID = Truncate-128(Hash(C | A)) */ - addr[0] = owe_dh + 5; - len[0] = owe_dh_len - 3; - addr[1] = wpabuf_head(pub); - len[1] = wpabuf_len(pub); - res = sha256_vector(2, addr, len, pmkid); - if (res < 0) { - wpabuf_free(pub); - wpabuf_clear_free(secret); - return WLAN_STATUS_UNSPECIFIED_FAILURE; - } + 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); - hkey = wpabuf_alloc(owe_dh_len - 3 + wpabuf_len(pub) + 2); - if (!hkey) { - wpabuf_free(pub); - wpabuf_clear_free(secret); - return WLAN_STATUS_UNSPECIFIED_FAILURE; - } + /* prk = HKDF-extract(C | A | group, z) */ - 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, OWE_DH_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) - return WLAN_STATUS_UNSPECIFIED_FAILURE; + 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; + } - wpa_hexdump_key(MSG_DEBUG, "OWE: prk", prk, SHA256_MAC_LEN); + /* 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); - /* PMK = HKDF-expand(prk, "OWE Key Generation", n) */ + 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; + } - os_free(sta->owe_pmk); - sta->owe_pmk = os_malloc(PMK_LEN); - if (!sta->owe_pmk) { - os_memset(prk, 0, SHA256_MAC_LEN); - 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; + } - res = hmac_sha256_kdf(prk, SHA256_MAC_LEN, NULL, (const u8 *) info, - os_strlen(info), sta->owe_pmk, PMK_LEN); - os_memset(prk, 0, SHA256_MAC_LEN); - if (res < 0) { - os_free(sta->owe_pmk); - sta->owe_pmk = NULL; - 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 */ - wpa_hexdump_key(MSG_DEBUG, "OWE: PMK", sta->owe_pmk, PMK_LEN); - wpa_hexdump(MSG_DEBUG, "OWE: PMKID", pmkid, PMKID_LEN); - /* TODO: Add PMKSA cache entry */ + res = hmac_sha256(wpabuf_head(hkey), wpabuf_len(hkey), + wpabuf_head(secret), wpabuf_len(secret), prk); + wpabuf_clear_free(hkey); + wpabuf_clear_free(secret); - return WLAN_STATUS_SUCCESS; + if (res < 0) { + 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; + } + + 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); + sta->owe_pmk = NULL; + 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); + + return WLAN_STATUS_SUCCESS; } + + +uint8_t *owe_build_assoc_resp_dhie(struct hostapd_data *hapd, const u8 *bssid, int *owe_ie_len) +{ + + struct wpabuf *pub; + struct sta_info *sta = ap_get_sta(hapd, bssid); + if (!sta) { + return NULL; + } + + struct wpabuf *owe_buf = wpabuf_alloc(hapd->wpa_auth->wpa_ie_len); + if (!owe_buf) { + wpa_printf(MSG_ERROR, "Memory allocation failed for OWE IE"); + return NULL; + } + + u8 *pos, buf[128]; + + pos = buf; + + pos = wpa_auth_write_assoc_resp_owe(hapd, sta->wpa_sm, pos, + buf + sizeof(buf) - pos); + + wpabuf_resize(&owe_buf, pos - buf); + wpabuf_put_data(owe_buf, buf, pos - buf); + *owe_ie_len = pos - buf; + + pub = crypto_ecdh_get_pubkey(sta->owe_ecdh, 0); + if (!pub) { + return NULL; + } + + + wpa_hexdump_buf(MSG_DEBUG, "Own public key", pub); + + wpabuf_resize(&owe_buf, OWE_DHIE_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 (uint8_t *)wpabuf_head(owe_buf); +} + #endif /* CONFIG_OWE_SOFTAP */ diff --git a/components/wpa_supplicant/src/ap/ieee802_11.h b/components/wpa_supplicant/src/ap/ieee802_11.h index 7c59f84ceac..e7af3edf4e0 100644 --- a/components/wpa_supplicant/src/ap/ieee802_11.h +++ b/components/wpa_supplicant/src/ap/ieee802_11.h @@ -17,7 +17,9 @@ int handle_auth_sae(struct hostapd_data *hapd, struct sta_info *sta, u16 auth_transaction, u16 status); u16 wpa_res_to_status_code(enum wpa_validate_result res); #ifdef CONFIG_OWE_SOFTAP -uint16_t owe_process_assoc_req(struct sta_info *sta, const uint8_t *owe_dh, - uint8_t owe_dh_len); -#endif +uint16_t owe_process_assoc_req(struct sta_info *sta, const u8 *owe_dh, + u8 owe_dh_len); +uint8_t *owe_build_assoc_resp_dhie(struct hostapd_data *hapd, const u8 *bssid, int *owe_ie_len); +#endif /* CONFIG_OWE_SOFTAP */ + #endif /* IEEE802_11_H */ diff --git a/components/wpa_supplicant/src/ap/sta_info.h b/components/wpa_supplicant/src/ap/sta_info.h index 38906c3112f..c99a9fb17d9 100644 --- a/components/wpa_supplicant/src/ap/sta_info.h +++ b/components/wpa_supplicant/src/ap/sta_info.h @@ -70,8 +70,9 @@ struct sta_info { #endif /* CONFIG_SAE */ #endif /* ESP_SUPPLICANT */ #ifdef CONFIG_OWE_SOFTAP - u8 *owe_pmk; - struct crypto_ecdh *owe_ecdh; + u16 owe_group; + u8 *owe_pmk; + struct crypto_ecdh *owe_ecdh; #endif /* CONFIG_OWE_SOFTAP */ }; diff --git a/components/wpa_supplicant/src/ap/wpa_auth.c b/components/wpa_supplicant/src/ap/wpa_auth.c index 54fbeb1444e..65786a90295 100644 --- a/components/wpa_supplicant/src/ap/wpa_auth.c +++ b/components/wpa_supplicant/src/ap/wpa_auth.c @@ -136,8 +136,9 @@ static inline const u8 * wpa_auth_get_psk(struct wpa_authenticator *wpa_auth, return NULL; } -#ifdef CONFIG_SAE +#if defined(CONFIG_SAE) || defined(CONFIG_OWE_SOFTAP) struct sta_info *sta = ap_get_sta(hapd, addr); +#ifdef CONFIG_SAE if (sta && sta->auth_alg == WLAN_AUTH_SAE) { if (!sta->sae || prev_psk) return NULL; @@ -155,7 +156,7 @@ static inline const u8 * wpa_auth_get_psk(struct wpa_authenticator *wpa_auth, return sta->owe_pmk; } #endif /* CONFIG_OWE_SOFTAP */ - +#endif /* defined(CONFIG_SAE) || defined(CONFIG_OWE_SOFTAP) */ return (u8*)hostapd_get_psk(hapd->conf, addr, prev_psk); } @@ -1472,7 +1473,8 @@ SM_STATE(WPA_PTK, INITIALIZE) wpa_remove_ptk(sm); wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_portValid, 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_EAPOL_authorized, 0); } @@ -1782,7 +1784,8 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING) } if (!wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) || - wpa_key_mgmt_sae(sm->wpa_key_mgmt)) { + wpa_key_mgmt_sae(sm->wpa_key_mgmt) || + sm->wpa_key_mgmt != WPA_KEY_MGMT_OWE) { wpa_printf( MSG_DEBUG, "wpa_key_mgmt=%x", sm->wpa_key_mgmt); break; } @@ -2253,7 +2256,8 @@ SM_STEP(WPA_PTK) wpa_auth_get_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_keyRun) > 0) 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 */) SM_ENTER(WPA_PTK, INITPSK); break; diff --git a/components/wpa_supplicant/src/ap/wpa_auth.h b/components/wpa_supplicant/src/ap/wpa_auth.h index 1f8abe71300..ec160cf9809 100644 --- a/components/wpa_supplicant/src/ap/wpa_auth.h +++ b/components/wpa_supplicant/src/ap/wpa_auth.h @@ -12,6 +12,7 @@ #include "common/defs.h" #include "common/eapol_common.h" #include "common/wpa_common.h" +#include "ap/hostapd.h" #ifdef _MSC_VER #pragma pack(push, 1) @@ -329,5 +330,7 @@ static inline bool wpa_auth_pmf_enabled(struct wpa_auth_config *conf) } u8 * wpa_auth_write_assoc_resp_owe(struct wpa_state_machine *sm, u8 *pos, size_t max_len); +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 */ diff --git a/components/wpa_supplicant/src/ap/wpa_auth_ie.c b/components/wpa_supplicant/src/ap/wpa_auth_ie.c index 0727191b41a..dbfc4bc75eb 100644 --- a/components/wpa_supplicant/src/ap/wpa_auth_ie.c +++ b/components/wpa_supplicant/src/ap/wpa_auth_ie.c @@ -870,15 +870,14 @@ int wpa_auth_uses_mfp(struct wpa_state_machine *sm) } -#ifdef CONFIG_OWE_SOFTAP -u8 * wpa_auth_write_assoc_resp_owe(struct wpa_state_machine *sm, +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(&sm->wpa_auth->conf, pos, max_len, NULL); + res = wpa_write_rsn_ie(&hapd->wpa_auth->conf, pos, max_len, NULL); if (res < 0) return pos; return pos + res; } -#endif /* CONFIG_OWE_SOFTAP */ diff --git a/components/wpa_supplicant/src/common/wpa_common.c b/components/wpa_supplicant/src/common/wpa_common.c index 457117caa03..a8448a7c2a9 100644 --- a/components/wpa_supplicant/src/common/wpa_common.c +++ b/components/wpa_supplicant/src/common/wpa_common.c @@ -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); break; #endif /* CONFIG_SUITEB192 */ -#ifdef CONFIG_OWE_STA +#if defined(CONFIG_OWE_STA) || defined(CONFIG_OWE_SOFTAP) case WPA_KEY_MGMT_OWE: wpa_printf(MSG_DEBUG, "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); break; -#endif /* CONFIG_OWE_STA */ +#endif /* CONFIG_OWE_STA || CONFIG_OWE_SOFTAP */ #ifdef CONFIG_DPP case WPA_KEY_MGMT_DPP: wpa_printf(MSG_DEBUG, From 376fb23ff7c1ff56e604b82dfc3d5e7807de7917 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 9 Oct 2017 12:08:12 +0300 Subject: [PATCH 06/13] OWE: PMKSA caching in AP mode This extends OWE support in hostapd to allow PMKSA caching to be used. Signed-off-by: Jouni Malinen --- components/wpa_supplicant/src/ap/ieee802_11.c | 126 +++++++++++++----- components/wpa_supplicant/src/ap/ieee802_11.h | 2 +- components/wpa_supplicant/src/ap/sta_info.h | 1 + components/wpa_supplicant/src/ap/wpa_auth.c | 27 +++- .../wpa_supplicant/src/ap/wpa_auth_ie.c | 3 +- 5 files changed, 121 insertions(+), 38 deletions(-) diff --git a/components/wpa_supplicant/src/ap/ieee802_11.c b/components/wpa_supplicant/src/ap/ieee802_11.c index a6f74183485..7aee02ac93a 100644 --- a/components/wpa_supplicant/src/ap/ieee802_11.c +++ b/components/wpa_supplicant/src/ap/ieee802_11.c @@ -20,6 +20,13 @@ #include "esp_wpa3_i.h" #include "esp_hostap.h" +#ifdef CONFIG_OWE_SOFTAP +#include "crypto/crypto.h" +#include "ap/wpa_auth_i.h" +#define OWE_DH_GRP19 19 +#define OWE_DHIE_LEN 37 +#endif + #ifdef CONFIG_SAE static void sae_set_state(struct sta_info *sta, enum sae_state state, @@ -775,14 +782,29 @@ u16 wpa_res_to_status_code(enum wpa_validate_result res) } #ifdef CONFIG_OWE_SOFTAP -#include "ap/wpa_auth_i.h" -#include "crypto/crypto.h" -#define OWE_DH_GRP19 19 -#define OWE_DHIE_LEN 37 -uint16_t owe_process_assoc_req(struct sta_info *sta, const uint8_t *owe_dh, - uint8_t owe_dh_len) -{ +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; @@ -791,6 +813,11 @@ uint16_t owe_process_assoc_req(struct sta_info *sta, const uint8_t *owe_dh, 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) { wpa_printf(MSG_ERROR, "OWE: Invalid DH data received"); return WLAN_STATUS_UNSPECIFIED_FAILURE; @@ -801,11 +828,25 @@ uint16_t owe_process_assoc_req(struct sta_info *sta, const uint8_t *owe_dh, if (sta->owe_group != OWE_DH_GRP19) return WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED; - crypto_ecdh_deinit(sta->owe_ecdh); - 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; + 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 { + + crypto_ecdh_deinit(sta->owe_ecdh); + 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 @@ -888,13 +929,27 @@ uint16_t owe_process_assoc_req(struct sta_info *sta, const uint8_t *owe_dh, 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 + wpa_auth_pmksa_add2(hapd->wpa_auth, sta->addr, sta->owe_pmk, sta->owe_pmk_len, pmkid, 0, WPA_KEY_MGMT_OWE, NULL); + + // 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; } uint8_t *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) { @@ -907,34 +962,39 @@ uint8_t *owe_build_assoc_resp_dhie(struct hostapd_data *hapd, const u8 *bssid, i return NULL; } - u8 *pos, buf[128]; + // If PMKSA caching is used, write and return only RSN IE with PMKID + if (sta->wpa_sm && sta->wpa_sm->pmksa) { + u8 *pos, buf[128]; + pos = buf; - pos = buf; - - pos = wpa_auth_write_assoc_resp_owe(hapd, sta->wpa_sm, pos, + 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); - wpabuf_resize(&owe_buf, pos - buf); - wpabuf_put_data(owe_buf, buf, pos - buf); - *owe_ie_len = pos - buf; - - pub = crypto_ecdh_get_pubkey(sta->owe_ecdh, 0); - if (!pub) { - return NULL; + wpabuf_resize(&owe_buf, pos - buf); + wpabuf_put_data(owe_buf, buf, pos - buf); + *owe_ie_len = pos - buf; + return (uint8_t *)wpabuf_head(owe_buf); } + if (sta->owe_ecdh) { + pub = crypto_ecdh_get_pubkey(sta->owe_ecdh, 0); + if (!pub) { + return NULL; + } - wpa_hexdump_buf(MSG_DEBUG, "Own public key", pub); + wpa_hexdump_buf(MSG_DEBUG, "Own public key", pub); - wpabuf_resize(&owe_buf, OWE_DHIE_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); + wpabuf_resize(&owe_buf, OWE_DHIE_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); + wpa_hexdump_buf(MSG_DEBUG, "OWE: Buffer", owe_buf); + } *owe_ie_len = wpabuf_len(owe_buf); return (uint8_t *)wpabuf_head(owe_buf); diff --git a/components/wpa_supplicant/src/ap/ieee802_11.h b/components/wpa_supplicant/src/ap/ieee802_11.h index e7af3edf4e0..d4d54246e2a 100644 --- a/components/wpa_supplicant/src/ap/ieee802_11.h +++ b/components/wpa_supplicant/src/ap/ieee802_11.h @@ -17,7 +17,7 @@ int handle_auth_sae(struct hostapd_data *hapd, struct sta_info *sta, u16 auth_transaction, u16 status); u16 wpa_res_to_status_code(enum wpa_validate_result res); #ifdef CONFIG_OWE_SOFTAP -uint16_t owe_process_assoc_req(struct sta_info *sta, const u8 *owe_dh, +uint16_t owe_process_assoc_req(struct hostapd_data *hapd, struct sta_info *sta, const u8 *owe_dh, u8 owe_dh_len); uint8_t *owe_build_assoc_resp_dhie(struct hostapd_data *hapd, const u8 *bssid, int *owe_ie_len); #endif /* CONFIG_OWE_SOFTAP */ diff --git a/components/wpa_supplicant/src/ap/sta_info.h b/components/wpa_supplicant/src/ap/sta_info.h index c99a9fb17d9..4bc2e42c6aa 100644 --- a/components/wpa_supplicant/src/ap/sta_info.h +++ b/components/wpa_supplicant/src/ap/sta_info.h @@ -72,6 +72,7 @@ struct sta_info { #ifdef CONFIG_OWE_SOFTAP u16 owe_group; u8 *owe_pmk; + size_t owe_pmk_len; struct crypto_ecdh *owe_ecdh; #endif /* CONFIG_OWE_SOFTAP */ diff --git a/components/wpa_supplicant/src/ap/wpa_auth.c b/components/wpa_supplicant/src/ap/wpa_auth.c index 65786a90295..5967cab302a 100644 --- a/components/wpa_supplicant/src/ap/wpa_auth.c +++ b/components/wpa_supplicant/src/ap/wpa_auth.c @@ -152,9 +152,20 @@ static inline const u8 * wpa_auth_get_psk(struct wpa_authenticator *wpa_auth, #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 && 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) */ @@ -1038,6 +1049,12 @@ void wpa_auth_add_sae_pmkid(struct wpa_state_machine *sm, const u8 *pmkid) 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, const u8 *gnonce, u8 *gtk, size_t gtk_len) { @@ -1633,6 +1650,9 @@ SM_STATE(WPA_PTK, INITPSK) psk = wpa_auth_get_psk(sm->wpa_auth, sm->addr, NULL); if (psk) { memcpy(sm->PMK, psk, PMK_LEN); +#ifdef CONFIG_OWE_SOFTAP + sm->pmk_len = PMK_LEN; +#endif #ifdef CONFIG_IEEE80211R_AP memcpy(sm->xxkey, psk, PMK_LEN); sm->xxkey_len = PMK_LEN; @@ -1671,6 +1691,7 @@ SM_STATE(WPA_PTK, PTKSTART) */ if (sm->wpa == WPA_VERSION_WPA2 && (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))) { pmkid = buf; pmkid_len = 2 + RSN_SELECTOR_LEN + PMKID_LEN; diff --git a/components/wpa_supplicant/src/ap/wpa_auth_ie.c b/components/wpa_supplicant/src/ap/wpa_auth_ie.c index dbfc4bc75eb..634d5b4750f 100644 --- a/components/wpa_supplicant/src/ap/wpa_auth_ie.c +++ b/components/wpa_supplicant/src/ap/wpa_auth_ie.c @@ -876,7 +876,8 @@ uint8_t *wpa_auth_write_assoc_resp_owe(struct hostapd_data *hapd, struct wpa_sta { int res; - res = wpa_write_rsn_ie(&hapd->wpa_auth->conf, pos, max_len, NULL); + res = wpa_write_rsn_ie(&hapd->wpa_auth->conf, pos, max_len, + sm->pmksa ? sm->pmksa->pmkid : NULL, hapd->wpa_auth->conf.group_mgmt_cipher); if (res < 0) return pos; return pos + res; From 165c9fa44c4a60ca1ac3dcfcd6a5883ebd0404f6 Mon Sep 17 00:00:00 2001 From: Aditi Date: Thu, 27 Mar 2025 15:41:40 +0530 Subject: [PATCH 07/13] feat(esp_wifi): Add ESP-IDF specific changes for OWE Only softap 1) Add OWE-Only Support in ESP-IDF softAP example 2) Add changes in documentation --- components/wpa_supplicant/src/ap/ieee802_11.c | 8 +++++++- docs/en/api-guides/wifi-security.rst | 9 ++++++++- .../getting_started/softAP/main/softap_example_main.c | 3 ++- 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/components/wpa_supplicant/src/ap/ieee802_11.c b/components/wpa_supplicant/src/ap/ieee802_11.c index 7aee02ac93a..37b8952f9fe 100644 --- a/components/wpa_supplicant/src/ap/ieee802_11.c +++ b/components/wpa_supplicant/src/ap/ieee802_11.c @@ -25,6 +25,13 @@ #include "ap/wpa_auth_i.h" #define OWE_DH_GRP19 19 #define OWE_DHIE_LEN 37 +/* +OWE_DHIE_LEN = 1 byte {WLAN_EID_EXTENSION} + + 1 byte {len of DHIE (1(pub_key len) + 2(dh group) + 32(len of pub_key)) = 35)} + + 1 byte {pub_key len} + + 2 bytes {DH group} + + 32 bytes {public key} +*/ #endif #ifdef CONFIG_SAE @@ -841,7 +848,6 @@ uint16_t owe_process_assoc_req(struct hostapd_data *hapd, struct sta_info *sta, "OWE: Try to reuse own previous DH key since the STA tried to go through OWE association again"); } else { - crypto_ecdh_deinit(sta->owe_ecdh); sta->owe_ecdh = crypto_ecdh_init(OWE_DH_GRP19); if (!sta->owe_ecdh) { wpa_printf(MSG_ERROR, "OWE: Error initializing ECDH for STA"); diff --git a/docs/en/api-guides/wifi-security.rst b/docs/en/api-guides/wifi-security.rst index 81101ed1923..b9d0fe11037 100644 --- a/docs/en/api-guides/wifi-security.rst +++ b/docs/en/api-guides/wifi-security.rst @@ -157,10 +157,17 @@ Enhanced Open™ is used for providing security and privacy to users connecting .. note:: - {IDF_TARGET_NAME} supports Wi-Fi Enhanced Open™ only in station mode. + {IDF_TARGET_NAME} supports Wi-Fi Enhanced Open™ (OWE Transition Mode + OWE Only) in station mode and (OWE Only) in softap mode. 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``. + + +For softap mode : + +A configuration option :ref:`CONFIG_ESP_WIFI_ENABLE_WPA3_OWE_SOFTAP` from menuconfig and configuration parameter :cpp:type:`owe_enabled` in :cpp:type:`wifi_ap_config_t` should be enabled and configuration parameter `authmode` from :cpp:type:`wifi_ap_config_t` should be set to ``WIFI_AUTH_OWE``. 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 c2bca87431a..dc455357427 100644 --- a/examples/wifi/getting_started/softAP/main/softap_example_main.c +++ b/examples/wifi/getting_started/softAP/main/softap_example_main.c @@ -90,7 +90,8 @@ void wifi_init_softap(void) .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.owe_enabled)) { wifi_config.ap.authmode = WIFI_AUTH_OPEN; } From 7d0551257c1a7e5f9773802a52df496d71321a70 Mon Sep 17 00:00:00 2001 From: Aditi Date: Wed, 21 May 2025 11:57:52 +0530 Subject: [PATCH 08/13] feat(esp_wifi): Add changes for addressing some review comments Closes https://github.com/espressif/esp-idf/issues/13457 --- components/esp_wifi/Kconfig | 2 - components/esp_wifi/include/esp_wifi.h | 10 ++- .../esp_supplicant/src/esp_hostap.c | 31 ++++---- .../esp_supplicant/src/esp_owe.c | 73 ++++++++++++++++++- .../esp_supplicant/src/esp_owe_i.h | 18 ++++- .../esp_supplicant/src/esp_wifi_driver.h | 4 +- components/wpa_supplicant/src/ap/ieee802_11.c | 67 ----------------- components/wpa_supplicant/src/ap/ieee802_11.h | 1 - components/wpa_supplicant/src/ap/wpa_auth.h | 2 - .../wpa_supplicant/src/ap/wpa_auth_ie.c | 7 +- docs/en/api-guides/wifi-security.rst | 6 +- .../softAP/main/softap_example_main.c | 3 +- 12 files changed, 125 insertions(+), 99 deletions(-) diff --git a/components/esp_wifi/Kconfig b/components/esp_wifi/Kconfig index 5f57d67ad07..14547d9efe7 100644 --- a/components/esp_wifi/Kconfig +++ b/components/esp_wifi/Kconfig @@ -353,8 +353,6 @@ menu "Wi-Fi" depends on ESP_WIFI_SOFTAP_SUPPORT help Select this option to allow the device to enable OWE Only mode for softap. - PMF (Protected Management Frames) is a prerequisite feature, it needs to be explicitly configured - before attempting connection. Please refer to the Wi-Fi Driver API Guide for details. config ESP_WIFI_SLP_IRAM_OPT bool "WiFi SLP IRAM speed optimization" diff --git a/components/esp_wifi/include/esp_wifi.h b/components/esp_wifi/include/esp_wifi.h index 45ed0476665..1419a3daf7a 100644 --- a/components/esp_wifi/include/esp_wifi.h +++ b/components/esp_wifi/include/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_ESP_WIFI_ENABLE_WPA3_OWE_SOFTAP +#define WIFI_ENABLE_OWE_SOFTAP (1<<9) +#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<<9) /* 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 498280842da..207f3dcb2d0 100644 --- a/components/wpa_supplicant/esp_supplicant/src/esp_hostap.c +++ b/components/wpa_supplicant/esp_supplicant/src/esp_hostap.c @@ -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 */ @@ -31,6 +31,7 @@ #ifdef CONFIG_OWE_SOFTAP #include "crypto/crypto.h" #include "ap/ieee802_11.h" +#include "esp_owe_i.h" #endif struct hostapd_data *global_hapd; @@ -375,28 +376,28 @@ u16 esp_send_assoc_resp(struct hostapd_data *hapd, const u8 *addr, u16 status_code, bool omit_rsnxe, int subtype) { #define ASSOC_RESP_LENGTH 20 - wifi_mgmt_frm_req_t *reply = NULL; - int res = WLAN_STATUS_SUCCESS; - -#ifdef CONFIG_OWE_SOFTAP - if ((hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_OWE) && esp_wifi_ap_get_owe_config_internal()) { - int owe_ie_len = 0; - u8 *owe_ie = NULL; - owe_ie = 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); - } - esp_wifi_set_appie_internal(WIFI_APPIE_ASSOC_RESP, owe_ie, owe_ie_len, 0); - } -#else u8 buf[ASSOC_RESP_LENGTH]; + wifi_mgmt_frm_req_t *reply = NULL; int send_len = 0; + int res = WLAN_STATUS_SUCCESS; + if (!omit_rsnxe) { send_len = esp_wifi_build_rsnxe(hapd, buf, ASSOC_RESP_LENGTH); } esp_wifi_set_appie_internal(WIFI_APPIE_ASSOC_RESP, buf, send_len, 0); +#ifdef CONFIG_OWE_SOFTAP + 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); + 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)); diff --git a/components/wpa_supplicant/esp_supplicant/src/esp_owe.c b/components/wpa_supplicant/esp_supplicant/src/esp_owe.c index 7077573f6b5..13630625eae 100644 --- a/components/wpa_supplicant/esp_supplicant/src/esp_owe.c +++ b/components/wpa_supplicant/esp_supplicant/src/esp_owe.c @@ -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 */ -#ifdef CONFIG_OWE_STA #include "crypto/crypto.h" #include "esp_owe_i.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) { struct wpa_sm *sm = NULL; @@ -36,3 +44,64 @@ void esp_wifi_register_owe_cb(struct wpa_funcs *wpa_cb) wpa_cb->owe_process_assoc_resp = owe_process_assoc_resp; } #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(hapd->wpa_auth->wpa_ie_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[128]; + 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); + + wpabuf_resize(&owe_buf, pos - buf); + wpabuf_put_data(owe_buf, buf, pos - buf); + *owe_ie_len = pos - buf; + return owe_buf; + } + + if (sta->owe_ecdh) { + pub = crypto_ecdh_get_pubkey(sta->owe_ecdh, 0); + if (!pub) { + wpabuf_free(owe_buf); + return NULL; + } + + wpa_hexdump_buf(MSG_DEBUG, "Own public key", pub); + + wpabuf_resize(&owe_buf, OWE_DHIE_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 */ diff --git a/components/wpa_supplicant/esp_supplicant/src/esp_owe_i.h b/components/wpa_supplicant/esp_supplicant/src/esp_owe_i.h index 44223f3854c..fc32924d1d7 100644 --- a/components/wpa_supplicant/esp_supplicant/src/esp_owe_i.h +++ b/components/wpa_supplicant/esp_supplicant/src/esp_owe_i.h @@ -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 */ @@ -20,4 +20,20 @@ void owe_deinit(void); void esp_wifi_register_owe_cb(struct wpa_funcs *wpa_cb); #endif /* CONFIG_OWE_STA */ + +#ifdef CONFIG_OWE_SOFTAP + +#include "ap/hostapd.h" + +/* +OWE_DHIE_LEN = 1 byte {WLAN_EID_EXTENSION} + + 1 byte {len of DHIE (1(pub_key len) + 2(dh group) + 32(len of pub_key)) = 35)} + + 1 byte {pub_key len} + + 2 bytes {DH group} + + 32 bytes {public key} +*/ +#define OWE_DHIE_LEN 37 +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 */ 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 5844560c1d1..f31638addf5 100644 --- a/components/wpa_supplicant/esp_supplicant/src/esp_wifi_driver.h +++ b/components/wpa_supplicant/esp_supplicant/src/esp_wifi_driver.h @@ -130,7 +130,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_dh, uint8_t owe_ie_len); + 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_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); @@ -312,6 +312,6 @@ 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_is_wpa3_compatible_mode_enabled(uint8_t if_index); -uint8_t esp_wifi_ap_get_owe_config_internal(); +uint8_t esp_wifi_ap_get_owe_config_internal(void); #endif /* _ESP_WIFI_DRIVER_H_ */ diff --git a/components/wpa_supplicant/src/ap/ieee802_11.c b/components/wpa_supplicant/src/ap/ieee802_11.c index 37b8952f9fe..5e09b8425b3 100644 --- a/components/wpa_supplicant/src/ap/ieee802_11.c +++ b/components/wpa_supplicant/src/ap/ieee802_11.c @@ -24,14 +24,6 @@ #include "crypto/crypto.h" #include "ap/wpa_auth_i.h" #define OWE_DH_GRP19 19 -#define OWE_DHIE_LEN 37 -/* -OWE_DHIE_LEN = 1 byte {WLAN_EID_EXTENSION} - + 1 byte {len of DHIE (1(pub_key len) + 2(dh group) + 32(len of pub_key)) = 35)} - + 1 byte {pub_key len} - + 2 bytes {DH group} - + 32 bytes {public key} -*/ #endif #ifdef CONFIG_SAE @@ -947,63 +939,4 @@ uint16_t owe_process_assoc_req(struct hostapd_data *hapd, struct sta_info *sta, return WLAN_STATUS_SUCCESS; } - -uint8_t *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(hapd->wpa_auth->wpa_ie_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[128]; - 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); - - wpabuf_resize(&owe_buf, pos - buf); - wpabuf_put_data(owe_buf, buf, pos - buf); - *owe_ie_len = pos - buf; - return (uint8_t *)wpabuf_head(owe_buf); - } - - if (sta->owe_ecdh) { - pub = crypto_ecdh_get_pubkey(sta->owe_ecdh, 0); - if (!pub) { - return NULL; - } - - wpa_hexdump_buf(MSG_DEBUG, "Own public key", pub); - - wpabuf_resize(&owe_buf, OWE_DHIE_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 (uint8_t *)wpabuf_head(owe_buf); -} - #endif /* CONFIG_OWE_SOFTAP */ diff --git a/components/wpa_supplicant/src/ap/ieee802_11.h b/components/wpa_supplicant/src/ap/ieee802_11.h index d4d54246e2a..6062aab86e8 100644 --- a/components/wpa_supplicant/src/ap/ieee802_11.h +++ b/components/wpa_supplicant/src/ap/ieee802_11.h @@ -19,7 +19,6 @@ 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); -uint8_t *owe_build_assoc_resp_dhie(struct hostapd_data *hapd, const u8 *bssid, int *owe_ie_len); #endif /* CONFIG_OWE_SOFTAP */ #endif /* IEEE802_11_H */ diff --git a/components/wpa_supplicant/src/ap/wpa_auth.h b/components/wpa_supplicant/src/ap/wpa_auth.h index ec160cf9809..696a04de3d2 100644 --- a/components/wpa_supplicant/src/ap/wpa_auth.h +++ b/components/wpa_supplicant/src/ap/wpa_auth.h @@ -328,8 +328,6 @@ static inline bool wpa_auth_pmf_enabled(struct wpa_auth_config *conf) return conf->ieee80211w != NO_MGMT_FRAME_PROTECTION; #endif } -u8 * wpa_auth_write_assoc_resp_owe(struct wpa_state_machine *sm, - u8 *pos, size_t max_len); uint8_t *wpa_auth_write_assoc_resp_owe(struct hostapd_data *hapd, struct wpa_state_machine *sm, u8 *pos, size_t max_len); diff --git a/components/wpa_supplicant/src/ap/wpa_auth_ie.c b/components/wpa_supplicant/src/ap/wpa_auth_ie.c index 634d5b4750f..61a17f554fb 100644 --- a/components/wpa_supplicant/src/ap/wpa_auth_ie.c +++ b/components/wpa_supplicant/src/ap/wpa_auth_ie.c @@ -235,7 +235,7 @@ static u8 * rsne_write_data(u8 *buf, size_t len, u8 *pos, int group, } #endif /* CONFIG_SAE */ #ifdef CONFIG_OWE_SOFTAP - if (conf->wpa_key_mgmt & WPA_KEY_MGMT_OWE) { + if (key_mgmt & WPA_KEY_MGMT_OWE) { RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_OWE); pos += RSN_SELECTOR_LEN; num_suites++; @@ -869,7 +869,7 @@ int wpa_auth_uses_mfp(struct wpa_state_machine *sm) 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) @@ -877,8 +877,9 @@ uint8_t *wpa_auth_write_assoc_resp_owe(struct hostapd_data *hapd, struct wpa_sta int res; res = wpa_write_rsn_ie(&hapd->wpa_auth->conf, pos, max_len, - sm->pmksa ? sm->pmksa->pmkid : NULL, hapd->wpa_auth->conf.group_mgmt_cipher); + sm->pmksa ? sm->pmksa->pmkid : NULL); if (res < 0) return pos; return pos + res; } +#endif /* CONFIG_OWE_SOFTAP */ diff --git a/docs/en/api-guides/wifi-security.rst b/docs/en/api-guides/wifi-security.rst index b9d0fe11037..fc6f77625d7 100644 --- a/docs/en/api-guides/wifi-security.rst +++ b/docs/en/api-guides/wifi-security.rst @@ -170,4 +170,8 @@ A configuration option :ref:`CONFIG_ESP_WIFI_ENABLE_WPA3_OWE_STA` and configurat For softap mode : -A configuration option :ref:`CONFIG_ESP_WIFI_ENABLE_WPA3_OWE_SOFTAP` from menuconfig and configuration parameter :cpp:type:`owe_enabled` in :cpp:type:`wifi_ap_config_t` should be enabled and configuration parameter `authmode` from :cpp:type:`wifi_ap_config_t` should be set to ``WIFI_AUTH_OWE``. +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``. + +.. note:: + + In softap mode, if the configuration option :ref:`CONFIG_ESP_WIFI_ENABLE_WPA3_OWE_SOFTAP` is enabled and authmode is set to ``WIFI_AUTH_OPEN``, authmode will be set to ``WIFI_AUTH_OWE`` internally. 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 dc455357427..c2bca87431a 100644 --- a/examples/wifi/getting_started/softAP/main/softap_example_main.c +++ b/examples/wifi/getting_started/softAP/main/softap_example_main.c @@ -90,8 +90,7 @@ void wifi_init_softap(void) .gtk_rekey_interval = EXAMPLE_GTK_REKEY_INTERVAL, }, }; - if (strlen(EXAMPLE_ESP_WIFI_PASS) == 0 && - (wifi_config.ap.authmode != WIFI_AUTH_OWE || !wifi_config.ap.owe_enabled)) { + if (strlen(EXAMPLE_ESP_WIFI_PASS) == 0) { wifi_config.ap.authmode = WIFI_AUTH_OPEN; } From c0b58df382391d917710aaa9c73135d55b52c7e5 Mon Sep 17 00:00:00 2001 From: "tarun.kumar" Date: Fri, 17 Apr 2026 00:34:16 +0530 Subject: [PATCH 09/13] fix(wifi) : Fixed some issues found using static analysis --- .../wpa_supplicant/esp_supplicant/src/esp_hostap.c | 5 ++++- components/wpa_supplicant/src/ap/ieee802_11.c | 13 ++++++++++--- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/components/wpa_supplicant/esp_supplicant/src/esp_hostap.c b/components/wpa_supplicant/esp_supplicant/src/esp_hostap.c index 207f3dcb2d0..d9f53672c30 100644 --- a/components/wpa_supplicant/esp_supplicant/src/esp_hostap.c +++ b/components/wpa_supplicant/esp_supplicant/src/esp_hostap.c @@ -393,6 +393,7 @@ u16 esp_send_assoc_resp(struct hostapd_data *hapd, const u8 *addr, 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); @@ -497,11 +498,13 @@ bool hostap_new_assoc_sta(struct sta_info *sta, uint8_t *bssid, u8 *wpa_ie, #ifdef CONFIG_OWE_SOFTAP uint8_t owe_enabled = esp_wifi_ap_get_owe_config_internal(); - if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_OWE && + 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); if (status != WLAN_STATUS_SUCCESS) { + *reason = wpa_status_to_reason_code(status); wpa_printf(MSG_ERROR, "OWE : Failed to process assoc req status %d", status); return false; } diff --git a/components/wpa_supplicant/src/ap/ieee802_11.c b/components/wpa_supplicant/src/ap/ieee802_11.c index 5e09b8425b3..bb1c0b57ae4 100644 --- a/components/wpa_supplicant/src/ap/ieee802_11.c +++ b/components/wpa_supplicant/src/ap/ieee802_11.c @@ -23,6 +23,7 @@ #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 @@ -817,8 +818,8 @@ uint16_t owe_process_assoc_req(struct hostapd_data *hapd, struct sta_info *sta, return WLAN_STATUS_SUCCESS; } - if (!owe_dh) { - wpa_printf(MSG_ERROR, "OWE: Invalid DH data received"); + if (!owe_dh || 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; } @@ -930,7 +931,13 @@ uint16_t owe_process_assoc_req(struct hostapd_data *hapd, struct sta_info *sta, sta->owe_pmk_len = SHA256_MAC_LEN; // Add the PMK to the PMKSA cache - wpa_auth_pmksa_add2(hapd->wpa_auth, sta->addr, sta->owe_pmk, sta->owe_pmk_len, pmkid, 0, WPA_KEY_MGMT_OWE, NULL); + 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); + sta->owe_pmk = NULL; + 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); From a5201bb8f4492d2de3146bc6d5fdb46d4971af17 Mon Sep 17 00:00:00 2001 From: "tarun.kumar" Date: Mon, 20 Apr 2026 23:34:55 +0530 Subject: [PATCH 10/13] fix(wifi) : Send assoc response with status code 77 in case of invalid DH group parameter element --- .../esp_supplicant/src/esp_hostap.c | 20 ++++++++++--------- components/wpa_supplicant/src/ap/ieee802_11.c | 9 +++++++-- 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/components/wpa_supplicant/esp_supplicant/src/esp_hostap.c b/components/wpa_supplicant/esp_supplicant/src/esp_hostap.c index d9f53672c30..0b43fa2f059 100644 --- a/components/wpa_supplicant/esp_supplicant/src/esp_hostap.c +++ b/components/wpa_supplicant/esp_supplicant/src/esp_hostap.c @@ -388,16 +388,18 @@ u16 esp_send_assoc_resp(struct hostapd_data *hapd, const u8 *addr, esp_wifi_set_appie_internal(WIFI_APPIE_ASSOC_RESP, buf, send_len, 0); #ifdef CONFIG_OWE_SOFTAP - 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); + 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); 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 */ @@ -503,7 +505,7 @@ bool hostap_new_assoc_sta(struct sta_info *sta, uint8_t *bssid, u8 *wpa_ie, 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); - if (status != WLAN_STATUS_SUCCESS) { + 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); return false; diff --git a/components/wpa_supplicant/src/ap/ieee802_11.c b/components/wpa_supplicant/src/ap/ieee802_11.c index bb1c0b57ae4..2b8aa10da08 100644 --- a/components/wpa_supplicant/src/ap/ieee802_11.c +++ b/components/wpa_supplicant/src/ap/ieee802_11.c @@ -818,16 +818,21 @@ uint16_t owe_process_assoc_req(struct hostapd_data *hapd, struct sta_info *sta, return WLAN_STATUS_SUCCESS; } - if (!owe_dh || owe_dh_len < OWE_DHIE_LEN - 2) { + 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 + /* 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 From d698d5345aa40c379c7d1b2e9eab29f7bd9c1fdb Mon Sep 17 00:00:00 2001 From: "tarun.kumar" Date: Thu, 23 Apr 2026 16:53:16 +0530 Subject: [PATCH 11/13] 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). --- components/esp_wifi/Kconfig | 2 +- components/esp_wifi/include/esp_wifi.h | 4 +- components/esp_wifi/remote/Kconfig.wifi.in | 8 +++ .../esp_wifi/remote/Kconfig.wifi_is_remote.in | 7 +++ .../remote/include/injected/esp_wifi.h | 10 +++- .../esp_supplicant/src/esp_hostap.c | 60 ++++++++++--------- .../esp_supplicant/src/esp_wifi_driver.h | 19 +++++- .../esp_supplicant/src/esp_wpa_main.c | 32 +++++++++- components/wpa_supplicant/src/ap/ap_config.h | 19 ++++-- components/wpa_supplicant/src/ap/ieee802_11.c | 23 ++++--- components/wpa_supplicant/src/ap/wpa_auth.c | 3 +- 11 files changed, 139 insertions(+), 48 deletions(-) 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; } From 2c3cd560c4938bd12e90b547d29823f8340db9ba Mon Sep 17 00:00:00 2001 From: "tarun.kumar" Date: Tue, 5 May 2026 20:42:27 +0530 Subject: [PATCH 12/13] fix(wifi) : Made changes based on more review comments MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit -Require STA DH IE for OWE associations. - Send failures using Association Response (no silent deauth-only path). - Include RSNE in OWE Association Response alongside DH Parameter IE. - Check wpabuf_resize return values when building OWE Assoc Response IEs. - Recognize OWE AKM in RSN IE when CONFIG_OWE_SOFTAP without CONFIG_OWE_STA. - Docs: SoftAP OWE-only; no transition mode; trim misleading OPEN→OWE note. --- components/esp_wifi/lib | 2 +- .../esp_supplicant/src/esp_hostap.c | 21 ++++++--- .../esp_supplicant/src/esp_owe.c | 44 +++++++++++++++++-- .../esp_supplicant/src/esp_owe_i.h | 18 +++++--- components/wpa_supplicant/src/ap/ieee802_11.c | 2 +- .../wpa_supplicant/src/common/wpa_common.c | 4 +- docs/en/api-guides/wifi-security.rst | 8 +--- .../softAP/main/softap_example_main.c | 2 +- 8 files changed, 73 insertions(+), 28 deletions(-) diff --git a/components/esp_wifi/lib b/components/esp_wifi/lib index 5bc1b234885..05dc7ac1d67 160000 --- a/components/esp_wifi/lib +++ b/components/esp_wifi/lib @@ -1 +1 @@ -Subproject commit 5bc1b234885938f265b75e7af3f1bb4036ef95ea +Subproject commit 05dc7ac1d67b3da59973df8238d634f66d686fef diff --git a/components/wpa_supplicant/esp_supplicant/src/esp_hostap.c b/components/wpa_supplicant/esp_supplicant/src/esp_hostap.c index 9e5e62f855f..0ae318b047f 100644 --- a/components/wpa_supplicant/esp_supplicant/src/esp_hostap.c +++ b/components/wpa_supplicant/esp_supplicant/src/esp_hostap.c @@ -507,14 +507,21 @@ bool hostap_new_assoc_sta(struct sta_info *sta, uint8_t *bssid, #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 && + (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_OWE) && sta->wpa_sm->wpa_key_mgmt == WPA_KEY_MGMT_OWE && - 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); - return false; + 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 */ diff --git a/components/wpa_supplicant/esp_supplicant/src/esp_owe.c b/components/wpa_supplicant/esp_supplicant/src/esp_owe.c index 13630625eae..99d43c6b7fe 100644 --- a/components/wpa_supplicant/esp_supplicant/src/esp_owe.c +++ b/components/wpa_supplicant/esp_supplicant/src/esp_owe.c @@ -60,7 +60,7 @@ struct wpabuf *esp_owe_build_assoc_resp_dhie(struct hostapd_data *hapd, const u8 return NULL; } - struct wpabuf *owe_buf = wpabuf_alloc(hapd->wpa_auth->wpa_ie_len); + 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; @@ -68,29 +68,65 @@ struct wpabuf *esp_owe_build_assoc_resp_dhie(struct hostapd_data *hapd, const u8 // If PMKSA caching is used, write and return only RSN IE with PMKID if (sta->wpa_sm && sta->wpa_sm->pmksa) { - u8 *pos, buf[128]; + 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); - wpabuf_resize(&owe_buf, pos - buf); + 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); - wpabuf_resize(&owe_buf, OWE_DHIE_LEN); + 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); diff --git a/components/wpa_supplicant/esp_supplicant/src/esp_owe_i.h b/components/wpa_supplicant/esp_supplicant/src/esp_owe_i.h index fc32924d1d7..971bddd6a56 100644 --- a/components/wpa_supplicant/esp_supplicant/src/esp_owe_i.h +++ b/components/wpa_supplicant/esp_supplicant/src/esp_owe_i.h @@ -26,13 +26,19 @@ void esp_wifi_register_owe_cb(struct wpa_funcs *wpa_cb); #include "ap/hostapd.h" /* -OWE_DHIE_LEN = 1 byte {WLAN_EID_EXTENSION} - + 1 byte {len of DHIE (1(pub_key len) + 2(dh group) + 32(len of pub_key)) = 35)} - + 1 byte {pub_key len} - + 2 bytes {DH group} - + 32 bytes {public key} -*/ + * 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 */ diff --git a/components/wpa_supplicant/src/ap/ieee802_11.c b/components/wpa_supplicant/src/ap/ieee802_11.c index e59339e917c..187c6757a6e 100644 --- a/components/wpa_supplicant/src/ap/ieee802_11.c +++ b/components/wpa_supplicant/src/ap/ieee802_11.c @@ -793,7 +793,7 @@ int wpa_auth_pmksa_add2(struct wpa_authenticator *wpa_auth, const u8 *addr, struct rsn_pmksa_cache_entry *entry; - wpa_hexdump_key(MSG_DEBUG, "RSN: Cache PMK (3)", pmk, PMK_LEN); + 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); diff --git a/components/wpa_supplicant/src/common/wpa_common.c b/components/wpa_supplicant/src/common/wpa_common.c index a8448a7c2a9..2b83b5801ca 100644 --- a/components/wpa_supplicant/src/common/wpa_common.c +++ b/components/wpa_supplicant/src/common/wpa_common.c @@ -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) return WPA_KEY_MGMT_IEEE8021X_SUITE_B_192; #endif -#ifdef CONFIG_OWE_STA +#if defined(CONFIG_OWE_STA) || defined(CONFIG_OWE_SOFTAP) if(RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_OWE) return WPA_KEY_MGMT_OWE; -#endif /* CONFIG_OWE_STA */ +#endif /* CONFIG_OWE_STA || CONFIG_OWE_SOFTAP */ #ifdef CONFIG_DPP if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_DPP) return WPA_KEY_MGMT_DPP; diff --git a/docs/en/api-guides/wifi-security.rst b/docs/en/api-guides/wifi-security.rst index fc6f77625d7..0040f106258 100644 --- a/docs/en/api-guides/wifi-security.rst +++ b/docs/en/api-guides/wifi-security.rst @@ -157,7 +157,7 @@ Enhanced Open™ is used for providing security and privacy to users connecting .. note:: - {IDF_TARGET_NAME} supports Wi-Fi Enhanced Open™ (OWE Transition Mode + OWE Only) in station mode and (OWE Only) in softap 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} @@ -170,8 +170,4 @@ A configuration option :ref:`CONFIG_ESP_WIFI_ENABLE_WPA3_OWE_STA` and configurat 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``. - -.. note:: - - In softap mode, if the configuration option :ref:`CONFIG_ESP_WIFI_ENABLE_WPA3_OWE_SOFTAP` is enabled and authmode is set to ``WIFI_AUTH_OPEN``, authmode will be set to ``WIFI_AUTH_OWE`` internally. +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. 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 c2bca87431a..9e450fbe080 100644 --- a/examples/wifi/getting_started/softAP/main/softap_example_main.c +++ b/examples/wifi/getting_started/softAP/main/softap_example_main.c @@ -90,7 +90,7 @@ void wifi_init_softap(void) .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; } From 1085d83c48509853edf0d8c792d521bb50a0bc3e Mon Sep 17 00:00:00 2001 From: Kapil Gupta Date: Wed, 6 May 2026 11:24:38 +0530 Subject: [PATCH 13/13] fix(esp_wifi): Update wifi lib pointer --- components/esp_wifi/lib | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/esp_wifi/lib b/components/esp_wifi/lib index 05dc7ac1d67..694f70f614a 160000 --- a/components/esp_wifi/lib +++ b/components/esp_wifi/lib @@ -1 +1 @@ -Subproject commit 05dc7ac1d67b3da59973df8238d634f66d686fef +Subproject commit 694f70f614ad857349eb7c2ba69093a5709bccfa