aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCy Schubert <cy@FreeBSD.org>2021-04-12 23:39:23 +0000
committerCy Schubert <cy@FreeBSD.org>2021-04-12 23:46:23 +0000
commitefec8223892b3e677acb46eae84ec3534989971f (patch)
tree06df51c4368ea0b59e2d8a48149e9ec685f923ea
parentf8262d7d8ac3000d0865826129738cd58a8fe1ab (diff)
downloadsrc-efec8223892b3e677acb46eae84ec3534989971f.tar.gz
src-efec8223892b3e677acb46eae84ec3534989971f.zip
wpa: Import wpa_supplicant/hostapd commit f91680c15
This is the April update to vendor/wpa committed upstream 2021/04/07.
-rw-r--r--hostapd/config_file.c33
-rw-r--r--hostapd/ctrl_iface.c33
-rw-r--r--hostapd/hostapd.conf24
-rw-r--r--src/ap/airtime_policy.c4
-rw-r--r--src/ap/ap_config.c5
-rw-r--r--src/ap/ap_config.h11
-rw-r--r--src/ap/ap_drv_ops.h13
-rw-r--r--src/ap/dpp_hostapd.c17
-rw-r--r--src/ap/drv_callbacks.c4
-rw-r--r--src/ap/hostapd.c6
-rw-r--r--src/ap/hostapd.h2
-rw-r--r--src/ap/ieee802_11.c123
-rw-r--r--src/ap/ieee802_11_shared.c69
-rw-r--r--src/ap/sta_info.h1
-rw-r--r--src/ap/wpa_auth.c8
-rw-r--r--src/ap/wpa_auth_ft.c3
-rw-r--r--src/common/common_module_tests.c131
-rw-r--r--src/common/ieee802_11_common.c29
-rw-r--r--src/common/ieee802_11_common.h3
-rw-r--r--src/common/qca-vendor.h42
-rw-r--r--src/common/sae.c59
-rw-r--r--src/common/sae.h2
-rw-r--r--src/common/wpa_common.c4
-rw-r--r--src/common/wpa_common.h4
-rw-r--r--src/crypto/crypto_openssl.c2
-rw-r--r--src/drivers/driver.h6
-rw-r--r--src/drivers/driver_nl80211.c65
-rw-r--r--src/drivers/driver_nl80211_capa.c2
-rw-r--r--src/eap_common/eap_sim_common.c24
-rw-r--r--src/rsn_supp/wpa.c12
-rw-r--r--src/rsn_supp/wpa_ft.c8
-rw-r--r--src/wps/wps_registrar.c40
-rw-r--r--tests/hwsim/example-hostapd.config1
-rw-r--r--tests/hwsim/hostapd.py16
-rw-r--r--tests/hwsim/test_ap_eap.py1
-rw-r--r--tests/hwsim/test_ap_ft.py30
-rw-r--r--tests/hwsim/test_ap_ht.py69
-rw-r--r--tests/hwsim/test_ap_params.py61
-rw-r--r--tests/hwsim/test_ap_psk.py16
-rw-r--r--tests/hwsim/test_ap_track.py32
-rw-r--r--tests/hwsim/test_ap_wps.py108
-rw-r--r--tests/hwsim/test_dpp.py524
-rw-r--r--tests/hwsim/test_eap_proto.py8
-rw-r--r--tests/hwsim/test_fils.py51
-rw-r--r--tests/hwsim/test_he.py22
-rw-r--r--tests/hwsim/test_ieee8021x.py17
-rw-r--r--tests/hwsim/test_mbo.py31
-rw-r--r--tests/hwsim/test_mscs.py231
-rw-r--r--tests/hwsim/test_multi_ap.py12
-rw-r--r--tests/hwsim/test_ocv.py57
-rw-r--r--tests/hwsim/test_p2p_discovery.py51
-rw-r--r--tests/hwsim/test_pasn.py235
-rw-r--r--tests/hwsim/test_pmksa_cache.py14
-rw-r--r--tests/hwsim/test_rrm.py14
-rw-r--r--tests/hwsim/test_wnm.py37
-rw-r--r--tests/hwsim/test_wpas_ctrl.py10
-rwxr-xr-xtests/hwsim/vm/inside.sh5
-rw-r--r--wpa_supplicant/ctrl_iface.c216
-rw-r--r--wpa_supplicant/ctrl_iface.h10
-rw-r--r--wpa_supplicant/ctrl_iface_named_pipe.c5
-rw-r--r--wpa_supplicant/ctrl_iface_udp.c6
-rw-r--r--wpa_supplicant/ctrl_iface_unix.c43
-rw-r--r--wpa_supplicant/eapol_test.c6
-rw-r--r--wpa_supplicant/events.c7
-rw-r--r--wpa_supplicant/mesh_rsn.c1
-rw-r--r--wpa_supplicant/pasn_supplicant.c196
-rw-r--r--wpa_supplicant/preauth_test.c6
-rw-r--r--wpa_supplicant/robust_av.c2
-rw-r--r--wpa_supplicant/sme.c1
-rw-r--r--wpa_supplicant/wpa_supplicant.c10
-rw-r--r--wpa_supplicant/wpa_supplicant_i.h7
71 files changed, 2511 insertions, 447 deletions
diff --git a/hostapd/config_file.c b/hostapd/config_file.c
index fd9bc0e9fced..e05c81366d9b 100644
--- a/hostapd/config_file.c
+++ b/hostapd/config_file.c
@@ -2332,6 +2332,22 @@ fail:
#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,
struct hostapd_bss_config *bss,
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);
} else if (os_strcmp(buf, "eapol_version") == 0) {
int eapol_version = atoi(pos);
-
#ifdef CONFIG_MACSEC
- if (eapol_version < 1 || eapol_version > 3) {
+ int max_ver = 3;
#else /* CONFIG_MACSEC */
- if (eapol_version < 1 || eapol_version > 2) {
+ int max_ver = 2;
#endif /* CONFIG_MACSEC */
+
+ if (eapol_version < 1 || eapol_version > max_ver) {
wpa_printf(MSG_ERROR,
"Line %d: invalid EAPOL version (%d): '%s'.",
line, eapol_version, pos);
@@ -4675,7 +4692,17 @@ static int hostapd_config_fill(struct hostapd_config *conf,
line, pos);
return 1;
}
+ } else if (os_strcmp(buf, "pasn_comeback_after") == 0) {
+ bss->pasn_comeback_after = atoi(pos);
#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 {
wpa_printf(MSG_ERROR,
"Line %d: unknown configuration item '%s'",
diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c
index 62fa51e91c20..b39f40252f29 100644
--- a/hostapd/ctrl_iface.c
+++ b/hostapd/ctrl_iface.c
@@ -1469,6 +1469,8 @@ static int hostapd_ctrl_iface_set(struct hostapd_data *hapd, char *cmd)
hapd->ext_mgmt_frame_handling = atoi(value);
} else if (os_strcasecmp(cmd, "ext_eapol_frame_io") == 0) {
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
} else if (os_strcasecmp(cmd, "dpp_config_obj_override") == 0) {
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);
}
+
+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 */
@@ -3646,6 +3676,9 @@ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
} else if (os_strncmp(buf, "GET_PMK ", 8) == 0) {
reply_len = hostapd_ctrl_get_pmk(hapd, buf + 8, reply,
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 */
} else if (os_strncmp(buf, "CHAN_SWITCH ", 12) == 0) {
if (hostapd_ctrl_iface_chan_switch(hapd->iface, buf + 12))
diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf
index e3ee8b2a0c1b..7932cb862f48 100644
--- a/hostapd/hostapd.conf
+++ b/hostapd/hostapd.conf
@@ -877,18 +877,31 @@ wmm_ac_vo_acm=0
#he_mu_edca_ac_vo_timer=255
# 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
+#
+# Non-SRG OBSS PD Max Offset (included if he_spr_sr_control B2=1)
#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
+#
+# SRG OBSS PD Max Offset (included if he_spr_sr_control B3=1)
#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
# 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.
#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
# 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
@@ -2038,6 +2051,13 @@ own_ip_addr=127.0.0.1
# http://www.iana.org/assignments/ipsec-registry/ipsec-registry.xml#ipsec-registry-10
#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 ##############################################
# Mobility Domain identifier (dot11FTMobilityDomainID, MDID)
diff --git a/src/ap/airtime_policy.c b/src/ap/airtime_policy.c
index 1e67f0d5996e..abe817c5b015 100644
--- a/src/ap/airtime_policy.c
+++ b/src/ap/airtime_policy.c
@@ -79,6 +79,10 @@ static void count_backlogged_sta(struct hostapd_data *hapd)
for (sta = hapd->sta_list; sta; sta = sta->next) {
if (hostapd_drv_read_sta_data(hapd, &data, sta->addr))
continue;
+#ifdef CONFIG_TESTING_OPTIONS
+ if (hapd->force_backlog_bytes)
+ data.backlog_bytes = 1;
+#endif /* CONFIG_TESTING_OPTIONS */
if (data.backlog_bytes > 0)
set_new_backlog_time(hapd, sta, &now);
diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c
index 452386b7e5de..7b6249bbe5cf 100644
--- a/src/ap/ap_config.c
+++ b/src/ap/ap_config.c
@@ -165,6 +165,11 @@ void hostapd_config_defaults_bss(struct hostapd_bss_config *bss)
#ifdef CONFIG_TESTING_OPTIONS
bss->sae_commit_status = -1;
#endif /* CONFIG_TESTING_OPTIONS */
+
+#ifdef CONFIG_PASN
+ /* comeback after 10 TUs */
+ bss->pasn_comeback_after = 10;
+#endif /* CONFIG_PASN */
}
diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h
index 8aeb03107af2..95bd79873a59 100644
--- a/src/ap/ap_config.h
+++ b/src/ap/ap_config.h
@@ -267,6 +267,8 @@ struct airtime_sta_weight {
u8 addr[ETH_ALEN];
};
+#define EXT_CAPA_MAX_LEN 15
+
/**
* struct hostapd_bss_config - Per-BSS configuration
*/
@@ -880,9 +882,18 @@ struct hostapd_bss_config {
#endif /* CONFIG_TESTING_OPTIONS */
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 */
unsigned int unsol_bcast_probe_resp_interval;
+
+ u8 ext_capa_mask[EXT_CAPA_MAX_LEN];
+ u8 ext_capa[EXT_CAPA_MAX_LEN];
};
/**
diff --git a/src/ap/ap_drv_ops.h b/src/ap/ap_drv_ops.h
index a42070116771..61c8f64eb471 100644
--- a/src/ap/ap_drv_ops.h
+++ b/src/ap/ap_drv_ops.h
@@ -403,4 +403,17 @@ static inline int hostapd_drv_driver_cmd(struct hostapd_data *hapd,
}
#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 */
diff --git a/src/ap/dpp_hostapd.c b/src/ap/dpp_hostapd.c
index e1e5a3ac4bb3..aaeb94c2f53b 100644
--- a/src/ap/dpp_hostapd.c
+++ b/src/ap/dpp_hostapd.c
@@ -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");
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");
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");
eloop_cancel_timeout(hostapd_dpp_config_result_wait_timeout,
hapd, NULL);
+ auth->waiting_conn_status_result = 1;
eloop_cancel_timeout(
hostapd_dpp_conn_status_result_wait_timeout,
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");
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,
"DPP: Received Configuration Request (GAS Query Request)",
query, query_len);
diff --git a/src/ap/drv_callbacks.c b/src/ap/drv_callbacks.c
index 290d354a016c..ec5abf166b23 100644
--- a/src/ap/drv_callbacks.c
+++ b/src/ap/drv_callbacks.c
@@ -459,8 +459,8 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
if (hapd->conf->sae_pwe == 2 &&
sta->auth_alg == WLAN_AUTH_SAE &&
sta->sae && !sta->sae->h2e &&
- elems.rsnxe && elems.rsnxe_len >= 1 &&
- (elems.rsnxe[0] & BIT(WLAN_RSNX_CAPAB_SAE_H2E))) {
+ ieee802_11_rsnx_capab_len(elems.rsnxe, elems.rsnxe_len,
+ WLAN_RSNX_CAPAB_SAE_H2E)) {
wpa_printf(MSG_INFO, "SAE: " MACSTR
" indicates support for SAE H2E, but did not use it",
MAC2STR(sta->addr));
diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c
index 7bb0f097669b..e9aae6dcf2f5 100644
--- a/src/ap/hostapd.c
+++ b/src/ap/hostapd.c
@@ -107,7 +107,8 @@ static void hostapd_reload_bss(struct hostapd_data *hapd)
return;
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
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)
- conf->wmm_enabled = hapd->iconf->ieee80211n;
+ conf->wmm_enabled = hapd->iconf->ieee80211n |
+ hapd->iconf->ieee80211ax;
#ifdef CONFIG_IEEE80211R_AP
if (is_zero_ether_addr(conf->r1_key_holder))
diff --git a/src/ap/hostapd.h b/src/ap/hostapd.h
index 44f566a42403..07d0aaa92100 100644
--- a/src/ap/hostapd.h
+++ b/src/ap/hostapd.h
@@ -354,6 +354,8 @@ struct hostapd_data {
int last_bigtk_key_idx;
u8 last_bigtk[WPA_BIGTK_MAX_LEN];
size_t last_bigtk_len;
+
+ bool force_backlog_bytes;
#endif /* CONFIG_TESTING_OPTIONS */
#ifdef CONFIG_MBO
diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c
index 72d102f44e21..b404e84affe5 100644
--- a/src/ap/ieee802_11.c
+++ b/src/ap/ieee802_11.c
@@ -572,7 +572,7 @@ static struct wpabuf * auth_build_sae_commit(struct hostapd_data *hapd,
if (update && !use_pt &&
sae_prepare_commit(hapd->own_addr, sta->addr,
- (u8 *) password, os_strlen(password), rx_id,
+ (u8 *) password, os_strlen(password),
sta->sae) < 0) {
wpa_printf(MSG_DEBUG, "SAE: Could not pick PWE");
return NULL;
@@ -702,13 +702,15 @@ static int use_anti_clogging(struct hostapd_data *hapd)
for (sta = hapd->sta_list; sta; sta = sta->next) {
#ifdef CONFIG_SAE
- if (!sta->sae)
- continue;
- if (sta->sae->state != SAE_COMMITTED &&
- sta->sae->state != SAE_CONFIRMED)
- continue;
- open++;
+ if (sta->sae &&
+ (sta->sae->state == SAE_COMMITTED ||
+ sta->sae->state == SAE_CONFIRMED))
+ open++;
#endif /* CONFIG_SAE */
+#ifdef CONFIG_PASN
+ if (sta->pasn && sta->pasn->ecdh)
+ open++;
+#endif /* CONFIG_PASN */
if (open >= hapd->conf->anti_clogging_threshold)
return 1;
}
@@ -806,7 +808,8 @@ static struct wpabuf * auth_build_token_req(struct hostapd_data *hapd,
if (buf == NULL)
return NULL;
- wpabuf_put_le16(buf, group); /* Finite Cyclic Group */
+ if (group)
+ wpabuf_put_le16(buf, group); /* Finite Cyclic Group */
if (h2e) {
/* Encapsulate Anti-clogging Token field in a container IE */
@@ -2380,11 +2383,12 @@ static int pasn_wd_handle_sae_commit(struct hostapd_data *hapd,
struct wpabuf *wd)
{
struct pasn_data *pasn = sta->pasn;
- const char *password = NULL;
+ const char *password;
const u8 *data;
size_t buf_len;
u16 res, alg, seq, status;
int groups[] = { pasn->group, 0 };
+ struct sae_pt *pt = NULL;
int ret;
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",
alg, seq, status);
- /* TODO: SAE H2E */
- if (alg != WLAN_AUTH_SAE || seq != 1 || status != WLAN_STATUS_SUCCESS) {
+ if (alg != WLAN_AUTH_SAE || seq != 1 ||
+ status != WLAN_STATUS_SAE_HASH_TO_ELEMENT) {
wpa_printf(MSG_DEBUG, "PASN: Dropping peer SAE commit");
return -1;
}
@@ -2421,15 +2425,14 @@ static int pasn_wd_handle_sae_commit(struct hostapd_data *hapd,
return -1;
}
- password = sae_get_password(hapd, sta, NULL, NULL, NULL, NULL);
- if (!password) {
- wpa_printf(MSG_DEBUG, "PASN: No SAE password found");
+ password = sae_get_password(hapd, sta, NULL, NULL, &pt, NULL);
+ if (!password || !pt) {
+ wpa_printf(MSG_DEBUG, "PASN: No SAE PT found");
return -1;
}
- ret = sae_prepare_commit(hapd->own_addr, sta->addr,
- (const u8 *) password, os_strlen(password), 0,
- &pasn->sae);
+ ret = sae_prepare_commit_pt(&pasn->sae, pt, hapd->own_addr, sta->addr,
+ NULL, NULL);
if (ret) {
wpa_printf(MSG_DEBUG, "PASN: Failed to prepare SAE commit");
return -1;
@@ -2526,7 +2529,7 @@ static struct wpabuf * pasn_get_sae_wd(struct hostapd_data *hapd,
len_ptr = wpabuf_put(buf, 2);
wpabuf_put_le16(buf, WLAN_AUTH_SAE);
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 */
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_len(pasn->secret),
&sta->pasn->ptk, sta->pasn->akmp,
- sta->pasn->cipher, WPA_KDK_MAX_LEN);
+ sta->pasn->cipher, sta->pasn->kdk_len);
if (ret) {
wpa_printf(MSG_DEBUG, "PASN: FILS: Failed to derive PTK");
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,
wpabuf_head(secret), wpabuf_len(secret),
&sta->pasn->ptk, sta->pasn->akmp,
- sta->pasn->cipher, WPA_KDK_MAX_LEN);
+ sta->pasn->cipher, sta->pasn->kdk_len);
if (ret) {
wpa_printf(MSG_DEBUG, "PASN: Failed to derive PTK");
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,
struct sta_info *sta,
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->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) {
wpa_printf(MSG_DEBUG,
"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;
}
+ 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);
if (!sta->pasn->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 &&
sta->auth_alg == WLAN_AUTH_SAE &&
sta->sae && !sta->sae->h2e &&
- elems.rsnxe && elems.rsnxe_len >= 1 &&
- (elems.rsnxe[0] & BIT(WLAN_RSNX_CAPAB_SAE_H2E))) {
+ ieee802_11_rsnx_capab_len(elems.rsnxe, elems.rsnxe_len,
+ WLAN_RSNX_CAPAB_SAE_H2E)) {
wpa_printf(MSG_INFO, "SAE: " MACSTR
" indicates support for SAE H2E, but did not use it",
MAC2STR(sta->addr));
diff --git a/src/ap/ieee802_11_shared.c b/src/ap/ieee802_11_shared.c
index d0074f6ba220..4bff9e591883 100644
--- a/src/ap/ieee802_11_shared.c
+++ b/src/ap/ieee802_11_shared.c
@@ -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 *pos = eid;
- u8 len = 0, 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 */
+ u8 len = EXT_CAPA_MAX_LEN, i;
+
if (len < hapd->iface->extended_capa_len)
len = hapd->iface->extended_capa_len;
- if (len == 0)
- return eid;
*pos++ = WLAN_EID_EXT_CAPAB;
*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[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) {
diff --git a/src/ap/sta_info.h b/src/ap/sta_info.h
index efa48e7e3d8d..27e72f9a0164 100644
--- a/src/ap/sta_info.h
+++ b/src/ap/sta_info.h
@@ -88,6 +88,7 @@ struct pasn_data {
u16 group;
u8 trans_seq;
u8 wrapped_data_format;
+ size_t kdk_len;
u8 hash[SHA384_MAC_LEN];
struct wpa_ptk ptk;
diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c
index 6c791e26b0b7..59cd46aa4601 100644
--- a/src/ap/wpa_auth.c
+++ b/src/ap/wpa_auth.c
@@ -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 ||
(sm->wpa_auth->conf.secure_ltf &&
- sm->rsnxe && sm->rsnxe_len >= 4 &&
- sm->rsnxe[3] & BIT(WLAN_RSNX_CAPAB_SECURE_LTF - 8)))
+ ieee802_11_rsnx_capab(sm->rsnxe, WLAN_RSNX_CAPAB_SECURE_LTF)))
kdk_len = WPA_KDK_MAX_LEN;
else
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 ||
(sm->wpa_auth->conf.secure_ltf &&
- sm->rsnxe && sm->rsnxe_len >= 4 &&
- sm->rsnxe[3] & BIT(WLAN_RSNX_CAPAB_SECURE_LTF - 8)))
+ ieee802_11_rsnx_capab(sm->rsnxe, WLAN_RSNX_CAPAB_SECURE_LTF)))
kdk_len = WPA_KDK_MAX_LEN;
else
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",
gsm->GN_bigtk);
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;
}
diff --git a/src/ap/wpa_auth_ft.c b/src/ap/wpa_auth_ft.c
index 32b745651ace..e80086b93d8d 100644
--- a/src/ap/wpa_auth_ft.c
+++ b/src/ap/wpa_auth_ft.c
@@ -3198,8 +3198,7 @@ pmk_r1_derived:
if (sm->wpa_auth->conf.force_kdk_derivation ||
(sm->wpa_auth->conf.secure_ltf &&
- sm->rsnxe && sm->rsnxe_len >= 4 &&
- sm->rsnxe[3] & BIT(WLAN_RSNX_CAPAB_SECURE_LTF - 8)))
+ ieee802_11_rsnx_capab(sm->rsnxe, WLAN_RSNX_CAPAB_SECURE_LTF)))
kdk_len = WPA_KDK_MAX_LEN;
else
kdk_len = 0;
diff --git a/src/common/common_module_tests.c b/src/common/common_module_tests.c
index 50ce1923c120..8aba713f92ba 100644
--- a/src/common/common_module_tests.c
+++ b/src/common/common_module_tests.c
@@ -256,87 +256,69 @@ static int sae_tests(void)
#ifdef CONFIG_SAE
struct sae_data sae;
int ret = -1;
- /* IEEE P802.11-REVmd/D2.1, Annex J.10 */
- const u8 addr1[ETH_ALEN] = { 0x82, 0x7b, 0x91, 0x9d, 0xd4, 0xb9 };
- const u8 addr2[ETH_ALEN] = { 0x1e, 0xec, 0x49, 0xea, 0x64, 0x88 };
+ /* IEEE Std 802.11-2020, Annex J.10 */
+ const u8 addr1[ETH_ALEN] = { 0x4d, 0x3f, 0x2f, 0xff, 0xe3, 0x87 };
+ const u8 addr2[ETH_ALEN] = { 0xa5, 0xd8, 0xaa, 0x95, 0x8e, 0x3c };
const char *ssid = "byteme";
const char *pw = "mekmitasdigoat";
const char *pwid = "psk4internet";
const u8 local_rand[] = {
- 0xa9, 0x06, 0xf6, 0x1e, 0x4d, 0x3a, 0x5d, 0x4e,
- 0xb2, 0x96, 0x5f, 0xf3, 0x4c, 0xf9, 0x17, 0xdd,
- 0x04, 0x44, 0x45, 0xc8, 0x78, 0xc1, 0x7c, 0xa5,
- 0xd5, 0xb9, 0x37, 0x86, 0xda, 0x9f, 0x83, 0xcf
+ 0x99, 0x24, 0x65, 0xfd, 0x3d, 0xaa, 0x3c, 0x60,
+ 0xaa, 0x65, 0x65, 0xb7, 0xf6, 0x2a, 0x2a, 0x7f,
+ 0x2e, 0x12, 0xdd, 0x12, 0xf1, 0x98, 0xfa, 0xf4,
+ 0xfb, 0xed, 0x89, 0xd7, 0xff, 0x1a, 0xce, 0x94
};
const u8 local_mask[] = {
- 0x42, 0x34, 0xb4, 0xfb, 0x17, 0xaa, 0x43, 0x5c,
- 0x52, 0xfb, 0xfd, 0xeb, 0xe6, 0x40, 0x39, 0xb4,
- 0x34, 0x78, 0x20, 0x0e, 0x54, 0xff, 0x7b, 0x6e,
- 0x07, 0xb6, 0x9c, 0xad, 0x74, 0x15, 0x3c, 0x15
+ 0x95, 0x07, 0xa9, 0x0f, 0x77, 0x7a, 0x04, 0x4d,
+ 0x6a, 0x08, 0x30, 0xb9, 0x1e, 0xa3, 0xd5, 0xdd,
+ 0x70, 0xbe, 0xce, 0x44, 0xe1, 0xac, 0xff, 0xb8,
+ 0x69, 0x83, 0xb5, 0xe1, 0xbf, 0x9f, 0xb3, 0x22
};
const u8 local_commit[] = {
- 0x13, 0x00, 0xeb, 0x3b, 0xab, 0x19, 0x64, 0xe4,
- 0xa0, 0xab, 0x05, 0x92, 0x5d, 0xdf, 0x33, 0x39,
- 0x51, 0x91, 0x38, 0xbc, 0x65, 0xd6, 0xcd, 0xc0,
- 0xf8, 0x13, 0xdd, 0x6f, 0xd4, 0x34, 0x4e, 0xb4,
- 0xbf, 0xe4, 0x4b, 0x5c, 0x21, 0x59, 0x76, 0x58,
- 0xf4, 0xe3, 0xed, 0xdf, 0xb4, 0xb9, 0x9f, 0x25,
- 0xb4, 0xd6, 0x54, 0x0f, 0x32, 0xff, 0x1f, 0xd5,
- 0xc5, 0x30, 0xc6, 0x0a, 0x79, 0x44, 0x48, 0x61,
- 0x0b, 0xc6, 0xde, 0x3d, 0x92, 0xbd, 0xbb, 0xd4,
- 0x7d, 0x93, 0x59, 0x80, 0xca, 0x6c, 0xf8, 0x98,
- 0x8a, 0xb6, 0x63, 0x0b, 0xe6, 0x76, 0x4c, 0x88,
- 0x5c, 0xeb, 0x97, 0x93, 0x97, 0x0f, 0x69, 0x52,
- 0x17, 0xee, 0xff, 0x0d, 0x21, 0x70, 0x73, 0x6b,
- 0x34, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65,
- 0x74
+ 0x13, 0x00, 0x2e, 0x2c, 0x0f, 0x0d, 0xb5, 0x24,
+ 0x40, 0xad, 0x14, 0x6d, 0x96, 0x71, 0x14, 0xce,
+ 0x00, 0x5c, 0xe1, 0xea, 0xb0, 0xaa, 0x2c, 0x2e,
+ 0x5c, 0x28, 0x71, 0xb7, 0x74, 0xf6, 0xc2, 0x57,
+ 0x5c, 0x65, 0xd5, 0xad, 0x9e, 0x00, 0x82, 0x97,
+ 0x07, 0xaa, 0x36, 0xba, 0x8b, 0x85, 0x97, 0x38,
+ 0xfc, 0x96, 0x1d, 0x08, 0x24, 0x35, 0x05, 0xf4,
+ 0x7c, 0x03, 0x53, 0x76, 0xd7, 0xac, 0x4b, 0xc8,
+ 0xd7, 0xb9, 0x50, 0x83, 0xbf, 0x43, 0x82, 0x7d,
+ 0x0f, 0xc3, 0x1e, 0xd7, 0x78, 0xdd, 0x36, 0x71,
+ 0xfd, 0x21, 0xa4, 0x6d, 0x10, 0x91, 0xd6, 0x4b,
+ 0x6f, 0x9a, 0x1e, 0x12, 0x72, 0x62, 0x13, 0x25,
+ 0xdb, 0xe1
};
const u8 peer_commit[] = {
- 0x13, 0x00, 0x55, 0x64, 0xf0, 0x45, 0xb2, 0xea,
- 0x1e, 0x56, 0x6c, 0xf1, 0xdd, 0x74, 0x1f, 0x70,
- 0xd9, 0xbe, 0x35, 0xd2, 0xdf, 0x5b, 0x9a, 0x55,
- 0x02, 0x94, 0x6e, 0xe0, 0x3c, 0xf8, 0xda, 0xe2,
- 0x7e, 0x1e, 0x05, 0xb8, 0x43, 0x0e, 0xb7, 0xa9,
- 0x9e, 0x24, 0x87, 0x7c, 0xe6, 0x9b, 0xaf, 0x3d,
- 0xc5, 0x80, 0xe3, 0x09, 0x63, 0x3d, 0x6b, 0x38,
- 0x5f, 0x83, 0xee, 0x1c, 0x3e, 0xc3, 0x59, 0x1f,
- 0x1a, 0x53, 0x93, 0xc0, 0x6e, 0x80, 0x5d, 0xdc,
- 0xeb, 0x2f, 0xde, 0x50, 0x93, 0x0d, 0xd7, 0xcf,
- 0xeb, 0xb9, 0x87, 0xc6, 0xff, 0x96, 0x66, 0xaf,
- 0x16, 0x4e, 0xb5, 0x18, 0x4d, 0x8e, 0x66, 0x62,
- 0xed, 0x6a, 0xff, 0x0d, 0x21, 0x70, 0x73, 0x6b,
- 0x34, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65,
- 0x74
+ 0x13, 0x00, 0x59, 0x1b, 0x96, 0xf3, 0x39, 0x7f,
+ 0xb9, 0x45, 0x10, 0x08, 0x48, 0xe7, 0xb5, 0x50,
+ 0x54, 0x3b, 0x67, 0x20, 0xd8, 0x83, 0x37, 0xee,
+ 0x93, 0xfc, 0x49, 0xfd, 0x6d, 0xf7, 0xe0, 0x8b,
+ 0x52, 0x23, 0xe7, 0x1b, 0x9b, 0xb0, 0x48, 0xd3,
+ 0x87, 0x3f, 0x20, 0x55, 0x69, 0x53, 0xa9, 0x6c,
+ 0x91, 0x53, 0x6f, 0xd8, 0xee, 0x6c, 0xa9, 0xb4,
+ 0xa6, 0x8a, 0x14, 0x8b, 0x05, 0x6a, 0x90, 0x9b,
+ 0xe0, 0x3e, 0x83, 0xae, 0x20, 0x8f, 0x60, 0xf8,
+ 0xef, 0x55, 0x37, 0x85, 0x80, 0x74, 0xdb, 0x06,
+ 0x68, 0x70, 0x32, 0x39, 0x98, 0x62, 0x99, 0x9b,
+ 0x51, 0x1e, 0x0a, 0x15, 0x52, 0xa5, 0xfe, 0xa3,
+ 0x17, 0xc2
};
const u8 kck[] = {
- 0x59, 0x9d, 0x6f, 0x1e, 0x27, 0x54, 0x8b, 0xe8,
- 0x49, 0x9d, 0xce, 0xed, 0x2f, 0xec, 0xcf, 0x94,
- 0x81, 0x8c, 0xe1, 0xc7, 0x9f, 0x1b, 0x4e, 0xb3,
- 0xd6, 0xa5, 0x32, 0x28, 0xa0, 0x9b, 0xf3, 0xed
+ 0x1e, 0x73, 0x3f, 0x6d, 0x9b, 0xd5, 0x32, 0x56,
+ 0x28, 0x73, 0x04, 0x33, 0x88, 0x31, 0xb0, 0x9a,
+ 0x39, 0x40, 0x6d, 0x12, 0x10, 0x17, 0x07, 0x3a,
+ 0x5c, 0x30, 0xdb, 0x36, 0xf3, 0x6c, 0xb8, 0x1a
};
const u8 pmk[] = {
- 0x7a, 0xea, 0xd8, 0x6f, 0xba, 0x4c, 0x32, 0x21,
- 0xfc, 0x43, 0x7f, 0x5f, 0x14, 0xd7, 0x0d, 0x85,
- 0x4e, 0xa5, 0xd5, 0xaa, 0xc1, 0x69, 0x01, 0x16,
- 0x79, 0x30, 0x81, 0xed, 0xa4, 0xd5, 0x57, 0xc5
+ 0x4e, 0x4d, 0xfa, 0xb1, 0xa2, 0xdd, 0x8a, 0xc1,
+ 0xa9, 0x17, 0x90, 0xf9, 0x53, 0xfa, 0xaa, 0x45,
+ 0x2a, 0xe5, 0xc6, 0x87, 0x3a, 0xb7, 0x5b, 0x63,
+ 0x60, 0x5b, 0xa6, 0x63, 0xf8, 0xa7, 0xfe, 0x59
};
const u8 pmkid[] = {
- 0x40, 0xa0, 0x9b, 0x60, 0x17, 0xce, 0xbf, 0x00,
- 0x72, 0x84, 0x3b, 0x53, 0x52, 0xaa, 0x2b, 0x4f
- };
- 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
+ 0x87, 0x47, 0xa6, 0x00, 0xee, 0xa3, 0xf9, 0xf2,
+ 0x24, 0x75, 0xdf, 0x58, 0xca, 0x1e, 0x54, 0x98
};
struct wpabuf *buf = NULL;
struct crypto_bignum *mask = NULL;
@@ -412,7 +394,7 @@ static int sae_tests(void)
if (!buf ||
sae_set_group(&sae, 19) < 0 ||
sae_prepare_commit(addr1, addr2, (const u8 *) pw, os_strlen(pw),
- pwid, &sae) < 0)
+ &sae) < 0)
goto fail;
/* Override local values based on SAE test vector */
@@ -434,7 +416,7 @@ static int sae_tests(void)
goto fail;
/* 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;
wpa_hexdump_buf(MSG_DEBUG, "SAE: Commit message", buf);
@@ -465,21 +447,6 @@ static int sae_tests(void)
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,
(const u8 *) ssid, os_strlen(ssid),
(const u8 *) pw, os_strlen(pw), pwid);
diff --git a/src/common/ieee802_11_common.c b/src/common/ieee802_11_common.c
index 5b80db6d3b83..96681843e258 100644
--- a/src/common/ieee802_11_common.c
+++ b/src/common/ieee802_11_common.c
@@ -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,
int primary_channel,
struct ieee80211_edmg_config *edmg)
diff --git a/src/common/ieee802_11_common.h b/src/common/ieee802_11_common.h
index 8a16f1666221..fe2b1bca601b 100644
--- a/src/common/ieee802_11_common.h
+++ b/src/common/ieee802_11_common.h
@@ -269,6 +269,9 @@ int ieee802_11_parse_candidate_list(const char *pos, u8 *nei_rep,
size_t nei_rep_len);
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_ch_width(u8 op_class);
diff --git a/src/common/qca-vendor.h b/src/common/qca-vendor.h
index 573e144a63d5..32c93bb84d54 100644
--- a/src/common/qca-vendor.h
+++ b/src/common/qca-vendor.h
@@ -8445,6 +8445,34 @@ enum qca_wlan_twt_setup_state {
* This parameter is used for
* 1. TWT SET Request and 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 {
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_BCAST_ID = 22,
+ QCA_WLAN_VENDOR_ATTR_TWT_SETUP_BCAST_RECOMMENDATION = 23,
+ QCA_WLAN_VENDOR_ATTR_TWT_SETUP_BCAST_PERSISTENCE = 24,
+
/* keep last */
QCA_WLAN_VENDOR_ATTR_TWT_SETUP_AFTER_LAST,
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
* session due to roaming. Used on the TWT_TERMINATE notification from the
* 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 {
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_PEER_INITIATED_TERMINATE = 16,
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,
};
/**
diff --git a/src/common/sae.c b/src/common/sae.c
index f0d4c228c5da..74920a78e46a 100644
--- a/src/common/sae.c
+++ b/src/common/sae.c
@@ -280,13 +280,12 @@ fail:
static int sae_derive_pwe_ecc(struct sae_data *sae, const u8 *addr1,
const u8 *addr2, const u8 *password,
- size_t password_len, const char *identifier)
+ size_t password_len)
{
u8 counter, k;
u8 addrs[2 * ETH_ALEN];
- const u8 *addr[3];
- size_t len[3];
- size_t num_elem;
+ const u8 *addr[2];
+ size_t len[2];
u8 *dummy_password, *tmp_password;
int pwd_seed_odd = 0;
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",
password, password_len);
- if (identifier)
- wpa_printf(MSG_DEBUG, "SAE: password identifier: %s",
- identifier);
/*
* 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),
* base || counter)
*/
@@ -338,15 +334,8 @@ static int sae_derive_pwe_ecc(struct sae_data *sae, const u8 *addr1,
addr[0] = tmp_password;
len[0] = password_len;
- num_elem = 1;
- if (identifier) {
- 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++;
+ addr[1] = &counter;
+ len[1] = sizeof(counter);
/*
* 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);
const_time_select_bin(found, dummy_password, 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)
break;
@@ -438,13 +427,12 @@ fail:
static int sae_derive_pwe_ffc(struct sae_data *sae, const u8 *addr1,
const u8 *addr2, const u8 *password,
- size_t password_len, const char *identifier)
+ size_t password_len)
{
u8 counter, k, sel_counter = 0;
u8 addrs[2 * ETH_ALEN];
- const u8 *addr[3];
- size_t len[3];
- size_t num_elem;
+ const u8 *addr[2];
+ size_t len[2];
u8 found = 0; /* 0 (false) or 0xff (true) to be used as const_time_*
* 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)
* 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);
addr[0] = password;
len[0] = password_len;
- num_elem = 1;
- if (identifier) {
- 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++;
+ addr[1] = &counter;
+ len[1] = sizeof(counter);
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);
- if (hmac_sha256_vector(addrs, sizeof(addrs), num_elem,
+ if (hmac_sha256_vector(addrs, sizeof(addrs), 2,
addr, len, pwd_seed) < 0)
break;
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,
const u8 *password, size_t password_len,
- const char *identifier, struct sae_data *sae)
+ struct sae_data *sae)
{
if (sae->tmp == NULL ||
(sae->tmp->ec && sae_derive_pwe_ecc(sae, addr1, addr2, password,
- password_len,
- identifier) < 0) ||
+ password_len) < 0) ||
(sae->tmp->dh && sae_derive_pwe_ffc(sae, addr1, addr2, password,
- password_len,
- identifier) < 0))
+ password_len) < 0))
return -1;
sae->h2e = 0;
@@ -2268,10 +2247,10 @@ int sae_write_confirm(struct sae_data *sae, struct wpabuf *buf)
hash_len = sae->tmp->kck_len;
/* Send-Confirm */
- sc = wpabuf_put(buf, 0);
- wpabuf_put_le16(buf, sae->send_confirm);
if (sae->send_confirm < 0xffff)
sae->send_confirm++;
+ sc = wpabuf_put(buf, 0);
+ wpabuf_put_le16(buf, sae->send_confirm);
if (sae->tmp->ec)
res = sae_cn_confirm_ecc(sae, sc, sae->tmp->own_commit_scalar,
diff --git a/src/common/sae.h b/src/common/sae.h
index 2243c0f339b0..93fc5fb39712 100644
--- a/src/common/sae.h
+++ b/src/common/sae.h
@@ -122,7 +122,7 @@ void sae_clear_data(struct sae_data *sae);
int sae_prepare_commit(const u8 *addr1, const u8 *addr2,
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,
const u8 *addr1, const u8 *addr2,
int *rejected_groups, const struct sae_pk *pk);
diff --git a/src/common/wpa_common.c b/src/common/wpa_common.c
index 493da18d7265..04461516f138 100644
--- a/src/common/wpa_common.c
+++ b/src/common/wpa_common.c
@@ -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,
u8 wrapped_data_format,
- struct wpabuf *pubkey, bool compressed,
- struct wpabuf *comeback, int after)
+ const struct wpabuf *pubkey, bool compressed,
+ const struct wpabuf *comeback, int after)
{
struct pasn_parameter_ie *params;
diff --git a/src/common/wpa_common.h b/src/common/wpa_common.h
index e51e19483e79..a1ff895659cb 100644
--- a/src/common/wpa_common.h
+++ b/src/common/wpa_common.h
@@ -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,
u8 wrapped_data_format,
- struct wpabuf *pubkey, bool compressed,
- struct wpabuf *comeback, int after);
+ const struct wpabuf *pubkey, bool compressed,
+ const struct wpabuf *comeback, int after);
int wpa_pasn_add_wrapped_data(struct wpabuf *buf,
struct wpabuf *wrapped_data_buf);
diff --git a/src/crypto/crypto_openssl.c b/src/crypto/crypto_openssl.c
index 72f93c19255a..a4b1083bb4c1 100644
--- a/src/crypto/crypto_openssl.c
+++ b/src/crypto/crypto_openssl.c
@@ -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)
{
if (pkey->type != EVP_PKEY_EC)
return NULL;
return pkey->pkey.ec;
}
+#endif /* CONFIG_ECC */
#endif /* OpenSSL version < 1.1.0 */
diff --git a/src/drivers/driver.h b/src/drivers/driver.h
index 5b2c71ca0fd0..8ef9ea23a986 100644
--- a/src/drivers/driver.h
+++ b/src/drivers/driver.h
@@ -4553,6 +4553,12 @@ struct wpa_driver_ops {
* explicitly allow reception of broadcast Public Action frames.
*/
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 */
};
/**
diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index 35526fc2fe06..ed194be2a8a6 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -656,12 +656,10 @@ struct nl_msg * nl80211_cmd_msg(struct i802_bss *bss, int flags, uint8_t cmd)
static struct nl_msg *
-nl80211_ifindex_msg(struct wpa_driver_nl80211_data *drv, int ifindex,
- int flags, uint8_t cmd)
+nl80211_ifindex_msg_build(struct wpa_driver_nl80211_data *drv,
+ struct nl_msg *msg, int ifindex, int flags,
+ uint8_t cmd)
{
- struct nl_msg *msg;
-
- msg = nlmsg_alloc();
if (!msg)
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,
uint8_t cmd)
{
@@ -4151,6 +4158,7 @@ static int wpa_driver_nl80211_set_acl(void *priv,
struct nl_msg *acl;
unsigned int i;
int ret;
+ size_t acl_nla_sz, acl_nlmsg_sz, nla_sz, nlmsg_sz;
if (!(drv->capa.max_acl_mac_addrs))
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)",
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)
return -ENOMEM;
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 ?
NL80211_ACL_POLICY_DENY_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 nl_msg *msg;
+ int ret;
wpa_printf(MSG_DEBUG,
"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))
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:
nlmsg_free(msg);
return -ENOBUFS;
@@ -12028,6 +12057,23 @@ static int nl80211_dpp_listen(void *priv, bool enable)
#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 = {
.name = "nl80211",
.desc = "Linux nl80211/cfg80211",
@@ -12166,4 +12212,7 @@ const struct wpa_driver_ops wpa_driver_nl80211_ops = {
#ifdef CONFIG_DPP
.dpp_listen = nl80211_dpp_listen,
#endif /* CONFIG_DPP */
+#ifdef CONFIG_TESTING_OPTIONS
+ .register_frame = testing_nl80211_register_frame,
+#endif /* CONFIG_TESTING_OPTIONS */
};
diff --git a/src/drivers/driver_nl80211_capa.c b/src/drivers/driver_nl80211_capa.c
index d3d43d48a7cb..cd596e311e59 100644
--- a/src/drivers/driver_nl80211_capa.c
+++ b/src/drivers/driver_nl80211_capa.c
@@ -891,7 +891,7 @@ static int wiphy_info_handler(struct nl_msg *msg, void *arg)
if (tb[NL80211_ATTR_MAC_ACL_MAX])
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_iface_comb(info, tb[NL80211_ATTR_INTERFACE_COMBINATIONS]);
diff --git a/src/eap_common/eap_sim_common.c b/src/eap_common/eap_sim_common.c
index 4a9324406509..ab9bd86774b3 100644
--- a/src/eap_common/eap_sim_common.c
+++ b/src/eap_common/eap_sim_common.c
@@ -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)
{
static const char *anonymous_id_prefix = "anonymous@";
+ const u8 *decorated;
size_t anonymous_id_len = os_strlen(anonymous_id_prefix);
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] == '@')
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;
}
diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c
index 9a5ba7b877c5..78e2380b15e8 100644
--- a/src/rsn_supp/wpa.c
+++ b/src/rsn_supp/wpa.c
@@ -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,
NULL, 0, &buflen, NULL);
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,
buf, buflen);
os_free(buf);
@@ -605,8 +609,8 @@ static int wpa_derive_ptk(struct wpa_sm *sm, const unsigned char *src_addr,
#endif /* CONFIG_OWE */
if (sm->force_kdk_derivation ||
- (sm->secure_ltf && sm->ap_rsnxe && sm->ap_rsnxe_len >= 4 &&
- sm->ap_rsnxe[3] & BIT(WLAN_RSNX_CAPAB_SECURE_LTF - 8)))
+ (sm->secure_ltf &&
+ ieee802_11_rsnx_capab(sm->ap_rsnxe, WLAN_RSNX_CAPAB_SECURE_LTF)))
kdk_len = WPA_KDK_MAX_LEN;
else
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 ||
- (sm->secure_ltf && sm->ap_rsnxe && sm->ap_rsnxe_len >= 4 &&
- sm->ap_rsnxe[3] & BIT(WLAN_RSNX_CAPAB_SECURE_LTF - 8)))
+ (sm->secure_ltf &&
+ ieee802_11_rsnx_capab(sm->ap_rsnxe, WLAN_RSNX_CAPAB_SECURE_LTF)))
kdk_len = WPA_KDK_MAX_LEN;
else
kdk_len = 0;
diff --git a/src/rsn_supp/wpa_ft.c b/src/rsn_supp/wpa_ft.c
index fce6e77e7fb9..2669da9b3fa8 100644
--- a/src/rsn_supp/wpa_ft.c
+++ b/src/rsn_supp/wpa_ft.c
@@ -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);
if (sm->force_kdk_derivation ||
- (sm->secure_ltf && sm->ap_rsnxe && sm->ap_rsnxe_len >= 4 &&
- sm->ap_rsnxe[3] & BIT(WLAN_RSNX_CAPAB_SECURE_LTF - 8)))
+ (sm->secure_ltf &&
+ ieee802_11_rsnx_capab(sm->ap_rsnxe, WLAN_RSNX_CAPAB_SECURE_LTF)))
kdk_len = WPA_KDK_MAX_LEN;
else
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);
if (sm->force_kdk_derivation ||
- (sm->secure_ltf && sm->ap_rsnxe && sm->ap_rsnxe_len >= 4 &&
- sm->ap_rsnxe[3] & BIT(WLAN_RSNX_CAPAB_SECURE_LTF - 8)))
+ (sm->secure_ltf &&
+ ieee802_11_rsnx_capab(sm->ap_rsnxe, WLAN_RSNX_CAPAB_SECURE_LTF)))
kdk_len = WPA_KDK_MAX_LEN;
else
kdk_len = 0;
diff --git a/src/wps/wps_registrar.c b/src/wps/wps_registrar.c
index 0db936744327..45f7e947e0fd 100644
--- a/src/wps/wps_registrar.c
+++ b/src/wps/wps_registrar.c
@@ -1320,13 +1320,9 @@ static int wps_set_ie(struct wps_registrar *reg)
}
beacon = wpabuf_alloc(400 + vendor_len);
- if (beacon == NULL)
- return -1;
probe = wpabuf_alloc(500 + vendor_len);
- if (probe == NULL) {
- wpabuf_free(beacon);
- return -1;
- }
+ if (!beacon || !probe)
+ goto fail;
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(&reg->wps->dev, beacon, 0)) ||
wps_build_wfa_ext(beacon, 0, auth_macs, count, 0) ||
wps_build_vendor_ext(&reg->wps->dev, beacon) ||
- wps_build_application_ext(&reg->wps->dev, beacon)) {
- wpabuf_free(beacon);
- wpabuf_free(probe);
- return -1;
- }
+ wps_build_application_ext(&reg->wps->dev, beacon))
+ goto fail;
#ifdef CONFIG_P2P
if (wps_build_dev_name(&reg->wps->dev, beacon) ||
- wps_build_primary_dev_type(&reg->wps->dev, beacon)) {
- wpabuf_free(beacon);
- wpabuf_free(probe);
- return -1;
- }
+ wps_build_primary_dev_type(&reg->wps->dev, beacon))
+ goto fail;
#endif /* CONFIG_P2P */
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(&reg->wps->dev, probe, 0)) ||
wps_build_wfa_ext(probe, 0, auth_macs, count, 0) ||
wps_build_vendor_ext(&reg->wps->dev, probe) ||
- wps_build_application_ext(&reg->wps->dev, probe)) {
- wpabuf_free(beacon);
- wpabuf_free(probe);
- return -1;
- }
+ wps_build_application_ext(&reg->wps->dev, probe))
+ goto fail;
beacon = wps_ie_encapsulate(beacon);
probe = wps_ie_encapsulate(probe);
- if (!beacon || !probe) {
- wpabuf_free(beacon);
- wpabuf_free(probe);
- return -1;
- }
+ if (!beacon || !probe)
+ goto fail;
return wps_cb_set_ie(reg, beacon, probe);
+fail:
+ wpabuf_free(beacon);
+ wpabuf_free(probe);
+ return -1;
}
diff --git a/tests/hwsim/example-hostapd.config b/tests/hwsim/example-hostapd.config
index 8b466e8aeca3..d01a1d2edcfe 100644
--- a/tests/hwsim/example-hostapd.config
+++ b/tests/hwsim/example-hostapd.config
@@ -113,3 +113,4 @@ CONFIG_DPP=y
CONFIG_DPP2=y
CONFIG_WEP=y
CONFIG_PASN=y
+CONFIG_AIRTIME_POLICY=y
diff --git a/tests/hwsim/hostapd.py b/tests/hwsim/hostapd.py
index d484f67bc47f..5ea68444c1b9 100644
--- a/tests/hwsim/hostapd.py
+++ b/tests/hwsim/hostapd.py
@@ -419,6 +419,12 @@ class Hostapd:
raise Exception("Failed to parse QR Code URI")
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,
curve=None, key=None):
cmd = "DPP_BOOTSTRAP_GEN type=" + type
@@ -466,10 +472,14 @@ class Hostapd:
def dpp_auth_init(self, peer=None, uri=None, conf=None, configurator=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"
if peer is None:
- peer = self.dpp_qr_code(uri)
+ if nfc_uri:
+ peer = self.dpp_nfc_uri(nfc_uri)
+ else:
+ peer = self.dpp_qr_code(uri)
cmd += " peer=%d" % peer
if own is not None:
cmd += " own=%d" % own
@@ -487,6 +497,8 @@ class Hostapd:
cmd += " ssid=" + binascii.hexlify(ssid.encode()).decode()
if passphrase:
cmd += " pass=" + binascii.hexlify(passphrase.encode()).decode()
+ if conn_status:
+ cmd += " conn_status=1"
res = self.request(cmd)
if expect_fail:
if "FAIL" not in res:
diff --git a/tests/hwsim/test_ap_eap.py b/tests/hwsim/test_ap_eap.py
index 9efa2b47d888..d5e1d995b81e 100644
--- a/tests/hwsim/test_ap_eap.py
+++ b/tests/hwsim/test_ap_eap.py
@@ -881,6 +881,7 @@ def test_ap_wpa2_eap_sim_ext_anonymous(dev, apdev):
try:
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!anonymous@otherexample.org")
finally:
dev[0].request("SET external_sim 0")
diff --git a/tests/hwsim/test_ap_ft.py b/tests/hwsim/test_ap_ft.py
index c28dd26e1e68..00b1635db072 100644
--- a/tests/hwsim/test_ap_ft.py
+++ b/tests/hwsim/test_ap_ft.py
@@ -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,
roam_with_reassoc=False, also_non_ft=False, only_one_way=False,
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")
copts = {}
@@ -151,6 +151,8 @@ def run_roams(dev, apdev, hapd0, hapd1, ssid, passphrase, over_ds=False,
copts["group_mgmt"] = group_mgmt
if ocv:
copts["ocv"] = ocv
+ if beacon_prot:
+ copts["beacon_prot"] = "1"
if eap:
if pmksa_caching:
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")
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
# set later.
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")
if (i == 0 or i == roams - 1) and test_connectivity:
hapd2ap.wait_sta()
+ dev.dump_monitor()
+ hapd1ap.dump_monitor()
+ hapd2ap.dump_monitor()
if conndev:
hwsim_utils.test_connectivity_iface(dev, hapd2ap, conndev)
else:
hwsim_utils.test_connectivity(dev, hapd2ap)
+ dev.dump_monitor()
+ hapd1ap.dump_monitor()
+ hapd2ap.dump_monitor()
+
if only_one_way:
return
# 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")
if (i == 0 or i == roams - 1) and test_connectivity:
hapd1ap.wait_sta()
+ dev.dump_monitor()
+ hapd1ap.dump_monitor()
+ hapd2ap.dump_monitor()
if conndev:
hwsim_utils.test_connectivity_iface(dev, hapd1ap, conndev)
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)"""
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"
passphrase = "12345678"
params = ft_params1(ssid=ssid, passphrase=passphrase)
params["ieee80211w"] = "2"
+ if beacon_prot:
+ params["beacon_prot"] = "1"
hapd0 = hostapd.add_ap(apdev[0], params)
params = ft_params2(ssid=ssid, passphrase=passphrase)
params["ieee80211w"] = "2"
+ if beacon_prot:
+ params["beacon_prot"] = "1"
hapd1 = hostapd.add_ap(apdev[1], params)
Wlantest.setup(hapd0)
@@ -494,7 +518,7 @@ def run_ap_ft_pmf(dev, apdev, ieee80211w, over_ds=False):
wt.add_passphrase(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):
"""WPA2-PSK-FT AP with PMF required on STA but AP2 not enabling PMF"""
diff --git a/tests/hwsim/test_ap_ht.py b/tests/hwsim/test_ap_ht.py
index 99adb12a36a4..510fe0836fc5 100644
--- a/tests/hwsim/test_ap_ht.py
+++ b/tests/hwsim/test_ap_ht.py
@@ -1370,13 +1370,15 @@ def test_ap_ht40_scan_broken_ap(dev, apdev):
hwsim_utils.test_connectivity(dev[1], hapd2)
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])
try:
params = {"ssid": "test-ht40",
"hw_mode": hw_mode,
"channel": channel,
"ht_capab": ht_capab}
+ if use_op_class:
+ params['op_class'] = str(opclass)
if country:
params['country_code'] = country
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:
raise Exception("Unexpected operating class: %d" % rx_opclass)
hapd.disable()
+ hapd.dump_monitor()
dev[0].request("REMOVE_NETWORK all")
dev[0].request("ABORT_SCAN")
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):
"""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):
"""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):
"""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):
"""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):
"""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):
"""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):
"""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):
"""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):
"""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):
"""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):
"""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):
"""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):
"""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):
"""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):
"""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):
"""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):
"""HT40 with both plus and minus allowed (1)"""
diff --git a/tests/hwsim/test_ap_params.py b/tests/hwsim/test_ap_params.py
index 5da861593948..72ac8e443ff9 100644
--- a/tests/hwsim/test_ap_params.py
+++ b/tests/hwsim/test_ap_params.py
@@ -909,3 +909,64 @@ def test_ap_notify_mgmt_frames_disabled(dev, apdev):
ev = hapd.wait_event(["AP-MGMT-FRAME-RECEIVED"], timeout=0.1)
if ev is not None:
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)
diff --git a/tests/hwsim/test_ap_psk.py b/tests/hwsim/test_ap_psk.py
index be6a88b2a164..b6048be13844 100644
--- a/tests/hwsim/test_ap_psk.py
+++ b/tests/hwsim/test_ap_psk.py
@@ -500,6 +500,22 @@ def test_ap_wpa2_gtk_rekey_request(dev, apdev):
raise Exception("GTK rekey timed out")
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
def test_ap_wpa_gtk_rekey(dev, apdev):
"""WPA-PSK/TKIP AP and GTK rekey enforced by AP"""
diff --git a/tests/hwsim/test_ap_track.py b/tests/hwsim/test_ap_track.py
index 9d9e2cd460ee..ba8f3eb252cd 100644
--- a/tests/hwsim/test_ap_track.py
+++ b/tests/hwsim/test_ap_track.py
@@ -403,3 +403,35 @@ def _test_ap_track_taxonomy(dev, apdev):
raise Exception("Unexpected SIGNATURE prefix")
if "|assoc:" not in res:
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")
diff --git a/tests/hwsim/test_ap_wps.py b/tests/hwsim/test_ap_wps.py
index 08be5f41f230..a07ed60b8218 100644
--- a/tests/hwsim/test_ap_wps.py
+++ b/tests/hwsim/test_ap_wps.py
@@ -44,10 +44,12 @@ from wpasupplicant import WpaSupplicant
from utils import *
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",
"wpa_passphrase": "12345678", "wpa": "2",
"wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP"}
+ if extra_cred:
+ params['extra_cred'] = extra_cred
return hostapd.add_ap(apdev, params)
@remote_compatible
@@ -1067,6 +1069,43 @@ def test_ap_wps_pbc_overlap_2sta(dev, apdev):
dev[0].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
def test_ap_wps_cancel(dev, apdev):
"""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")
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:
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
wps_event_url = None
server.handle_request()
@@ -5105,6 +5146,15 @@ def test_ap_wps_er_http_client(dev, apdev):
run_wps_er_proto_test(dev[0], WPSAPHTTPServer_req_as_resp,
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):
"""wps_init OOM cases"""
ssid = "test-wps"
@@ -10464,3 +10514,55 @@ def run_ap_wps_ap_timeout(dev, apdev, cmd):
logger.info("BSS after timeout: " + str(bss))
if bss['ie'].endswith("0106ffffffffffff"):
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")
diff --git a/tests/hwsim/test_dpp.py b/tests/hwsim/test_dpp.py
index 3ba99bb1b0c7..b696c5d1dc2e 100644
--- a/tests/hwsim/test_dpp.py
+++ b/tests/hwsim/test_dpp.py
@@ -2581,6 +2581,14 @@ def test_dpp_pkex_hostapd_errors(dev, apdev):
def test_dpp_hostapd_configurator(dev, apdev):
"""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])
hapd = hostapd.add_ap(apdev[0], {"ssid": "unconfigured",
"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],
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):
"""DPP with hostapd as configurator and override objects"""
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:
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):
"""DPP MUD URL"""
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")
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):
"""DPP bootstrapping via NFC negotiated handover"""
run_dpp_nfc_negotiated_handover(dev)
@@ -5471,6 +5874,40 @@ def run_dpp_nfc_negotiated_handover(dev, curve0=None, curve1=None,
conf=conf)
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):
"""DPP exchange when driver uses a separate P2P Device interface"""
check_dpp_capab(dev[0])
@@ -5648,6 +6085,74 @@ def test_dpp_chirp_ap(dev, apdev):
timeout=20)
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):
"""DPP chirp errors in hostapd"""
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)
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):
"""DPP reconfiguration connector"""
try:
diff --git a/tests/hwsim/test_eap_proto.py b/tests/hwsim/test_eap_proto.py
index dab218dc1c57..afdc45d70ee2 100644
--- a/tests/hwsim/test_eap_proto.py
+++ b/tests/hwsim/test_eap_proto.py
@@ -2869,10 +2869,10 @@ def test_eap_proto_eke_errors(dev, apdev):
(1, "os_get_random;eap_eke_dhcomp", None),
(1, "aes_128_cbc_encrypt;eap_eke_dhcomp", None),
(1, "aes_128_cbc_decrypt;eap_eke_shared_secret", None),
- (1, "eap_eke_prf;eap_eke_shared_secret", None),
- (1, "eap_eke_prfplus;eap_eke_derive_ke_ki", None),
- (1, "eap_eke_prfplus;eap_eke_derive_ka", None),
- (1, "eap_eke_prfplus;eap_eke_derive_msk", None),
+ (1, "hmac_sha256_vector;eap_eke_shared_secret", None),
+ (1, "eap_eke_prf_hmac_sha256;eap_eke_derive_ke_ki", None),
+ (1, "eap_eke_prf_hmac_sha256;eap_eke_derive_ka", None),
+ (1, "eap_eke_prf_hmac_sha256;eap_eke_derive_msk", None),
(1, "os_get_random;eap_eke_prot", None),
(1, "aes_128_cbc_decrypt;eap_eke_decrypt_prot", None),
(1, "eap_eke_derive_key;eap_eke_process_commit", None),
diff --git a/tests/hwsim/test_fils.py b/tests/hwsim/test_fils.py
index 39b48e9808ce..9998299d81a8 100644
--- a/tests/hwsim/test_fils.py
+++ b/tests/hwsim/test_fils.py
@@ -2358,3 +2358,54 @@ def test_fils_discovery_frame(dev, apdev, params):
eap="PSK", identity="psk.user@example.com",
password_hex="0123456789abcdef0123456789abcdef",
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()
diff --git a/tests/hwsim/test_he.py b/tests/hwsim/test_he.py
index 68633c81c2cb..2593f35f0bf1 100644
--- a/tests/hwsim/test_he.py
+++ b/tests/hwsim/test_he.py
@@ -24,7 +24,7 @@ def test_he_open(dev, apdev):
"he_mu_edca_ac_be_ecwmax": "15"}
hapd = hostapd.add_ap(apdev[0], params)
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")
sta = hapd.get_sta(dev[0].own_addr())
if "[HE]" not in sta['flags']:
@@ -94,7 +94,25 @@ def test_he_params(dev, apdev):
"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 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")
def he_supported():
diff --git a/tests/hwsim/test_ieee8021x.py b/tests/hwsim/test_ieee8021x.py
index 89c282b396e0..630d6d0dbe92 100644
--- a/tests/hwsim/test_ieee8021x.py
+++ b/tests/hwsim/test_ieee8021x.py
@@ -245,6 +245,23 @@ def test_ieee8021x_held(dev, apdev):
dev[0].request("SET EAPOL::maxStart 3")
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):
zero_sign = "00000000000000000000000000000000"
frame = frame_start + zero_sign + frame_end
diff --git a/tests/hwsim/test_mbo.py b/tests/hwsim/test_mbo.py
index 65d446b7ee25..36efd6a0e0ce 100644
--- a/tests/hwsim/test_mbo.py
+++ b/tests/hwsim/test_mbo.py
@@ -543,15 +543,32 @@ def test_mbo_without_pmf(dev, apdev):
def test_mbo_without_pmf_workaround(dev, apdev):
"""MBO and WPA2 without PMF on misbehaving AP"""
ssid = "test-wnm-mbo"
- params = {'ssid': ssid, "wpa": '2',
- "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP",
- "wpa_passphrase": "12345678",
- "vendor_elements": "dd07506f9a16010100"}
- hapd = hostapd.add_ap(apdev[0], params)
+ params0 = {'ssid': ssid, "wpa": '2',
+ "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP",
+ "wpa_passphrase": "12345678",
+ "vendor_elements": "dd07506f9a16010100"}
+ 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",
proto="WPA2", ieee80211w="1", scan_freq="2412")
- hapd.wait_sta()
- sta = hapd.get_sta(dev[0].own_addr())
+ hapd0.wait_sta()
+ 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']))
if ext_capab[2] & 0x08:
raise Exception("STA did not disable BSS Transition capability")
diff --git a/tests/hwsim/test_mscs.py b/tests/hwsim/test_mscs.py
new file mode 100644
index 000000000000..b200550b3ac3
--- /dev/null
+++ b/tests/hwsim/test_mscs.py
@@ -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")
diff --git a/tests/hwsim/test_multi_ap.py b/tests/hwsim/test_multi_ap.py
index 183fb660d200..ca8ea3a31f90 100644
--- a/tests/hwsim/test_multi_ap.py
+++ b/tests/hwsim/test_multi_ap.py
@@ -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'])
raise
+ return hapd
+
def test_multi_ap_wps_shared(dev, apdev):
"""WPS on shared fronthaul/backhaul AP"""
ssid = "multi-ap-wps"
@@ -233,7 +235,15 @@ def test_multi_ap_wps_shared(dev, apdev):
params.update({"multi_ap": "3",
"multi_ap_backhaul_ssid": '"%s"' % ssid,
"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):
"""WPS on shared fronthaul/backhaul AP, run CSA"""
diff --git a/tests/hwsim/test_ocv.py b/tests/hwsim/test_ocv.py
index 08e8ba20f47b..e93cea6ffa18 100644
--- a/tests/hwsim/test_ocv.py
+++ b/tests/hwsim/test_ocv.py
@@ -982,12 +982,22 @@ def check_ocv_failure(dev, frame_txt, frame, addr):
def test_wpa2_ocv_ap_override_eapol_m3(dev, apdev):
"""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",
"ieee80211w": "2",
- "ocv": "1",
- "oci_freq_override_eapol_m3": "2462"}
+ "ocv": "1"}
+ if not post_enable:
+ params["oci_freq_override_eapol_m3"] = "2462"
hapd, ssid, passphrase = ocv_setup_ap(apdev[0], params)
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",
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):
"""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",
"ieee80211w": "2",
- "ocv": "1",
- "oci_freq_override_eapol_g1": "2462"}
+ "ocv": "1"}
+ if not post_enable:
+ params["oci_freq_override_eapol_g1"] = "2462"
hapd, ssid, passphrase = ocv_setup_ap(apdev[0], params)
bssid = hapd.own_addr()
dev[0].connect(ssid, psk=passphrase, scan_freq="2412", ocv="1",
ieee80211w="2")
+ if post_enable:
+ hapd.set("oci_freq_override_eapol_g1", "2462")
if "OK" not in hapd.request("REKEY_GTK"):
raise Exception("REKEY_GTK failed")
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):
"""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_erp_capa(dev[0])
@@ -1060,7 +1087,8 @@ def test_wpa2_ocv_ap_override_fils_assoc(dev, apdev, params):
params['wpa_group_rekey'] = '1'
params["ieee80211w"] = "2"
params["ocv"] = "1"
- params["oci_freq_override_fils_assoc"] = "2462"
+ if not post_enable:
+ params["oci_freq_override_fils_assoc"] = "2462"
try:
hapd = hostapd.add_ap(apdev[0], params)
except Exception as e:
@@ -1068,6 +1096,8 @@ def test_wpa2_ocv_ap_override_fils_assoc(dev, apdev, params):
raise HwsimSkip("OCV not supported")
raise
bssid = hapd.own_addr()
+ if post_enable:
+ hapd.set("oci_freq_override_fils_assoc", "2462")
dev[0].request("ERP_FLUSH")
id = dev[0].connect(ssid, key_mgmt="FILS-SHA256",
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):
"""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"
passphrase = "qwertyuiop"
params = ft_params1(ssid=ssid, passphrase=passphrase)
params["ieee80211w"] = "2"
params["ocv"] = "1"
- params["oci_freq_override_fils_assoc"] = "2462"
+ if not post_enable:
+ params["oci_freq_override_ft_assoc"] = "2462"
try:
hapd0 = hostapd.add_ap(apdev[0], params)
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["ieee80211w"] = "2"
params["ocv"] = "1"
- params["oci_freq_override_ft_assoc"] = "2462"
+ if not post_enable:
+ params["oci_freq_override_ft_assoc"] = "2462"
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,
scan_freq="2412", ocv="1", ieee80211w="2")
diff --git a/tests/hwsim/test_p2p_discovery.py b/tests/hwsim/test_p2p_discovery.py
index 4bce4ecccfbb..0537f02e9e5b 100644
--- a/tests/hwsim/test_p2p_discovery.py
+++ b/tests/hwsim/test_p2p_discovery.py
@@ -818,3 +818,54 @@ def test_p2p_group_cli_invalid(dev, apdev):
ev = dev[i].wait_global_event(["P2P-DEVICE-FOUND"], timeout=5)
if not ev:
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")
diff --git a/tests/hwsim/test_pasn.py b/tests/hwsim/test_pasn.py
index f2c7b3b221b6..c8bcd63f6ac7 100644
--- a/tests/hwsim/test_pasn.py
+++ b/tests/hwsim/test_pasn.py
@@ -13,6 +13,7 @@ logger = logging.getLogger()
import socket
import struct
import subprocess
+import re
import hwsim_utils
import hostapd
@@ -231,18 +232,23 @@ def test_pasn_sae_pmksa_cache(dev, apdev):
params = hostapd.wpa2_params(ssid="test-sae",
passphrase="12345678")
params['wpa_key_mgmt'] = 'SAE PASN'
+ params['sae_pwe'] = "2"
hapd = start_pasn_ap(apdev[0], params)
- dev[0].set("sae_groups", "19")
- dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", scan_freq="2412")
+ try:
+ 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")
- hapd.wait_sta()
- hwsim_utils.test_connectivity(dev[0], hapd)
+ hapd.wait_sta()
+ hwsim_utils.test_connectivity(dev[0], hapd)
- dev[0].request("DISCONNECT")
- dev[0].wait_disconnected()
+ dev[0].request("DISCONNECT")
+ 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):
check_fils_capa(dev[0])
@@ -298,16 +304,19 @@ def test_pasn_sae_kdk(dev, apdev):
params = hostapd.wpa2_params(ssid="test-sae",
passphrase="12345678")
params['wpa_key_mgmt'] = 'SAE PASN'
+ params['sae_pwe'] = "2"
params['force_kdk_derivation'] = "1"
hapd = start_pasn_ap(apdev[0], params)
dev[0].set("force_kdk_derivation", "1")
+ dev[0].set("sae_pwe", "2")
dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
scan_freq="2412")
check_pasn_ptk(dev[0], hapd, "CCMP", clear_keys=False)
finally:
dev[0].set("force_kdk_derivation", "0")
+ dev[0].set("sae_pwe", "0")
def check_pasn_fils_kdk(dev, apdev, params, key_mgmt):
@@ -383,23 +392,28 @@ def test_pasn_sae(dev, apdev):
params = hostapd.wpa2_params(ssid="test-pasn-sae",
passphrase="12345678")
params['wpa_key_mgmt'] = 'SAE PASN'
+ params['sae_pwe'] = "2"
hapd = start_pasn_ap(apdev[0], params)
- dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", scan_freq="2412",
- only_add_network=True)
+ 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")
+ # 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 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")
+ # 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")
+ 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_sae_while_connected_same_channel(dev, apdev):
@@ -411,18 +425,23 @@ def test_pasn_sae_while_connected_same_channel(dev, apdev):
passphrase="12345678")
hapd = hostapd.add_ap(apdev[0], params)
- dev[0].connect("test-pasn-wpa2-psk", psk="12345678", scan_freq="2412")
+ try:
+ dev[0].set("sae_pwe", "2")
+ dev[0].connect("test-pasn-wpa2-psk", psk="12345678", scan_freq="2412")
- params = hostapd.wpa2_params(ssid="test-pasn-sae",
- passphrase="12345678")
+ params = hostapd.wpa2_params(ssid="test-pasn-sae",
+ passphrase="12345678")
- params['wpa_key_mgmt'] = 'SAE PASN'
- hapd = start_pasn_ap(apdev[1], params)
+ params['wpa_key_mgmt'] = 'SAE PASN'
+ params['sae_pwe'] = "2"
+ hapd = start_pasn_ap(apdev[1], params)
- dev[0].connect("test-pasn-sae", psk="12345678", key_mgmt="SAE",
- scan_freq="2412", only_add_network=True)
+ dev[0].connect("test-pasn-sae", psk="12345678", key_mgmt="SAE",
+ 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
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"
hapd = hostapd.add_ap(apdev[0], params)
- wpas.connect("test-pasn-wpa2-psk", psk="12345678", scan_freq="2437")
+ try:
+ wpas.set("sae_pwe", "2")
+ wpas.connect("test-pasn-wpa2-psk", psk="12345678", scan_freq="2437")
- params = hostapd.wpa2_params(ssid="test-pasn-sae",
- passphrase="12345678")
+ params = hostapd.wpa2_params(ssid="test-pasn-sae",
+ passphrase="12345678")
- params['wpa_key_mgmt'] = 'SAE PASN'
- hapd = start_pasn_ap(apdev[1], params)
+ params['wpa_key_mgmt'] = 'SAE PASN'
+ params['sae_pwe'] = "2"
+ hapd = start_pasn_ap(apdev[1], params)
- wpas.connect("test-pasn-sae", psk="12345678", key_mgmt="SAE",
- scan_freq="2412", only_add_network=True)
+ wpas.connect("test-pasn-sae", psk="12345678", key_mgmt="SAE",
+ 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):
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], 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")
diff --git a/tests/hwsim/test_pmksa_cache.py b/tests/hwsim/test_pmksa_cache.py
index 526f7f455685..10d76a394f8d 100644
--- a/tests/hwsim/test_pmksa_cache.py
+++ b/tests/hwsim/test_pmksa_cache.py
@@ -1251,3 +1251,17 @@ def test_rsn_preauth_local_errors(dev, apdev):
raise Exception("ENABLE failed")
sock.send(_bssid + foreign + 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")
diff --git a/tests/hwsim/test_rrm.py b/tests/hwsim/test_rrm.py
index 84318f6cb64f..9111a357eaca 100644
--- a/tests/hwsim/test_rrm.py
+++ b/tests/hwsim/test_rrm.py
@@ -212,6 +212,20 @@ def test_rrm_neighbor_db(dev, apdev):
if apdev[0]['bssid'] not in res:
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):
"""hostapd ctrl_iface SHOW_NEIGHBOR while neighbor report disabled"""
params = {"ssid": "test"}
diff --git a/tests/hwsim/test_wnm.py b/tests/hwsim/test_wnm.py
index 10b07559b9ce..354822327210 100644
--- a/tests/hwsim/test_wnm.py
+++ b/tests/hwsim/test_wnm.py
@@ -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,
ocv=False, ap_max_inactivity=0, coloc_intf_reporting=False,
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 not ssid:
ssid = "test-wnm-rsn"
@@ -47,6 +48,8 @@ def start_wnm_ap(apdev, bss_transition=True, time_adv=False, ssid=None,
if pmf:
params["wpa_key_mgmt"] = "WPA-PSK-SHA256"
params["ieee80211w"] = "2"
+ if beacon_prot:
+ params["beacon_prot"] = "1"
else:
params = {"ssid": "test-wnm"}
if bss_transition:
@@ -195,7 +198,8 @@ def test_wnm_ess_disassoc_imminent_pmf(dev, apdev):
if ev is None:
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()
sta = hapd.get_sta(addr)
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:
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")
ok = False
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:
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
def test_wnm_sleep_mode_open(dev, apdev):
"""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")
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
def test_wnm_sleep_mode_rsn_ocv(dev, apdev):
"""WNM Sleep Mode - RSN with OCV"""
diff --git a/tests/hwsim/test_wpas_ctrl.py b/tests/hwsim/test_wpas_ctrl.py
index a99e2f49af83..210c11907ee7 100644
--- a/tests/hwsim/test_wpas_ctrl.py
+++ b/tests/hwsim/test_wpas_ctrl.py
@@ -1402,6 +1402,8 @@ def test_wpas_ctrl_driver_event(dev, apdev):
"""wpa_supplicant ctrl_iface DRIVER_EVENT"""
if "FAIL" not in dev[0].request("DRIVER_EVENT foo"):
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
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", "")
res = dev[0].request("GET_PREF_FREQ_LIST STATION").strip()
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()
diff --git a/tests/hwsim/vm/inside.sh b/tests/hwsim/vm/inside.sh
index 6ccad4bec487..9d4a933fe729 100755
--- a/tests/hwsim/vm/inside.sh
+++ b/tests/hwsim/vm/inside.sh
@@ -15,11 +15,16 @@ mount sysfs -t sysfs /sys
# needed for tracing
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
mkdir /dev/pts
mount devpts -t devpts /dev/pts
export PATH=/usr/sbin:$PATH
+export HOME=/tmp
# reboot on any sort of crash
sysctl kernel.panic_on_oops=1
diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c
index b54d7d4968d8..bf83e41686a0 100644
--- a/wpa_supplicant/ctrl_iface.c
+++ b/wpa_supplicant/ctrl_iface.c
@@ -512,6 +512,19 @@ static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s,
} else if (os_strcasecmp(cmd, "EAPOL::maxStart") == 0) {
eapol_sm_configure(wpa_s->eapol,
-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) {
if (wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
atoi(value))) {
@@ -2999,19 +3012,17 @@ static int wpa_supplicant_ctrl_iface_scan_result(
ie2, 2 + ie2[1]);
}
rsnxe = wpa_bss_get_ie(bss, WLAN_EID_RSNX);
- if (rsnxe && rsnxe[1] >= 1) {
- if (rsnxe[2] & BIT(WLAN_RSNX_CAPAB_SAE_H2E)) {
- ret = os_snprintf(pos, end - pos, "[SAE-H2E]");
- if (os_snprintf_error(end - pos, ret))
- return -1;
- pos += ret;
- }
- if (rsnxe[2] & BIT(WLAN_RSNX_CAPAB_SAE_PK)) {
- ret = os_snprintf(pos, end - pos, "[SAE-PK]");
- if (os_snprintf_error(end - pos, ret))
- return -1;
- pos += ret;
- }
+ if (ieee802_11_rsnx_capab(rsnxe, WLAN_RSNX_CAPAB_SAE_H2E)) {
+ ret = os_snprintf(pos, end - pos, "[SAE-H2E]");
+ if (os_snprintf_error(end - pos, ret))
+ return -1;
+ pos += ret;
+ }
+ if (ieee802_11_rsnx_capab(rsnxe, WLAN_RSNX_CAPAB_SAE_PK)) {
+ ret = os_snprintf(pos, end - pos, "[SAE-PK]");
+ if (os_snprintf_error(end - pos, ret))
+ return -1;
+ pos += ret;
}
osen_ie = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE);
if (osen_ie)
@@ -5099,19 +5110,17 @@ static int print_bss_info(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
mesh ? "RSN" : "WPA2", ie2,
2 + ie2[1]);
rsnxe = wpa_bss_get_ie(bss, WLAN_EID_RSNX);
- if (rsnxe && rsnxe[1] >= 1) {
- if (rsnxe[2] & BIT(WLAN_RSNX_CAPAB_SAE_H2E)) {
- ret = os_snprintf(pos, end - pos, "[SAE-H2E]");
- if (os_snprintf_error(end - pos, ret))
- return -1;
- pos += ret;
- }
- if (rsnxe[2] & BIT(WLAN_RSNX_CAPAB_SAE_PK)) {
- ret = os_snprintf(pos, end - pos, "[SAE-PK]");
- if (os_snprintf_error(end - pos, ret))
- return -1;
- pos += ret;
- }
+ if (ieee802_11_rsnx_capab(rsnxe, WLAN_RSNX_CAPAB_SAE_H2E)) {
+ ret = os_snprintf(pos, end - pos, "[SAE-H2E]");
+ if (os_snprintf_error(end - pos, ret))
+ return -1;
+ pos += ret;
+ }
+ if (ieee802_11_rsnx_capab(rsnxe, WLAN_RSNX_CAPAB_SAE_PK)) {
+ ret = os_snprintf(pos, end - pos, "[SAE-PK]");
+ if (os_snprintf_error(end - pos, ret))
+ return -1;
+ pos += ret;
}
osen_ie = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE);
if (osen_ie)
@@ -9300,6 +9309,132 @@ fail:
}
+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)
{
char *pos, *param;
@@ -9332,6 +9467,8 @@ static int wpas_ctrl_iface_driver_event(struct wpa_supplicant *wpa_s, char *cmd)
return 0;
} else if (os_strcmp(cmd, "SCAN_RES") == 0) {
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 {
wpa_dbg(wpa_s, MSG_DEBUG, "Testing - unknown driver event: %s",
cmd);
@@ -10598,15 +10735,18 @@ static int wpas_ctrl_iface_pasn_start(struct wpa_supplicant *wpa_s, char *cmd)
u8 bssid[ETH_ALEN];
int akmp = -1, cipher = -1, got_bssid = 0;
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>
+ * [comeback=<hexdump>]
*/
while ((token = str_token(cmd, " ", &context))) {
if (os_strncmp(token, "bssid=", 6) == 0) {
if (hwaddr_aton(token + 6, bssid))
- return -1;
+ goto out;
got_bssid = 1;
} else if (os_strcmp(token, "akmp=PASN") == 0) {
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);
} else if (os_strncmp(token, "nid=", 4) == 0) {
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 {
wpa_printf(MSG_DEBUG,
"CTRL: PASN Invalid parameter: '%s'",
token);
- return -1;
+ goto out;
}
}
if (!got_bssid || akmp == -1 || cipher == -1 || group == 0xFFFF) {
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;
}
diff --git a/wpa_supplicant/ctrl_iface.h b/wpa_supplicant/ctrl_iface.h
index 510668d49353..dfbd25a03b1b 100644
--- a/wpa_supplicant/ctrl_iface.h
+++ b/wpa_supplicant/ctrl_iface.h
@@ -70,14 +70,17 @@ wpa_supplicant_ctrl_iface_init(struct wpa_supplicant *wpa_s);
/**
* 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()
*
* 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.
*/
-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
@@ -128,7 +131,8 @@ wpa_supplicant_ctrl_iface_init(struct wpa_supplicant *wpa_s)
}
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)
{
}
diff --git a/wpa_supplicant/ctrl_iface_named_pipe.c b/wpa_supplicant/ctrl_iface_named_pipe.c
index 79ff7871db8d..bddc0414245e 100644
--- a/wpa_supplicant/ctrl_iface_named_pipe.c
+++ b/wpa_supplicant/ctrl_iface_named_pipe.c
@@ -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)
ctrl_close_pipe(priv->ctrl_dst);
if (priv->sec_attr_set)
diff --git a/wpa_supplicant/ctrl_iface_udp.c b/wpa_supplicant/ctrl_iface_udp.c
index 1512080d6b3b..1cbf7fa28d3f 100644
--- a/wpa_supplicant/ctrl_iface_udp.c
+++ b/wpa_supplicant/ctrl_iface_udp.c
@@ -490,8 +490,12 @@ fail:
}
-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) {
eloop_unregister_read_sock(priv->sock);
if (priv->ctrl_dst) {
diff --git a/wpa_supplicant/ctrl_iface_unix.c b/wpa_supplicant/ctrl_iface_unix.c
index 953fd2ccfe50..639573dae75e 100644
--- a/wpa_supplicant/ctrl_iface_unix.c
+++ b/wpa_supplicant/ctrl_iface_unix.c
@@ -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 ctrl_iface_msg *msg, *prev_msg;
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) {
char *fname;
char *buf, *dir = NULL;
@@ -877,6 +917,7 @@ free_dst:
}
}
}
+ wpas_global_ctrl_iface_flush_queued_msg(wpa_s->global, wpa_s);
eloop_cancel_timeout(wpas_ctrl_msg_queue_timeout, priv->wpa_s, NULL);
os_free(priv);
}
diff --git a/wpa_supplicant/eapol_test.c b/wpa_supplicant/eapol_test.c
index d137ad6ac5ab..e256ac50eec4 100644
--- a/wpa_supplicant/eapol_test.c
+++ b/wpa_supplicant/eapol_test.c
@@ -674,10 +674,8 @@ static void test_eapol_clean(struct eapol_test_data *e,
os_free(e->radius_conf);
e->radius_conf = NULL;
scard_deinit(wpa_s->scard);
- if (wpa_s->ctrl_iface) {
- wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface);
- wpa_s->ctrl_iface = NULL;
- }
+ wpa_supplicant_ctrl_iface_deinit(wpa_s, wpa_s->ctrl_iface);
+ wpa_s->ctrl_iface = NULL;
ext_password_deinit(wpa_s->ext_pw);
wpa_s->ext_pw = NULL;
diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c
index 5e73ab406d02..b3c07f926b69 100644
--- a/wpa_supplicant/events.c
+++ b/wpa_supplicant/events.c
@@ -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) {
int count;
const u8 *ie;
- u8 rsnxe_capa = 0;
if (bss == orig_bss)
continue;
ie = wpa_bss_get_ie(bss, WLAN_EID_RSNX);
- if (ie && ie[1] >= 1)
- rsnxe_capa = ie[2];
- if (!(rsnxe_capa & BIT(WLAN_RSNX_CAPAB_SAE_PK)))
+ if (!(ieee802_11_rsnx_capab(ie, WLAN_RSNX_CAPAB_SAE_PK)))
continue;
/* 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_s->last_eapol_matches_bssid = 1;
+
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,
data->assoc_info.ptk_kck_len,
diff --git a/wpa_supplicant/mesh_rsn.c b/wpa_supplicant/mesh_rsn.c
index 834c7a1ccc88..65daa77c2c98 100644
--- a/wpa_supplicant/mesh_rsn.c
+++ b/wpa_supplicant/mesh_rsn.c
@@ -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,
(u8 *) password, os_strlen(password),
- ssid->sae_password_id,
sta->sae);
}
diff --git a/wpa_supplicant/pasn_supplicant.c b/wpa_supplicant/pasn_supplicant.c
index e6adf73f3e42..baf4c2643e42 100644
--- a/wpa_supplicant/pasn_supplicant.c
+++ b/wpa_supplicant/pasn_supplicant.c
@@ -33,9 +33,18 @@ struct wpa_pasn_auth_work {
int cipher;
u16 group;
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)
{
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,
- 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,
PASN_AUTH_STATUS MACSTR " akmp=%s, status=%u",
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 wpabuf *buf = NULL;
- const char *password = NULL;
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);
if (ret) {
wpa_printf(MSG_DEBUG, "PASN: Failed to set SAE group");
return NULL;
}
- /* TODO: SAE H2E */
- ret = sae_prepare_commit(wpa_s->own_addr, pasn->bssid,
- (const u8 *) password, os_strlen(password), 0,
- &pasn->sae);
+ ret = sae_prepare_commit_pt(&pasn->sae, pasn->ssid->pt,
+ wpa_s->own_addr, pasn->bssid,
+ NULL, NULL);
if (ret) {
wpa_printf(MSG_DEBUG, "PASN: Failed to prepare SAE commit");
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, 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);
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",
alg, seq, status);
- /* TODO: SAE H2E */
- if (alg != WLAN_AUTH_SAE || seq != 1 || status != WLAN_STATUS_SUCCESS) {
+ if (alg != WLAN_AUTH_SAE || seq != 1 ||
+ status != WLAN_STATUS_SAE_HASH_TO_ELEMENT) {
wpa_printf(MSG_DEBUG, "PASN: SAE: dropping peer commit");
return -1;
}
res = sae_parse_commit(&pasn->sae, data + 6, len - 6, NULL, 0, groups,
- 0);
+ 1);
if (res != WLAN_STATUS_SUCCESS) {
wpa_printf(MSG_DEBUG, "PASN: SAE failed parsing commit");
return -1;
@@ -240,6 +258,31 @@ static struct wpabuf * wpas_pasn_wd_sae_confirm(struct wpa_supplicant *wpa_s)
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 */
@@ -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 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;
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)
goto fail;
/* Add own RNSXE */
- /* TODO: How to handle protected TWT and SAE H2E? */
capab = 0;
+ capab |= BIT(WLAN_RSNX_CAPAB_SAE_H2E);
if (wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_SEC_LTF)
capab |= BIT(WLAN_RSNX_CAPAB_SECURE_LTF);
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);
pasn->beacon_rsne_rsnxe = NULL;
+ wpabuf_free(pasn->comeback);
+ pasn->comeback = NULL;
+ pasn->comeback_after = 0;
+
#ifdef CONFIG_SAE
sae_clear_data(&pasn->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,
const u8 *beacon_rsne, u8 beacon_rsne_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 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");
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.send_confirm = 0;
pasn->ssid = ssid;
@@ -1016,6 +1078,15 @@ static int wpas_pasn_start(struct wpa_supplicant *wpa_s, const u8 *bssid,
pasn->cipher = cipher;
pasn->group = group;
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);
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,
pasn->group);
- frame = wpas_pasn_build_auth_1(wpa_s);
+ frame = wpas_pasn_build_auth_1(wpa_s, comeback);
if (!frame) {
wpa_printf(MSG_DEBUG, "PASN: Failed building 1st auth frame");
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->pasn_auth_work = NULL;
}
- os_free(awork);
+
+ wpas_pasn_free_auth_work(awork);
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,
awork->group, bss->freq, rsne, *(rsne + 1) + 2,
rsnxe, rsnxe ? *(rsnxe + 1) + 2 : 0,
- awork->network_id);
+ awork->network_id, awork->comeback);
if (ret) {
wpa_printf(MSG_DEBUG,
"PASN: Failed to start PASN authentication");
goto fail;
}
+ /* comeback token is no longer needed at this stage */
+ wpabuf_free(awork->comeback);
+ awork->comeback = NULL;
+
wpa_s->pasn_auth_work = work;
return;
fail:
- os_free(awork);
+ wpas_pasn_free_auth_work(awork);
work->ctx = NULL;
radio_work_done(work);
}
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_bss *bss;
@@ -1195,9 +1272,17 @@ int wpas_pasn_auth_start(struct wpa_supplicant *wpa_s, const u8 *bssid,
awork->group = group;
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,
wpas_pasn_auth_start_cb, awork) < 0) {
- os_free(awork);
+ wpas_pasn_free_auth_work(awork);
return -1;
}
@@ -1216,12 +1301,33 @@ void wpas_pasn_auth_stop(struct wpa_supplicant *wpa_s)
wpa_printf(MSG_DEBUG, "PASN: Stopping authentication");
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);
}
+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,
const struct ieee80211_mgmt *mgmt, size_t len)
{
@@ -1315,10 +1421,26 @@ int wpas_pasn_auth_rx(struct wpa_supplicant *wpa_s,
goto fail;
}
- /* TODO: handle comeback flow */
if (status == WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY) {
wpa_printf(MSG_DEBUG,
"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;
}
@@ -1393,7 +1515,7 @@ int wpas_pasn_auth_rx(struct wpa_supplicant *wpa_s,
wpa_s->own_addr, pasn->bssid,
wpabuf_head(secret), wpabuf_len(secret),
&pasn->ptk, pasn->akmp, pasn->cipher,
- WPA_KDK_MAX_LEN);
+ pasn->kdk_len);
if (ret) {
wpa_printf(MSG_DEBUG, "PASN: Failed to derive PTK");
goto fail;
@@ -1456,7 +1578,11 @@ fail:
* the frame and terminate the authentication exchange. However, better
* reply to the AP with an error status.
*/
- pasn->status = WLAN_STATUS_UNSPECIFIED_FAILURE;
+ if (status == WLAN_STATUS_SUCCESS)
+ pasn->status = WLAN_STATUS_UNSPECIFIED_FAILURE;
+ else
+ pasn->status = status;
+
wpas_pasn_auth_stop(wpa_s);
return -1;
}
diff --git a/wpa_supplicant/preauth_test.c b/wpa_supplicant/preauth_test.c
index de49948f71e4..97c16fb80d27 100644
--- a/wpa_supplicant/preauth_test.c
+++ b/wpa_supplicant/preauth_test.c
@@ -193,10 +193,8 @@ static void test_eapol_clean(struct wpa_supplicant *wpa_s)
pmksa_candidate_free(wpa_s->wpa);
wpa_sm_deinit(wpa_s->wpa);
scard_deinit(wpa_s->scard);
- if (wpa_s->ctrl_iface) {
- wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface);
- wpa_s->ctrl_iface = NULL;
- }
+ wpa_supplicant_ctrl_iface_deinit(wpa_s, wpa_s->ctrl_iface);
+ wpa_s->ctrl_iface = NULL;
wpa_config_free(wpa_s->conf);
}
diff --git a/wpa_supplicant/robust_av.c b/wpa_supplicant/robust_av.c
index f6da56eeda9b..39d282f0870d 100644
--- a/wpa_supplicant/robust_av.c
+++ b/wpa_supplicant/robust_av.c
@@ -118,7 +118,7 @@ void wpas_handle_robust_av_recv_action(struct wpa_supplicant *wpa_s,
return;
}
- status_code = *buf;
+ status_code = WPA_GET_LE16(buf);
wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_MSCS_RESULT "bssid=" MACSTR
" status_code=%u", MAC2STR(src), status_code);
wpa_s->mscs_setup_done = status_code == WLAN_STATUS_SUCCESS;
diff --git a/wpa_supplicant/sme.c b/wpa_supplicant/sme.c
index dde80863a988..72aa9b5b8f18 100644
--- a/wpa_supplicant/sme.c
+++ b/wpa_supplicant/sme.c
@@ -186,7 +186,6 @@ static struct wpabuf * sme_auth_build_sae_commit(struct wpa_supplicant *wpa_s,
if (!use_pt &&
sae_prepare_commit(wpa_s->own_addr, bssid,
(u8 *) password, os_strlen(password),
- ssid->sae_password_id,
&wpa_s->sme.sae) < 0) {
wpa_printf(MSG_DEBUG, "SAE: Could not pick PWE");
return NULL;
diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index 90e8a466aba2..835b33575760 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -1158,8 +1158,8 @@ int wpa_supplicant_reload_configuration(struct wpa_supplicant *wpa_s)
os_strcmp(conf->ctrl_interface,
wpa_s->conf->ctrl_interface) != 0);
- if (reconf_ctrl && wpa_s->ctrl_iface) {
- wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface);
+ if (reconf_ctrl) {
+ wpa_supplicant_ctrl_iface_deinit(wpa_s, wpa_s->ctrl_iface);
wpa_s->ctrl_iface = NULL;
}
@@ -6748,10 +6748,8 @@ static void wpa_supplicant_deinit_iface(struct wpa_supplicant *wpa_s,
if (terminate)
wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TERMINATING);
- if (wpa_s->ctrl_iface) {
- wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface);
- wpa_s->ctrl_iface = NULL;
- }
+ wpa_supplicant_ctrl_iface_deinit(wpa_s, wpa_s->ctrl_iface);
+ wpa_s->ctrl_iface = NULL;
#ifdef CONFIG_MESH
if (wpa_s->ifmsh) {
diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h
index 7ed8c0ee4d92..49007cfc2e8f 100644
--- a/wpa_supplicant/wpa_supplicant_i.h
+++ b/wpa_supplicant/wpa_supplicant_i.h
@@ -539,6 +539,7 @@ struct wpas_pasn {
int cipher;
u16 group;
int freq;
+ size_t kdk_len;
u8 trans_seq;
u8 status;
@@ -554,6 +555,9 @@ struct wpas_pasn {
struct wpa_ptk ptk;
struct crypto_ecdh *ecdh;
+ struct wpabuf *comeback;
+ u16 comeback_after;
+
#ifdef CONFIG_SAE
struct sae_data 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,
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);
int wpas_pasn_auth_tx_status(struct wpa_supplicant *wpa_s,
const u8 *data, size_t data_len, u8 acked);