Merge branch 'bugfix/sae_identifier_nvs' into 'master'

fix(esp_wifi): Set default nvs value for sae identifier to NULL

See merge request espressif/esp-idf!42047
This commit is contained in:
Jiang Jiang Jian
2025-09-28 16:37:06 +08:00
29 changed files with 1384 additions and 648 deletions

View File

@@ -1,4 +1,3 @@
menu "Wi-Fi"
visible if (SOC_WIFI_SUPPORTED || SOC_WIRELESS_HOST_SUPPORTED)
@@ -308,13 +307,6 @@ menu "Wi-Fi"
explicitly configured before attempting connection. Please refer to the Wi-Fi Driver API Guide
for details.
config ESP_WIFI_ENABLE_SAE_PK
bool "Enable SAE-PK"
default y
depends on (ESP_WIFI_ENABLE_WPA3_SAE && ESP_WIFI_ENABLE_SAE_H2E)
help
Select this option to enable SAE-PK
config ESP_WIFI_ENABLE_SAE_H2E
bool "Enable SAE-H2E"
default y
@@ -322,6 +314,13 @@ menu "Wi-Fi"
help
Select this option to enable SAE-H2E
config ESP_WIFI_ENABLE_SAE_PK
bool "Enable SAE-PK"
default y
depends on ESP_WIFI_ENABLE_SAE_H2E
help
Select this option to enable SAE-PK
config ESP_WIFI_SOFTAP_SAE_SUPPORT
bool "Enable WPA3 Personal(SAE) SoftAP"
default y
@@ -340,6 +339,13 @@ menu "Wi-Fi"
explicitly configured before attempting connection. Please refer to the Wi-Fi Driver API Guide
for details.
config ESP_WIFI_WPA3_COMPATIBLE_SUPPORT
bool "Enable WPA3 Compatible support"
default y
depends on ESP_WIFI_ENABLE_SAE_H2E
help
Select this option to support wpa3_compatible mode for station and AP
config ESP_WIFI_SLP_IRAM_OPT
bool "WiFi SLP IRAM speed optimization"
select PM_SLP_DEFAULT_PARAMS_OPT

View File

@@ -533,8 +533,10 @@ typedef struct {
bool ftm_responder; /**< Enable FTM Responder mode */
wifi_pmf_config_t pmf_cfg; /**< Configuration for Protected Management Frame */
wifi_sae_pwe_method_t sae_pwe_h2e; /**< Configuration for SAE PWE derivation method */
uint8_t transition_disable; /**< Whether to enable transition disable feature */
uint8_t sae_ext; /**< Enable SAE EXT feature. SOC_GCMP_SUPPORT is required for this feature. */
uint8_t transition_disable: 1; /**< Whether to enable transition disable feature */
uint8_t sae_ext: 1; /**< Enable SAE EXT feature. SOC_GCMP_SUPPORT is required for this feature. */
uint8_t wpa3_compatible_mode: 1; /**< Enable WPA3 compatible authmode feature. Note: Enabling this will override the AP configuration's authmode and pairwise_cipher. The AP will operate as a WPA2 access point for all stations except for those that support WPA3 compatible mode. Only WPA3 compatibility mode stations will be able to use WPA3-SAE */
uint8_t reserved: 5; /**< Reserved for future feature set */
wifi_bss_max_idle_config_t bss_max_idle_cfg; /**< Configuration for bss max idle, effective if CONFIG_WIFI_BSS_MAX_IDLE_SUPPORT is enabled */
uint16_t gtk_rekey_interval; /**< GTK rekeying interval in seconds. If set to 0, GTK rekeying is disabled. Range: 60 ~ 65535 including 0. */
} wifi_ap_config_t;
@@ -561,7 +563,8 @@ typedef struct {
uint32_t ft_enabled: 1; /**< Whether FT is enabled for the connection */
uint32_t owe_enabled: 1; /**< Whether OWE is enabled for the connection */
uint32_t transition_disable: 1; /**< Whether to enable transition disable feature */
uint32_t reserved1: 26; /**< Reserved for future feature set */
uint32_t disable_wpa3_compatible_mode: 1; /**< Whether to disable wpa3 compatible authmode feature. Disabling this prevents connecting to WPA3-Personal RSN override (compatibility mode) APs; connection falls back to WPA2 only. */
uint32_t reserved1: 25; /**< Reserved for future feature set */
wifi_sae_pwe_method_t sae_pwe_h2e; /**< Configuration for SAE PWE derivation method */
wifi_sae_pk_mode_t sae_pk_mode; /**< Configuration for SAE-PK (Public Key) Authentication method */
uint8_t failure_retry_cnt; /**< Number of connection retries station will do before moving to next AP. scan_method should be set as WIFI_ALL_CHANNEL_SCAN to use this config.
@@ -578,7 +581,7 @@ typedef struct {
uint32_t vht_mu_beamformee_disabled: 1; /**< Whether to disable support for operation as an VHT MU beamformee. */
uint32_t vht_mcs8_enabled: 1; /**< Whether to support VHT-MCS8. The default value is 0. */
uint32_t reserved2: 19; /**< Reserved for future feature set */
uint8_t sae_h2e_identifier[SAE_H2E_IDENTIFIER_LEN];/**< Password identifier for H2E. this needs to be null terminated string */
uint8_t sae_h2e_identifier[SAE_H2E_IDENTIFIER_LEN]; /**< Password identifier for H2E. Strings null-terminated (length < SAE_H2E_IDENTIFIER_LEN) or non-null terminated (length = SAE_H2E_IDENTIFIER_LEN) are accepted. Non-null terminated string with 0xFF for full length of SAE_H2E_IDENTIFIER_LEN is not considered a valid identifier */
} wifi_sta_config_t;
/**

View File

@@ -287,6 +287,9 @@ endif()
if(CONFIG_ESP_WIFI_SOFTAP_SAE_SUPPORT)
target_compile_definitions(${COMPONENT_LIB} PRIVATE CONFIG_SAE)
endif()
if(CONFIG_ESP_WIFI_WPA3_COMPATIBLE_SUPPORT)
target_compile_definitions(${COMPONENT_LIB} PRIVATE CONFIG_WPA3_COMPAT)
endif()
if(CONFIG_ESP_WIFI_WPS_STRICT)
target_compile_definitions(${COMPONENT_LIB} PRIVATE CONFIG_WPS_STRICT)
endif()

View File

@@ -322,6 +322,10 @@ void supplicant_sta_conn_handler(uint8_t *bssid)
u8 *ie;
struct wpa_supplicant *wpa_s = &g_wpa_supp;
struct wpa_bss *bss = wpa_bss_get_bssid(wpa_s, bssid);
#ifdef CONFIG_RRM
struct ieee802_11_elems elems;
#endif
if (!bss) {
wpa_printf(MSG_INFO, "connected bss entry not present in scan cache");
return;
@@ -329,7 +333,13 @@ void supplicant_sta_conn_handler(uint8_t *bssid)
wpa_s->current_bss = bss;
ie = (u8 *)bss;
ie += sizeof(struct wpa_bss);
ieee802_11_parse_elems(wpa_s, ie, bss->ie_len);
#ifdef CONFIG_RRM
ieee802_11_parse_elems(ie, bss->ie_len, &elems, 0);
if (elems.rrm_enabled_len > 0 && elems.rrm_enabled != NULL) {
os_memcpy(wpa_s->rrm_ie, elems.rrm_enabled, 5);
wpa_s->rrm.rrm_used = true;
}
#endif
wpa_bss_flush(wpa_s);
/* Register for mgmt frames */
register_mgmt_frames(wpa_s);

View File

@@ -84,7 +84,6 @@ void *hostap_init(void)
}
hapd->conf->sae_pwe = esp_wifi_get_config_sae_pwe_h2e_internal(WIFI_IF_AP);
auth_conf->sae_pwe = hapd->conf->sae_pwe;
auth_conf->wpa_group_rekey = esp_wifi_ap_get_gtk_rekeying_config_internal();
#define MIN_GTK_REKEYING_INTERVAL 60
if (auth_conf->wpa_group_rekey && auth_conf->wpa_group_rekey < MIN_GTK_REKEYING_INTERVAL) {
@@ -110,6 +109,20 @@ void *hostap_init(void)
}
}
#endif /* CONFIG_IEEE80211W */
if (esp_wifi_is_wpa3_compatible_mode_enabled(WIFI_IF_AP)) {
#ifdef CONFIG_WPA3_COMPAT
auth_conf->rsn_override_omit_rsnxe = 1;
hapd->conf->rsn_override_omit_rsnxe = 1;
hapd->conf->rsn_override_key_mgmt = WPA_KEY_MGMT_SAE;
hapd->conf->rsn_override_pairwise = WPA_CIPHER_CCMP;
hapd->conf->rsn_override_mfp = MGMT_FRAME_PROTECTION_REQUIRED;
auth_conf->rsn_override_key_mgmt = WPA_KEY_MGMT_SAE;
auth_conf->rsn_override_pairwise = WPA_CIPHER_CCMP;
auth_conf->rsn_override_mfp = MGMT_FRAME_PROTECTION_REQUIRED;
#else
wpa_printf(MSG_ERROR, "ESP_WIFI_WPA3_COMPATIBLE_SUPPORT disabled, ignoring wpa3_compatible configuration");
#endif
}
/* TKIP is compulsory in WPA Mode */
if (auth_conf->wpa == WPA_PROTO_WPA && pairwise_cipher == WIFI_CIPHER_TYPE_CCMP) {
pairwise_cipher = WIFI_CIPHER_TYPE_TKIP_CCMP;
@@ -136,6 +149,7 @@ void *hostap_init(void)
auth_conf->rsn_pairwise = WPA_CIPHER_CCMP | WPA_CIPHER_TKIP;
}
auth_conf->sae_pwe = hapd->conf->sae_pwe;
auth_conf->wpa_key_mgmt = WPA_KEY_MGMT_PSK;
auth_conf->eapol_version = EAPOL_VERSION;
@@ -192,7 +206,8 @@ void *hostap_init(void)
#ifdef CONFIG_SAE
if (authmode == WIFI_AUTH_WPA3_PSK ||
authmode == WIFI_AUTH_WPA2_WPA3_PSK) {
authmode == WIFI_AUTH_WPA2_WPA3_PSK ||
esp_wifi_is_wpa3_compatible_mode_enabled(WIFI_IF_AP)) {
if (wpa3_hostap_auth_init(hapd) != 0) {
goto fail;
}
@@ -203,10 +218,13 @@ void *hostap_init(void)
hapd->conf->ssid.wpa_passphrase[WIFI_PASSWORD_LEN_MAX - 1] = '\0';
hapd->conf->max_num_sta = esp_wifi_ap_get_max_sta_conn();
auth_conf->transition_disable = esp_wifi_ap_get_transition_disable_internal();
if (authmode != WIFI_AUTH_WPA3_PSK &&
authmode != WIFI_AUTH_WPA2_WPA3_PSK && auth_conf->transition_disable) {
authmode != WIFI_AUTH_WPA2_WPA3_PSK &&
!esp_wifi_is_wpa3_compatible_mode_enabled(WIFI_IF_AP) &&
auth_conf->transition_disable) {
auth_conf->transition_disable = 0;
wpa_printf(MSG_DEBUG, "overriding transition_disable config with 0 as authmode is not WPA3");
wpa_printf(MSG_DEBUG, "overriding transition_disable config with 0 as authmode is not WPA3/WPA2-WPA3/compatible");
}
#ifdef CONFIG_SAE
@@ -396,15 +414,20 @@ uint8_t wpa_status_to_reason_code(int status)
}
}
bool hostap_new_assoc_sta(struct sta_info *sta, uint8_t *bssid, uint8_t *wpa_ie,
uint8_t wpa_ie_len, uint8_t *rsnxe, uint16_t rsnxe_len,
bool *pmf_enable, int subtype, uint8_t *pairwise_cipher, uint8_t *reason)
bool hostap_new_assoc_sta(struct sta_info *sta, uint8_t *bssid, u8 *wpa_ie,
u8 wpa_ie_len, u8 *rsnxe, uint16_t rsnxe_len,
bool *pmf_enable, int subtype, uint8_t *pairwise_cipher, uint8_t *reason, uint8_t *rsn_selection_ie)
{
struct hostapd_data *hapd = (struct hostapd_data*)esp_wifi_get_hostap_private_internal();
enum wpa_validate_result res = WPA_IE_OK;
int status = WLAN_STATUS_SUCCESS;
bool omit_rsnxe = false;
#ifdef CONFIG_WPA3_COMPAT
uint8_t rsn_selection_variant_len = 0;
uint8_t *rsn_selection_variant_ie = NULL;
#endif
if (!sta || !bssid || !wpa_ie) {
return false;
}
@@ -422,6 +445,16 @@ bool hostap_new_assoc_sta(struct sta_info *sta, uint8_t *bssid, uint8_t *wpa_ie,
goto send_resp;
}
#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];
}
wpa_auth_set_rsn_selection(sta->wpa_sm, rsn_selection_variant_ie, rsn_selection_variant_len);
#endif
res = wpa_validate_wpa_ie(hapd->wpa_auth, sta->wpa_sm, wpa_ie, wpa_ie_len, rsnxe, rsnxe_len);
#ifdef CONFIG_SAE
if (wpa_auth_uses_sae(sta->wpa_sm) && sta->sae &&
@@ -438,6 +471,12 @@ send_resp:
omit_rsnxe = true;
}
#ifdef CONFIG_WPA3_COMPAT
if (hapd->conf->rsn_override_omit_rsnxe) {
omit_rsnxe = false;
}
#endif
if (esp_send_assoc_resp(hapd, bssid, status, omit_rsnxe, subtype) != WLAN_STATUS_SUCCESS) {
status = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
}

View File

@@ -129,7 +129,7 @@ struct wpa_funcs {
bool (*wpa_sta_in_4way_handshake)(void);
void *(*wpa_ap_init)(void);
bool (*wpa_ap_deinit)(void *data);
bool (*wpa_ap_join)(void **sm, u8 *bssid, u8 *wpa_ie, u8 wpa_ie_len, u8* rsnxe, u16 rsnxe_len, bool *pmf_enable, int subtype, uint8_t *pairwise_cipher);
bool (*wpa_ap_join)(void **sm, u8 *bssid, u8 *wpa_ie, u8 wpa_ie_len, u8* rsnxe, u16 rsnxe_len, bool *pmf_enable, int subtype, uint8_t *pairwise_cipher, uint8_t *rsn_selection_ie);
bool (*wpa_ap_remove)(u8 *bssid);
uint8_t *(*wpa_ap_get_wpa_ie)(uint8_t *len);
bool (*wpa_ap_rx_eapol)(void *hapd_data, void *sm, u8 *data, size_t data_len);
@@ -302,7 +302,7 @@ bool esp_wifi_ap_notify_node_sae_auth_done(uint8_t *mac);
bool esp_wifi_ap_is_sta_sae_reauth_node(uint8_t *mac);
uint8_t* esp_wifi_sta_get_sae_identifier_internal(void);
bool esp_wifi_eb_tx_status_success_internal(void *eb);
uint8_t* esp_wifi_sta_get_rsnxe(u8 *bssid);
uint8_t* esp_wifi_sta_get_ie(u8 *bssid, uint8_t elem_id);
esp_err_t esp_wifi_sta_connect_internal(const uint8_t *bssid);
void esp_wifi_enable_sae_pk_only_mode_internal(void);
uint8_t esp_wifi_ap_get_transition_disable_internal(void);
@@ -310,4 +310,5 @@ int esp_wifi_softap_set_obss_overlap(bool overlap);
void esp_wifi_set_sigma_internal(bool flag);
void esp_wifi_ap_set_group_mgmt_cipher_internal(wifi_cipher_type_t cipher);
uint8_t esp_wifi_op_class_supported_internal(uint8_t op_class, uint8_t min_chan, uint8_t max_chan, uint8_t inc, uint8_t bw, channel_bitmap_t *non_pref_channels);
bool esp_wifi_is_wpa3_compatible_mode_enabled(uint8_t if_index);
#endif /* _ESP_WIFI_DRIVER_H_ */

View File

@@ -37,7 +37,7 @@ static esp_err_t wpa3_build_sae_commit(u8 *bssid, size_t *sae_msg_len)
bool valid_pwd_id = false;
#ifdef CONFIG_SAE_H2E
uint8_t sae_pwe = esp_wifi_get_config_sae_pwe_h2e_internal(WIFI_IF_STA);
const u8 *rsnxe;
const u8 *rsnxe = NULL;
uint8_t use_pt = 0;
struct wifi_ssid *ssid = esp_wifi_sta_get_prof_ssid_internal();
u8 rsnxe_capa = 0;
@@ -46,9 +46,19 @@ static esp_err_t wpa3_build_sae_commit(u8 *bssid, size_t *sae_msg_len)
use_pt = 1;
}
rsnxe = esp_wifi_sta_get_rsnxe(bssid);
if (rsnxe && rsnxe[1] >= 1) {
rsnxe_capa = rsnxe[2];
#ifdef CONFIG_WPA3_COMPAT
if (esp_wifi_is_wpa3_compatible_mode_enabled(WIFI_IF_STA)) {
rsnxe = esp_wifi_sta_get_ie((u8*)bssid, WFA_RSNXE_OVERRIDE_OUI_TYPE);
if (rsnxe) {
rsnxe_capa = rsnxe[2 + 4];
}
}
#endif
if (!rsnxe) {
rsnxe = esp_wifi_sta_get_ie((u8*)bssid, WLAN_EID_RSNX);
if (rsnxe) {
rsnxe_capa = rsnxe[2];
}
}
#endif /* CONFIG_SAE_H2E */

View File

@@ -113,7 +113,7 @@ int wpa_config_bss(uint8_t *bssid)
u8 mac[6];
esp_wifi_get_macaddr_internal(0, mac);
ret = wpa_set_bss((char *)mac, (char *)bssid, esp_wifi_sta_get_pairwise_cipher_internal(), esp_wifi_sta_get_group_cipher_internal(),
ret = wpa_set_bss(mac, bssid, esp_wifi_sta_get_pairwise_cipher_internal(), esp_wifi_sta_get_group_cipher_internal(),
(char *)esp_wifi_sta_get_prof_password_internal(), ssid->ssid, ssid->len);
return ret;
}
@@ -345,7 +345,7 @@ static void wpa_sta_disconnected_cb(uint8_t reason_code)
#ifdef CONFIG_ESP_WIFI_SOFTAP_SUPPORT
#ifdef CONFIG_WPS_REGISTRAR
static int check_n_add_wps_sta(struct hostapd_data *hapd, struct sta_info *sta_info, u8 *ies, u8 ies_len, bool *pmf_enable, int subtype)
static int check_n_add_wps_sta(struct hostapd_data *hapd, struct sta_info *sta_info, const u8 *ies, u8 ies_len, bool *pmf_enable, int subtype)
{
struct wpabuf *wps_ie = ieee802_11_vendor_ie_concat(ies, ies_len, WPS_DEV_OUI_WFA);
int wps_type = esp_wifi_get_wps_type_internal();
@@ -377,7 +377,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)
static bool hostap_sta_join(void **sta, u8 *bssid, u8 *wpa_ie, u8 wpa_ie_len, u8 *rsnxe, u16 rsnxe_len, bool *pmf_enable, int subtype, uint8_t *pairwise_cipher, uint8_t *rsn_selection_ie)
{
struct sta_info *sta_info = NULL;
struct hostapd_data *hapd = hostapd_get_hapd_data();
@@ -439,7 +439,7 @@ process_old_sta:
goto fail;
}
#endif
if (hostap_new_assoc_sta(sta_info, bssid, wpa_ie, wpa_ie_len, rsnxe, rsnxe_len, pmf_enable, subtype, pairwise_cipher, &reason)) {
if (hostap_new_assoc_sta(sta_info, bssid, wpa_ie, wpa_ie_len, rsnxe, rsnxe_len, pmf_enable, subtype, pairwise_cipher, &reason, rsn_selection_ie)) {
goto done;
} else {
goto fail;

View File

@@ -149,8 +149,12 @@ int hostapd_setup_sae_pt(struct hostapd_bss_config *conf)
{
#ifdef CONFIG_SAE_H2E
struct hostapd_ssid *ssid = &conf->ssid;
if ((conf->sae_pwe == SAE_PWE_HUNT_AND_PECK ||
!wpa_key_mgmt_sae(conf->wpa_key_mgmt)))
if (conf->sae_pwe == SAE_PWE_HUNT_AND_PECK ||
!wpa_key_mgmt_sae(conf->wpa_key_mgmt
#ifdef CONFIG_WPA3_COMPAT
| conf->rsn_override_key_mgmt
#endif
))
return 0; /* PT not needed */
sae_deinit_pt(ssid->pt);

View File

@@ -11,6 +11,7 @@
#include "common/defs.h"
#include "common/wpa_common.h"
#include "common/ieee802_11_common.h"
#define MAX_STA_COUNT 10
#define MAX_VLAN_ID 4094
@@ -199,8 +200,14 @@ struct hostapd_bss_config {
int wpa; /* bitfield of WPA_PROTO_WPA, WPA_PROTO_RSN */
int wpa_key_mgmt;
#ifdef CONFIG_WPA3_COMPAT
int rsn_override_key_mgmt;
#endif
#ifdef CONFIG_IEEE80211W
enum mfp_options ieee80211w;
#ifdef CONFIG_WPA3_COMPAT
enum mfp_options rsn_override_mfp;
#endif
/* dot11AssociationSAQueryMaximumTimeout (in TUs) */
unsigned int assoc_sa_query_max_timeout;
/* dot11AssociationSAQueryRetryTimeout (in TUs) */
@@ -219,6 +226,9 @@ struct hostapd_bss_config {
int wpa_ptk_rekey;
int rsn_pairwise;
int rsn_preauth;
#ifdef CONFIG_WPA3_COMPAT
int rsn_override_pairwise;
#endif
char *rsn_preauth_interfaces;
#ifdef CONFIG_IEEE80211R
@@ -306,6 +316,9 @@ struct hostapd_bss_config {
int *sae_groups;
#define SAE_ANTI_CLOGGING_THRESHOLD 2 /* max number of commit msg allowed to queue without anti-clogging token request */
#ifdef CONFIG_WPA3_COMPAT
int rsn_override_omit_rsnxe;
#endif
};
@@ -382,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, uint8_t *wpa_ie,
uint8_t wpa_ie_len, uint8_t *rsnxe, uint16_t rsnxe_len,
bool *pmf_enable, int subtype, uint8_t *pairwise_cipher, uint8_t *reason);
bool hostap_new_assoc_sta(struct sta_info *sta, uint8_t *bssid, u8 *wpa_ie,
u8 wpa_ie_len, u8 *rsnxe, uint16_t rsnxe_len,
bool *pmf_enable, int subtype, uint8_t *pairwise_cipher, uint8_t *reason, uint8_t *rsn_selection_ie);
bool wpa_ap_remove(u8* bssid);
#endif /* HOSTAPD_CONFIG_H */

View File

@@ -22,6 +22,7 @@
#include "ap/ap_config.h"
#include "ap/sta_info.h"
#include "common/wpa_common.h"
#include "common/ieee802_11_common.h"
#include "ap/pmksa_cache_auth.h"
#include "crypto/aes.h"
@@ -196,6 +197,30 @@ static inline int wpa_auth_get_seqnum(struct wpa_authenticator *wpa_auth,
return -1;
}
#ifdef CONFIG_WPA3_COMPAT
void wpa_auth_set_rsn_selection(struct wpa_state_machine *sm, const u8 *ie,
size_t len)
{
if (!sm)
return;
if (sm->rsn_selection) {
os_free(sm->rsn_selection);
sm->rsn_selection = NULL;
}
sm->rsn_selection_len = 0;
sm->rsn_override = false;
if (ie) {
if (len >= 1) {
if (ie[0] == RSN_SELECTION_RSNE_OVERRIDE)
sm->rsn_override = true;
}
sm->rsn_selection = os_memdup(ie, len);
if (sm->rsn_selection)
sm->rsn_selection_len = len;
}
}
#endif
/* fix buf for tx for now */
#define WPA_TX_MSG_BUFF_MAXLEN 200
@@ -501,6 +526,9 @@ static void wpa_free_sta_sm(struct wpa_state_machine *sm)
os_free(sm->last_rx_eapol_key);
os_free(sm->wpa_ie);
os_free(sm->rsnxe);
#ifdef CONFIG_WPA3_COMPAT
os_free(sm->rsn_selection);
#endif
os_free(sm);
}
@@ -958,7 +986,8 @@ continue_processing:
sm->EAPOLKeyReceived = TRUE;
sm->EAPOLKeyPairwise = !!(key_info & WPA_KEY_INFO_KEY_TYPE);
sm->EAPOLKeyRequest = !!(key_info & WPA_KEY_INFO_REQUEST);
memcpy(sm->SNonce, key->key_nonce, WPA_NONCE_LEN);
if (msg == PAIRWISE_2)
os_memcpy(sm->SNonce, key->key_nonce, WPA_NONCE_LEN);
wpa_sm_step(sm);
}
@@ -1741,6 +1770,34 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING)
return;
}
#ifdef CONFIG_WPA3_COMPAT
/* Verify RSN Selection element for RSN overriding */
if (sm->wpa_auth->conf.rsn_override_key_mgmt &&
((rsn_is_snonce_cookie(sm->SNonce) && !kde.rsn_selection) ||
(!rsn_is_snonce_cookie(sm->SNonce) && kde.rsn_selection) ||
(sm->rsn_selection && !kde.rsn_selection) ||
(!sm->rsn_selection && kde.rsn_selection) ||
(sm->rsn_selection && kde.rsn_selection &&
(sm->rsn_selection_len != kde.rsn_selection_len ||
os_memcmp(sm->rsn_selection, kde.rsn_selection,
sm->rsn_selection_len) != 0)))) {
wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm), LOGGER_INFO,
"RSN Selection element from (Re)AssocReq did not match the one in EAPOL-Key msg 2/4");
wpa_printf(MSG_DEBUG,
"SNonce cookie for RSN overriding %sused",
rsn_is_snonce_cookie(sm->SNonce) ? "" : "not ");
wpa_hexdump(MSG_DEBUG, "RSN Selection in AssocReq",
sm->rsn_selection, sm->rsn_selection_len);
wpa_hexdump(MSG_DEBUG, "RSN Selection in EAPOL-Key msg 2/4",
kde.rsn_selection, kde.rsn_selection_len);
/* MLME-DEAUTHENTICATE.request */
wpa_sta_disconnect(sm->wpa_auth, sm->addr,
WLAN_REASON_PREV_AUTH_NOT_VALID);
return;
}
#endif
sm->pending_1_of_4_timeout = 0;
eloop_cancel_timeout(resend_eapol_handle, (void*)(sm->index), NULL);
@@ -1832,11 +1889,15 @@ static u8 * ieee80211w_kde_add(struct wpa_state_machine *sm, u8 *pos)
SM_STATE(WPA_PTK, PTKINITNEGOTIATING)
{
u8 rsc[WPA_KEY_RSC_LEN], *_rsc, *gtk, *kde, *pos, dummy_gtk[32];
u8 rsc[WPA_KEY_RSC_LEN], *_rsc, *gtk, *kde = NULL, *pos, dummy_gtk[32];
size_t gtk_len, kde_len;
struct wpa_group *gsm = sm->group;
u8 *wpa_ie;
int wpa_ie_len, secure, keyidx, encr = 0;
#ifdef CONFIG_WPA3_COMPAT
u8 *wpa_ie_buf3 = NULL;
struct wpa_auth_config *conf = &sm->wpa_auth->conf;
#endif
SM_ENTRY_MA(WPA_PTK, PTKINITNEGOTIATING, wpa_ptk);
sm->TimeoutEvt = FALSE;
@@ -1865,6 +1926,40 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING)
wpa_ie = wpa_ie + wpa_ie[1] + 2;
wpa_ie_len = wpa_ie[1] + 2;
}
#ifdef CONFIG_WPA3_COMPAT
if (conf->rsn_override_key_mgmt &&
!rsn_is_snonce_cookie(sm->SNonce)) {
u8 *ie;
size_t ie_len;
u32 ids[] = {
RSNE_OVERRIDE_IE_VENDOR_TYPE,
RSNXE_OVERRIDE_IE_VENDOR_TYPE,
0
};
int i;
wpa_printf(MSG_DEBUG,
"RSN: Remove RSNE/RSNXE override elements");
wpa_hexdump(MSG_DEBUG, "EAPOL-Key msg 3/4 IEs before edits",
wpa_ie, wpa_ie_len);
wpa_ie_buf3 = os_memdup(wpa_ie, wpa_ie_len);
if (!wpa_ie_buf3)
goto done;
wpa_ie = wpa_ie_buf3;
for (i = 0; ids[i]; i++) {
ie = (u8 *) get_vendor_ie(wpa_ie, wpa_ie_len, ids[i]);
if (ie) {
ie_len = 2 + ie[1];
os_memmove(ie, ie + ie_len,
wpa_ie_len - (ie + ie_len - wpa_ie));
wpa_ie_len -= ie_len;
}
}
wpa_hexdump(MSG_DEBUG, "EAPOL-Key msg 3/4 IEs after edits",
wpa_ie, wpa_ie_len);
}
#endif
if (sm->wpa == WPA_VERSION_WPA2) {
/* WPA2 send GTK in the 4-way handshake */
secure = 1;
@@ -1876,7 +1971,7 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING)
* of GTK in the BSS.
*/
if (os_get_random(dummy_gtk, gtk_len) < 0)
return;
goto done;
gtk = dummy_gtk;
}
keyidx = gsm->GN;
@@ -1916,8 +2011,8 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING)
}
#endif /* CONFIG_IEEE80211R_AP */
kde = (u8 *)os_malloc(kde_len);
if (kde == NULL)
return;
if (!kde)
goto done;
pos = kde;
memcpy(pos, wpa_ie, wpa_ie_len);
@@ -1928,8 +2023,7 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING)
if (res < 0) {
wpa_printf( MSG_ERROR, "FT: Failed to insert "
"PMKR1Name into RSN IE in EAPOL-Key data");
os_free(kde);
return;
goto done;
}
pos += res;
}
@@ -1959,8 +2053,7 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING)
if (res < 0) {
wpa_printf( MSG_ERROR, "FT: Failed to insert FTIE "
"into EAPOL-Key Key Data");
os_free(kde);
return;
goto done;
}
pos += res;
@@ -1985,7 +2078,11 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING)
WPA_KEY_INFO_ACK | WPA_KEY_INFO_INSTALL |
WPA_KEY_INFO_KEY_TYPE,
_rsc, sm->ANonce, kde, pos - kde, keyidx, encr);
done:
os_free(kde);
#ifdef CONFIG_WPA3_COMPAT
os_free(wpa_ie_buf3);
#endif
}
@@ -2296,7 +2393,7 @@ static int wpa_gtk_update(struct wpa_authenticator *wpa_auth,
group->GTK[group->GN - 1], group->GTK_len);
#ifdef CONFIG_IEEE80211W
if (wpa_auth->conf.ieee80211w != NO_MGMT_FRAME_PROTECTION) {
if (wpa_auth_pmf_enabled(&wpa_auth->conf)) {
len = wpa_cipher_key_len(wpa_auth->conf.group_mgmt_cipher);
memcpy(group->GNonce, group->Counter, WPA_NONCE_LEN);
inc_byte_array(group->Counter, WPA_NONCE_LEN);
@@ -2492,7 +2589,7 @@ static int wpa_group_config_group_keys(struct wpa_authenticator *wpa_auth,
ret = -1;
#ifdef CONFIG_IEEE80211W
if (wpa_auth->conf.ieee80211w != NO_MGMT_FRAME_PROTECTION &&
if (wpa_auth_pmf_enabled(&wpa_auth->conf) &&
wpa_auth_set_key(wpa_auth, group->vlan_id, WIFI_WPA_ALG_IGTK,
broadcast_ether_addr, group->GN_igtk,
group->IGTK[group->GN_igtk - 4],

View File

@@ -127,6 +127,9 @@ struct ft_remote_r1kh {
struct wpa_auth_config {
int wpa;
int wpa_key_mgmt;
#ifdef CONFIG_WPA3_COMPAT
int rsn_override_key_mgmt;
#endif
int wpa_pairwise;
int wpa_group;
int wpa_group_rekey;
@@ -134,6 +137,9 @@ struct wpa_auth_config {
int wpa_gmk_rekey;
int wpa_ptk_rekey;
int rsn_pairwise;
#ifdef CONFIG_WPA3_COMPAT
int rsn_override_pairwise;
#endif
int rsn_preauth;
int eapol_version;
int wmm_enabled;
@@ -143,6 +149,9 @@ struct wpa_auth_config {
int tx_status;
#ifdef CONFIG_IEEE80211W
enum mfp_options ieee80211w;
#ifdef CONFIG_WPA3_COMPAT
enum mfp_options rsn_override_mfp;
#endif
#endif /* CONFIG_IEEE80211W */
int group_mgmt_cipher;
#ifdef CONFIG_SAE
@@ -168,6 +177,9 @@ struct wpa_auth_config {
enum sae_pwe sae_pwe;
struct rsn_sppamsdu_sup spp_sup;
u8 transition_disable;
#ifdef CONFIG_WPA3_COMPAT
int rsn_override_omit_rsnxe;
#endif
};
typedef enum {
@@ -304,5 +316,16 @@ int wpa_auth_pmksa_add_sae(struct wpa_authenticator *wpa_auth, const u8 *addr,
void wpa_auth_add_sae_pmkid(struct wpa_state_machine *sm, const u8 *pmkid);
void wpa_auth_pmksa_remove(struct wpa_authenticator *wpa_auth,
const u8 *sta_addr);
void wpa_auth_set_rsn_selection(struct wpa_state_machine *sm, const u8 *ie,
size_t len);
static inline bool wpa_auth_pmf_enabled(struct wpa_auth_config *conf)
{
#ifdef CONFIG_WPA3_COMPAT
return conf->ieee80211w != NO_MGMT_FRAME_PROTECTION ||
conf->rsn_override_mfp != NO_MGMT_FRAME_PROTECTION;
#else
return conf->ieee80211w != NO_MGMT_FRAME_PROTECTION;
#endif
}
#endif /* WPA_AUTH_H */

View File

@@ -100,6 +100,10 @@ struct wpa_state_machine {
size_t wpa_ie_len;
u8 *rsnxe;
size_t rsnxe_len;
#ifdef CONFIG_WPA3_COMPAT
u8 *rsn_selection;
size_t rsn_selection_len;
#endif
enum {
WPA_VERSION_NO_WPA = 0 /* WPA not used */,
@@ -110,6 +114,10 @@ struct wpa_state_machine {
int wpa_key_mgmt; /* the selected WPA_KEY_MGMT_* */
struct rsn_pmksa_cache_entry *pmksa;
#ifdef CONFIG_WPA3_COMPAT
bool rsn_override;
#endif
#ifdef CONFIG_IEEE80211R_AP
u8 xxkey[PMK_LEN_MAX]; /* PSK or the second 256 bits of MSK, or the
* first 384 bits of MSK */
@@ -195,7 +203,7 @@ struct wpa_authenticator {
int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len,
const u8 *pmkid, int group_mgmt_cipher);
const u8 *pmkid);
int wpa_write_rsnxe(struct wpa_auth_config *conf, u8 *buf, size_t len);
void __wpa_send_eapol(struct wpa_authenticator *wpa_auth,
struct wpa_state_machine *sm, int key_info,

View File

@@ -85,25 +85,57 @@ static int wpa_write_wpa_ie(struct wpa_auth_config *conf, u8 *buf, size_t len)
}
int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len,
const u8 *pmkid, int group_mgmt_cipher)
static u16 wpa_own_rsn_capab(struct wpa_auth_config *conf,
enum mfp_options mfp)
{
u16 capab = 0;
if (conf->rsn_preauth)
capab |= WPA_CAPABILITY_PREAUTH;
if (conf->wmm_enabled) {
/* 4 PTKSA replay counters when using WMM */
capab |= (RSN_NUM_REPLAY_COUNTERS_16 << 2);
}
if (conf->spp_sup.capable) {
capab |= WPA_CAPABILITY_SPP_CAPABLE;
}
if (conf->spp_sup.require) {
capab |= WPA_CAPABILITY_SPP_REQUIRED;
}
if (mfp != NO_MGMT_FRAME_PROTECTION) {
capab |= WPA_CAPABILITY_MFPC;
if (mfp == MGMT_FRAME_PROTECTION_REQUIRED)
capab |= WPA_CAPABILITY_MFPR;
}
#ifdef CONFIG_OCV
if (conf->ocv)
capab |= WPA_CAPABILITY_OCVC;
#endif /* CONFIG_OCV */
#ifdef CONFIG_RSN_TESTING
if (rsn_testing)
capab |= BIT(8) | BIT(15);
#endif /* CONFIG_RSN_TESTING */
return capab;
}
static u8 * rsne_write_data(u8 *buf, size_t len, u8 *pos, int group,
int pairwise, int key_mgmt, u16 rsn_capab,
const u8 *pmkid, enum mfp_options mfp,
int group_mgmt_cipher)
{
struct rsn_ie_hdr *hdr;
int num_suites, res;
u8 *pos, *count;
u16 capab;
u8 *count;
u32 suite;
hdr = (struct rsn_ie_hdr *) buf;
hdr->elem_id = WLAN_EID_RSN;
WPA_PUT_LE16(hdr->version, RSN_VERSION);
pos = (u8 *) (hdr + 1);
suite = wpa_cipher_to_suite(WPA_PROTO_RSN, conf->wpa_group);
suite = wpa_cipher_to_suite(WPA_PROTO_RSN, group);
if (suite == 0) {
wpa_printf( MSG_DEBUG, "Invalid group cipher (%d).",
conf->wpa_group);
return -1;
wpa_printf(MSG_DEBUG, "Invalid group cipher (%d).", group);
return NULL;
}
RSN_SELECTOR_PUT(pos, suite);
pos += RSN_SELECTOR_LEN;
@@ -120,7 +152,7 @@ int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len,
}
#endif /* CONFIG_RSN_TESTING */
res = rsn_cipher_put_suites(pos, conf->rsn_pairwise);
res = rsn_cipher_put_suites(pos, pairwise);
num_suites += res;
pos += res * RSN_SELECTOR_LEN;
@@ -134,8 +166,8 @@ int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len,
if (num_suites == 0) {
wpa_printf( MSG_DEBUG, "Invalid pairwise cipher (%d).",
conf->rsn_pairwise);
return -1;
pairwise);
return NULL;
}
WPA_PUT_LE16(count, num_suites);
@@ -151,52 +183,52 @@ int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len,
}
#endif /* CONFIG_RSN_TESTING */
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X) {
if (key_mgmt & WPA_KEY_MGMT_IEEE8021X) {
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_UNSPEC_802_1X);
pos += RSN_SELECTOR_LEN;
num_suites++;
}
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK) {
if (key_mgmt & WPA_KEY_MGMT_PSK) {
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X);
pos += RSN_SELECTOR_LEN;
num_suites++;
}
#ifdef CONFIG_IEEE80211R_AP
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) {
if (key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) {
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_802_1X);
pos += RSN_SELECTOR_LEN;
num_suites++;
}
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_PSK) {
if (key_mgmt & WPA_KEY_MGMT_FT_PSK) {
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_PSK);
pos += RSN_SELECTOR_LEN;
num_suites++;
}
#endif /* CONFIG_IEEE80211R_AP */
#ifdef CONFIG_IEEE80211W
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) {
if (key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) {
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_802_1X_SHA256);
pos += RSN_SELECTOR_LEN;
num_suites++;
}
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK_SHA256) {
if (key_mgmt & WPA_KEY_MGMT_PSK_SHA256) {
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_PSK_SHA256);
pos += RSN_SELECTOR_LEN;
num_suites++;
}
#endif /* CONFIG_IEEE80211W */
#ifdef CONFIG_SAE
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_SAE) {
if (key_mgmt & WPA_KEY_MGMT_SAE) {
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_SAE);
pos += RSN_SELECTOR_LEN;
num_suites++;
}
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_SAE_EXT_KEY) {
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_SAE_EXT_KEY);
pos += RSN_SELECTOR_LEN;
num_suites++;
if (key_mgmt & WPA_KEY_MGMT_SAE_EXT_KEY) {
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_SAE_EXT_KEY);
pos += RSN_SELECTOR_LEN;
num_suites++;
}
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_SAE) {
if (key_mgmt & WPA_KEY_MGMT_FT_SAE) {
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_SAE);
pos += RSN_SELECTOR_LEN;
num_suites++;
@@ -212,46 +244,19 @@ int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len,
#endif /* CONFIG_RSN_TESTING */
if (num_suites == 0) {
wpa_printf( MSG_DEBUG, "Invalid key management type (%d).",
conf->wpa_key_mgmt);
return -1;
wpa_printf(MSG_DEBUG, "Invalid key management type (%d).",
key_mgmt);
return NULL;
}
WPA_PUT_LE16(count, num_suites);
/* RSN Capabilities */
capab = 0;
if (conf->rsn_preauth)
capab |= WPA_CAPABILITY_PREAUTH;
if (conf->wmm_enabled) {
/* 4 PTKSA replay counters when using WMM */
capab |= (RSN_NUM_REPLAY_COUNTERS_16 << 2);
}
if (conf->spp_sup.capable) {
capab |= WPA_CAPABILITY_SPP_CAPABLE;
}
if (conf->spp_sup.require) {
capab |= WPA_CAPABILITY_SPP_REQUIRED;
}
#ifdef CONFIG_IEEE80211W
if (conf->ieee80211w != NO_MGMT_FRAME_PROTECTION) {
capab |= WPA_CAPABILITY_MFPC;
if (conf->ieee80211w == MGMT_FRAME_PROTECTION_REQUIRED)
capab |= WPA_CAPABILITY_MFPR;
}
#endif /* CONFIG_IEEE80211W */
#ifdef CONFIG_RSN_TESTING
if (rsn_testing)
capab |= BIT(8) | BIT(14) | BIT(15);
#endif /* CONFIG_RSN_TESTING */
WPA_PUT_LE16(pos, capab);
WPA_PUT_LE16(pos, rsn_capab);
pos += 2;
if (pmkid) {
if (pos + 2 + PMKID_LEN > buf + len)
return -1;
return NULL;
/* PMKID Count */
WPA_PUT_LE16(pos, 1);
pos += 2;
@@ -260,9 +265,9 @@ int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len,
}
#ifdef CONFIG_IEEE80211W
if (conf->ieee80211w != NO_MGMT_FRAME_PROTECTION) {
if (mfp != NO_MGMT_FRAME_PROTECTION) {
if (pos + 2 + 4 > buf + len)
return -1;
return NULL;
if (pmkid == NULL) {
/* PMKID Count */
WPA_PUT_LE16(pos, 0);
@@ -281,7 +286,10 @@ int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len,
RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_BIP_GMAC_256);
break;
default:
RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_AES_128_CMAC);
wpa_printf(MSG_DEBUG,
"Invalid group management cipher (0x%x)",
group_mgmt_cipher);
return NULL;
}
pos += RSN_SELECTOR_LEN;
}
@@ -294,12 +302,12 @@ int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len,
* the element.
*/
int pmkid_count_set = pmkid != NULL;
if (conf->ieee80211w != NO_MGMT_FRAME_PROTECTION)
if (mfp != NO_MGMT_FRAME_PROTECTION)
pmkid_count_set = 1;
/* PMKID Count */
WPA_PUT_LE16(pos, 0);
pos += 2;
if (conf->ieee80211w == NO_MGMT_FRAME_PROTECTION) {
if (mfp == NO_MGMT_FRAME_PROTECTION) {
/* Management Group Cipher Suite */
RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_AES_128_CMAC);
pos += RSN_SELECTOR_LEN;
@@ -309,6 +317,27 @@ int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len,
pos += 17;
}
#endif /* CONFIG_RSN_TESTING */
return pos;
}
int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len,
const u8 *pmkid)
{
struct rsn_ie_hdr *hdr;
u8 *pos;
hdr = (struct rsn_ie_hdr *) buf;
hdr->elem_id = WLAN_EID_RSN;
WPA_PUT_LE16(hdr->version, RSN_VERSION);
pos = (u8 *) (hdr + 1);
pos = rsne_write_data(buf, len, pos, conf->wpa_group,
conf->rsn_pairwise, conf->wpa_key_mgmt,
wpa_own_rsn_capab(conf, conf->ieee80211w), pmkid,
conf->ieee80211w, conf->group_mgmt_cipher);
if (!pos)
return -1;
hdr->len = (pos - buf) - 2;
@@ -316,32 +345,118 @@ int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len,
}
int wpa_write_rsnxe(struct wpa_auth_config *conf, u8 *buf, size_t len)
{
u8 *pos = buf;
u16 capab = 0;
size_t flen;
if (wpa_key_mgmt_sae(conf->wpa_key_mgmt) &&
#ifdef CONFIG_WPA3_COMPAT
static int wpa_write_rsne_override(struct wpa_auth_config *conf, u8 *buf,
size_t len)
{
u8 *pos, *len_pos;
pos = buf;
*pos++ = WLAN_EID_VENDOR_SPECIFIC;
len_pos = pos++;
WPA_PUT_BE32(pos, RSNE_OVERRIDE_IE_VENDOR_TYPE);
pos += 4;
WPA_PUT_LE16(pos, RSN_VERSION);
pos += 2;
pos = rsne_write_data(buf, len, pos, conf->wpa_group,
conf->rsn_override_pairwise,
conf->rsn_override_key_mgmt,
wpa_own_rsn_capab(conf, conf->rsn_override_mfp),
NULL, conf->rsn_override_mfp,
conf->group_mgmt_cipher);
if (!pos)
return -1;
*len_pos = (pos - buf) - 2;
return pos - buf;
}
#endif
static u32 rsnxe_capab(struct wpa_auth_config *conf, int key_mgmt)
{
u32 capab = 0;
if (wpa_key_mgmt_sae(key_mgmt) &&
(conf->sae_pwe == SAE_PWE_HASH_TO_ELEMENT ||
conf->sae_pwe == SAE_PWE_BOTH)) {
capab |= BIT(WLAN_RSNX_CAPAB_SAE_H2E);
}
flen = 1;
return capab;
}
int wpa_write_rsnxe(struct wpa_auth_config *conf, u8 *buf, size_t len)
{
u8 *pos = buf;
u32 capab = 0, tmp;
size_t flen;
capab = rsnxe_capab(conf, conf->wpa_key_mgmt);
if (!capab)
return 0; /* no supported extended RSN capabilities */
tmp = capab;
flen = 0;
while (tmp) {
flen++;
tmp >>= 8;
}
if (len < 2 + flen)
return -1;
capab |= flen - 1; /* bit 0-3 = Field length (n - 1) */
*pos++ = WLAN_EID_RSNX;
*pos++ = flen;
*pos++ = capab & 0x00ff;
while (capab) {
*pos++ = capab & 0xff;
capab >>= 8;
}
return pos - buf;
}
#ifdef CONFIG_WPA3_COMPAT
static int wpa_write_rsnxe_override(struct wpa_auth_config *conf, u8 *buf,
size_t len)
{
u8 *pos = buf;
u32 capab, tmp;
size_t flen;
capab = rsnxe_capab(conf, conf->rsn_override_key_mgmt);
if (!capab)
return 0; /* no supported extended RSN capabilities */
tmp = capab;
flen = 0;
while (tmp) {
flen++;
tmp >>= 8;
}
if (len < 2 + flen)
return -1;
capab |= flen - 1; /* bit 0-3 = Field length (n - 1) */
*pos++ = WLAN_EID_VENDOR_SPECIFIC;
*pos++ = 4 + flen;
WPA_PUT_BE32(pos, RSNXE_OVERRIDE_IE_VENDOR_TYPE);
pos += 4;
while (capab) {
*pos++ = capab & 0xff;
capab >>= 8;
}
return pos - buf;
}
#endif
int wpa_auth_gen_wpa_ie(struct wpa_authenticator *wpa_auth)
{
@@ -352,12 +467,19 @@ int wpa_auth_gen_wpa_ie(struct wpa_authenticator *wpa_auth)
if (wpa_auth->conf.wpa & WPA_PROTO_RSN) {
res = wpa_write_rsn_ie(&wpa_auth->conf,
pos, buf + sizeof(buf) - pos, NULL, wpa_auth->conf.group_mgmt_cipher);
pos, buf + sizeof(buf) - pos, NULL);
if (res < 0)
return res;
pos += res;
res = wpa_write_rsnxe(&wpa_auth->conf, pos,
buf + sizeof(buf) - pos);
#ifdef CONFIG_WPA3_COMPAT
if (wpa_auth->conf.rsn_override_omit_rsnxe)
res = 0;
else
#endif
res = wpa_write_rsnxe(&wpa_auth->conf, pos,
buf + sizeof(buf) - pos);
if (res < 0)
return res;
pos += res;
@@ -379,6 +501,26 @@ int wpa_auth_gen_wpa_ie(struct wpa_authenticator *wpa_auth)
pos += res;
}
#ifdef CONFIG_WPA3_COMPAT
if ((wpa_auth->conf.wpa & WPA_PROTO_RSN) &&
wpa_auth->conf.rsn_override_key_mgmt) {
res = wpa_write_rsne_override(&wpa_auth->conf,
pos, buf + sizeof(buf) - pos);
if (res < 0)
return res;
pos += res;
}
if ((wpa_auth->conf.wpa & WPA_PROTO_RSN) &&
(wpa_auth->conf.rsn_override_key_mgmt)) {
res = wpa_write_rsnxe_override(&wpa_auth->conf, pos,
buf + sizeof(buf) - pos);
if (res < 0)
return res;
pos += res;
}
#endif
os_free(wpa_auth->wpa_ie);
wpa_auth->wpa_ie = os_malloc(pos - buf);
if (wpa_auth->wpa_ie == NULL)
@@ -460,8 +602,8 @@ wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth,
#ifdef CONFIG_SAE
else if (data.key_mgmt & WPA_KEY_MGMT_SAE)
selector = RSN_AUTH_KEY_MGMT_SAE;
else if (data.key_mgmt & WPA_KEY_MGMT_SAE_EXT_KEY)
selector = RSN_AUTH_KEY_MGMT_SAE_EXT_KEY;
else if (data.key_mgmt & WPA_KEY_MGMT_SAE_EXT_KEY)
selector = RSN_AUTH_KEY_MGMT_SAE_EXT_KEY;
else if (data.key_mgmt & WPA_KEY_MGMT_FT_SAE)
selector = RSN_AUTH_KEY_MGMT_FT_SAE;
#endif /* CONFIG_SAE */
@@ -514,12 +656,18 @@ wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth,
return WPA_INVALID_GROUP;
}
key_mgmt = data.key_mgmt & wpa_auth->conf.wpa_key_mgmt;
#ifdef CONFIG_WPA3_COMPAT
if (sm->rsn_override)
key_mgmt = data.key_mgmt & wpa_auth->conf.rsn_override_key_mgmt;
else
#endif
key_mgmt = data.key_mgmt & wpa_auth->conf.wpa_key_mgmt;
if (!key_mgmt) {
wpa_printf( MSG_DEBUG, "Invalid WPA key mgmt (0x%x) from "
wpa_printf(MSG_DEBUG, "Invalid WPA key mgmt (0x%x) from "
MACSTR, data.key_mgmt, MAC2STR(sm->addr));
return WPA_INVALID_AKMP;
}
if (0) {
}
#ifdef CONFIG_IEEE80211R_AP
@@ -547,12 +695,18 @@ wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth,
else
sm->wpa_key_mgmt = WPA_KEY_MGMT_PSK;
#ifdef CONFIG_WPA3_COMPAT
if (version == WPA_PROTO_RSN && sm->rsn_override)
ciphers = data.pairwise_cipher &
wpa_auth->conf.rsn_override_pairwise;
else
#endif
if (version == WPA_PROTO_RSN)
ciphers = data.pairwise_cipher & wpa_auth->conf.rsn_pairwise;
else
ciphers = data.pairwise_cipher & wpa_auth->conf.wpa_pairwise;
if (!ciphers) {
wpa_printf( MSG_DEBUG, "Invalid %s pairwise cipher (0x%x) "
wpa_printf(MSG_DEBUG, "Invalid %s pairwise cipher (0x%x) "
"from " MACSTR,
version == WPA_PROTO_RSN ? "RSN" : "WPA",
data.pairwise_cipher, MAC2STR(sm->addr));
@@ -602,7 +756,7 @@ wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth,
}
#endif /* CONFIG_SAE */
if (wpa_auth->conf.ieee80211w == NO_MGMT_FRAME_PROTECTION ||
if (!wpa_auth_pmf_enabled(&wpa_auth->conf) ||
!(data.capabilities & WPA_CAPABILITY_MFPC))
sm->mgmt_frame_prot = 0;
else
@@ -689,124 +843,6 @@ wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth,
return WPA_IE_OK;
}
/**
* wpa_parse_generic - Parse EAPOL-Key Key Data Generic IEs
* @pos: Pointer to the IE header
* @end: Pointer to the end of the Key Data buffer
* @ie: Pointer to parsed IE data
* Returns: 0 on success, 1 if end mark is found, -1 on failure
*/
static int wpa_parse_generic(const u8 *pos, const u8 *end,
struct wpa_eapol_ie_parse *ie)
{
if (pos[1] == 0)
return 1;
if (pos[1] >= 6 &&
RSN_SELECTOR_GET(pos + 2) == WPA_OUI_TYPE &&
pos[2 + WPA_SELECTOR_LEN] == 1 &&
pos[2 + WPA_SELECTOR_LEN + 1] == 0) {
ie->wpa_ie = pos;
ie->wpa_ie_len = pos[1] + 2;
return 0;
}
if (pos + 1 + RSN_SELECTOR_LEN < end &&
pos[1] >= RSN_SELECTOR_LEN + PMKID_LEN &&
RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_PMKID) {
ie->pmkid = pos + 2 + RSN_SELECTOR_LEN;
return 0;
}
if (pos[1] > RSN_SELECTOR_LEN + 2 &&
RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_GROUPKEY) {
ie->gtk = pos + 2 + RSN_SELECTOR_LEN;
ie->gtk_len = pos[1] - RSN_SELECTOR_LEN;
return 0;
}
if (pos[1] > RSN_SELECTOR_LEN + 2 &&
RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_MAC_ADDR) {
ie->mac_addr = pos + 2 + RSN_SELECTOR_LEN;
ie->mac_addr_len = pos[1] - RSN_SELECTOR_LEN;
return 0;
}
#ifdef CONFIG_IEEE80211W
if (pos[1] > RSN_SELECTOR_LEN + 2 &&
RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_IGTK) {
ie->igtk = pos + 2 + RSN_SELECTOR_LEN;
ie->igtk_len = pos[1] - RSN_SELECTOR_LEN;
return 0;
}
#endif /* CONFIG_IEEE80211W */
return 0;
}
/**
* wpa_parse_kde_ies - Parse EAPOL-Key Key Data IEs
* @buf: Pointer to the Key Data buffer
* @len: Key Data Length
* @ie: Pointer to parsed IE data
* Returns: 0 on success, -1 on failure
*/
int wpa_parse_kde_ies(const u8 *buf, size_t len, struct wpa_eapol_ie_parse *ie)
{
const u8 *pos, *end;
int ret = 0;
memset(ie, 0, sizeof(*ie));
for (pos = buf, end = pos + len; pos + 1 < end; pos += 2 + pos[1]) {
if (pos[0] == 0xdd &&
((pos == buf + len - 1) || pos[1] == 0)) {
/* Ignore padding */
break;
}
if (pos + 2 + pos[1] > end) {
wpa_printf( MSG_DEBUG, "WPA: EAPOL-Key Key Data "
"underflow (ie=%d len=%d pos=%d)",
pos[0], pos[1], (int) (pos - buf));
wpa_hexdump_key(MSG_DEBUG, "WPA: Key Data",
buf, len);
ret = -1;
break;
}
if (*pos == WLAN_EID_RSN) {
ie->rsn_ie = pos;
ie->rsn_ie_len = pos[1] + 2;
#ifdef CONFIG_IEEE80211R_AP
} else if (*pos == WLAN_EID_MOBILITY_DOMAIN) {
ie->mdie = pos;
ie->mdie_len = pos[1] + 2;
} else if (*pos == WLAN_EID_FAST_BSS_TRANSITION) {
ie->ftie = pos;
ie->ftie_len = pos[1] + 2;
#endif /* CONFIG_IEEE80211R_AP */
} else if (*pos == WLAN_EID_RSNX) {
ie->rsnxe = pos;
ie->rsnxe_len = pos[1] + 2;
wpa_hexdump(MSG_DEBUG, "WPA: RSNXE in EAPOL-Key",
ie->rsnxe, ie->rsnxe_len);
} else if (*pos == WLAN_EID_VENDOR_SPECIFIC) {
ret = wpa_parse_generic(pos, end, ie);
if (ret < 0)
break;
if (ret > 0) {
ret = 0;
break;
}
} else {
wpa_hexdump(MSG_DEBUG, "WPA: Unrecognized EAPOL-Key "
"Key Data IE", pos, 2 + pos[1]);
}
}
return ret;
}
int wpa_auth_uses_mfp(struct wpa_state_machine *sm)
{
return sm ? sm->mgmt_frame_prot : 0;

View File

@@ -9,32 +9,6 @@
#ifndef WPA_AUTH_IE_H
#define WPA_AUTH_IE_H
struct wpa_eapol_ie_parse {
const u8 *wpa_ie;
size_t wpa_ie_len;
const u8 *rsn_ie;
size_t rsn_ie_len;
const u8 *pmkid;
const u8 *gtk;
size_t gtk_len;
const u8 *mac_addr;
size_t mac_addr_len;
#ifdef CONFIG_IEEE80211W
const u8 *igtk;
size_t igtk_len;
#endif /* CONFIG_IEEE80211W */
#ifdef CONFIG_IEEE80211R
const u8 *mdie;
size_t mdie_len;
const u8 *ftie;
size_t ftie_len;
#endif /* CONFIG_IEEE80211R */
const u8 *rsnxe;
size_t rsnxe_len;
};
int wpa_parse_kde_ies(const u8 *buf, size_t len,
struct wpa_eapol_ie_parse *ie);
u8 * wpa_add_kde(u8 *pos, u32 kde, const u8 *data, size_t data_len,
const u8 *data2, size_t data2_len);
int wpa_auth_gen_wpa_ie(struct wpa_authenticator *wpa_auth);

View File

@@ -192,72 +192,152 @@ int ieee802_11_parse_candidate_list(const char *pos, u8 *nei_rep,
}
#ifdef CONFIG_SAE_PK
static int ieee802_11_parse_vendor_specific(struct wpa_supplicant *wpa_s, const struct element *elem, const u8* pos)
static int ieee802_11_parse_vendor_specific(const u8 *pos, size_t elen,
struct ieee802_11_elems *elems,
int show_errors)
{
u32 oui;
/* first 3 bytes in vendor specific information element are the IEEE
* OUI of the vendor. The following byte is used a vendor specific
* sub-type. */
if (elen < 4) {
if (show_errors) {
wpa_printf(MSG_MSGDUMP, "short vendor specific "
"information element ignored (len=%lu)",
(unsigned long) elen);
}
return -1;
}
oui = WPA_GET_BE24(pos);
switch (oui) {
case OUI_WFA:
switch (pos[3]) {
case SAE_PK_OUI_TYPE:
wpa_s->sae_pk_elems.sae_pk_len = elem->datalen - 4;
wpa_s->sae_pk_elems.sae_pk = (u8*)os_zalloc(sizeof(u8)*(elem->datalen-4));
if (!wpa_s->sae_pk_elems.sae_pk) {
wpa_printf(MSG_EXCESSIVE, "Can not allocate memory for sae_pk");
return -1;
}
os_memcpy(wpa_s->sae_pk_elems.sae_pk, pos+4, elem->datalen-4);
elems->sae_pk = pos + 4;
elems->sae_pk_len = elen - 4;
break;
default:
wpa_printf(MSG_EXCESSIVE, "Unknown WFA "
"information element ignored "
"(type=%d len=%lu)",
pos[3], (unsigned long) elem->datalen);
return -1;
pos[3], (unsigned long) elen);
//TODO discuss if to ignore it
break;
//return -1;
}
break;
default:
wpa_printf(MSG_EXCESSIVE, "unknown vendor specific "
wpa_printf(MSG_EXCESSIVE, "unknown vendor specific "
"information element ignored (vendor OUI "
"%02x:%02x:%02x len=%lu)",
pos[0], pos[1], pos[2], (unsigned long) elem->datalen);
return -1;
}
return 0;
}
static int ieee802_11_parse_extension(struct wpa_supplicant *wpa_s, const struct element *elem, const u8* pos){
// do not consider extension_id element len in datalen
if (elem->datalen < 1) {
wpa_printf(MSG_DEBUG,
"short information element (Ext)");
return -1;
}
u8 ext_id;
ext_id = *pos++;
switch (ext_id) {
case WLAN_EID_EXT_FILS_KEY_CONFIRM:
wpa_s->sae_pk_elems.fils_key_confirm_len = elem->datalen - 1;
wpa_s->sae_pk_elems.fils_key_confirm = (u8*)os_zalloc(sizeof(u8)*(elem->datalen - 1));
os_memcpy(wpa_s->sae_pk_elems.fils_key_confirm, pos, elem->datalen - 1);
pos[0], pos[1], pos[2], (unsigned long) elen);
//TODO discuss if to ignore it
break;
case WLAN_EID_EXT_FILS_PUBLIC_KEY:
wpa_s->sae_pk_elems.fils_pk_len = elem->datalen - 1;
wpa_s->sae_pk_elems.fils_pk = (u8*)os_zalloc(sizeof(u8)*(elem->datalen - 1));
os_memcpy(wpa_s->sae_pk_elems.fils_pk, pos, elem->datalen - 1);
break;
default:
wpa_printf(MSG_EXCESSIVE,
"IEEE 802.11 element parsing ignored unknown element extension (ext_id=%u elen=%u)",
ext_id, (unsigned int) elem->datalen-1);
return -1;
//return -1;
}
return 0;
}
#endif /* CONFIG_SAE_PK */
#ifdef CONFIG_SAE_PK
static int ieee802_11_parse_extension(const u8 *pos, size_t elen,
struct ieee802_11_elems *elems,
const u8 *start, size_t len,
int show_errors)
{
u8 ext_id;
if (elen < 1) {
wpa_printf(MSG_DEBUG,
"short information element (Ext)");
return -1;
}
ext_id = *pos++;
elen--;
switch (ext_id) {
case WLAN_EID_EXT_FILS_KEY_CONFIRM:
elems->fils_key_confirm = pos;
elems->fils_key_confirm_len = elen;
break;
case WLAN_EID_EXT_FILS_PUBLIC_KEY:
if (elen < 1)
break;
elems->fils_pk = pos;
elems->fils_pk_len = elen;
break;
default:
wpa_printf(MSG_EXCESSIVE,
"IEEE 802.11 element parsing ignored unknown element extension (ext_id=%u elen=%u)",
ext_id, (unsigned int) elen);
//TODO discuss if to ignore it
break;
//return -1;
}
return 0;
}
#endif /* CONFIG_SAE_PK */
#if defined(CONFIG_RRM) || defined(CONFIG_WMM) || defined(CONFIG_SAE_PK)
static ParseRes __ieee802_11_parse_elems(const u8 *start, size_t len,
struct ieee802_11_elems *elems,
int show_errors)
{
const struct element *elem;
u8 unknown = 0;
if (!start)
return ParseOK;
for_each_element(elem, start, len) {
u8 id = elem->id, elen = elem->datalen;
const u8 *pos = elem->data;
switch (id) {
#ifdef CONFIG_RRM
case WLAN_EID_RRM_ENABLED_CAPABILITIES:
elems->rrm_enabled = pos;
elems->rrm_enabled_len = elen;
break;
#endif
#ifdef CONFIG_SAE_PK
case WLAN_EID_EXTENSION:
if (ieee802_11_parse_extension(pos, elen, elems, start,
len, show_errors) != 0) {
unknown++;
}
break;
case WLAN_EID_VENDOR_SPECIFIC:
if (ieee802_11_parse_vendor_specific(pos, elen,
elems,
show_errors) != 0) {
unknown++;
}
break;
#endif /*CONFIG_SAE_PK*/
#ifdef CONFIG_WNM
case WLAN_EID_EXT_CAPAB:
/* extended caps can go beyond 8 octacts but we aren't using them now */
elems->ext_capab = pos;
elems->ext_capab_len = elen;
break;
#endif
default:
break;
}
}
if (unknown)
return ParseFailed;
return ParseOK;
}
#endif
/**
* ieee802_11_parse_elems - Parse information elements in management frames
* @start: Pointer to the start of IEs
@@ -266,54 +346,14 @@ static int ieee802_11_parse_extension(struct wpa_supplicant *wpa_s, const struct
* @show_errors: Whether to show parsing errors in debug log
* Returns: Parsing result
*/
int ieee802_11_parse_elems(struct wpa_supplicant *wpa_s, const u8 *start, size_t len)
#if defined(CONFIG_RRM) || defined(CONFIG_WMM) || defined(CONFIG_SAE_PK)
ParseRes ieee802_11_parse_elems(const u8 *start, size_t len, struct ieee802_11_elems *elems, int show_errors)
{
#if defined(CONFIG_RRM) || defined(CONFIG_WNM) || defined(CONFIG_SAE_PK)
const struct element *elem;
u8 unknown = 0;
os_memset(elems, 0, sizeof(*elems));
if (!start)
return 0;
for_each_element(elem, start, len) {
u8 id = elem->id;
const u8 *pos = elem->data;
switch (id) {
#ifdef CONFIG_RRM
case WLAN_EID_RRM_ENABLED_CAPABILITIES:
os_memcpy(wpa_s->rrm_ie, pos, 5);
wpa_s->rrm.rrm_used = true;
break;
#endif
#ifdef CONFIG_SAE_PK
case WLAN_EID_EXTENSION:
if(ieee802_11_parse_extension(wpa_s, elem, pos) != 0){
unknown++;
}
break;
case WLAN_EID_VENDOR_SPECIFIC:
if(ieee802_11_parse_vendor_specific(wpa_s, elem, pos) != 0){
unknown++;
}
break;
#endif /*CONFIG_SAE_PK*/
#ifdef CONFIG_WNM
case WLAN_EID_EXT_CAPAB:
/* extended caps can go beyond 8 octacts but we aren't using them now */
os_memcpy(wpa_s->extend_caps, pos, 5);
break;
#endif
default:
break;
}
}
if (unknown)
return -1;
#endif /* defined(CONFIG_RRM) || defined(CONFIG_WNM) || defined(CONFIG_SAE_PK) */
return 0;
return __ieee802_11_parse_elems(start, len, elems, show_errors);
}
#endif
struct wpabuf * ieee802_11_vendor_ie_concat(const u8 *ies, size_t ies_len,
u32 oui_type)
@@ -379,6 +419,38 @@ const struct oper_class_map global_op_class[] = {
size_t global_op_class_size = ARRAY_SIZE(global_op_class);
bool ieee802_11_rsnx_capab_len(const u8 *rsnxe, size_t rsnxe_len,
unsigned int capab)
{
const u8 *end;
size_t flen, i;
u32 capabs = 0;
if (!rsnxe || rsnxe_len == 0)
return false;
end = rsnxe + rsnxe_len;
flen = (rsnxe[0] & 0x0f) + 1;
if (rsnxe + flen > end)
return false;
if (flen > 4)
flen = 4;
for (i = 0; i < flen; i++)
capabs |= (u32) rsnxe[i] << (8 * i);
return capabs & BIT(capab);
}
bool ieee802_11_rsnx_capab(const u8 *rsnxe, unsigned int capab)
{
if (!rsnxe)
return false;
if (rsnxe[0] == WLAN_EID_VENDOR_SPECIFIC && rsnxe[1] >= 4 + 1)
return ieee802_11_rsnx_capab_len(rsnxe + 2 + 4, rsnxe[1] - 4,
capab);
return ieee802_11_rsnx_capab_len(rsnxe + 2, rsnxe[1], capab);
}
u8 get_operating_class(u8 chan, int sec_channel)
{
u8 op_class = 0;

View File

@@ -48,10 +48,38 @@ struct oper_class_map {
extern const struct oper_class_map global_op_class[];
extern size_t global_op_class_size;
/* Parsed Information Elements */
struct ieee802_11_elems {
const u8 *rsn_ie;
u8 rsn_ie_len;
const u8 *rsnxe;
u8 rsnxe_len;
#ifdef CONFIG_RRM
const u8 *rrm_enabled;
u8 rrm_enabled_len;
#endif
#ifdef CONFIG_WNM
const u8 *ext_capab;
u8 ext_capab_len;
#endif
#ifdef CONFIG_SAE_PK
const u8 *fils_pk;
u8 fils_pk_len;
const u8 *fils_key_confirm;
u8 fils_key_confirm_len;
const u8 *sae_pk;
u8 sae_pk_len;
#endif
};
typedef enum { ParseOK = 0, ParseUnknown = 1, ParseFailed = -1 } ParseRes;
int ieee802_11_parse_candidate_list(const char *pos, u8 *nei_rep,
size_t nei_rep_len);
const u8 * get_ie(const u8 *ies, size_t len, u8 eid);
int ieee802_11_parse_elems(struct wpa_supplicant *wpa_s, const u8 *start, size_t len);
ParseRes ieee802_11_parse_elems(const u8 *start, size_t len,
struct ieee802_11_elems *elems,
int show_errors);
int ieee802_11_ext_capab(const u8 *ie, unsigned int capab);
const u8 * get_vendor_ie(const u8 *ies, size_t len, u32 vendor_type);
size_t mbo_add_ie(u8 *buf, size_t len, const u8 *attr, size_t attr_len);

View File

@@ -299,8 +299,15 @@
#define WLAN_TIMEOUT_KEY_LIFETIME 2
#define WLAN_TIMEOUT_ASSOC_COMEBACK 3
#define OUI_WFA 0x506f9a
/* DPP Public Action frame identifiers - OUI_WFA */
#define DPP_OUI_TYPE 0x1A
#define OUI_WFA 0x506f9a
#define WFA_RSNE_OVERRIDE_OUI_TYPE 0x29
#define WFA_RSNXE_OVERRIDE_OUI_TYPE 0x2b
#define WFA_RSN_SELECTION_OUI_TYPE 0x2c
#define RSNE_OVERRIDE_IE_VENDOR_TYPE 0x506f9a29
#define RSNXE_OVERRIDE_IE_VENDOR_TYPE 0x506f9a2b
#define RSN_SELECTION_IE_VENDOR_TYPE 0x506f9a2c
#ifdef _MSC_VER
#pragma pack(push, 1)

View File

@@ -618,9 +618,7 @@ int sae_check_confirm_pk(struct sae_data *sae, const u8 *ies, size_t ies_len)
u8 hash[SAE_MAX_HASH_LEN];
size_t hash_len;
int group;
struct wpa_supplicant *wpa_s = &g_wpa_supp;
struct sae_pk_elems elems;
int ret = 0;
struct ieee802_11_elems elems;
if (!tmp) {
return -1;
@@ -644,15 +642,16 @@ int sae_check_confirm_pk(struct sae_data *sae, const u8 *ies, size_t ies_len)
}
wpa_hexdump(MSG_DEBUG, "SAE-PK: Received confirm IEs", ies, ies_len);
ieee802_11_parse_elems(wpa_s, ies, ies_len);
elems = wpa_s->sae_pk_elems;
if (ieee802_11_parse_elems(ies, ies_len, &elems, 1) == ParseFailed) {
wpa_printf(MSG_INFO, "SAE-PK: Failed to parse confirm IEs");
return -1;
}
if (!elems.fils_pk || !elems.fils_key_confirm || !elems.sae_pk) {
wpa_printf(MSG_INFO,
"SAE-PK: Not all mandatory IEs included in confirm");
ret = -1;
goto done;
return -1;
}
/* TODO: Fragment reassembly */
@@ -660,8 +659,7 @@ int sae_check_confirm_pk(struct sae_data *sae, const u8 *ies, size_t ies_len)
if (elems.sae_pk_len < SAE_PK_M_LEN + AES_BLOCK_SIZE) {
wpa_printf(MSG_INFO,
"SAE-PK: No room for EncryptedModifier in SAE-PK element");
ret = -1;
goto done;
return -1;
}
wpa_hexdump(MSG_DEBUG, "SAE-PK: EncryptedModifier",
@@ -672,16 +670,14 @@ int sae_check_confirm_pk(struct sae_data *sae, const u8 *ies, size_t ies_len)
0, NULL, NULL, m) < 0) {
wpa_printf(MSG_INFO,
"SAE-PK: Failed to decrypt EncryptedModifier");
ret = -1;
goto done;
return -1;
}
wpa_hexdump_key(MSG_DEBUG, "SAE-PK: Modifier M", m, SAE_PK_M_LEN);
if (elems.fils_pk[0] != 2) {
wpa_printf(MSG_INFO, "SAE-PK: Unsupported public key type %u",
elems.fils_pk[0]);
ret = -1;
goto done;
return -1;
}
k_ap_len = elems.fils_pk_len - 1;
k_ap = elems.fils_pk + 1;
@@ -691,15 +687,13 @@ int sae_check_confirm_pk(struct sae_data *sae, const u8 *ies, size_t ies_len)
key = crypto_ec_key_parse_pub(k_ap, k_ap_len);
if (!key) {
wpa_printf(MSG_INFO, "SAE-PK: Failed to parse K_AP");
ret = -1;
goto done;
return -1;
}
group = crypto_ec_key_group(key);
if (!sae_pk_valid_fingerprint(sae, m, SAE_PK_M_LEN, k_ap, k_ap_len,
group)) {
crypto_ec_key_deinit(key);
ret = -1;
goto done;
return -1;
}
wpa_hexdump(MSG_DEBUG, "SAE-PK: Received KeyAuth",
@@ -709,8 +703,7 @@ int sae_check_confirm_pk(struct sae_data *sae, const u8 *ies, size_t ies_len)
if (sae_pk_hash_sig_data(sae, hash_len, false, m, SAE_PK_M_LEN,
k_ap, k_ap_len, hash) < 0) {
crypto_ec_key_deinit(key);
ret = -1;
goto done;
return -1;
}
res = crypto_ec_key_verify_signature(key, hash, hash_len,
@@ -721,25 +714,12 @@ int sae_check_confirm_pk(struct sae_data *sae, const u8 *ies, size_t ies_len)
if (res != 1) {
wpa_printf(MSG_INFO,
"SAE-PK: Invalid or incorrect signature in KeyAuth");
ret = -1;
goto done;
return -1;
}
wpa_printf(MSG_DEBUG, "SAE-PK: Valid KeyAuth signature received");
/* TODO: Store validated public key into network profile */
done:
if (wpa_s->sae_pk_elems.fils_pk) {
os_free(wpa_s->sae_pk_elems.fils_pk);
}
if (wpa_s->sae_pk_elems.sae_pk) {
os_free(wpa_s->sae_pk_elems.sae_pk);
}
if (wpa_s->sae_pk_elems.fils_key_confirm) {
os_free(wpa_s->sae_pk_elems.fils_key_confirm);
}
os_memset(&wpa_s->sae_pk_elems, 0, sizeof(wpa_s->sae_pk_elems));
return ret;
return 0;
}
#endif /* CONFIG_SAE_PK */

View File

@@ -402,7 +402,12 @@ int wpa_parse_wpa_ie_rsnxe(const u8 *rsnxe_ie, size_t rsnxe_ie_len,
if (rsnxe_ie_len < 1) {
return -1;
}
rsnxe_capa = rsnxe_ie[2];
if (rsnxe_ie && rsnxe_ie[0] == WLAN_EID_VENDOR_SPECIFIC &&
rsnxe_ie[1] >= 1 + 4) {
rsnxe_capa = rsnxe_ie[2 + 4];
} else {
rsnxe_capa = rsnxe_ie[2];
}
if (sae_pwe == 1 && !(rsnxe_capa & BIT(WLAN_RSNX_CAPAB_SAE_H2E))){
wpa_printf(MSG_ERROR, "SAE H2E required, but not supported by the AP");
return -1;
@@ -421,7 +426,6 @@ int wpa_parse_wpa_ie_rsnxe(const u8 *rsnxe_ie, size_t rsnxe_ie_len,
int wpa_parse_wpa_ie_rsn(const u8 *rsn_ie, size_t rsn_ie_len,
struct wpa_ie_data *data)
{
const struct rsn_ie_hdr *hdr;
const u8 *pos;
int left;
int i, count;
@@ -448,19 +452,29 @@ int wpa_parse_wpa_ie_rsn(const u8 *rsn_ie, size_t rsn_ie_len,
return -1;
}
hdr = (const struct rsn_ie_hdr *) rsn_ie;
if (rsn_ie_len >= 2 + 4 + 2 && rsn_ie[1] >= 4 + 2 &&
rsn_ie[1] == rsn_ie_len - 2 &&
(WPA_GET_BE32(&rsn_ie[2]) == RSNE_OVERRIDE_IE_VENDOR_TYPE) &&
WPA_GET_LE16(&rsn_ie[2 + 4]) == RSN_VERSION) {
pos = rsn_ie + 2 + 4 + 2;
left = rsn_ie_len - 2 - 4 - 2;
} else {
const struct rsn_ie_hdr *hdr;
if (hdr->elem_id != WLAN_EID_RSN ||
hdr->len != rsn_ie_len - 2 ||
WPA_GET_LE16(hdr->version) != RSN_VERSION) {
wpa_printf(MSG_DEBUG, "%s: malformed ie or unknown version",
__func__);
return -2;
hdr = (const struct rsn_ie_hdr *) rsn_ie;
if (hdr->elem_id != WLAN_EID_RSN ||
hdr->len != rsn_ie_len - 2 ||
WPA_GET_LE16(hdr->version) != RSN_VERSION) {
wpa_printf(MSG_DEBUG, "%s: malformed ie or unknown version",
__func__);
return -2;
}
pos = (const u8 *) (hdr + 1);
left = rsn_ie_len - sizeof(*hdr);
}
pos = (const u8 *) (hdr + 1);
left = rsn_ie_len - sizeof(*hdr);
if (left >= RSN_SELECTOR_LEN) {
data->group_cipher = rsn_selector_to_bitfield(pos);
pos += RSN_SELECTOR_LEN;
@@ -1580,4 +1594,189 @@ int wpa_cipher_put_suites(u8 *pos, int ciphers)
return num_suites;
}
/**
* wpa_parse_generic - Parse EAPOL-Key Key Data Generic IEs
* @pos: Pointer to the IE header
* @end: Pointer to the end of the Key Data buffer
* @ie: Pointer to parsed IE data
* Returns: 0 on success, 1 if end mark is found, -1 on failure
*/
static int wpa_parse_generic(const u8 *pos, const u8 *end,
struct wpa_eapol_ie_parse *ie)
{
u8 len = pos[1];
size_t dlen = 2 + len;
u32 selector;
const u8 *p;
size_t left;
if (len == 0)
return 1;
if (len < RSN_SELECTOR_LEN)
return 2;
p = pos + 2;
selector = RSN_SELECTOR_GET(p);
p += RSN_SELECTOR_LEN;
left = len - RSN_SELECTOR_LEN;
if (left >= 2 && selector == WPA_OUI_TYPE && p[0] == 1 && p[1] == 0) {
ie->wpa_ie = pos;
ie->wpa_ie_len = dlen;
wpa_hexdump(MSG_DEBUG, "WPA: WPA IE in EAPOL-Key",
ie->wpa_ie, ie->wpa_ie_len);
return 0;
}
if (left >= PMKID_LEN && selector == RSN_KEY_DATA_PMKID) {
ie->pmkid = p;
wpa_hexdump(MSG_DEBUG, "WPA: PMKID in EAPOL-Key", pos, dlen);
return 0;
}
if (left > 2 && selector == RSN_KEY_DATA_GROUPKEY) {
ie->gtk = p;
ie->gtk_len = left;
wpa_hexdump_key(MSG_DEBUG, "WPA: GTK in EAPOL-Key", pos, dlen);
return 0;
}
if (left >= ETH_ALEN && selector == RSN_KEY_DATA_MAC_ADDR) {
ie->mac_addr = p;
wpa_printf(MSG_DEBUG, "WPA: MAC Address in EAPOL-Key: " MACSTR,
MAC2STR(ie->mac_addr));
return 0;
}
#ifdef CONFIG_IEEE80211W
if (left > 2 && selector == RSN_KEY_DATA_IGTK) {
ie->igtk = p;
ie->igtk_len = left;
wpa_hexdump_key(MSG_DEBUG, "WPA: IGTK in EAPOL-Key",
pos, dlen);
return 0;
}
#endif /* CONFIG_IEEE80211W */
if (left >= 1 && selector == WFA_KEY_DATA_TRANSITION_DISABLE) {
ie->transition_disable = p;
ie->transition_disable_len = left;
wpa_hexdump(MSG_DEBUG,
"WPA: Transition Disable KDE in EAPOL-Key",
pos, dlen);
return 0;
}
#ifdef CONFIG_WPA3_COMPAT
if (selector == RSNE_OVERRIDE_IE_VENDOR_TYPE) {
ie->rsne_override = pos;
ie->rsne_override_len = dlen;
wpa_hexdump(MSG_DEBUG,
"RSN: RSNE Override element in EAPOL-Key",
ie->rsne_override, ie->rsne_override_len);
return 0;
}
if (selector == RSNXE_OVERRIDE_IE_VENDOR_TYPE) {
ie->rsnxe_override = pos;
ie->rsnxe_override_len = dlen;
wpa_hexdump(MSG_DEBUG,
"RSN: RSNXE Override element in EAPOL-Key",
ie->rsnxe_override, ie->rsnxe_override_len);
return 0;
}
if (selector == RSN_SELECTION_IE_VENDOR_TYPE) {
ie->rsn_selection = p;
ie->rsn_selection_len = left;
wpa_hexdump(MSG_DEBUG,
"RSN: RSN Selection element in EAPOL-Key",
ie->rsn_selection, ie->rsn_selection_len);
return 0;
}
#endif
return 2;
}
/**
* wpa_parse_kde_ies - Parse EAPOL-Key Key Data IEs
* @buf: Pointer to the Key Data buffer
* @len: Key Data Length
* @ie: Pointer to parsed IE data
* Returns: 0 on success, -1 on failure
*/
int wpa_parse_kde_ies(const u8 *buf, size_t len, struct wpa_eapol_ie_parse *ie)
{
const u8 *pos, *end;
int ret = 0;
os_memset(ie, 0, sizeof(*ie));
for (pos = buf, end = pos + len; pos + 1 < end; pos += 2 + pos[1]) {
if (pos[0] == 0xdd &&
((pos == buf + len - 1) || pos[1] == 0)) {
/* Ignore padding */
break;
}
if (pos + 2 + pos[1] > end) {
wpa_printf( MSG_DEBUG, "WPA: EAPOL-Key Key Data "
"underflow (ie=%d len=%d pos=%d)",
pos[0], pos[1], (int) (pos - buf));
wpa_hexdump_key(MSG_DEBUG, "WPA: Key Data",
buf, len);
ret = -1;
break;
}
if (*pos == WLAN_EID_RSN) {
ie->rsn_ie = pos;
ie->rsn_ie_len = pos[1] + 2;
#ifdef CONFIG_IEEE80211R_AP
} else if (*pos == WLAN_EID_MOBILITY_DOMAIN) {
ie->mdie = pos;
ie->mdie_len = pos[1] + 2;
} else if (*pos == WLAN_EID_FAST_BSS_TRANSITION) {
ie->ftie = pos;
ie->ftie_len = pos[1] + 2;
#endif /* CONFIG_IEEE80211R_AP */
} else if (*pos == WLAN_EID_RSNX) {
ie->rsnxe = pos;
ie->rsnxe_len = pos[1] + 2;
wpa_hexdump(MSG_DEBUG, "WPA: RSNXE in EAPOL-Key",
ie->rsnxe, ie->rsnxe_len);
} else if (*pos == WLAN_EID_VENDOR_SPECIFIC) {
ret = wpa_parse_generic(pos, end, ie);
if (ret < 0)
break;
if (ret > 0) {
ret = 0;
break;
}
} else {
wpa_hexdump(MSG_DEBUG, "WPA: Unrecognized EAPOL-Key "
"Key Data IE", pos, 2 + pos[1]);
}
}
return ret;
}
void rsn_set_snonce_cookie(u8 *snonce)
{
u8 *pos;
pos = snonce + WPA_NONCE_LEN - 6;
WPA_PUT_BE24(pos, OUI_WFA);
pos += 3;
WPA_PUT_BE24(pos, 0x000029);
}
bool rsn_is_snonce_cookie(const u8 *snonce)
{
const u8 *pos;
pos = snonce + WPA_NONCE_LEN - 6;
return WPA_GET_BE24(pos) == OUI_WFA &&
WPA_GET_BE24(pos + 3) == 0x000029;
}
#endif // ESP_SUPPLICANT

View File

@@ -427,6 +427,13 @@ struct wpa_ft_ies {
size_t ric_len;
};
/* WPA3 specification - RSN Selection element */
enum rsn_selection_variant {
RSN_SELECTION_RSNE = 0,
RSN_SELECTION_RSNE_OVERRIDE = 1,
};
int wpa_ft_parse_ies(const u8 *ies, size_t ies_len, struct wpa_ft_ies *parse);
int wpa_eapol_key_mic(const u8 *key, size_t key_len, int akmp, int ver,
@@ -439,6 +446,48 @@ int wpa_pmk_to_ptk(const u8 *pmk, size_t pmk_len, const char *label,
void rsn_pmkid(const u8 *pmk, size_t pmk_len, const u8 *aa, const u8 *spa,
u8 *pmkid, int akmp);
struct wpa_eapol_ie_parse {
const u8 *wpa_ie;
size_t wpa_ie_len;
const u8 *rsn_ie;
size_t rsn_ie_len;
const u8 *pmkid;
const u8 *gtk;
size_t gtk_len;
const u8 *mac_addr;
size_t mac_addr_len;
#ifdef CONFIG_IEEE80211W
const u8 *igtk;
size_t igtk_len;
#endif /* CONFIG_IEEE80211W */
#ifdef CONFIG_IEEE80211R
const u8 *mdie;
size_t mdie_len;
const u8 *ftie;
size_t ftie_len;
const u8 *reassoc_deadline;
const u8 *key_lifetime;
#endif /* CONFIG_IEEE80211R */
const u8 *transition_disable;
size_t transition_disable_len;
const u8 *rsnxe;
size_t rsnxe_len;
#ifdef CONFIG_WPA3_COMPAT
const u8 *rsn_selection;
size_t rsn_selection_len;
const u8 *rsne_override;
size_t rsne_override_len;
const u8 *rsnxe_override;
size_t rsnxe_override_len;
#endif
};
int wpa_parse_kde_ies(const u8 *buf, size_t len, struct wpa_eapol_ie_parse *ie);
static inline int wpa_supplicant_parse_ies(const u8 *buf, size_t len,
struct wpa_eapol_ie_parse *ie)
{
return wpa_parse_kde_ies(buf, len, ie);
}
int wpa_cipher_key_len(int cipher);
int wpa_cipher_rsc_len(int cipher);
int wpa_cipher_to_alg(int cipher);
@@ -456,4 +505,7 @@ unsigned int wpa_mic_len(int akmp, size_t pmk_len);
int wpa_use_akm_defined(int akmp);
int wpa_use_aes_key_wrap(int akmp);
void rsn_set_snonce_cookie(u8 *snonce);
bool rsn_is_snonce_cookie(const u8 *snonce);
#endif /* WPA_COMMON_H */

View File

@@ -67,17 +67,6 @@ enum scan_trigger_reason {
REASON_WNM_BSS_TRANS_REQ,
};
#ifdef CONFIG_SAE_PK
struct sae_pk_elems {
u8 *fils_pk;
u8 fils_pk_len;
u8 *fils_key_confirm;
u8 fils_key_confirm_len;
u8 *sae_pk;
u8 sae_pk_len;
};
#endif
struct wpa_supplicant {
int scanning;
@@ -149,10 +138,6 @@ struct wpa_supplicant {
struct beacon_rep_data beacon_rep_data;
struct os_reltime beacon_rep_scan;
#endif
#ifdef CONFIG_SAE_PK
struct sae_pk_elems sae_pk_elems;
#endif
};
struct non_pref_chan_s;

View File

@@ -537,6 +537,9 @@ int wpa_supplicant_send_2_of_4(struct wpa_sm *sm, const unsigned char *dst,
struct wpa_eapol_key *reply;
struct wpa_eapol_key_192 *reply192;
u8 *rsn_ie_buf = NULL;
#ifdef CONFIG_WPA3_COMPAT
u8 *buf2 = NULL;
#endif
u8 *rbuf, *key_mic;
if (wpa_ie == NULL) {
@@ -582,6 +585,36 @@ int wpa_supplicant_send_2_of_4(struct wpa_sm *sm, const unsigned char *dst,
wpa_ie = rsn_ie_buf;
}
#endif /* CONFIG_IEEE80211R */
#ifdef CONFIG_WPA3_COMPAT
if (sm->rsn_override != RSN_OVERRIDE_NOT_USED) {
u8 *pos;
buf2 = os_malloc(wpa_ie_len + 2 + 4 + 1);
if (!buf2) {
os_free(rsn_ie_buf);
return -1;
}
os_memcpy(buf2, wpa_ie, wpa_ie_len);
pos = buf2 + wpa_ie_len;
*pos++ = WLAN_EID_VENDOR_SPECIFIC;
*pos++ = 4 + 1;
WPA_PUT_BE32(pos, RSN_SELECTION_IE_VENDOR_TYPE);
pos += 4;
if (sm->rsn_override == RSN_OVERRIDE_RSNE) {
*pos++ = RSN_SELECTION_RSNE;
} else if (sm->rsn_override == RSN_OVERRIDE_RSNE_OVERRIDE) {
*pos++ = RSN_SELECTION_RSNE_OVERRIDE;
} else {
os_free(rsn_ie_buf);
os_free(buf2);
return -1;
}
wpa_ie = buf2;
wpa_ie_len += 2 + 4 + 1;
}
#endif
wpa_hexdump(MSG_MSGDUMP, "WPA: WPA IE for msg 2/4\n", wpa_ie, wpa_ie_len);
mic_len = wpa_mic_len(sm->key_mgmt, sm->pmk_len);
@@ -591,6 +624,9 @@ int wpa_supplicant_send_2_of_4(struct wpa_sm *sm, const unsigned char *dst,
&rlen, (void *) &reply);
if (rbuf == NULL) {
os_free(rsn_ie_buf);
#ifdef CONFIG_WPA3_COMPAT
os_free(buf2);
#endif
return -1;
}
reply192 = (struct wpa_eapol_key_192 *) reply;
@@ -617,6 +653,9 @@ int wpa_supplicant_send_2_of_4(struct wpa_sm *sm, const unsigned char *dst,
}
os_free(rsn_ie_buf);
#ifdef CONFIG_WPA3_COMPAT
os_free(buf2);
#endif
os_memcpy(reply->key_nonce, nonce, WPA_NONCE_LEN);
wpa_printf(MSG_DEBUG, "WPA Send EAPOL-Key 2/4");
@@ -702,7 +741,10 @@ void wpa_supplicant_process_1_of_4(struct wpa_sm *sm,
wpa_printf(MSG_DEBUG, "WPA: Failed to get random data for SNonce");
goto failed;
}
#ifdef CONFIG_WPA3_COMPAT
if (wpa_sm_rsn_overriding_supported(sm))
rsn_set_snonce_cookie(sm->snonce);
#endif
sm->renew_snonce = 0;
wpa_hexdump(MSG_DEBUG, "WPA: Renewed SNonce",
sm->snonce, WPA_NONCE_LEN);
@@ -1183,6 +1225,49 @@ static int wpa_supplicant_validate_ie(struct wpa_sm *sm,
return -1;
}
#ifdef CONFIG_WPA3_COMPAT
if (sm->proto == WPA_PROTO_RSN && wpa_sm_rsn_overriding_supported(sm)) {
if ((sm->ap_rsne_override && !ie->rsne_override) ||
(!sm->ap_rsne_override && ie->rsne_override) ||
(sm->ap_rsne_override && ie->rsne_override &&
(sm->ap_rsne_override_len != ie->rsne_override_len ||
os_memcmp(sm->ap_rsne_override, ie->rsne_override,
sm->ap_rsne_override_len) != 0))) {
wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
"RSN: RSNE Override element mismatch between Beacon/ProbeResp and EAPOL-Key msg 3/4");
wpa_hexdump(MSG_INFO,
"RSNE Override element in Beacon/ProbeResp",
sm->ap_rsne_override,
sm->ap_rsne_override_len);
wpa_hexdump(MSG_INFO,
"RSNE Override element in EAPOL-Key msg 3/4",
ie->rsne_override, ie->rsne_override_len);
wpa_sm_deauthenticate(sm,
WLAN_REASON_IE_IN_4WAY_DIFFERS);
return -1;
}
if ((sm->ap_rsnxe_override && !ie->rsnxe_override) ||
(!sm->ap_rsnxe_override && ie->rsnxe_override) ||
(sm->ap_rsnxe_override && ie->rsnxe_override &&
(sm->ap_rsnxe_override_len != ie->rsnxe_override_len ||
os_memcmp(sm->ap_rsnxe_override, ie->rsnxe_override,
sm->ap_rsnxe_override_len) != 0))) {
wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
"RSN: RSNXE Override element mismatch between Beacon/ProbeResp and EAPOL-Key msg 3/4");
wpa_hexdump(MSG_INFO,
"RSNXE Override element in Beacon/ProbeResp",
sm->ap_rsnxe_override,
sm->ap_rsnxe_override_len);
wpa_hexdump(MSG_INFO,
"RSNXE Override element in EAPOL-Key msg 3/4",
ie->rsnxe_override, ie->rsnxe_override_len);
wpa_sm_deauthenticate(sm,
WLAN_REASON_IE_IN_4WAY_DIFFERS);
return -1;
}
}
#endif
return 0;
}
@@ -1276,10 +1361,19 @@ static void wpa_supplicant_process_3_of_4(struct wpa_sm *sm,
key_info = WPA_GET_BE16(key->key_info);
if (wpa_supplicant_parse_ies(key_data, key_data_len, &ie) < 0)
if (wpa_supplicant_parse_ies(key_data, key_data_len, &ie) < 0) {
goto failed;
if (wpa_supplicant_validate_ie(sm, sm->bssid, &ie) < 0)
}
if (wpa_supplicant_validate_ie(sm, sm->bssid, &ie) < 0) {
goto failed;
}
if (os_memcmp(sm->anonce, key->key_nonce, WPA_NONCE_LEN) != 0) {
wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
"WPA: ANonce from message 1 of 4-Way Handshake differs from 3 of 4-Way Handshake - drop packet (src="
MACSTR ")", MAC2STR(sm->bssid));
goto failed;
}
if (ie.gtk && !(key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) {
wpa_printf(MSG_DEBUG, "WPA: GTK IE in unencrypted key data");
@@ -1326,10 +1420,10 @@ static void wpa_supplicant_process_3_of_4(struct wpa_sm *sm,
(sm->gd).gtk_len=0; //used as flag if gtk is installed in callback
if (ie.gtk) {
wpa_sm_set_seq(sm, key, 0);
if (wpa_supplicant_pairwise_gtk(sm,
if (wpa_supplicant_pairwise_gtk(sm,
ie.gtk, ie.gtk_len, key_info) < 0) {
wpa_printf(MSG_DEBUG, "RSN: Failed to configure GTK");
goto failed;
wpa_printf(MSG_DEBUG, "RSN: Failed to configure GTK");
goto failed;
}
}
@@ -1388,7 +1482,7 @@ static int wpa_supplicant_activate_ptk(struct wpa_sm *sm)
static int wpa_supplicant_send_4_of_4_txcallback(struct wpa_sm *sm)
{
u16 key_info=sm->key_info;
u16 key_info = sm->key_info;
if (sm->key_install && key_info & WPA_KEY_INFO_INSTALL) {
if (sm->use_ext_key_id) {
@@ -1447,7 +1541,7 @@ static int wpa_supplicant_send_4_of_4_txcallback(struct wpa_sm *sm)
return 0;
failed:
return WLAN_REASON_UNSPECIFIED;
return WLAN_REASON_UNSPECIFIED;
}
static int wpa_supplicant_process_1_of_2_rsn(struct wpa_sm *sm,
@@ -1766,7 +1860,7 @@ static int wpa_supplicant_decrypt_key_data(struct wpa_sm *sm,
*key_data_len -= 8; /* AES-WRAP adds 8 bytes */
/*replaced by xxx to remove malloc*/
buf = ((u8 *) (key+1))+ 8;
/*
/*
buf = os_wifi_malloc(keydatalen);
if (buf == NULL) {
wpa_printf(MSG_DEBUG, "WPA: No memory for "
@@ -1873,8 +1967,7 @@ int wpa_sm_rx_eapol(u8 *src_addr, u8 *buf, u32 len)
hdr = (struct ieee802_1x_hdr *) tmp;
key = (struct wpa_eapol_key *) (hdr + 1);
key192 = (struct wpa_eapol_key_192 *)
(tmp + sizeof(struct ieee802_1x_hdr));
key192 = (struct wpa_eapol_key_192 *)(tmp + sizeof(struct ieee802_1x_hdr));
if (mic_len == 24)
key_data = (u8 *) (key192 + 1);
else
@@ -2089,7 +2182,7 @@ void wpa_sm_set_state(enum wpa_states state)
{
struct wpa_sm *sm = &gWpaSm;
if(WPA_MIC_FAILURE==WPA_SM_STATE(sm))
eloop_cancel_timeout(wpa_supplicant_stop_countermeasures, NULL, NULL);
eloop_cancel_timeout(wpa_supplicant_stop_countermeasures, NULL, NULL);
sm->wpa_state= state;
}
@@ -2180,14 +2273,75 @@ void wpa_sm_deinit(void)
struct wpa_sm *sm = &gWpaSm;
pmksa_cache_deinit(sm->pmksa);
sm->pmksa = NULL;
os_free(sm->assoc_rsnxe);
sm->assoc_rsnxe = NULL;
os_free(sm->ap_rsn_ie);
sm->ap_rsn_ie = NULL;
os_free(sm->ap_rsnxe);
sm->ap_rsnxe = NULL;
os_free(sm->assoc_rsnxe);
#ifdef CONFIG_WPA3_COMPAT
os_free(sm->ap_rsne_override);
sm->ap_rsne_override = NULL;
os_free(sm->ap_rsnxe_override);
sm->ap_rsnxe_override = NULL;
#endif
wpa_sm_drop_sa(sm);
sm->assoc_rsnxe = NULL;
memset(sm, 0, sizeof(*sm));
}
/**
* wpa_sm_set_param - Set WPA state machine parameters
* @sm: Pointer to WPA state machine data from wpa_sm_init()
* @param: Parameter field
* @value: Parameter value
* Returns: 0 on success, -1 on failure
*/
#ifdef CONFIG_WPA3_COMPAT
int wpa_sm_set_param(struct wpa_sm *sm, enum wpa_sm_conf_params param,
unsigned int value)
{
int ret = 0;
if (sm == NULL)
return -1;
switch (param) {
case WPA_PARAM_RSN_OVERRIDE:
sm->rsn_override = value;
break;
case WPA_PARAM_RSN_OVERRIDE_SUPPORT:
sm->rsn_override_support = value;
break;
default:
break;
}
return ret;
}
#endif
#ifdef CONFIG_WPA3_COMPAT
static const u8 * wpa_sm_get_ap_rsne(struct wpa_sm *sm, size_t *len)
{
if (sm->rsn_override == RSN_OVERRIDE_RSNE_OVERRIDE) {
*len = sm->ap_rsne_override_len;
return sm->ap_rsne_override;
}
*len = sm->ap_rsn_ie_len;
return sm->ap_rsn_ie;
}
#endif
#ifdef CONFIG_WPA3_COMPAT
bool wpa_sm_rsn_overriding_supported(struct wpa_sm *sm)
{
const u8 *rsne;
size_t rsne_len;
rsne = wpa_sm_get_ap_rsne(sm, &rsne_len);
return sm->rsn_override_support && rsne;
}
#endif
#ifdef ESP_SUPPLICANT
/**
@@ -2320,15 +2474,17 @@ void wpa_set_pmk(uint8_t *pmk, size_t pmk_length, const u8 *pmkid, bool cache_pm
}
}
int wpa_set_bss(char *macddr, char * bssid, u8 pairwise_cipher, u8 group_cipher, char *passphrase, u8 *ssid, size_t ssid_len)
int wpa_set_bss(uint8_t *macddr, uint8_t *bssid, uint8_t pairwise_cipher, uint8_t group_cipher, char *passphrase, uint8_t *ssid, int ssid_len)
{
int res = 0;
struct wpa_sm *sm = &gWpaSm;
bool use_pmk_cache = !esp_wifi_skip_supp_pmkcaching();
u8 assoc_rsnxe[20];
size_t assoc_rsnxe_len = sizeof(assoc_rsnxe);
uint8_t assoc_ie[128] = {0};
uint16_t assoc_ie_len = sizeof(assoc_ie);
bool reassoc_same_ess = false;
int try_opportunistic = 0;
const u8 *ie = NULL;
uint8_t *pos = NULL;
/* Incase AP has changed it's SSID, don't try with PMK caching for SAE connection */
/* Ideally we should use network_ctx for this purpose however currently network profile block
@@ -2367,11 +2523,11 @@ int wpa_set_bss(char *macddr, char * bssid, u8 pairwise_cipher, u8 group_cipher,
}
}
if (wpa_key_mgmt_supports_caching(sm->key_mgmt) && use_pmk_cache) {
if (reassoc_same_ess && wpa_key_mgmt_wpa_ieee8021x(sm->key_mgmt)) {
if (reassoc_same_ess && wpa_key_mgmt_wpa_ieee8021x(sm->key_mgmt)) {
pmksa_cache_set_current(sm, NULL, (const u8*) bssid, (void*)sm->network_ctx, try_opportunistic);
} else {
} else {
pmksa_cache_set_current(sm, NULL, (const u8*) bssid, 0, try_opportunistic);
}
}
wpa_sm_set_pmk_from_pmksa(sm);
} else {
if (pmksa) {
@@ -2388,9 +2544,9 @@ int wpa_set_bss(char *macddr, char * bssid, u8 pairwise_cipher, u8 group_cipher,
sm->pmf_cfg = wifi_cfg.sta.pmf_cfg;
sm->mgmt_group_cipher = cipher_type_map_public_to_supp(mgmt_cipher);
if (sm->mgmt_group_cipher == WPA_CIPHER_NONE) {
wpa_printf(MSG_ERROR, "mgmt_cipher %d not supported", mgmt_cipher);
return -1;
}
wpa_printf(MSG_ERROR, "mgmt_cipher %d not supported", mgmt_cipher);
return -1;
}
#ifdef CONFIG_SUITEB192
extern bool g_wpa_suiteb_certification;
if (is_wpa2_enterprise_connection() && g_wpa_suiteb_certification) {
@@ -2420,7 +2576,7 @@ int wpa_set_bss(char *macddr, char * bssid, u8 pairwise_cipher, u8 group_cipher,
#ifdef CONFIG_IEEE80211R
if (sm->key_mgmt == WPA_KEY_MGMT_FT_PSK) {
const u8 *ie, *md = NULL;
struct wpa_bss *bss = wpa_bss_get_bssid(&g_wpa_supp, (uint8_t *)bssid);
struct wpa_bss *bss = wpa_bss_get_bssid(&g_wpa_supp, bssid);
if (!bss) {
return -1;
}
@@ -2447,24 +2603,80 @@ int wpa_set_bss(char *macddr, char * bssid, u8 pairwise_cipher, u8 group_cipher,
return -1;
sm->assoc_wpa_ie_len = res;
const u8 *rsnxe;
rsnxe = esp_wifi_sta_get_rsnxe((u8*)bssid);
wpa_sm_set_ap_rsnxe(rsnxe, rsnxe ? (rsnxe[1] + 2) : 0);
ie = esp_wifi_sta_get_ie(bssid, WLAN_EID_RSN);
wpa_sm_set_ap_rsn_ie(sm, ie, ie ? (ie[1] + 2) : 0);
ie = esp_wifi_sta_get_ie(bssid, WLAN_EID_RSNX);
wpa_sm_set_ap_rsnxe(sm, ie, ie ? (ie[1] + 2) : 0);
res = wpa_gen_rsnxe(sm, assoc_rsnxe, assoc_rsnxe_len);
#ifdef CONFIG_WPA3_COMPAT
ie = esp_wifi_sta_get_ie(bssid, WFA_RSNE_OVERRIDE_OUI_TYPE);
wpa_sm_set_ap_rsne_override(sm, ie, ie ? (ie[1] + 2) : 0);
ie = esp_wifi_sta_get_ie(bssid, WFA_RSNXE_OVERRIDE_OUI_TYPE);
wpa_sm_set_ap_rsnxe_override(sm, ie, ie ? (ie[1] + 2) : 0);
#endif
pos = assoc_ie;
res = wpa_gen_rsnxe(sm, pos, assoc_ie_len);
if (res < 0)
return -1;
assoc_rsnxe_len = res;
res = wpa_sm_set_assoc_rsnxe(sm, assoc_rsnxe, assoc_rsnxe_len);
if (res < 0)
assoc_ie_len = res;
res = wpa_sm_set_assoc_rsnxe(sm, pos, assoc_ie_len);
if (res < 0) {
return -1;
esp_set_assoc_ie((uint8_t *)bssid, assoc_rsnxe, assoc_rsnxe_len, true);
}
pos += assoc_ie_len;
#ifdef CONFIG_WPA3_COMPAT
wpa_sm_set_param(sm, WPA_PARAM_RSN_OVERRIDE_SUPPORT,
esp_wifi_is_wpa3_compatible_mode_enabled(WIFI_IF_STA));
wpa_sm_set_param(sm, WPA_PARAM_RSN_OVERRIDE,
RSN_OVERRIDE_NOT_USED);
ie = esp_wifi_sta_get_ie(bssid, WFA_RSNE_OVERRIDE_OUI_TYPE);
if (esp_wifi_is_wpa3_compatible_mode_enabled(WIFI_IF_STA) && ie) {
enum rsn_selection_variant variant = RSN_SELECTION_RSNE;
if (ie && ie[0] == WLAN_EID_VENDOR_SPECIFIC && ie[1] >= 4) {
u32 type;
type = WPA_GET_BE32(&ie[2]);
if (type == RSNE_OVERRIDE_IE_VENDOR_TYPE) {
variant = RSN_SELECTION_RSNE_OVERRIDE;
wpa_sm_set_param(sm,
WPA_PARAM_RSN_OVERRIDE,
RSN_OVERRIDE_RSNE_OVERRIDE);
}
}
/* Indicate support for RSN overriding */
*pos++ = WLAN_EID_VENDOR_SPECIFIC;
*pos++ = 4 + 1;
WPA_PUT_BE32(pos, RSN_SELECTION_IE_VENDOR_TYPE);
pos += 4;
*pos = variant;
assoc_ie_len += 2 + 4 + 1;
}
#endif
wpa_hexdump(MSG_DEBUG, "WPA: ASSOC IE LEN", assoc_ie, assoc_ie_len);
esp_set_assoc_ie(bssid, assoc_ie, assoc_ie_len, true);
if (sm->ap_rsnxe != NULL) {
#ifdef CONFIG_SAE_PK
const u8 *pw = (const u8 *)esp_wifi_sta_get_prof_password_internal();
if (esp_wifi_sta_get_config_sae_pk_internal() != WPA3_SAE_PK_MODE_DISABLED &&
sae_pk_valid_password((const char*)pw)) {
sm->sae_pk = true;
}
#endif /* CONFIG_SAE_PK */
}
os_memset(sm->ssid, 0, sizeof(sm->ssid));
os_memcpy(sm->ssid, ssid, ssid_len);
sm->ssid_len = ssid_len;
wpa_set_passphrase(passphrase, ssid, ssid_len);
#ifdef CONFIG_MBO
if (!mbo_bss_profile_match((u8 *)bssid))
if (!mbo_bss_profile_match(bssid))
return -1;
#endif
@@ -2477,8 +2689,7 @@ int wpa_set_bss(char *macddr, char * bssid, u8 pairwise_cipher, u8 group_cipher,
/*
* Call after set ssid since we calc pmk inside this routine directly
*/
void
wpa_set_passphrase(char * passphrase, u8 *ssid, size_t ssid_len)
void wpa_set_passphrase(char * passphrase, u8 *ssid, size_t ssid_len)
{
struct wifi_ssid *sta_ssid = esp_wifi_sta_get_prof_ssid_internal();
struct wpa_sm *sm = &gWpaSm;
@@ -2511,7 +2722,7 @@ wpa_set_passphrase(char * passphrase, u8 *ssid, size_t ssid_len)
}
if (sm->key_mgmt == WPA_KEY_MGMT_IEEE8021X) {
/* TODO nothing */
/* TODO nothing */
} else {
memcpy(sm->pmk, esp_wifi_sta_get_ap_info_prof_pmk_internal(), PMK_LEN);
sm->pmk_len = PMK_LEN;
@@ -2523,18 +2734,17 @@ wpa_set_passphrase(char * passphrase, u8 *ssid, size_t ssid_len)
#endif /* CONFIG_IEEE80211R */
}
void
set_assoc_ie(u8 * assoc_buf)
void set_assoc_ie(u8 * assoc_buf)
{
struct wpa_sm *sm = &gWpaSm;
sm->assoc_wpa_ie = assoc_buf + 2;
//wpa_ie insert OUI 4 byte before ver, but RSN have 2 bytes of RSN capability,
// so wpa_ie have two more bytes than rsn_ie
if ( sm->proto == WPA_PROTO_WPA)
sm->assoc_wpa_ie_len = ASSOC_IE_LEN;
if (sm->proto == WPA_PROTO_WPA)
sm->assoc_wpa_ie_len = ASSOC_IE_LEN;
else
sm->assoc_wpa_ie_len = ASSOC_IE_LEN - 2;
sm->assoc_wpa_ie_len = ASSOC_IE_LEN - 2;
wpa_config_assoc_ie(sm->proto, assoc_buf, sm->assoc_wpa_ie_len);
}
@@ -2616,7 +2826,7 @@ int wpa_michael_mic_failure(u16 isunicast)
* Need to wait for completion of request frame. We do not get
* any callback for the message completion, so just wait a
* short while and hope for the best. */
os_sleep(0, 10000);
os_sleep(0, 10000);
/*deauthenticate AP*/
@@ -2740,13 +2950,57 @@ struct wpa_sm * get_wpa_sm(void)
return &gWpaSm;
}
int wpa_sm_set_ap_rsnxe(const u8 *ie, size_t len)
/**
* wpa_sm_set_ap_rsn_ie - Set AP RSN IE from Beacon/ProbeResp
* @sm: Pointer to WPA state machine data from wpa_sm_init()
* @ie: Pointer to IE data (starting from id)
* @len: IE length
* Returns: 0 on success, -1 on failure
*
* Inform WPA state machine about the RSN IE used in Beacon / Probe Response
* frame.
*/
int wpa_sm_set_ap_rsn_ie(struct wpa_sm *sm, const u8 *ie, size_t len)
{
struct wpa_sm *sm = &gWpaSm;
if (sm == NULL)
return -1;
os_free(sm->ap_rsn_ie);
if (ie == NULL || len == 0) {
wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
"WPA: clearing AP RSN IE");
sm->ap_rsn_ie = NULL;
sm->ap_rsn_ie_len = 0;
} else {
wpa_hexdump(MSG_DEBUG, "WPA: set AP RSN IE", ie, len);
sm->ap_rsn_ie = os_memdup(ie, len);
if (sm->ap_rsn_ie == NULL)
return -1;
sm->ap_rsn_ie_len = len;
}
return 0;
}
/**
* wpa_sm_set_ap_rsnxe - Set AP RSNXE from Beacon/ProbeResp
* @sm: Pointer to WPA state machine data from wpa_sm_init()
* @ie: Pointer to IE data (starting from id)
* @len: IE length
* Returns: 0 on success, -1 on failure
*
* Inform WPA state machine about the RSNXE used in Beacon / Probe Response
* frame.
*/
int wpa_sm_set_ap_rsnxe(struct wpa_sm *sm, const u8 *ie, size_t len)
{
if (!sm)
return -1;
os_free(sm->ap_rsnxe);
if (!ie || len == 0) {
wpa_hexdump(MSG_DEBUG, "WPA: set AP RSNXE", ie, len);
wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: clearing AP RSNXE");
sm->ap_rsnxe = NULL;
sm->ap_rsnxe_len = 0;
} else {
@@ -2758,20 +3012,64 @@ int wpa_sm_set_ap_rsnxe(const u8 *ie, size_t len)
sm->ap_rsnxe_len = len;
}
if (sm->ap_rsnxe != NULL) {
sm->sae_pwe = esp_wifi_get_config_sae_pwe_h2e_internal(WIFI_IF_STA);
#ifdef CONFIG_SAE_PK
const u8 *pw = (const u8 *)esp_wifi_sta_get_prof_password_internal();
if (esp_wifi_sta_get_config_sae_pk_internal() != WPA3_SAE_PK_MODE_DISABLED &&
sae_pk_valid_password((const char*)pw)) {
sm->sae_pk = true;
}
#endif /* CONFIG_SAE_PK */
}
return 0;
}
#ifdef CONFIG_WPA3_COMPAT
int wpa_sm_set_ap_rsne_override(struct wpa_sm *sm, const u8 *ie, size_t len)
{
if (!sm)
return -1;
os_free(sm->ap_rsne_override);
if (!ie || len == 0) {
wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
"RSN: Clearing AP RSNE Override element");
sm->ap_rsne_override = NULL;
sm->ap_rsne_override_len = 0;
} else {
wpa_hexdump(MSG_DEBUG, "RSN: Set AP RSNE Override element",
ie, len);
sm->ap_rsne_override = os_memdup(ie, len);
if (!sm->ap_rsne_override)
return -1;
sm->ap_rsne_override_len = len;
}
return 0;
}
#endif
#ifdef CONFIG_WPA3_COMPAT
int wpa_sm_set_ap_rsnxe_override(struct wpa_sm *sm, const u8 *ie, size_t len)
{
if (!sm)
return -1;
os_free(sm->ap_rsnxe_override);
if (!ie || len == 0) {
wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
"RSN: Clearing AP RSNXE Override element");
sm->ap_rsnxe_override = NULL;
sm->ap_rsnxe_override_len = 0;
} else {
wpa_hexdump(MSG_DEBUG, "RSN: Set AP RSNXE Override element",
ie, len);
sm->ap_rsnxe_override = os_memdup(ie, len);
if (!sm->ap_rsnxe_override)
return -1;
sm->ap_rsnxe_override_len = len;
}
return 0;
}
#endif
int wpa_sm_set_assoc_rsnxe(struct wpa_sm *sm, const u8 *ie, size_t len)
{
if (!sm)

View File

@@ -35,6 +35,12 @@ struct l2_ethhdr {
be16 h_proto;
} STRUCT_PACKED;
#ifdef CONFIG_WPA3_COMPAT
enum wpa_sm_conf_params {
WPA_PARAM_RSN_OVERRIDE,
WPA_PARAM_RSN_OVERRIDE_SUPPORT,
};
#endif
void wpa_sm_set_state(enum wpa_states state);
@@ -54,12 +60,24 @@ int wpa_sm_set_key(struct install_key *sm, enum wpa_alg alg,
u8 *key, size_t key_len,
enum key_flag key_flag);
int wpa_sm_set_ap_rsnxe(const u8 *ie, size_t len);
int wpa_sm_set_ap_rsn_ie(struct wpa_sm *sm, const u8 *ie, size_t len);
int wpa_sm_set_ap_rsnxe(struct wpa_sm *sm, const u8 *ie, size_t len);
#ifdef CONFIG_WPA3_COMPAT
int wpa_sm_set_ap_rsne_override(struct wpa_sm *sm, const u8 *ie, size_t len);
int wpa_sm_set_ap_rsnxe_override(struct wpa_sm *sm, const u8 *ie, size_t len);
#endif
int wpa_sm_set_assoc_rsnxe(struct wpa_sm *sm, const u8 *ie, size_t len);
void wpa_sm_drop_sa(struct wpa_sm *sm);
#ifdef CONFIG_WPA3_COMPAT
int wpa_sm_set_param(struct wpa_sm *sm, enum wpa_sm_conf_params param,
unsigned int value);
#endif
#ifdef CONFIG_IEEE80211R
int wpa_sm_set_ft_params(struct wpa_sm *sm, const u8 *ies, size_t ies_len);

View File

@@ -22,6 +22,13 @@ struct install_key {
u8 key[32];
};
#ifdef CONFIG_WPA3_COMPAT
enum wpa_rsn_override {
RSN_OVERRIDE_NOT_USED,
RSN_OVERRIDE_RSNE,
RSN_OVERRIDE_RSNE_OVERRIDE,
};
#endif
/**
* struct wpa_sm - Internal WPA state machine data
*/
@@ -76,6 +83,10 @@ struct wpa_sm {
u8 *ap_wpa_ie, *ap_rsn_ie, *ap_rsnxe;
size_t ap_wpa_ie_len, ap_rsn_ie_len, ap_rsnxe_len;
#ifdef CONFIG_WPA3_COMPAT
u8 *ap_rsne_override, *ap_rsnxe_override;
size_t ap_rsne_override_len, ap_rsnxe_override_len;
#endif
bool key_install;
@@ -119,6 +130,10 @@ struct wpa_sm {
#endif /* CONFIG_OWE_STA */
int (*wpa_sm_wps_disable)(void);
esp_err_t (*wpa_sm_eap_disable)(void);
#ifdef CONFIG_WPA3_COMPAT
bool rsn_override_support;
enum wpa_rsn_override rsn_override;
#endif
};
/**
@@ -204,10 +219,13 @@ void eapol_txcb(uint8_t *eapol_payload, size_t len, bool tx_failure);
void wpa_set_profile(u32 wpa_proto, u8 auth_mode);
int wpa_set_bss(char *macddr, char * bssid, u8 pairwise_cipher, u8 group_cipher, char *passphrase, u8 *ssid, size_t ssid_len);
int wpa_set_bss(uint8_t *macddr, uint8_t *bssid, uint8_t pairwise_cipher, uint8_t group_cipher, char *passphrase, uint8_t *ssid, int ssid_len);
int wpa_sm_rx_eapol(u8 *src_addr, u8 *buf, u32 len);
int wpa_derive_ptk_ft(struct wpa_sm *sm, const unsigned char *src_addr,
const struct wpa_eapol_key *key, struct wpa_ptk *ptk);
#ifdef CONFIG_WPA3_COMPAT
bool wpa_sm_rsn_overriding_supported(struct wpa_sm *sm);
#endif
#endif /* WPA_I_H */

View File

@@ -39,6 +39,16 @@ int wpa_parse_wpa_ie(const u8 *wpa_ie, size_t wpa_ie_len,
return wpa_parse_wpa_ie_rsnxe(wpa_ie, wpa_ie_len, data);
} else if (wpa_ie[0] == WLAN_EID_WAPI) {
return 0;
#ifdef CONFIG_WPA3_COMPAT
} else if (wpa_ie_len >= 6 && wpa_ie[0] == WLAN_EID_VENDOR_SPECIFIC &&
wpa_ie[1] >= 4 &&
WPA_GET_BE32(&wpa_ie[2]) == RSNE_OVERRIDE_IE_VENDOR_TYPE) {
return wpa_parse_wpa_ie_rsn(wpa_ie, wpa_ie_len, data);
} else if (wpa_ie_len >= 6 && wpa_ie[0] == WLAN_EID_VENDOR_SPECIFIC &&
wpa_ie[1] >= 4 &&
WPA_GET_BE32(&wpa_ie[2]) == RSNXE_OVERRIDE_IE_VENDOR_TYPE) {
return wpa_parse_wpa_ie_rsnxe(wpa_ie, wpa_ie_len, data);
#endif
}
return wpa_parse_wpa_ie_wpa(wpa_ie, wpa_ie_len, data);
@@ -297,7 +307,7 @@ int wpa_gen_wpa_ie(struct wpa_sm *sm, u8 *wpa_ie, size_t wpa_ie_len)
int wpa_gen_rsnxe(struct wpa_sm *sm, u8 *rsnxe, size_t rsnxe_len)
{
u8 *pos = rsnxe;
u16 capab = 0, tmp;
u32 capab = 0, tmp;
size_t flen;
if (wpa_key_mgmt_sae(sm->key_mgmt) &&
@@ -326,142 +336,11 @@ int wpa_gen_rsnxe(struct wpa_sm *sm, u8 *rsnxe, size_t rsnxe_len)
*pos++ = WLAN_EID_RSNX;
*pos++ = flen;
*pos++ = capab & 0x00ff;
capab >>= 8;
if (capab)
*pos++ = capab;
while (capab) {
*pos++ = capab & 0xff;
capab >>= 8;
}
return pos - rsnxe;
}
/**
* wpa_parse_generic - Parse EAPOL-Key Key Data Generic IEs
* @pos: Pointer to the IE header
* @end: Pointer to the end of the Key Data buffer
* @ie: Pointer to parsed IE data
* Returns: 0 on success, 1 if end mark is found, -1 on failure
*/
static int wpa_parse_generic(const u8 *pos, const u8 *end,
struct wpa_eapol_ie_parse *ie)
{
if (pos[1] == 0)
return 1;
if (pos[1] >= 6 &&
RSN_SELECTOR_GET(pos + 2) == WPA_OUI_TYPE &&
pos[2 + WPA_SELECTOR_LEN] == 1 &&
pos[2 + WPA_SELECTOR_LEN + 1] == 0) {
ie->wpa_ie = pos;
ie->wpa_ie_len = pos[1] + 2;
wpa_hexdump(MSG_DEBUG, "WPA: WPA IE in EAPOL-Key",
ie->wpa_ie, ie->wpa_ie_len);
return 0;
}
if (pos + 1 + RSN_SELECTOR_LEN < end &&
pos[1] >= RSN_SELECTOR_LEN + PMKID_LEN &&
RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_PMKID) {
ie->pmkid = pos + 2 + RSN_SELECTOR_LEN;
wpa_hexdump(MSG_DEBUG, "WPA: PMKID in EAPOL-Key",
pos, pos[1] + 2);
return 0;
}
if (pos[1] > RSN_SELECTOR_LEN + 2 &&
RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_GROUPKEY) {
ie->gtk = pos + 2 + RSN_SELECTOR_LEN;
ie->gtk_len = pos[1] - RSN_SELECTOR_LEN;
wpa_hexdump(MSG_DEBUG, "WPA: GTK in EAPOL-Key",
pos, pos[1] + 2);
return 0;
}
if (pos[1] > RSN_SELECTOR_LEN + 2 &&
RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_MAC_ADDR) {
ie->mac_addr = pos + 2 + RSN_SELECTOR_LEN;
ie->mac_addr_len = pos[1] - RSN_SELECTOR_LEN;
wpa_hexdump(MSG_DEBUG, "WPA: MAC Address in EAPOL-Key",
pos, pos[1] + 2);
return 0;
}
#ifdef CONFIG_IEEE80211W
if (pos[1] > RSN_SELECTOR_LEN + 2 &&
RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_IGTK) {
ie->igtk = pos + 2 + RSN_SELECTOR_LEN;
ie->igtk_len = pos[1] - RSN_SELECTOR_LEN;
wpa_hexdump(MSG_DEBUG, "WPA: IGTK in EAPOL-Key",
pos, pos[1] + 2);
return 0;
}
#endif
if (pos[1] >= RSN_SELECTOR_LEN + 1 &&
RSN_SELECTOR_GET(pos + 2) == WFA_KEY_DATA_TRANSITION_DISABLE) {
ie->transition_disable = pos + 2 + RSN_SELECTOR_LEN;
ie->transition_disable_len = pos[1] - RSN_SELECTOR_LEN;
wpa_hexdump(MSG_DEBUG,
"WPA: Transition Disable KDE in EAPOL-Key",
pos, pos[1] + 2);
return 0;
}
return 0;
}
/**
* wpa_supplicant_parse_ies - Parse EAPOL-Key Key Data IEs
* @buf: Pointer to the Key Data buffer
* @len: Key Data Length
* @ie: Pointer to parsed IE data
* Returns: 0 on success, -1 on failure
*/
int wpa_supplicant_parse_ies(const u8 *buf, size_t len,
struct wpa_eapol_ie_parse *ie)
{
const u8 *pos, *end;
int ret = 0;
memset(ie, 0, sizeof(*ie));
for (pos = buf, end = pos + len; pos + 1 < end; pos += 2 + pos[1]) {
if (pos[0] == 0xdd &&
((pos == buf + len - 1) || pos[1] == 0)) {
/* Ignore padding */
break;
}
if (pos + 2 + pos[1] > end) {
wpa_printf(MSG_DEBUG, "WPA: EAPOL-Key Key Data "
"underflow (ie=%d len=%d pos=%d)",
pos[0], pos[1], (int) (pos - buf));
wpa_hexdump(MSG_DEBUG, "WPA: Key Data",
buf, len);
ret = -1;
break;
}
if (*pos == WLAN_EID_RSN) {
ie->rsn_ie = pos;
ie->rsn_ie_len = pos[1] + 2;
wpa_hexdump(MSG_DEBUG, "WPA: RSN IE in EAPOL-Key",
ie->rsn_ie, ie->rsn_ie_len);
} else if (*pos == WLAN_EID_RSNX) {
ie->rsnxe = pos;
ie->rsnxe_len = pos[1] + 2;
wpa_hexdump(MSG_DEBUG, "WPA: RSNXE in EAPOL-Key",
ie->rsnxe, ie->rsnxe_len);
} else if (*pos == WLAN_EID_VENDOR_SPECIFIC) {
ret = wpa_parse_generic(pos, end, ie);
if (ret < 0)
break;
if (ret > 0) {
ret = 0;
break;
}
} else {
wpa_hexdump(MSG_DEBUG, "WPA: Unrecognized EAPOL-Key "
"Key Data IE", pos, 2 + pos[1]);
}
}
return ret;
}
#endif // ESP_SUPPLICANT

View File

@@ -15,36 +15,6 @@
#ifndef WPA_IE_H
#define WPA_IE_H
struct wpa_eapol_ie_parse {
const u8 *wpa_ie;
size_t wpa_ie_len;
const u8 *rsn_ie;
size_t rsn_ie_len;
const u8 *pmkid;
const u8 *gtk;
size_t gtk_len;
const u8 *mac_addr;
size_t mac_addr_len;
#ifdef CONFIG_IEEE80211W
const u8 *igtk;
size_t igtk_len;
#endif /* CONFIG_IEEE80211W */
#ifdef CONFIG_IEEE80211R
const u8 *mdie;
size_t mdie_len;
const u8 *ftie;
size_t ftie_len;
const u8 *reassoc_deadline;
const u8 *key_lifetime;
#endif /* CONFIG_IEEE80211R */
const u8 *transition_disable;
size_t transition_disable_len;
const u8 *rsnxe;
size_t rsnxe_len;
};
int wpa_supplicant_parse_ies(const u8 *buf, size_t len,
struct wpa_eapol_ie_parse *ie);
int wpa_gen_wpa_ie(struct wpa_sm *sm, u8 *wpa_ie, size_t wpa_ie_len);
int wpa_gen_rsnxe(struct wpa_sm *sm, u8 *rsnxe, size_t rsnxe_len);
int wpa_parse_wpa_ie(const u8 *wpa_ie, size_t wpa_ie_len,

View File

@@ -129,6 +129,9 @@ void wifi_init_sta(void)
.threshold.authmode = ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD,
.sae_pwe_h2e = ESP_WIFI_SAE_MODE,
.sae_h2e_identifier = EXAMPLE_H2E_IDENTIFIER,
#ifdef CONFIG_ESP_WIFI_WPA3_COMPATIBLE_SUPPORT
.disable_wpa3_compatible_mode = 0,
#endif
},
};
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA) );