wpa: Import wpa_supplicant/hostapd commit f91680c15
This is the April update to vendor/wpa committed upstream 2021/04/07.
This commit is contained in:
parent
f8262d7d8a
commit
efec822389
@ -2332,6 +2332,22 @@ static int hostapd_dpp_controller_parse(struct hostapd_bss_config *bss,
|
|||||||
#endif /* CONFIG_DPP2 */
|
#endif /* CONFIG_DPP2 */
|
||||||
|
|
||||||
|
|
||||||
|
static int get_hex_config(u8 *buf, size_t max_len, int line,
|
||||||
|
const char *field, const char *val)
|
||||||
|
{
|
||||||
|
size_t hlen = os_strlen(val), len = hlen / 2;
|
||||||
|
u8 tmp[EXT_CAPA_MAX_LEN];
|
||||||
|
|
||||||
|
os_memset(tmp, 0, EXT_CAPA_MAX_LEN);
|
||||||
|
if (hlen & 1 || len > EXT_CAPA_MAX_LEN || hexstr2bin(val, tmp, len)) {
|
||||||
|
wpa_printf(MSG_ERROR, "Line %d: Invalid %s", line, field);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
os_memcpy(buf, tmp, EXT_CAPA_MAX_LEN);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int hostapd_config_fill(struct hostapd_config *conf,
|
static int hostapd_config_fill(struct hostapd_config *conf,
|
||||||
struct hostapd_bss_config *bss,
|
struct hostapd_bss_config *bss,
|
||||||
const char *buf, char *pos, int line)
|
const char *buf, char *pos, int line)
|
||||||
@ -2458,12 +2474,13 @@ static int hostapd_config_fill(struct hostapd_config *conf,
|
|||||||
bss->ieee802_1x = atoi(pos);
|
bss->ieee802_1x = atoi(pos);
|
||||||
} else if (os_strcmp(buf, "eapol_version") == 0) {
|
} else if (os_strcmp(buf, "eapol_version") == 0) {
|
||||||
int eapol_version = atoi(pos);
|
int eapol_version = atoi(pos);
|
||||||
|
|
||||||
#ifdef CONFIG_MACSEC
|
#ifdef CONFIG_MACSEC
|
||||||
if (eapol_version < 1 || eapol_version > 3) {
|
int max_ver = 3;
|
||||||
#else /* CONFIG_MACSEC */
|
#else /* CONFIG_MACSEC */
|
||||||
if (eapol_version < 1 || eapol_version > 2) {
|
int max_ver = 2;
|
||||||
#endif /* CONFIG_MACSEC */
|
#endif /* CONFIG_MACSEC */
|
||||||
|
|
||||||
|
if (eapol_version < 1 || eapol_version > max_ver) {
|
||||||
wpa_printf(MSG_ERROR,
|
wpa_printf(MSG_ERROR,
|
||||||
"Line %d: invalid EAPOL version (%d): '%s'.",
|
"Line %d: invalid EAPOL version (%d): '%s'.",
|
||||||
line, eapol_version, pos);
|
line, eapol_version, pos);
|
||||||
@ -4675,7 +4692,17 @@ static int hostapd_config_fill(struct hostapd_config *conf,
|
|||||||
line, pos);
|
line, pos);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
} else if (os_strcmp(buf, "pasn_comeback_after") == 0) {
|
||||||
|
bss->pasn_comeback_after = atoi(pos);
|
||||||
#endif /* CONFIG_PASN */
|
#endif /* CONFIG_PASN */
|
||||||
|
} else if (os_strcmp(buf, "ext_capa_mask") == 0) {
|
||||||
|
if (get_hex_config(bss->ext_capa_mask, EXT_CAPA_MAX_LEN,
|
||||||
|
line, "ext_capa_mask", pos))
|
||||||
|
return 1;
|
||||||
|
} else if (os_strcmp(buf, "ext_capa") == 0) {
|
||||||
|
if (get_hex_config(bss->ext_capa, EXT_CAPA_MAX_LEN,
|
||||||
|
line, "ext_capa", pos))
|
||||||
|
return 1;
|
||||||
} else {
|
} else {
|
||||||
wpa_printf(MSG_ERROR,
|
wpa_printf(MSG_ERROR,
|
||||||
"Line %d: unknown configuration item '%s'",
|
"Line %d: unknown configuration item '%s'",
|
||||||
|
@ -1469,6 +1469,8 @@ static int hostapd_ctrl_iface_set(struct hostapd_data *hapd, char *cmd)
|
|||||||
hapd->ext_mgmt_frame_handling = atoi(value);
|
hapd->ext_mgmt_frame_handling = atoi(value);
|
||||||
} else if (os_strcasecmp(cmd, "ext_eapol_frame_io") == 0) {
|
} else if (os_strcasecmp(cmd, "ext_eapol_frame_io") == 0) {
|
||||||
hapd->ext_eapol_frame_io = atoi(value);
|
hapd->ext_eapol_frame_io = atoi(value);
|
||||||
|
} else if (os_strcasecmp(cmd, "force_backlog_bytes") == 0) {
|
||||||
|
hapd->force_backlog_bytes = atoi(value);
|
||||||
#ifdef CONFIG_DPP
|
#ifdef CONFIG_DPP
|
||||||
} else if (os_strcasecmp(cmd, "dpp_config_obj_override") == 0) {
|
} else if (os_strcasecmp(cmd, "dpp_config_obj_override") == 0) {
|
||||||
os_free(hapd->dpp_config_obj_override);
|
os_free(hapd->dpp_config_obj_override);
|
||||||
@ -2562,6 +2564,34 @@ static int hostapd_ctrl_get_pmk(struct hostapd_data *hapd, const char *cmd,
|
|||||||
return wpa_snprintf_hex(buf, buflen, pmk, pmk_len);
|
return wpa_snprintf_hex(buf, buflen, pmk, pmk_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int hostapd_ctrl_register_frame(struct hostapd_data *hapd,
|
||||||
|
const char *cmd)
|
||||||
|
{
|
||||||
|
u16 type;
|
||||||
|
char *pos, *end;
|
||||||
|
u8 match[10];
|
||||||
|
size_t match_len;
|
||||||
|
bool multicast = false;
|
||||||
|
|
||||||
|
type = strtol(cmd, &pos, 16);
|
||||||
|
if (*pos != ' ')
|
||||||
|
return -1;
|
||||||
|
pos++;
|
||||||
|
end = os_strchr(pos, ' ');
|
||||||
|
if (end) {
|
||||||
|
match_len = end - pos;
|
||||||
|
multicast = os_strstr(end, "multicast") != NULL;
|
||||||
|
} else {
|
||||||
|
match_len = os_strlen(pos) / 2;
|
||||||
|
}
|
||||||
|
if (hexstr2bin(pos, match, match_len))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return hostapd_drv_register_frame(hapd, type, match, match_len,
|
||||||
|
multicast);
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* CONFIG_TESTING_OPTIONS */
|
#endif /* CONFIG_TESTING_OPTIONS */
|
||||||
|
|
||||||
|
|
||||||
@ -3646,6 +3676,9 @@ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
|
|||||||
} else if (os_strncmp(buf, "GET_PMK ", 8) == 0) {
|
} else if (os_strncmp(buf, "GET_PMK ", 8) == 0) {
|
||||||
reply_len = hostapd_ctrl_get_pmk(hapd, buf + 8, reply,
|
reply_len = hostapd_ctrl_get_pmk(hapd, buf + 8, reply,
|
||||||
reply_size);
|
reply_size);
|
||||||
|
} else if (os_strncmp(buf, "REGISTER_FRAME ", 15) == 0) {
|
||||||
|
if (hostapd_ctrl_register_frame(hapd, buf + 16) < 0)
|
||||||
|
reply_len = -1;
|
||||||
#endif /* CONFIG_TESTING_OPTIONS */
|
#endif /* CONFIG_TESTING_OPTIONS */
|
||||||
} else if (os_strncmp(buf, "CHAN_SWITCH ", 12) == 0) {
|
} else if (os_strncmp(buf, "CHAN_SWITCH ", 12) == 0) {
|
||||||
if (hostapd_ctrl_iface_chan_switch(hapd->iface, buf + 12))
|
if (hostapd_ctrl_iface_chan_switch(hapd->iface, buf + 12))
|
||||||
|
@ -877,18 +877,31 @@ wmm_ac_vo_acm=0
|
|||||||
#he_mu_edca_ac_vo_timer=255
|
#he_mu_edca_ac_vo_timer=255
|
||||||
|
|
||||||
# Spatial Reuse Parameter Set
|
# Spatial Reuse Parameter Set
|
||||||
|
#
|
||||||
|
# SR Control field value
|
||||||
|
# B0 = PSR Disallowed
|
||||||
|
# B1 = Non-SRG OBSS PD SR Disallowed
|
||||||
|
# B2 = Non-SRG Offset Present
|
||||||
|
# B3 = SRG Information Present
|
||||||
|
# B4 = HESIGA_Spatial_reuse_value15_allowed
|
||||||
#he_spr_sr_control
|
#he_spr_sr_control
|
||||||
|
#
|
||||||
|
# Non-SRG OBSS PD Max Offset (included if he_spr_sr_control B2=1)
|
||||||
#he_spr_non_srg_obss_pd_max_offset
|
#he_spr_non_srg_obss_pd_max_offset
|
||||||
|
|
||||||
|
# SRG OBSS PD Min Offset (included if he_spr_sr_control B3=1)
|
||||||
#he_spr_srg_obss_pd_min_offset
|
#he_spr_srg_obss_pd_min_offset
|
||||||
|
#
|
||||||
|
# SRG OBSS PD Max Offset (included if he_spr_sr_control B3=1)
|
||||||
#he_spr_srg_obss_pd_max_offset
|
#he_spr_srg_obss_pd_max_offset
|
||||||
#
|
#
|
||||||
# SPR SRG BSS Color
|
# SPR SRG BSS Color (included if he_spr_sr_control B3=1)
|
||||||
# This config represents SRG BSS Color Bitmap field of Spatial Reuse Parameter
|
# This config represents SRG BSS Color Bitmap field of Spatial Reuse Parameter
|
||||||
# Set element that indicates the BSS color values used by members of the
|
# Set element that indicates the BSS color values used by members of the
|
||||||
# SRG of which the transmitting STA is a member. The value is in range of 0-63.
|
# SRG of which the transmitting STA is a member. The value is in range of 0-63.
|
||||||
#he_spr_srg_bss_colors=1 2 10 63
|
#he_spr_srg_bss_colors=1 2 10 63
|
||||||
#
|
#
|
||||||
# SPR SRG Partial BSSID
|
# SPR SRG Partial BSSID (included if he_spr_sr_control B3=1)
|
||||||
# This config represents SRG Partial BSSID Bitmap field of Spatial Reuse
|
# This config represents SRG Partial BSSID Bitmap field of Spatial Reuse
|
||||||
# Parameter Set element that indicates the Partial BSSID values used by members
|
# Parameter Set element that indicates the Partial BSSID values used by members
|
||||||
# of the SRG of which the transmitting STA is a member. The value range
|
# of the SRG of which the transmitting STA is a member. The value range
|
||||||
@ -2038,6 +2051,13 @@ own_ip_addr=127.0.0.1
|
|||||||
# http://www.iana.org/assignments/ipsec-registry/ipsec-registry.xml#ipsec-registry-10
|
# http://www.iana.org/assignments/ipsec-registry/ipsec-registry.xml#ipsec-registry-10
|
||||||
#pasn_groups=19 20 21
|
#pasn_groups=19 20 21
|
||||||
|
|
||||||
|
# PASN comeback after time in TUs
|
||||||
|
# In case the AP is temporarily unable to handle a PASN authentication exchange
|
||||||
|
# due to a too large number of parallel operations, this value indicates to the
|
||||||
|
# peer after how many TUs it can try the PASN exchange again.
|
||||||
|
# (default: 10 TUs)
|
||||||
|
#pasn_comeback_after=10
|
||||||
|
|
||||||
##### IEEE 802.11r configuration ##############################################
|
##### IEEE 802.11r configuration ##############################################
|
||||||
|
|
||||||
# Mobility Domain identifier (dot11FTMobilityDomainID, MDID)
|
# Mobility Domain identifier (dot11FTMobilityDomainID, MDID)
|
||||||
|
@ -79,6 +79,10 @@ static void count_backlogged_sta(struct hostapd_data *hapd)
|
|||||||
for (sta = hapd->sta_list; sta; sta = sta->next) {
|
for (sta = hapd->sta_list; sta; sta = sta->next) {
|
||||||
if (hostapd_drv_read_sta_data(hapd, &data, sta->addr))
|
if (hostapd_drv_read_sta_data(hapd, &data, sta->addr))
|
||||||
continue;
|
continue;
|
||||||
|
#ifdef CONFIG_TESTING_OPTIONS
|
||||||
|
if (hapd->force_backlog_bytes)
|
||||||
|
data.backlog_bytes = 1;
|
||||||
|
#endif /* CONFIG_TESTING_OPTIONS */
|
||||||
|
|
||||||
if (data.backlog_bytes > 0)
|
if (data.backlog_bytes > 0)
|
||||||
set_new_backlog_time(hapd, sta, &now);
|
set_new_backlog_time(hapd, sta, &now);
|
||||||
|
@ -165,6 +165,11 @@ void hostapd_config_defaults_bss(struct hostapd_bss_config *bss)
|
|||||||
#ifdef CONFIG_TESTING_OPTIONS
|
#ifdef CONFIG_TESTING_OPTIONS
|
||||||
bss->sae_commit_status = -1;
|
bss->sae_commit_status = -1;
|
||||||
#endif /* CONFIG_TESTING_OPTIONS */
|
#endif /* CONFIG_TESTING_OPTIONS */
|
||||||
|
|
||||||
|
#ifdef CONFIG_PASN
|
||||||
|
/* comeback after 10 TUs */
|
||||||
|
bss->pasn_comeback_after = 10;
|
||||||
|
#endif /* CONFIG_PASN */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -267,6 +267,8 @@ struct airtime_sta_weight {
|
|||||||
u8 addr[ETH_ALEN];
|
u8 addr[ETH_ALEN];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define EXT_CAPA_MAX_LEN 15
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct hostapd_bss_config - Per-BSS configuration
|
* struct hostapd_bss_config - Per-BSS configuration
|
||||||
*/
|
*/
|
||||||
@ -880,9 +882,18 @@ struct hostapd_bss_config {
|
|||||||
#endif /* CONFIG_TESTING_OPTIONS */
|
#endif /* CONFIG_TESTING_OPTIONS */
|
||||||
|
|
||||||
int *pasn_groups;
|
int *pasn_groups;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The time in TUs after which the non-AP STA is requested to retry the
|
||||||
|
* PASN authentication in case there are too many parallel operations.
|
||||||
|
*/
|
||||||
|
u16 pasn_comeback_after;
|
||||||
#endif /* CONFIG_PASN */
|
#endif /* CONFIG_PASN */
|
||||||
|
|
||||||
unsigned int unsol_bcast_probe_resp_interval;
|
unsigned int unsol_bcast_probe_resp_interval;
|
||||||
|
|
||||||
|
u8 ext_capa_mask[EXT_CAPA_MAX_LEN];
|
||||||
|
u8 ext_capa[EXT_CAPA_MAX_LEN];
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -403,4 +403,17 @@ static inline int hostapd_drv_driver_cmd(struct hostapd_data *hapd,
|
|||||||
}
|
}
|
||||||
#endif /* ANDROID */
|
#endif /* ANDROID */
|
||||||
|
|
||||||
|
#ifdef CONFIG_TESTING_OPTIONS
|
||||||
|
static inline int
|
||||||
|
hostapd_drv_register_frame(struct hostapd_data *hapd, u16 type,
|
||||||
|
const u8 *match, size_t match_len,
|
||||||
|
bool multicast)
|
||||||
|
{
|
||||||
|
if (!hapd->driver || !hapd->drv_priv || !hapd->driver->register_frame)
|
||||||
|
return -1;
|
||||||
|
return hapd->driver->register_frame(hapd->drv_priv, type, match,
|
||||||
|
match_len, multicast);
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_TESTING_OPTIONS */
|
||||||
|
|
||||||
#endif /* AP_DRV_OPS */
|
#endif /* AP_DRV_OPS */
|
||||||
|
@ -915,7 +915,8 @@ static void hostapd_dpp_gas_resp_cb(void *ctx, const u8 *addr, u8 dialog_token,
|
|||||||
wpa_printf(MSG_DEBUG, "DPP: No matching exchange in progress");
|
wpa_printf(MSG_DEBUG, "DPP: No matching exchange in progress");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!resp || status_code != WLAN_STATUS_SUCCESS) {
|
if (result != GAS_QUERY_AP_SUCCESS ||
|
||||||
|
!resp || status_code != WLAN_STATUS_SUCCESS) {
|
||||||
wpa_printf(MSG_DEBUG, "DPP: GAS query did not succeed");
|
wpa_printf(MSG_DEBUG, "DPP: GAS query did not succeed");
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
@ -1189,6 +1190,7 @@ static void hostapd_dpp_rx_conf_result(struct hostapd_data *hapd, const u8 *src,
|
|||||||
wpa_printf(MSG_DEBUG, "DPP: Wait for Connection Status Result");
|
wpa_printf(MSG_DEBUG, "DPP: Wait for Connection Status Result");
|
||||||
eloop_cancel_timeout(hostapd_dpp_config_result_wait_timeout,
|
eloop_cancel_timeout(hostapd_dpp_config_result_wait_timeout,
|
||||||
hapd, NULL);
|
hapd, NULL);
|
||||||
|
auth->waiting_conn_status_result = 1;
|
||||||
eloop_cancel_timeout(
|
eloop_cancel_timeout(
|
||||||
hostapd_dpp_conn_status_result_wait_timeout,
|
hostapd_dpp_conn_status_result_wait_timeout,
|
||||||
hapd, NULL);
|
hapd, NULL);
|
||||||
@ -1981,6 +1983,19 @@ hostapd_dpp_gas_req_handler(struct hostapd_data *hapd, const u8 *sa,
|
|||||||
wpa_printf(MSG_DEBUG, "DPP: No matching exchange in progress");
|
wpa_printf(MSG_DEBUG, "DPP: No matching exchange in progress");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (hapd->dpp_auth_ok_on_ack && auth->configurator) {
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"DPP: Have not received ACK for Auth Confirm yet - assume it was received based on this GAS request");
|
||||||
|
/* hostapd_dpp_auth_success() would normally have been called
|
||||||
|
* from TX status handler, but since there was no such handler
|
||||||
|
* call yet, simply send out the event message and proceed with
|
||||||
|
* exchange. */
|
||||||
|
wpa_msg(hapd->msg_ctx, MSG_INFO,
|
||||||
|
DPP_EVENT_AUTH_SUCCESS "init=1");
|
||||||
|
hapd->dpp_auth_ok_on_ack = 0;
|
||||||
|
}
|
||||||
|
|
||||||
wpa_hexdump(MSG_DEBUG,
|
wpa_hexdump(MSG_DEBUG,
|
||||||
"DPP: Received Configuration Request (GAS Query Request)",
|
"DPP: Received Configuration Request (GAS Query Request)",
|
||||||
query, query_len);
|
query, query_len);
|
||||||
|
@ -459,8 +459,8 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
|
|||||||
if (hapd->conf->sae_pwe == 2 &&
|
if (hapd->conf->sae_pwe == 2 &&
|
||||||
sta->auth_alg == WLAN_AUTH_SAE &&
|
sta->auth_alg == WLAN_AUTH_SAE &&
|
||||||
sta->sae && !sta->sae->h2e &&
|
sta->sae && !sta->sae->h2e &&
|
||||||
elems.rsnxe && elems.rsnxe_len >= 1 &&
|
ieee802_11_rsnx_capab_len(elems.rsnxe, elems.rsnxe_len,
|
||||||
(elems.rsnxe[0] & BIT(WLAN_RSNX_CAPAB_SAE_H2E))) {
|
WLAN_RSNX_CAPAB_SAE_H2E)) {
|
||||||
wpa_printf(MSG_INFO, "SAE: " MACSTR
|
wpa_printf(MSG_INFO, "SAE: " MACSTR
|
||||||
" indicates support for SAE H2E, but did not use it",
|
" indicates support for SAE H2E, but did not use it",
|
||||||
MAC2STR(sta->addr));
|
MAC2STR(sta->addr));
|
||||||
|
@ -107,7 +107,8 @@ static void hostapd_reload_bss(struct hostapd_data *hapd)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
if (hapd->conf->wmm_enabled < 0)
|
if (hapd->conf->wmm_enabled < 0)
|
||||||
hapd->conf->wmm_enabled = hapd->iconf->ieee80211n;
|
hapd->conf->wmm_enabled = hapd->iconf->ieee80211n |
|
||||||
|
hapd->iconf->ieee80211ax;
|
||||||
|
|
||||||
#ifndef CONFIG_NO_RADIUS
|
#ifndef CONFIG_NO_RADIUS
|
||||||
radius_client_reconfig(hapd->radius, hapd->conf->radius);
|
radius_client_reconfig(hapd->radius, hapd->conf->radius);
|
||||||
@ -1173,7 +1174,8 @@ static int hostapd_setup_bss(struct hostapd_data *hapd, int first)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (conf->wmm_enabled < 0)
|
if (conf->wmm_enabled < 0)
|
||||||
conf->wmm_enabled = hapd->iconf->ieee80211n;
|
conf->wmm_enabled = hapd->iconf->ieee80211n |
|
||||||
|
hapd->iconf->ieee80211ax;
|
||||||
|
|
||||||
#ifdef CONFIG_IEEE80211R_AP
|
#ifdef CONFIG_IEEE80211R_AP
|
||||||
if (is_zero_ether_addr(conf->r1_key_holder))
|
if (is_zero_ether_addr(conf->r1_key_holder))
|
||||||
|
@ -354,6 +354,8 @@ struct hostapd_data {
|
|||||||
int last_bigtk_key_idx;
|
int last_bigtk_key_idx;
|
||||||
u8 last_bigtk[WPA_BIGTK_MAX_LEN];
|
u8 last_bigtk[WPA_BIGTK_MAX_LEN];
|
||||||
size_t last_bigtk_len;
|
size_t last_bigtk_len;
|
||||||
|
|
||||||
|
bool force_backlog_bytes;
|
||||||
#endif /* CONFIG_TESTING_OPTIONS */
|
#endif /* CONFIG_TESTING_OPTIONS */
|
||||||
|
|
||||||
#ifdef CONFIG_MBO
|
#ifdef CONFIG_MBO
|
||||||
|
@ -572,7 +572,7 @@ static struct wpabuf * auth_build_sae_commit(struct hostapd_data *hapd,
|
|||||||
|
|
||||||
if (update && !use_pt &&
|
if (update && !use_pt &&
|
||||||
sae_prepare_commit(hapd->own_addr, sta->addr,
|
sae_prepare_commit(hapd->own_addr, sta->addr,
|
||||||
(u8 *) password, os_strlen(password), rx_id,
|
(u8 *) password, os_strlen(password),
|
||||||
sta->sae) < 0) {
|
sta->sae) < 0) {
|
||||||
wpa_printf(MSG_DEBUG, "SAE: Could not pick PWE");
|
wpa_printf(MSG_DEBUG, "SAE: Could not pick PWE");
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -702,13 +702,15 @@ static int use_anti_clogging(struct hostapd_data *hapd)
|
|||||||
|
|
||||||
for (sta = hapd->sta_list; sta; sta = sta->next) {
|
for (sta = hapd->sta_list; sta; sta = sta->next) {
|
||||||
#ifdef CONFIG_SAE
|
#ifdef CONFIG_SAE
|
||||||
if (!sta->sae)
|
if (sta->sae &&
|
||||||
continue;
|
(sta->sae->state == SAE_COMMITTED ||
|
||||||
if (sta->sae->state != SAE_COMMITTED &&
|
sta->sae->state == SAE_CONFIRMED))
|
||||||
sta->sae->state != SAE_CONFIRMED)
|
|
||||||
continue;
|
|
||||||
open++;
|
open++;
|
||||||
#endif /* CONFIG_SAE */
|
#endif /* CONFIG_SAE */
|
||||||
|
#ifdef CONFIG_PASN
|
||||||
|
if (sta->pasn && sta->pasn->ecdh)
|
||||||
|
open++;
|
||||||
|
#endif /* CONFIG_PASN */
|
||||||
if (open >= hapd->conf->anti_clogging_threshold)
|
if (open >= hapd->conf->anti_clogging_threshold)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -806,6 +808,7 @@ static struct wpabuf * auth_build_token_req(struct hostapd_data *hapd,
|
|||||||
if (buf == NULL)
|
if (buf == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
if (group)
|
||||||
wpabuf_put_le16(buf, group); /* Finite Cyclic Group */
|
wpabuf_put_le16(buf, group); /* Finite Cyclic Group */
|
||||||
|
|
||||||
if (h2e) {
|
if (h2e) {
|
||||||
@ -2380,11 +2383,12 @@ static int pasn_wd_handle_sae_commit(struct hostapd_data *hapd,
|
|||||||
struct wpabuf *wd)
|
struct wpabuf *wd)
|
||||||
{
|
{
|
||||||
struct pasn_data *pasn = sta->pasn;
|
struct pasn_data *pasn = sta->pasn;
|
||||||
const char *password = NULL;
|
const char *password;
|
||||||
const u8 *data;
|
const u8 *data;
|
||||||
size_t buf_len;
|
size_t buf_len;
|
||||||
u16 res, alg, seq, status;
|
u16 res, alg, seq, status;
|
||||||
int groups[] = { pasn->group, 0 };
|
int groups[] = { pasn->group, 0 };
|
||||||
|
struct sae_pt *pt = NULL;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (!wd)
|
if (!wd)
|
||||||
@ -2406,8 +2410,8 @@ static int pasn_wd_handle_sae_commit(struct hostapd_data *hapd,
|
|||||||
wpa_printf(MSG_DEBUG, "PASN: SAE commit: alg=%u, seq=%u, status=%u",
|
wpa_printf(MSG_DEBUG, "PASN: SAE commit: alg=%u, seq=%u, status=%u",
|
||||||
alg, seq, status);
|
alg, seq, status);
|
||||||
|
|
||||||
/* TODO: SAE H2E */
|
if (alg != WLAN_AUTH_SAE || seq != 1 ||
|
||||||
if (alg != WLAN_AUTH_SAE || seq != 1 || status != WLAN_STATUS_SUCCESS) {
|
status != WLAN_STATUS_SAE_HASH_TO_ELEMENT) {
|
||||||
wpa_printf(MSG_DEBUG, "PASN: Dropping peer SAE commit");
|
wpa_printf(MSG_DEBUG, "PASN: Dropping peer SAE commit");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -2421,15 +2425,14 @@ static int pasn_wd_handle_sae_commit(struct hostapd_data *hapd,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
password = sae_get_password(hapd, sta, NULL, NULL, NULL, NULL);
|
password = sae_get_password(hapd, sta, NULL, NULL, &pt, NULL);
|
||||||
if (!password) {
|
if (!password || !pt) {
|
||||||
wpa_printf(MSG_DEBUG, "PASN: No SAE password found");
|
wpa_printf(MSG_DEBUG, "PASN: No SAE PT found");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = sae_prepare_commit(hapd->own_addr, sta->addr,
|
ret = sae_prepare_commit_pt(&pasn->sae, pt, hapd->own_addr, sta->addr,
|
||||||
(const u8 *) password, os_strlen(password), 0,
|
NULL, NULL);
|
||||||
&pasn->sae);
|
|
||||||
if (ret) {
|
if (ret) {
|
||||||
wpa_printf(MSG_DEBUG, "PASN: Failed to prepare SAE commit");
|
wpa_printf(MSG_DEBUG, "PASN: Failed to prepare SAE commit");
|
||||||
return -1;
|
return -1;
|
||||||
@ -2526,7 +2529,7 @@ static struct wpabuf * pasn_get_sae_wd(struct hostapd_data *hapd,
|
|||||||
len_ptr = wpabuf_put(buf, 2);
|
len_ptr = wpabuf_put(buf, 2);
|
||||||
wpabuf_put_le16(buf, WLAN_AUTH_SAE);
|
wpabuf_put_le16(buf, WLAN_AUTH_SAE);
|
||||||
wpabuf_put_le16(buf, 1);
|
wpabuf_put_le16(buf, 1);
|
||||||
wpabuf_put_le16(buf, WLAN_STATUS_SUCCESS);
|
wpabuf_put_le16(buf, WLAN_STATUS_SAE_HASH_TO_ELEMENT);
|
||||||
|
|
||||||
/* Write the actual commit and update the length accordingly */
|
/* Write the actual commit and update the length accordingly */
|
||||||
sae_write_commit(&pasn->sae, buf, NULL, 0);
|
sae_write_commit(&pasn->sae, buf, NULL, 0);
|
||||||
@ -2643,7 +2646,7 @@ static void pasn_fils_auth_resp(struct hostapd_data *hapd,
|
|||||||
wpabuf_head(pasn->secret),
|
wpabuf_head(pasn->secret),
|
||||||
wpabuf_len(pasn->secret),
|
wpabuf_len(pasn->secret),
|
||||||
&sta->pasn->ptk, sta->pasn->akmp,
|
&sta->pasn->ptk, sta->pasn->akmp,
|
||||||
sta->pasn->cipher, WPA_KDK_MAX_LEN);
|
sta->pasn->cipher, sta->pasn->kdk_len);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
wpa_printf(MSG_DEBUG, "PASN: FILS: Failed to derive PTK");
|
wpa_printf(MSG_DEBUG, "PASN: FILS: Failed to derive PTK");
|
||||||
goto fail;
|
goto fail;
|
||||||
@ -2880,7 +2883,7 @@ pasn_derive_keys(struct hostapd_data *hapd, struct sta_info *sta,
|
|||||||
ret = pasn_pmk_to_ptk(pmk, pmk_len, sta->addr, hapd->own_addr,
|
ret = pasn_pmk_to_ptk(pmk, pmk_len, sta->addr, hapd->own_addr,
|
||||||
wpabuf_head(secret), wpabuf_len(secret),
|
wpabuf_head(secret), wpabuf_len(secret),
|
||||||
&sta->pasn->ptk, sta->pasn->akmp,
|
&sta->pasn->ptk, sta->pasn->akmp,
|
||||||
sta->pasn->cipher, WPA_KDK_MAX_LEN);
|
sta->pasn->cipher, sta->pasn->kdk_len);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
wpa_printf(MSG_DEBUG, "PASN: Failed to derive PTK");
|
wpa_printf(MSG_DEBUG, "PASN: Failed to derive PTK");
|
||||||
return -1;
|
return -1;
|
||||||
@ -2891,6 +2894,54 @@ pasn_derive_keys(struct hostapd_data *hapd, struct sta_info *sta,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void handle_auth_pasn_comeback(struct hostapd_data *hapd,
|
||||||
|
struct sta_info *sta, u16 group)
|
||||||
|
{
|
||||||
|
struct wpabuf *buf, *comeback;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"PASN: Building comeback frame 2. Comeback after=%u",
|
||||||
|
hapd->conf->pasn_comeback_after);
|
||||||
|
|
||||||
|
buf = wpabuf_alloc(1500);
|
||||||
|
if (!buf)
|
||||||
|
return;
|
||||||
|
|
||||||
|
wpa_pasn_build_auth_header(buf, hapd->own_addr, hapd->own_addr,
|
||||||
|
sta->addr, 2,
|
||||||
|
WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Do not include the group as a part of the token since it is not going
|
||||||
|
* to be used.
|
||||||
|
*/
|
||||||
|
comeback = auth_build_token_req(hapd, 0, sta->addr, 0);
|
||||||
|
if (!comeback) {
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"PASN: Failed sending auth with comeback");
|
||||||
|
wpabuf_free(buf);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
wpa_pasn_add_parameter_ie(buf, group,
|
||||||
|
WPA_PASN_WRAPPED_DATA_NO,
|
||||||
|
NULL, 0, comeback,
|
||||||
|
hapd->conf->pasn_comeback_after);
|
||||||
|
wpabuf_free(comeback);
|
||||||
|
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"PASN: comeback: STA=" MACSTR, MAC2STR(sta->addr));
|
||||||
|
|
||||||
|
ret = hostapd_drv_send_mlme(hapd, wpabuf_head(buf), wpabuf_len(buf), 0,
|
||||||
|
NULL, 0, 0);
|
||||||
|
if (ret)
|
||||||
|
wpa_printf(MSG_INFO, "PASN: Failed to send comeback frame 2");
|
||||||
|
|
||||||
|
wpabuf_free(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int handle_auth_pasn_resp(struct hostapd_data *hapd,
|
static int handle_auth_pasn_resp(struct hostapd_data *hapd,
|
||||||
struct sta_info *sta,
|
struct sta_info *sta,
|
||||||
struct rsn_pmksa_cache_entry *pmksa,
|
struct rsn_pmksa_cache_entry *pmksa,
|
||||||
@ -3100,6 +3151,15 @@ static void handle_auth_pasn_1(struct hostapd_data *hapd, struct sta_info *sta,
|
|||||||
sta->pasn->akmp = rsn_data.key_mgmt;
|
sta->pasn->akmp = rsn_data.key_mgmt;
|
||||||
sta->pasn->cipher = rsn_data.pairwise_cipher;
|
sta->pasn->cipher = rsn_data.pairwise_cipher;
|
||||||
|
|
||||||
|
if (hapd->conf->force_kdk_derivation ||
|
||||||
|
((hapd->iface->drv_flags2 & WPA_DRIVER_FLAGS2_SEC_LTF) &&
|
||||||
|
ieee802_11_rsnx_capab_len(elems.rsnxe, elems.rsnxe_len,
|
||||||
|
WLAN_RSNX_CAPAB_SECURE_LTF)))
|
||||||
|
sta->pasn->kdk_len = WPA_KDK_MAX_LEN;
|
||||||
|
else
|
||||||
|
sta->pasn->kdk_len = 0;
|
||||||
|
wpa_printf(MSG_DEBUG, "PASN: kdk_len=%zu", sta->pasn->kdk_len);
|
||||||
|
|
||||||
if (!elems.pasn_params || !elems.pasn_params_len) {
|
if (!elems.pasn_params || !elems.pasn_params_len) {
|
||||||
wpa_printf(MSG_DEBUG,
|
wpa_printf(MSG_DEBUG,
|
||||||
"PASN: No PASN Parameters element found");
|
"PASN: No PASN Parameters element found");
|
||||||
@ -3133,6 +3193,25 @@ static void handle_auth_pasn_1(struct hostapd_data *hapd, struct sta_info *sta,
|
|||||||
goto send_resp;
|
goto send_resp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (pasn_params.comeback) {
|
||||||
|
wpa_printf(MSG_DEBUG, "PASN: Checking peer comeback token");
|
||||||
|
|
||||||
|
ret = check_comeback_token(hapd, sta->addr,
|
||||||
|
pasn_params.comeback,
|
||||||
|
pasn_params.comeback_len);
|
||||||
|
|
||||||
|
if (ret) {
|
||||||
|
wpa_printf(MSG_DEBUG, "PASN: Invalid comeback token");
|
||||||
|
status = WLAN_STATUS_UNSPECIFIED_FAILURE;
|
||||||
|
goto send_resp;
|
||||||
|
}
|
||||||
|
} else if (use_anti_clogging(hapd)) {
|
||||||
|
wpa_printf(MSG_DEBUG, "PASN: Respond with comeback");
|
||||||
|
handle_auth_pasn_comeback(hapd, sta, pasn_params.group);
|
||||||
|
ap_free_sta(hapd, sta);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
sta->pasn->ecdh = crypto_ecdh_init(pasn_params.group);
|
sta->pasn->ecdh = crypto_ecdh_init(pasn_params.group);
|
||||||
if (!sta->pasn->ecdh) {
|
if (!sta->pasn->ecdh) {
|
||||||
wpa_printf(MSG_DEBUG, "PASN: Failed to init ECDH");
|
wpa_printf(MSG_DEBUG, "PASN: Failed to init ECDH");
|
||||||
@ -4614,8 +4693,8 @@ static int check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta,
|
|||||||
if (hapd->conf->sae_pwe == 2 &&
|
if (hapd->conf->sae_pwe == 2 &&
|
||||||
sta->auth_alg == WLAN_AUTH_SAE &&
|
sta->auth_alg == WLAN_AUTH_SAE &&
|
||||||
sta->sae && !sta->sae->h2e &&
|
sta->sae && !sta->sae->h2e &&
|
||||||
elems.rsnxe && elems.rsnxe_len >= 1 &&
|
ieee802_11_rsnx_capab_len(elems.rsnxe, elems.rsnxe_len,
|
||||||
(elems.rsnxe[0] & BIT(WLAN_RSNX_CAPAB_SAE_H2E))) {
|
WLAN_RSNX_CAPAB_SAE_H2E)) {
|
||||||
wpa_printf(MSG_INFO, "SAE: " MACSTR
|
wpa_printf(MSG_INFO, "SAE: " MACSTR
|
||||||
" indicates support for SAE H2E, but did not use it",
|
" indicates support for SAE H2E, but did not use it",
|
||||||
MAC2STR(sta->addr));
|
MAC2STR(sta->addr));
|
||||||
|
@ -451,70 +451,10 @@ static void hostapd_ext_capab_byte(struct hostapd_data *hapd, u8 *pos, int idx)
|
|||||||
u8 * hostapd_eid_ext_capab(struct hostapd_data *hapd, u8 *eid)
|
u8 * hostapd_eid_ext_capab(struct hostapd_data *hapd, u8 *eid)
|
||||||
{
|
{
|
||||||
u8 *pos = eid;
|
u8 *pos = eid;
|
||||||
u8 len = 0, i;
|
u8 len = EXT_CAPA_MAX_LEN, i;
|
||||||
|
|
||||||
if (hapd->conf->qos_map_set_len ||
|
|
||||||
(hapd->conf->tdls & (TDLS_PROHIBIT | TDLS_PROHIBIT_CHAN_SWITCH)))
|
|
||||||
len = 5;
|
|
||||||
if (len < 4 &&
|
|
||||||
(hapd->conf->time_advertisement == 2 || hapd->conf->interworking))
|
|
||||||
len = 4;
|
|
||||||
if (len < 3 &&
|
|
||||||
(hapd->conf->wnm_sleep_mode || hapd->conf->bss_transition))
|
|
||||||
len = 3;
|
|
||||||
if (len < 1 &&
|
|
||||||
(hapd->iconf->obss_interval ||
|
|
||||||
(hapd->iface->drv_flags & WPA_DRIVER_FLAGS_AP_CSA)))
|
|
||||||
len = 1;
|
|
||||||
if (len < 2 &&
|
|
||||||
(hapd->conf->proxy_arp || hapd->conf->coloc_intf_reporting))
|
|
||||||
len = 2;
|
|
||||||
if (len < 7 && hapd->conf->ssid.utf8_ssid)
|
|
||||||
len = 7;
|
|
||||||
if (len < 9 &&
|
|
||||||
(hapd->conf->ftm_initiator || hapd->conf->ftm_responder))
|
|
||||||
len = 9;
|
|
||||||
#ifdef CONFIG_WNM_AP
|
|
||||||
if (len < 4)
|
|
||||||
len = 4;
|
|
||||||
#endif /* CONFIG_WNM_AP */
|
|
||||||
#ifdef CONFIG_HS20
|
|
||||||
if (hapd->conf->hs20 && len < 6)
|
|
||||||
len = 6;
|
|
||||||
#endif /* CONFIG_HS20 */
|
|
||||||
#ifdef CONFIG_MBO
|
|
||||||
if (hapd->conf->mbo_enabled && len < 6)
|
|
||||||
len = 6;
|
|
||||||
#endif /* CONFIG_MBO */
|
|
||||||
#ifdef CONFIG_FILS
|
|
||||||
if ((!(hapd->conf->wpa & WPA_PROTO_RSN) ||
|
|
||||||
!wpa_key_mgmt_fils(hapd->conf->wpa_key_mgmt)) && len < 10)
|
|
||||||
len = 10;
|
|
||||||
#endif /* CONFIG_FILS */
|
|
||||||
#ifdef CONFIG_IEEE80211AX
|
|
||||||
if (len < 10 && hapd->iconf->ieee80211ax &&
|
|
||||||
hostapd_get_he_twt_responder(hapd, IEEE80211_MODE_AP))
|
|
||||||
len = 10;
|
|
||||||
#endif /* CONFIG_IEEE80211AX */
|
|
||||||
#ifdef CONFIG_SAE
|
|
||||||
if (len < 11 && hapd->conf->wpa &&
|
|
||||||
wpa_key_mgmt_sae(hapd->conf->wpa_key_mgmt) &&
|
|
||||||
hostapd_sae_pw_id_in_use(hapd->conf))
|
|
||||||
len = 11;
|
|
||||||
#endif /* CONFIG_SAE */
|
|
||||||
if (len < 11 && hapd->conf->beacon_prot &&
|
|
||||||
(hapd->iface->drv_flags & WPA_DRIVER_FLAGS_BEACON_PROTECTION))
|
|
||||||
len = 11;
|
|
||||||
#ifdef CONFIG_SAE_PK
|
|
||||||
if (len < 12 && hapd->conf->wpa &&
|
|
||||||
wpa_key_mgmt_sae(hapd->conf->wpa_key_mgmt) &&
|
|
||||||
hostapd_sae_pk_exclusively(hapd->conf))
|
|
||||||
len = 12;
|
|
||||||
#endif /* CONFIG_SAE_PK */
|
|
||||||
if (len < hapd->iface->extended_capa_len)
|
if (len < hapd->iface->extended_capa_len)
|
||||||
len = hapd->iface->extended_capa_len;
|
len = hapd->iface->extended_capa_len;
|
||||||
if (len == 0)
|
|
||||||
return eid;
|
|
||||||
|
|
||||||
*pos++ = WLAN_EID_EXT_CAPAB;
|
*pos++ = WLAN_EID_EXT_CAPAB;
|
||||||
*pos++ = len;
|
*pos++ = len;
|
||||||
@ -525,6 +465,11 @@ u8 * hostapd_eid_ext_capab(struct hostapd_data *hapd, u8 *eid)
|
|||||||
*pos &= ~hapd->iface->extended_capa_mask[i];
|
*pos &= ~hapd->iface->extended_capa_mask[i];
|
||||||
*pos |= hapd->iface->extended_capa[i];
|
*pos |= hapd->iface->extended_capa[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (i < EXT_CAPA_MAX_LEN) {
|
||||||
|
*pos &= ~hapd->conf->ext_capa_mask[i];
|
||||||
|
*pos |= hapd->conf->ext_capa[i];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
while (len > 0 && eid[1 + len] == 0) {
|
while (len > 0 && eid[1 + len] == 0) {
|
||||||
|
@ -88,6 +88,7 @@ struct pasn_data {
|
|||||||
u16 group;
|
u16 group;
|
||||||
u8 trans_seq;
|
u8 trans_seq;
|
||||||
u8 wrapped_data_format;
|
u8 wrapped_data_format;
|
||||||
|
size_t kdk_len;
|
||||||
|
|
||||||
u8 hash[SHA384_MAC_LEN];
|
u8 hash[SHA384_MAC_LEN];
|
||||||
struct wpa_ptk ptk;
|
struct wpa_ptk ptk;
|
||||||
|
@ -2283,8 +2283,7 @@ static int wpa_derive_ptk(struct wpa_state_machine *sm, const u8 *snonce,
|
|||||||
|
|
||||||
if (sm->wpa_auth->conf.force_kdk_derivation ||
|
if (sm->wpa_auth->conf.force_kdk_derivation ||
|
||||||
(sm->wpa_auth->conf.secure_ltf &&
|
(sm->wpa_auth->conf.secure_ltf &&
|
||||||
sm->rsnxe && sm->rsnxe_len >= 4 &&
|
ieee802_11_rsnx_capab(sm->rsnxe, WLAN_RSNX_CAPAB_SECURE_LTF)))
|
||||||
sm->rsnxe[3] & BIT(WLAN_RSNX_CAPAB_SECURE_LTF - 8)))
|
|
||||||
kdk_len = WPA_KDK_MAX_LEN;
|
kdk_len = WPA_KDK_MAX_LEN;
|
||||||
else
|
else
|
||||||
kdk_len = 0;
|
kdk_len = 0;
|
||||||
@ -2338,8 +2337,7 @@ int fils_auth_pmk_to_ptk(struct wpa_state_machine *sm, const u8 *pmk,
|
|||||||
|
|
||||||
if (sm->wpa_auth->conf.force_kdk_derivation ||
|
if (sm->wpa_auth->conf.force_kdk_derivation ||
|
||||||
(sm->wpa_auth->conf.secure_ltf &&
|
(sm->wpa_auth->conf.secure_ltf &&
|
||||||
sm->rsnxe && sm->rsnxe_len >= 4 &&
|
ieee802_11_rsnx_capab(sm->rsnxe, WLAN_RSNX_CAPAB_SECURE_LTF)))
|
||||||
sm->rsnxe[3] & BIT(WLAN_RSNX_CAPAB_SECURE_LTF - 8)))
|
|
||||||
kdk_len = WPA_KDK_MAX_LEN;
|
kdk_len = WPA_KDK_MAX_LEN;
|
||||||
else
|
else
|
||||||
kdk_len = 0;
|
kdk_len = 0;
|
||||||
@ -4267,7 +4265,7 @@ int wpa_wnmsleep_bigtk_subelem(struct wpa_state_machine *sm, u8 *pos)
|
|||||||
wpa_printf(MSG_DEBUG, "WNM: BIGTK Key ID %u in WNM-Sleep Mode exit",
|
wpa_printf(MSG_DEBUG, "WNM: BIGTK Key ID %u in WNM-Sleep Mode exit",
|
||||||
gsm->GN_bigtk);
|
gsm->GN_bigtk);
|
||||||
wpa_hexdump_key(MSG_DEBUG, "WNM: BIGTK in WNM-Sleep Mode exit",
|
wpa_hexdump_key(MSG_DEBUG, "WNM: BIGTK in WNM-Sleep Mode exit",
|
||||||
gsm->IGTK[gsm->GN_bigtk - 6], len);
|
gsm->BIGTK[gsm->GN_bigtk - 6], len);
|
||||||
|
|
||||||
return pos - start;
|
return pos - start;
|
||||||
}
|
}
|
||||||
|
@ -3198,8 +3198,7 @@ static int wpa_ft_process_auth_req(struct wpa_state_machine *sm,
|
|||||||
|
|
||||||
if (sm->wpa_auth->conf.force_kdk_derivation ||
|
if (sm->wpa_auth->conf.force_kdk_derivation ||
|
||||||
(sm->wpa_auth->conf.secure_ltf &&
|
(sm->wpa_auth->conf.secure_ltf &&
|
||||||
sm->rsnxe && sm->rsnxe_len >= 4 &&
|
ieee802_11_rsnx_capab(sm->rsnxe, WLAN_RSNX_CAPAB_SECURE_LTF)))
|
||||||
sm->rsnxe[3] & BIT(WLAN_RSNX_CAPAB_SECURE_LTF - 8)))
|
|
||||||
kdk_len = WPA_KDK_MAX_LEN;
|
kdk_len = WPA_KDK_MAX_LEN;
|
||||||
else
|
else
|
||||||
kdk_len = 0;
|
kdk_len = 0;
|
||||||
|
@ -256,87 +256,69 @@ static int sae_tests(void)
|
|||||||
#ifdef CONFIG_SAE
|
#ifdef CONFIG_SAE
|
||||||
struct sae_data sae;
|
struct sae_data sae;
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
/* IEEE P802.11-REVmd/D2.1, Annex J.10 */
|
/* IEEE Std 802.11-2020, Annex J.10 */
|
||||||
const u8 addr1[ETH_ALEN] = { 0x82, 0x7b, 0x91, 0x9d, 0xd4, 0xb9 };
|
const u8 addr1[ETH_ALEN] = { 0x4d, 0x3f, 0x2f, 0xff, 0xe3, 0x87 };
|
||||||
const u8 addr2[ETH_ALEN] = { 0x1e, 0xec, 0x49, 0xea, 0x64, 0x88 };
|
const u8 addr2[ETH_ALEN] = { 0xa5, 0xd8, 0xaa, 0x95, 0x8e, 0x3c };
|
||||||
const char *ssid = "byteme";
|
const char *ssid = "byteme";
|
||||||
const char *pw = "mekmitasdigoat";
|
const char *pw = "mekmitasdigoat";
|
||||||
const char *pwid = "psk4internet";
|
const char *pwid = "psk4internet";
|
||||||
const u8 local_rand[] = {
|
const u8 local_rand[] = {
|
||||||
0xa9, 0x06, 0xf6, 0x1e, 0x4d, 0x3a, 0x5d, 0x4e,
|
0x99, 0x24, 0x65, 0xfd, 0x3d, 0xaa, 0x3c, 0x60,
|
||||||
0xb2, 0x96, 0x5f, 0xf3, 0x4c, 0xf9, 0x17, 0xdd,
|
0xaa, 0x65, 0x65, 0xb7, 0xf6, 0x2a, 0x2a, 0x7f,
|
||||||
0x04, 0x44, 0x45, 0xc8, 0x78, 0xc1, 0x7c, 0xa5,
|
0x2e, 0x12, 0xdd, 0x12, 0xf1, 0x98, 0xfa, 0xf4,
|
||||||
0xd5, 0xb9, 0x37, 0x86, 0xda, 0x9f, 0x83, 0xcf
|
0xfb, 0xed, 0x89, 0xd7, 0xff, 0x1a, 0xce, 0x94
|
||||||
};
|
};
|
||||||
const u8 local_mask[] = {
|
const u8 local_mask[] = {
|
||||||
0x42, 0x34, 0xb4, 0xfb, 0x17, 0xaa, 0x43, 0x5c,
|
0x95, 0x07, 0xa9, 0x0f, 0x77, 0x7a, 0x04, 0x4d,
|
||||||
0x52, 0xfb, 0xfd, 0xeb, 0xe6, 0x40, 0x39, 0xb4,
|
0x6a, 0x08, 0x30, 0xb9, 0x1e, 0xa3, 0xd5, 0xdd,
|
||||||
0x34, 0x78, 0x20, 0x0e, 0x54, 0xff, 0x7b, 0x6e,
|
0x70, 0xbe, 0xce, 0x44, 0xe1, 0xac, 0xff, 0xb8,
|
||||||
0x07, 0xb6, 0x9c, 0xad, 0x74, 0x15, 0x3c, 0x15
|
0x69, 0x83, 0xb5, 0xe1, 0xbf, 0x9f, 0xb3, 0x22
|
||||||
};
|
};
|
||||||
const u8 local_commit[] = {
|
const u8 local_commit[] = {
|
||||||
0x13, 0x00, 0xeb, 0x3b, 0xab, 0x19, 0x64, 0xe4,
|
0x13, 0x00, 0x2e, 0x2c, 0x0f, 0x0d, 0xb5, 0x24,
|
||||||
0xa0, 0xab, 0x05, 0x92, 0x5d, 0xdf, 0x33, 0x39,
|
0x40, 0xad, 0x14, 0x6d, 0x96, 0x71, 0x14, 0xce,
|
||||||
0x51, 0x91, 0x38, 0xbc, 0x65, 0xd6, 0xcd, 0xc0,
|
0x00, 0x5c, 0xe1, 0xea, 0xb0, 0xaa, 0x2c, 0x2e,
|
||||||
0xf8, 0x13, 0xdd, 0x6f, 0xd4, 0x34, 0x4e, 0xb4,
|
0x5c, 0x28, 0x71, 0xb7, 0x74, 0xf6, 0xc2, 0x57,
|
||||||
0xbf, 0xe4, 0x4b, 0x5c, 0x21, 0x59, 0x76, 0x58,
|
0x5c, 0x65, 0xd5, 0xad, 0x9e, 0x00, 0x82, 0x97,
|
||||||
0xf4, 0xe3, 0xed, 0xdf, 0xb4, 0xb9, 0x9f, 0x25,
|
0x07, 0xaa, 0x36, 0xba, 0x8b, 0x85, 0x97, 0x38,
|
||||||
0xb4, 0xd6, 0x54, 0x0f, 0x32, 0xff, 0x1f, 0xd5,
|
0xfc, 0x96, 0x1d, 0x08, 0x24, 0x35, 0x05, 0xf4,
|
||||||
0xc5, 0x30, 0xc6, 0x0a, 0x79, 0x44, 0x48, 0x61,
|
0x7c, 0x03, 0x53, 0x76, 0xd7, 0xac, 0x4b, 0xc8,
|
||||||
0x0b, 0xc6, 0xde, 0x3d, 0x92, 0xbd, 0xbb, 0xd4,
|
0xd7, 0xb9, 0x50, 0x83, 0xbf, 0x43, 0x82, 0x7d,
|
||||||
0x7d, 0x93, 0x59, 0x80, 0xca, 0x6c, 0xf8, 0x98,
|
0x0f, 0xc3, 0x1e, 0xd7, 0x78, 0xdd, 0x36, 0x71,
|
||||||
0x8a, 0xb6, 0x63, 0x0b, 0xe6, 0x76, 0x4c, 0x88,
|
0xfd, 0x21, 0xa4, 0x6d, 0x10, 0x91, 0xd6, 0x4b,
|
||||||
0x5c, 0xeb, 0x97, 0x93, 0x97, 0x0f, 0x69, 0x52,
|
0x6f, 0x9a, 0x1e, 0x12, 0x72, 0x62, 0x13, 0x25,
|
||||||
0x17, 0xee, 0xff, 0x0d, 0x21, 0x70, 0x73, 0x6b,
|
0xdb, 0xe1
|
||||||
0x34, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65,
|
|
||||||
0x74
|
|
||||||
};
|
};
|
||||||
const u8 peer_commit[] = {
|
const u8 peer_commit[] = {
|
||||||
0x13, 0x00, 0x55, 0x64, 0xf0, 0x45, 0xb2, 0xea,
|
0x13, 0x00, 0x59, 0x1b, 0x96, 0xf3, 0x39, 0x7f,
|
||||||
0x1e, 0x56, 0x6c, 0xf1, 0xdd, 0x74, 0x1f, 0x70,
|
0xb9, 0x45, 0x10, 0x08, 0x48, 0xe7, 0xb5, 0x50,
|
||||||
0xd9, 0xbe, 0x35, 0xd2, 0xdf, 0x5b, 0x9a, 0x55,
|
0x54, 0x3b, 0x67, 0x20, 0xd8, 0x83, 0x37, 0xee,
|
||||||
0x02, 0x94, 0x6e, 0xe0, 0x3c, 0xf8, 0xda, 0xe2,
|
0x93, 0xfc, 0x49, 0xfd, 0x6d, 0xf7, 0xe0, 0x8b,
|
||||||
0x7e, 0x1e, 0x05, 0xb8, 0x43, 0x0e, 0xb7, 0xa9,
|
0x52, 0x23, 0xe7, 0x1b, 0x9b, 0xb0, 0x48, 0xd3,
|
||||||
0x9e, 0x24, 0x87, 0x7c, 0xe6, 0x9b, 0xaf, 0x3d,
|
0x87, 0x3f, 0x20, 0x55, 0x69, 0x53, 0xa9, 0x6c,
|
||||||
0xc5, 0x80, 0xe3, 0x09, 0x63, 0x3d, 0x6b, 0x38,
|
0x91, 0x53, 0x6f, 0xd8, 0xee, 0x6c, 0xa9, 0xb4,
|
||||||
0x5f, 0x83, 0xee, 0x1c, 0x3e, 0xc3, 0x59, 0x1f,
|
0xa6, 0x8a, 0x14, 0x8b, 0x05, 0x6a, 0x90, 0x9b,
|
||||||
0x1a, 0x53, 0x93, 0xc0, 0x6e, 0x80, 0x5d, 0xdc,
|
0xe0, 0x3e, 0x83, 0xae, 0x20, 0x8f, 0x60, 0xf8,
|
||||||
0xeb, 0x2f, 0xde, 0x50, 0x93, 0x0d, 0xd7, 0xcf,
|
0xef, 0x55, 0x37, 0x85, 0x80, 0x74, 0xdb, 0x06,
|
||||||
0xeb, 0xb9, 0x87, 0xc6, 0xff, 0x96, 0x66, 0xaf,
|
0x68, 0x70, 0x32, 0x39, 0x98, 0x62, 0x99, 0x9b,
|
||||||
0x16, 0x4e, 0xb5, 0x18, 0x4d, 0x8e, 0x66, 0x62,
|
0x51, 0x1e, 0x0a, 0x15, 0x52, 0xa5, 0xfe, 0xa3,
|
||||||
0xed, 0x6a, 0xff, 0x0d, 0x21, 0x70, 0x73, 0x6b,
|
0x17, 0xc2
|
||||||
0x34, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65,
|
|
||||||
0x74
|
|
||||||
};
|
};
|
||||||
const u8 kck[] = {
|
const u8 kck[] = {
|
||||||
0x59, 0x9d, 0x6f, 0x1e, 0x27, 0x54, 0x8b, 0xe8,
|
0x1e, 0x73, 0x3f, 0x6d, 0x9b, 0xd5, 0x32, 0x56,
|
||||||
0x49, 0x9d, 0xce, 0xed, 0x2f, 0xec, 0xcf, 0x94,
|
0x28, 0x73, 0x04, 0x33, 0x88, 0x31, 0xb0, 0x9a,
|
||||||
0x81, 0x8c, 0xe1, 0xc7, 0x9f, 0x1b, 0x4e, 0xb3,
|
0x39, 0x40, 0x6d, 0x12, 0x10, 0x17, 0x07, 0x3a,
|
||||||
0xd6, 0xa5, 0x32, 0x28, 0xa0, 0x9b, 0xf3, 0xed
|
0x5c, 0x30, 0xdb, 0x36, 0xf3, 0x6c, 0xb8, 0x1a
|
||||||
};
|
};
|
||||||
const u8 pmk[] = {
|
const u8 pmk[] = {
|
||||||
0x7a, 0xea, 0xd8, 0x6f, 0xba, 0x4c, 0x32, 0x21,
|
0x4e, 0x4d, 0xfa, 0xb1, 0xa2, 0xdd, 0x8a, 0xc1,
|
||||||
0xfc, 0x43, 0x7f, 0x5f, 0x14, 0xd7, 0x0d, 0x85,
|
0xa9, 0x17, 0x90, 0xf9, 0x53, 0xfa, 0xaa, 0x45,
|
||||||
0x4e, 0xa5, 0xd5, 0xaa, 0xc1, 0x69, 0x01, 0x16,
|
0x2a, 0xe5, 0xc6, 0x87, 0x3a, 0xb7, 0x5b, 0x63,
|
||||||
0x79, 0x30, 0x81, 0xed, 0xa4, 0xd5, 0x57, 0xc5
|
0x60, 0x5b, 0xa6, 0x63, 0xf8, 0xa7, 0xfe, 0x59
|
||||||
};
|
};
|
||||||
const u8 pmkid[] = {
|
const u8 pmkid[] = {
|
||||||
0x40, 0xa0, 0x9b, 0x60, 0x17, 0xce, 0xbf, 0x00,
|
0x87, 0x47, 0xa6, 0x00, 0xee, 0xa3, 0xf9, 0xf2,
|
||||||
0x72, 0x84, 0x3b, 0x53, 0x52, 0xaa, 0x2b, 0x4f
|
0x24, 0x75, 0xdf, 0x58, 0xca, 0x1e, 0x54, 0x98
|
||||||
};
|
|
||||||
const u8 local_confirm[] = {
|
|
||||||
0x01, 0x00, 0x12, 0xd9, 0xd5, 0xc7, 0x8c, 0x50,
|
|
||||||
0x05, 0x26, 0xd3, 0x6c, 0x41, 0xdb, 0xc5, 0x6a,
|
|
||||||
0xed, 0xf2, 0x91, 0x4c, 0xed, 0xdd, 0xd7, 0xca,
|
|
||||||
0xd4, 0xa5, 0x8c, 0x48, 0xf8, 0x3d, 0xbd, 0xe9,
|
|
||||||
0xfc, 0x77
|
|
||||||
};
|
|
||||||
const u8 peer_confirm[] = {
|
|
||||||
0x01, 0x00, 0x02, 0x87, 0x1c, 0xf9, 0x06, 0x89,
|
|
||||||
0x8b, 0x80, 0x60, 0xec, 0x18, 0x41, 0x43, 0xbe,
|
|
||||||
0x77, 0xb8, 0xc0, 0x8a, 0x80, 0x19, 0xb1, 0x3e,
|
|
||||||
0xb6, 0xd0, 0xae, 0xf0, 0xd8, 0x38, 0x3d, 0xfa,
|
|
||||||
0xc2, 0xfd
|
|
||||||
};
|
};
|
||||||
struct wpabuf *buf = NULL;
|
struct wpabuf *buf = NULL;
|
||||||
struct crypto_bignum *mask = NULL;
|
struct crypto_bignum *mask = NULL;
|
||||||
@ -412,7 +394,7 @@ static int sae_tests(void)
|
|||||||
if (!buf ||
|
if (!buf ||
|
||||||
sae_set_group(&sae, 19) < 0 ||
|
sae_set_group(&sae, 19) < 0 ||
|
||||||
sae_prepare_commit(addr1, addr2, (const u8 *) pw, os_strlen(pw),
|
sae_prepare_commit(addr1, addr2, (const u8 *) pw, os_strlen(pw),
|
||||||
pwid, &sae) < 0)
|
&sae) < 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
/* Override local values based on SAE test vector */
|
/* Override local values based on SAE test vector */
|
||||||
@ -434,7 +416,7 @@ static int sae_tests(void)
|
|||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
/* Check that output matches the test vector */
|
/* Check that output matches the test vector */
|
||||||
if (sae_write_commit(&sae, buf, NULL, pwid) < 0)
|
if (sae_write_commit(&sae, buf, NULL, NULL) < 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
wpa_hexdump_buf(MSG_DEBUG, "SAE: Commit message", buf);
|
wpa_hexdump_buf(MSG_DEBUG, "SAE: Commit message", buf);
|
||||||
|
|
||||||
@ -465,21 +447,6 @@ static int sae_tests(void)
|
|||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
buf->used = 0;
|
|
||||||
sae.send_confirm = 1;
|
|
||||||
sae_write_confirm(&sae, buf);
|
|
||||||
wpa_hexdump_buf(MSG_DEBUG, "SAE: Confirm message", buf);
|
|
||||||
|
|
||||||
if (wpabuf_len(buf) != sizeof(local_confirm) ||
|
|
||||||
os_memcmp(wpabuf_head(buf), local_confirm,
|
|
||||||
sizeof(local_confirm)) != 0) {
|
|
||||||
wpa_printf(MSG_ERROR, "SAE: Mismatch in local confirm");
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sae_check_confirm(&sae, peer_confirm, sizeof(peer_confirm)) < 0)
|
|
||||||
goto fail;
|
|
||||||
|
|
||||||
pt_info = sae_derive_pt(pt_groups,
|
pt_info = sae_derive_pt(pt_groups,
|
||||||
(const u8 *) ssid, os_strlen(ssid),
|
(const u8 *) ssid, os_strlen(ssid),
|
||||||
(const u8 *) pw, os_strlen(pw), pwid);
|
(const u8 *) pw, os_strlen(pw), pwid);
|
||||||
|
@ -2403,6 +2403,35 @@ int ieee802_11_ext_capab(const u8 *ie, unsigned int capab)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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 |= rsnxe[i] << (8 * i);
|
||||||
|
|
||||||
|
return capabs & BIT(capab);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool ieee802_11_rsnx_capab(const u8 *rsnxe, unsigned int capab)
|
||||||
|
{
|
||||||
|
return ieee802_11_rsnx_capab_len(rsnxe ? rsnxe + 2 : NULL,
|
||||||
|
rsnxe ? rsnxe[1] : 0, capab);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void hostapd_encode_edmg_chan(int edmg_enable, u8 edmg_channel,
|
void hostapd_encode_edmg_chan(int edmg_enable, u8 edmg_channel,
|
||||||
int primary_channel,
|
int primary_channel,
|
||||||
struct ieee80211_edmg_config *edmg)
|
struct ieee80211_edmg_config *edmg)
|
||||||
|
@ -269,6 +269,9 @@ int ieee802_11_parse_candidate_list(const char *pos, u8 *nei_rep,
|
|||||||
size_t nei_rep_len);
|
size_t nei_rep_len);
|
||||||
|
|
||||||
int ieee802_11_ext_capab(const u8 *ie, unsigned int capab);
|
int ieee802_11_ext_capab(const u8 *ie, unsigned int capab);
|
||||||
|
bool ieee802_11_rsnx_capab_len(const u8 *rsnxe, size_t rsnxe_len,
|
||||||
|
unsigned int capab);
|
||||||
|
bool ieee802_11_rsnx_capab(const u8 *rsnxe, unsigned int capab);
|
||||||
int op_class_to_bandwidth(u8 op_class);
|
int op_class_to_bandwidth(u8 op_class);
|
||||||
int op_class_to_ch_width(u8 op_class);
|
int op_class_to_ch_width(u8 op_class);
|
||||||
|
|
||||||
|
@ -8445,6 +8445,34 @@ enum qca_wlan_twt_setup_state {
|
|||||||
* This parameter is used for
|
* This parameter is used for
|
||||||
* 1. TWT SET Request and Response
|
* 1. TWT SET Request and Response
|
||||||
* 2. TWT GET Response
|
* 2. TWT GET Response
|
||||||
|
*
|
||||||
|
* @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_BCAST_ID: Optional (u8)
|
||||||
|
* This attribute is used to configure Broadcast TWT ID.
|
||||||
|
* The Broadcast TWT ID indicates a specific Broadcast TWT for which the
|
||||||
|
* transmitting STA is providing TWT parameters. The allowed values are 0 to 31.
|
||||||
|
* This parameter is used for
|
||||||
|
* 1. TWT SET Request
|
||||||
|
* 2. TWT TERMINATE Request
|
||||||
|
*
|
||||||
|
* @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_BCAST_RECOMMENDATION: Optional (u8)
|
||||||
|
* This attribute is used to configure Broadcast TWT recommendation.
|
||||||
|
* The Broadcast TWT Recommendation subfield contains a value that indicates
|
||||||
|
* recommendations on the types of frames that are transmitted by TWT
|
||||||
|
* scheduled STAs and scheduling AP during the broadcast TWT SP.
|
||||||
|
* The allowed values are 0 - 3.
|
||||||
|
* This parameter is used for
|
||||||
|
* 1. TWT SET Request
|
||||||
|
*
|
||||||
|
* @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_BCAST_PERSISTENCE: Optional (u8)
|
||||||
|
* This attribute is used to configure Broadcast TWT Persistence.
|
||||||
|
* The Broadcast TWT Persistence subfield indicates the number of
|
||||||
|
* TBTTs during which the Broadcast TWT SPs corresponding to this
|
||||||
|
* broadcast TWT Parameter set are present. The number of beacon intervals
|
||||||
|
* during which the Broadcast TWT SPs are present is equal to the value in the
|
||||||
|
* Broadcast TWT Persistence subfield plus 1 except that the value 255
|
||||||
|
* indicates that the Broadcast TWT SPs are present until explicitly terminated.
|
||||||
|
* This parameter is used for
|
||||||
|
* 1. TWT SET Request
|
||||||
*/
|
*/
|
||||||
enum qca_wlan_vendor_attr_twt_setup {
|
enum qca_wlan_vendor_attr_twt_setup {
|
||||||
QCA_WLAN_VENDOR_ATTR_TWT_SETUP_INVALID = 0,
|
QCA_WLAN_VENDOR_ATTR_TWT_SETUP_INVALID = 0,
|
||||||
@ -8474,6 +8502,10 @@ enum qca_wlan_vendor_attr_twt_setup {
|
|||||||
|
|
||||||
QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_INTVL2_MANTISSA = 21,
|
QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_INTVL2_MANTISSA = 21,
|
||||||
|
|
||||||
|
QCA_WLAN_VENDOR_ATTR_TWT_SETUP_BCAST_ID = 22,
|
||||||
|
QCA_WLAN_VENDOR_ATTR_TWT_SETUP_BCAST_RECOMMENDATION = 23,
|
||||||
|
QCA_WLAN_VENDOR_ATTR_TWT_SETUP_BCAST_PERSISTENCE = 24,
|
||||||
|
|
||||||
/* keep last */
|
/* keep last */
|
||||||
QCA_WLAN_VENDOR_ATTR_TWT_SETUP_AFTER_LAST,
|
QCA_WLAN_VENDOR_ATTR_TWT_SETUP_AFTER_LAST,
|
||||||
QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MAX =
|
QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MAX =
|
||||||
@ -8512,6 +8544,13 @@ enum qca_wlan_vendor_attr_twt_setup {
|
|||||||
* @QCA_WLAN_VENDOR_TWT_STATUS_ROAM_INITIATED_TERMINATE: FW terminated the TWT
|
* @QCA_WLAN_VENDOR_TWT_STATUS_ROAM_INITIATED_TERMINATE: FW terminated the TWT
|
||||||
* session due to roaming. Used on the TWT_TERMINATE notification from the
|
* session due to roaming. Used on the TWT_TERMINATE notification from the
|
||||||
* firmware.
|
* firmware.
|
||||||
|
* @QCA_WLAN_VENDOR_TWT_STATUS_SCC_MCC_CONCURRENCY_TERMINATE: FW terminated the
|
||||||
|
* TWT session due to SCC (Single Channel Concurrency) and MCC (Multi Channel
|
||||||
|
* Concurrency). Used on the TWT_TERMINATE notification from the firmware.
|
||||||
|
* @QCA_WLAN_VENDOR_TWT_STATUS_ROAMING_IN_PROGRESS: FW rejected the TWT setup
|
||||||
|
* request due to roaming in progress.
|
||||||
|
* @QCA_WLAN_VENDOR_TWT_STATUS_CHANNEL_SWITCH_IN_PROGRESS: FW rejected the TWT
|
||||||
|
* setup request due to channel switch in progress.
|
||||||
*/
|
*/
|
||||||
enum qca_wlan_vendor_twt_status {
|
enum qca_wlan_vendor_twt_status {
|
||||||
QCA_WLAN_VENDOR_TWT_STATUS_OK = 0,
|
QCA_WLAN_VENDOR_TWT_STATUS_OK = 0,
|
||||||
@ -8532,6 +8571,9 @@ enum qca_wlan_vendor_twt_status {
|
|||||||
QCA_WLAN_VENDOR_TWT_STATUS_PARAMS_NOT_IN_RANGE = 15,
|
QCA_WLAN_VENDOR_TWT_STATUS_PARAMS_NOT_IN_RANGE = 15,
|
||||||
QCA_WLAN_VENDOR_TWT_STATUS_PEER_INITIATED_TERMINATE = 16,
|
QCA_WLAN_VENDOR_TWT_STATUS_PEER_INITIATED_TERMINATE = 16,
|
||||||
QCA_WLAN_VENDOR_TWT_STATUS_ROAM_INITIATED_TERMINATE = 17,
|
QCA_WLAN_VENDOR_TWT_STATUS_ROAM_INITIATED_TERMINATE = 17,
|
||||||
|
QCA_WLAN_VENDOR_TWT_STATUS_SCC_MCC_CONCURRENCY_TERMINATE = 18,
|
||||||
|
QCA_WLAN_VENDOR_TWT_STATUS_ROAMING_IN_PROGRESS = 19,
|
||||||
|
QCA_WLAN_VENDOR_TWT_STATUS_CHANNEL_SWITCH_IN_PROGRESS = 20,
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -280,13 +280,12 @@ static int sae_test_pwd_seed_ffc(struct sae_data *sae, const u8 *pwd_seed,
|
|||||||
|
|
||||||
static int sae_derive_pwe_ecc(struct sae_data *sae, const u8 *addr1,
|
static int sae_derive_pwe_ecc(struct sae_data *sae, const u8 *addr1,
|
||||||
const u8 *addr2, const u8 *password,
|
const u8 *addr2, const u8 *password,
|
||||||
size_t password_len, const char *identifier)
|
size_t password_len)
|
||||||
{
|
{
|
||||||
u8 counter, k;
|
u8 counter, k;
|
||||||
u8 addrs[2 * ETH_ALEN];
|
u8 addrs[2 * ETH_ALEN];
|
||||||
const u8 *addr[3];
|
const u8 *addr[2];
|
||||||
size_t len[3];
|
size_t len[2];
|
||||||
size_t num_elem;
|
|
||||||
u8 *dummy_password, *tmp_password;
|
u8 *dummy_password, *tmp_password;
|
||||||
int pwd_seed_odd = 0;
|
int pwd_seed_odd = 0;
|
||||||
u8 prime[SAE_MAX_ECC_PRIME_LEN];
|
u8 prime[SAE_MAX_ECC_PRIME_LEN];
|
||||||
@ -324,13 +323,10 @@ static int sae_derive_pwe_ecc(struct sae_data *sae, const u8 *addr1,
|
|||||||
|
|
||||||
wpa_hexdump_ascii_key(MSG_DEBUG, "SAE: password",
|
wpa_hexdump_ascii_key(MSG_DEBUG, "SAE: password",
|
||||||
password, password_len);
|
password, password_len);
|
||||||
if (identifier)
|
|
||||||
wpa_printf(MSG_DEBUG, "SAE: password identifier: %s",
|
|
||||||
identifier);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* H(salt, ikm) = HMAC-SHA256(salt, ikm)
|
* H(salt, ikm) = HMAC-SHA256(salt, ikm)
|
||||||
* base = password [|| identifier]
|
* base = password
|
||||||
* pwd-seed = H(MAX(STA-A-MAC, STA-B-MAC) || MIN(STA-A-MAC, STA-B-MAC),
|
* pwd-seed = H(MAX(STA-A-MAC, STA-B-MAC) || MIN(STA-A-MAC, STA-B-MAC),
|
||||||
* base || counter)
|
* base || counter)
|
||||||
*/
|
*/
|
||||||
@ -338,15 +334,8 @@ static int sae_derive_pwe_ecc(struct sae_data *sae, const u8 *addr1,
|
|||||||
|
|
||||||
addr[0] = tmp_password;
|
addr[0] = tmp_password;
|
||||||
len[0] = password_len;
|
len[0] = password_len;
|
||||||
num_elem = 1;
|
addr[1] = &counter;
|
||||||
if (identifier) {
|
len[1] = sizeof(counter);
|
||||||
addr[num_elem] = (const u8 *) identifier;
|
|
||||||
len[num_elem] = os_strlen(identifier);
|
|
||||||
num_elem++;
|
|
||||||
}
|
|
||||||
addr[num_elem] = &counter;
|
|
||||||
len[num_elem] = sizeof(counter);
|
|
||||||
num_elem++;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Continue for at least k iterations to protect against side-channel
|
* Continue for at least k iterations to protect against side-channel
|
||||||
@ -367,7 +356,7 @@ static int sae_derive_pwe_ecc(struct sae_data *sae, const u8 *addr1,
|
|||||||
wpa_printf(MSG_DEBUG, "SAE: counter = %03u", counter);
|
wpa_printf(MSG_DEBUG, "SAE: counter = %03u", counter);
|
||||||
const_time_select_bin(found, dummy_password, password,
|
const_time_select_bin(found, dummy_password, password,
|
||||||
password_len, tmp_password);
|
password_len, tmp_password);
|
||||||
if (hmac_sha256_vector(addrs, sizeof(addrs), num_elem,
|
if (hmac_sha256_vector(addrs, sizeof(addrs), 2,
|
||||||
addr, len, pwd_seed) < 0)
|
addr, len, pwd_seed) < 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -438,13 +427,12 @@ static int sae_derive_pwe_ecc(struct sae_data *sae, const u8 *addr1,
|
|||||||
|
|
||||||
static int sae_derive_pwe_ffc(struct sae_data *sae, const u8 *addr1,
|
static int sae_derive_pwe_ffc(struct sae_data *sae, const u8 *addr1,
|
||||||
const u8 *addr2, const u8 *password,
|
const u8 *addr2, const u8 *password,
|
||||||
size_t password_len, const char *identifier)
|
size_t password_len)
|
||||||
{
|
{
|
||||||
u8 counter, k, sel_counter = 0;
|
u8 counter, k, sel_counter = 0;
|
||||||
u8 addrs[2 * ETH_ALEN];
|
u8 addrs[2 * ETH_ALEN];
|
||||||
const u8 *addr[3];
|
const u8 *addr[2];
|
||||||
size_t len[3];
|
size_t len[2];
|
||||||
size_t num_elem;
|
|
||||||
u8 found = 0; /* 0 (false) or 0xff (true) to be used as const_time_*
|
u8 found = 0; /* 0 (false) or 0xff (true) to be used as const_time_*
|
||||||
* mask */
|
* mask */
|
||||||
u8 mask;
|
u8 mask;
|
||||||
@ -468,21 +456,14 @@ static int sae_derive_pwe_ffc(struct sae_data *sae, const u8 *addr1,
|
|||||||
/*
|
/*
|
||||||
* H(salt, ikm) = HMAC-SHA256(salt, ikm)
|
* H(salt, ikm) = HMAC-SHA256(salt, ikm)
|
||||||
* pwd-seed = H(MAX(STA-A-MAC, STA-B-MAC) || MIN(STA-A-MAC, STA-B-MAC),
|
* pwd-seed = H(MAX(STA-A-MAC, STA-B-MAC) || MIN(STA-A-MAC, STA-B-MAC),
|
||||||
* password [|| identifier] || counter)
|
* password || counter)
|
||||||
*/
|
*/
|
||||||
sae_pwd_seed_key(addr1, addr2, addrs);
|
sae_pwd_seed_key(addr1, addr2, addrs);
|
||||||
|
|
||||||
addr[0] = password;
|
addr[0] = password;
|
||||||
len[0] = password_len;
|
len[0] = password_len;
|
||||||
num_elem = 1;
|
addr[1] = &counter;
|
||||||
if (identifier) {
|
len[1] = sizeof(counter);
|
||||||
addr[num_elem] = (const u8 *) identifier;
|
|
||||||
len[num_elem] = os_strlen(identifier);
|
|
||||||
num_elem++;
|
|
||||||
}
|
|
||||||
addr[num_elem] = &counter;
|
|
||||||
len[num_elem] = sizeof(counter);
|
|
||||||
num_elem++;
|
|
||||||
|
|
||||||
k = dragonfly_min_pwe_loop_iter(sae->group);
|
k = dragonfly_min_pwe_loop_iter(sae->group);
|
||||||
|
|
||||||
@ -497,7 +478,7 @@ static int sae_derive_pwe_ffc(struct sae_data *sae, const u8 *addr1,
|
|||||||
}
|
}
|
||||||
|
|
||||||
wpa_printf(MSG_DEBUG, "SAE: counter = %02u", counter);
|
wpa_printf(MSG_DEBUG, "SAE: counter = %02u", counter);
|
||||||
if (hmac_sha256_vector(addrs, sizeof(addrs), num_elem,
|
if (hmac_sha256_vector(addrs, sizeof(addrs), 2,
|
||||||
addr, len, pwd_seed) < 0)
|
addr, len, pwd_seed) < 0)
|
||||||
break;
|
break;
|
||||||
res = sae_test_pwd_seed_ffc(sae, pwd_seed, pwe);
|
res = sae_test_pwd_seed_ffc(sae, pwd_seed, pwe);
|
||||||
@ -1354,15 +1335,13 @@ static int sae_derive_commit(struct sae_data *sae)
|
|||||||
|
|
||||||
int sae_prepare_commit(const u8 *addr1, const u8 *addr2,
|
int sae_prepare_commit(const u8 *addr1, const u8 *addr2,
|
||||||
const u8 *password, size_t password_len,
|
const u8 *password, size_t password_len,
|
||||||
const char *identifier, struct sae_data *sae)
|
struct sae_data *sae)
|
||||||
{
|
{
|
||||||
if (sae->tmp == NULL ||
|
if (sae->tmp == NULL ||
|
||||||
(sae->tmp->ec && sae_derive_pwe_ecc(sae, addr1, addr2, password,
|
(sae->tmp->ec && sae_derive_pwe_ecc(sae, addr1, addr2, password,
|
||||||
password_len,
|
password_len) < 0) ||
|
||||||
identifier) < 0) ||
|
|
||||||
(sae->tmp->dh && sae_derive_pwe_ffc(sae, addr1, addr2, password,
|
(sae->tmp->dh && sae_derive_pwe_ffc(sae, addr1, addr2, password,
|
||||||
password_len,
|
password_len) < 0))
|
||||||
identifier) < 0))
|
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
sae->h2e = 0;
|
sae->h2e = 0;
|
||||||
@ -2268,10 +2247,10 @@ int sae_write_confirm(struct sae_data *sae, struct wpabuf *buf)
|
|||||||
hash_len = sae->tmp->kck_len;
|
hash_len = sae->tmp->kck_len;
|
||||||
|
|
||||||
/* Send-Confirm */
|
/* Send-Confirm */
|
||||||
sc = wpabuf_put(buf, 0);
|
|
||||||
wpabuf_put_le16(buf, sae->send_confirm);
|
|
||||||
if (sae->send_confirm < 0xffff)
|
if (sae->send_confirm < 0xffff)
|
||||||
sae->send_confirm++;
|
sae->send_confirm++;
|
||||||
|
sc = wpabuf_put(buf, 0);
|
||||||
|
wpabuf_put_le16(buf, sae->send_confirm);
|
||||||
|
|
||||||
if (sae->tmp->ec)
|
if (sae->tmp->ec)
|
||||||
res = sae_cn_confirm_ecc(sae, sc, sae->tmp->own_commit_scalar,
|
res = sae_cn_confirm_ecc(sae, sc, sae->tmp->own_commit_scalar,
|
||||||
|
@ -122,7 +122,7 @@ void sae_clear_data(struct sae_data *sae);
|
|||||||
|
|
||||||
int sae_prepare_commit(const u8 *addr1, const u8 *addr2,
|
int sae_prepare_commit(const u8 *addr1, const u8 *addr2,
|
||||||
const u8 *password, size_t password_len,
|
const u8 *password, size_t password_len,
|
||||||
const char *identifier, struct sae_data *sae);
|
struct sae_data *sae);
|
||||||
int sae_prepare_commit_pt(struct sae_data *sae, const struct sae_pt *pt,
|
int sae_prepare_commit_pt(struct sae_data *sae, const struct sae_pt *pt,
|
||||||
const u8 *addr1, const u8 *addr2,
|
const u8 *addr1, const u8 *addr2,
|
||||||
int *rejected_groups, const struct sae_pk *pk);
|
int *rejected_groups, const struct sae_pk *pk);
|
||||||
|
@ -3428,8 +3428,8 @@ int wpa_pasn_add_rsne(struct wpabuf *buf, const u8 *pmkid, int akmp, int cipher)
|
|||||||
*/
|
*/
|
||||||
void wpa_pasn_add_parameter_ie(struct wpabuf *buf, u16 pasn_group,
|
void wpa_pasn_add_parameter_ie(struct wpabuf *buf, u16 pasn_group,
|
||||||
u8 wrapped_data_format,
|
u8 wrapped_data_format,
|
||||||
struct wpabuf *pubkey, bool compressed,
|
const struct wpabuf *pubkey, bool compressed,
|
||||||
struct wpabuf *comeback, int after)
|
const struct wpabuf *comeback, int after)
|
||||||
{
|
{
|
||||||
struct pasn_parameter_ie *params;
|
struct pasn_parameter_ie *params;
|
||||||
|
|
||||||
|
@ -662,8 +662,8 @@ int wpa_pasn_add_rsne(struct wpabuf *buf, const u8 *pmkid,
|
|||||||
|
|
||||||
void wpa_pasn_add_parameter_ie(struct wpabuf *buf, u16 pasn_group,
|
void wpa_pasn_add_parameter_ie(struct wpabuf *buf, u16 pasn_group,
|
||||||
u8 wrapped_data_format,
|
u8 wrapped_data_format,
|
||||||
struct wpabuf *pubkey, bool compressed,
|
const struct wpabuf *pubkey, bool compressed,
|
||||||
struct wpabuf *comeback, int after);
|
const struct wpabuf *comeback, int after);
|
||||||
|
|
||||||
int wpa_pasn_add_wrapped_data(struct wpabuf *buf,
|
int wpa_pasn_add_wrapped_data(struct wpabuf *buf,
|
||||||
struct wpabuf *wrapped_data_buf);
|
struct wpabuf *wrapped_data_buf);
|
||||||
|
@ -81,12 +81,14 @@ static void EVP_MD_CTX_free(EVP_MD_CTX *ctx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef CONFIG_ECC
|
||||||
static EC_KEY * EVP_PKEY_get0_EC_KEY(EVP_PKEY *pkey)
|
static EC_KEY * EVP_PKEY_get0_EC_KEY(EVP_PKEY *pkey)
|
||||||
{
|
{
|
||||||
if (pkey->type != EVP_PKEY_EC)
|
if (pkey->type != EVP_PKEY_EC)
|
||||||
return NULL;
|
return NULL;
|
||||||
return pkey->pkey.ec;
|
return pkey->pkey.ec;
|
||||||
}
|
}
|
||||||
|
#endif /* CONFIG_ECC */
|
||||||
|
|
||||||
#endif /* OpenSSL version < 1.1.0 */
|
#endif /* OpenSSL version < 1.1.0 */
|
||||||
|
|
||||||
|
@ -4553,6 +4553,12 @@ struct wpa_driver_ops {
|
|||||||
* explicitly allow reception of broadcast Public Action frames.
|
* explicitly allow reception of broadcast Public Action frames.
|
||||||
*/
|
*/
|
||||||
int (*dpp_listen)(void *priv, bool enable);
|
int (*dpp_listen)(void *priv, bool enable);
|
||||||
|
|
||||||
|
#ifdef CONFIG_TESTING_OPTIONS
|
||||||
|
int (*register_frame)(void *priv, u16 type,
|
||||||
|
const u8 *match, size_t match_len,
|
||||||
|
bool multicast);
|
||||||
|
#endif /* CONFIG_TESTING_OPTIONS */
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -656,12 +656,10 @@ struct nl_msg * nl80211_cmd_msg(struct i802_bss *bss, int flags, uint8_t cmd)
|
|||||||
|
|
||||||
|
|
||||||
static struct nl_msg *
|
static struct nl_msg *
|
||||||
nl80211_ifindex_msg(struct wpa_driver_nl80211_data *drv, int ifindex,
|
nl80211_ifindex_msg_build(struct wpa_driver_nl80211_data *drv,
|
||||||
int flags, uint8_t cmd)
|
struct nl_msg *msg, int ifindex, int flags,
|
||||||
|
uint8_t cmd)
|
||||||
{
|
{
|
||||||
struct nl_msg *msg;
|
|
||||||
|
|
||||||
msg = nlmsg_alloc();
|
|
||||||
if (!msg)
|
if (!msg)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
@ -675,6 +673,15 @@ nl80211_ifindex_msg(struct wpa_driver_nl80211_data *drv, int ifindex,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static struct nl_msg *
|
||||||
|
nl80211_ifindex_msg(struct wpa_driver_nl80211_data *drv, int ifindex,
|
||||||
|
int flags, uint8_t cmd)
|
||||||
|
{
|
||||||
|
return nl80211_ifindex_msg_build(drv, nlmsg_alloc(), ifindex, flags,
|
||||||
|
cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
struct nl_msg * nl80211_drv_msg(struct wpa_driver_nl80211_data *drv, int flags,
|
struct nl_msg * nl80211_drv_msg(struct wpa_driver_nl80211_data *drv, int flags,
|
||||||
uint8_t cmd)
|
uint8_t cmd)
|
||||||
{
|
{
|
||||||
@ -4151,6 +4158,7 @@ static int wpa_driver_nl80211_set_acl(void *priv,
|
|||||||
struct nl_msg *acl;
|
struct nl_msg *acl;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
int ret;
|
int ret;
|
||||||
|
size_t acl_nla_sz, acl_nlmsg_sz, nla_sz, nlmsg_sz;
|
||||||
|
|
||||||
if (!(drv->capa.max_acl_mac_addrs))
|
if (!(drv->capa.max_acl_mac_addrs))
|
||||||
return -ENOTSUP;
|
return -ENOTSUP;
|
||||||
@ -4161,7 +4169,9 @@ static int wpa_driver_nl80211_set_acl(void *priv,
|
|||||||
wpa_printf(MSG_DEBUG, "nl80211: Set %s ACL (num_mac_acl=%u)",
|
wpa_printf(MSG_DEBUG, "nl80211: Set %s ACL (num_mac_acl=%u)",
|
||||||
params->acl_policy ? "Accept" : "Deny", params->num_mac_acl);
|
params->acl_policy ? "Accept" : "Deny", params->num_mac_acl);
|
||||||
|
|
||||||
acl = nlmsg_alloc();
|
acl_nla_sz = nla_total_size(ETH_ALEN) * params->num_mac_acl;
|
||||||
|
acl_nlmsg_sz = nlmsg_total_size(acl_nla_sz);
|
||||||
|
acl = nlmsg_alloc_size(acl_nlmsg_sz);
|
||||||
if (!acl)
|
if (!acl)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
for (i = 0; i < params->num_mac_acl; i++) {
|
for (i = 0; i < params->num_mac_acl; i++) {
|
||||||
@ -4171,7 +4181,19 @@ static int wpa_driver_nl80211_set_acl(void *priv,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(msg = nl80211_drv_msg(drv, 0, NL80211_CMD_SET_MAC_ACL)) ||
|
/*
|
||||||
|
* genetlink message header (Length of user header is 0) +
|
||||||
|
* u32 attr: NL80211_ATTR_IFINDEX +
|
||||||
|
* u32 attr: NL80211_ATTR_ACL_POLICY +
|
||||||
|
* nested acl attr
|
||||||
|
*/
|
||||||
|
nla_sz = GENL_HDRLEN +
|
||||||
|
nla_total_size(4) * 2 +
|
||||||
|
nla_total_size(acl_nla_sz);
|
||||||
|
nlmsg_sz = nlmsg_total_size(nla_sz);
|
||||||
|
if (!(msg = nl80211_ifindex_msg_build(drv, nlmsg_alloc_size(nlmsg_sz),
|
||||||
|
drv->ifindex, 0,
|
||||||
|
NL80211_CMD_SET_MAC_ACL)) ||
|
||||||
nla_put_u32(msg, NL80211_ATTR_ACL_POLICY, params->acl_policy ?
|
nla_put_u32(msg, NL80211_ATTR_ACL_POLICY, params->acl_policy ?
|
||||||
NL80211_ACL_POLICY_DENY_UNLESS_LISTED :
|
NL80211_ACL_POLICY_DENY_UNLESS_LISTED :
|
||||||
NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED) ||
|
NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED) ||
|
||||||
@ -5789,6 +5811,7 @@ static int driver_nl80211_sta_set_airtime_weight(void *priv, const u8 *addr,
|
|||||||
{
|
{
|
||||||
struct i802_bss *bss = priv;
|
struct i802_bss *bss = priv;
|
||||||
struct nl_msg *msg;
|
struct nl_msg *msg;
|
||||||
|
int ret;
|
||||||
|
|
||||||
wpa_printf(MSG_DEBUG,
|
wpa_printf(MSG_DEBUG,
|
||||||
"nl80211: Set STA airtime weight - ifname=%s addr=" MACSTR
|
"nl80211: Set STA airtime weight - ifname=%s addr=" MACSTR
|
||||||
@ -5799,7 +5822,13 @@ static int driver_nl80211_sta_set_airtime_weight(void *priv, const u8 *addr,
|
|||||||
nla_put_u16(msg, NL80211_ATTR_AIRTIME_WEIGHT, weight))
|
nla_put_u16(msg, NL80211_ATTR_AIRTIME_WEIGHT, weight))
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
return send_and_recv_msgs(bss->drv, msg, NULL, NULL, NULL, NULL);
|
ret = send_and_recv_msgs(bss->drv, msg, NULL, NULL, NULL, NULL);
|
||||||
|
if (ret) {
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"nl80211: SET_STATION[AIRTIME_WEIGHT] failed: ret=%d (%s)",
|
||||||
|
ret, strerror(-ret));
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
fail:
|
fail:
|
||||||
nlmsg_free(msg);
|
nlmsg_free(msg);
|
||||||
return -ENOBUFS;
|
return -ENOBUFS;
|
||||||
@ -12028,6 +12057,23 @@ static int nl80211_dpp_listen(void *priv, bool enable)
|
|||||||
#endif /* CONFIG_DPP */
|
#endif /* CONFIG_DPP */
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef CONFIG_TESTING_OPTIONS
|
||||||
|
static int testing_nl80211_register_frame(void *priv, u16 type,
|
||||||
|
const u8 *match, size_t match_len,
|
||||||
|
bool multicast)
|
||||||
|
{
|
||||||
|
struct i802_bss *bss = priv;
|
||||||
|
struct nl_sock *handle;
|
||||||
|
|
||||||
|
if (!bss->nl_mgmt)
|
||||||
|
return -1;
|
||||||
|
handle = (void *) (((intptr_t) bss->nl_mgmt) ^ ELOOP_SOCKET_INVALID);
|
||||||
|
return nl80211_register_frame(bss, handle, type, match, match_len,
|
||||||
|
multicast);
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_TESTING_OPTIONS */
|
||||||
|
|
||||||
|
|
||||||
const struct wpa_driver_ops wpa_driver_nl80211_ops = {
|
const struct wpa_driver_ops wpa_driver_nl80211_ops = {
|
||||||
.name = "nl80211",
|
.name = "nl80211",
|
||||||
.desc = "Linux nl80211/cfg80211",
|
.desc = "Linux nl80211/cfg80211",
|
||||||
@ -12166,4 +12212,7 @@ const struct wpa_driver_ops wpa_driver_nl80211_ops = {
|
|||||||
#ifdef CONFIG_DPP
|
#ifdef CONFIG_DPP
|
||||||
.dpp_listen = nl80211_dpp_listen,
|
.dpp_listen = nl80211_dpp_listen,
|
||||||
#endif /* CONFIG_DPP */
|
#endif /* CONFIG_DPP */
|
||||||
|
#ifdef CONFIG_TESTING_OPTIONS
|
||||||
|
.register_frame = testing_nl80211_register_frame,
|
||||||
|
#endif /* CONFIG_TESTING_OPTIONS */
|
||||||
};
|
};
|
||||||
|
@ -891,7 +891,7 @@ static int wiphy_info_handler(struct nl_msg *msg, void *arg)
|
|||||||
|
|
||||||
if (tb[NL80211_ATTR_MAC_ACL_MAX])
|
if (tb[NL80211_ATTR_MAC_ACL_MAX])
|
||||||
capa->max_acl_mac_addrs =
|
capa->max_acl_mac_addrs =
|
||||||
nla_get_u8(tb[NL80211_ATTR_MAC_ACL_MAX]);
|
nla_get_u32(tb[NL80211_ATTR_MAC_ACL_MAX]);
|
||||||
|
|
||||||
wiphy_info_supported_iftypes(info, tb[NL80211_ATTR_SUPPORTED_IFTYPES]);
|
wiphy_info_supported_iftypes(info, tb[NL80211_ATTR_SUPPORTED_IFTYPES]);
|
||||||
wiphy_info_iface_comb(info, tb[NL80211_ATTR_INTERFACE_COMBINATIONS]);
|
wiphy_info_iface_comb(info, tb[NL80211_ATTR_INTERFACE_COMBINATIONS]);
|
||||||
|
@ -1210,9 +1210,24 @@ void eap_sim_report_notification(void *msg_ctx, int notification, int aka)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static const u8 * get_last_char(const u8 *val, size_t len, char c)
|
||||||
|
{
|
||||||
|
while (len > 0) {
|
||||||
|
const u8 *pos = &val[len - 1];
|
||||||
|
|
||||||
|
if (*pos == (u8) c)
|
||||||
|
return pos;
|
||||||
|
len--;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int eap_sim_anonymous_username(const u8 *id, size_t id_len)
|
int eap_sim_anonymous_username(const u8 *id, size_t id_len)
|
||||||
{
|
{
|
||||||
static const char *anonymous_id_prefix = "anonymous@";
|
static const char *anonymous_id_prefix = "anonymous@";
|
||||||
|
const u8 *decorated;
|
||||||
size_t anonymous_id_len = os_strlen(anonymous_id_prefix);
|
size_t anonymous_id_len = os_strlen(anonymous_id_prefix);
|
||||||
|
|
||||||
if (id_len > anonymous_id_len &&
|
if (id_len > anonymous_id_len &&
|
||||||
@ -1226,5 +1241,14 @@ int eap_sim_anonymous_username(const u8 *id, size_t id_len)
|
|||||||
if (id_len > 1 && id[0] == '@')
|
if (id_len > 1 && id[0] == '@')
|
||||||
return 1; /* '@realm' */
|
return 1; /* '@realm' */
|
||||||
|
|
||||||
|
/* RFC 7542 decorated username, for example:
|
||||||
|
* homerealm.example.org!anonymous@otherrealm.example.net */
|
||||||
|
decorated = get_last_char(id, id_len, '!');
|
||||||
|
if (decorated) {
|
||||||
|
decorated++;
|
||||||
|
return eap_sim_anonymous_username(decorated,
|
||||||
|
id + id_len - decorated);
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -451,6 +451,10 @@ static int wpa_supplicant_get_pmk(struct wpa_sm *sm,
|
|||||||
buf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_START,
|
buf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_START,
|
||||||
NULL, 0, &buflen, NULL);
|
NULL, 0, &buflen, NULL);
|
||||||
if (buf) {
|
if (buf) {
|
||||||
|
/* Set and reset eapFail to allow EAP state machine to
|
||||||
|
* proceed with new authentication. */
|
||||||
|
eapol_sm_notify_eap_fail(sm->eapol, true);
|
||||||
|
eapol_sm_notify_eap_fail(sm->eapol, false);
|
||||||
wpa_sm_ether_send(sm, sm->bssid, ETH_P_EAPOL,
|
wpa_sm_ether_send(sm, sm->bssid, ETH_P_EAPOL,
|
||||||
buf, buflen);
|
buf, buflen);
|
||||||
os_free(buf);
|
os_free(buf);
|
||||||
@ -605,8 +609,8 @@ static int wpa_derive_ptk(struct wpa_sm *sm, const unsigned char *src_addr,
|
|||||||
#endif /* CONFIG_OWE */
|
#endif /* CONFIG_OWE */
|
||||||
|
|
||||||
if (sm->force_kdk_derivation ||
|
if (sm->force_kdk_derivation ||
|
||||||
(sm->secure_ltf && sm->ap_rsnxe && sm->ap_rsnxe_len >= 4 &&
|
(sm->secure_ltf &&
|
||||||
sm->ap_rsnxe[3] & BIT(WLAN_RSNX_CAPAB_SECURE_LTF - 8)))
|
ieee802_11_rsnx_capab(sm->ap_rsnxe, WLAN_RSNX_CAPAB_SECURE_LTF)))
|
||||||
kdk_len = WPA_KDK_MAX_LEN;
|
kdk_len = WPA_KDK_MAX_LEN;
|
||||||
else
|
else
|
||||||
kdk_len = 0;
|
kdk_len = 0;
|
||||||
@ -4372,8 +4376,8 @@ int fils_process_auth(struct wpa_sm *sm, const u8 *bssid, const u8 *data,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (sm->force_kdk_derivation ||
|
if (sm->force_kdk_derivation ||
|
||||||
(sm->secure_ltf && sm->ap_rsnxe && sm->ap_rsnxe_len >= 4 &&
|
(sm->secure_ltf &&
|
||||||
sm->ap_rsnxe[3] & BIT(WLAN_RSNX_CAPAB_SECURE_LTF - 8)))
|
ieee802_11_rsnx_capab(sm->ap_rsnxe, WLAN_RSNX_CAPAB_SECURE_LTF)))
|
||||||
kdk_len = WPA_KDK_MAX_LEN;
|
kdk_len = WPA_KDK_MAX_LEN;
|
||||||
else
|
else
|
||||||
kdk_len = 0;
|
kdk_len = 0;
|
||||||
|
@ -69,8 +69,8 @@ int wpa_derive_ptk_ft(struct wpa_sm *sm, const unsigned char *src_addr,
|
|||||||
wpa_ft_pasn_store_r1kh(sm, src_addr);
|
wpa_ft_pasn_store_r1kh(sm, src_addr);
|
||||||
|
|
||||||
if (sm->force_kdk_derivation ||
|
if (sm->force_kdk_derivation ||
|
||||||
(sm->secure_ltf && sm->ap_rsnxe && sm->ap_rsnxe_len >= 4 &&
|
(sm->secure_ltf &&
|
||||||
sm->ap_rsnxe[3] & BIT(WLAN_RSNX_CAPAB_SECURE_LTF - 8)))
|
ieee802_11_rsnx_capab(sm->ap_rsnxe, WLAN_RSNX_CAPAB_SECURE_LTF)))
|
||||||
kdk_len = WPA_KDK_MAX_LEN;
|
kdk_len = WPA_KDK_MAX_LEN;
|
||||||
else
|
else
|
||||||
kdk_len = 0;
|
kdk_len = 0;
|
||||||
@ -672,8 +672,8 @@ int wpa_ft_process_response(struct wpa_sm *sm, const u8 *ies, size_t ies_len,
|
|||||||
wpa_ft_pasn_store_r1kh(sm, bssid);
|
wpa_ft_pasn_store_r1kh(sm, bssid);
|
||||||
|
|
||||||
if (sm->force_kdk_derivation ||
|
if (sm->force_kdk_derivation ||
|
||||||
(sm->secure_ltf && sm->ap_rsnxe && sm->ap_rsnxe_len >= 4 &&
|
(sm->secure_ltf &&
|
||||||
sm->ap_rsnxe[3] & BIT(WLAN_RSNX_CAPAB_SECURE_LTF - 8)))
|
ieee802_11_rsnx_capab(sm->ap_rsnxe, WLAN_RSNX_CAPAB_SECURE_LTF)))
|
||||||
kdk_len = WPA_KDK_MAX_LEN;
|
kdk_len = WPA_KDK_MAX_LEN;
|
||||||
else
|
else
|
||||||
kdk_len = 0;
|
kdk_len = 0;
|
||||||
|
@ -1320,13 +1320,9 @@ static int wps_set_ie(struct wps_registrar *reg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
beacon = wpabuf_alloc(400 + vendor_len);
|
beacon = wpabuf_alloc(400 + vendor_len);
|
||||||
if (beacon == NULL)
|
|
||||||
return -1;
|
|
||||||
probe = wpabuf_alloc(500 + vendor_len);
|
probe = wpabuf_alloc(500 + vendor_len);
|
||||||
if (probe == NULL) {
|
if (!beacon || !probe)
|
||||||
wpabuf_free(beacon);
|
goto fail;
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
auth_macs = wps_authorized_macs(reg, &count);
|
auth_macs = wps_authorized_macs(reg, &count);
|
||||||
|
|
||||||
@ -1342,19 +1338,13 @@ static int wps_set_ie(struct wps_registrar *reg)
|
|||||||
(reg->dualband && wps_build_rf_bands(®->wps->dev, beacon, 0)) ||
|
(reg->dualband && wps_build_rf_bands(®->wps->dev, beacon, 0)) ||
|
||||||
wps_build_wfa_ext(beacon, 0, auth_macs, count, 0) ||
|
wps_build_wfa_ext(beacon, 0, auth_macs, count, 0) ||
|
||||||
wps_build_vendor_ext(®->wps->dev, beacon) ||
|
wps_build_vendor_ext(®->wps->dev, beacon) ||
|
||||||
wps_build_application_ext(®->wps->dev, beacon)) {
|
wps_build_application_ext(®->wps->dev, beacon))
|
||||||
wpabuf_free(beacon);
|
goto fail;
|
||||||
wpabuf_free(probe);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef CONFIG_P2P
|
#ifdef CONFIG_P2P
|
||||||
if (wps_build_dev_name(®->wps->dev, beacon) ||
|
if (wps_build_dev_name(®->wps->dev, beacon) ||
|
||||||
wps_build_primary_dev_type(®->wps->dev, beacon)) {
|
wps_build_primary_dev_type(®->wps->dev, beacon))
|
||||||
wpabuf_free(beacon);
|
goto fail;
|
||||||
wpabuf_free(probe);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
#endif /* CONFIG_P2P */
|
#endif /* CONFIG_P2P */
|
||||||
|
|
||||||
wpa_printf(MSG_DEBUG, "WPS: Build Probe Response IEs");
|
wpa_printf(MSG_DEBUG, "WPS: Build Probe Response IEs");
|
||||||
@ -1373,22 +1363,20 @@ static int wps_set_ie(struct wps_registrar *reg)
|
|||||||
(reg->dualband && wps_build_rf_bands(®->wps->dev, probe, 0)) ||
|
(reg->dualband && wps_build_rf_bands(®->wps->dev, probe, 0)) ||
|
||||||
wps_build_wfa_ext(probe, 0, auth_macs, count, 0) ||
|
wps_build_wfa_ext(probe, 0, auth_macs, count, 0) ||
|
||||||
wps_build_vendor_ext(®->wps->dev, probe) ||
|
wps_build_vendor_ext(®->wps->dev, probe) ||
|
||||||
wps_build_application_ext(®->wps->dev, probe)) {
|
wps_build_application_ext(®->wps->dev, probe))
|
||||||
wpabuf_free(beacon);
|
goto fail;
|
||||||
wpabuf_free(probe);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
beacon = wps_ie_encapsulate(beacon);
|
beacon = wps_ie_encapsulate(beacon);
|
||||||
probe = wps_ie_encapsulate(probe);
|
probe = wps_ie_encapsulate(probe);
|
||||||
|
|
||||||
if (!beacon || !probe) {
|
if (!beacon || !probe)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
return wps_cb_set_ie(reg, beacon, probe);
|
||||||
|
fail:
|
||||||
wpabuf_free(beacon);
|
wpabuf_free(beacon);
|
||||||
wpabuf_free(probe);
|
wpabuf_free(probe);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
|
||||||
|
|
||||||
return wps_cb_set_ie(reg, beacon, probe);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -113,3 +113,4 @@ CONFIG_DPP=y
|
|||||||
CONFIG_DPP2=y
|
CONFIG_DPP2=y
|
||||||
CONFIG_WEP=y
|
CONFIG_WEP=y
|
||||||
CONFIG_PASN=y
|
CONFIG_PASN=y
|
||||||
|
CONFIG_AIRTIME_POLICY=y
|
||||||
|
@ -419,6 +419,12 @@ def dpp_qr_code(self, uri):
|
|||||||
raise Exception("Failed to parse QR Code URI")
|
raise Exception("Failed to parse QR Code URI")
|
||||||
return int(res)
|
return int(res)
|
||||||
|
|
||||||
|
def dpp_nfc_uri(self, uri):
|
||||||
|
res = self.request("DPP_NFC_URI " + uri)
|
||||||
|
if "FAIL" in res:
|
||||||
|
raise Exception("Failed to parse NFC URI")
|
||||||
|
return int(res)
|
||||||
|
|
||||||
def dpp_bootstrap_gen(self, type="qrcode", chan=None, mac=None, info=None,
|
def dpp_bootstrap_gen(self, type="qrcode", chan=None, mac=None, info=None,
|
||||||
curve=None, key=None):
|
curve=None, key=None):
|
||||||
cmd = "DPP_BOOTSTRAP_GEN type=" + type
|
cmd = "DPP_BOOTSTRAP_GEN type=" + type
|
||||||
@ -466,9 +472,13 @@ def dpp_listen(self, freq, netrole=None, qr=None, role=None):
|
|||||||
|
|
||||||
def dpp_auth_init(self, peer=None, uri=None, conf=None, configurator=None,
|
def dpp_auth_init(self, peer=None, uri=None, conf=None, configurator=None,
|
||||||
extra=None, own=None, role=None, neg_freq=None,
|
extra=None, own=None, role=None, neg_freq=None,
|
||||||
ssid=None, passphrase=None, expect_fail=False):
|
ssid=None, passphrase=None, expect_fail=False,
|
||||||
|
conn_status=False, nfc_uri=None):
|
||||||
cmd = "DPP_AUTH_INIT"
|
cmd = "DPP_AUTH_INIT"
|
||||||
if peer is None:
|
if peer is None:
|
||||||
|
if nfc_uri:
|
||||||
|
peer = self.dpp_nfc_uri(nfc_uri)
|
||||||
|
else:
|
||||||
peer = self.dpp_qr_code(uri)
|
peer = self.dpp_qr_code(uri)
|
||||||
cmd += " peer=%d" % peer
|
cmd += " peer=%d" % peer
|
||||||
if own is not None:
|
if own is not None:
|
||||||
@ -487,6 +497,8 @@ def dpp_auth_init(self, peer=None, uri=None, conf=None, configurator=None,
|
|||||||
cmd += " ssid=" + binascii.hexlify(ssid.encode()).decode()
|
cmd += " ssid=" + binascii.hexlify(ssid.encode()).decode()
|
||||||
if passphrase:
|
if passphrase:
|
||||||
cmd += " pass=" + binascii.hexlify(passphrase.encode()).decode()
|
cmd += " pass=" + binascii.hexlify(passphrase.encode()).decode()
|
||||||
|
if conn_status:
|
||||||
|
cmd += " conn_status=1"
|
||||||
res = self.request(cmd)
|
res = self.request(cmd)
|
||||||
if expect_fail:
|
if expect_fail:
|
||||||
if "FAIL" not in res:
|
if "FAIL" not in res:
|
||||||
|
@ -881,6 +881,7 @@ def test_ap_wpa2_eap_sim_ext_anonymous(dev, apdev):
|
|||||||
try:
|
try:
|
||||||
run_ap_wpa2_eap_sim_ext_anonymous(dev, "anonymous@example.org")
|
run_ap_wpa2_eap_sim_ext_anonymous(dev, "anonymous@example.org")
|
||||||
run_ap_wpa2_eap_sim_ext_anonymous(dev, "@example.org")
|
run_ap_wpa2_eap_sim_ext_anonymous(dev, "@example.org")
|
||||||
|
run_ap_wpa2_eap_sim_ext_anonymous(dev, "example.org!anonymous@otherexample.org")
|
||||||
finally:
|
finally:
|
||||||
dev[0].request("SET external_sim 0")
|
dev[0].request("SET external_sim 0")
|
||||||
|
|
||||||
|
@ -137,7 +137,7 @@ def run_roams(dev, apdev, hapd0, hapd1, ssid, passphrase, over_ds=False,
|
|||||||
sae_password_id=None, sae_and_psk=False, pmksa_caching=False,
|
sae_password_id=None, sae_and_psk=False, pmksa_caching=False,
|
||||||
roam_with_reassoc=False, also_non_ft=False, only_one_way=False,
|
roam_with_reassoc=False, also_non_ft=False, only_one_way=False,
|
||||||
wait_before_roam=0, return_after_initial=False, ieee80211w="1",
|
wait_before_roam=0, return_after_initial=False, ieee80211w="1",
|
||||||
sae_transition=False):
|
sae_transition=False, beacon_prot=False):
|
||||||
logger.info("Connect to first AP")
|
logger.info("Connect to first AP")
|
||||||
|
|
||||||
copts = {}
|
copts = {}
|
||||||
@ -151,6 +151,8 @@ def run_roams(dev, apdev, hapd0, hapd1, ssid, passphrase, over_ds=False,
|
|||||||
copts["group_mgmt"] = group_mgmt
|
copts["group_mgmt"] = group_mgmt
|
||||||
if ocv:
|
if ocv:
|
||||||
copts["ocv"] = ocv
|
copts["ocv"] = ocv
|
||||||
|
if beacon_prot:
|
||||||
|
copts["beacon_prot"] = "1"
|
||||||
if eap:
|
if eap:
|
||||||
if pmksa_caching:
|
if pmksa_caching:
|
||||||
copts["ft_eap_pmksa_caching"] = "1"
|
copts["ft_eap_pmksa_caching"] = "1"
|
||||||
@ -221,6 +223,10 @@ def run_roams(dev, apdev, hapd0, hapd1, ssid, passphrase, over_ds=False,
|
|||||||
dev.scan_for_bss(ap2['bssid'], freq="2412")
|
dev.scan_for_bss(ap2['bssid'], freq="2412")
|
||||||
|
|
||||||
for i in range(0, roams):
|
for i in range(0, roams):
|
||||||
|
dev.dump_monitor()
|
||||||
|
hapd1ap.dump_monitor()
|
||||||
|
hapd2ap.dump_monitor()
|
||||||
|
|
||||||
# Roaming artificially fast can make data test fail because the key is
|
# Roaming artificially fast can make data test fail because the key is
|
||||||
# set later.
|
# set later.
|
||||||
time.sleep(0.01)
|
time.sleep(0.01)
|
||||||
@ -239,11 +245,18 @@ def run_roams(dev, apdev, hapd0, hapd1, ssid, passphrase, over_ds=False,
|
|||||||
raise Exception("Did not connect to correct AP")
|
raise Exception("Did not connect to correct AP")
|
||||||
if (i == 0 or i == roams - 1) and test_connectivity:
|
if (i == 0 or i == roams - 1) and test_connectivity:
|
||||||
hapd2ap.wait_sta()
|
hapd2ap.wait_sta()
|
||||||
|
dev.dump_monitor()
|
||||||
|
hapd1ap.dump_monitor()
|
||||||
|
hapd2ap.dump_monitor()
|
||||||
if conndev:
|
if conndev:
|
||||||
hwsim_utils.test_connectivity_iface(dev, hapd2ap, conndev)
|
hwsim_utils.test_connectivity_iface(dev, hapd2ap, conndev)
|
||||||
else:
|
else:
|
||||||
hwsim_utils.test_connectivity(dev, hapd2ap)
|
hwsim_utils.test_connectivity(dev, hapd2ap)
|
||||||
|
|
||||||
|
dev.dump_monitor()
|
||||||
|
hapd1ap.dump_monitor()
|
||||||
|
hapd2ap.dump_monitor()
|
||||||
|
|
||||||
if only_one_way:
|
if only_one_way:
|
||||||
return
|
return
|
||||||
# Roaming artificially fast can make data test fail because the key is
|
# Roaming artificially fast can make data test fail because the key is
|
||||||
@ -262,6 +275,9 @@ def run_roams(dev, apdev, hapd0, hapd1, ssid, passphrase, over_ds=False,
|
|||||||
raise Exception("Did not connect to correct AP")
|
raise Exception("Did not connect to correct AP")
|
||||||
if (i == 0 or i == roams - 1) and test_connectivity:
|
if (i == 0 or i == roams - 1) and test_connectivity:
|
||||||
hapd1ap.wait_sta()
|
hapd1ap.wait_sta()
|
||||||
|
dev.dump_monitor()
|
||||||
|
hapd1ap.dump_monitor()
|
||||||
|
hapd2ap.dump_monitor()
|
||||||
if conndev:
|
if conndev:
|
||||||
hwsim_utils.test_connectivity_iface(dev, hapd1ap, conndev)
|
hwsim_utils.test_connectivity_iface(dev, hapd1ap, conndev)
|
||||||
else:
|
else:
|
||||||
@ -477,15 +493,23 @@ def test_ap_ft_pmf_required_over_ds(dev, apdev):
|
|||||||
"""WPA2-PSK-FT AP with PMF required on STA (over DS)"""
|
"""WPA2-PSK-FT AP with PMF required on STA (over DS)"""
|
||||||
run_ap_ft_pmf(dev, apdev, "2", over_ds=True)
|
run_ap_ft_pmf(dev, apdev, "2", over_ds=True)
|
||||||
|
|
||||||
def run_ap_ft_pmf(dev, apdev, ieee80211w, over_ds=False):
|
def test_ap_ft_pmf_beacon_prot(dev, apdev):
|
||||||
|
"""WPA2-PSK-FT AP with PMF and beacon protection"""
|
||||||
|
run_ap_ft_pmf(dev, apdev, "1", beacon_prot=True)
|
||||||
|
|
||||||
|
def run_ap_ft_pmf(dev, apdev, ieee80211w, over_ds=False, beacon_prot=False):
|
||||||
ssid = "test-ft"
|
ssid = "test-ft"
|
||||||
passphrase = "12345678"
|
passphrase = "12345678"
|
||||||
|
|
||||||
params = ft_params1(ssid=ssid, passphrase=passphrase)
|
params = ft_params1(ssid=ssid, passphrase=passphrase)
|
||||||
params["ieee80211w"] = "2"
|
params["ieee80211w"] = "2"
|
||||||
|
if beacon_prot:
|
||||||
|
params["beacon_prot"] = "1"
|
||||||
hapd0 = hostapd.add_ap(apdev[0], params)
|
hapd0 = hostapd.add_ap(apdev[0], params)
|
||||||
params = ft_params2(ssid=ssid, passphrase=passphrase)
|
params = ft_params2(ssid=ssid, passphrase=passphrase)
|
||||||
params["ieee80211w"] = "2"
|
params["ieee80211w"] = "2"
|
||||||
|
if beacon_prot:
|
||||||
|
params["beacon_prot"] = "1"
|
||||||
hapd1 = hostapd.add_ap(apdev[1], params)
|
hapd1 = hostapd.add_ap(apdev[1], params)
|
||||||
|
|
||||||
Wlantest.setup(hapd0)
|
Wlantest.setup(hapd0)
|
||||||
@ -494,7 +518,7 @@ def run_ap_ft_pmf(dev, apdev, ieee80211w, over_ds=False):
|
|||||||
wt.add_passphrase(passphrase)
|
wt.add_passphrase(passphrase)
|
||||||
|
|
||||||
run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase,
|
run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase,
|
||||||
ieee80211w=ieee80211w, over_ds=over_ds)
|
ieee80211w=ieee80211w, over_ds=over_ds, beacon_prot=beacon_prot)
|
||||||
|
|
||||||
def test_ap_ft_pmf_required_mismatch(dev, apdev):
|
def test_ap_ft_pmf_required_mismatch(dev, apdev):
|
||||||
"""WPA2-PSK-FT AP with PMF required on STA but AP2 not enabling PMF"""
|
"""WPA2-PSK-FT AP with PMF required on STA but AP2 not enabling PMF"""
|
||||||
|
@ -1370,13 +1370,15 @@ def test_ap_ht40_scan_broken_ap(dev, apdev):
|
|||||||
hwsim_utils.test_connectivity(dev[1], hapd2)
|
hwsim_utils.test_connectivity(dev[1], hapd2)
|
||||||
|
|
||||||
def run_op_class(dev, apdev, hw_mode, channel, country, ht_capab, sec_chan,
|
def run_op_class(dev, apdev, hw_mode, channel, country, ht_capab, sec_chan,
|
||||||
freq, opclass):
|
freq, opclass, use_op_class=False):
|
||||||
clear_scan_cache(apdev[0])
|
clear_scan_cache(apdev[0])
|
||||||
try:
|
try:
|
||||||
params = {"ssid": "test-ht40",
|
params = {"ssid": "test-ht40",
|
||||||
"hw_mode": hw_mode,
|
"hw_mode": hw_mode,
|
||||||
"channel": channel,
|
"channel": channel,
|
||||||
"ht_capab": ht_capab}
|
"ht_capab": ht_capab}
|
||||||
|
if use_op_class:
|
||||||
|
params['op_class'] = str(opclass)
|
||||||
if country:
|
if country:
|
||||||
params['country_code'] = country
|
params['country_code'] = country
|
||||||
hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False)
|
hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False)
|
||||||
@ -1397,6 +1399,7 @@ def run_op_class(dev, apdev, hw_mode, channel, country, ht_capab, sec_chan,
|
|||||||
if rx_opclass != opclass:
|
if rx_opclass != opclass:
|
||||||
raise Exception("Unexpected operating class: %d" % rx_opclass)
|
raise Exception("Unexpected operating class: %d" % rx_opclass)
|
||||||
hapd.disable()
|
hapd.disable()
|
||||||
|
hapd.dump_monitor()
|
||||||
dev[0].request("REMOVE_NETWORK all")
|
dev[0].request("REMOVE_NETWORK all")
|
||||||
dev[0].request("ABORT_SCAN")
|
dev[0].request("ABORT_SCAN")
|
||||||
dev[0].wait_disconnected()
|
dev[0].wait_disconnected()
|
||||||
@ -1407,67 +1410,99 @@ def run_op_class(dev, apdev, hw_mode, channel, country, ht_capab, sec_chan,
|
|||||||
|
|
||||||
def test_ap_ht_op_class_81(dev, apdev):
|
def test_ap_ht_op_class_81(dev, apdev):
|
||||||
"""HT20 on operationg class 81"""
|
"""HT20 on operationg class 81"""
|
||||||
run_op_class(dev, apdev, "g", "1", None, "", "0", "2412", 81)
|
for o in [False, True]:
|
||||||
|
run_op_class(dev, apdev, "g", "1", None, "", "0", "2412", 81,
|
||||||
|
use_op_class=o)
|
||||||
|
|
||||||
def test_ap_ht_op_class_83(dev, apdev):
|
def test_ap_ht_op_class_83(dev, apdev):
|
||||||
"""HT40 on operationg class 83"""
|
"""HT40 on operationg class 83"""
|
||||||
run_op_class(dev, apdev, "g", "1", None, "[HT40+]", "1", "2412", 83)
|
for o in [False, True]:
|
||||||
|
run_op_class(dev, apdev, "g", "1", None, "[HT40+]", "1", "2412", 83,
|
||||||
|
use_op_class=o)
|
||||||
|
|
||||||
def test_ap_ht_op_class_84(dev, apdev):
|
def test_ap_ht_op_class_84(dev, apdev):
|
||||||
"""HT40 on operationg class 84"""
|
"""HT40 on operationg class 84"""
|
||||||
run_op_class(dev, apdev, "g", "11", None, "[HT40-]", "-1", "2462", 84)
|
for o in [False, True]:
|
||||||
|
run_op_class(dev, apdev, "g", "11", None, "[HT40-]", "-1", "2462", 84,
|
||||||
|
use_op_class=o)
|
||||||
|
|
||||||
def test_ap_ht_op_class_115(dev, apdev):
|
def test_ap_ht_op_class_115(dev, apdev):
|
||||||
"""HT20 on operationg class 115"""
|
"""HT20 on operationg class 115"""
|
||||||
run_op_class(dev, apdev, "a", "36", "FI", "", "0", "5180", 115)
|
for o in [False, True]:
|
||||||
|
run_op_class(dev, apdev, "a", "36", "FI", "", "0", "5180", 115,
|
||||||
|
use_op_class=o)
|
||||||
|
|
||||||
def test_ap_ht_op_class_116(dev, apdev):
|
def test_ap_ht_op_class_116(dev, apdev):
|
||||||
"""HT40 on operationg class 116"""
|
"""HT40 on operationg class 116"""
|
||||||
run_op_class(dev, apdev, "a", "36", "FI", "[HT40+]", "1", "5180", 116)
|
for o in [False, True]:
|
||||||
|
run_op_class(dev, apdev, "a", "36", "FI", "[HT40+]", "1", "5180", 116,
|
||||||
|
use_op_class=o)
|
||||||
|
|
||||||
def test_ap_ht_op_class_117(dev, apdev):
|
def test_ap_ht_op_class_117(dev, apdev):
|
||||||
"""HT40 on operationg class 117"""
|
"""HT40 on operationg class 117"""
|
||||||
run_op_class(dev, apdev, "a", "40", "FI", "[HT40-]", "-1", "5200", 117)
|
for o in [False, True]:
|
||||||
|
run_op_class(dev, apdev, "a", "40", "FI", "[HT40-]", "-1", "5200", 117,
|
||||||
|
use_op_class=o)
|
||||||
|
|
||||||
def test_ap_ht_op_class_118(dev, apdev):
|
def test_ap_ht_op_class_118(dev, apdev):
|
||||||
"""HT20 on operationg class 118"""
|
"""HT20 on operationg class 118"""
|
||||||
run_op_class(dev, apdev, "a", "60", "RS", "", "0", "5300", 118)
|
for o in [False, True]:
|
||||||
|
run_op_class(dev, apdev, "a", "60", "PA", "", "0", "5300", 118,
|
||||||
|
use_op_class=o)
|
||||||
|
|
||||||
def test_ap_ht_op_class_119(dev, apdev):
|
def test_ap_ht_op_class_119(dev, apdev):
|
||||||
"""HT40 on operationg class 119"""
|
"""HT40 on operationg class 119"""
|
||||||
run_op_class(dev, apdev, "a", "60", "RS", "[HT40+]", "1", "5300", 119)
|
for o in [False, True]:
|
||||||
|
run_op_class(dev, apdev, "a", "60", "PA", "[HT40+]", "1", "5300", 119,
|
||||||
|
use_op_class=o)
|
||||||
|
|
||||||
def test_ap_ht_op_class_120(dev, apdev):
|
def test_ap_ht_op_class_120(dev, apdev):
|
||||||
"""HT40 on operationg class 120"""
|
"""HT40 on operationg class 120"""
|
||||||
run_op_class(dev, apdev, "a", "64", "RS", "[HT40-]", "-1", "5320", 120)
|
for o in [False, True]:
|
||||||
|
run_op_class(dev, apdev, "a", "64", "PA", "[HT40-]", "-1", "5320", 120,
|
||||||
|
use_op_class=o)
|
||||||
|
|
||||||
def test_ap_ht_op_class_121(dev, apdev):
|
def test_ap_ht_op_class_121(dev, apdev):
|
||||||
"""HT20 on operationg class 121"""
|
"""HT20 on operationg class 121"""
|
||||||
run_op_class(dev, apdev, "a", "100", "ZA", "", "0", "5500", 121)
|
for o in [False, True]:
|
||||||
|
run_op_class(dev, apdev, "a", "100", "ZA", "", "0", "5500", 121,
|
||||||
|
use_op_class=o)
|
||||||
|
|
||||||
def test_ap_ht_op_class_122(dev, apdev):
|
def test_ap_ht_op_class_122(dev, apdev):
|
||||||
"""HT40 on operationg class 122"""
|
"""HT40 on operationg class 122"""
|
||||||
run_op_class(dev, apdev, "a", "100", "ZA", "[HT40+]", "1", "5500", 122)
|
for o in [False, True]:
|
||||||
|
run_op_class(dev, apdev, "a", "100", "ZA", "[HT40+]", "1", "5500", 122,
|
||||||
|
use_op_class=o)
|
||||||
|
|
||||||
def test_ap_ht_op_class_123(dev, apdev):
|
def test_ap_ht_op_class_123(dev, apdev):
|
||||||
"""HT40 on operationg class 123"""
|
"""HT40 on operationg class 123"""
|
||||||
run_op_class(dev, apdev, "a", "104", "ZA", "[HT40-]", "-1", "5520", 123)
|
for o in [False, True]:
|
||||||
|
run_op_class(dev, apdev, "a", "104", "ZA", "[HT40-]", "-1", "5520", 123,
|
||||||
|
use_op_class=o)
|
||||||
|
|
||||||
def test_ap_ht_op_class_124(dev, apdev):
|
def test_ap_ht_op_class_124(dev, apdev):
|
||||||
"""HT20 on operationg class 124"""
|
"""HT20 on operationg class 124"""
|
||||||
run_op_class(dev, apdev, "a", "149", "US", "", "0", "5745", 124)
|
for o in [False, True]:
|
||||||
|
run_op_class(dev, apdev, "a", "149", "US", "", "0", "5745", 124,
|
||||||
|
use_op_class=o)
|
||||||
|
|
||||||
def test_ap_ht_op_class_125(dev, apdev):
|
def test_ap_ht_op_class_125(dev, apdev):
|
||||||
"""HT20 on operationg class 125"""
|
"""HT20 on operationg class 125"""
|
||||||
run_op_class(dev, apdev, "a", "169", "NL", "", "0", "5845", 125)
|
for o in [False, True]:
|
||||||
|
run_op_class(dev, apdev, "a", "169", "NL", "", "0", "5845", 125,
|
||||||
|
use_op_class=o)
|
||||||
|
|
||||||
def test_ap_ht_op_class_126(dev, apdev):
|
def test_ap_ht_op_class_126(dev, apdev):
|
||||||
"""HT40 on operationg class 126"""
|
"""HT40 on operationg class 126"""
|
||||||
run_op_class(dev, apdev, "a", "149", "US", "[HT40+]", "1", "5745", 126)
|
for o in [False, True]:
|
||||||
|
run_op_class(dev, apdev, "a", "149", "US", "[HT40+]", "1", "5745", 126,
|
||||||
|
use_op_class=o)
|
||||||
|
|
||||||
def test_ap_ht_op_class_127(dev, apdev):
|
def test_ap_ht_op_class_127(dev, apdev):
|
||||||
"""HT40 on operationg class 127"""
|
"""HT40 on operationg class 127"""
|
||||||
run_op_class(dev, apdev, "a", "153", "US", "[HT40-]", "-1", "5765", 127)
|
for o in [False, True]:
|
||||||
|
run_op_class(dev, apdev, "a", "153", "US", "[HT40-]", "-1", "5765", 127,
|
||||||
|
use_op_class=o)
|
||||||
|
|
||||||
def test_ap_ht40_plus_minus1(dev, apdev):
|
def test_ap_ht40_plus_minus1(dev, apdev):
|
||||||
"""HT40 with both plus and minus allowed (1)"""
|
"""HT40 with both plus and minus allowed (1)"""
|
||||||
|
@ -909,3 +909,64 @@ def test_ap_notify_mgmt_frames_disabled(dev, apdev):
|
|||||||
ev = hapd.wait_event(["AP-MGMT-FRAME-RECEIVED"], timeout=0.1)
|
ev = hapd.wait_event(["AP-MGMT-FRAME-RECEIVED"], timeout=0.1)
|
||||||
if ev is not None:
|
if ev is not None:
|
||||||
raise Exception("Unexpected AP-MGMT-FRAME-RECEIVED")
|
raise Exception("Unexpected AP-MGMT-FRAME-RECEIVED")
|
||||||
|
|
||||||
|
def test_ap_airtime_policy_static(dev, apdev):
|
||||||
|
"""Airtime policy - static"""
|
||||||
|
ssid = "test-wpa2-psk"
|
||||||
|
passphrase = 'qwertyuiop'
|
||||||
|
params = hostapd.wpa2_params(ssid=ssid, passphrase=passphrase)
|
||||||
|
params['airtime_mode'] = "1"
|
||||||
|
params['airtime_update_interval'] = "200"
|
||||||
|
params['airtime_sta_weight'] = dev[0].own_addr() + " 512"
|
||||||
|
hapd = hostapd.add_ap(apdev[0], params)
|
||||||
|
dev[0].connect(ssid, psk=passphrase, scan_freq="2412")
|
||||||
|
dev[1].connect(ssid, psk=passphrase, scan_freq="2412")
|
||||||
|
time.sleep(1)
|
||||||
|
|
||||||
|
def test_ap_airtime_policy_per_bss_dynamic(dev, apdev):
|
||||||
|
"""Airtime policy - per-BSS dynamic"""
|
||||||
|
ssid = "test-wpa2-psk"
|
||||||
|
passphrase = 'qwertyuiop'
|
||||||
|
params = hostapd.wpa2_params(ssid=ssid, passphrase=passphrase)
|
||||||
|
params['airtime_mode'] = "2"
|
||||||
|
params['airtime_update_interval'] = "200"
|
||||||
|
params['airtime_bss_weight'] = "2"
|
||||||
|
hapd = hostapd.add_ap(apdev[0], params)
|
||||||
|
dev[0].connect(ssid, psk=passphrase, scan_freq="2412")
|
||||||
|
dev[1].connect(ssid, psk=passphrase, scan_freq="2412")
|
||||||
|
time.sleep(1)
|
||||||
|
|
||||||
|
def test_ap_airtime_policy_per_bss_limit(dev, apdev):
|
||||||
|
"""Airtime policy - per-BSS limit"""
|
||||||
|
ssid = "test-wpa2-psk"
|
||||||
|
passphrase = 'qwertyuiop'
|
||||||
|
params = hostapd.wpa2_params(ssid=ssid, passphrase=passphrase)
|
||||||
|
params['airtime_mode'] = "3"
|
||||||
|
params['airtime_update_interval'] = "200"
|
||||||
|
params['airtime_bss_weight'] = "2"
|
||||||
|
params['airtime_bss_limit'] = "1"
|
||||||
|
hapd = hostapd.add_ap(apdev[0], params)
|
||||||
|
dev[0].connect(ssid, psk=passphrase, scan_freq="2412")
|
||||||
|
dev[1].connect(ssid, psk=passphrase, scan_freq="2412")
|
||||||
|
time.sleep(1)
|
||||||
|
hapd.set("force_backlog_bytes", "1")
|
||||||
|
time.sleep(1)
|
||||||
|
|
||||||
|
def test_ap_airtime_policy_per_bss_limit_invalid(dev, apdev):
|
||||||
|
"""Airtime policy - per-BSS limit (invalid)"""
|
||||||
|
ssid = "test-wpa2-psk"
|
||||||
|
passphrase = 'qwertyuiop'
|
||||||
|
params = hostapd.wpa2_params(ssid=ssid, passphrase=passphrase)
|
||||||
|
params['airtime_mode'] = "3"
|
||||||
|
params['airtime_update_interval'] = "0"
|
||||||
|
params['airtime_bss_weight'] = "2"
|
||||||
|
params['airtime_bss_limit'] = "1"
|
||||||
|
hapd = hostapd.add_ap(apdev[0], params, no_enable=True)
|
||||||
|
if "FAIL" not in hapd.request("ENABLE"):
|
||||||
|
raise Exception("Invalid airtime policy configuration accepted")
|
||||||
|
hapd.set("airtime_update_interval", "200")
|
||||||
|
hapd.enable()
|
||||||
|
hapd.set("airtime_update_interval", "0")
|
||||||
|
dev[0].connect(ssid, psk=passphrase, scan_freq="2412")
|
||||||
|
dev[1].connect(ssid, psk=passphrase, scan_freq="2412")
|
||||||
|
time.sleep(1)
|
||||||
|
@ -500,6 +500,22 @@ def test_ap_wpa2_gtk_rekey_request(dev, apdev):
|
|||||||
raise Exception("GTK rekey timed out")
|
raise Exception("GTK rekey timed out")
|
||||||
hwsim_utils.test_connectivity(dev[0], hapd)
|
hwsim_utils.test_connectivity(dev[0], hapd)
|
||||||
|
|
||||||
|
def test_ap_wpa2_gtk_rekey_failure(dev, apdev):
|
||||||
|
"""WPA2-PSK AP and GTK rekey failure"""
|
||||||
|
ssid = "test-wpa2-psk"
|
||||||
|
passphrase = 'qwertyuiop'
|
||||||
|
params = hostapd.wpa2_params(ssid=ssid, passphrase=passphrase)
|
||||||
|
hapd = hostapd.add_ap(apdev[0], params)
|
||||||
|
dev[0].connect(ssid, psk=passphrase, scan_freq="2412")
|
||||||
|
with fail_test(hapd, 1, "wpa_group_config_group_keys"):
|
||||||
|
if "OK" not in hapd.request("REKEY_GTK"):
|
||||||
|
raise Exception("REKEY_GTK failed")
|
||||||
|
wait_fail_trigger(hapd, "GET_FAIL")
|
||||||
|
ev = dev[0].wait_event(["WPA: Group rekeying completed"], timeout=2)
|
||||||
|
if ev is None:
|
||||||
|
raise Exception("GTK rekey timed out")
|
||||||
|
dev[0].wait_disconnected()
|
||||||
|
|
||||||
@remote_compatible
|
@remote_compatible
|
||||||
def test_ap_wpa_gtk_rekey(dev, apdev):
|
def test_ap_wpa_gtk_rekey(dev, apdev):
|
||||||
"""WPA-PSK/TKIP AP and GTK rekey enforced by AP"""
|
"""WPA-PSK/TKIP AP and GTK rekey enforced by AP"""
|
||||||
|
@ -403,3 +403,35 @@ def _test_ap_track_taxonomy(dev, apdev):
|
|||||||
raise Exception("Unexpected SIGNATURE prefix")
|
raise Exception("Unexpected SIGNATURE prefix")
|
||||||
if "|assoc:" not in res:
|
if "|assoc:" not in res:
|
||||||
raise Exception("Missing assoc info in SIGNATURE")
|
raise Exception("Missing assoc info in SIGNATURE")
|
||||||
|
|
||||||
|
def test_ap_track_taxonomy_5g(dev, apdev):
|
||||||
|
"""AP tracking STA taxonomy (5 GHz)"""
|
||||||
|
try:
|
||||||
|
_test_ap_track_taxonomy_5g(dev, apdev)
|
||||||
|
finally:
|
||||||
|
subprocess.call(['iw', 'reg', 'set', '00'])
|
||||||
|
dev[0].flush_scan_cache()
|
||||||
|
|
||||||
|
def _test_ap_track_taxonomy_5g(dev, apdev):
|
||||||
|
params = {"ssid": "track",
|
||||||
|
"country_code": "US",
|
||||||
|
"hw_mode": "a",
|
||||||
|
"channel": "40",
|
||||||
|
"track_sta_max_num": "2"}
|
||||||
|
hapd = hostapd.add_ap(apdev[0], params)
|
||||||
|
bssid = apdev[0]['bssid']
|
||||||
|
|
||||||
|
dev[0].scan_for_bss(bssid, freq=5200, force_scan=True)
|
||||||
|
addr0 = dev[0].own_addr()
|
||||||
|
dev[0].connect("track", key_mgmt="NONE", scan_freq="5200")
|
||||||
|
|
||||||
|
res = hapd.request("SIGNATURE " + addr0)
|
||||||
|
logger.info("sta0: " + res)
|
||||||
|
if not res.startswith("wifi4|probe:"):
|
||||||
|
raise Exception("Unexpected SIGNATURE prefix")
|
||||||
|
if "|assoc:" not in res:
|
||||||
|
raise Exception("Missing assoc info in SIGNATURE")
|
||||||
|
if ",htcap:" not in res:
|
||||||
|
raise Exception("Missing HT info in SIGNATURE")
|
||||||
|
if ",vhtcap:" not in res:
|
||||||
|
raise Exception("Missing VHT info in SIGNATURE")
|
||||||
|
@ -44,10 +44,12 @@
|
|||||||
from utils import *
|
from utils import *
|
||||||
from test_ap_eap import int_eap_server_params
|
from test_ap_eap import int_eap_server_params
|
||||||
|
|
||||||
def wps_start_ap(apdev, ssid="test-wps-conf"):
|
def wps_start_ap(apdev, ssid="test-wps-conf", extra_cred=None):
|
||||||
params = {"ssid": ssid, "eap_server": "1", "wps_state": "2",
|
params = {"ssid": ssid, "eap_server": "1", "wps_state": "2",
|
||||||
"wpa_passphrase": "12345678", "wpa": "2",
|
"wpa_passphrase": "12345678", "wpa": "2",
|
||||||
"wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP"}
|
"wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP"}
|
||||||
|
if extra_cred:
|
||||||
|
params['extra_cred'] = extra_cred
|
||||||
return hostapd.add_ap(apdev, params)
|
return hostapd.add_ap(apdev, params)
|
||||||
|
|
||||||
@remote_compatible
|
@remote_compatible
|
||||||
@ -1067,6 +1069,43 @@ def test_ap_wps_pbc_overlap_2sta(dev, apdev):
|
|||||||
dev[0].flush_scan_cache()
|
dev[0].flush_scan_cache()
|
||||||
dev[1].flush_scan_cache()
|
dev[1].flush_scan_cache()
|
||||||
|
|
||||||
|
def test_ap_wps_pbc_session_workaround(dev, apdev):
|
||||||
|
"""WPS PBC session overlap workaround"""
|
||||||
|
ssid = "test-wps-pbc-overlap"
|
||||||
|
hapd = hostapd.add_ap(apdev[0],
|
||||||
|
{"ssid": ssid, "eap_server": "1", "wps_state": "2",
|
||||||
|
"wpa_passphrase": "12345678", "wpa": "2",
|
||||||
|
"wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP"})
|
||||||
|
bssid = hapd.own_addr()
|
||||||
|
hapd.request("WPS_PBC")
|
||||||
|
dev[0].scan_for_bss(bssid, freq="2412")
|
||||||
|
dev[0].request("WPS_PBC " + bssid)
|
||||||
|
dev[0].wait_connected(timeout=30)
|
||||||
|
|
||||||
|
dev[0].request("REMOVE_NETWORK all")
|
||||||
|
dev[0].wait_disconnected(timeout=30)
|
||||||
|
dev[0].dump_monitor()
|
||||||
|
# Trigger AP/Registrar to ignore PBC activation immediately after
|
||||||
|
# successfully completed provisioning
|
||||||
|
dev[0].request("WPS_PBC " + bssid)
|
||||||
|
ev = dev[0].wait_event(["CTRL-EVENT-SCAN-RESULTS"], timeout=10)
|
||||||
|
if ev is None:
|
||||||
|
raise Exception("No scan results reported")
|
||||||
|
dev[0].request("WPS_CANCEL")
|
||||||
|
dev[0].dump_monitor()
|
||||||
|
|
||||||
|
# Verify that PBC session overlap does not prevent connection
|
||||||
|
hapd.request("WPS_PBC")
|
||||||
|
dev[1].scan_for_bss(bssid, freq="2412")
|
||||||
|
dev[1].request("WPS_PBC " + bssid)
|
||||||
|
dev[1].wait_connected()
|
||||||
|
dev[1].request("REMOVE_NETWORK all")
|
||||||
|
dev[1].wait_disconnected()
|
||||||
|
|
||||||
|
hapd.request("DISABLE")
|
||||||
|
dev[0].flush_scan_cache()
|
||||||
|
dev[1].flush_scan_cache()
|
||||||
|
|
||||||
@remote_compatible
|
@remote_compatible
|
||||||
def test_ap_wps_cancel(dev, apdev):
|
def test_ap_wps_cancel(dev, apdev):
|
||||||
"""WPS AP cancelling enabled config method"""
|
"""WPS AP cancelling enabled config method"""
|
||||||
@ -4358,10 +4397,12 @@ def wps_er_stop(dev, sock, server, on_alloc_fail=False):
|
|||||||
raise Exception("No WPS-ER-AP-REMOVE event on max-age timeout")
|
raise Exception("No WPS-ER-AP-REMOVE event on max-age timeout")
|
||||||
dev.request("WPS_ER_STOP")
|
dev.request("WPS_ER_STOP")
|
||||||
|
|
||||||
def run_wps_er_proto_test(dev, handler, no_event_url=False, location_url=None):
|
def run_wps_er_proto_test(dev, handler, no_event_url=False, location_url=None,
|
||||||
|
max_age=1):
|
||||||
try:
|
try:
|
||||||
uuid = '27ea801a-9e5c-4e73-bd82-f89cbcd10d7e'
|
uuid = '27ea801a-9e5c-4e73-bd82-f89cbcd10d7e'
|
||||||
server, sock = wps_er_start(dev, handler, location_url=location_url)
|
server, sock = wps_er_start(dev, handler, location_url=location_url,
|
||||||
|
max_age=max_age)
|
||||||
global wps_event_url
|
global wps_event_url
|
||||||
wps_event_url = None
|
wps_event_url = None
|
||||||
server.handle_request()
|
server.handle_request()
|
||||||
@ -5105,6 +5146,15 @@ def handle_upnp_info(self):
|
|||||||
run_wps_er_proto_test(dev[0], WPSAPHTTPServer_req_as_resp,
|
run_wps_er_proto_test(dev[0], WPSAPHTTPServer_req_as_resp,
|
||||||
no_event_url=True)
|
no_event_url=True)
|
||||||
|
|
||||||
|
def test_ap_wps_er_http_client_timeout(dev, apdev):
|
||||||
|
"""WPS ER and HTTP client timeout"""
|
||||||
|
class WPSAPHTTPServer_timeout(WPSAPHTTPServer):
|
||||||
|
def handle_upnp_info(self):
|
||||||
|
time.sleep(31)
|
||||||
|
self.wfile.write(b"GET / HTTP/1.1\r\n\r\n")
|
||||||
|
run_wps_er_proto_test(dev[0], WPSAPHTTPServer_timeout,
|
||||||
|
no_event_url=True, max_age=60)
|
||||||
|
|
||||||
def test_ap_wps_init_oom(dev, apdev):
|
def test_ap_wps_init_oom(dev, apdev):
|
||||||
"""wps_init OOM cases"""
|
"""wps_init OOM cases"""
|
||||||
ssid = "test-wps"
|
ssid = "test-wps"
|
||||||
@ -10464,3 +10514,55 @@ def run_ap_wps_ap_timeout(dev, apdev, cmd):
|
|||||||
logger.info("BSS after timeout: " + str(bss))
|
logger.info("BSS after timeout: " + str(bss))
|
||||||
if bss['ie'].endswith("0106ffffffffffff"):
|
if bss['ie'].endswith("0106ffffffffffff"):
|
||||||
raise Exception("Authorized MAC not removed")
|
raise Exception("Authorized MAC not removed")
|
||||||
|
|
||||||
|
def test_ap_wps_er_unsubscribe_errors(dev, apdev):
|
||||||
|
"""WPS ER and UNSUBSCRIBE errors"""
|
||||||
|
start_wps_ap(apdev[0])
|
||||||
|
tests = [(1, "http_client_url_parse;wps_er_ap_unsubscribe"),
|
||||||
|
(1, "wpabuf_alloc;wps_er_ap_unsubscribe"),
|
||||||
|
(1, "http_client_addr;wps_er_ap_unsubscribe")]
|
||||||
|
try:
|
||||||
|
for count, func in tests:
|
||||||
|
start_wps_er(dev[0])
|
||||||
|
with alloc_fail(dev[0], count, func):
|
||||||
|
dev[0].request("WPS_ER_STOP")
|
||||||
|
dev[0].request("REMOVE_NETWORK all")
|
||||||
|
dev[0].wait_disconnected()
|
||||||
|
dev[0].dump_monitor()
|
||||||
|
finally:
|
||||||
|
dev[0].request("WPS_ER_STOP")
|
||||||
|
|
||||||
|
def start_wps_ap(apdev):
|
||||||
|
ssid = "wps-er-ap-config"
|
||||||
|
ap_pin = "12345670"
|
||||||
|
ap_uuid = "27ea801a-9e5c-4e73-bd82-f89cbcd10d7e"
|
||||||
|
params = {"ssid": ssid, "eap_server": "1", "wps_state": "2",
|
||||||
|
"wpa_passphrase": "12345678", "wpa": "2",
|
||||||
|
"wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP",
|
||||||
|
"device_name": "Wireless AP", "manufacturer": "Company",
|
||||||
|
"model_name": "WAP", "model_number": "123",
|
||||||
|
"serial_number": "12345", "device_type": "6-0050F204-1",
|
||||||
|
"os_version": "01020300",
|
||||||
|
"config_methods": "label push_button",
|
||||||
|
"ap_pin": ap_pin, "uuid": ap_uuid, "upnp_iface": "lo"}
|
||||||
|
hostapd.add_ap(apdev, params)
|
||||||
|
|
||||||
|
def start_wps_er(dev):
|
||||||
|
ssid = "wps-er-ap-config"
|
||||||
|
dev.connect(ssid, psk="12345678", scan_freq="2412")
|
||||||
|
dev.request("WPS_ER_START ifname=lo")
|
||||||
|
ev = dev.wait_event(["WPS-ER-AP-ADD"], timeout=15)
|
||||||
|
if ev is None:
|
||||||
|
raise Exception("AP discovery timed out")
|
||||||
|
|
||||||
|
def test_ap_wps_registrar_init_errors(dev, apdev):
|
||||||
|
"""WPS Registrar init errors"""
|
||||||
|
hapd = wps_start_ap(apdev[0], extra_cred="wps-mixed-cred")
|
||||||
|
hapd.disable()
|
||||||
|
tests = [(1, "wps_registrar_init"),
|
||||||
|
(1, "wpabuf_alloc_copy;wps_registrar_init"),
|
||||||
|
(1, "wps_set_ie;wps_registrar_init")]
|
||||||
|
for count, func in tests:
|
||||||
|
with alloc_fail(hapd, count, func):
|
||||||
|
if "FAIL" not in hapd.request("ENABLE"):
|
||||||
|
raise Exception("ENABLE succeeded unexpectedly")
|
||||||
|
@ -2581,6 +2581,14 @@ def test_dpp_pkex_hostapd_errors(dev, apdev):
|
|||||||
|
|
||||||
def test_dpp_hostapd_configurator(dev, apdev):
|
def test_dpp_hostapd_configurator(dev, apdev):
|
||||||
"""DPP with hostapd as configurator/initiator"""
|
"""DPP with hostapd as configurator/initiator"""
|
||||||
|
run_dpp_hostapd_configurator(dev, apdev)
|
||||||
|
|
||||||
|
def test_dpp_hostapd_configurator_enrollee_v1(dev, apdev):
|
||||||
|
"""DPP with hostapd as configurator/initiator with v1 enrollee"""
|
||||||
|
dev[0].set("dpp_version_override", "1")
|
||||||
|
run_dpp_hostapd_configurator(dev, apdev)
|
||||||
|
|
||||||
|
def run_dpp_hostapd_configurator(dev, apdev):
|
||||||
check_dpp_capab(dev[0])
|
check_dpp_capab(dev[0])
|
||||||
hapd = hostapd.add_ap(apdev[0], {"ssid": "unconfigured",
|
hapd = hostapd.add_ap(apdev[0], {"ssid": "unconfigured",
|
||||||
"channel": "1"})
|
"channel": "1"})
|
||||||
@ -2640,6 +2648,340 @@ def test_dpp_hostapd_configurator_fragmentation(dev, apdev):
|
|||||||
wait_auth_success(dev[0], hapd, configurator=hapd, enrollee=dev[0],
|
wait_auth_success(dev[0], hapd, configurator=hapd, enrollee=dev[0],
|
||||||
stop_responder=True)
|
stop_responder=True)
|
||||||
|
|
||||||
|
def test_dpp_hostapd_enrollee_fragmentation(dev, apdev):
|
||||||
|
"""DPP and hostapd as Enrollee with GAS fragmentation"""
|
||||||
|
check_dpp_capab(dev[0])
|
||||||
|
hapd = hostapd.add_ap(apdev[0], {"ssid": "unconfigured",
|
||||||
|
"channel": "6"})
|
||||||
|
check_dpp_capab(hapd)
|
||||||
|
conf_id = dev[0].dpp_configurator_add()
|
||||||
|
id0 = dev[0].dpp_bootstrap_gen(chan="81/6", mac=True)
|
||||||
|
uri0 = dev[0].request("DPP_BOOTSTRAP_GET_URI %d" % id0)
|
||||||
|
conf = '{"wi-fi_tech":"infra", "discovery":{"ssid":"test"},"cred":{"akm":"psk","pass":"secret passphrase"}}' + 3000*' '
|
||||||
|
dev[0].set("dpp_config_obj_override", conf)
|
||||||
|
dev[0].set("dpp_configurator_params",
|
||||||
|
" conf=ap-dpp configurator=%d" % conf_id)
|
||||||
|
dev[0].dpp_listen(2437, role="configurator")
|
||||||
|
hapd.dpp_auth_init(uri=uri0, role="enrollee")
|
||||||
|
wait_auth_success(dev[0], hapd, configurator=dev[0], enrollee=hapd,
|
||||||
|
stop_responder=True)
|
||||||
|
|
||||||
|
def test_dpp_hostapd_enrollee_gas_timeout(dev, apdev):
|
||||||
|
"""DPP and hostapd as Enrollee with GAS timeout"""
|
||||||
|
check_dpp_capab(dev[0])
|
||||||
|
hapd = hostapd.add_ap(apdev[0], {"ssid": "unconfigured",
|
||||||
|
"channel": "6"})
|
||||||
|
check_dpp_capab(hapd)
|
||||||
|
conf_id = dev[0].dpp_configurator_add()
|
||||||
|
id0 = dev[0].dpp_bootstrap_gen(chan="81/6", mac=True)
|
||||||
|
uri0 = dev[0].request("DPP_BOOTSTRAP_GET_URI %d" % id0)
|
||||||
|
conf = '{"wi-fi_tech":"infra", "discovery":{"ssid":"test"},"cred":{"akm":"psk","pass":"secret passphrase"}}' + 3000*' '
|
||||||
|
dev[0].set("dpp_config_obj_override", conf)
|
||||||
|
dev[0].set("dpp_configurator_params",
|
||||||
|
"conf=ap-dpp configurator=%d" % conf_id)
|
||||||
|
dev[0].set("ext_mgmt_frame_handling", "1")
|
||||||
|
dev[0].dpp_listen(2437, role="configurator")
|
||||||
|
hapd.dpp_auth_init(uri=uri0, role="enrollee")
|
||||||
|
process_dpp_frames(dev[0])
|
||||||
|
ev = hapd.wait_event(["GAS-QUERY-DONE"], timeout=10)
|
||||||
|
if "result=TIMEOUT" not in ev:
|
||||||
|
raise Exception("GAS timeout not reported")
|
||||||
|
|
||||||
|
def test_dpp_hostapd_enrollee_gas_timeout_comeback(dev, apdev):
|
||||||
|
"""DPP and hostapd as Enrollee with GAS timeout during comeback"""
|
||||||
|
check_dpp_capab(dev[0])
|
||||||
|
hapd = hostapd.add_ap(apdev[0], {"ssid": "unconfigured",
|
||||||
|
"channel": "6"})
|
||||||
|
check_dpp_capab(hapd)
|
||||||
|
conf_id = dev[0].dpp_configurator_add()
|
||||||
|
id0 = dev[0].dpp_bootstrap_gen(chan="81/6", mac=True)
|
||||||
|
uri0 = dev[0].request("DPP_BOOTSTRAP_GET_URI %d" % id0)
|
||||||
|
conf = '{"wi-fi_tech":"infra", "discovery":{"ssid":"test"},"cred":{"akm":"psk","pass":"secret passphrase"}}' + 3000*' '
|
||||||
|
dev[0].set("dpp_config_obj_override", conf)
|
||||||
|
dev[0].set("dpp_configurator_params",
|
||||||
|
"conf=ap-dpp configurator=%d" % conf_id)
|
||||||
|
dev[0].set("ext_mgmt_frame_handling", "1")
|
||||||
|
dev[0].dpp_listen(2437, role="configurator")
|
||||||
|
hapd.dpp_auth_init(uri=uri0, role="enrollee")
|
||||||
|
process_dpp_frames(dev[0], count=4)
|
||||||
|
ev = hapd.wait_event(["GAS-QUERY-DONE"], timeout=10)
|
||||||
|
if "result=TIMEOUT" not in ev:
|
||||||
|
raise Exception("GAS timeout not reported")
|
||||||
|
|
||||||
|
def process_dpp_frames(dev, count=3):
|
||||||
|
for i in range(count):
|
||||||
|
msg = dev.mgmt_rx()
|
||||||
|
cmd = "MGMT_RX_PROCESS freq={} datarate={} ssi_signal={} frame={}".format(msg['freq'], msg['datarate'], msg['ssi_signal'], binascii.hexlify(msg['frame']).decode())
|
||||||
|
if "OK" not in dev.request(cmd):
|
||||||
|
raise Exception("MGMT_RX_PROCESS failed")
|
||||||
|
|
||||||
|
def test_dpp_hostapd_enrollee_gas_errors(dev, apdev):
|
||||||
|
"""DPP and hostapd as Enrollee with GAS query local errors"""
|
||||||
|
check_dpp_capab(dev[0])
|
||||||
|
hapd = hostapd.add_ap(apdev[0], {"ssid": "unconfigured",
|
||||||
|
"channel": "6"})
|
||||||
|
check_dpp_capab(hapd)
|
||||||
|
conf_id = dev[0].dpp_configurator_add()
|
||||||
|
id0 = dev[0].dpp_bootstrap_gen(chan="81/6", mac=True)
|
||||||
|
uri0 = dev[0].request("DPP_BOOTSTRAP_GET_URI %d" % id0)
|
||||||
|
dev[0].set("dpp_configurator_params",
|
||||||
|
"conf=ap-dpp configurator=%d" % conf_id)
|
||||||
|
dev[0].set("ext_mgmt_frame_handling", "1")
|
||||||
|
|
||||||
|
# GAS without comeback
|
||||||
|
tests = [(1, "gas_query_append;gas_query_rx_initial", 3, True),
|
||||||
|
(1, "gas_query_rx_initial", 3, True),
|
||||||
|
(1, "gas_query_tx_initial_req", 2, True),
|
||||||
|
(1, "gas_query_ap_req", 2, False)]
|
||||||
|
for count, func, frame_count, wait_ev in tests:
|
||||||
|
dev[0].request("DPP_STOP_LISTEN")
|
||||||
|
dev[0].dpp_listen(2437, role="configurator")
|
||||||
|
dev[0].dump_monitor()
|
||||||
|
hapd.dump_monitor()
|
||||||
|
with alloc_fail(hapd, count, func):
|
||||||
|
hapd.dpp_auth_init(uri=uri0, role="enrollee")
|
||||||
|
process_dpp_frames(dev[0], count=frame_count)
|
||||||
|
if wait_ev:
|
||||||
|
ev = hapd.wait_event(["GAS-QUERY-DONE"], timeout=10)
|
||||||
|
if not ev or "result=INTERNAL_ERROR" not in ev:
|
||||||
|
raise Exception("Unexpect GAS query result: " + str(ev))
|
||||||
|
|
||||||
|
# GAS with comeback
|
||||||
|
conf = '{"wi-fi_tech":"infra", "discovery":{"ssid":"test"},"cred":{"akm":"psk","pass":"secret passphrase"}}' + 3000*' '
|
||||||
|
dev[0].set("dpp_config_obj_override", conf)
|
||||||
|
|
||||||
|
tests = [(1, "gas_query_append;gas_query_rx_comeback", 4),
|
||||||
|
(1, "wpabuf_alloc;gas_query_tx_comeback_req", 3),
|
||||||
|
(1, "hostapd_drv_send_action;gas_query_tx_comeback_req", 3)]
|
||||||
|
for count, func, frame_count in tests:
|
||||||
|
dev[0].request("DPP_STOP_LISTEN")
|
||||||
|
dev[0].dpp_listen(2437, role="configurator")
|
||||||
|
dev[0].dump_monitor()
|
||||||
|
hapd.dump_monitor()
|
||||||
|
with alloc_fail(hapd, count, func):
|
||||||
|
hapd.dpp_auth_init(uri=uri0, role="enrollee")
|
||||||
|
process_dpp_frames(dev[0], count=frame_count)
|
||||||
|
ev = hapd.wait_event(["GAS-QUERY-DONE"], timeout=10)
|
||||||
|
if not ev or "result=INTERNAL_ERROR" not in ev:
|
||||||
|
raise Exception("Unexpect GAS query result: " + str(ev))
|
||||||
|
|
||||||
|
def test_dpp_hostapd_enrollee_gas_proto(dev, apdev):
|
||||||
|
"""DPP and hostapd as Enrollee with GAS query protocol testing"""
|
||||||
|
check_dpp_capab(dev[0])
|
||||||
|
hapd = hostapd.add_ap(apdev[0], {"ssid": "unconfigured",
|
||||||
|
"channel": "6"})
|
||||||
|
check_dpp_capab(hapd)
|
||||||
|
bssid = hapd.own_addr()
|
||||||
|
conf_id = dev[0].dpp_configurator_add()
|
||||||
|
id0 = dev[0].dpp_bootstrap_gen(chan="81/6", mac=True)
|
||||||
|
uri0 = dev[0].request("DPP_BOOTSTRAP_GET_URI %d" % id0)
|
||||||
|
dev[0].set("dpp_configurator_params",
|
||||||
|
"conf=ap-dpp configurator=%d" % conf_id)
|
||||||
|
conf = '{"wi-fi_tech":"infra", "discovery":{"ssid":"test"},"cred":{"akm":"psk","pass":"secret passphrase"}}' + 3000*' '
|
||||||
|
dev[0].set("dpp_config_obj_override", conf)
|
||||||
|
dev[0].set("ext_mgmt_frame_handling", "1")
|
||||||
|
dev[0].dpp_listen(2437, role="configurator")
|
||||||
|
hapd.dpp_auth_init(uri=uri0, role="enrollee")
|
||||||
|
process_dpp_frames(dev[0], count=3)
|
||||||
|
msg = dev[0].mgmt_rx()
|
||||||
|
payload = msg['payload']
|
||||||
|
dialog_token, = struct.unpack('B', payload[2:3])
|
||||||
|
hdr = struct.pack('<BBBHBH', 4, 13, dialog_token, 0, 0x80, 0)
|
||||||
|
# GAS: Advertisement Protocol changed between initial and comeback response from 02:00:00:00:00:00
|
||||||
|
adv_proto = "6c087fdd05506f9a1a02"
|
||||||
|
action = binascii.hexlify(hdr).decode() + adv_proto + "0300" + "001001"
|
||||||
|
cmd = "MGMT_TX %s %s freq=2437 wait_time=100 action=%s" % (bssid, bssid, action)
|
||||||
|
dev[0].request(cmd)
|
||||||
|
ev = hapd.wait_event(["GAS-QUERY-DONE"], timeout=10)
|
||||||
|
if not ev or "result=PEER_ERROR" not in ev:
|
||||||
|
raise Exception("Unexpect GAS query result: " + str(ev))
|
||||||
|
dev[0].request("DPP_STOP_LISTEN")
|
||||||
|
hapd.dump_monitor()
|
||||||
|
dev[0].dump_monitor()
|
||||||
|
|
||||||
|
dev[0].dpp_listen(2437, role="configurator")
|
||||||
|
hapd.dpp_auth_init(uri=uri0, role="enrollee")
|
||||||
|
process_dpp_frames(dev[0], count=3)
|
||||||
|
msg = dev[0].mgmt_rx()
|
||||||
|
payload = msg['payload']
|
||||||
|
dialog_token, = struct.unpack('B', payload[2:3])
|
||||||
|
# Another comeback delay
|
||||||
|
hdr = struct.pack('<BBBHBH', 4, 13, dialog_token, 0, 0x80, 1)
|
||||||
|
adv_proto = "6c087fdd05506f9a1a01"
|
||||||
|
action = binascii.hexlify(hdr).decode() + adv_proto + "0300" + "001001"
|
||||||
|
cmd = "MGMT_TX %s %s freq=2437 wait_time=100 action=%s" % (bssid, bssid, action)
|
||||||
|
dev[0].request(cmd)
|
||||||
|
msg = dev[0].mgmt_rx()
|
||||||
|
hdr = struct.pack('<BBBHBH', 4, 13, dialog_token, 0, 0x81, 1)
|
||||||
|
# GAS: Invalid comeback response with non-zero frag_id and comeback_delay from 02:00:00:00:00:00
|
||||||
|
action = binascii.hexlify(hdr).decode() + adv_proto + "0300" + "001001"
|
||||||
|
cmd = "MGMT_TX %s %s freq=2437 wait_time=100 action=%s" % (bssid, bssid, action)
|
||||||
|
dev[0].request(cmd)
|
||||||
|
ev = hapd.wait_event(["GAS-QUERY-DONE"], timeout=10)
|
||||||
|
if not ev or "result=PEER_ERROR" not in ev:
|
||||||
|
raise Exception("Unexpect GAS query result: " + str(ev))
|
||||||
|
dev[0].request("DPP_STOP_LISTEN")
|
||||||
|
hapd.dump_monitor()
|
||||||
|
dev[0].dump_monitor()
|
||||||
|
|
||||||
|
dev[0].dpp_listen(2437, role="configurator")
|
||||||
|
hapd.dpp_auth_init(uri=uri0, role="enrollee")
|
||||||
|
process_dpp_frames(dev[0], count=3)
|
||||||
|
msg = dev[0].mgmt_rx()
|
||||||
|
payload = msg['payload']
|
||||||
|
dialog_token, = struct.unpack('B', payload[2:3])
|
||||||
|
# Valid comeback response
|
||||||
|
hdr = struct.pack('<BBBHBH', 4, 13, dialog_token, 0, 0x80, 0)
|
||||||
|
action = binascii.hexlify(hdr).decode() + adv_proto + "0300" + "001001"
|
||||||
|
cmd = "MGMT_TX %s %s freq=2437 wait_time=100 action=%s" % (bssid, bssid, action)
|
||||||
|
dev[0].request(cmd)
|
||||||
|
msg = dev[0].mgmt_rx()
|
||||||
|
# GAS: Drop frame as possible retry of previous fragment
|
||||||
|
hdr = struct.pack('<BBBHBH', 4, 13, dialog_token, 0, 0x80, 0)
|
||||||
|
action = binascii.hexlify(hdr).decode() + adv_proto + "0300" + "001001"
|
||||||
|
cmd = "MGMT_TX %s %s freq=2437 wait_time=100 action=%s" % (bssid, bssid, action)
|
||||||
|
dev[0].request(cmd)
|
||||||
|
# GAS: Unexpected frag_id in response from 02:00:00:00:00:00
|
||||||
|
hdr = struct.pack('<BBBHBH', 4, 13, dialog_token, 0, 0x82, 0)
|
||||||
|
action = binascii.hexlify(hdr).decode() + adv_proto + "0300" + "001001"
|
||||||
|
cmd = "MGMT_TX %s %s freq=2437 wait_time=100 action=%s" % (bssid, bssid, action)
|
||||||
|
dev[0].request(cmd)
|
||||||
|
ev = hapd.wait_event(["GAS-QUERY-DONE"], timeout=10)
|
||||||
|
if not ev or "result=PEER_ERROR" not in ev:
|
||||||
|
raise Exception("Unexpect GAS query result: " + str(ev))
|
||||||
|
dev[0].request("DPP_STOP_LISTEN")
|
||||||
|
hapd.dump_monitor()
|
||||||
|
dev[0].dump_monitor()
|
||||||
|
|
||||||
|
dev[0].dpp_listen(2437, role="configurator")
|
||||||
|
hapd.dpp_auth_init(uri=uri0, role="enrollee")
|
||||||
|
process_dpp_frames(dev[0], count=3)
|
||||||
|
msg = dev[0].mgmt_rx()
|
||||||
|
payload = msg['payload']
|
||||||
|
dialog_token, = struct.unpack('B', payload[2:3])
|
||||||
|
# GAS: Unexpected initial response from 02:00:00:00:00:00 dialog token 3 when waiting for comeback response
|
||||||
|
hdr = struct.pack('<BBBHBH', 4, 11, dialog_token, 0, 0x80, 0)
|
||||||
|
action = binascii.hexlify(hdr).decode() + adv_proto + "0300" + "001001"
|
||||||
|
cmd = "MGMT_TX %s %s freq=2437 wait_time=100 action=%s" % (bssid, bssid, action)
|
||||||
|
dev[0].request(cmd)
|
||||||
|
# GAS: Allow non-zero status for outstanding comeback response
|
||||||
|
hdr = struct.pack('<BBBHBH', 4, 13, dialog_token, 95, 0x80, 0)
|
||||||
|
# GAS: Ignore 1 octets of extra data after Query Response from 02:00:00:00:00:00
|
||||||
|
action = binascii.hexlify(hdr).decode() + adv_proto + "0300" + "001001" + "ff"
|
||||||
|
cmd = "MGMT_TX %s %s freq=2437 wait_time=100 action=%s" % (bssid, bssid, action)
|
||||||
|
dev[0].request(cmd)
|
||||||
|
# GAS: No pending query found for 02:00:00:00:00:00 dialog token 4
|
||||||
|
hdr = struct.pack('<BBBHBH', 4, 13, (dialog_token + 1) % 256, 0, 0x80, 0)
|
||||||
|
action = binascii.hexlify(hdr).decode() + adv_proto + "0300" + "001001"
|
||||||
|
cmd = "MGMT_TX %s %s freq=2437 wait_time=100 action=%s" % (bssid, bssid, action)
|
||||||
|
dev[0].request(cmd)
|
||||||
|
# GAS: Truncated Query Response in response from 02:00:00:00:00:00
|
||||||
|
hdr = struct.pack('<BBBHBH', 4, 13, dialog_token, 0, 0x81, 0)
|
||||||
|
action = binascii.hexlify(hdr).decode() + adv_proto + "0300" + "0010"
|
||||||
|
cmd = "MGMT_TX %s %s freq=2437 wait_time=100 action=%s" % (bssid, bssid, action)
|
||||||
|
dev[0].request(cmd)
|
||||||
|
# GAS: No room for GAS Response Length
|
||||||
|
hdr = struct.pack('<BBBHBH', 4, 13, dialog_token, 0, 0x81, 0)
|
||||||
|
action = binascii.hexlify(hdr).decode() + adv_proto + "03"
|
||||||
|
cmd = "MGMT_TX %s %s freq=2437 wait_time=100 action=%s" % (bssid, bssid, action)
|
||||||
|
dev[0].request(cmd)
|
||||||
|
# GAS: Unexpected Advertisement Protocol element ID 0 in response from 02:00:00:00:00:00
|
||||||
|
hdr = struct.pack('<BBBHBH', 4, 13, dialog_token, 0, 0x81, 0)
|
||||||
|
adv_proto_broken = "0000"
|
||||||
|
action = binascii.hexlify(hdr).decode() + adv_proto_broken + "0300" + "001001"
|
||||||
|
cmd = "MGMT_TX %s %s freq=2437 wait_time=100 action=%s" % (bssid, bssid, action)
|
||||||
|
dev[0].request(cmd)
|
||||||
|
# GAS: No room for Advertisement Protocol element in the response from 02:00:00:00:00:00
|
||||||
|
hdr = struct.pack('<BBBHBH', 4, 13, dialog_token, 0, 0x81, 0)
|
||||||
|
adv_proto_broken = "00ff"
|
||||||
|
action = binascii.hexlify(hdr).decode() + adv_proto_broken + "0300" + "001001"
|
||||||
|
cmd = "MGMT_TX %s %s freq=2437 wait_time=100 action=%s" % (bssid, bssid, action)
|
||||||
|
dev[0].request(cmd)
|
||||||
|
# No room for Comeback Delay
|
||||||
|
hdr = struct.pack('<BBBHBB', 4, 13, dialog_token, 0, 0x81, 0)
|
||||||
|
action = binascii.hexlify(hdr).decode()
|
||||||
|
cmd = "MGMT_TX %s %s freq=2437 wait_time=100 action=%s" % (bssid, bssid, action)
|
||||||
|
dev[0].request(cmd)
|
||||||
|
# No room for frag_id
|
||||||
|
hdr = struct.pack('<BBBH', 4, 13, dialog_token, 0)
|
||||||
|
action = binascii.hexlify(hdr).decode()
|
||||||
|
cmd = "MGMT_TX %s %s freq=2437 wait_time=100 action=%s" % (bssid, bssid, action)
|
||||||
|
dev[0].request(cmd)
|
||||||
|
# GAS: Query to 02:00:00:00:00:00 dialog token 3 failed - status code 1
|
||||||
|
hdr = struct.pack('<BBBHBH', 4, 13, dialog_token, 1, 0x81, 0)
|
||||||
|
action = binascii.hexlify(hdr).decode() + adv_proto + "0300" + "001001"
|
||||||
|
cmd = "MGMT_TX %s %s freq=2437 wait_time=100 action=%s" % (bssid, bssid, action)
|
||||||
|
dev[0].request(cmd)
|
||||||
|
ev = hapd.wait_event(["GAS-QUERY-DONE"], timeout=10)
|
||||||
|
if not ev or "result=FAILURE" not in ev:
|
||||||
|
raise Exception("Unexpect GAS query result: " + str(ev))
|
||||||
|
dev[0].request("DPP_STOP_LISTEN")
|
||||||
|
hapd.dump_monitor()
|
||||||
|
dev[0].dump_monitor()
|
||||||
|
|
||||||
|
dev[0].dpp_listen(2437, role="configurator")
|
||||||
|
hapd.dpp_auth_init(uri=uri0, role="enrollee")
|
||||||
|
process_dpp_frames(dev[0], count=2)
|
||||||
|
msg = dev[0].mgmt_rx()
|
||||||
|
payload = msg['payload']
|
||||||
|
dialog_token, = struct.unpack('B', payload[2:3])
|
||||||
|
# Unexpected comeback delay
|
||||||
|
hdr = struct.pack('<BBBHBH', 4, 13, dialog_token, 0, 0x80, 0)
|
||||||
|
adv_proto = "6c087fdd05506f9a1a01"
|
||||||
|
action = binascii.hexlify(hdr).decode() + adv_proto + "0300" + "001001"
|
||||||
|
cmd = "MGMT_TX %s %s freq=2437 wait_time=100 action=%s" % (bssid, bssid, action)
|
||||||
|
dev[0].request(cmd)
|
||||||
|
# GAS: Query to 02:00:00:00:00:00 dialog token 3 failed - status code 1
|
||||||
|
hdr = struct.pack('<BBBHBH', 4, 11, dialog_token, 1, 0x80, 0)
|
||||||
|
action = binascii.hexlify(hdr).decode() + adv_proto + "0300" + "001001"
|
||||||
|
cmd = "MGMT_TX %s %s freq=2437 wait_time=100 action=%s" % (bssid, bssid, action)
|
||||||
|
dev[0].request(cmd)
|
||||||
|
ev = hapd.wait_event(["GAS-QUERY-DONE"], timeout=10)
|
||||||
|
if not ev or "result=FAILURE" not in ev:
|
||||||
|
raise Exception("Unexpect GAS query result: " + str(ev))
|
||||||
|
dev[0].request("DPP_STOP_LISTEN")
|
||||||
|
hapd.dump_monitor()
|
||||||
|
dev[0].dump_monitor()
|
||||||
|
|
||||||
|
def test_dpp_hostapd_enrollee_gas_tx_status_errors(dev, apdev):
|
||||||
|
"""DPP and hostapd as Enrollee with GAS TX status errors"""
|
||||||
|
check_dpp_capab(dev[0])
|
||||||
|
hapd = hostapd.add_ap(apdev[0], {"ssid": "unconfigured",
|
||||||
|
"channel": "6"})
|
||||||
|
check_dpp_capab(hapd)
|
||||||
|
conf_id = dev[0].dpp_configurator_add()
|
||||||
|
id0 = dev[0].dpp_bootstrap_gen(chan="81/6", mac=True)
|
||||||
|
uri0 = dev[0].request("DPP_BOOTSTRAP_GET_URI %d" % id0)
|
||||||
|
conf = '{"wi-fi_tech":"infra", "discovery":{"ssid":"test"},"cred":{"akm":"psk","pass":"secret passphrase"}}' + 3000*' '
|
||||||
|
dev[0].set("dpp_config_obj_override", conf)
|
||||||
|
dev[0].set("dpp_configurator_params",
|
||||||
|
"conf=ap-dpp configurator=%d" % conf_id)
|
||||||
|
dev[0].set("ext_mgmt_frame_handling", "1")
|
||||||
|
dev[0].dpp_listen(2437, role="configurator")
|
||||||
|
hapd.dpp_auth_init(uri=uri0, role="enrollee")
|
||||||
|
process_dpp_frames(dev[0], count=3)
|
||||||
|
|
||||||
|
hapd.set("ext_mgmt_frame_handling", "1")
|
||||||
|
# GAS: TX status for unexpected destination
|
||||||
|
frame = "d0003a01" + "222222222222"
|
||||||
|
frame += hapd.own_addr().replace(':', '') + "ffffffffffff"
|
||||||
|
frame += "5000" + "040a"
|
||||||
|
hapd.request("MGMT_TX_STATUS_PROCESS stype=13 ok=1 buf=" + frame)
|
||||||
|
|
||||||
|
# GAS: No ACK to GAS request
|
||||||
|
frame = "d0003a01" + dev[0].own_addr().replace(':', '')
|
||||||
|
frame += hapd.own_addr().replace(':', '') + "ffffffffffff"
|
||||||
|
frame += "5000" + "040a"
|
||||||
|
hapd.request("MGMT_TX_STATUS_PROCESS stype=13 ok=0 buf=" + frame)
|
||||||
|
|
||||||
|
ev = hapd.wait_event(["GAS-QUERY-DONE"], timeout=10)
|
||||||
|
if "result=TIMEOUT" not in ev:
|
||||||
|
raise Exception("GAS timeout not reported")
|
||||||
|
|
||||||
|
# GAS: Unexpected TX status: dst=02:00:00:00:00:00 ok=1 - no query in progress
|
||||||
|
hapd.request("MGMT_TX_STATUS_PROCESS stype=13 ok=1 buf=" + frame)
|
||||||
|
hapd.set("ext_mgmt_frame_handling", "0")
|
||||||
|
|
||||||
def test_dpp_hostapd_configurator_override_objects(dev, apdev):
|
def test_dpp_hostapd_configurator_override_objects(dev, apdev):
|
||||||
"""DPP with hostapd as configurator and override objects"""
|
"""DPP with hostapd as configurator and override objects"""
|
||||||
check_dpp_capab(dev[0])
|
check_dpp_capab(dev[0])
|
||||||
@ -5303,6 +5645,49 @@ def run_dpp_conn_status(dev, apdev, result=0, assoc_reject=False):
|
|||||||
if result == 10 and "channel_list=" not in ev:
|
if result == 10 and "channel_list=" not in ev:
|
||||||
raise Exception("Channel list not reported for no-AP")
|
raise Exception("Channel list not reported for no-AP")
|
||||||
|
|
||||||
|
def test_dpp_conn_status_success_hostapd_configurator(dev, apdev):
|
||||||
|
"""DPP connection status - success with hostapd as Configurator"""
|
||||||
|
try:
|
||||||
|
run_dpp_conn_status_hostapd_configurator(dev, apdev)
|
||||||
|
finally:
|
||||||
|
dev[0].set("dpp_config_processing", "0", allow_fail=True)
|
||||||
|
|
||||||
|
def run_dpp_conn_status_hostapd_configurator(dev, apdev):
|
||||||
|
check_dpp_capab(dev[0])
|
||||||
|
hapd = hostapd.add_ap(apdev[0], {"ssid": "unconfigured",
|
||||||
|
"channel": "1"})
|
||||||
|
check_dpp_capab(hapd)
|
||||||
|
conf_id = hapd.dpp_configurator_add()
|
||||||
|
|
||||||
|
cmd = "DPP_CONFIGURATOR_SIGN conf=ap-dpp configurator=%d" % conf_id
|
||||||
|
res = hapd.request(cmd)
|
||||||
|
if "FAIL" in res:
|
||||||
|
raise Exception("Failed to generate own configuration")
|
||||||
|
update_hapd_config(hapd)
|
||||||
|
|
||||||
|
id0 = dev[0].dpp_bootstrap_gen(chan="81/1", mac=True)
|
||||||
|
uri0 = dev[0].request("DPP_BOOTSTRAP_GET_URI %d" % id0)
|
||||||
|
id1 = hapd.dpp_qr_code(uri0)
|
||||||
|
res = hapd.request("DPP_BOOTSTRAP_INFO %d" % id1)
|
||||||
|
if "FAIL" in res:
|
||||||
|
raise Exception("DPP_BOOTSTRAP_INFO failed")
|
||||||
|
if "type=QRCODE" not in res:
|
||||||
|
raise Exception("DPP_BOOTSTRAP_INFO did not report correct type")
|
||||||
|
if "mac_addr=" + dev[0].own_addr() not in res:
|
||||||
|
raise Exception("DPP_BOOTSTRAP_INFO did not report correct mac_addr")
|
||||||
|
dev[0].set("dpp_config_processing", "2")
|
||||||
|
dev[0].dpp_listen(2412)
|
||||||
|
hapd.dpp_auth_init(peer=id1, configurator=conf_id, conf="sta-dpp",
|
||||||
|
conn_status=True)
|
||||||
|
res = wait_auth_success(dev[0], hapd, configurator=hapd, enrollee=dev[0])
|
||||||
|
if 'wait_conn_status' not in res:
|
||||||
|
raise Exception("Configurator did not request connection status")
|
||||||
|
ev = hapd.wait_event(["DPP-CONN-STATUS-RESULT"], timeout=20)
|
||||||
|
if ev is None:
|
||||||
|
raise Exception("No connection status reported")
|
||||||
|
if "result=0" not in ev:
|
||||||
|
raise Exception("Unexpected connection status: " + ev)
|
||||||
|
|
||||||
def test_dpp_mud_url(dev, apdev):
|
def test_dpp_mud_url(dev, apdev):
|
||||||
"""DPP MUD URL"""
|
"""DPP MUD URL"""
|
||||||
check_dpp_capab(dev[0])
|
check_dpp_capab(dev[0])
|
||||||
@ -5408,6 +5793,24 @@ def test_dpp_nfc_uri_hostapd(dev, apdev):
|
|||||||
dev[0].dpp_auth_init(nfc_uri=uri, configurator=conf_id, conf="ap-dpp")
|
dev[0].dpp_auth_init(nfc_uri=uri, configurator=conf_id, conf="ap-dpp")
|
||||||
wait_auth_success(hapd, dev[0], configurator=dev[0], enrollee=hapd)
|
wait_auth_success(hapd, dev[0], configurator=dev[0], enrollee=hapd)
|
||||||
|
|
||||||
|
def test_dpp_nfc_uri_hostapd_tag_read(dev, apdev):
|
||||||
|
"""DPP bootstrapping via NFC URI record (hostapd reading tag)"""
|
||||||
|
check_dpp_capab(dev[0])
|
||||||
|
|
||||||
|
hapd = hostapd.add_ap(apdev[0], {"ssid": "unconfigured"})
|
||||||
|
check_dpp_capab(hapd)
|
||||||
|
|
||||||
|
id = dev[0].dpp_bootstrap_gen(type="nfc-uri", chan="81/1", mac=True)
|
||||||
|
uri = dev[0].request("DPP_BOOTSTRAP_GET_URI %d" % id)
|
||||||
|
info = dev[0].request("DPP_BOOTSTRAP_INFO %d" % id)
|
||||||
|
conf_id = dev[0].dpp_configurator_add()
|
||||||
|
dev[0].set("dpp_configurator_params",
|
||||||
|
"conf=ap-dpp configurator=%d" % conf_id)
|
||||||
|
dev[0].dpp_listen(2412)
|
||||||
|
|
||||||
|
hapd.dpp_auth_init(nfc_uri=uri, role="enrollee")
|
||||||
|
wait_auth_success(dev[0], hapd, configurator=dev[0], enrollee=hapd)
|
||||||
|
|
||||||
def test_dpp_nfc_negotiated_handover(dev, apdev):
|
def test_dpp_nfc_negotiated_handover(dev, apdev):
|
||||||
"""DPP bootstrapping via NFC negotiated handover"""
|
"""DPP bootstrapping via NFC negotiated handover"""
|
||||||
run_dpp_nfc_negotiated_handover(dev)
|
run_dpp_nfc_negotiated_handover(dev)
|
||||||
@ -5471,6 +5874,40 @@ def run_dpp_nfc_negotiated_handover(dev, curve0=None, curve1=None,
|
|||||||
conf=conf)
|
conf=conf)
|
||||||
wait_auth_success(dev[1], dev[0], configurator=dev[0], enrollee=dev[1])
|
wait_auth_success(dev[1], dev[0], configurator=dev[0], enrollee=dev[1])
|
||||||
|
|
||||||
|
def test_dpp_nfc_errors_hostapd(dev, apdev):
|
||||||
|
"""DPP NFC operation failures in hostapd"""
|
||||||
|
check_dpp_capab(dev[0])
|
||||||
|
check_dpp_capab(dev[1])
|
||||||
|
|
||||||
|
id0 = dev[0].dpp_bootstrap_gen(type="nfc-uri", chan="81/11", mac=True,
|
||||||
|
curve="secp384r1")
|
||||||
|
uri0 = dev[0].request("DPP_BOOTSTRAP_GET_URI %d" % id0)
|
||||||
|
|
||||||
|
hapd = hostapd.add_ap(apdev[0], {"ssid": "unconfigured",
|
||||||
|
"channel": "6"})
|
||||||
|
check_dpp_capab(hapd)
|
||||||
|
|
||||||
|
id_h = hapd.dpp_bootstrap_gen(type="nfc-uri", chan="81/6", mac=True)
|
||||||
|
uri_h = hapd.request("DPP_BOOTSTRAP_GET_URI %d" % id_h)
|
||||||
|
|
||||||
|
tests = ["",
|
||||||
|
"own=123456789",
|
||||||
|
"own=%d" % id_h,
|
||||||
|
"own=%d uri=%s" % (id_h, "foo")]
|
||||||
|
for t in tests:
|
||||||
|
if "FAIL" not in hapd.request("DPP_NFC_HANDOVER_REQ " + t):
|
||||||
|
raise Exception("Invalid DPP_NFC_HANDOVER_REQ accepted")
|
||||||
|
if "FAIL" not in hapd.request("DPP_NFC_HANDOVER_SEL " + t):
|
||||||
|
raise Exception("Invalid DPP_NFC_HANDOVER_SEL accepted")
|
||||||
|
|
||||||
|
# DPP: Peer (NFC Handover Selector) used different curve
|
||||||
|
if "FAIL" not in hapd.request("DPP_NFC_HANDOVER_SEL own=%d uri=%s" % (id_h, uri0)):
|
||||||
|
raise Exception("Invalid DPP_NFC_HANDOVER_SEL accepted")
|
||||||
|
|
||||||
|
# DPP: No common channel found
|
||||||
|
if "FAIL" not in hapd.request("DPP_NFC_HANDOVER_REQ own=%d uri=%s" % (id_h, uri0)):
|
||||||
|
raise Exception("DPP_NFC_HANDOVER_REQ with local error accepted")
|
||||||
|
|
||||||
def test_dpp_with_p2p_device(dev, apdev):
|
def test_dpp_with_p2p_device(dev, apdev):
|
||||||
"""DPP exchange when driver uses a separate P2P Device interface"""
|
"""DPP exchange when driver uses a separate P2P Device interface"""
|
||||||
check_dpp_capab(dev[0])
|
check_dpp_capab(dev[0])
|
||||||
@ -5648,6 +6085,74 @@ def test_dpp_chirp_ap(dev, apdev):
|
|||||||
timeout=20)
|
timeout=20)
|
||||||
update_hapd_config(hapd)
|
update_hapd_config(hapd)
|
||||||
|
|
||||||
|
@long_duration_test
|
||||||
|
def test_dpp_chirp_ap_5g(dev, apdev):
|
||||||
|
"""DPP chirp by an AP on 5 GHz"""
|
||||||
|
check_dpp_capab(dev[0], min_ver=2)
|
||||||
|
|
||||||
|
try:
|
||||||
|
hapd = None
|
||||||
|
hapd2 = None
|
||||||
|
|
||||||
|
params = {"ssid": "unconfigured",
|
||||||
|
"country_code": "US",
|
||||||
|
"hw_mode": "a",
|
||||||
|
"channel": "40",
|
||||||
|
"dpp_configurator_connectivity": "1"}
|
||||||
|
hapd2 = hostapd.add_ap(apdev[1], params)
|
||||||
|
check_dpp_capab(hapd2, min_ver=2)
|
||||||
|
|
||||||
|
params = {"ssid": "unconfigured",
|
||||||
|
"country_code": "US",
|
||||||
|
"hw_mode": "a",
|
||||||
|
"channel": "36",
|
||||||
|
"start_disabled": "1"}
|
||||||
|
hapd = hostapd.add_ap(apdev[0], params)
|
||||||
|
check_dpp_capab(hapd, min_ver=2)
|
||||||
|
|
||||||
|
id_h = hapd.dpp_bootstrap_gen(chan="81/1", mac=True)
|
||||||
|
uri = hapd.request("DPP_BOOTSTRAP_GET_URI %d" % id_h)
|
||||||
|
|
||||||
|
# First, check chirping iteration and timeout
|
||||||
|
if "OK" not in hapd.request("DPP_CHIRP own=%d iter=2" % id_h):
|
||||||
|
raise Exception("DPP_CHIRP failed")
|
||||||
|
chan1 = 0
|
||||||
|
chan6 = 0
|
||||||
|
chan40 = 0
|
||||||
|
chan149 = 0
|
||||||
|
for i in range(30):
|
||||||
|
ev = hapd.wait_event(["DPP-CHIRP-STOPPED", "DPP-TX "], timeout=60)
|
||||||
|
if ev is None:
|
||||||
|
raise Exception("DPP chirp stop not reported")
|
||||||
|
if "DPP-CHIRP-STOPPED" in ev:
|
||||||
|
break
|
||||||
|
if "type=13" not in ev:
|
||||||
|
continue
|
||||||
|
freq = int(ev.split(' ')[2].split('=')[1])
|
||||||
|
if freq == 2412:
|
||||||
|
chan1 += 1
|
||||||
|
elif freq == 2437:
|
||||||
|
chan6 += 1
|
||||||
|
elif freq == 5200:
|
||||||
|
chan40 += 1
|
||||||
|
elif freq == 5745:
|
||||||
|
chan149 += 1
|
||||||
|
if not chan1 or not chan6 or not chan40 or not chan149:
|
||||||
|
raise Exception("Chirp not sent on all channels")
|
||||||
|
|
||||||
|
# Then, check successful chirping
|
||||||
|
conf_id = dev[0].dpp_configurator_add()
|
||||||
|
idc = dev[0].dpp_qr_code(uri)
|
||||||
|
dev[0].dpp_bootstrap_set(idc, conf="ap-dpp", configurator=conf_id)
|
||||||
|
dev[0].dpp_listen(5200)
|
||||||
|
if "OK" not in hapd.request("DPP_CHIRP own=%d iter=5" % id_h):
|
||||||
|
raise Exception("DPP_CHIRP failed")
|
||||||
|
wait_auth_success(hapd, dev[0], configurator=dev[0], enrollee=hapd,
|
||||||
|
timeout=20)
|
||||||
|
update_hapd_config(hapd)
|
||||||
|
finally:
|
||||||
|
clear_regdom(hapd, dev)
|
||||||
|
|
||||||
def test_dpp_chirp_ap_errors(dev, apdev):
|
def test_dpp_chirp_ap_errors(dev, apdev):
|
||||||
"""DPP chirp errors in hostapd"""
|
"""DPP chirp errors in hostapd"""
|
||||||
hapd = hostapd.add_ap(apdev[0], {"ssid": "unconfigured",
|
hapd = hostapd.add_ap(apdev[0], {"ssid": "unconfigured",
|
||||||
@ -5779,6 +6284,25 @@ def test_dpp_pfs_ap_0_sta_ver1(dev, apdev):
|
|||||||
hapd = start_dpp_pfs_ap(apdev[0], 0)
|
hapd = start_dpp_pfs_ap(apdev[0], 0)
|
||||||
run_dpp_pfs_sta(dev[0], 0, pfs_expected=False)
|
run_dpp_pfs_sta(dev[0], 0, pfs_expected=False)
|
||||||
|
|
||||||
|
def test_dpp_pfs_errors(dev, apdev):
|
||||||
|
"""DPP PFS error cases"""
|
||||||
|
check_dpp_capab(dev[0], min_ver=2)
|
||||||
|
hapd = start_dpp_pfs_ap(apdev[0], 1)
|
||||||
|
tests = [(1, "dpp_pfs_init"),
|
||||||
|
(1, "crypto_ecdh_init;dpp_pfs_init"),
|
||||||
|
(1, "wpabuf_alloc;dpp_pfs_init")]
|
||||||
|
for count, func in tests:
|
||||||
|
with alloc_fail(dev[0], count, func):
|
||||||
|
dev[0].connect("dpp", key_mgmt="DPP", scan_freq="2412",
|
||||||
|
ieee80211w="2", dpp_pfs="1",
|
||||||
|
dpp_csign=params1_csign,
|
||||||
|
dpp_connector=params1_sta_connector,
|
||||||
|
dpp_netaccesskey=params1_sta_netaccesskey)
|
||||||
|
dev[0].request("REMOVE_NETWORK all")
|
||||||
|
dev[0].wait_disconnected()
|
||||||
|
dev[0].dump_monitor()
|
||||||
|
hapd.dump_monitor()
|
||||||
|
|
||||||
def test_dpp_reconfig_connector(dev, apdev):
|
def test_dpp_reconfig_connector(dev, apdev):
|
||||||
"""DPP reconfiguration connector"""
|
"""DPP reconfiguration connector"""
|
||||||
try:
|
try:
|
||||||
|
@ -2869,10 +2869,10 @@ def test_eap_proto_eke_errors(dev, apdev):
|
|||||||
(1, "os_get_random;eap_eke_dhcomp", None),
|
(1, "os_get_random;eap_eke_dhcomp", None),
|
||||||
(1, "aes_128_cbc_encrypt;eap_eke_dhcomp", None),
|
(1, "aes_128_cbc_encrypt;eap_eke_dhcomp", None),
|
||||||
(1, "aes_128_cbc_decrypt;eap_eke_shared_secret", None),
|
(1, "aes_128_cbc_decrypt;eap_eke_shared_secret", None),
|
||||||
(1, "eap_eke_prf;eap_eke_shared_secret", None),
|
(1, "hmac_sha256_vector;eap_eke_shared_secret", None),
|
||||||
(1, "eap_eke_prfplus;eap_eke_derive_ke_ki", None),
|
(1, "eap_eke_prf_hmac_sha256;eap_eke_derive_ke_ki", None),
|
||||||
(1, "eap_eke_prfplus;eap_eke_derive_ka", None),
|
(1, "eap_eke_prf_hmac_sha256;eap_eke_derive_ka", None),
|
||||||
(1, "eap_eke_prfplus;eap_eke_derive_msk", None),
|
(1, "eap_eke_prf_hmac_sha256;eap_eke_derive_msk", None),
|
||||||
(1, "os_get_random;eap_eke_prot", None),
|
(1, "os_get_random;eap_eke_prot", None),
|
||||||
(1, "aes_128_cbc_decrypt;eap_eke_decrypt_prot", None),
|
(1, "aes_128_cbc_decrypt;eap_eke_decrypt_prot", None),
|
||||||
(1, "eap_eke_derive_key;eap_eke_process_commit", None),
|
(1, "eap_eke_derive_key;eap_eke_process_commit", None),
|
||||||
|
@ -2358,3 +2358,54 @@ def test_fils_discovery_frame(dev, apdev, params):
|
|||||||
eap="PSK", identity="psk.user@example.com",
|
eap="PSK", identity="psk.user@example.com",
|
||||||
password_hex="0123456789abcdef0123456789abcdef",
|
password_hex="0123456789abcdef0123456789abcdef",
|
||||||
erp="1", scan_freq="2412")
|
erp="1", scan_freq="2412")
|
||||||
|
|
||||||
|
def test_fils_offload_to_driver(dev, apdev, params):
|
||||||
|
"""FILS offload to driver"""
|
||||||
|
check_fils_capa(dev[0])
|
||||||
|
check_erp_capa(dev[0])
|
||||||
|
run_fils_offload_to_driver(dev[0], apdev, params)
|
||||||
|
|
||||||
|
def test_fils_offload_to_driver2(dev, apdev, params):
|
||||||
|
"""FILS offload to driver"""
|
||||||
|
wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
|
||||||
|
wpas.interface_add("wlan5", drv_params="force_connect_cmd=1")
|
||||||
|
run_fils_offload_to_driver(wpas, apdev, params)
|
||||||
|
|
||||||
|
def run_fils_offload_to_driver(dev, apdev, params):
|
||||||
|
start_erp_as(msk_dump=os.path.join(params['logdir'], "msk.lst"))
|
||||||
|
|
||||||
|
bssid = apdev[0]['bssid']
|
||||||
|
params = hostapd.wpa2_eap_params(ssid="fils")
|
||||||
|
params['wpa_key_mgmt'] = "FILS-SHA256"
|
||||||
|
params['auth_server_port'] = "18128"
|
||||||
|
params['erp_send_reauth_start'] = '1'
|
||||||
|
params['erp_domain'] = 'example.com'
|
||||||
|
params['fils_realm'] = 'example.com'
|
||||||
|
params['disable_pmksa_caching'] = '1'
|
||||||
|
hapd = hostapd.add_ap(apdev[0]['ifname'], params)
|
||||||
|
|
||||||
|
dev.request("ERP_FLUSH")
|
||||||
|
id = dev.connect("fils", key_mgmt="FILS-SHA256",
|
||||||
|
eap="PSK", identity="psk.user@example.com",
|
||||||
|
password_hex="0123456789abcdef0123456789abcdef",
|
||||||
|
erp="1", scan_freq="2412")
|
||||||
|
|
||||||
|
p = "freq=2412 authorized=1 fils_erp_next_seq_num=4"
|
||||||
|
if "OK" not in dev.request("DRIVER_EVENT ASSOC " + p):
|
||||||
|
raise Exception("DRIVER_EVENT ASSOC did not succeed")
|
||||||
|
dev.wait_connected()
|
||||||
|
|
||||||
|
dev.request("DISCONNECT")
|
||||||
|
dev.wait_disconnected()
|
||||||
|
dev.dump_monitor()
|
||||||
|
|
||||||
|
dev.select_network(id, freq=2412)
|
||||||
|
dev.wait_connected()
|
||||||
|
dev.dump_monitor()
|
||||||
|
|
||||||
|
# This does not really work properly with SME-in-wpa_supplicant case
|
||||||
|
p = "freq=2412 authorized=1 fils_erp_next_seq_num=4"
|
||||||
|
if "OK" not in dev.request("DRIVER_EVENT ASSOC " + p):
|
||||||
|
raise Exception("DRIVER_EVENT ASSOC did not succeed")
|
||||||
|
|
||||||
|
dev.wait_connected()
|
||||||
|
@ -24,7 +24,7 @@ def test_he_open(dev, apdev):
|
|||||||
"he_mu_edca_ac_be_ecwmax": "15"}
|
"he_mu_edca_ac_be_ecwmax": "15"}
|
||||||
hapd = hostapd.add_ap(apdev[0], params)
|
hapd = hostapd.add_ap(apdev[0], params)
|
||||||
if hapd.get_status_field("ieee80211ax") != "1":
|
if hapd.get_status_field("ieee80211ax") != "1":
|
||||||
raise Exception("STATUS did not indicate ieee80211ac=1")
|
raise Exception("STATUS did not indicate ieee80211ax=1")
|
||||||
dev[0].connect("he", key_mgmt="NONE", scan_freq="2412")
|
dev[0].connect("he", key_mgmt="NONE", scan_freq="2412")
|
||||||
sta = hapd.get_sta(dev[0].own_addr())
|
sta = hapd.get_sta(dev[0].own_addr())
|
||||||
if "[HE]" not in sta['flags']:
|
if "[HE]" not in sta['flags']:
|
||||||
@ -94,7 +94,25 @@ def test_he_params(dev, apdev):
|
|||||||
"he_oper_centr_freq_seg1_idx": "0"}
|
"he_oper_centr_freq_seg1_idx": "0"}
|
||||||
hapd = hostapd.add_ap(apdev[0], params)
|
hapd = hostapd.add_ap(apdev[0], params)
|
||||||
if hapd.get_status_field("ieee80211ax") != "1":
|
if hapd.get_status_field("ieee80211ax") != "1":
|
||||||
raise Exception("STATUS did not indicate ieee80211ac=1")
|
raise Exception("STATUS did not indicate ieee80211ax=1")
|
||||||
|
dev[0].connect("he", key_mgmt="NONE", scan_freq="2412")
|
||||||
|
|
||||||
|
def test_he_spr_params(dev, apdev):
|
||||||
|
"""HE AP spatial reuse parameters"""
|
||||||
|
params = {"ssid": "he",
|
||||||
|
"ieee80211ax": "1",
|
||||||
|
"he_spr_sr_control": "12",
|
||||||
|
"he_spr_non_srg_obss_pd_max_offset": "1",
|
||||||
|
"he_spr_srg_obss_pd_min_offset": "2",
|
||||||
|
"he_spr_srg_obss_pd_max_offset": "3",
|
||||||
|
"he_spr_srg_bss_colors": "1 2 10 63",
|
||||||
|
"he_spr_srg_partial_bssid": "0 1 3 63",
|
||||||
|
"he_oper_chwidth": "0",
|
||||||
|
"he_oper_centr_freq_seg0_idx": "1",
|
||||||
|
"he_oper_centr_freq_seg1_idx": "0"}
|
||||||
|
hapd = hostapd.add_ap(apdev[0], params)
|
||||||
|
if hapd.get_status_field("ieee80211ax") != "1":
|
||||||
|
raise Exception("STATUS did not indicate ieee80211ax=1")
|
||||||
dev[0].connect("he", key_mgmt="NONE", scan_freq="2412")
|
dev[0].connect("he", key_mgmt="NONE", scan_freq="2412")
|
||||||
|
|
||||||
def he_supported():
|
def he_supported():
|
||||||
|
@ -245,6 +245,23 @@ def test_ieee8021x_held(dev, apdev):
|
|||||||
dev[0].request("SET EAPOL::maxStart 3")
|
dev[0].request("SET EAPOL::maxStart 3")
|
||||||
dev[0].request("SET EAPOL::heldPeriod 60")
|
dev[0].request("SET EAPOL::heldPeriod 60")
|
||||||
|
|
||||||
|
def test_ieee8021x_force_unauth(dev, apdev):
|
||||||
|
"""IEEE 802.1X and FORCE_UNAUTH state"""
|
||||||
|
params = hostapd.radius_params()
|
||||||
|
params["ssid"] = "ieee8021x-open"
|
||||||
|
params["ieee8021x"] = "1"
|
||||||
|
hapd = hostapd.add_ap(apdev[0], params)
|
||||||
|
bssid = apdev[0]['bssid']
|
||||||
|
|
||||||
|
dev[0].connect("ieee8021x-open", key_mgmt="IEEE8021X", eapol_flags="0",
|
||||||
|
eap="PSK", identity="psk.user@example.com",
|
||||||
|
password_hex="0123456789abcdef0123456789abcdef",
|
||||||
|
scan_freq="2412")
|
||||||
|
dev[0].request("SET EAPOL::portControl ForceUnauthorized")
|
||||||
|
pae = dev[0].get_status_field('Supplicant PAE state')
|
||||||
|
dev[0].wait_disconnected()
|
||||||
|
dev[0].request("SET EAPOL::portControl Auto")
|
||||||
|
|
||||||
def send_eapol_key(dev, bssid, signkey, frame_start, frame_end):
|
def send_eapol_key(dev, bssid, signkey, frame_start, frame_end):
|
||||||
zero_sign = "00000000000000000000000000000000"
|
zero_sign = "00000000000000000000000000000000"
|
||||||
frame = frame_start + zero_sign + frame_end
|
frame = frame_start + zero_sign + frame_end
|
||||||
|
@ -543,15 +543,32 @@ def test_mbo_without_pmf(dev, apdev):
|
|||||||
def test_mbo_without_pmf_workaround(dev, apdev):
|
def test_mbo_without_pmf_workaround(dev, apdev):
|
||||||
"""MBO and WPA2 without PMF on misbehaving AP"""
|
"""MBO and WPA2 without PMF on misbehaving AP"""
|
||||||
ssid = "test-wnm-mbo"
|
ssid = "test-wnm-mbo"
|
||||||
params = {'ssid': ssid, "wpa": '2',
|
params0 = {'ssid': ssid, "wpa": '2',
|
||||||
"wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP",
|
"wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP",
|
||||||
"wpa_passphrase": "12345678",
|
"wpa_passphrase": "12345678",
|
||||||
"vendor_elements": "dd07506f9a16010100"}
|
"vendor_elements": "dd07506f9a16010100"}
|
||||||
hapd = hostapd.add_ap(apdev[0], params)
|
params1 = {'ssid': ssid, "mbo": '1', "wpa": '2',
|
||||||
|
"wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP",
|
||||||
|
"wpa_passphrase": "12345678", "ieee80211w": "1"}
|
||||||
|
hapd0 = hostapd.add_ap(apdev[0], params0)
|
||||||
dev[0].connect(ssid, psk="12345678", key_mgmt="WPA-PSK",
|
dev[0].connect(ssid, psk="12345678", key_mgmt="WPA-PSK",
|
||||||
proto="WPA2", ieee80211w="1", scan_freq="2412")
|
proto="WPA2", ieee80211w="1", scan_freq="2412")
|
||||||
hapd.wait_sta()
|
hapd0.wait_sta()
|
||||||
sta = hapd.get_sta(dev[0].own_addr())
|
sta = hapd0.get_sta(dev[0].own_addr())
|
||||||
|
ext_capab = bytearray(binascii.unhexlify(sta['ext_capab']))
|
||||||
|
if ext_capab[2] & 0x08:
|
||||||
|
raise Exception("STA did not disable BSS Transition capability")
|
||||||
|
hapd1 = hostapd.add_ap(apdev[1], params1)
|
||||||
|
dev[0].scan_for_bss(hapd1.own_addr(), 2412, force_scan=True)
|
||||||
|
dev[0].roam(hapd1.own_addr())
|
||||||
|
hapd1.wait_sta()
|
||||||
|
sta = hapd1.get_sta(dev[0].own_addr())
|
||||||
|
ext_capab = bytearray(binascii.unhexlify(sta['ext_capab']))
|
||||||
|
if not ext_capab[2] & 0x08:
|
||||||
|
raise Exception("STA disabled BSS Transition capability")
|
||||||
|
dev[0].roam(hapd0.own_addr())
|
||||||
|
hapd0.wait_sta()
|
||||||
|
sta = hapd0.get_sta(dev[0].own_addr())
|
||||||
ext_capab = bytearray(binascii.unhexlify(sta['ext_capab']))
|
ext_capab = bytearray(binascii.unhexlify(sta['ext_capab']))
|
||||||
if ext_capab[2] & 0x08:
|
if ext_capab[2] & 0x08:
|
||||||
raise Exception("STA did not disable BSS Transition capability")
|
raise Exception("STA did not disable BSS Transition capability")
|
||||||
|
231
tests/hwsim/test_mscs.py
Normal file
231
tests/hwsim/test_mscs.py
Normal file
@ -0,0 +1,231 @@
|
|||||||
|
# Test cases for MSCS
|
||||||
|
# Copyright (c) 2021, Jouni Malinen <j@w1.fi>
|
||||||
|
#
|
||||||
|
# This software may be distributed under the terms of the BSD license.
|
||||||
|
# See README for more details.
|
||||||
|
|
||||||
|
import struct
|
||||||
|
import time
|
||||||
|
|
||||||
|
import hostapd
|
||||||
|
from utils import *
|
||||||
|
|
||||||
|
def register_mcsc_req(hapd):
|
||||||
|
type = 0x00d0
|
||||||
|
match = "1304"
|
||||||
|
if "OK" not in hapd.request("REGISTER_FRAME %04x %s" % (type, match)):
|
||||||
|
raise Exception("Could not register frame reception for Robust AV Streaming")
|
||||||
|
|
||||||
|
def handle_mscs_req(hapd, wrong_dialog=False, status_code=0):
|
||||||
|
msg = hapd.mgmt_rx()
|
||||||
|
if msg['subtype'] != 13:
|
||||||
|
logger.info("RX:" + str(msg))
|
||||||
|
raise Exception("Received unexpected Management frame")
|
||||||
|
categ, act, dialog_token = struct.unpack('BBB', msg['payload'][0:3])
|
||||||
|
if categ != 19 or act != 4:
|
||||||
|
logger.info("RX:" + str(msg))
|
||||||
|
raise Exception("Received unexpected Action frame")
|
||||||
|
|
||||||
|
if wrong_dialog:
|
||||||
|
dialog_token = (dialog_token + 1) % 256
|
||||||
|
msg['da'] = msg['sa']
|
||||||
|
msg['sa'] = hapd.own_addr()
|
||||||
|
msg['payload'] = struct.pack('<BBBH', 19, 5, dialog_token, status_code)
|
||||||
|
hapd.mgmt_tx(msg)
|
||||||
|
ev = hapd.wait_event(["MGMT-TX-STATUS"], timeout=5)
|
||||||
|
if ev is None or "stype=13 ok=1" not in ev:
|
||||||
|
raise Exception("No TX status reported")
|
||||||
|
|
||||||
|
def wait_mscs_result(dev, expect_status=0):
|
||||||
|
ev = dev.wait_event(["CTRL-EVENT-MSCS-RESULT"], timeout=1)
|
||||||
|
if ev is None:
|
||||||
|
raise Exception("No MSCS result reported")
|
||||||
|
if "status_code=%d" % expect_status not in ev:
|
||||||
|
raise Exception("Unexpected MSCS result: " + ev)
|
||||||
|
|
||||||
|
def test_mscs_invalid_params(dev, apdev):
|
||||||
|
"""MSCS command invalid parameters"""
|
||||||
|
tests = ["",
|
||||||
|
"add Xp_bitmap=F0 up_limit=7 stream_timeout=12345 frame_classifier=045F",
|
||||||
|
"add up_bitmap=F0 Xp_limit=7 stream_timeout=12345 frame_classifier=045F",
|
||||||
|
"add up_bitmap=F0 up_limit=7 Xtream_timeout=12345 frame_classifier=045F",
|
||||||
|
"add up_bitmap=F0 up_limit=7 stream_timeout=12345 Xrame_classifier=045F",
|
||||||
|
"add up_bitmap=X0 up_limit=7 stream_timeout=12345 frame_classifier=045F",
|
||||||
|
"add up_bitmap=F0 up_limit=7 stream_timeout=0 frame_classifier=045F",
|
||||||
|
"add up_bitmap=F0 up_limit=7 stream_timeout=12345 frame_classifier=X45F",
|
||||||
|
"change "]
|
||||||
|
for t in tests:
|
||||||
|
if "FAIL" not in dev[0].request("MSCS " + t):
|
||||||
|
raise Exception("Invalid MSCS parameters accepted: " + t)
|
||||||
|
|
||||||
|
def test_mscs_without_ap_support(dev, apdev):
|
||||||
|
"""MSCS without AP support"""
|
||||||
|
try:
|
||||||
|
run_mscs_without_ap_support(dev, apdev)
|
||||||
|
finally:
|
||||||
|
dev[0].request("MSCS remove")
|
||||||
|
|
||||||
|
def run_mscs_without_ap_support(dev, apdev):
|
||||||
|
params = {"ssid": "mscs",
|
||||||
|
"ext_capa_mask": 10*"00" + "20"}
|
||||||
|
hapd = hostapd.add_ap(apdev[0], params)
|
||||||
|
|
||||||
|
cmd = "MSCS add up_bitmap=F0 up_limit=7 stream_timeout=12345 frame_classifier=045F"
|
||||||
|
if "OK" not in dev[0].request(cmd):
|
||||||
|
raise Exception("Failed to configure MSCS")
|
||||||
|
|
||||||
|
dev[0].connect("mscs", key_mgmt="NONE", scan_freq="2412")
|
||||||
|
|
||||||
|
cmd = "MSCS change up_bitmap=F0 up_limit=7 stream_timeout=12345 frame_classifier=045F"
|
||||||
|
if "FAIL" not in dev[0].request(cmd):
|
||||||
|
raise Exception("MSCS change accepted unexpectedly")
|
||||||
|
|
||||||
|
cmd = "MSCS add up_bitmap=F0 up_limit=7 stream_timeout=12345 frame_classifier=045F"
|
||||||
|
if "FAIL" not in dev[0].request(cmd):
|
||||||
|
raise Exception("MSCS add accepted unexpectedly")
|
||||||
|
|
||||||
|
def test_mscs_post_assoc(dev, apdev):
|
||||||
|
"""MSCS configuration post-association"""
|
||||||
|
try:
|
||||||
|
run_mscs_post_assoc(dev, apdev)
|
||||||
|
finally:
|
||||||
|
dev[0].request("MSCS remove")
|
||||||
|
|
||||||
|
def run_mscs_post_assoc(dev, apdev):
|
||||||
|
params = {"ssid": "mscs",
|
||||||
|
"ext_capa": 10*"00" + "20"}
|
||||||
|
hapd = hostapd.add_ap(apdev[0], params)
|
||||||
|
register_mcsc_req(hapd)
|
||||||
|
|
||||||
|
dev[0].connect("mscs", key_mgmt="NONE", scan_freq="2412")
|
||||||
|
|
||||||
|
hapd.dump_monitor()
|
||||||
|
hapd.set("ext_mgmt_frame_handling", "1")
|
||||||
|
|
||||||
|
cmd = "MSCS change up_bitmap=F0 up_limit=7 stream_timeout=12345 frame_classifier=045F"
|
||||||
|
if "FAIL" not in dev[0].request(cmd):
|
||||||
|
raise Exception("MSCS change accepted unexpectedly")
|
||||||
|
|
||||||
|
cmd = "MSCS add up_bitmap=F0 up_limit=7 stream_timeout=12345 frame_classifier=045F"
|
||||||
|
if "OK" not in dev[0].request(cmd):
|
||||||
|
raise Exception("MSCS add failed")
|
||||||
|
|
||||||
|
handle_mscs_req(hapd)
|
||||||
|
wait_mscs_result(dev[0])
|
||||||
|
|
||||||
|
cmd = "MSCS change up_bitmap=F0 up_limit=7 stream_timeout=12345 frame_classifier=045F"
|
||||||
|
if "OK" not in dev[0].request(cmd):
|
||||||
|
raise Exception("MSCS change failed")
|
||||||
|
|
||||||
|
handle_mscs_req(hapd)
|
||||||
|
wait_mscs_result(dev[0])
|
||||||
|
|
||||||
|
cmd = "MSCS change up_bitmap=F0 up_limit=7 stream_timeout=12345 frame_classifier=045F"
|
||||||
|
if "OK" not in dev[0].request(cmd):
|
||||||
|
raise Exception("MSCS change failed")
|
||||||
|
|
||||||
|
handle_mscs_req(hapd, status_code=23456)
|
||||||
|
wait_mscs_result(dev[0], expect_status=23456)
|
||||||
|
|
||||||
|
def test_mscs_pre_assoc(dev, apdev):
|
||||||
|
"""MSCS configuration pre-association"""
|
||||||
|
try:
|
||||||
|
run_mscs_pre_assoc(dev, apdev)
|
||||||
|
finally:
|
||||||
|
dev[0].request("MSCS remove")
|
||||||
|
|
||||||
|
def run_mscs_pre_assoc(dev, apdev):
|
||||||
|
params = {"ssid": "mscs",
|
||||||
|
"ext_capa": 10*"00" + "20",
|
||||||
|
"assocresp_elements": "ff0c5800000000000000" + "01020000"}
|
||||||
|
hapd = hostapd.add_ap(apdev[0], params)
|
||||||
|
register_mcsc_req(hapd)
|
||||||
|
|
||||||
|
cmd = "MSCS add up_bitmap=F0 up_limit=7 stream_timeout=12345 frame_classifier=045F"
|
||||||
|
if "OK" not in dev[0].request(cmd):
|
||||||
|
raise Exception("MSCS add failed")
|
||||||
|
|
||||||
|
dev[0].connect("mscs", key_mgmt="NONE", scan_freq="2412",
|
||||||
|
wait_connect=False)
|
||||||
|
wait_mscs_result(dev[0])
|
||||||
|
dev[0].wait_connected()
|
||||||
|
|
||||||
|
hapd.set("ext_mgmt_frame_handling", "1")
|
||||||
|
|
||||||
|
cmd = "MSCS change up_bitmap=F0 up_limit=7 stream_timeout=12345 frame_classifier=045F"
|
||||||
|
if "OK" not in dev[0].request(cmd):
|
||||||
|
raise Exception("MSCS change failed")
|
||||||
|
|
||||||
|
handle_mscs_req(hapd)
|
||||||
|
wait_mscs_result(dev[0])
|
||||||
|
|
||||||
|
cmd = "MSCS change up_bitmap=F0 up_limit=7 stream_timeout=12345 frame_classifier=045F"
|
||||||
|
if "OK" not in dev[0].request(cmd):
|
||||||
|
raise Exception("MSCS change failed")
|
||||||
|
|
||||||
|
handle_mscs_req(hapd, wrong_dialog=True)
|
||||||
|
|
||||||
|
ev = dev[0].wait_event(["CTRL-EVENT-MSCS-RESULT"], timeout=1)
|
||||||
|
if ev is not None:
|
||||||
|
raise Exception("Unexpected MSCS result reported")
|
||||||
|
|
||||||
|
def test_mscs_assoc_failure(dev, apdev):
|
||||||
|
"""MSCS configuration failure during association exchange"""
|
||||||
|
try:
|
||||||
|
run_mscs_assoc_failure(dev, apdev)
|
||||||
|
finally:
|
||||||
|
dev[0].request("MSCS remove")
|
||||||
|
|
||||||
|
def run_mscs_assoc_failure(dev, apdev):
|
||||||
|
params = {"ssid": "mscs",
|
||||||
|
"ext_capa": 10*"00" + "20",
|
||||||
|
"assocresp_elements": "ff0c5800000000000000" + "01020001"}
|
||||||
|
hapd = hostapd.add_ap(apdev[0], params)
|
||||||
|
register_mcsc_req(hapd)
|
||||||
|
|
||||||
|
cmd = "MSCS add up_bitmap=F0 up_limit=7 stream_timeout=12345 frame_classifier=045F"
|
||||||
|
if "OK" not in dev[0].request(cmd):
|
||||||
|
raise Exception("MSCS add failed")
|
||||||
|
|
||||||
|
dev[0].connect("mscs", key_mgmt="NONE", scan_freq="2412",
|
||||||
|
wait_connect=False)
|
||||||
|
wait_mscs_result(dev[0], expect_status=256)
|
||||||
|
dev[0].wait_connected()
|
||||||
|
dev[0].request("REMOVE_NETWORK all")
|
||||||
|
dev[0].wait_disconnected()
|
||||||
|
|
||||||
|
hapd.dump_monitor()
|
||||||
|
# No MSCS Status subelement
|
||||||
|
hapd.set("assocresp_elements", "ff085800000000000000")
|
||||||
|
dev[0].connect("mscs", key_mgmt="NONE", scan_freq="2412",
|
||||||
|
wait_connect=False)
|
||||||
|
ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED", "CTRL-EVENT-MSCS-RESULT"],
|
||||||
|
timeout=10)
|
||||||
|
if ev is None:
|
||||||
|
raise Exception("No connection event")
|
||||||
|
if "CTRL-EVENT-MSCS-RESULT" in ev:
|
||||||
|
raise Exception("Unexpected MSCS result")
|
||||||
|
|
||||||
|
def test_mscs_local_errors(dev, apdev):
|
||||||
|
"""MSCS configuration local errors"""
|
||||||
|
try:
|
||||||
|
run_mscs_local_errors(dev, apdev)
|
||||||
|
finally:
|
||||||
|
dev[0].request("MSCS remove")
|
||||||
|
|
||||||
|
def run_mscs_local_errors(dev, apdev):
|
||||||
|
params = {"ssid": "mscs",
|
||||||
|
"ext_capa": 10*"00" + "20"}
|
||||||
|
hapd = hostapd.add_ap(apdev[0], params)
|
||||||
|
register_mcsc_req(hapd)
|
||||||
|
|
||||||
|
dev[0].connect("mscs", key_mgmt="NONE", scan_freq="2412")
|
||||||
|
|
||||||
|
hapd.dump_monitor()
|
||||||
|
hapd.set("ext_mgmt_frame_handling", "1")
|
||||||
|
|
||||||
|
for count in range(1, 3):
|
||||||
|
with alloc_fail(dev[0], count, "wpas_send_mscs_req"):
|
||||||
|
cmd = "MSCS add up_bitmap=F0 up_limit=7 stream_timeout=12345 frame_classifier=045F"
|
||||||
|
if "FAIL" not in dev[0].request(cmd):
|
||||||
|
raise Exception("MSCS add succeeded in error case")
|
@ -225,6 +225,8 @@ def run_multi_ap_wps(dev, apdev, params, params_backhaul=None, add_apdev=False,
|
|||||||
dev[0].cmd_execute(['iw', wpas_apdev['ifname'], 'del'])
|
dev[0].cmd_execute(['iw', wpas_apdev['ifname'], 'del'])
|
||||||
raise
|
raise
|
||||||
|
|
||||||
|
return hapd
|
||||||
|
|
||||||
def test_multi_ap_wps_shared(dev, apdev):
|
def test_multi_ap_wps_shared(dev, apdev):
|
||||||
"""WPS on shared fronthaul/backhaul AP"""
|
"""WPS on shared fronthaul/backhaul AP"""
|
||||||
ssid = "multi-ap-wps"
|
ssid = "multi-ap-wps"
|
||||||
@ -233,7 +235,15 @@ def test_multi_ap_wps_shared(dev, apdev):
|
|||||||
params.update({"multi_ap": "3",
|
params.update({"multi_ap": "3",
|
||||||
"multi_ap_backhaul_ssid": '"%s"' % ssid,
|
"multi_ap_backhaul_ssid": '"%s"' % ssid,
|
||||||
"multi_ap_backhaul_wpa_passphrase": passphrase})
|
"multi_ap_backhaul_wpa_passphrase": passphrase})
|
||||||
run_multi_ap_wps(dev, apdev, params)
|
hapd = run_multi_ap_wps(dev, apdev, params)
|
||||||
|
# Verify WPS parameter update with Multi-AP
|
||||||
|
if "OK" not in hapd.request("RELOAD"):
|
||||||
|
raise Exception("hostapd RELOAD failed")
|
||||||
|
dev[0].wait_disconnected()
|
||||||
|
dev[0].request("REMOVE_NETWORK all")
|
||||||
|
hapd.request("WPS_PBC")
|
||||||
|
dev[0].request("WPS_PBC multi_ap=1")
|
||||||
|
dev[0].wait_connected(timeout=20)
|
||||||
|
|
||||||
def test_multi_ap_wps_shared_csa(dev, apdev):
|
def test_multi_ap_wps_shared_csa(dev, apdev):
|
||||||
"""WPS on shared fronthaul/backhaul AP, run CSA"""
|
"""WPS on shared fronthaul/backhaul AP, run CSA"""
|
||||||
|
@ -982,12 +982,22 @@ def check_ocv_failure(dev, frame_txt, frame, addr):
|
|||||||
|
|
||||||
def test_wpa2_ocv_ap_override_eapol_m3(dev, apdev):
|
def test_wpa2_ocv_ap_override_eapol_m3(dev, apdev):
|
||||||
"""OCV on 2.4 GHz and AP override EAPOL-Key msg 3/4"""
|
"""OCV on 2.4 GHz and AP override EAPOL-Key msg 3/4"""
|
||||||
|
run_wpa2_ocv_ap_override_eapol_m3(dev, apdev)
|
||||||
|
|
||||||
|
def test_wpa2_ocv_ap_override_eapol_m3_post_enable(dev, apdev):
|
||||||
|
"""OCV on 2.4 GHz and AP override EAPOL-Key msg 3/4 (post enable)"""
|
||||||
|
run_wpa2_ocv_ap_override_eapol_m3(dev, apdev, True)
|
||||||
|
|
||||||
|
def run_wpa2_ocv_ap_override_eapol_m3(dev, apdev, post_enable=False):
|
||||||
params = {"channel": "1",
|
params = {"channel": "1",
|
||||||
"ieee80211w": "2",
|
"ieee80211w": "2",
|
||||||
"ocv": "1",
|
"ocv": "1"}
|
||||||
"oci_freq_override_eapol_m3": "2462"}
|
if not post_enable:
|
||||||
|
params["oci_freq_override_eapol_m3"] = "2462"
|
||||||
hapd, ssid, passphrase = ocv_setup_ap(apdev[0], params)
|
hapd, ssid, passphrase = ocv_setup_ap(apdev[0], params)
|
||||||
bssid = hapd.own_addr()
|
bssid = hapd.own_addr()
|
||||||
|
if post_enable:
|
||||||
|
hapd.set("oci_freq_override_eapol_m3", "2462")
|
||||||
dev[0].connect(ssid, psk=passphrase, scan_freq="2412", ocv="1",
|
dev[0].connect(ssid, psk=passphrase, scan_freq="2412", ocv="1",
|
||||||
ieee80211w="2", wait_connect=False)
|
ieee80211w="2", wait_connect=False)
|
||||||
|
|
||||||
@ -999,15 +1009,25 @@ def test_wpa2_ocv_ap_override_eapol_m3(dev, apdev):
|
|||||||
|
|
||||||
def test_wpa2_ocv_ap_override_eapol_g1(dev, apdev):
|
def test_wpa2_ocv_ap_override_eapol_g1(dev, apdev):
|
||||||
"""OCV on 2.4 GHz and AP override EAPOL-Key group msg 1/2"""
|
"""OCV on 2.4 GHz and AP override EAPOL-Key group msg 1/2"""
|
||||||
|
run_wpa2_ocv_ap_override_eapol_g1(dev, apdev)
|
||||||
|
|
||||||
|
def test_wpa2_ocv_ap_override_eapol_g1_post_enable(dev, apdev):
|
||||||
|
"""OCV on 2.4 GHz and AP override EAPOL-Key group msg 1/2 (post enable)"""
|
||||||
|
run_wpa2_ocv_ap_override_eapol_g1(dev, apdev, True)
|
||||||
|
|
||||||
|
def run_wpa2_ocv_ap_override_eapol_g1(dev, apdev, post_enable=False):
|
||||||
params = {"channel": "1",
|
params = {"channel": "1",
|
||||||
"ieee80211w": "2",
|
"ieee80211w": "2",
|
||||||
"ocv": "1",
|
"ocv": "1"}
|
||||||
"oci_freq_override_eapol_g1": "2462"}
|
if not post_enable:
|
||||||
|
params["oci_freq_override_eapol_g1"] = "2462"
|
||||||
hapd, ssid, passphrase = ocv_setup_ap(apdev[0], params)
|
hapd, ssid, passphrase = ocv_setup_ap(apdev[0], params)
|
||||||
bssid = hapd.own_addr()
|
bssid = hapd.own_addr()
|
||||||
dev[0].connect(ssid, psk=passphrase, scan_freq="2412", ocv="1",
|
dev[0].connect(ssid, psk=passphrase, scan_freq="2412", ocv="1",
|
||||||
ieee80211w="2")
|
ieee80211w="2")
|
||||||
|
|
||||||
|
if post_enable:
|
||||||
|
hapd.set("oci_freq_override_eapol_g1", "2462")
|
||||||
if "OK" not in hapd.request("REKEY_GTK"):
|
if "OK" not in hapd.request("REKEY_GTK"):
|
||||||
raise Exception("REKEY_GTK failed")
|
raise Exception("REKEY_GTK failed")
|
||||||
check_ocv_failure(dev[0], "EAPOL-Key group msg 1/2", "eapol-key-g1", bssid)
|
check_ocv_failure(dev[0], "EAPOL-Key group msg 1/2", "eapol-key-g1", bssid)
|
||||||
@ -1044,6 +1064,13 @@ def test_wpa2_ocv_ap_override_saquery_resp(dev, apdev):
|
|||||||
|
|
||||||
def test_wpa2_ocv_ap_override_fils_assoc(dev, apdev, params):
|
def test_wpa2_ocv_ap_override_fils_assoc(dev, apdev, params):
|
||||||
"""OCV on 2.4 GHz and AP override FILS association"""
|
"""OCV on 2.4 GHz and AP override FILS association"""
|
||||||
|
run_wpa2_ocv_ap_override_fils_assoc(dev, apdev, params)
|
||||||
|
|
||||||
|
def test_wpa2_ocv_ap_override_fils_assoc_post_enable(dev, apdev, params):
|
||||||
|
"""OCV on 2.4 GHz and AP override FILS association (post enable)"""
|
||||||
|
run_wpa2_ocv_ap_override_fils_assoc(dev, apdev, params, True)
|
||||||
|
|
||||||
|
def run_wpa2_ocv_ap_override_fils_assoc(dev, apdev, params, post_enable=False):
|
||||||
check_fils_capa(dev[0])
|
check_fils_capa(dev[0])
|
||||||
check_erp_capa(dev[0])
|
check_erp_capa(dev[0])
|
||||||
|
|
||||||
@ -1060,6 +1087,7 @@ def test_wpa2_ocv_ap_override_fils_assoc(dev, apdev, params):
|
|||||||
params['wpa_group_rekey'] = '1'
|
params['wpa_group_rekey'] = '1'
|
||||||
params["ieee80211w"] = "2"
|
params["ieee80211w"] = "2"
|
||||||
params["ocv"] = "1"
|
params["ocv"] = "1"
|
||||||
|
if not post_enable:
|
||||||
params["oci_freq_override_fils_assoc"] = "2462"
|
params["oci_freq_override_fils_assoc"] = "2462"
|
||||||
try:
|
try:
|
||||||
hapd = hostapd.add_ap(apdev[0], params)
|
hapd = hostapd.add_ap(apdev[0], params)
|
||||||
@ -1068,6 +1096,8 @@ def test_wpa2_ocv_ap_override_fils_assoc(dev, apdev, params):
|
|||||||
raise HwsimSkip("OCV not supported")
|
raise HwsimSkip("OCV not supported")
|
||||||
raise
|
raise
|
||||||
bssid = hapd.own_addr()
|
bssid = hapd.own_addr()
|
||||||
|
if post_enable:
|
||||||
|
hapd.set("oci_freq_override_fils_assoc", "2462")
|
||||||
dev[0].request("ERP_FLUSH")
|
dev[0].request("ERP_FLUSH")
|
||||||
id = dev[0].connect(ssid, key_mgmt="FILS-SHA256",
|
id = dev[0].connect(ssid, key_mgmt="FILS-SHA256",
|
||||||
eap="PSK", identity="psk.user@example.com",
|
eap="PSK", identity="psk.user@example.com",
|
||||||
@ -1085,12 +1115,20 @@ def test_wpa2_ocv_ap_override_fils_assoc(dev, apdev, params):
|
|||||||
|
|
||||||
def test_wpa2_ocv_ap_override_ft_assoc(dev, apdev):
|
def test_wpa2_ocv_ap_override_ft_assoc(dev, apdev):
|
||||||
"""OCV on 2.4 GHz and AP override FT reassociation"""
|
"""OCV on 2.4 GHz and AP override FT reassociation"""
|
||||||
|
run_wpa2_ocv_ap_override_ft_assoc(dev, apdev)
|
||||||
|
|
||||||
|
def test_wpa2_ocv_ap_override_ft_assoc_post_enable(dev, apdev):
|
||||||
|
"""OCV on 2.4 GHz and AP override FT reassociation (post enable)"""
|
||||||
|
run_wpa2_ocv_ap_override_ft_assoc(dev, apdev, True)
|
||||||
|
|
||||||
|
def run_wpa2_ocv_ap_override_ft_assoc(dev, apdev, post_enable=False):
|
||||||
ssid = "test-wpa2-ocv"
|
ssid = "test-wpa2-ocv"
|
||||||
passphrase = "qwertyuiop"
|
passphrase = "qwertyuiop"
|
||||||
params = ft_params1(ssid=ssid, passphrase=passphrase)
|
params = ft_params1(ssid=ssid, passphrase=passphrase)
|
||||||
params["ieee80211w"] = "2"
|
params["ieee80211w"] = "2"
|
||||||
params["ocv"] = "1"
|
params["ocv"] = "1"
|
||||||
params["oci_freq_override_fils_assoc"] = "2462"
|
if not post_enable:
|
||||||
|
params["oci_freq_override_ft_assoc"] = "2462"
|
||||||
try:
|
try:
|
||||||
hapd0 = hostapd.add_ap(apdev[0], params)
|
hapd0 = hostapd.add_ap(apdev[0], params)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@ -1100,9 +1138,14 @@ def test_wpa2_ocv_ap_override_ft_assoc(dev, apdev):
|
|||||||
params = ft_params2(ssid=ssid, passphrase=passphrase)
|
params = ft_params2(ssid=ssid, passphrase=passphrase)
|
||||||
params["ieee80211w"] = "2"
|
params["ieee80211w"] = "2"
|
||||||
params["ocv"] = "1"
|
params["ocv"] = "1"
|
||||||
|
if not post_enable:
|
||||||
params["oci_freq_override_ft_assoc"] = "2462"
|
params["oci_freq_override_ft_assoc"] = "2462"
|
||||||
hapd1 = hostapd.add_ap(apdev[1], params)
|
hapd1 = hostapd.add_ap(apdev[1], params)
|
||||||
|
|
||||||
|
if post_enable:
|
||||||
|
hapd0.set("oci_freq_override_ft_assoc", "2462")
|
||||||
|
hapd1.set("oci_freq_override_ft_assoc", "2462")
|
||||||
|
|
||||||
dev[0].connect(ssid, key_mgmt="FT-PSK", psk=passphrase,
|
dev[0].connect(ssid, key_mgmt="FT-PSK", psk=passphrase,
|
||||||
scan_freq="2412", ocv="1", ieee80211w="2")
|
scan_freq="2412", ocv="1", ieee80211w="2")
|
||||||
|
|
||||||
|
@ -818,3 +818,54 @@ def test_p2p_group_cli_invalid(dev, apdev):
|
|||||||
ev = dev[i].wait_global_event(["P2P-DEVICE-FOUND"], timeout=5)
|
ev = dev[i].wait_global_event(["P2P-DEVICE-FOUND"], timeout=5)
|
||||||
if not ev:
|
if not ev:
|
||||||
raise Exception("P2P device not found")
|
raise Exception("P2P device not found")
|
||||||
|
|
||||||
|
def test_discovery_max_peers(dev):
|
||||||
|
"""P2P device discovery and maximum peer limit exceeded"""
|
||||||
|
dev[0].p2p_listen()
|
||||||
|
dev[0].request("SET ext_mgmt_frame_handling 1")
|
||||||
|
probereq1 = "40000000ffffffffffff"
|
||||||
|
probereq2 = "ffffffffffff000000074449524543542d01080c1218243048606c0301012d1afe131bffff000000000000000000000100000000000000000000ff16230178c812400000bfce0000000000000000fafffaffdd730050f204104a000110103a00010110080002314810470010572cf82fc95756539b16b5cfb298abf1105400080000000000000000103c0001031002000200001009000200001012000200001021000120102300012010240001201011000844657669636520421049000900372a000120030101dd11506f9a0902020025000605005858045106"
|
||||||
|
|
||||||
|
# Fill the P2P peer table with max+1 entries based on Probe Request frames
|
||||||
|
# to verify correct behavior on# removing the oldest entry when running out
|
||||||
|
# of room.
|
||||||
|
for i in range(101):
|
||||||
|
addr = "0202020202%02x" % i
|
||||||
|
probereq = probereq1 + addr + probereq2
|
||||||
|
if "OK" not in dev[0].request("MGMT_RX_PROCESS freq=2412 datarate=60 ssi_signal=-30 frame=" + probereq):
|
||||||
|
raise Exception("MGMT_RX_PROCESS failed")
|
||||||
|
|
||||||
|
res = dev[0].global_request("P2P_PEER FIRST")
|
||||||
|
addr = res.splitlines()[0]
|
||||||
|
peers = [addr]
|
||||||
|
limit = 200
|
||||||
|
while limit > 0:
|
||||||
|
res = dev[0].global_request("P2P_PEER NEXT-" + addr)
|
||||||
|
addr = res.splitlines()[0]
|
||||||
|
if addr == "FAIL":
|
||||||
|
break
|
||||||
|
peers.append(addr)
|
||||||
|
limit -= 1
|
||||||
|
logger.info("Peers: " + str(peers))
|
||||||
|
|
||||||
|
if len(peers) != 100:
|
||||||
|
raise Exception("Unexpected number of peer entries")
|
||||||
|
oldest = "02:02:02:02:02:00"
|
||||||
|
if oldest in peers:
|
||||||
|
raise Exception("Oldest entry is still present")
|
||||||
|
for i in range(101):
|
||||||
|
addr = "02:02:02:02:02:%02x" % i
|
||||||
|
if addr == oldest:
|
||||||
|
continue
|
||||||
|
if addr not in peers:
|
||||||
|
raise Exception("Peer missing from table: " + addr)
|
||||||
|
|
||||||
|
# Provision Discovery Request from the oldest peer (SA) using internally
|
||||||
|
# different P2P Device Address as a regression test for incorrect processing
|
||||||
|
# for this corner case.
|
||||||
|
dst = dev[0].own_addr().replace(':', '')
|
||||||
|
src = peers[99].replace(':', '')
|
||||||
|
devaddr = "0202020202ff"
|
||||||
|
pdreq = "d0004000" + dst + src + dst + "d0000409506f9a090701dd29506f9a0902020025000d1d00" + devaddr + "1108000000000000000000101100084465766963652041dd0a0050f204100800020008"
|
||||||
|
if "OK" not in dev[0].request("MGMT_RX_PROCESS freq=2412 datarate=60 ssi_signal=-30 frame=" + pdreq):
|
||||||
|
raise Exception("MGMT_RX_PROCESS failed")
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
import socket
|
import socket
|
||||||
import struct
|
import struct
|
||||||
import subprocess
|
import subprocess
|
||||||
|
import re
|
||||||
|
|
||||||
import hwsim_utils
|
import hwsim_utils
|
||||||
import hostapd
|
import hostapd
|
||||||
@ -231,9 +232,12 @@ def test_pasn_sae_pmksa_cache(dev, apdev):
|
|||||||
params = hostapd.wpa2_params(ssid="test-sae",
|
params = hostapd.wpa2_params(ssid="test-sae",
|
||||||
passphrase="12345678")
|
passphrase="12345678")
|
||||||
params['wpa_key_mgmt'] = 'SAE PASN'
|
params['wpa_key_mgmt'] = 'SAE PASN'
|
||||||
|
params['sae_pwe'] = "2"
|
||||||
hapd = start_pasn_ap(apdev[0], params)
|
hapd = start_pasn_ap(apdev[0], params)
|
||||||
|
|
||||||
|
try:
|
||||||
dev[0].set("sae_groups", "19")
|
dev[0].set("sae_groups", "19")
|
||||||
|
dev[0].set("sae_pwe", "2")
|
||||||
dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", scan_freq="2412")
|
dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", scan_freq="2412")
|
||||||
|
|
||||||
hapd.wait_sta()
|
hapd.wait_sta()
|
||||||
@ -243,6 +247,8 @@ def test_pasn_sae_pmksa_cache(dev, apdev):
|
|||||||
dev[0].wait_disconnected()
|
dev[0].wait_disconnected()
|
||||||
|
|
||||||
check_pasn_akmp_cipher(dev[0], hapd, "SAE", "CCMP")
|
check_pasn_akmp_cipher(dev[0], hapd, "SAE", "CCMP")
|
||||||
|
finally:
|
||||||
|
dev[0].set("sae_pwe", "0")
|
||||||
|
|
||||||
def check_pasn_fils_pmksa_cache(dev, apdev, params, key_mgmt):
|
def check_pasn_fils_pmksa_cache(dev, apdev, params, key_mgmt):
|
||||||
check_fils_capa(dev[0])
|
check_fils_capa(dev[0])
|
||||||
@ -298,16 +304,19 @@ def test_pasn_sae_kdk(dev, apdev):
|
|||||||
params = hostapd.wpa2_params(ssid="test-sae",
|
params = hostapd.wpa2_params(ssid="test-sae",
|
||||||
passphrase="12345678")
|
passphrase="12345678")
|
||||||
params['wpa_key_mgmt'] = 'SAE PASN'
|
params['wpa_key_mgmt'] = 'SAE PASN'
|
||||||
|
params['sae_pwe'] = "2"
|
||||||
params['force_kdk_derivation'] = "1"
|
params['force_kdk_derivation'] = "1"
|
||||||
hapd = start_pasn_ap(apdev[0], params)
|
hapd = start_pasn_ap(apdev[0], params)
|
||||||
|
|
||||||
dev[0].set("force_kdk_derivation", "1")
|
dev[0].set("force_kdk_derivation", "1")
|
||||||
|
dev[0].set("sae_pwe", "2")
|
||||||
dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
|
dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
|
||||||
scan_freq="2412")
|
scan_freq="2412")
|
||||||
|
|
||||||
check_pasn_ptk(dev[0], hapd, "CCMP", clear_keys=False)
|
check_pasn_ptk(dev[0], hapd, "CCMP", clear_keys=False)
|
||||||
finally:
|
finally:
|
||||||
dev[0].set("force_kdk_derivation", "0")
|
dev[0].set("force_kdk_derivation", "0")
|
||||||
|
dev[0].set("sae_pwe", "0")
|
||||||
|
|
||||||
|
|
||||||
def check_pasn_fils_kdk(dev, apdev, params, key_mgmt):
|
def check_pasn_fils_kdk(dev, apdev, params, key_mgmt):
|
||||||
@ -383,10 +392,13 @@ def test_pasn_sae(dev, apdev):
|
|||||||
params = hostapd.wpa2_params(ssid="test-pasn-sae",
|
params = hostapd.wpa2_params(ssid="test-pasn-sae",
|
||||||
passphrase="12345678")
|
passphrase="12345678")
|
||||||
params['wpa_key_mgmt'] = 'SAE PASN'
|
params['wpa_key_mgmt'] = 'SAE PASN'
|
||||||
|
params['sae_pwe'] = "2"
|
||||||
hapd = start_pasn_ap(apdev[0], params)
|
hapd = start_pasn_ap(apdev[0], params)
|
||||||
|
|
||||||
dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", scan_freq="2412",
|
try:
|
||||||
only_add_network=True)
|
dev[0].set("sae_pwe", "2")
|
||||||
|
dev[0].connect("test-pasn-sae", psk="12345678", key_mgmt="SAE",
|
||||||
|
scan_freq="2412", only_add_network=True)
|
||||||
|
|
||||||
# first test with a valid PSK
|
# first test with a valid PSK
|
||||||
check_pasn_akmp_cipher(dev[0], hapd, "SAE", "CCMP", nid="0")
|
check_pasn_akmp_cipher(dev[0], hapd, "SAE", "CCMP", nid="0")
|
||||||
@ -400,6 +412,8 @@ def test_pasn_sae(dev, apdev):
|
|||||||
|
|
||||||
dev[0].set_network_quoted(0, "psk", "12345678787")
|
dev[0].set_network_quoted(0, "psk", "12345678787")
|
||||||
check_pasn_akmp_cipher(dev[0], hapd, "SAE", "CCMP", status=1, nid="0")
|
check_pasn_akmp_cipher(dev[0], hapd, "SAE", "CCMP", status=1, nid="0")
|
||||||
|
finally:
|
||||||
|
dev[0].set("sae_pwe", "0")
|
||||||
|
|
||||||
@remote_compatible
|
@remote_compatible
|
||||||
def test_pasn_sae_while_connected_same_channel(dev, apdev):
|
def test_pasn_sae_while_connected_same_channel(dev, apdev):
|
||||||
@ -411,18 +425,23 @@ def test_pasn_sae_while_connected_same_channel(dev, apdev):
|
|||||||
passphrase="12345678")
|
passphrase="12345678")
|
||||||
hapd = hostapd.add_ap(apdev[0], params)
|
hapd = hostapd.add_ap(apdev[0], params)
|
||||||
|
|
||||||
|
try:
|
||||||
|
dev[0].set("sae_pwe", "2")
|
||||||
dev[0].connect("test-pasn-wpa2-psk", psk="12345678", scan_freq="2412")
|
dev[0].connect("test-pasn-wpa2-psk", psk="12345678", scan_freq="2412")
|
||||||
|
|
||||||
params = hostapd.wpa2_params(ssid="test-pasn-sae",
|
params = hostapd.wpa2_params(ssid="test-pasn-sae",
|
||||||
passphrase="12345678")
|
passphrase="12345678")
|
||||||
|
|
||||||
params['wpa_key_mgmt'] = 'SAE PASN'
|
params['wpa_key_mgmt'] = 'SAE PASN'
|
||||||
|
params['sae_pwe'] = "2"
|
||||||
hapd = start_pasn_ap(apdev[1], params)
|
hapd = start_pasn_ap(apdev[1], params)
|
||||||
|
|
||||||
dev[0].connect("test-pasn-sae", psk="12345678", key_mgmt="SAE",
|
dev[0].connect("test-pasn-sae", psk="12345678", key_mgmt="SAE",
|
||||||
scan_freq="2412", only_add_network=True)
|
scan_freq="2412", only_add_network=True)
|
||||||
|
|
||||||
check_pasn_akmp_cipher(dev[0], hapd, "SAE", "CCMP", nid="1")
|
check_pasn_akmp_cipher(dev[0], hapd, "SAE", "CCMP", nid="1")
|
||||||
|
finally:
|
||||||
|
dev[0].set("sae_pwe", "0")
|
||||||
|
|
||||||
@remote_compatible
|
@remote_compatible
|
||||||
def test_pasn_sae_while_connected_diff_channel(dev, apdev):
|
def test_pasn_sae_while_connected_diff_channel(dev, apdev):
|
||||||
@ -442,18 +461,23 @@ def test_pasn_sae_while_connected_diff_channel(dev, apdev):
|
|||||||
params['channel'] = "6"
|
params['channel'] = "6"
|
||||||
hapd = hostapd.add_ap(apdev[0], params)
|
hapd = hostapd.add_ap(apdev[0], params)
|
||||||
|
|
||||||
|
try:
|
||||||
|
wpas.set("sae_pwe", "2")
|
||||||
wpas.connect("test-pasn-wpa2-psk", psk="12345678", scan_freq="2437")
|
wpas.connect("test-pasn-wpa2-psk", psk="12345678", scan_freq="2437")
|
||||||
|
|
||||||
params = hostapd.wpa2_params(ssid="test-pasn-sae",
|
params = hostapd.wpa2_params(ssid="test-pasn-sae",
|
||||||
passphrase="12345678")
|
passphrase="12345678")
|
||||||
|
|
||||||
params['wpa_key_mgmt'] = 'SAE PASN'
|
params['wpa_key_mgmt'] = 'SAE PASN'
|
||||||
|
params['sae_pwe'] = "2"
|
||||||
hapd = start_pasn_ap(apdev[1], params)
|
hapd = start_pasn_ap(apdev[1], params)
|
||||||
|
|
||||||
wpas.connect("test-pasn-sae", psk="12345678", key_mgmt="SAE",
|
wpas.connect("test-pasn-sae", psk="12345678", key_mgmt="SAE",
|
||||||
scan_freq="2412", only_add_network=True)
|
scan_freq="2412", only_add_network=True)
|
||||||
|
|
||||||
check_pasn_akmp_cipher(wpas, hapd, "SAE", "CCMP", nid="1")
|
check_pasn_akmp_cipher(wpas, hapd, "SAE", "CCMP", nid="1")
|
||||||
|
finally:
|
||||||
|
wpas.set("sae_pwe", "0")
|
||||||
|
|
||||||
def pasn_fils_setup(wpas, apdev, params, key_mgmt):
|
def pasn_fils_setup(wpas, apdev, params, key_mgmt):
|
||||||
check_fils_capa(wpas)
|
check_fils_capa(wpas)
|
||||||
@ -681,3 +705,146 @@ def test_pasn_ap_mic_error(dev, apdev):
|
|||||||
|
|
||||||
check_pasn_akmp_cipher(dev[0], hapd1, "PASN", "CCMP", status=1)
|
check_pasn_akmp_cipher(dev[0], hapd1, "PASN", "CCMP", status=1)
|
||||||
check_pasn_akmp_cipher(dev[0], hapd0, "PASN", "CCMP")
|
check_pasn_akmp_cipher(dev[0], hapd0, "PASN", "CCMP")
|
||||||
|
|
||||||
|
@remote_compatible
|
||||||
|
def test_pasn_comeback(dev, apdev, params):
|
||||||
|
"""PASN authentication with comeback flow"""
|
||||||
|
check_pasn_capab(dev[0])
|
||||||
|
|
||||||
|
params = pasn_ap_params("PASN", "CCMP", "19")
|
||||||
|
params['sae_anti_clogging_threshold'] = '0'
|
||||||
|
hapd = hostapd.add_ap(apdev[0], params)
|
||||||
|
bssid = hapd.own_addr()
|
||||||
|
|
||||||
|
dev[0].scan(type="ONLY", freq=2412)
|
||||||
|
cmd = "PASN_START bssid=%s akmp=PASN cipher=CCMP group=19" % bssid
|
||||||
|
|
||||||
|
resp = dev[0].request(cmd)
|
||||||
|
if "OK" not in resp:
|
||||||
|
raise Exception("Failed to start PASN authentication")
|
||||||
|
|
||||||
|
ev = dev[0].wait_event(["PASN-AUTH-STATUS"], 3)
|
||||||
|
if not ev:
|
||||||
|
raise Exception("PASN: PASN-AUTH-STATUS not seen")
|
||||||
|
|
||||||
|
if bssid + " akmp=PASN, status=30 comeback_after=" not in ev:
|
||||||
|
raise Exception("PASN: unexpected status")
|
||||||
|
|
||||||
|
comeback = re.split("comeback=", ev)[1]
|
||||||
|
|
||||||
|
cmd = "PASN_START bssid=%s akmp=PASN cipher=CCMP group=19 comeback=%s" % \
|
||||||
|
(bssid, comeback)
|
||||||
|
|
||||||
|
resp = dev[0].request(cmd)
|
||||||
|
if "OK" not in resp:
|
||||||
|
raise Exception("Failed to start PASN authentication")
|
||||||
|
|
||||||
|
ev = dev[0].wait_event(["PASN-AUTH-STATUS"], 3)
|
||||||
|
if not ev:
|
||||||
|
raise Exception("PASN: PASN-AUTH-STATUS not seen")
|
||||||
|
|
||||||
|
if bssid + " akmp=PASN, status=0" not in ev:
|
||||||
|
raise Exception("PASN: unexpected status with comeback token")
|
||||||
|
|
||||||
|
check_pasn_ptk(dev[0], hapd, "CCMP")
|
||||||
|
|
||||||
|
@remote_compatible
|
||||||
|
def test_pasn_comeback_after_0(dev, apdev, params):
|
||||||
|
"""PASN authentication with comeback flow with comeback after set to 0"""
|
||||||
|
check_pasn_capab(dev[0])
|
||||||
|
|
||||||
|
params = pasn_ap_params("PASN", "CCMP", "19")
|
||||||
|
params['anti_clogging_threshold'] = '0'
|
||||||
|
params['pasn_comeback_after'] = '0'
|
||||||
|
hapd = start_pasn_ap(apdev[0], params)
|
||||||
|
|
||||||
|
check_pasn_akmp_cipher(dev[0], hapd, "PASN", "CCMP")
|
||||||
|
|
||||||
|
@remote_compatible
|
||||||
|
def test_pasn_comeback_after_0_sae(dev, apdev):
|
||||||
|
"""PASN authentication with SAE, with comeback flow where comeback after is set to 0"""
|
||||||
|
check_pasn_capab(dev[0])
|
||||||
|
check_sae_capab(dev[0])
|
||||||
|
|
||||||
|
params = hostapd.wpa2_params(ssid="test-pasn-sae",
|
||||||
|
passphrase="12345678")
|
||||||
|
params['wpa_key_mgmt'] = 'SAE PASN'
|
||||||
|
params['anti_clogging_threshold'] = '0'
|
||||||
|
params['pasn_comeback_after'] = '0'
|
||||||
|
params['sae_pwe'] = "2"
|
||||||
|
hapd = start_pasn_ap(apdev[0], params)
|
||||||
|
|
||||||
|
try:
|
||||||
|
dev[0].set("sae_pwe", "2")
|
||||||
|
dev[0].connect("test-pasn-sae", psk="12345678", key_mgmt="SAE",
|
||||||
|
scan_freq="2412", only_add_network=True)
|
||||||
|
|
||||||
|
# first test with a valid PSK
|
||||||
|
check_pasn_akmp_cipher(dev[0], hapd, "SAE", "CCMP", nid="0")
|
||||||
|
|
||||||
|
# And now with PMKSA caching
|
||||||
|
check_pasn_akmp_cipher(dev[0], hapd, "SAE", "CCMP")
|
||||||
|
|
||||||
|
# And now with a wrong passphrase
|
||||||
|
if "FAIL" in dev[0].request("PMKSA_FLUSH"):
|
||||||
|
raise Exception("PMKSA_FLUSH failed")
|
||||||
|
|
||||||
|
dev[0].set_network_quoted(0, "psk", "12345678787")
|
||||||
|
check_pasn_akmp_cipher(dev[0], hapd, "SAE", "CCMP", status=1, nid="0")
|
||||||
|
finally:
|
||||||
|
dev[0].set("sae_pwe", "0")
|
||||||
|
|
||||||
|
@remote_compatible
|
||||||
|
def test_pasn_comeback_multi(dev, apdev):
|
||||||
|
"""PASN authentication with SAE, with multiple stations with comeback"""
|
||||||
|
check_pasn_capab(dev[0])
|
||||||
|
check_sae_capab(dev[0])
|
||||||
|
|
||||||
|
params = hostapd.wpa2_params(ssid="test-pasn-sae",
|
||||||
|
passphrase="12345678")
|
||||||
|
params['wpa_key_mgmt'] = 'SAE PASN'
|
||||||
|
params['anti_clogging_threshold'] = '1'
|
||||||
|
params['pasn_comeback_after'] = '0'
|
||||||
|
hapd = start_pasn_ap(apdev[0], params)
|
||||||
|
bssid = hapd.own_addr()
|
||||||
|
|
||||||
|
id = {}
|
||||||
|
for i in range(0, 2):
|
||||||
|
dev[i].flush_scan_cache()
|
||||||
|
dev[i].scan(type="ONLY", freq=2412)
|
||||||
|
id[i] = dev[i].connect("test-pasn-sae", psk="12345678", key_mgmt="SAE",
|
||||||
|
scan_freq="2412", only_add_network=True)
|
||||||
|
|
||||||
|
for i in range(0, 2):
|
||||||
|
cmd = "PASN_START bssid=%s akmp=PASN cipher=CCMP group=19, nid=%s" % (bssid, id[i])
|
||||||
|
resp = dev[i].request(cmd)
|
||||||
|
|
||||||
|
if "OK" not in resp:
|
||||||
|
raise Exception("Failed to start pasn authentication")
|
||||||
|
|
||||||
|
for i in range(0, 2):
|
||||||
|
ev = dev[i].wait_event(["PASN-AUTH-STATUS"], 3)
|
||||||
|
if not ev:
|
||||||
|
raise Exception("PASN: PASN-AUTH-STATUS not seen")
|
||||||
|
|
||||||
|
if bssid + " akmp=PASN, status=0" not in ev:
|
||||||
|
raise Exception("PASN: unexpected status")
|
||||||
|
|
||||||
|
check_pasn_ptk(dev[i], hapd, "CCMP")
|
||||||
|
|
||||||
|
def test_pasn_kdk_derivation(dev, apdev):
|
||||||
|
"""PASN authentication with forced KDK derivation"""
|
||||||
|
check_pasn_capab(dev[0])
|
||||||
|
|
||||||
|
params = pasn_ap_params("PASN", "CCMP", "19")
|
||||||
|
hapd0 = start_pasn_ap(apdev[0], params)
|
||||||
|
|
||||||
|
params['force_kdk_derivation'] = "1"
|
||||||
|
hapd1 = start_pasn_ap(apdev[1], params)
|
||||||
|
|
||||||
|
try:
|
||||||
|
check_pasn_akmp_cipher(dev[0], hapd0, "PASN", "CCMP")
|
||||||
|
dev[0].set("force_kdk_derivation", "1")
|
||||||
|
check_pasn_akmp_cipher(dev[0], hapd1, "PASN", "CCMP")
|
||||||
|
finally:
|
||||||
|
dev[0].set("force_kdk_derivation", "0")
|
||||||
|
@ -1251,3 +1251,17 @@ def test_rsn_preauth_local_errors(dev, apdev):
|
|||||||
raise Exception("ENABLE failed")
|
raise Exception("ENABLE failed")
|
||||||
sock.send(_bssid + foreign + proto + struct.pack('>BBH', 2, 1, 0))
|
sock.send(_bssid + foreign + proto + struct.pack('>BBH', 2, 1, 0))
|
||||||
sock.send(_bssid + foreign2 + proto + struct.pack('>BBH', 2, 1, 0))
|
sock.send(_bssid + foreign2 + proto + struct.pack('>BBH', 2, 1, 0))
|
||||||
|
|
||||||
|
def test_pmksa_cache_add_failure(dev, apdev):
|
||||||
|
"""PMKSA cache add failure"""
|
||||||
|
params = hostapd.wpa2_eap_params(ssid="test-pmksa-cache")
|
||||||
|
hostapd.add_ap(apdev[0], params)
|
||||||
|
bssid = apdev[0]['bssid']
|
||||||
|
with alloc_fail(dev[0], 1, "pmksa_cache_add"):
|
||||||
|
dev[0].connect("test-pmksa-cache", proto="RSN", key_mgmt="WPA-EAP",
|
||||||
|
eap="GPSK", identity="gpsk user",
|
||||||
|
password="abcdefghijklmnop0123456789abcdef",
|
||||||
|
scan_freq="2412")
|
||||||
|
pmksa = dev[0].get_pmksa(bssid)
|
||||||
|
if pmksa is None:
|
||||||
|
raise Exception("No PMKSA cache entry created")
|
||||||
|
@ -212,6 +212,20 @@ def test_rrm_neighbor_db(dev, apdev):
|
|||||||
if apdev[0]['bssid'] not in res:
|
if apdev[0]['bssid'] not in res:
|
||||||
raise Exception("Own BSS not visible in SHOW_NEIGHBOR output")
|
raise Exception("Own BSS not visible in SHOW_NEIGHBOR output")
|
||||||
|
|
||||||
|
def test_rrm_neighbor_db_failures(dev, apdev):
|
||||||
|
"""hostapd ctrl_iface SET_NEIGHBOR failures"""
|
||||||
|
params = {"ssid": "test", "rrm_neighbor_report": "1"}
|
||||||
|
hapd = hostapd.add_ap(apdev[0]['ifname'], params)
|
||||||
|
cmd = "SET_NEIGHBOR 00:11:22:33:44:55 ssid=\"test1\" nr=" + nr + " lci=" + lci + " civic=" + civic
|
||||||
|
tests = [(1, "hostapd_neighbor_add"),
|
||||||
|
(1, "wpabuf_dup;hostapd_neighbor_set"),
|
||||||
|
(2, "wpabuf_dup;hostapd_neighbor_set"),
|
||||||
|
(3, "wpabuf_dup;hostapd_neighbor_set")]
|
||||||
|
for count, func in tests:
|
||||||
|
with alloc_fail(hapd, count, func):
|
||||||
|
if "FAIL" not in hapd.request(cmd):
|
||||||
|
raise Exception("Set neighbor succeeded")
|
||||||
|
|
||||||
def test_rrm_neighbor_db_disabled(dev, apdev):
|
def test_rrm_neighbor_db_disabled(dev, apdev):
|
||||||
"""hostapd ctrl_iface SHOW_NEIGHBOR while neighbor report disabled"""
|
"""hostapd ctrl_iface SHOW_NEIGHBOR while neighbor report disabled"""
|
||||||
params = {"ssid": "test"}
|
params = {"ssid": "test"}
|
||||||
|
@ -37,7 +37,8 @@ def start_wnm_ap(apdev, bss_transition=True, time_adv=False, ssid=None,
|
|||||||
wnm_sleep_mode=False, wnm_sleep_mode_no_keys=False, rsn=False,
|
wnm_sleep_mode=False, wnm_sleep_mode_no_keys=False, rsn=False,
|
||||||
ocv=False, ap_max_inactivity=0, coloc_intf_reporting=False,
|
ocv=False, ap_max_inactivity=0, coloc_intf_reporting=False,
|
||||||
hw_mode=None, channel=None, country_code=None, country3=None,
|
hw_mode=None, channel=None, country_code=None, country3=None,
|
||||||
pmf=True, passphrase=None, ht=True, vht=False, mbo=False):
|
pmf=True, passphrase=None, ht=True, vht=False, mbo=False,
|
||||||
|
beacon_prot=False):
|
||||||
if rsn:
|
if rsn:
|
||||||
if not ssid:
|
if not ssid:
|
||||||
ssid = "test-wnm-rsn"
|
ssid = "test-wnm-rsn"
|
||||||
@ -47,6 +48,8 @@ def start_wnm_ap(apdev, bss_transition=True, time_adv=False, ssid=None,
|
|||||||
if pmf:
|
if pmf:
|
||||||
params["wpa_key_mgmt"] = "WPA-PSK-SHA256"
|
params["wpa_key_mgmt"] = "WPA-PSK-SHA256"
|
||||||
params["ieee80211w"] = "2"
|
params["ieee80211w"] = "2"
|
||||||
|
if beacon_prot:
|
||||||
|
params["beacon_prot"] = "1"
|
||||||
else:
|
else:
|
||||||
params = {"ssid": "test-wnm"}
|
params = {"ssid": "test-wnm"}
|
||||||
if bss_transition:
|
if bss_transition:
|
||||||
@ -195,7 +198,8 @@ def test_wnm_ess_disassoc_imminent_pmf(dev, apdev):
|
|||||||
if ev is None:
|
if ev is None:
|
||||||
raise Exception("Timeout while waiting for re-connection scan")
|
raise Exception("Timeout while waiting for re-connection scan")
|
||||||
|
|
||||||
def check_wnm_sleep_mode_enter_exit(hapd, dev, interval=None, tfs_req=None):
|
def check_wnm_sleep_mode_enter_exit(hapd, dev, interval=None, tfs_req=None,
|
||||||
|
rekey=False):
|
||||||
addr = dev.p2p_interface_addr()
|
addr = dev.p2p_interface_addr()
|
||||||
sta = hapd.get_sta(addr)
|
sta = hapd.get_sta(addr)
|
||||||
if "[WNM_SLEEP_MODE]" in sta['flags']:
|
if "[WNM_SLEEP_MODE]" in sta['flags']:
|
||||||
@ -219,6 +223,14 @@ def check_wnm_sleep_mode_enter_exit(hapd, dev, interval=None, tfs_req=None):
|
|||||||
if not ok:
|
if not ok:
|
||||||
raise Exception("Station failed to enter WNM-Sleep Mode")
|
raise Exception("Station failed to enter WNM-Sleep Mode")
|
||||||
|
|
||||||
|
if rekey:
|
||||||
|
time.sleep(0.1)
|
||||||
|
if "OK" not in hapd.request("REKEY_GTK"):
|
||||||
|
raise Exception("REKEY_GTK failed")
|
||||||
|
ev = dev.wait_event(["WPA: Group rekeying completed"], timeout=0.1)
|
||||||
|
if ev is not None:
|
||||||
|
raise Exception("Unexpected report of GTK rekey during WNM-Sleep Mode")
|
||||||
|
|
||||||
logger.info("Waking up from WNM Sleep Mode")
|
logger.info("Waking up from WNM Sleep Mode")
|
||||||
ok = False
|
ok = False
|
||||||
dev.request("WNM_SLEEP exit")
|
dev.request("WNM_SLEEP exit")
|
||||||
@ -231,6 +243,14 @@ def check_wnm_sleep_mode_enter_exit(hapd, dev, interval=None, tfs_req=None):
|
|||||||
if not ok:
|
if not ok:
|
||||||
raise Exception("Station failed to exit WNM-Sleep Mode")
|
raise Exception("Station failed to exit WNM-Sleep Mode")
|
||||||
|
|
||||||
|
if rekey:
|
||||||
|
time.sleep(0.1)
|
||||||
|
if "OK" not in hapd.request("REKEY_GTK"):
|
||||||
|
raise Exception("REKEY_GTK failed")
|
||||||
|
ev = dev.wait_event(["WPA: Group rekeying completed"], timeout=2)
|
||||||
|
if ev is None:
|
||||||
|
raise Exception("GTK rekey timed out")
|
||||||
|
|
||||||
@remote_compatible
|
@remote_compatible
|
||||||
def test_wnm_sleep_mode_open(dev, apdev):
|
def test_wnm_sleep_mode_open(dev, apdev):
|
||||||
"""WNM Sleep Mode - open"""
|
"""WNM Sleep Mode - open"""
|
||||||
@ -303,6 +323,19 @@ def test_wnm_sleep_mode_rsn_pmf(dev, apdev):
|
|||||||
raise Exception("No connection event received from hostapd")
|
raise Exception("No connection event received from hostapd")
|
||||||
check_wnm_sleep_mode_enter_exit(hapd, dev[0])
|
check_wnm_sleep_mode_enter_exit(hapd, dev[0])
|
||||||
|
|
||||||
|
def test_wnm_sleep_mode_rsn_beacon_prot(dev, apdev):
|
||||||
|
"""WNM Sleep Mode - RSN with PMF and beacon protection"""
|
||||||
|
hapd = start_wnm_ap(apdev[0], rsn=True, wnm_sleep_mode=True, time_adv=True,
|
||||||
|
beacon_prot=True)
|
||||||
|
dev[0].connect("test-wnm-rsn", psk="12345678", ieee80211w="2",
|
||||||
|
beacon_prot="1",
|
||||||
|
key_mgmt="WPA-PSK-SHA256", proto="WPA2", scan_freq="2412")
|
||||||
|
ev = hapd.wait_event(["AP-STA-CONNECTED"], timeout=5)
|
||||||
|
if ev is None:
|
||||||
|
raise Exception("No connection event received from hostapd")
|
||||||
|
check_wnm_sleep_mode_enter_exit(hapd, dev[0])
|
||||||
|
check_wnm_sleep_mode_enter_exit(hapd, dev[0], rekey=True)
|
||||||
|
|
||||||
@remote_compatible
|
@remote_compatible
|
||||||
def test_wnm_sleep_mode_rsn_ocv(dev, apdev):
|
def test_wnm_sleep_mode_rsn_ocv(dev, apdev):
|
||||||
"""WNM Sleep Mode - RSN with OCV"""
|
"""WNM Sleep Mode - RSN with OCV"""
|
||||||
|
@ -1402,6 +1402,8 @@ def test_wpas_ctrl_driver_event(dev, apdev):
|
|||||||
"""wpa_supplicant ctrl_iface DRIVER_EVENT"""
|
"""wpa_supplicant ctrl_iface DRIVER_EVENT"""
|
||||||
if "FAIL" not in dev[0].request("DRIVER_EVENT foo"):
|
if "FAIL" not in dev[0].request("DRIVER_EVENT foo"):
|
||||||
raise Exception("Invalid DRIVER_EVENT accepted")
|
raise Exception("Invalid DRIVER_EVENT accepted")
|
||||||
|
if "OK" not in dev[0].request("DRIVER_EVENT ASSOC reassoc=1 req_ies=0000 resp_ies=0000 resp_frame=0000 beacon_ies=0000 freq=2412 wmm::info_bitmap=0 wmm::uapsd_queues=0 addr=02:02:02:02:02:02 authorized=0 key_replay_ctr=00 ptk_kck=00 ptk_kek=00 subnet_status=0 fils_erp_next_seq_num=0 fils_pmk=00 fils_pmkid=" + 16*"00"):
|
||||||
|
raise Exception("DRIVER_EVENT ASSOC did not succeed")
|
||||||
|
|
||||||
@remote_compatible
|
@remote_compatible
|
||||||
def test_wpas_ctrl_eapol_rx(dev, apdev):
|
def test_wpas_ctrl_eapol_rx(dev, apdev):
|
||||||
@ -2147,3 +2149,11 @@ def test_wpas_ctrl_get_pref_freq_list_override(dev):
|
|||||||
dev[0].set("get_pref_freq_list_override", "")
|
dev[0].set("get_pref_freq_list_override", "")
|
||||||
res = dev[0].request("GET_PREF_FREQ_LIST STATION").strip()
|
res = dev[0].request("GET_PREF_FREQ_LIST STATION").strip()
|
||||||
logger.info("STATION (without override): " + res)
|
logger.info("STATION (without override): " + res)
|
||||||
|
|
||||||
|
def test_wpas_ctrl_interface_add_driver_init_failure(dev, apdev):
|
||||||
|
"""wpa_supplicant INTERFACE_ADD and driver init failing"""
|
||||||
|
for i in range(1000):
|
||||||
|
res = dev[0].global_request("INTERFACE_ADD FOO")
|
||||||
|
if "FAIL" not in res:
|
||||||
|
raise Exception("Unexpected result: " + res)
|
||||||
|
dev[0].dump_monitor()
|
||||||
|
@ -15,11 +15,16 @@ mount sysfs -t sysfs /sys
|
|||||||
# needed for tracing
|
# needed for tracing
|
||||||
mount debugfs -t debugfs /sys/kernel/debug
|
mount debugfs -t debugfs /sys/kernel/debug
|
||||||
|
|
||||||
|
mkdir /tmp/wireshark-share
|
||||||
|
mount --bind /usr/share/wireshark /tmp/wireshark-share
|
||||||
|
mount tmpfs -t tmpfs /usr/share/wireshark
|
||||||
|
|
||||||
# for inside telnet
|
# for inside telnet
|
||||||
mkdir /dev/pts
|
mkdir /dev/pts
|
||||||
mount devpts -t devpts /dev/pts
|
mount devpts -t devpts /dev/pts
|
||||||
|
|
||||||
export PATH=/usr/sbin:$PATH
|
export PATH=/usr/sbin:$PATH
|
||||||
|
export HOME=/tmp
|
||||||
|
|
||||||
# reboot on any sort of crash
|
# reboot on any sort of crash
|
||||||
sysctl kernel.panic_on_oops=1
|
sysctl kernel.panic_on_oops=1
|
||||||
|
@ -512,6 +512,19 @@ static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s,
|
|||||||
} else if (os_strcasecmp(cmd, "EAPOL::maxStart") == 0) {
|
} else if (os_strcasecmp(cmd, "EAPOL::maxStart") == 0) {
|
||||||
eapol_sm_configure(wpa_s->eapol,
|
eapol_sm_configure(wpa_s->eapol,
|
||||||
-1, -1, -1, atoi(value));
|
-1, -1, -1, atoi(value));
|
||||||
|
#ifdef CONFIG_TESTING_OPTIONS
|
||||||
|
} else if (os_strcasecmp(cmd, "EAPOL::portControl") == 0) {
|
||||||
|
if (os_strcmp(value, "Auto") == 0)
|
||||||
|
eapol_sm_notify_portControl(wpa_s->eapol, Auto);
|
||||||
|
else if (os_strcmp(value, "ForceUnauthorized") == 0)
|
||||||
|
eapol_sm_notify_portControl(wpa_s->eapol,
|
||||||
|
ForceUnauthorized);
|
||||||
|
else if (os_strcmp(value, "ForceAuthorized") == 0)
|
||||||
|
eapol_sm_notify_portControl(wpa_s->eapol,
|
||||||
|
ForceAuthorized);
|
||||||
|
else
|
||||||
|
ret = -1;
|
||||||
|
#endif /* CONFIG_TESTING_OPTIONS */
|
||||||
} else if (os_strcasecmp(cmd, "dot11RSNAConfigPMKLifetime") == 0) {
|
} else if (os_strcasecmp(cmd, "dot11RSNAConfigPMKLifetime") == 0) {
|
||||||
if (wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
|
if (wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
|
||||||
atoi(value))) {
|
atoi(value))) {
|
||||||
@ -2999,20 +3012,18 @@ static int wpa_supplicant_ctrl_iface_scan_result(
|
|||||||
ie2, 2 + ie2[1]);
|
ie2, 2 + ie2[1]);
|
||||||
}
|
}
|
||||||
rsnxe = wpa_bss_get_ie(bss, WLAN_EID_RSNX);
|
rsnxe = wpa_bss_get_ie(bss, WLAN_EID_RSNX);
|
||||||
if (rsnxe && rsnxe[1] >= 1) {
|
if (ieee802_11_rsnx_capab(rsnxe, WLAN_RSNX_CAPAB_SAE_H2E)) {
|
||||||
if (rsnxe[2] & BIT(WLAN_RSNX_CAPAB_SAE_H2E)) {
|
|
||||||
ret = os_snprintf(pos, end - pos, "[SAE-H2E]");
|
ret = os_snprintf(pos, end - pos, "[SAE-H2E]");
|
||||||
if (os_snprintf_error(end - pos, ret))
|
if (os_snprintf_error(end - pos, ret))
|
||||||
return -1;
|
return -1;
|
||||||
pos += ret;
|
pos += ret;
|
||||||
}
|
}
|
||||||
if (rsnxe[2] & BIT(WLAN_RSNX_CAPAB_SAE_PK)) {
|
if (ieee802_11_rsnx_capab(rsnxe, WLAN_RSNX_CAPAB_SAE_PK)) {
|
||||||
ret = os_snprintf(pos, end - pos, "[SAE-PK]");
|
ret = os_snprintf(pos, end - pos, "[SAE-PK]");
|
||||||
if (os_snprintf_error(end - pos, ret))
|
if (os_snprintf_error(end - pos, ret))
|
||||||
return -1;
|
return -1;
|
||||||
pos += ret;
|
pos += ret;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
osen_ie = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE);
|
osen_ie = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE);
|
||||||
if (osen_ie)
|
if (osen_ie)
|
||||||
pos = wpa_supplicant_ie_txt(pos, end, "OSEN",
|
pos = wpa_supplicant_ie_txt(pos, end, "OSEN",
|
||||||
@ -5099,20 +5110,18 @@ static int print_bss_info(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
|
|||||||
mesh ? "RSN" : "WPA2", ie2,
|
mesh ? "RSN" : "WPA2", ie2,
|
||||||
2 + ie2[1]);
|
2 + ie2[1]);
|
||||||
rsnxe = wpa_bss_get_ie(bss, WLAN_EID_RSNX);
|
rsnxe = wpa_bss_get_ie(bss, WLAN_EID_RSNX);
|
||||||
if (rsnxe && rsnxe[1] >= 1) {
|
if (ieee802_11_rsnx_capab(rsnxe, WLAN_RSNX_CAPAB_SAE_H2E)) {
|
||||||
if (rsnxe[2] & BIT(WLAN_RSNX_CAPAB_SAE_H2E)) {
|
|
||||||
ret = os_snprintf(pos, end - pos, "[SAE-H2E]");
|
ret = os_snprintf(pos, end - pos, "[SAE-H2E]");
|
||||||
if (os_snprintf_error(end - pos, ret))
|
if (os_snprintf_error(end - pos, ret))
|
||||||
return -1;
|
return -1;
|
||||||
pos += ret;
|
pos += ret;
|
||||||
}
|
}
|
||||||
if (rsnxe[2] & BIT(WLAN_RSNX_CAPAB_SAE_PK)) {
|
if (ieee802_11_rsnx_capab(rsnxe, WLAN_RSNX_CAPAB_SAE_PK)) {
|
||||||
ret = os_snprintf(pos, end - pos, "[SAE-PK]");
|
ret = os_snprintf(pos, end - pos, "[SAE-PK]");
|
||||||
if (os_snprintf_error(end - pos, ret))
|
if (os_snprintf_error(end - pos, ret))
|
||||||
return -1;
|
return -1;
|
||||||
pos += ret;
|
pos += ret;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
osen_ie = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE);
|
osen_ie = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE);
|
||||||
if (osen_ie)
|
if (osen_ie)
|
||||||
pos = wpa_supplicant_ie_txt(pos, end, "OSEN",
|
pos = wpa_supplicant_ie_txt(pos, end, "OSEN",
|
||||||
@ -9300,6 +9309,132 @@ static int wpas_ctrl_iface_driver_scan_res(struct wpa_supplicant *wpa_s,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int wpas_ctrl_iface_driver_event_assoc(struct wpa_supplicant *wpa_s,
|
||||||
|
char *param)
|
||||||
|
{
|
||||||
|
union wpa_event_data event;
|
||||||
|
struct assoc_info *ai;
|
||||||
|
char *ctx = NULL;
|
||||||
|
int ret = -1;
|
||||||
|
struct wpabuf *req_ies = NULL;
|
||||||
|
struct wpabuf *resp_ies = NULL;
|
||||||
|
struct wpabuf *resp_frame = NULL;
|
||||||
|
struct wpabuf *beacon_ies = NULL;
|
||||||
|
struct wpabuf *key_replay_ctr = NULL;
|
||||||
|
struct wpabuf *ptk_kck = NULL;
|
||||||
|
struct wpabuf *ptk_kek = NULL;
|
||||||
|
struct wpabuf *fils_pmk = NULL;
|
||||||
|
char *str, *pos;
|
||||||
|
u8 addr[ETH_ALEN];
|
||||||
|
u8 fils_pmkid[PMKID_LEN];
|
||||||
|
|
||||||
|
os_memset(&event, 0, sizeof(event));
|
||||||
|
ai = &event.assoc_info;
|
||||||
|
|
||||||
|
while ((str = str_token(param, " ", &ctx))) {
|
||||||
|
pos = os_strchr(str, '=');
|
||||||
|
if (!pos)
|
||||||
|
goto fail;
|
||||||
|
*pos++ = '\0';
|
||||||
|
|
||||||
|
if (os_strcmp(str, "reassoc") == 0) {
|
||||||
|
ai->reassoc = atoi(pos);
|
||||||
|
} else if (os_strcmp(str, "req_ies") == 0) {
|
||||||
|
wpabuf_free(req_ies);
|
||||||
|
req_ies = wpabuf_parse_bin(pos);
|
||||||
|
if (!req_ies)
|
||||||
|
goto fail;
|
||||||
|
ai->req_ies = wpabuf_head(req_ies);
|
||||||
|
ai->req_ies_len = wpabuf_len(req_ies);
|
||||||
|
} else if (os_strcmp(str, "resp_ies") == 0) {
|
||||||
|
wpabuf_free(resp_ies);
|
||||||
|
resp_ies = wpabuf_parse_bin(pos);
|
||||||
|
if (!resp_ies)
|
||||||
|
goto fail;
|
||||||
|
ai->resp_ies = wpabuf_head(resp_ies);
|
||||||
|
ai->resp_ies_len = wpabuf_len(resp_ies);
|
||||||
|
} else if (os_strcmp(str, "resp_frame") == 0) {
|
||||||
|
wpabuf_free(resp_frame);
|
||||||
|
resp_frame = wpabuf_parse_bin(pos);
|
||||||
|
if (!resp_frame)
|
||||||
|
goto fail;
|
||||||
|
ai->resp_frame = wpabuf_head(resp_frame);
|
||||||
|
ai->resp_frame_len = wpabuf_len(resp_frame);
|
||||||
|
} else if (os_strcmp(str, "beacon_ies") == 0) {
|
||||||
|
wpabuf_free(beacon_ies);
|
||||||
|
beacon_ies = wpabuf_parse_bin(pos);
|
||||||
|
if (!beacon_ies)
|
||||||
|
goto fail;
|
||||||
|
ai->beacon_ies = wpabuf_head(beacon_ies);
|
||||||
|
ai->beacon_ies_len = wpabuf_len(beacon_ies);
|
||||||
|
} else if (os_strcmp(str, "freq") == 0) {
|
||||||
|
ai->freq = atoi(pos);
|
||||||
|
} else if (os_strcmp(str, "wmm::info_bitmap") == 0) {
|
||||||
|
ai->wmm_params.info_bitmap = atoi(pos);
|
||||||
|
} else if (os_strcmp(str, "wmm::uapsd_queues") == 0) {
|
||||||
|
ai->wmm_params.uapsd_queues = atoi(pos);
|
||||||
|
} else if (os_strcmp(str, "addr") == 0) {
|
||||||
|
if (hwaddr_aton(pos, addr))
|
||||||
|
goto fail;
|
||||||
|
ai->addr = addr;
|
||||||
|
} else if (os_strcmp(str, "authorized") == 0) {
|
||||||
|
ai->authorized = atoi(pos);
|
||||||
|
} else if (os_strcmp(str, "key_replay_ctr") == 0) {
|
||||||
|
wpabuf_free(key_replay_ctr);
|
||||||
|
key_replay_ctr = wpabuf_parse_bin(pos);
|
||||||
|
if (!key_replay_ctr)
|
||||||
|
goto fail;
|
||||||
|
ai->key_replay_ctr = wpabuf_head(key_replay_ctr);
|
||||||
|
ai->key_replay_ctr_len = wpabuf_len(key_replay_ctr);
|
||||||
|
} else if (os_strcmp(str, "ptk_kck") == 0) {
|
||||||
|
wpabuf_free(ptk_kck);
|
||||||
|
ptk_kck = wpabuf_parse_bin(pos);
|
||||||
|
if (!ptk_kck)
|
||||||
|
goto fail;
|
||||||
|
ai->ptk_kck = wpabuf_head(ptk_kck);
|
||||||
|
ai->ptk_kck_len = wpabuf_len(ptk_kck);
|
||||||
|
} else if (os_strcmp(str, "ptk_kek") == 0) {
|
||||||
|
wpabuf_free(ptk_kek);
|
||||||
|
ptk_kek = wpabuf_parse_bin(pos);
|
||||||
|
if (!ptk_kek)
|
||||||
|
goto fail;
|
||||||
|
ai->ptk_kek = wpabuf_head(ptk_kek);
|
||||||
|
ai->ptk_kek_len = wpabuf_len(ptk_kek);
|
||||||
|
} else if (os_strcmp(str, "subnet_status") == 0) {
|
||||||
|
ai->subnet_status = atoi(pos);
|
||||||
|
} else if (os_strcmp(str, "fils_erp_next_seq_num") == 0) {
|
||||||
|
ai->fils_erp_next_seq_num = atoi(pos);
|
||||||
|
} else if (os_strcmp(str, "fils_pmk") == 0) {
|
||||||
|
wpabuf_free(fils_pmk);
|
||||||
|
fils_pmk = wpabuf_parse_bin(pos);
|
||||||
|
if (!fils_pmk)
|
||||||
|
goto fail;
|
||||||
|
ai->fils_pmk = wpabuf_head(fils_pmk);
|
||||||
|
ai->fils_pmk_len = wpabuf_len(fils_pmk);
|
||||||
|
} else if (os_strcmp(str, "fils_pmkid") == 0) {
|
||||||
|
if (hexstr2bin(pos, fils_pmkid, PMKID_LEN) < 0)
|
||||||
|
goto fail;
|
||||||
|
ai->fils_pmkid = fils_pmkid;
|
||||||
|
} else {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
wpa_supplicant_event(wpa_s, EVENT_ASSOC, &event);
|
||||||
|
ret = 0;
|
||||||
|
fail:
|
||||||
|
wpabuf_free(req_ies);
|
||||||
|
wpabuf_free(resp_ies);
|
||||||
|
wpabuf_free(resp_frame);
|
||||||
|
wpabuf_free(beacon_ies);
|
||||||
|
wpabuf_free(key_replay_ctr);
|
||||||
|
wpabuf_free(ptk_kck);
|
||||||
|
wpabuf_free(ptk_kek);
|
||||||
|
wpabuf_free(fils_pmk);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int wpas_ctrl_iface_driver_event(struct wpa_supplicant *wpa_s, char *cmd)
|
static int wpas_ctrl_iface_driver_event(struct wpa_supplicant *wpa_s, char *cmd)
|
||||||
{
|
{
|
||||||
char *pos, *param;
|
char *pos, *param;
|
||||||
@ -9332,6 +9467,8 @@ static int wpas_ctrl_iface_driver_event(struct wpa_supplicant *wpa_s, char *cmd)
|
|||||||
return 0;
|
return 0;
|
||||||
} else if (os_strcmp(cmd, "SCAN_RES") == 0) {
|
} else if (os_strcmp(cmd, "SCAN_RES") == 0) {
|
||||||
return wpas_ctrl_iface_driver_scan_res(wpa_s, param);
|
return wpas_ctrl_iface_driver_scan_res(wpa_s, param);
|
||||||
|
} else if (os_strcmp(cmd, "ASSOC") == 0) {
|
||||||
|
return wpas_ctrl_iface_driver_event_assoc(wpa_s, param);
|
||||||
} else {
|
} else {
|
||||||
wpa_dbg(wpa_s, MSG_DEBUG, "Testing - unknown driver event: %s",
|
wpa_dbg(wpa_s, MSG_DEBUG, "Testing - unknown driver event: %s",
|
||||||
cmd);
|
cmd);
|
||||||
@ -10598,15 +10735,18 @@ static int wpas_ctrl_iface_pasn_start(struct wpa_supplicant *wpa_s, char *cmd)
|
|||||||
u8 bssid[ETH_ALEN];
|
u8 bssid[ETH_ALEN];
|
||||||
int akmp = -1, cipher = -1, got_bssid = 0;
|
int akmp = -1, cipher = -1, got_bssid = 0;
|
||||||
u16 group = 0xFFFF;
|
u16 group = 0xFFFF;
|
||||||
int id = 0;
|
u8 *comeback = NULL;
|
||||||
|
size_t comeback_len = 0;
|
||||||
|
int id = 0, ret = -1;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Entry format: bssid=<BSSID> akmp=<AKMP> cipher=<CIPHER> group=<group>
|
* Entry format: bssid=<BSSID> akmp=<AKMP> cipher=<CIPHER> group=<group>
|
||||||
|
* [comeback=<hexdump>]
|
||||||
*/
|
*/
|
||||||
while ((token = str_token(cmd, " ", &context))) {
|
while ((token = str_token(cmd, " ", &context))) {
|
||||||
if (os_strncmp(token, "bssid=", 6) == 0) {
|
if (os_strncmp(token, "bssid=", 6) == 0) {
|
||||||
if (hwaddr_aton(token + 6, bssid))
|
if (hwaddr_aton(token + 6, bssid))
|
||||||
return -1;
|
goto out;
|
||||||
got_bssid = 1;
|
got_bssid = 1;
|
||||||
} else if (os_strcmp(token, "akmp=PASN") == 0) {
|
} else if (os_strcmp(token, "akmp=PASN") == 0) {
|
||||||
akmp = WPA_KEY_MGMT_PASN;
|
akmp = WPA_KEY_MGMT_PASN;
|
||||||
@ -10640,20 +10780,34 @@ static int wpas_ctrl_iface_pasn_start(struct wpa_supplicant *wpa_s, char *cmd)
|
|||||||
group = atoi(token + 6);
|
group = atoi(token + 6);
|
||||||
} else if (os_strncmp(token, "nid=", 4) == 0) {
|
} else if (os_strncmp(token, "nid=", 4) == 0) {
|
||||||
id = atoi(token + 4);
|
id = atoi(token + 4);
|
||||||
|
} else if (os_strncmp(token, "comeback=", 9) == 0) {
|
||||||
|
comeback_len = os_strlen(token + 9);
|
||||||
|
if (comeback || !comeback_len || comeback_len % 2)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
comeback_len /= 2;
|
||||||
|
comeback = os_malloc(comeback_len);
|
||||||
|
if (!comeback ||
|
||||||
|
hexstr2bin(token + 9, comeback, comeback_len))
|
||||||
|
goto out;
|
||||||
} else {
|
} else {
|
||||||
wpa_printf(MSG_DEBUG,
|
wpa_printf(MSG_DEBUG,
|
||||||
"CTRL: PASN Invalid parameter: '%s'",
|
"CTRL: PASN Invalid parameter: '%s'",
|
||||||
token);
|
token);
|
||||||
return -1;
|
goto out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!got_bssid || akmp == -1 || cipher == -1 || group == 0xFFFF) {
|
if (!got_bssid || akmp == -1 || cipher == -1 || group == 0xFFFF) {
|
||||||
wpa_printf(MSG_DEBUG,"CTRL: PASN missing parameter");
|
wpa_printf(MSG_DEBUG,"CTRL: PASN missing parameter");
|
||||||
return -1;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
return wpas_pasn_auth_start(wpa_s, bssid, akmp, cipher, group, id);
|
ret = wpas_pasn_auth_start(wpa_s, bssid, akmp, cipher, group, id,
|
||||||
|
comeback, comeback_len);
|
||||||
|
out:
|
||||||
|
os_free(comeback);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -70,14 +70,17 @@ wpa_supplicant_ctrl_iface_init(struct wpa_supplicant *wpa_s);
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* wpa_supplicant_ctrl_iface_deinit - Deinitialize control interface
|
* wpa_supplicant_ctrl_iface_deinit - Deinitialize control interface
|
||||||
|
* @wpa_s: Pointer to wpa_supplicant data
|
||||||
* @priv: Pointer to private data from wpa_supplicant_ctrl_iface_init()
|
* @priv: Pointer to private data from wpa_supplicant_ctrl_iface_init()
|
||||||
*
|
*
|
||||||
* Deinitialize the control interface that was initialized with
|
* Deinitialize the control interface that was initialized with
|
||||||
* wpa_supplicant_ctrl_iface_init().
|
* wpa_supplicant_ctrl_iface_init() and any data related to the wpa_s instance.
|
||||||
|
* @priv may be %NULL if the control interface has not yet been initialized.
|
||||||
*
|
*
|
||||||
* Required to be implemented in each control interface backend.
|
* Required to be implemented in each control interface backend.
|
||||||
*/
|
*/
|
||||||
void wpa_supplicant_ctrl_iface_deinit(struct ctrl_iface_priv *priv);
|
void wpa_supplicant_ctrl_iface_deinit(struct wpa_supplicant *wpa_s,
|
||||||
|
struct ctrl_iface_priv *priv);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* wpa_supplicant_ctrl_iface_wait - Wait for ctrl_iface monitor
|
* wpa_supplicant_ctrl_iface_wait - Wait for ctrl_iface monitor
|
||||||
@ -128,7 +131,8 @@ wpa_supplicant_ctrl_iface_init(struct wpa_supplicant *wpa_s)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
wpa_supplicant_ctrl_iface_deinit(struct ctrl_iface_priv *priv)
|
wpa_supplicant_ctrl_iface_deinit(struct wpa_supplicant *wpa_s,
|
||||||
|
struct ctrl_iface_priv *priv)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -462,8 +462,11 @@ wpa_supplicant_ctrl_iface_init(struct wpa_supplicant *wpa_s)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void wpa_supplicant_ctrl_iface_deinit(struct ctrl_iface_priv *priv)
|
void wpa_supplicant_ctrl_iface_deinit(struct wpa_supplicant *wpa_s,
|
||||||
|
struct ctrl_iface_priv *priv)
|
||||||
{
|
{
|
||||||
|
if (!priv)
|
||||||
|
return;
|
||||||
while (priv->ctrl_dst)
|
while (priv->ctrl_dst)
|
||||||
ctrl_close_pipe(priv->ctrl_dst);
|
ctrl_close_pipe(priv->ctrl_dst);
|
||||||
if (priv->sec_attr_set)
|
if (priv->sec_attr_set)
|
||||||
|
@ -490,8 +490,12 @@ wpa_supplicant_ctrl_iface_init(struct wpa_supplicant *wpa_s)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void wpa_supplicant_ctrl_iface_deinit(struct ctrl_iface_priv *priv)
|
void wpa_supplicant_ctrl_iface_deinit(struct wpa_supplicant *wpa_s,
|
||||||
|
struct ctrl_iface_priv *priv)
|
||||||
{
|
{
|
||||||
|
if (!priv)
|
||||||
|
return;
|
||||||
|
|
||||||
if (priv->sock > -1) {
|
if (priv->sock > -1) {
|
||||||
eloop_unregister_read_sock(priv->sock);
|
eloop_unregister_read_sock(priv->sock);
|
||||||
if (priv->ctrl_dst) {
|
if (priv->ctrl_dst) {
|
||||||
|
@ -800,12 +800,52 @@ static int wpas_ctrl_iface_reinit(struct wpa_supplicant *wpa_s,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void wpa_supplicant_ctrl_iface_deinit(struct ctrl_iface_priv *priv)
|
static void
|
||||||
|
wpas_global_ctrl_iface_flush_queued_msg(struct wpa_global *global,
|
||||||
|
struct wpa_supplicant *wpa_s)
|
||||||
|
{
|
||||||
|
struct ctrl_iface_global_priv *gpriv;
|
||||||
|
struct ctrl_iface_msg *msg, *prev_msg;
|
||||||
|
unsigned int count = 0;
|
||||||
|
|
||||||
|
if (!global || !global->ctrl_iface)
|
||||||
|
return;
|
||||||
|
|
||||||
|
gpriv = global->ctrl_iface;
|
||||||
|
dl_list_for_each_safe(msg, prev_msg, &gpriv->msg_queue,
|
||||||
|
struct ctrl_iface_msg, list) {
|
||||||
|
if (msg->wpa_s == wpa_s) {
|
||||||
|
count++;
|
||||||
|
dl_list_del(&msg->list);
|
||||||
|
os_free(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count) {
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"CTRL: Dropped %u pending message(s) for interface that is being removed",
|
||||||
|
count);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void wpa_supplicant_ctrl_iface_deinit(struct wpa_supplicant *wpa_s,
|
||||||
|
struct ctrl_iface_priv *priv)
|
||||||
{
|
{
|
||||||
struct wpa_ctrl_dst *dst, *prev;
|
struct wpa_ctrl_dst *dst, *prev;
|
||||||
struct ctrl_iface_msg *msg, *prev_msg;
|
struct ctrl_iface_msg *msg, *prev_msg;
|
||||||
struct ctrl_iface_global_priv *gpriv;
|
struct ctrl_iface_global_priv *gpriv;
|
||||||
|
|
||||||
|
if (!priv) {
|
||||||
|
/* Control interface has not yet been initialized, so there is
|
||||||
|
* nothing to deinitialize here. However, there might be a
|
||||||
|
* pending message for this interface, so get rid of any such
|
||||||
|
* entry before completing interface removal. */
|
||||||
|
wpas_global_ctrl_iface_flush_queued_msg(wpa_s->global, wpa_s);
|
||||||
|
eloop_cancel_timeout(wpas_ctrl_msg_queue_timeout, wpa_s, NULL);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (priv->sock > -1) {
|
if (priv->sock > -1) {
|
||||||
char *fname;
|
char *fname;
|
||||||
char *buf, *dir = NULL;
|
char *buf, *dir = NULL;
|
||||||
@ -877,6 +917,7 @@ void wpa_supplicant_ctrl_iface_deinit(struct ctrl_iface_priv *priv)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
wpas_global_ctrl_iface_flush_queued_msg(wpa_s->global, wpa_s);
|
||||||
eloop_cancel_timeout(wpas_ctrl_msg_queue_timeout, priv->wpa_s, NULL);
|
eloop_cancel_timeout(wpas_ctrl_msg_queue_timeout, priv->wpa_s, NULL);
|
||||||
os_free(priv);
|
os_free(priv);
|
||||||
}
|
}
|
||||||
|
@ -674,10 +674,8 @@ static void test_eapol_clean(struct eapol_test_data *e,
|
|||||||
os_free(e->radius_conf);
|
os_free(e->radius_conf);
|
||||||
e->radius_conf = NULL;
|
e->radius_conf = NULL;
|
||||||
scard_deinit(wpa_s->scard);
|
scard_deinit(wpa_s->scard);
|
||||||
if (wpa_s->ctrl_iface) {
|
wpa_supplicant_ctrl_iface_deinit(wpa_s, wpa_s->ctrl_iface);
|
||||||
wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface);
|
|
||||||
wpa_s->ctrl_iface = NULL;
|
wpa_s->ctrl_iface = NULL;
|
||||||
}
|
|
||||||
|
|
||||||
ext_password_deinit(wpa_s->ext_pw);
|
ext_password_deinit(wpa_s->ext_pw);
|
||||||
wpa_s->ext_pw = NULL;
|
wpa_s->ext_pw = NULL;
|
||||||
|
@ -1102,14 +1102,11 @@ static bool sae_pk_acceptable_bss_with_pk(struct wpa_supplicant *wpa_s,
|
|||||||
dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
|
dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
|
||||||
int count;
|
int count;
|
||||||
const u8 *ie;
|
const u8 *ie;
|
||||||
u8 rsnxe_capa = 0;
|
|
||||||
|
|
||||||
if (bss == orig_bss)
|
if (bss == orig_bss)
|
||||||
continue;
|
continue;
|
||||||
ie = wpa_bss_get_ie(bss, WLAN_EID_RSNX);
|
ie = wpa_bss_get_ie(bss, WLAN_EID_RSNX);
|
||||||
if (ie && ie[1] >= 1)
|
if (!(ieee802_11_rsnx_capab(ie, WLAN_RSNX_CAPAB_SAE_PK)))
|
||||||
rsnxe_capa = ie[2];
|
|
||||||
if (!(rsnxe_capa & BIT(WLAN_RSNX_CAPAB_SAE_PK)))
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* TODO: Could be more thorough in checking what kind of
|
/* TODO: Could be more thorough in checking what kind of
|
||||||
@ -4405,6 +4402,8 @@ static void wpa_supplicant_event_assoc_auth(struct wpa_supplicant *wpa_s,
|
|||||||
|
|
||||||
wpa_supplicant_event_port_authorized(wpa_s);
|
wpa_supplicant_event_port_authorized(wpa_s);
|
||||||
|
|
||||||
|
wpa_s->last_eapol_matches_bssid = 1;
|
||||||
|
|
||||||
wpa_sm_set_rx_replay_ctr(wpa_s->wpa, data->assoc_info.key_replay_ctr);
|
wpa_sm_set_rx_replay_ctr(wpa_s->wpa, data->assoc_info.key_replay_ctr);
|
||||||
wpa_sm_set_ptk_kck_kek(wpa_s->wpa, data->assoc_info.ptk_kck,
|
wpa_sm_set_ptk_kck_kek(wpa_s->wpa, data->assoc_info.ptk_kck,
|
||||||
data->assoc_info.ptk_kck_len,
|
data->assoc_info.ptk_kck_len,
|
||||||
|
@ -344,7 +344,6 @@ static int mesh_rsn_build_sae_commit(struct wpa_supplicant *wpa_s,
|
|||||||
}
|
}
|
||||||
return sae_prepare_commit(wpa_s->own_addr, sta->addr,
|
return sae_prepare_commit(wpa_s->own_addr, sta->addr,
|
||||||
(u8 *) password, os_strlen(password),
|
(u8 *) password, os_strlen(password),
|
||||||
ssid->sae_password_id,
|
|
||||||
sta->sae);
|
sta->sae);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,9 +33,18 @@ struct wpa_pasn_auth_work {
|
|||||||
int cipher;
|
int cipher;
|
||||||
u16 group;
|
u16 group;
|
||||||
int network_id;
|
int network_id;
|
||||||
|
struct wpabuf *comeback;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static void wpas_pasn_free_auth_work(struct wpa_pasn_auth_work *awork)
|
||||||
|
{
|
||||||
|
wpabuf_free(awork->comeback);
|
||||||
|
awork->comeback = NULL;
|
||||||
|
os_free(awork);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void wpas_pasn_auth_work_timeout(void *eloop_ctx, void *timeout_ctx)
|
static void wpas_pasn_auth_work_timeout(void *eloop_ctx, void *timeout_ctx)
|
||||||
{
|
{
|
||||||
struct wpa_supplicant *wpa_s = eloop_ctx;
|
struct wpa_supplicant *wpa_s = eloop_ctx;
|
||||||
@ -56,8 +65,30 @@ static void wpas_pasn_cancel_auth_work(struct wpa_supplicant *wpa_s)
|
|||||||
|
|
||||||
|
|
||||||
static void wpas_pasn_auth_status(struct wpa_supplicant *wpa_s, const u8 *bssid,
|
static void wpas_pasn_auth_status(struct wpa_supplicant *wpa_s, const u8 *bssid,
|
||||||
int akmp, int cipher, u8 status)
|
int akmp, int cipher, u8 status,
|
||||||
|
struct wpabuf *comeback,
|
||||||
|
u16 comeback_after)
|
||||||
{
|
{
|
||||||
|
if (comeback) {
|
||||||
|
size_t comeback_len = wpabuf_len(comeback);
|
||||||
|
size_t buflen = comeback_len * 2 + 1;
|
||||||
|
char *comeback_txt = os_malloc(buflen);
|
||||||
|
|
||||||
|
if (comeback_txt) {
|
||||||
|
wpa_snprintf_hex(comeback_txt, buflen,
|
||||||
|
wpabuf_head(comeback), comeback_len);
|
||||||
|
|
||||||
|
wpa_msg(wpa_s, MSG_INFO, PASN_AUTH_STATUS MACSTR
|
||||||
|
" akmp=%s, status=%u comeback_after=%u comeback=%s",
|
||||||
|
MAC2STR(bssid),
|
||||||
|
wpa_key_mgmt_txt(akmp, WPA_PROTO_RSN),
|
||||||
|
status, comeback_after, comeback_txt);
|
||||||
|
|
||||||
|
os_free(comeback_txt);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
wpa_msg(wpa_s, MSG_INFO,
|
wpa_msg(wpa_s, MSG_INFO,
|
||||||
PASN_AUTH_STATUS MACSTR " akmp=%s, status=%u",
|
PASN_AUTH_STATUS MACSTR " akmp=%s, status=%u",
|
||||||
MAC2STR(bssid), wpa_key_mgmt_txt(akmp, WPA_PROTO_RSN),
|
MAC2STR(bssid), wpa_key_mgmt_txt(akmp, WPA_PROTO_RSN),
|
||||||
@ -71,30 +102,17 @@ static struct wpabuf * wpas_pasn_wd_sae_commit(struct wpa_supplicant *wpa_s)
|
|||||||
{
|
{
|
||||||
struct wpas_pasn *pasn = &wpa_s->pasn;
|
struct wpas_pasn *pasn = &wpa_s->pasn;
|
||||||
struct wpabuf *buf = NULL;
|
struct wpabuf *buf = NULL;
|
||||||
const char *password = NULL;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (pasn->ssid) {
|
|
||||||
password = pasn->ssid->sae_password;
|
|
||||||
if (!password)
|
|
||||||
password = pasn->ssid->passphrase;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!password) {
|
|
||||||
wpa_printf(MSG_DEBUG, "PASN: SAE without a password");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = sae_set_group(&pasn->sae, pasn->group);
|
ret = sae_set_group(&pasn->sae, pasn->group);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
wpa_printf(MSG_DEBUG, "PASN: Failed to set SAE group");
|
wpa_printf(MSG_DEBUG, "PASN: Failed to set SAE group");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO: SAE H2E */
|
ret = sae_prepare_commit_pt(&pasn->sae, pasn->ssid->pt,
|
||||||
ret = sae_prepare_commit(wpa_s->own_addr, pasn->bssid,
|
wpa_s->own_addr, pasn->bssid,
|
||||||
(const u8 *) password, os_strlen(password), 0,
|
NULL, NULL);
|
||||||
&pasn->sae);
|
|
||||||
if (ret) {
|
if (ret) {
|
||||||
wpa_printf(MSG_DEBUG, "PASN: Failed to prepare SAE commit");
|
wpa_printf(MSG_DEBUG, "PASN: Failed to prepare SAE commit");
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -109,7 +127,7 @@ static struct wpabuf * wpas_pasn_wd_sae_commit(struct wpa_supplicant *wpa_s)
|
|||||||
|
|
||||||
wpabuf_put_le16(buf, WLAN_AUTH_SAE);
|
wpabuf_put_le16(buf, WLAN_AUTH_SAE);
|
||||||
wpabuf_put_le16(buf, 1);
|
wpabuf_put_le16(buf, 1);
|
||||||
wpabuf_put_le16(buf, WLAN_STATUS_SUCCESS);
|
wpabuf_put_le16(buf, WLAN_STATUS_SAE_HASH_TO_ELEMENT);
|
||||||
|
|
||||||
sae_write_commit(&pasn->sae, buf, NULL, 0);
|
sae_write_commit(&pasn->sae, buf, NULL, 0);
|
||||||
pasn->sae.state = SAE_COMMITTED;
|
pasn->sae.state = SAE_COMMITTED;
|
||||||
@ -155,14 +173,14 @@ static int wpas_pasn_wd_sae_rx(struct wpa_supplicant *wpa_s, struct wpabuf *wd)
|
|||||||
wpa_printf(MSG_DEBUG, "PASN: SAE: commit: alg=%u, seq=%u, status=%u",
|
wpa_printf(MSG_DEBUG, "PASN: SAE: commit: alg=%u, seq=%u, status=%u",
|
||||||
alg, seq, status);
|
alg, seq, status);
|
||||||
|
|
||||||
/* TODO: SAE H2E */
|
if (alg != WLAN_AUTH_SAE || seq != 1 ||
|
||||||
if (alg != WLAN_AUTH_SAE || seq != 1 || status != WLAN_STATUS_SUCCESS) {
|
status != WLAN_STATUS_SAE_HASH_TO_ELEMENT) {
|
||||||
wpa_printf(MSG_DEBUG, "PASN: SAE: dropping peer commit");
|
wpa_printf(MSG_DEBUG, "PASN: SAE: dropping peer commit");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
res = sae_parse_commit(&pasn->sae, data + 6, len - 6, NULL, 0, groups,
|
res = sae_parse_commit(&pasn->sae, data + 6, len - 6, NULL, 0, groups,
|
||||||
0);
|
1);
|
||||||
if (res != WLAN_STATUS_SUCCESS) {
|
if (res != WLAN_STATUS_SUCCESS) {
|
||||||
wpa_printf(MSG_DEBUG, "PASN: SAE failed parsing commit");
|
wpa_printf(MSG_DEBUG, "PASN: SAE failed parsing commit");
|
||||||
return -1;
|
return -1;
|
||||||
@ -240,6 +258,31 @@ static struct wpabuf * wpas_pasn_wd_sae_confirm(struct wpa_supplicant *wpa_s)
|
|||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int wpas_pasn_sae_setup_pt(struct wpa_supplicant *wpa_s,
|
||||||
|
struct wpa_ssid *ssid, int group)
|
||||||
|
{
|
||||||
|
const char *password = ssid->sae_password;
|
||||||
|
int groups[2] = { group, 0 };
|
||||||
|
|
||||||
|
if (!password)
|
||||||
|
password = ssid->passphrase;
|
||||||
|
|
||||||
|
if (!password) {
|
||||||
|
wpa_printf(MSG_DEBUG, "PASN: SAE without a password");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ssid->pt)
|
||||||
|
return 0; /* PT already derived */
|
||||||
|
|
||||||
|
ssid->pt = sae_derive_pt(groups, ssid->ssid, ssid->ssid_len,
|
||||||
|
(const u8 *) password, os_strlen(password),
|
||||||
|
ssid->sae_password_id);
|
||||||
|
|
||||||
|
return ssid->pt ? 0 : -1;
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* CONFIG_SAE */
|
#endif /* CONFIG_SAE */
|
||||||
|
|
||||||
|
|
||||||
@ -612,7 +655,8 @@ static u8 wpas_pasn_get_wrapped_data_format(struct wpas_pasn *pasn)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static struct wpabuf * wpas_pasn_build_auth_1(struct wpa_supplicant *wpa_s)
|
static struct wpabuf * wpas_pasn_build_auth_1(struct wpa_supplicant *wpa_s,
|
||||||
|
const struct wpabuf *comeback)
|
||||||
{
|
{
|
||||||
struct wpas_pasn *pasn = &wpa_s->pasn;
|
struct wpas_pasn *pasn = &wpa_s->pasn;
|
||||||
struct wpabuf *buf, *pubkey = NULL, *wrapped_data_buf = NULL;
|
struct wpabuf *buf, *pubkey = NULL, *wrapped_data_buf = NULL;
|
||||||
@ -680,14 +724,14 @@ static struct wpabuf * wpas_pasn_build_auth_1(struct wpa_supplicant *wpa_s)
|
|||||||
wrapped_data = WPA_PASN_WRAPPED_DATA_NO;
|
wrapped_data = WPA_PASN_WRAPPED_DATA_NO;
|
||||||
|
|
||||||
wpa_pasn_add_parameter_ie(buf, pasn->group, wrapped_data,
|
wpa_pasn_add_parameter_ie(buf, pasn->group, wrapped_data,
|
||||||
pubkey, true, NULL, -1);
|
pubkey, true, comeback, -1);
|
||||||
|
|
||||||
if (wpa_pasn_add_wrapped_data(buf, wrapped_data_buf) < 0)
|
if (wpa_pasn_add_wrapped_data(buf, wrapped_data_buf) < 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
/* Add own RNSXE */
|
/* Add own RNSXE */
|
||||||
/* TODO: How to handle protected TWT and SAE H2E? */
|
|
||||||
capab = 0;
|
capab = 0;
|
||||||
|
capab |= BIT(WLAN_RSNX_CAPAB_SAE_H2E);
|
||||||
if (wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_SEC_LTF)
|
if (wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_SEC_LTF)
|
||||||
capab |= BIT(WLAN_RSNX_CAPAB_SECURE_LTF);
|
capab |= BIT(WLAN_RSNX_CAPAB_SECURE_LTF);
|
||||||
if (wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_SEC_RTT)
|
if (wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_SEC_RTT)
|
||||||
@ -828,6 +872,10 @@ static void wpas_pasn_reset(struct wpa_supplicant *wpa_s)
|
|||||||
wpabuf_free(pasn->beacon_rsne_rsnxe);
|
wpabuf_free(pasn->beacon_rsne_rsnxe);
|
||||||
pasn->beacon_rsne_rsnxe = NULL;
|
pasn->beacon_rsne_rsnxe = NULL;
|
||||||
|
|
||||||
|
wpabuf_free(pasn->comeback);
|
||||||
|
pasn->comeback = NULL;
|
||||||
|
pasn->comeback_after = 0;
|
||||||
|
|
||||||
#ifdef CONFIG_SAE
|
#ifdef CONFIG_SAE
|
||||||
sae_clear_data(&pasn->sae);
|
sae_clear_data(&pasn->sae);
|
||||||
#endif /* CONFIG_SAE */
|
#endif /* CONFIG_SAE */
|
||||||
@ -946,7 +994,7 @@ static int wpas_pasn_start(struct wpa_supplicant *wpa_s, const u8 *bssid,
|
|||||||
int akmp, int cipher, u16 group, int freq,
|
int akmp, int cipher, u16 group, int freq,
|
||||||
const u8 *beacon_rsne, u8 beacon_rsne_len,
|
const u8 *beacon_rsne, u8 beacon_rsne_len,
|
||||||
const u8 *beacon_rsnxe, u8 beacon_rsnxe_len,
|
const u8 *beacon_rsnxe, u8 beacon_rsnxe_len,
|
||||||
int network_id)
|
int network_id, struct wpabuf *comeback)
|
||||||
{
|
{
|
||||||
struct wpas_pasn *pasn = &wpa_s->pasn;
|
struct wpas_pasn *pasn = &wpa_s->pasn;
|
||||||
struct wpa_ssid *ssid = NULL;
|
struct wpa_ssid *ssid = NULL;
|
||||||
@ -972,6 +1020,20 @@ static int wpas_pasn_start(struct wpa_supplicant *wpa_s, const u8 *bssid,
|
|||||||
"PASN: No network profile found for SAE");
|
"PASN: No network profile found for SAE");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!ieee802_11_rsnx_capab(beacon_rsnxe,
|
||||||
|
WLAN_RSNX_CAPAB_SAE_H2E)) {
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"PASN: AP does not support SAE H2E");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wpas_pasn_sae_setup_pt(wpa_s, ssid, group) < 0) {
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"PASN: Failed to derive PT");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
pasn->sae.state = SAE_NOTHING;
|
pasn->sae.state = SAE_NOTHING;
|
||||||
pasn->sae.send_confirm = 0;
|
pasn->sae.send_confirm = 0;
|
||||||
pasn->ssid = ssid;
|
pasn->ssid = ssid;
|
||||||
@ -1016,6 +1078,15 @@ static int wpas_pasn_start(struct wpa_supplicant *wpa_s, const u8 *bssid,
|
|||||||
pasn->cipher = cipher;
|
pasn->cipher = cipher;
|
||||||
pasn->group = group;
|
pasn->group = group;
|
||||||
pasn->freq = freq;
|
pasn->freq = freq;
|
||||||
|
|
||||||
|
if (wpa_s->conf->force_kdk_derivation ||
|
||||||
|
(wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_SEC_LTF &&
|
||||||
|
ieee802_11_rsnx_capab(beacon_rsnxe, WLAN_RSNX_CAPAB_SECURE_LTF)))
|
||||||
|
pasn->kdk_len = WPA_KDK_MAX_LEN;
|
||||||
|
else
|
||||||
|
pasn->kdk_len = 0;
|
||||||
|
wpa_printf(MSG_DEBUG, "PASN: kdk_len=%zu", pasn->kdk_len);
|
||||||
|
|
||||||
os_memcpy(pasn->bssid, bssid, ETH_ALEN);
|
os_memcpy(pasn->bssid, bssid, ETH_ALEN);
|
||||||
|
|
||||||
wpa_printf(MSG_DEBUG,
|
wpa_printf(MSG_DEBUG,
|
||||||
@ -1023,7 +1094,7 @@ static int wpas_pasn_start(struct wpa_supplicant *wpa_s, const u8 *bssid,
|
|||||||
MAC2STR(pasn->bssid), pasn->akmp, pasn->cipher,
|
MAC2STR(pasn->bssid), pasn->akmp, pasn->cipher,
|
||||||
pasn->group);
|
pasn->group);
|
||||||
|
|
||||||
frame = wpas_pasn_build_auth_1(wpa_s);
|
frame = wpas_pasn_build_auth_1(wpa_s, comeback);
|
||||||
if (!frame) {
|
if (!frame) {
|
||||||
wpa_printf(MSG_DEBUG, "PASN: Failed building 1st auth frame");
|
wpa_printf(MSG_DEBUG, "PASN: Failed building 1st auth frame");
|
||||||
goto fail;
|
goto fail;
|
||||||
@ -1105,7 +1176,8 @@ static void wpas_pasn_auth_start_cb(struct wpa_radio_work *work, int deinit)
|
|||||||
wpa_s, NULL);
|
wpa_s, NULL);
|
||||||
wpa_s->pasn_auth_work = NULL;
|
wpa_s->pasn_auth_work = NULL;
|
||||||
}
|
}
|
||||||
os_free(awork);
|
|
||||||
|
wpas_pasn_free_auth_work(awork);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1132,24 +1204,29 @@ static void wpas_pasn_auth_start_cb(struct wpa_radio_work *work, int deinit)
|
|||||||
ret = wpas_pasn_start(wpa_s, awork->bssid, awork->akmp, awork->cipher,
|
ret = wpas_pasn_start(wpa_s, awork->bssid, awork->akmp, awork->cipher,
|
||||||
awork->group, bss->freq, rsne, *(rsne + 1) + 2,
|
awork->group, bss->freq, rsne, *(rsne + 1) + 2,
|
||||||
rsnxe, rsnxe ? *(rsnxe + 1) + 2 : 0,
|
rsnxe, rsnxe ? *(rsnxe + 1) + 2 : 0,
|
||||||
awork->network_id);
|
awork->network_id, awork->comeback);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
wpa_printf(MSG_DEBUG,
|
wpa_printf(MSG_DEBUG,
|
||||||
"PASN: Failed to start PASN authentication");
|
"PASN: Failed to start PASN authentication");
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* comeback token is no longer needed at this stage */
|
||||||
|
wpabuf_free(awork->comeback);
|
||||||
|
awork->comeback = NULL;
|
||||||
|
|
||||||
wpa_s->pasn_auth_work = work;
|
wpa_s->pasn_auth_work = work;
|
||||||
return;
|
return;
|
||||||
fail:
|
fail:
|
||||||
os_free(awork);
|
wpas_pasn_free_auth_work(awork);
|
||||||
work->ctx = NULL;
|
work->ctx = NULL;
|
||||||
radio_work_done(work);
|
radio_work_done(work);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int wpas_pasn_auth_start(struct wpa_supplicant *wpa_s, const u8 *bssid,
|
int wpas_pasn_auth_start(struct wpa_supplicant *wpa_s, const u8 *bssid,
|
||||||
int akmp, int cipher, u16 group, int network_id)
|
int akmp, int cipher, u16 group, int network_id,
|
||||||
|
const u8 *comeback, size_t comeback_len)
|
||||||
{
|
{
|
||||||
struct wpa_pasn_auth_work *awork;
|
struct wpa_pasn_auth_work *awork;
|
||||||
struct wpa_bss *bss;
|
struct wpa_bss *bss;
|
||||||
@ -1195,9 +1272,17 @@ int wpas_pasn_auth_start(struct wpa_supplicant *wpa_s, const u8 *bssid,
|
|||||||
awork->group = group;
|
awork->group = group;
|
||||||
awork->network_id = network_id;
|
awork->network_id = network_id;
|
||||||
|
|
||||||
|
if (comeback && comeback_len) {
|
||||||
|
awork->comeback = wpabuf_alloc_copy(comeback, comeback_len);
|
||||||
|
if (!awork->comeback) {
|
||||||
|
wpas_pasn_free_auth_work(awork);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (radio_add_work(wpa_s, bss->freq, "pasn-start-auth", 1,
|
if (radio_add_work(wpa_s, bss->freq, "pasn-start-auth", 1,
|
||||||
wpas_pasn_auth_start_cb, awork) < 0) {
|
wpas_pasn_auth_start_cb, awork) < 0) {
|
||||||
os_free(awork);
|
wpas_pasn_free_auth_work(awork);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1216,12 +1301,33 @@ void wpas_pasn_auth_stop(struct wpa_supplicant *wpa_s)
|
|||||||
wpa_printf(MSG_DEBUG, "PASN: Stopping authentication");
|
wpa_printf(MSG_DEBUG, "PASN: Stopping authentication");
|
||||||
|
|
||||||
wpas_pasn_auth_status(wpa_s, pasn->bssid, pasn->akmp, pasn->cipher,
|
wpas_pasn_auth_status(wpa_s, pasn->bssid, pasn->akmp, pasn->cipher,
|
||||||
pasn->status);
|
pasn->status, pasn->comeback,
|
||||||
|
pasn->comeback_after);
|
||||||
|
|
||||||
wpas_pasn_reset(wpa_s);
|
wpas_pasn_reset(wpa_s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int wpas_pasn_immediate_retry(struct wpa_supplicant *wpa_s,
|
||||||
|
struct wpas_pasn *pasn,
|
||||||
|
struct wpa_pasn_params_data *params)
|
||||||
|
{
|
||||||
|
int akmp = pasn->akmp;
|
||||||
|
int cipher = pasn->cipher;
|
||||||
|
u16 group = pasn->group;
|
||||||
|
u8 bssid[ETH_ALEN];
|
||||||
|
int network_id = pasn->ssid ? pasn->ssid->id : 0;
|
||||||
|
|
||||||
|
wpa_printf(MSG_DEBUG, "PASN: Immediate retry");
|
||||||
|
os_memcpy(bssid, pasn->bssid, ETH_ALEN);
|
||||||
|
wpas_pasn_reset(wpa_s);
|
||||||
|
|
||||||
|
return wpas_pasn_auth_start(wpa_s, bssid, akmp, cipher, group,
|
||||||
|
network_id,
|
||||||
|
params->comeback, params->comeback_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int wpas_pasn_auth_rx(struct wpa_supplicant *wpa_s,
|
int wpas_pasn_auth_rx(struct wpa_supplicant *wpa_s,
|
||||||
const struct ieee80211_mgmt *mgmt, size_t len)
|
const struct ieee80211_mgmt *mgmt, size_t len)
|
||||||
{
|
{
|
||||||
@ -1315,10 +1421,26 @@ int wpas_pasn_auth_rx(struct wpa_supplicant *wpa_s,
|
|||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO: handle comeback flow */
|
|
||||||
if (status == WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY) {
|
if (status == WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY) {
|
||||||
wpa_printf(MSG_DEBUG,
|
wpa_printf(MSG_DEBUG,
|
||||||
"PASN: Authentication temporarily rejected");
|
"PASN: Authentication temporarily rejected");
|
||||||
|
|
||||||
|
if (pasn_params.comeback && pasn_params.comeback_len) {
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"PASN: Comeback token available. After=%u",
|
||||||
|
pasn_params.after);
|
||||||
|
|
||||||
|
if (!pasn_params.after)
|
||||||
|
return wpas_pasn_immediate_retry(wpa_s, pasn,
|
||||||
|
&pasn_params);
|
||||||
|
|
||||||
|
pasn->comeback = wpabuf_alloc_copy(
|
||||||
|
pasn_params.comeback, pasn_params.comeback_len);
|
||||||
|
if (pasn->comeback)
|
||||||
|
pasn->comeback_after = pasn_params.after;
|
||||||
|
}
|
||||||
|
|
||||||
|
pasn->status = status;
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1393,7 +1515,7 @@ int wpas_pasn_auth_rx(struct wpa_supplicant *wpa_s,
|
|||||||
wpa_s->own_addr, pasn->bssid,
|
wpa_s->own_addr, pasn->bssid,
|
||||||
wpabuf_head(secret), wpabuf_len(secret),
|
wpabuf_head(secret), wpabuf_len(secret),
|
||||||
&pasn->ptk, pasn->akmp, pasn->cipher,
|
&pasn->ptk, pasn->akmp, pasn->cipher,
|
||||||
WPA_KDK_MAX_LEN);
|
pasn->kdk_len);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
wpa_printf(MSG_DEBUG, "PASN: Failed to derive PTK");
|
wpa_printf(MSG_DEBUG, "PASN: Failed to derive PTK");
|
||||||
goto fail;
|
goto fail;
|
||||||
@ -1456,7 +1578,11 @@ int wpas_pasn_auth_rx(struct wpa_supplicant *wpa_s,
|
|||||||
* the frame and terminate the authentication exchange. However, better
|
* the frame and terminate the authentication exchange. However, better
|
||||||
* reply to the AP with an error status.
|
* reply to the AP with an error status.
|
||||||
*/
|
*/
|
||||||
|
if (status == WLAN_STATUS_SUCCESS)
|
||||||
pasn->status = WLAN_STATUS_UNSPECIFIED_FAILURE;
|
pasn->status = WLAN_STATUS_UNSPECIFIED_FAILURE;
|
||||||
|
else
|
||||||
|
pasn->status = status;
|
||||||
|
|
||||||
wpas_pasn_auth_stop(wpa_s);
|
wpas_pasn_auth_stop(wpa_s);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -193,10 +193,8 @@ static void test_eapol_clean(struct wpa_supplicant *wpa_s)
|
|||||||
pmksa_candidate_free(wpa_s->wpa);
|
pmksa_candidate_free(wpa_s->wpa);
|
||||||
wpa_sm_deinit(wpa_s->wpa);
|
wpa_sm_deinit(wpa_s->wpa);
|
||||||
scard_deinit(wpa_s->scard);
|
scard_deinit(wpa_s->scard);
|
||||||
if (wpa_s->ctrl_iface) {
|
wpa_supplicant_ctrl_iface_deinit(wpa_s, wpa_s->ctrl_iface);
|
||||||
wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface);
|
|
||||||
wpa_s->ctrl_iface = NULL;
|
wpa_s->ctrl_iface = NULL;
|
||||||
}
|
|
||||||
wpa_config_free(wpa_s->conf);
|
wpa_config_free(wpa_s->conf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -118,7 +118,7 @@ void wpas_handle_robust_av_recv_action(struct wpa_supplicant *wpa_s,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
status_code = *buf;
|
status_code = WPA_GET_LE16(buf);
|
||||||
wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_MSCS_RESULT "bssid=" MACSTR
|
wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_MSCS_RESULT "bssid=" MACSTR
|
||||||
" status_code=%u", MAC2STR(src), status_code);
|
" status_code=%u", MAC2STR(src), status_code);
|
||||||
wpa_s->mscs_setup_done = status_code == WLAN_STATUS_SUCCESS;
|
wpa_s->mscs_setup_done = status_code == WLAN_STATUS_SUCCESS;
|
||||||
|
@ -186,7 +186,6 @@ static struct wpabuf * sme_auth_build_sae_commit(struct wpa_supplicant *wpa_s,
|
|||||||
if (!use_pt &&
|
if (!use_pt &&
|
||||||
sae_prepare_commit(wpa_s->own_addr, bssid,
|
sae_prepare_commit(wpa_s->own_addr, bssid,
|
||||||
(u8 *) password, os_strlen(password),
|
(u8 *) password, os_strlen(password),
|
||||||
ssid->sae_password_id,
|
|
||||||
&wpa_s->sme.sae) < 0) {
|
&wpa_s->sme.sae) < 0) {
|
||||||
wpa_printf(MSG_DEBUG, "SAE: Could not pick PWE");
|
wpa_printf(MSG_DEBUG, "SAE: Could not pick PWE");
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -1158,8 +1158,8 @@ int wpa_supplicant_reload_configuration(struct wpa_supplicant *wpa_s)
|
|||||||
os_strcmp(conf->ctrl_interface,
|
os_strcmp(conf->ctrl_interface,
|
||||||
wpa_s->conf->ctrl_interface) != 0);
|
wpa_s->conf->ctrl_interface) != 0);
|
||||||
|
|
||||||
if (reconf_ctrl && wpa_s->ctrl_iface) {
|
if (reconf_ctrl) {
|
||||||
wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface);
|
wpa_supplicant_ctrl_iface_deinit(wpa_s, wpa_s->ctrl_iface);
|
||||||
wpa_s->ctrl_iface = NULL;
|
wpa_s->ctrl_iface = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -6748,10 +6748,8 @@ static void wpa_supplicant_deinit_iface(struct wpa_supplicant *wpa_s,
|
|||||||
if (terminate)
|
if (terminate)
|
||||||
wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TERMINATING);
|
wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TERMINATING);
|
||||||
|
|
||||||
if (wpa_s->ctrl_iface) {
|
wpa_supplicant_ctrl_iface_deinit(wpa_s, wpa_s->ctrl_iface);
|
||||||
wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface);
|
|
||||||
wpa_s->ctrl_iface = NULL;
|
wpa_s->ctrl_iface = NULL;
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef CONFIG_MESH
|
#ifdef CONFIG_MESH
|
||||||
if (wpa_s->ifmsh) {
|
if (wpa_s->ifmsh) {
|
||||||
|
@ -539,6 +539,7 @@ struct wpas_pasn {
|
|||||||
int cipher;
|
int cipher;
|
||||||
u16 group;
|
u16 group;
|
||||||
int freq;
|
int freq;
|
||||||
|
size_t kdk_len;
|
||||||
|
|
||||||
u8 trans_seq;
|
u8 trans_seq;
|
||||||
u8 status;
|
u8 status;
|
||||||
@ -554,6 +555,9 @@ struct wpas_pasn {
|
|||||||
struct wpa_ptk ptk;
|
struct wpa_ptk ptk;
|
||||||
struct crypto_ecdh *ecdh;
|
struct crypto_ecdh *ecdh;
|
||||||
|
|
||||||
|
struct wpabuf *comeback;
|
||||||
|
u16 comeback_after;
|
||||||
|
|
||||||
#ifdef CONFIG_SAE
|
#ifdef CONFIG_SAE
|
||||||
struct sae_data sae;
|
struct sae_data sae;
|
||||||
#endif /* CONFIG_SAE */
|
#endif /* CONFIG_SAE */
|
||||||
@ -1730,7 +1734,8 @@ void wpas_handle_assoc_resp_mscs(struct wpa_supplicant *wpa_s, const u8 *bssid,
|
|||||||
|
|
||||||
int wpas_pasn_auth_start(struct wpa_supplicant *wpa_s,
|
int wpas_pasn_auth_start(struct wpa_supplicant *wpa_s,
|
||||||
const u8 *bssid, int akmp, int cipher,
|
const u8 *bssid, int akmp, int cipher,
|
||||||
u16 group, int network_id);
|
u16 group, int network_id,
|
||||||
|
const u8 *comeback, size_t comeback_len);
|
||||||
void wpas_pasn_auth_stop(struct wpa_supplicant *wpa_s);
|
void wpas_pasn_auth_stop(struct wpa_supplicant *wpa_s);
|
||||||
int wpas_pasn_auth_tx_status(struct wpa_supplicant *wpa_s,
|
int wpas_pasn_auth_tx_status(struct wpa_supplicant *wpa_s,
|
||||||
const u8 *data, size_t data_len, u8 acked);
|
const u8 *data, size_t data_len, u8 acked);
|
||||||
|
Loading…
Reference in New Issue
Block a user