mirror of
https://github.com/espressif/esp-idf.git
synced 2025-10-02 18:10:57 +02:00
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:
@@ -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
|
||||
|
@@ -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;
|
||||
|
||||
/**
|
||||
|
Submodule components/esp_wifi/lib updated: 5bcb2be0dd...0e7080ea59
@@ -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()
|
||||
|
@@ -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);
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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_ */
|
||||
|
@@ -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 */
|
||||
|
||||
|
@@ -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;
|
||||
|
@@ -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);
|
||||
|
@@ -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 */
|
||||
|
@@ -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],
|
||||
|
@@ -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 */
|
||||
|
@@ -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,
|
||||
|
@@ -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;
|
||||
|
@@ -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);
|
||||
|
@@ -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;
|
||||
|
@@ -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);
|
||||
|
@@ -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)
|
||||
|
@@ -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 */
|
||||
|
@@ -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
|
||||
|
@@ -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 */
|
||||
|
@@ -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;
|
||||
|
@@ -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)
|
||||
|
@@ -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);
|
||||
|
@@ -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 */
|
||||
|
@@ -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
|
||||
|
@@ -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,
|
||||
|
@@ -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) );
|
||||
|
Reference in New Issue
Block a user