wpa: Import wpa_supplicant/hostapd commit f91680c15

This is the April update to vendor/wpa committed upstream
2021/04/07.
This commit is contained in:
Cy Schubert 2021-04-12 16:39:23 -07:00
parent f8262d7d8a
commit efec822389
71 changed files with 2510 additions and 446 deletions

View File

@ -2332,6 +2332,22 @@ static int hostapd_dpp_controller_parse(struct hostapd_bss_config *bss,
#endif /* CONFIG_DPP2 */ #endif /* CONFIG_DPP2 */
static int get_hex_config(u8 *buf, size_t max_len, int line,
const char *field, const char *val)
{
size_t hlen = os_strlen(val), len = hlen / 2;
u8 tmp[EXT_CAPA_MAX_LEN];
os_memset(tmp, 0, EXT_CAPA_MAX_LEN);
if (hlen & 1 || len > EXT_CAPA_MAX_LEN || hexstr2bin(val, tmp, len)) {
wpa_printf(MSG_ERROR, "Line %d: Invalid %s", line, field);
return -1;
}
os_memcpy(buf, tmp, EXT_CAPA_MAX_LEN);
return 0;
}
static int hostapd_config_fill(struct hostapd_config *conf, static int hostapd_config_fill(struct hostapd_config *conf,
struct hostapd_bss_config *bss, struct hostapd_bss_config *bss,
const char *buf, char *pos, int line) const char *buf, char *pos, int line)
@ -2458,12 +2474,13 @@ static int hostapd_config_fill(struct hostapd_config *conf,
bss->ieee802_1x = atoi(pos); bss->ieee802_1x = atoi(pos);
} else if (os_strcmp(buf, "eapol_version") == 0) { } else if (os_strcmp(buf, "eapol_version") == 0) {
int eapol_version = atoi(pos); int eapol_version = atoi(pos);
#ifdef CONFIG_MACSEC #ifdef CONFIG_MACSEC
if (eapol_version < 1 || eapol_version > 3) { int max_ver = 3;
#else /* CONFIG_MACSEC */ #else /* CONFIG_MACSEC */
if (eapol_version < 1 || eapol_version > 2) { int max_ver = 2;
#endif /* CONFIG_MACSEC */ #endif /* CONFIG_MACSEC */
if (eapol_version < 1 || eapol_version > max_ver) {
wpa_printf(MSG_ERROR, wpa_printf(MSG_ERROR,
"Line %d: invalid EAPOL version (%d): '%s'.", "Line %d: invalid EAPOL version (%d): '%s'.",
line, eapol_version, pos); line, eapol_version, pos);
@ -4675,7 +4692,17 @@ static int hostapd_config_fill(struct hostapd_config *conf,
line, pos); line, pos);
return 1; return 1;
} }
} else if (os_strcmp(buf, "pasn_comeback_after") == 0) {
bss->pasn_comeback_after = atoi(pos);
#endif /* CONFIG_PASN */ #endif /* CONFIG_PASN */
} else if (os_strcmp(buf, "ext_capa_mask") == 0) {
if (get_hex_config(bss->ext_capa_mask, EXT_CAPA_MAX_LEN,
line, "ext_capa_mask", pos))
return 1;
} else if (os_strcmp(buf, "ext_capa") == 0) {
if (get_hex_config(bss->ext_capa, EXT_CAPA_MAX_LEN,
line, "ext_capa", pos))
return 1;
} else { } else {
wpa_printf(MSG_ERROR, wpa_printf(MSG_ERROR,
"Line %d: unknown configuration item '%s'", "Line %d: unknown configuration item '%s'",

View File

@ -1469,6 +1469,8 @@ static int hostapd_ctrl_iface_set(struct hostapd_data *hapd, char *cmd)
hapd->ext_mgmt_frame_handling = atoi(value); hapd->ext_mgmt_frame_handling = atoi(value);
} else if (os_strcasecmp(cmd, "ext_eapol_frame_io") == 0) { } else if (os_strcasecmp(cmd, "ext_eapol_frame_io") == 0) {
hapd->ext_eapol_frame_io = atoi(value); hapd->ext_eapol_frame_io = atoi(value);
} else if (os_strcasecmp(cmd, "force_backlog_bytes") == 0) {
hapd->force_backlog_bytes = atoi(value);
#ifdef CONFIG_DPP #ifdef CONFIG_DPP
} else if (os_strcasecmp(cmd, "dpp_config_obj_override") == 0) { } else if (os_strcasecmp(cmd, "dpp_config_obj_override") == 0) {
os_free(hapd->dpp_config_obj_override); os_free(hapd->dpp_config_obj_override);
@ -2562,6 +2564,34 @@ static int hostapd_ctrl_get_pmk(struct hostapd_data *hapd, const char *cmd,
return wpa_snprintf_hex(buf, buflen, pmk, pmk_len); return wpa_snprintf_hex(buf, buflen, pmk, pmk_len);
} }
static int hostapd_ctrl_register_frame(struct hostapd_data *hapd,
const char *cmd)
{
u16 type;
char *pos, *end;
u8 match[10];
size_t match_len;
bool multicast = false;
type = strtol(cmd, &pos, 16);
if (*pos != ' ')
return -1;
pos++;
end = os_strchr(pos, ' ');
if (end) {
match_len = end - pos;
multicast = os_strstr(end, "multicast") != NULL;
} else {
match_len = os_strlen(pos) / 2;
}
if (hexstr2bin(pos, match, match_len))
return -1;
return hostapd_drv_register_frame(hapd, type, match, match_len,
multicast);
}
#endif /* CONFIG_TESTING_OPTIONS */ #endif /* CONFIG_TESTING_OPTIONS */
@ -3646,6 +3676,9 @@ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
} else if (os_strncmp(buf, "GET_PMK ", 8) == 0) { } else if (os_strncmp(buf, "GET_PMK ", 8) == 0) {
reply_len = hostapd_ctrl_get_pmk(hapd, buf + 8, reply, reply_len = hostapd_ctrl_get_pmk(hapd, buf + 8, reply,
reply_size); reply_size);
} else if (os_strncmp(buf, "REGISTER_FRAME ", 15) == 0) {
if (hostapd_ctrl_register_frame(hapd, buf + 16) < 0)
reply_len = -1;
#endif /* CONFIG_TESTING_OPTIONS */ #endif /* CONFIG_TESTING_OPTIONS */
} else if (os_strncmp(buf, "CHAN_SWITCH ", 12) == 0) { } else if (os_strncmp(buf, "CHAN_SWITCH ", 12) == 0) {
if (hostapd_ctrl_iface_chan_switch(hapd->iface, buf + 12)) if (hostapd_ctrl_iface_chan_switch(hapd->iface, buf + 12))

View File

@ -877,18 +877,31 @@ wmm_ac_vo_acm=0
#he_mu_edca_ac_vo_timer=255 #he_mu_edca_ac_vo_timer=255
# Spatial Reuse Parameter Set # Spatial Reuse Parameter Set
#
# SR Control field value
# B0 = PSR Disallowed
# B1 = Non-SRG OBSS PD SR Disallowed
# B2 = Non-SRG Offset Present
# B3 = SRG Information Present
# B4 = HESIGA_Spatial_reuse_value15_allowed
#he_spr_sr_control #he_spr_sr_control
#
# Non-SRG OBSS PD Max Offset (included if he_spr_sr_control B2=1)
#he_spr_non_srg_obss_pd_max_offset #he_spr_non_srg_obss_pd_max_offset
# SRG OBSS PD Min Offset (included if he_spr_sr_control B3=1)
#he_spr_srg_obss_pd_min_offset #he_spr_srg_obss_pd_min_offset
#
# SRG OBSS PD Max Offset (included if he_spr_sr_control B3=1)
#he_spr_srg_obss_pd_max_offset #he_spr_srg_obss_pd_max_offset
# #
# SPR SRG BSS Color # SPR SRG BSS Color (included if he_spr_sr_control B3=1)
# This config represents SRG BSS Color Bitmap field of Spatial Reuse Parameter # This config represents SRG BSS Color Bitmap field of Spatial Reuse Parameter
# Set element that indicates the BSS color values used by members of the # Set element that indicates the BSS color values used by members of the
# SRG of which the transmitting STA is a member. The value is in range of 0-63. # SRG of which the transmitting STA is a member. The value is in range of 0-63.
#he_spr_srg_bss_colors=1 2 10 63 #he_spr_srg_bss_colors=1 2 10 63
# #
# SPR SRG Partial BSSID # SPR SRG Partial BSSID (included if he_spr_sr_control B3=1)
# This config represents SRG Partial BSSID Bitmap field of Spatial Reuse # This config represents SRG Partial BSSID Bitmap field of Spatial Reuse
# Parameter Set element that indicates the Partial BSSID values used by members # Parameter Set element that indicates the Partial BSSID values used by members
# of the SRG of which the transmitting STA is a member. The value range # of the SRG of which the transmitting STA is a member. The value range
@ -2038,6 +2051,13 @@ own_ip_addr=127.0.0.1
# http://www.iana.org/assignments/ipsec-registry/ipsec-registry.xml#ipsec-registry-10 # http://www.iana.org/assignments/ipsec-registry/ipsec-registry.xml#ipsec-registry-10
#pasn_groups=19 20 21 #pasn_groups=19 20 21
# PASN comeback after time in TUs
# In case the AP is temporarily unable to handle a PASN authentication exchange
# due to a too large number of parallel operations, this value indicates to the
# peer after how many TUs it can try the PASN exchange again.
# (default: 10 TUs)
#pasn_comeback_after=10
##### IEEE 802.11r configuration ############################################## ##### IEEE 802.11r configuration ##############################################
# Mobility Domain identifier (dot11FTMobilityDomainID, MDID) # Mobility Domain identifier (dot11FTMobilityDomainID, MDID)

View File

@ -79,6 +79,10 @@ static void count_backlogged_sta(struct hostapd_data *hapd)
for (sta = hapd->sta_list; sta; sta = sta->next) { for (sta = hapd->sta_list; sta; sta = sta->next) {
if (hostapd_drv_read_sta_data(hapd, &data, sta->addr)) if (hostapd_drv_read_sta_data(hapd, &data, sta->addr))
continue; continue;
#ifdef CONFIG_TESTING_OPTIONS
if (hapd->force_backlog_bytes)
data.backlog_bytes = 1;
#endif /* CONFIG_TESTING_OPTIONS */
if (data.backlog_bytes > 0) if (data.backlog_bytes > 0)
set_new_backlog_time(hapd, sta, &now); set_new_backlog_time(hapd, sta, &now);

View File

@ -165,6 +165,11 @@ void hostapd_config_defaults_bss(struct hostapd_bss_config *bss)
#ifdef CONFIG_TESTING_OPTIONS #ifdef CONFIG_TESTING_OPTIONS
bss->sae_commit_status = -1; bss->sae_commit_status = -1;
#endif /* CONFIG_TESTING_OPTIONS */ #endif /* CONFIG_TESTING_OPTIONS */
#ifdef CONFIG_PASN
/* comeback after 10 TUs */
bss->pasn_comeback_after = 10;
#endif /* CONFIG_PASN */
} }

View File

@ -267,6 +267,8 @@ struct airtime_sta_weight {
u8 addr[ETH_ALEN]; u8 addr[ETH_ALEN];
}; };
#define EXT_CAPA_MAX_LEN 15
/** /**
* struct hostapd_bss_config - Per-BSS configuration * struct hostapd_bss_config - Per-BSS configuration
*/ */
@ -880,9 +882,18 @@ struct hostapd_bss_config {
#endif /* CONFIG_TESTING_OPTIONS */ #endif /* CONFIG_TESTING_OPTIONS */
int *pasn_groups; int *pasn_groups;
/*
* The time in TUs after which the non-AP STA is requested to retry the
* PASN authentication in case there are too many parallel operations.
*/
u16 pasn_comeback_after;
#endif /* CONFIG_PASN */ #endif /* CONFIG_PASN */
unsigned int unsol_bcast_probe_resp_interval; unsigned int unsol_bcast_probe_resp_interval;
u8 ext_capa_mask[EXT_CAPA_MAX_LEN];
u8 ext_capa[EXT_CAPA_MAX_LEN];
}; };
/** /**

View File

@ -403,4 +403,17 @@ static inline int hostapd_drv_driver_cmd(struct hostapd_data *hapd,
} }
#endif /* ANDROID */ #endif /* ANDROID */
#ifdef CONFIG_TESTING_OPTIONS
static inline int
hostapd_drv_register_frame(struct hostapd_data *hapd, u16 type,
const u8 *match, size_t match_len,
bool multicast)
{
if (!hapd->driver || !hapd->drv_priv || !hapd->driver->register_frame)
return -1;
return hapd->driver->register_frame(hapd->drv_priv, type, match,
match_len, multicast);
}
#endif /* CONFIG_TESTING_OPTIONS */
#endif /* AP_DRV_OPS */ #endif /* AP_DRV_OPS */

View File

@ -915,7 +915,8 @@ static void hostapd_dpp_gas_resp_cb(void *ctx, const u8 *addr, u8 dialog_token,
wpa_printf(MSG_DEBUG, "DPP: No matching exchange in progress"); wpa_printf(MSG_DEBUG, "DPP: No matching exchange in progress");
return; return;
} }
if (!resp || status_code != WLAN_STATUS_SUCCESS) { if (result != GAS_QUERY_AP_SUCCESS ||
!resp || status_code != WLAN_STATUS_SUCCESS) {
wpa_printf(MSG_DEBUG, "DPP: GAS query did not succeed"); wpa_printf(MSG_DEBUG, "DPP: GAS query did not succeed");
goto fail; goto fail;
} }
@ -1189,6 +1190,7 @@ static void hostapd_dpp_rx_conf_result(struct hostapd_data *hapd, const u8 *src,
wpa_printf(MSG_DEBUG, "DPP: Wait for Connection Status Result"); wpa_printf(MSG_DEBUG, "DPP: Wait for Connection Status Result");
eloop_cancel_timeout(hostapd_dpp_config_result_wait_timeout, eloop_cancel_timeout(hostapd_dpp_config_result_wait_timeout,
hapd, NULL); hapd, NULL);
auth->waiting_conn_status_result = 1;
eloop_cancel_timeout( eloop_cancel_timeout(
hostapd_dpp_conn_status_result_wait_timeout, hostapd_dpp_conn_status_result_wait_timeout,
hapd, NULL); hapd, NULL);
@ -1981,6 +1983,19 @@ hostapd_dpp_gas_req_handler(struct hostapd_data *hapd, const u8 *sa,
wpa_printf(MSG_DEBUG, "DPP: No matching exchange in progress"); wpa_printf(MSG_DEBUG, "DPP: No matching exchange in progress");
return NULL; return NULL;
} }
if (hapd->dpp_auth_ok_on_ack && auth->configurator) {
wpa_printf(MSG_DEBUG,
"DPP: Have not received ACK for Auth Confirm yet - assume it was received based on this GAS request");
/* hostapd_dpp_auth_success() would normally have been called
* from TX status handler, but since there was no such handler
* call yet, simply send out the event message and proceed with
* exchange. */
wpa_msg(hapd->msg_ctx, MSG_INFO,
DPP_EVENT_AUTH_SUCCESS "init=1");
hapd->dpp_auth_ok_on_ack = 0;
}
wpa_hexdump(MSG_DEBUG, wpa_hexdump(MSG_DEBUG,
"DPP: Received Configuration Request (GAS Query Request)", "DPP: Received Configuration Request (GAS Query Request)",
query, query_len); query, query_len);

View File

@ -459,8 +459,8 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
if (hapd->conf->sae_pwe == 2 && if (hapd->conf->sae_pwe == 2 &&
sta->auth_alg == WLAN_AUTH_SAE && sta->auth_alg == WLAN_AUTH_SAE &&
sta->sae && !sta->sae->h2e && sta->sae && !sta->sae->h2e &&
elems.rsnxe && elems.rsnxe_len >= 1 && ieee802_11_rsnx_capab_len(elems.rsnxe, elems.rsnxe_len,
(elems.rsnxe[0] & BIT(WLAN_RSNX_CAPAB_SAE_H2E))) { WLAN_RSNX_CAPAB_SAE_H2E)) {
wpa_printf(MSG_INFO, "SAE: " MACSTR wpa_printf(MSG_INFO, "SAE: " MACSTR
" indicates support for SAE H2E, but did not use it", " indicates support for SAE H2E, but did not use it",
MAC2STR(sta->addr)); MAC2STR(sta->addr));

View File

@ -107,7 +107,8 @@ static void hostapd_reload_bss(struct hostapd_data *hapd)
return; return;
if (hapd->conf->wmm_enabled < 0) if (hapd->conf->wmm_enabled < 0)
hapd->conf->wmm_enabled = hapd->iconf->ieee80211n; hapd->conf->wmm_enabled = hapd->iconf->ieee80211n |
hapd->iconf->ieee80211ax;
#ifndef CONFIG_NO_RADIUS #ifndef CONFIG_NO_RADIUS
radius_client_reconfig(hapd->radius, hapd->conf->radius); radius_client_reconfig(hapd->radius, hapd->conf->radius);
@ -1173,7 +1174,8 @@ static int hostapd_setup_bss(struct hostapd_data *hapd, int first)
} }
if (conf->wmm_enabled < 0) if (conf->wmm_enabled < 0)
conf->wmm_enabled = hapd->iconf->ieee80211n; conf->wmm_enabled = hapd->iconf->ieee80211n |
hapd->iconf->ieee80211ax;
#ifdef CONFIG_IEEE80211R_AP #ifdef CONFIG_IEEE80211R_AP
if (is_zero_ether_addr(conf->r1_key_holder)) if (is_zero_ether_addr(conf->r1_key_holder))

View File

@ -354,6 +354,8 @@ struct hostapd_data {
int last_bigtk_key_idx; int last_bigtk_key_idx;
u8 last_bigtk[WPA_BIGTK_MAX_LEN]; u8 last_bigtk[WPA_BIGTK_MAX_LEN];
size_t last_bigtk_len; size_t last_bigtk_len;
bool force_backlog_bytes;
#endif /* CONFIG_TESTING_OPTIONS */ #endif /* CONFIG_TESTING_OPTIONS */
#ifdef CONFIG_MBO #ifdef CONFIG_MBO

View File

@ -572,7 +572,7 @@ static struct wpabuf * auth_build_sae_commit(struct hostapd_data *hapd,
if (update && !use_pt && if (update && !use_pt &&
sae_prepare_commit(hapd->own_addr, sta->addr, sae_prepare_commit(hapd->own_addr, sta->addr,
(u8 *) password, os_strlen(password), rx_id, (u8 *) password, os_strlen(password),
sta->sae) < 0) { sta->sae) < 0) {
wpa_printf(MSG_DEBUG, "SAE: Could not pick PWE"); wpa_printf(MSG_DEBUG, "SAE: Could not pick PWE");
return NULL; return NULL;
@ -702,13 +702,15 @@ static int use_anti_clogging(struct hostapd_data *hapd)
for (sta = hapd->sta_list; sta; sta = sta->next) { for (sta = hapd->sta_list; sta; sta = sta->next) {
#ifdef CONFIG_SAE #ifdef CONFIG_SAE
if (!sta->sae) if (sta->sae &&
continue; (sta->sae->state == SAE_COMMITTED ||
if (sta->sae->state != SAE_COMMITTED && sta->sae->state == SAE_CONFIRMED))
sta->sae->state != SAE_CONFIRMED)
continue;
open++; open++;
#endif /* CONFIG_SAE */ #endif /* CONFIG_SAE */
#ifdef CONFIG_PASN
if (sta->pasn && sta->pasn->ecdh)
open++;
#endif /* CONFIG_PASN */
if (open >= hapd->conf->anti_clogging_threshold) if (open >= hapd->conf->anti_clogging_threshold)
return 1; return 1;
} }
@ -806,6 +808,7 @@ static struct wpabuf * auth_build_token_req(struct hostapd_data *hapd,
if (buf == NULL) if (buf == NULL)
return NULL; return NULL;
if (group)
wpabuf_put_le16(buf, group); /* Finite Cyclic Group */ wpabuf_put_le16(buf, group); /* Finite Cyclic Group */
if (h2e) { if (h2e) {
@ -2380,11 +2383,12 @@ static int pasn_wd_handle_sae_commit(struct hostapd_data *hapd,
struct wpabuf *wd) struct wpabuf *wd)
{ {
struct pasn_data *pasn = sta->pasn; struct pasn_data *pasn = sta->pasn;
const char *password = NULL; const char *password;
const u8 *data; const u8 *data;
size_t buf_len; size_t buf_len;
u16 res, alg, seq, status; u16 res, alg, seq, status;
int groups[] = { pasn->group, 0 }; int groups[] = { pasn->group, 0 };
struct sae_pt *pt = NULL;
int ret; int ret;
if (!wd) if (!wd)
@ -2406,8 +2410,8 @@ static int pasn_wd_handle_sae_commit(struct hostapd_data *hapd,
wpa_printf(MSG_DEBUG, "PASN: SAE commit: alg=%u, seq=%u, status=%u", wpa_printf(MSG_DEBUG, "PASN: SAE commit: alg=%u, seq=%u, status=%u",
alg, seq, status); alg, seq, status);
/* TODO: SAE H2E */ if (alg != WLAN_AUTH_SAE || seq != 1 ||
if (alg != WLAN_AUTH_SAE || seq != 1 || status != WLAN_STATUS_SUCCESS) { status != WLAN_STATUS_SAE_HASH_TO_ELEMENT) {
wpa_printf(MSG_DEBUG, "PASN: Dropping peer SAE commit"); wpa_printf(MSG_DEBUG, "PASN: Dropping peer SAE commit");
return -1; return -1;
} }
@ -2421,15 +2425,14 @@ static int pasn_wd_handle_sae_commit(struct hostapd_data *hapd,
return -1; return -1;
} }
password = sae_get_password(hapd, sta, NULL, NULL, NULL, NULL); password = sae_get_password(hapd, sta, NULL, NULL, &pt, NULL);
if (!password) { if (!password || !pt) {
wpa_printf(MSG_DEBUG, "PASN: No SAE password found"); wpa_printf(MSG_DEBUG, "PASN: No SAE PT found");
return -1; return -1;
} }
ret = sae_prepare_commit(hapd->own_addr, sta->addr, ret = sae_prepare_commit_pt(&pasn->sae, pt, hapd->own_addr, sta->addr,
(const u8 *) password, os_strlen(password), 0, NULL, NULL);
&pasn->sae);
if (ret) { if (ret) {
wpa_printf(MSG_DEBUG, "PASN: Failed to prepare SAE commit"); wpa_printf(MSG_DEBUG, "PASN: Failed to prepare SAE commit");
return -1; return -1;
@ -2526,7 +2529,7 @@ static struct wpabuf * pasn_get_sae_wd(struct hostapd_data *hapd,
len_ptr = wpabuf_put(buf, 2); len_ptr = wpabuf_put(buf, 2);
wpabuf_put_le16(buf, WLAN_AUTH_SAE); wpabuf_put_le16(buf, WLAN_AUTH_SAE);
wpabuf_put_le16(buf, 1); wpabuf_put_le16(buf, 1);
wpabuf_put_le16(buf, WLAN_STATUS_SUCCESS); wpabuf_put_le16(buf, WLAN_STATUS_SAE_HASH_TO_ELEMENT);
/* Write the actual commit and update the length accordingly */ /* Write the actual commit and update the length accordingly */
sae_write_commit(&pasn->sae, buf, NULL, 0); sae_write_commit(&pasn->sae, buf, NULL, 0);
@ -2643,7 +2646,7 @@ static void pasn_fils_auth_resp(struct hostapd_data *hapd,
wpabuf_head(pasn->secret), wpabuf_head(pasn->secret),
wpabuf_len(pasn->secret), wpabuf_len(pasn->secret),
&sta->pasn->ptk, sta->pasn->akmp, &sta->pasn->ptk, sta->pasn->akmp,
sta->pasn->cipher, WPA_KDK_MAX_LEN); sta->pasn->cipher, sta->pasn->kdk_len);
if (ret) { if (ret) {
wpa_printf(MSG_DEBUG, "PASN: FILS: Failed to derive PTK"); wpa_printf(MSG_DEBUG, "PASN: FILS: Failed to derive PTK");
goto fail; goto fail;
@ -2880,7 +2883,7 @@ pasn_derive_keys(struct hostapd_data *hapd, struct sta_info *sta,
ret = pasn_pmk_to_ptk(pmk, pmk_len, sta->addr, hapd->own_addr, ret = pasn_pmk_to_ptk(pmk, pmk_len, sta->addr, hapd->own_addr,
wpabuf_head(secret), wpabuf_len(secret), wpabuf_head(secret), wpabuf_len(secret),
&sta->pasn->ptk, sta->pasn->akmp, &sta->pasn->ptk, sta->pasn->akmp,
sta->pasn->cipher, WPA_KDK_MAX_LEN); sta->pasn->cipher, sta->pasn->kdk_len);
if (ret) { if (ret) {
wpa_printf(MSG_DEBUG, "PASN: Failed to derive PTK"); wpa_printf(MSG_DEBUG, "PASN: Failed to derive PTK");
return -1; return -1;
@ -2891,6 +2894,54 @@ pasn_derive_keys(struct hostapd_data *hapd, struct sta_info *sta,
} }
static void handle_auth_pasn_comeback(struct hostapd_data *hapd,
struct sta_info *sta, u16 group)
{
struct wpabuf *buf, *comeback;
int ret;
wpa_printf(MSG_DEBUG,
"PASN: Building comeback frame 2. Comeback after=%u",
hapd->conf->pasn_comeback_after);
buf = wpabuf_alloc(1500);
if (!buf)
return;
wpa_pasn_build_auth_header(buf, hapd->own_addr, hapd->own_addr,
sta->addr, 2,
WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY);
/*
* Do not include the group as a part of the token since it is not going
* to be used.
*/
comeback = auth_build_token_req(hapd, 0, sta->addr, 0);
if (!comeback) {
wpa_printf(MSG_DEBUG,
"PASN: Failed sending auth with comeback");
wpabuf_free(buf);
return;
}
wpa_pasn_add_parameter_ie(buf, group,
WPA_PASN_WRAPPED_DATA_NO,
NULL, 0, comeback,
hapd->conf->pasn_comeback_after);
wpabuf_free(comeback);
wpa_printf(MSG_DEBUG,
"PASN: comeback: STA=" MACSTR, MAC2STR(sta->addr));
ret = hostapd_drv_send_mlme(hapd, wpabuf_head(buf), wpabuf_len(buf), 0,
NULL, 0, 0);
if (ret)
wpa_printf(MSG_INFO, "PASN: Failed to send comeback frame 2");
wpabuf_free(buf);
}
static int handle_auth_pasn_resp(struct hostapd_data *hapd, static int handle_auth_pasn_resp(struct hostapd_data *hapd,
struct sta_info *sta, struct sta_info *sta,
struct rsn_pmksa_cache_entry *pmksa, struct rsn_pmksa_cache_entry *pmksa,
@ -3100,6 +3151,15 @@ static void handle_auth_pasn_1(struct hostapd_data *hapd, struct sta_info *sta,
sta->pasn->akmp = rsn_data.key_mgmt; sta->pasn->akmp = rsn_data.key_mgmt;
sta->pasn->cipher = rsn_data.pairwise_cipher; sta->pasn->cipher = rsn_data.pairwise_cipher;
if (hapd->conf->force_kdk_derivation ||
((hapd->iface->drv_flags2 & WPA_DRIVER_FLAGS2_SEC_LTF) &&
ieee802_11_rsnx_capab_len(elems.rsnxe, elems.rsnxe_len,
WLAN_RSNX_CAPAB_SECURE_LTF)))
sta->pasn->kdk_len = WPA_KDK_MAX_LEN;
else
sta->pasn->kdk_len = 0;
wpa_printf(MSG_DEBUG, "PASN: kdk_len=%zu", sta->pasn->kdk_len);
if (!elems.pasn_params || !elems.pasn_params_len) { if (!elems.pasn_params || !elems.pasn_params_len) {
wpa_printf(MSG_DEBUG, wpa_printf(MSG_DEBUG,
"PASN: No PASN Parameters element found"); "PASN: No PASN Parameters element found");
@ -3133,6 +3193,25 @@ static void handle_auth_pasn_1(struct hostapd_data *hapd, struct sta_info *sta,
goto send_resp; goto send_resp;
} }
if (pasn_params.comeback) {
wpa_printf(MSG_DEBUG, "PASN: Checking peer comeback token");
ret = check_comeback_token(hapd, sta->addr,
pasn_params.comeback,
pasn_params.comeback_len);
if (ret) {
wpa_printf(MSG_DEBUG, "PASN: Invalid comeback token");
status = WLAN_STATUS_UNSPECIFIED_FAILURE;
goto send_resp;
}
} else if (use_anti_clogging(hapd)) {
wpa_printf(MSG_DEBUG, "PASN: Respond with comeback");
handle_auth_pasn_comeback(hapd, sta, pasn_params.group);
ap_free_sta(hapd, sta);
return;
}
sta->pasn->ecdh = crypto_ecdh_init(pasn_params.group); sta->pasn->ecdh = crypto_ecdh_init(pasn_params.group);
if (!sta->pasn->ecdh) { if (!sta->pasn->ecdh) {
wpa_printf(MSG_DEBUG, "PASN: Failed to init ECDH"); wpa_printf(MSG_DEBUG, "PASN: Failed to init ECDH");
@ -4614,8 +4693,8 @@ static int check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta,
if (hapd->conf->sae_pwe == 2 && if (hapd->conf->sae_pwe == 2 &&
sta->auth_alg == WLAN_AUTH_SAE && sta->auth_alg == WLAN_AUTH_SAE &&
sta->sae && !sta->sae->h2e && sta->sae && !sta->sae->h2e &&
elems.rsnxe && elems.rsnxe_len >= 1 && ieee802_11_rsnx_capab_len(elems.rsnxe, elems.rsnxe_len,
(elems.rsnxe[0] & BIT(WLAN_RSNX_CAPAB_SAE_H2E))) { WLAN_RSNX_CAPAB_SAE_H2E)) {
wpa_printf(MSG_INFO, "SAE: " MACSTR wpa_printf(MSG_INFO, "SAE: " MACSTR
" indicates support for SAE H2E, but did not use it", " indicates support for SAE H2E, but did not use it",
MAC2STR(sta->addr)); MAC2STR(sta->addr));

View File

@ -451,70 +451,10 @@ static void hostapd_ext_capab_byte(struct hostapd_data *hapd, u8 *pos, int idx)
u8 * hostapd_eid_ext_capab(struct hostapd_data *hapd, u8 *eid) u8 * hostapd_eid_ext_capab(struct hostapd_data *hapd, u8 *eid)
{ {
u8 *pos = eid; u8 *pos = eid;
u8 len = 0, i; u8 len = EXT_CAPA_MAX_LEN, i;
if (hapd->conf->qos_map_set_len ||
(hapd->conf->tdls & (TDLS_PROHIBIT | TDLS_PROHIBIT_CHAN_SWITCH)))
len = 5;
if (len < 4 &&
(hapd->conf->time_advertisement == 2 || hapd->conf->interworking))
len = 4;
if (len < 3 &&
(hapd->conf->wnm_sleep_mode || hapd->conf->bss_transition))
len = 3;
if (len < 1 &&
(hapd->iconf->obss_interval ||
(hapd->iface->drv_flags & WPA_DRIVER_FLAGS_AP_CSA)))
len = 1;
if (len < 2 &&
(hapd->conf->proxy_arp || hapd->conf->coloc_intf_reporting))
len = 2;
if (len < 7 && hapd->conf->ssid.utf8_ssid)
len = 7;
if (len < 9 &&
(hapd->conf->ftm_initiator || hapd->conf->ftm_responder))
len = 9;
#ifdef CONFIG_WNM_AP
if (len < 4)
len = 4;
#endif /* CONFIG_WNM_AP */
#ifdef CONFIG_HS20
if (hapd->conf->hs20 && len < 6)
len = 6;
#endif /* CONFIG_HS20 */
#ifdef CONFIG_MBO
if (hapd->conf->mbo_enabled && len < 6)
len = 6;
#endif /* CONFIG_MBO */
#ifdef CONFIG_FILS
if ((!(hapd->conf->wpa & WPA_PROTO_RSN) ||
!wpa_key_mgmt_fils(hapd->conf->wpa_key_mgmt)) && len < 10)
len = 10;
#endif /* CONFIG_FILS */
#ifdef CONFIG_IEEE80211AX
if (len < 10 && hapd->iconf->ieee80211ax &&
hostapd_get_he_twt_responder(hapd, IEEE80211_MODE_AP))
len = 10;
#endif /* CONFIG_IEEE80211AX */
#ifdef CONFIG_SAE
if (len < 11 && hapd->conf->wpa &&
wpa_key_mgmt_sae(hapd->conf->wpa_key_mgmt) &&
hostapd_sae_pw_id_in_use(hapd->conf))
len = 11;
#endif /* CONFIG_SAE */
if (len < 11 && hapd->conf->beacon_prot &&
(hapd->iface->drv_flags & WPA_DRIVER_FLAGS_BEACON_PROTECTION))
len = 11;
#ifdef CONFIG_SAE_PK
if (len < 12 && hapd->conf->wpa &&
wpa_key_mgmt_sae(hapd->conf->wpa_key_mgmt) &&
hostapd_sae_pk_exclusively(hapd->conf))
len = 12;
#endif /* CONFIG_SAE_PK */
if (len < hapd->iface->extended_capa_len) if (len < hapd->iface->extended_capa_len)
len = hapd->iface->extended_capa_len; len = hapd->iface->extended_capa_len;
if (len == 0)
return eid;
*pos++ = WLAN_EID_EXT_CAPAB; *pos++ = WLAN_EID_EXT_CAPAB;
*pos++ = len; *pos++ = len;
@ -525,6 +465,11 @@ u8 * hostapd_eid_ext_capab(struct hostapd_data *hapd, u8 *eid)
*pos &= ~hapd->iface->extended_capa_mask[i]; *pos &= ~hapd->iface->extended_capa_mask[i];
*pos |= hapd->iface->extended_capa[i]; *pos |= hapd->iface->extended_capa[i];
} }
if (i < EXT_CAPA_MAX_LEN) {
*pos &= ~hapd->conf->ext_capa_mask[i];
*pos |= hapd->conf->ext_capa[i];
}
} }
while (len > 0 && eid[1 + len] == 0) { while (len > 0 && eid[1 + len] == 0) {

View File

@ -88,6 +88,7 @@ struct pasn_data {
u16 group; u16 group;
u8 trans_seq; u8 trans_seq;
u8 wrapped_data_format; u8 wrapped_data_format;
size_t kdk_len;
u8 hash[SHA384_MAC_LEN]; u8 hash[SHA384_MAC_LEN];
struct wpa_ptk ptk; struct wpa_ptk ptk;

View File

@ -2283,8 +2283,7 @@ static int wpa_derive_ptk(struct wpa_state_machine *sm, const u8 *snonce,
if (sm->wpa_auth->conf.force_kdk_derivation || if (sm->wpa_auth->conf.force_kdk_derivation ||
(sm->wpa_auth->conf.secure_ltf && (sm->wpa_auth->conf.secure_ltf &&
sm->rsnxe && sm->rsnxe_len >= 4 && ieee802_11_rsnx_capab(sm->rsnxe, WLAN_RSNX_CAPAB_SECURE_LTF)))
sm->rsnxe[3] & BIT(WLAN_RSNX_CAPAB_SECURE_LTF - 8)))
kdk_len = WPA_KDK_MAX_LEN; kdk_len = WPA_KDK_MAX_LEN;
else else
kdk_len = 0; kdk_len = 0;
@ -2338,8 +2337,7 @@ int fils_auth_pmk_to_ptk(struct wpa_state_machine *sm, const u8 *pmk,
if (sm->wpa_auth->conf.force_kdk_derivation || if (sm->wpa_auth->conf.force_kdk_derivation ||
(sm->wpa_auth->conf.secure_ltf && (sm->wpa_auth->conf.secure_ltf &&
sm->rsnxe && sm->rsnxe_len >= 4 && ieee802_11_rsnx_capab(sm->rsnxe, WLAN_RSNX_CAPAB_SECURE_LTF)))
sm->rsnxe[3] & BIT(WLAN_RSNX_CAPAB_SECURE_LTF - 8)))
kdk_len = WPA_KDK_MAX_LEN; kdk_len = WPA_KDK_MAX_LEN;
else else
kdk_len = 0; kdk_len = 0;
@ -4267,7 +4265,7 @@ int wpa_wnmsleep_bigtk_subelem(struct wpa_state_machine *sm, u8 *pos)
wpa_printf(MSG_DEBUG, "WNM: BIGTK Key ID %u in WNM-Sleep Mode exit", wpa_printf(MSG_DEBUG, "WNM: BIGTK Key ID %u in WNM-Sleep Mode exit",
gsm->GN_bigtk); gsm->GN_bigtk);
wpa_hexdump_key(MSG_DEBUG, "WNM: BIGTK in WNM-Sleep Mode exit", wpa_hexdump_key(MSG_DEBUG, "WNM: BIGTK in WNM-Sleep Mode exit",
gsm->IGTK[gsm->GN_bigtk - 6], len); gsm->BIGTK[gsm->GN_bigtk - 6], len);
return pos - start; return pos - start;
} }

View File

@ -3198,8 +3198,7 @@ static int wpa_ft_process_auth_req(struct wpa_state_machine *sm,
if (sm->wpa_auth->conf.force_kdk_derivation || if (sm->wpa_auth->conf.force_kdk_derivation ||
(sm->wpa_auth->conf.secure_ltf && (sm->wpa_auth->conf.secure_ltf &&
sm->rsnxe && sm->rsnxe_len >= 4 && ieee802_11_rsnx_capab(sm->rsnxe, WLAN_RSNX_CAPAB_SECURE_LTF)))
sm->rsnxe[3] & BIT(WLAN_RSNX_CAPAB_SECURE_LTF - 8)))
kdk_len = WPA_KDK_MAX_LEN; kdk_len = WPA_KDK_MAX_LEN;
else else
kdk_len = 0; kdk_len = 0;

View File

@ -256,87 +256,69 @@ static int sae_tests(void)
#ifdef CONFIG_SAE #ifdef CONFIG_SAE
struct sae_data sae; struct sae_data sae;
int ret = -1; int ret = -1;
/* IEEE P802.11-REVmd/D2.1, Annex J.10 */ /* IEEE Std 802.11-2020, Annex J.10 */
const u8 addr1[ETH_ALEN] = { 0x82, 0x7b, 0x91, 0x9d, 0xd4, 0xb9 }; const u8 addr1[ETH_ALEN] = { 0x4d, 0x3f, 0x2f, 0xff, 0xe3, 0x87 };
const u8 addr2[ETH_ALEN] = { 0x1e, 0xec, 0x49, 0xea, 0x64, 0x88 }; const u8 addr2[ETH_ALEN] = { 0xa5, 0xd8, 0xaa, 0x95, 0x8e, 0x3c };
const char *ssid = "byteme"; const char *ssid = "byteme";
const char *pw = "mekmitasdigoat"; const char *pw = "mekmitasdigoat";
const char *pwid = "psk4internet"; const char *pwid = "psk4internet";
const u8 local_rand[] = { const u8 local_rand[] = {
0xa9, 0x06, 0xf6, 0x1e, 0x4d, 0x3a, 0x5d, 0x4e, 0x99, 0x24, 0x65, 0xfd, 0x3d, 0xaa, 0x3c, 0x60,
0xb2, 0x96, 0x5f, 0xf3, 0x4c, 0xf9, 0x17, 0xdd, 0xaa, 0x65, 0x65, 0xb7, 0xf6, 0x2a, 0x2a, 0x7f,
0x04, 0x44, 0x45, 0xc8, 0x78, 0xc1, 0x7c, 0xa5, 0x2e, 0x12, 0xdd, 0x12, 0xf1, 0x98, 0xfa, 0xf4,
0xd5, 0xb9, 0x37, 0x86, 0xda, 0x9f, 0x83, 0xcf 0xfb, 0xed, 0x89, 0xd7, 0xff, 0x1a, 0xce, 0x94
}; };
const u8 local_mask[] = { const u8 local_mask[] = {
0x42, 0x34, 0xb4, 0xfb, 0x17, 0xaa, 0x43, 0x5c, 0x95, 0x07, 0xa9, 0x0f, 0x77, 0x7a, 0x04, 0x4d,
0x52, 0xfb, 0xfd, 0xeb, 0xe6, 0x40, 0x39, 0xb4, 0x6a, 0x08, 0x30, 0xb9, 0x1e, 0xa3, 0xd5, 0xdd,
0x34, 0x78, 0x20, 0x0e, 0x54, 0xff, 0x7b, 0x6e, 0x70, 0xbe, 0xce, 0x44, 0xe1, 0xac, 0xff, 0xb8,
0x07, 0xb6, 0x9c, 0xad, 0x74, 0x15, 0x3c, 0x15 0x69, 0x83, 0xb5, 0xe1, 0xbf, 0x9f, 0xb3, 0x22
}; };
const u8 local_commit[] = { const u8 local_commit[] = {
0x13, 0x00, 0xeb, 0x3b, 0xab, 0x19, 0x64, 0xe4, 0x13, 0x00, 0x2e, 0x2c, 0x0f, 0x0d, 0xb5, 0x24,
0xa0, 0xab, 0x05, 0x92, 0x5d, 0xdf, 0x33, 0x39, 0x40, 0xad, 0x14, 0x6d, 0x96, 0x71, 0x14, 0xce,
0x51, 0x91, 0x38, 0xbc, 0x65, 0xd6, 0xcd, 0xc0, 0x00, 0x5c, 0xe1, 0xea, 0xb0, 0xaa, 0x2c, 0x2e,
0xf8, 0x13, 0xdd, 0x6f, 0xd4, 0x34, 0x4e, 0xb4, 0x5c, 0x28, 0x71, 0xb7, 0x74, 0xf6, 0xc2, 0x57,
0xbf, 0xe4, 0x4b, 0x5c, 0x21, 0x59, 0x76, 0x58, 0x5c, 0x65, 0xd5, 0xad, 0x9e, 0x00, 0x82, 0x97,
0xf4, 0xe3, 0xed, 0xdf, 0xb4, 0xb9, 0x9f, 0x25, 0x07, 0xaa, 0x36, 0xba, 0x8b, 0x85, 0x97, 0x38,
0xb4, 0xd6, 0x54, 0x0f, 0x32, 0xff, 0x1f, 0xd5, 0xfc, 0x96, 0x1d, 0x08, 0x24, 0x35, 0x05, 0xf4,
0xc5, 0x30, 0xc6, 0x0a, 0x79, 0x44, 0x48, 0x61, 0x7c, 0x03, 0x53, 0x76, 0xd7, 0xac, 0x4b, 0xc8,
0x0b, 0xc6, 0xde, 0x3d, 0x92, 0xbd, 0xbb, 0xd4, 0xd7, 0xb9, 0x50, 0x83, 0xbf, 0x43, 0x82, 0x7d,
0x7d, 0x93, 0x59, 0x80, 0xca, 0x6c, 0xf8, 0x98, 0x0f, 0xc3, 0x1e, 0xd7, 0x78, 0xdd, 0x36, 0x71,
0x8a, 0xb6, 0x63, 0x0b, 0xe6, 0x76, 0x4c, 0x88, 0xfd, 0x21, 0xa4, 0x6d, 0x10, 0x91, 0xd6, 0x4b,
0x5c, 0xeb, 0x97, 0x93, 0x97, 0x0f, 0x69, 0x52, 0x6f, 0x9a, 0x1e, 0x12, 0x72, 0x62, 0x13, 0x25,
0x17, 0xee, 0xff, 0x0d, 0x21, 0x70, 0x73, 0x6b, 0xdb, 0xe1
0x34, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65,
0x74
}; };
const u8 peer_commit[] = { const u8 peer_commit[] = {
0x13, 0x00, 0x55, 0x64, 0xf0, 0x45, 0xb2, 0xea, 0x13, 0x00, 0x59, 0x1b, 0x96, 0xf3, 0x39, 0x7f,
0x1e, 0x56, 0x6c, 0xf1, 0xdd, 0x74, 0x1f, 0x70, 0xb9, 0x45, 0x10, 0x08, 0x48, 0xe7, 0xb5, 0x50,
0xd9, 0xbe, 0x35, 0xd2, 0xdf, 0x5b, 0x9a, 0x55, 0x54, 0x3b, 0x67, 0x20, 0xd8, 0x83, 0x37, 0xee,
0x02, 0x94, 0x6e, 0xe0, 0x3c, 0xf8, 0xda, 0xe2, 0x93, 0xfc, 0x49, 0xfd, 0x6d, 0xf7, 0xe0, 0x8b,
0x7e, 0x1e, 0x05, 0xb8, 0x43, 0x0e, 0xb7, 0xa9, 0x52, 0x23, 0xe7, 0x1b, 0x9b, 0xb0, 0x48, 0xd3,
0x9e, 0x24, 0x87, 0x7c, 0xe6, 0x9b, 0xaf, 0x3d, 0x87, 0x3f, 0x20, 0x55, 0x69, 0x53, 0xa9, 0x6c,
0xc5, 0x80, 0xe3, 0x09, 0x63, 0x3d, 0x6b, 0x38, 0x91, 0x53, 0x6f, 0xd8, 0xee, 0x6c, 0xa9, 0xb4,
0x5f, 0x83, 0xee, 0x1c, 0x3e, 0xc3, 0x59, 0x1f, 0xa6, 0x8a, 0x14, 0x8b, 0x05, 0x6a, 0x90, 0x9b,
0x1a, 0x53, 0x93, 0xc0, 0x6e, 0x80, 0x5d, 0xdc, 0xe0, 0x3e, 0x83, 0xae, 0x20, 0x8f, 0x60, 0xf8,
0xeb, 0x2f, 0xde, 0x50, 0x93, 0x0d, 0xd7, 0xcf, 0xef, 0x55, 0x37, 0x85, 0x80, 0x74, 0xdb, 0x06,
0xeb, 0xb9, 0x87, 0xc6, 0xff, 0x96, 0x66, 0xaf, 0x68, 0x70, 0x32, 0x39, 0x98, 0x62, 0x99, 0x9b,
0x16, 0x4e, 0xb5, 0x18, 0x4d, 0x8e, 0x66, 0x62, 0x51, 0x1e, 0x0a, 0x15, 0x52, 0xa5, 0xfe, 0xa3,
0xed, 0x6a, 0xff, 0x0d, 0x21, 0x70, 0x73, 0x6b, 0x17, 0xc2
0x34, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65,
0x74
}; };
const u8 kck[] = { const u8 kck[] = {
0x59, 0x9d, 0x6f, 0x1e, 0x27, 0x54, 0x8b, 0xe8, 0x1e, 0x73, 0x3f, 0x6d, 0x9b, 0xd5, 0x32, 0x56,
0x49, 0x9d, 0xce, 0xed, 0x2f, 0xec, 0xcf, 0x94, 0x28, 0x73, 0x04, 0x33, 0x88, 0x31, 0xb0, 0x9a,
0x81, 0x8c, 0xe1, 0xc7, 0x9f, 0x1b, 0x4e, 0xb3, 0x39, 0x40, 0x6d, 0x12, 0x10, 0x17, 0x07, 0x3a,
0xd6, 0xa5, 0x32, 0x28, 0xa0, 0x9b, 0xf3, 0xed 0x5c, 0x30, 0xdb, 0x36, 0xf3, 0x6c, 0xb8, 0x1a
}; };
const u8 pmk[] = { const u8 pmk[] = {
0x7a, 0xea, 0xd8, 0x6f, 0xba, 0x4c, 0x32, 0x21, 0x4e, 0x4d, 0xfa, 0xb1, 0xa2, 0xdd, 0x8a, 0xc1,
0xfc, 0x43, 0x7f, 0x5f, 0x14, 0xd7, 0x0d, 0x85, 0xa9, 0x17, 0x90, 0xf9, 0x53, 0xfa, 0xaa, 0x45,
0x4e, 0xa5, 0xd5, 0xaa, 0xc1, 0x69, 0x01, 0x16, 0x2a, 0xe5, 0xc6, 0x87, 0x3a, 0xb7, 0x5b, 0x63,
0x79, 0x30, 0x81, 0xed, 0xa4, 0xd5, 0x57, 0xc5 0x60, 0x5b, 0xa6, 0x63, 0xf8, 0xa7, 0xfe, 0x59
}; };
const u8 pmkid[] = { const u8 pmkid[] = {
0x40, 0xa0, 0x9b, 0x60, 0x17, 0xce, 0xbf, 0x00, 0x87, 0x47, 0xa6, 0x00, 0xee, 0xa3, 0xf9, 0xf2,
0x72, 0x84, 0x3b, 0x53, 0x52, 0xaa, 0x2b, 0x4f 0x24, 0x75, 0xdf, 0x58, 0xca, 0x1e, 0x54, 0x98
};
const u8 local_confirm[] = {
0x01, 0x00, 0x12, 0xd9, 0xd5, 0xc7, 0x8c, 0x50,
0x05, 0x26, 0xd3, 0x6c, 0x41, 0xdb, 0xc5, 0x6a,
0xed, 0xf2, 0x91, 0x4c, 0xed, 0xdd, 0xd7, 0xca,
0xd4, 0xa5, 0x8c, 0x48, 0xf8, 0x3d, 0xbd, 0xe9,
0xfc, 0x77
};
const u8 peer_confirm[] = {
0x01, 0x00, 0x02, 0x87, 0x1c, 0xf9, 0x06, 0x89,
0x8b, 0x80, 0x60, 0xec, 0x18, 0x41, 0x43, 0xbe,
0x77, 0xb8, 0xc0, 0x8a, 0x80, 0x19, 0xb1, 0x3e,
0xb6, 0xd0, 0xae, 0xf0, 0xd8, 0x38, 0x3d, 0xfa,
0xc2, 0xfd
}; };
struct wpabuf *buf = NULL; struct wpabuf *buf = NULL;
struct crypto_bignum *mask = NULL; struct crypto_bignum *mask = NULL;
@ -412,7 +394,7 @@ static int sae_tests(void)
if (!buf || if (!buf ||
sae_set_group(&sae, 19) < 0 || sae_set_group(&sae, 19) < 0 ||
sae_prepare_commit(addr1, addr2, (const u8 *) pw, os_strlen(pw), sae_prepare_commit(addr1, addr2, (const u8 *) pw, os_strlen(pw),
pwid, &sae) < 0) &sae) < 0)
goto fail; goto fail;
/* Override local values based on SAE test vector */ /* Override local values based on SAE test vector */
@ -434,7 +416,7 @@ static int sae_tests(void)
goto fail; goto fail;
/* Check that output matches the test vector */ /* Check that output matches the test vector */
if (sae_write_commit(&sae, buf, NULL, pwid) < 0) if (sae_write_commit(&sae, buf, NULL, NULL) < 0)
goto fail; goto fail;
wpa_hexdump_buf(MSG_DEBUG, "SAE: Commit message", buf); wpa_hexdump_buf(MSG_DEBUG, "SAE: Commit message", buf);
@ -465,21 +447,6 @@ static int sae_tests(void)
goto fail; goto fail;
} }
buf->used = 0;
sae.send_confirm = 1;
sae_write_confirm(&sae, buf);
wpa_hexdump_buf(MSG_DEBUG, "SAE: Confirm message", buf);
if (wpabuf_len(buf) != sizeof(local_confirm) ||
os_memcmp(wpabuf_head(buf), local_confirm,
sizeof(local_confirm)) != 0) {
wpa_printf(MSG_ERROR, "SAE: Mismatch in local confirm");
goto fail;
}
if (sae_check_confirm(&sae, peer_confirm, sizeof(peer_confirm)) < 0)
goto fail;
pt_info = sae_derive_pt(pt_groups, pt_info = sae_derive_pt(pt_groups,
(const u8 *) ssid, os_strlen(ssid), (const u8 *) ssid, os_strlen(ssid),
(const u8 *) pw, os_strlen(pw), pwid); (const u8 *) pw, os_strlen(pw), pwid);

View File

@ -2403,6 +2403,35 @@ int ieee802_11_ext_capab(const u8 *ie, unsigned int capab)
} }
bool ieee802_11_rsnx_capab_len(const u8 *rsnxe, size_t rsnxe_len,
unsigned int capab)
{
const u8 *end;
size_t flen, i;
u32 capabs = 0;
if (!rsnxe || rsnxe_len == 0)
return false;
end = rsnxe + rsnxe_len;
flen = (rsnxe[0] & 0x0f) + 1;
if (rsnxe + flen > end)
return false;
if (flen > 4)
flen = 4;
for (i = 0; i < flen; i++)
capabs |= rsnxe[i] << (8 * i);
return capabs & BIT(capab);
}
bool ieee802_11_rsnx_capab(const u8 *rsnxe, unsigned int capab)
{
return ieee802_11_rsnx_capab_len(rsnxe ? rsnxe + 2 : NULL,
rsnxe ? rsnxe[1] : 0, capab);
}
void hostapd_encode_edmg_chan(int edmg_enable, u8 edmg_channel, void hostapd_encode_edmg_chan(int edmg_enable, u8 edmg_channel,
int primary_channel, int primary_channel,
struct ieee80211_edmg_config *edmg) struct ieee80211_edmg_config *edmg)

View File

@ -269,6 +269,9 @@ int ieee802_11_parse_candidate_list(const char *pos, u8 *nei_rep,
size_t nei_rep_len); size_t nei_rep_len);
int ieee802_11_ext_capab(const u8 *ie, unsigned int capab); int ieee802_11_ext_capab(const u8 *ie, unsigned int capab);
bool ieee802_11_rsnx_capab_len(const u8 *rsnxe, size_t rsnxe_len,
unsigned int capab);
bool ieee802_11_rsnx_capab(const u8 *rsnxe, unsigned int capab);
int op_class_to_bandwidth(u8 op_class); int op_class_to_bandwidth(u8 op_class);
int op_class_to_ch_width(u8 op_class); int op_class_to_ch_width(u8 op_class);

View File

@ -8445,6 +8445,34 @@ enum qca_wlan_twt_setup_state {
* This parameter is used for * This parameter is used for
* 1. TWT SET Request and Response * 1. TWT SET Request and Response
* 2. TWT GET Response * 2. TWT GET Response
*
* @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_BCAST_ID: Optional (u8)
* This attribute is used to configure Broadcast TWT ID.
* The Broadcast TWT ID indicates a specific Broadcast TWT for which the
* transmitting STA is providing TWT parameters. The allowed values are 0 to 31.
* This parameter is used for
* 1. TWT SET Request
* 2. TWT TERMINATE Request
*
* @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_BCAST_RECOMMENDATION: Optional (u8)
* This attribute is used to configure Broadcast TWT recommendation.
* The Broadcast TWT Recommendation subfield contains a value that indicates
* recommendations on the types of frames that are transmitted by TWT
* scheduled STAs and scheduling AP during the broadcast TWT SP.
* The allowed values are 0 - 3.
* This parameter is used for
* 1. TWT SET Request
*
* @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_BCAST_PERSISTENCE: Optional (u8)
* This attribute is used to configure Broadcast TWT Persistence.
* The Broadcast TWT Persistence subfield indicates the number of
* TBTTs during which the Broadcast TWT SPs corresponding to this
* broadcast TWT Parameter set are present. The number of beacon intervals
* during which the Broadcast TWT SPs are present is equal to the value in the
* Broadcast TWT Persistence subfield plus 1 except that the value 255
* indicates that the Broadcast TWT SPs are present until explicitly terminated.
* This parameter is used for
* 1. TWT SET Request
*/ */
enum qca_wlan_vendor_attr_twt_setup { enum qca_wlan_vendor_attr_twt_setup {
QCA_WLAN_VENDOR_ATTR_TWT_SETUP_INVALID = 0, QCA_WLAN_VENDOR_ATTR_TWT_SETUP_INVALID = 0,
@ -8474,6 +8502,10 @@ enum qca_wlan_vendor_attr_twt_setup {
QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_INTVL2_MANTISSA = 21, QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_INTVL2_MANTISSA = 21,
QCA_WLAN_VENDOR_ATTR_TWT_SETUP_BCAST_ID = 22,
QCA_WLAN_VENDOR_ATTR_TWT_SETUP_BCAST_RECOMMENDATION = 23,
QCA_WLAN_VENDOR_ATTR_TWT_SETUP_BCAST_PERSISTENCE = 24,
/* keep last */ /* keep last */
QCA_WLAN_VENDOR_ATTR_TWT_SETUP_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_TWT_SETUP_AFTER_LAST,
QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MAX = QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MAX =
@ -8512,6 +8544,13 @@ enum qca_wlan_vendor_attr_twt_setup {
* @QCA_WLAN_VENDOR_TWT_STATUS_ROAM_INITIATED_TERMINATE: FW terminated the TWT * @QCA_WLAN_VENDOR_TWT_STATUS_ROAM_INITIATED_TERMINATE: FW terminated the TWT
* session due to roaming. Used on the TWT_TERMINATE notification from the * session due to roaming. Used on the TWT_TERMINATE notification from the
* firmware. * firmware.
* @QCA_WLAN_VENDOR_TWT_STATUS_SCC_MCC_CONCURRENCY_TERMINATE: FW terminated the
* TWT session due to SCC (Single Channel Concurrency) and MCC (Multi Channel
* Concurrency). Used on the TWT_TERMINATE notification from the firmware.
* @QCA_WLAN_VENDOR_TWT_STATUS_ROAMING_IN_PROGRESS: FW rejected the TWT setup
* request due to roaming in progress.
* @QCA_WLAN_VENDOR_TWT_STATUS_CHANNEL_SWITCH_IN_PROGRESS: FW rejected the TWT
* setup request due to channel switch in progress.
*/ */
enum qca_wlan_vendor_twt_status { enum qca_wlan_vendor_twt_status {
QCA_WLAN_VENDOR_TWT_STATUS_OK = 0, QCA_WLAN_VENDOR_TWT_STATUS_OK = 0,
@ -8532,6 +8571,9 @@ enum qca_wlan_vendor_twt_status {
QCA_WLAN_VENDOR_TWT_STATUS_PARAMS_NOT_IN_RANGE = 15, QCA_WLAN_VENDOR_TWT_STATUS_PARAMS_NOT_IN_RANGE = 15,
QCA_WLAN_VENDOR_TWT_STATUS_PEER_INITIATED_TERMINATE = 16, QCA_WLAN_VENDOR_TWT_STATUS_PEER_INITIATED_TERMINATE = 16,
QCA_WLAN_VENDOR_TWT_STATUS_ROAM_INITIATED_TERMINATE = 17, QCA_WLAN_VENDOR_TWT_STATUS_ROAM_INITIATED_TERMINATE = 17,
QCA_WLAN_VENDOR_TWT_STATUS_SCC_MCC_CONCURRENCY_TERMINATE = 18,
QCA_WLAN_VENDOR_TWT_STATUS_ROAMING_IN_PROGRESS = 19,
QCA_WLAN_VENDOR_TWT_STATUS_CHANNEL_SWITCH_IN_PROGRESS = 20,
}; };
/** /**

View File

@ -280,13 +280,12 @@ static int sae_test_pwd_seed_ffc(struct sae_data *sae, const u8 *pwd_seed,
static int sae_derive_pwe_ecc(struct sae_data *sae, const u8 *addr1, static int sae_derive_pwe_ecc(struct sae_data *sae, const u8 *addr1,
const u8 *addr2, const u8 *password, const u8 *addr2, const u8 *password,
size_t password_len, const char *identifier) size_t password_len)
{ {
u8 counter, k; u8 counter, k;
u8 addrs[2 * ETH_ALEN]; u8 addrs[2 * ETH_ALEN];
const u8 *addr[3]; const u8 *addr[2];
size_t len[3]; size_t len[2];
size_t num_elem;
u8 *dummy_password, *tmp_password; u8 *dummy_password, *tmp_password;
int pwd_seed_odd = 0; int pwd_seed_odd = 0;
u8 prime[SAE_MAX_ECC_PRIME_LEN]; u8 prime[SAE_MAX_ECC_PRIME_LEN];
@ -324,13 +323,10 @@ static int sae_derive_pwe_ecc(struct sae_data *sae, const u8 *addr1,
wpa_hexdump_ascii_key(MSG_DEBUG, "SAE: password", wpa_hexdump_ascii_key(MSG_DEBUG, "SAE: password",
password, password_len); password, password_len);
if (identifier)
wpa_printf(MSG_DEBUG, "SAE: password identifier: %s",
identifier);
/* /*
* H(salt, ikm) = HMAC-SHA256(salt, ikm) * H(salt, ikm) = HMAC-SHA256(salt, ikm)
* base = password [|| identifier] * base = password
* pwd-seed = H(MAX(STA-A-MAC, STA-B-MAC) || MIN(STA-A-MAC, STA-B-MAC), * pwd-seed = H(MAX(STA-A-MAC, STA-B-MAC) || MIN(STA-A-MAC, STA-B-MAC),
* base || counter) * base || counter)
*/ */
@ -338,15 +334,8 @@ static int sae_derive_pwe_ecc(struct sae_data *sae, const u8 *addr1,
addr[0] = tmp_password; addr[0] = tmp_password;
len[0] = password_len; len[0] = password_len;
num_elem = 1; addr[1] = &counter;
if (identifier) { len[1] = sizeof(counter);
addr[num_elem] = (const u8 *) identifier;
len[num_elem] = os_strlen(identifier);
num_elem++;
}
addr[num_elem] = &counter;
len[num_elem] = sizeof(counter);
num_elem++;
/* /*
* Continue for at least k iterations to protect against side-channel * Continue for at least k iterations to protect against side-channel
@ -367,7 +356,7 @@ static int sae_derive_pwe_ecc(struct sae_data *sae, const u8 *addr1,
wpa_printf(MSG_DEBUG, "SAE: counter = %03u", counter); wpa_printf(MSG_DEBUG, "SAE: counter = %03u", counter);
const_time_select_bin(found, dummy_password, password, const_time_select_bin(found, dummy_password, password,
password_len, tmp_password); password_len, tmp_password);
if (hmac_sha256_vector(addrs, sizeof(addrs), num_elem, if (hmac_sha256_vector(addrs, sizeof(addrs), 2,
addr, len, pwd_seed) < 0) addr, len, pwd_seed) < 0)
break; break;
@ -438,13 +427,12 @@ static int sae_derive_pwe_ecc(struct sae_data *sae, const u8 *addr1,
static int sae_derive_pwe_ffc(struct sae_data *sae, const u8 *addr1, static int sae_derive_pwe_ffc(struct sae_data *sae, const u8 *addr1,
const u8 *addr2, const u8 *password, const u8 *addr2, const u8 *password,
size_t password_len, const char *identifier) size_t password_len)
{ {
u8 counter, k, sel_counter = 0; u8 counter, k, sel_counter = 0;
u8 addrs[2 * ETH_ALEN]; u8 addrs[2 * ETH_ALEN];
const u8 *addr[3]; const u8 *addr[2];
size_t len[3]; size_t len[2];
size_t num_elem;
u8 found = 0; /* 0 (false) or 0xff (true) to be used as const_time_* u8 found = 0; /* 0 (false) or 0xff (true) to be used as const_time_*
* mask */ * mask */
u8 mask; u8 mask;
@ -468,21 +456,14 @@ static int sae_derive_pwe_ffc(struct sae_data *sae, const u8 *addr1,
/* /*
* H(salt, ikm) = HMAC-SHA256(salt, ikm) * H(salt, ikm) = HMAC-SHA256(salt, ikm)
* pwd-seed = H(MAX(STA-A-MAC, STA-B-MAC) || MIN(STA-A-MAC, STA-B-MAC), * pwd-seed = H(MAX(STA-A-MAC, STA-B-MAC) || MIN(STA-A-MAC, STA-B-MAC),
* password [|| identifier] || counter) * password || counter)
*/ */
sae_pwd_seed_key(addr1, addr2, addrs); sae_pwd_seed_key(addr1, addr2, addrs);
addr[0] = password; addr[0] = password;
len[0] = password_len; len[0] = password_len;
num_elem = 1; addr[1] = &counter;
if (identifier) { len[1] = sizeof(counter);
addr[num_elem] = (const u8 *) identifier;
len[num_elem] = os_strlen(identifier);
num_elem++;
}
addr[num_elem] = &counter;
len[num_elem] = sizeof(counter);
num_elem++;
k = dragonfly_min_pwe_loop_iter(sae->group); k = dragonfly_min_pwe_loop_iter(sae->group);
@ -497,7 +478,7 @@ static int sae_derive_pwe_ffc(struct sae_data *sae, const u8 *addr1,
} }
wpa_printf(MSG_DEBUG, "SAE: counter = %02u", counter); wpa_printf(MSG_DEBUG, "SAE: counter = %02u", counter);
if (hmac_sha256_vector(addrs, sizeof(addrs), num_elem, if (hmac_sha256_vector(addrs, sizeof(addrs), 2,
addr, len, pwd_seed) < 0) addr, len, pwd_seed) < 0)
break; break;
res = sae_test_pwd_seed_ffc(sae, pwd_seed, pwe); res = sae_test_pwd_seed_ffc(sae, pwd_seed, pwe);
@ -1354,15 +1335,13 @@ static int sae_derive_commit(struct sae_data *sae)
int sae_prepare_commit(const u8 *addr1, const u8 *addr2, int sae_prepare_commit(const u8 *addr1, const u8 *addr2,
const u8 *password, size_t password_len, const u8 *password, size_t password_len,
const char *identifier, struct sae_data *sae) struct sae_data *sae)
{ {
if (sae->tmp == NULL || if (sae->tmp == NULL ||
(sae->tmp->ec && sae_derive_pwe_ecc(sae, addr1, addr2, password, (sae->tmp->ec && sae_derive_pwe_ecc(sae, addr1, addr2, password,
password_len, password_len) < 0) ||
identifier) < 0) ||
(sae->tmp->dh && sae_derive_pwe_ffc(sae, addr1, addr2, password, (sae->tmp->dh && sae_derive_pwe_ffc(sae, addr1, addr2, password,
password_len, password_len) < 0))
identifier) < 0))
return -1; return -1;
sae->h2e = 0; sae->h2e = 0;
@ -2268,10 +2247,10 @@ int sae_write_confirm(struct sae_data *sae, struct wpabuf *buf)
hash_len = sae->tmp->kck_len; hash_len = sae->tmp->kck_len;
/* Send-Confirm */ /* Send-Confirm */
sc = wpabuf_put(buf, 0);
wpabuf_put_le16(buf, sae->send_confirm);
if (sae->send_confirm < 0xffff) if (sae->send_confirm < 0xffff)
sae->send_confirm++; sae->send_confirm++;
sc = wpabuf_put(buf, 0);
wpabuf_put_le16(buf, sae->send_confirm);
if (sae->tmp->ec) if (sae->tmp->ec)
res = sae_cn_confirm_ecc(sae, sc, sae->tmp->own_commit_scalar, res = sae_cn_confirm_ecc(sae, sc, sae->tmp->own_commit_scalar,

View File

@ -122,7 +122,7 @@ void sae_clear_data(struct sae_data *sae);
int sae_prepare_commit(const u8 *addr1, const u8 *addr2, int sae_prepare_commit(const u8 *addr1, const u8 *addr2,
const u8 *password, size_t password_len, const u8 *password, size_t password_len,
const char *identifier, struct sae_data *sae); struct sae_data *sae);
int sae_prepare_commit_pt(struct sae_data *sae, const struct sae_pt *pt, int sae_prepare_commit_pt(struct sae_data *sae, const struct sae_pt *pt,
const u8 *addr1, const u8 *addr2, const u8 *addr1, const u8 *addr2,
int *rejected_groups, const struct sae_pk *pk); int *rejected_groups, const struct sae_pk *pk);

View File

@ -3428,8 +3428,8 @@ int wpa_pasn_add_rsne(struct wpabuf *buf, const u8 *pmkid, int akmp, int cipher)
*/ */
void wpa_pasn_add_parameter_ie(struct wpabuf *buf, u16 pasn_group, void wpa_pasn_add_parameter_ie(struct wpabuf *buf, u16 pasn_group,
u8 wrapped_data_format, u8 wrapped_data_format,
struct wpabuf *pubkey, bool compressed, const struct wpabuf *pubkey, bool compressed,
struct wpabuf *comeback, int after) const struct wpabuf *comeback, int after)
{ {
struct pasn_parameter_ie *params; struct pasn_parameter_ie *params;

View File

@ -662,8 +662,8 @@ int wpa_pasn_add_rsne(struct wpabuf *buf, const u8 *pmkid,
void wpa_pasn_add_parameter_ie(struct wpabuf *buf, u16 pasn_group, void wpa_pasn_add_parameter_ie(struct wpabuf *buf, u16 pasn_group,
u8 wrapped_data_format, u8 wrapped_data_format,
struct wpabuf *pubkey, bool compressed, const struct wpabuf *pubkey, bool compressed,
struct wpabuf *comeback, int after); const struct wpabuf *comeback, int after);
int wpa_pasn_add_wrapped_data(struct wpabuf *buf, int wpa_pasn_add_wrapped_data(struct wpabuf *buf,
struct wpabuf *wrapped_data_buf); struct wpabuf *wrapped_data_buf);

View File

@ -81,12 +81,14 @@ static void EVP_MD_CTX_free(EVP_MD_CTX *ctx)
} }
#ifdef CONFIG_ECC
static EC_KEY * EVP_PKEY_get0_EC_KEY(EVP_PKEY *pkey) static EC_KEY * EVP_PKEY_get0_EC_KEY(EVP_PKEY *pkey)
{ {
if (pkey->type != EVP_PKEY_EC) if (pkey->type != EVP_PKEY_EC)
return NULL; return NULL;
return pkey->pkey.ec; return pkey->pkey.ec;
} }
#endif /* CONFIG_ECC */
#endif /* OpenSSL version < 1.1.0 */ #endif /* OpenSSL version < 1.1.0 */

View File

@ -4553,6 +4553,12 @@ struct wpa_driver_ops {
* explicitly allow reception of broadcast Public Action frames. * explicitly allow reception of broadcast Public Action frames.
*/ */
int (*dpp_listen)(void *priv, bool enable); int (*dpp_listen)(void *priv, bool enable);
#ifdef CONFIG_TESTING_OPTIONS
int (*register_frame)(void *priv, u16 type,
const u8 *match, size_t match_len,
bool multicast);
#endif /* CONFIG_TESTING_OPTIONS */
}; };
/** /**

View File

@ -656,12 +656,10 @@ struct nl_msg * nl80211_cmd_msg(struct i802_bss *bss, int flags, uint8_t cmd)
static struct nl_msg * static struct nl_msg *
nl80211_ifindex_msg(struct wpa_driver_nl80211_data *drv, int ifindex, nl80211_ifindex_msg_build(struct wpa_driver_nl80211_data *drv,
int flags, uint8_t cmd) struct nl_msg *msg, int ifindex, int flags,
uint8_t cmd)
{ {
struct nl_msg *msg;
msg = nlmsg_alloc();
if (!msg) if (!msg)
return NULL; return NULL;
@ -675,6 +673,15 @@ nl80211_ifindex_msg(struct wpa_driver_nl80211_data *drv, int ifindex,
} }
static struct nl_msg *
nl80211_ifindex_msg(struct wpa_driver_nl80211_data *drv, int ifindex,
int flags, uint8_t cmd)
{
return nl80211_ifindex_msg_build(drv, nlmsg_alloc(), ifindex, flags,
cmd);
}
struct nl_msg * nl80211_drv_msg(struct wpa_driver_nl80211_data *drv, int flags, struct nl_msg * nl80211_drv_msg(struct wpa_driver_nl80211_data *drv, int flags,
uint8_t cmd) uint8_t cmd)
{ {
@ -4151,6 +4158,7 @@ static int wpa_driver_nl80211_set_acl(void *priv,
struct nl_msg *acl; struct nl_msg *acl;
unsigned int i; unsigned int i;
int ret; int ret;
size_t acl_nla_sz, acl_nlmsg_sz, nla_sz, nlmsg_sz;
if (!(drv->capa.max_acl_mac_addrs)) if (!(drv->capa.max_acl_mac_addrs))
return -ENOTSUP; return -ENOTSUP;
@ -4161,7 +4169,9 @@ static int wpa_driver_nl80211_set_acl(void *priv,
wpa_printf(MSG_DEBUG, "nl80211: Set %s ACL (num_mac_acl=%u)", wpa_printf(MSG_DEBUG, "nl80211: Set %s ACL (num_mac_acl=%u)",
params->acl_policy ? "Accept" : "Deny", params->num_mac_acl); params->acl_policy ? "Accept" : "Deny", params->num_mac_acl);
acl = nlmsg_alloc(); acl_nla_sz = nla_total_size(ETH_ALEN) * params->num_mac_acl;
acl_nlmsg_sz = nlmsg_total_size(acl_nla_sz);
acl = nlmsg_alloc_size(acl_nlmsg_sz);
if (!acl) if (!acl)
return -ENOMEM; return -ENOMEM;
for (i = 0; i < params->num_mac_acl; i++) { for (i = 0; i < params->num_mac_acl; i++) {
@ -4171,7 +4181,19 @@ static int wpa_driver_nl80211_set_acl(void *priv,
} }
} }
if (!(msg = nl80211_drv_msg(drv, 0, NL80211_CMD_SET_MAC_ACL)) || /*
* genetlink message header (Length of user header is 0) +
* u32 attr: NL80211_ATTR_IFINDEX +
* u32 attr: NL80211_ATTR_ACL_POLICY +
* nested acl attr
*/
nla_sz = GENL_HDRLEN +
nla_total_size(4) * 2 +
nla_total_size(acl_nla_sz);
nlmsg_sz = nlmsg_total_size(nla_sz);
if (!(msg = nl80211_ifindex_msg_build(drv, nlmsg_alloc_size(nlmsg_sz),
drv->ifindex, 0,
NL80211_CMD_SET_MAC_ACL)) ||
nla_put_u32(msg, NL80211_ATTR_ACL_POLICY, params->acl_policy ? nla_put_u32(msg, NL80211_ATTR_ACL_POLICY, params->acl_policy ?
NL80211_ACL_POLICY_DENY_UNLESS_LISTED : NL80211_ACL_POLICY_DENY_UNLESS_LISTED :
NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED) || NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED) ||
@ -5789,6 +5811,7 @@ static int driver_nl80211_sta_set_airtime_weight(void *priv, const u8 *addr,
{ {
struct i802_bss *bss = priv; struct i802_bss *bss = priv;
struct nl_msg *msg; struct nl_msg *msg;
int ret;
wpa_printf(MSG_DEBUG, wpa_printf(MSG_DEBUG,
"nl80211: Set STA airtime weight - ifname=%s addr=" MACSTR "nl80211: Set STA airtime weight - ifname=%s addr=" MACSTR
@ -5799,7 +5822,13 @@ static int driver_nl80211_sta_set_airtime_weight(void *priv, const u8 *addr,
nla_put_u16(msg, NL80211_ATTR_AIRTIME_WEIGHT, weight)) nla_put_u16(msg, NL80211_ATTR_AIRTIME_WEIGHT, weight))
goto fail; goto fail;
return send_and_recv_msgs(bss->drv, msg, NULL, NULL, NULL, NULL); ret = send_and_recv_msgs(bss->drv, msg, NULL, NULL, NULL, NULL);
if (ret) {
wpa_printf(MSG_DEBUG,
"nl80211: SET_STATION[AIRTIME_WEIGHT] failed: ret=%d (%s)",
ret, strerror(-ret));
}
return ret;
fail: fail:
nlmsg_free(msg); nlmsg_free(msg);
return -ENOBUFS; return -ENOBUFS;
@ -12028,6 +12057,23 @@ static int nl80211_dpp_listen(void *priv, bool enable)
#endif /* CONFIG_DPP */ #endif /* CONFIG_DPP */
#ifdef CONFIG_TESTING_OPTIONS
static int testing_nl80211_register_frame(void *priv, u16 type,
const u8 *match, size_t match_len,
bool multicast)
{
struct i802_bss *bss = priv;
struct nl_sock *handle;
if (!bss->nl_mgmt)
return -1;
handle = (void *) (((intptr_t) bss->nl_mgmt) ^ ELOOP_SOCKET_INVALID);
return nl80211_register_frame(bss, handle, type, match, match_len,
multicast);
}
#endif /* CONFIG_TESTING_OPTIONS */
const struct wpa_driver_ops wpa_driver_nl80211_ops = { const struct wpa_driver_ops wpa_driver_nl80211_ops = {
.name = "nl80211", .name = "nl80211",
.desc = "Linux nl80211/cfg80211", .desc = "Linux nl80211/cfg80211",
@ -12166,4 +12212,7 @@ const struct wpa_driver_ops wpa_driver_nl80211_ops = {
#ifdef CONFIG_DPP #ifdef CONFIG_DPP
.dpp_listen = nl80211_dpp_listen, .dpp_listen = nl80211_dpp_listen,
#endif /* CONFIG_DPP */ #endif /* CONFIG_DPP */
#ifdef CONFIG_TESTING_OPTIONS
.register_frame = testing_nl80211_register_frame,
#endif /* CONFIG_TESTING_OPTIONS */
}; };

View File

@ -891,7 +891,7 @@ static int wiphy_info_handler(struct nl_msg *msg, void *arg)
if (tb[NL80211_ATTR_MAC_ACL_MAX]) if (tb[NL80211_ATTR_MAC_ACL_MAX])
capa->max_acl_mac_addrs = capa->max_acl_mac_addrs =
nla_get_u8(tb[NL80211_ATTR_MAC_ACL_MAX]); nla_get_u32(tb[NL80211_ATTR_MAC_ACL_MAX]);
wiphy_info_supported_iftypes(info, tb[NL80211_ATTR_SUPPORTED_IFTYPES]); wiphy_info_supported_iftypes(info, tb[NL80211_ATTR_SUPPORTED_IFTYPES]);
wiphy_info_iface_comb(info, tb[NL80211_ATTR_INTERFACE_COMBINATIONS]); wiphy_info_iface_comb(info, tb[NL80211_ATTR_INTERFACE_COMBINATIONS]);

View File

@ -1210,9 +1210,24 @@ void eap_sim_report_notification(void *msg_ctx, int notification, int aka)
} }
static const u8 * get_last_char(const u8 *val, size_t len, char c)
{
while (len > 0) {
const u8 *pos = &val[len - 1];
if (*pos == (u8) c)
return pos;
len--;
}
return NULL;
}
int eap_sim_anonymous_username(const u8 *id, size_t id_len) int eap_sim_anonymous_username(const u8 *id, size_t id_len)
{ {
static const char *anonymous_id_prefix = "anonymous@"; static const char *anonymous_id_prefix = "anonymous@";
const u8 *decorated;
size_t anonymous_id_len = os_strlen(anonymous_id_prefix); size_t anonymous_id_len = os_strlen(anonymous_id_prefix);
if (id_len > anonymous_id_len && if (id_len > anonymous_id_len &&
@ -1226,5 +1241,14 @@ int eap_sim_anonymous_username(const u8 *id, size_t id_len)
if (id_len > 1 && id[0] == '@') if (id_len > 1 && id[0] == '@')
return 1; /* '@realm' */ return 1; /* '@realm' */
/* RFC 7542 decorated username, for example:
* homerealm.example.org!anonymous@otherrealm.example.net */
decorated = get_last_char(id, id_len, '!');
if (decorated) {
decorated++;
return eap_sim_anonymous_username(decorated,
id + id_len - decorated);
}
return 0; return 0;
} }

View File

@ -451,6 +451,10 @@ static int wpa_supplicant_get_pmk(struct wpa_sm *sm,
buf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_START, buf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_START,
NULL, 0, &buflen, NULL); NULL, 0, &buflen, NULL);
if (buf) { if (buf) {
/* Set and reset eapFail to allow EAP state machine to
* proceed with new authentication. */
eapol_sm_notify_eap_fail(sm->eapol, true);
eapol_sm_notify_eap_fail(sm->eapol, false);
wpa_sm_ether_send(sm, sm->bssid, ETH_P_EAPOL, wpa_sm_ether_send(sm, sm->bssid, ETH_P_EAPOL,
buf, buflen); buf, buflen);
os_free(buf); os_free(buf);
@ -605,8 +609,8 @@ static int wpa_derive_ptk(struct wpa_sm *sm, const unsigned char *src_addr,
#endif /* CONFIG_OWE */ #endif /* CONFIG_OWE */
if (sm->force_kdk_derivation || if (sm->force_kdk_derivation ||
(sm->secure_ltf && sm->ap_rsnxe && sm->ap_rsnxe_len >= 4 && (sm->secure_ltf &&
sm->ap_rsnxe[3] & BIT(WLAN_RSNX_CAPAB_SECURE_LTF - 8))) ieee802_11_rsnx_capab(sm->ap_rsnxe, WLAN_RSNX_CAPAB_SECURE_LTF)))
kdk_len = WPA_KDK_MAX_LEN; kdk_len = WPA_KDK_MAX_LEN;
else else
kdk_len = 0; kdk_len = 0;
@ -4372,8 +4376,8 @@ int fils_process_auth(struct wpa_sm *sm, const u8 *bssid, const u8 *data,
} }
if (sm->force_kdk_derivation || if (sm->force_kdk_derivation ||
(sm->secure_ltf && sm->ap_rsnxe && sm->ap_rsnxe_len >= 4 && (sm->secure_ltf &&
sm->ap_rsnxe[3] & BIT(WLAN_RSNX_CAPAB_SECURE_LTF - 8))) ieee802_11_rsnx_capab(sm->ap_rsnxe, WLAN_RSNX_CAPAB_SECURE_LTF)))
kdk_len = WPA_KDK_MAX_LEN; kdk_len = WPA_KDK_MAX_LEN;
else else
kdk_len = 0; kdk_len = 0;

View File

@ -69,8 +69,8 @@ int wpa_derive_ptk_ft(struct wpa_sm *sm, const unsigned char *src_addr,
wpa_ft_pasn_store_r1kh(sm, src_addr); wpa_ft_pasn_store_r1kh(sm, src_addr);
if (sm->force_kdk_derivation || if (sm->force_kdk_derivation ||
(sm->secure_ltf && sm->ap_rsnxe && sm->ap_rsnxe_len >= 4 && (sm->secure_ltf &&
sm->ap_rsnxe[3] & BIT(WLAN_RSNX_CAPAB_SECURE_LTF - 8))) ieee802_11_rsnx_capab(sm->ap_rsnxe, WLAN_RSNX_CAPAB_SECURE_LTF)))
kdk_len = WPA_KDK_MAX_LEN; kdk_len = WPA_KDK_MAX_LEN;
else else
kdk_len = 0; kdk_len = 0;
@ -672,8 +672,8 @@ int wpa_ft_process_response(struct wpa_sm *sm, const u8 *ies, size_t ies_len,
wpa_ft_pasn_store_r1kh(sm, bssid); wpa_ft_pasn_store_r1kh(sm, bssid);
if (sm->force_kdk_derivation || if (sm->force_kdk_derivation ||
(sm->secure_ltf && sm->ap_rsnxe && sm->ap_rsnxe_len >= 4 && (sm->secure_ltf &&
sm->ap_rsnxe[3] & BIT(WLAN_RSNX_CAPAB_SECURE_LTF - 8))) ieee802_11_rsnx_capab(sm->ap_rsnxe, WLAN_RSNX_CAPAB_SECURE_LTF)))
kdk_len = WPA_KDK_MAX_LEN; kdk_len = WPA_KDK_MAX_LEN;
else else
kdk_len = 0; kdk_len = 0;

View File

@ -1320,13 +1320,9 @@ static int wps_set_ie(struct wps_registrar *reg)
} }
beacon = wpabuf_alloc(400 + vendor_len); beacon = wpabuf_alloc(400 + vendor_len);
if (beacon == NULL)
return -1;
probe = wpabuf_alloc(500 + vendor_len); probe = wpabuf_alloc(500 + vendor_len);
if (probe == NULL) { if (!beacon || !probe)
wpabuf_free(beacon); goto fail;
return -1;
}
auth_macs = wps_authorized_macs(reg, &count); auth_macs = wps_authorized_macs(reg, &count);
@ -1342,19 +1338,13 @@ static int wps_set_ie(struct wps_registrar *reg)
(reg->dualband && wps_build_rf_bands(&reg->wps->dev, beacon, 0)) || (reg->dualband && wps_build_rf_bands(&reg->wps->dev, beacon, 0)) ||
wps_build_wfa_ext(beacon, 0, auth_macs, count, 0) || wps_build_wfa_ext(beacon, 0, auth_macs, count, 0) ||
wps_build_vendor_ext(&reg->wps->dev, beacon) || wps_build_vendor_ext(&reg->wps->dev, beacon) ||
wps_build_application_ext(&reg->wps->dev, beacon)) { wps_build_application_ext(&reg->wps->dev, beacon))
wpabuf_free(beacon); goto fail;
wpabuf_free(probe);
return -1;
}
#ifdef CONFIG_P2P #ifdef CONFIG_P2P
if (wps_build_dev_name(&reg->wps->dev, beacon) || if (wps_build_dev_name(&reg->wps->dev, beacon) ||
wps_build_primary_dev_type(&reg->wps->dev, beacon)) { wps_build_primary_dev_type(&reg->wps->dev, beacon))
wpabuf_free(beacon); goto fail;
wpabuf_free(probe);
return -1;
}
#endif /* CONFIG_P2P */ #endif /* CONFIG_P2P */
wpa_printf(MSG_DEBUG, "WPS: Build Probe Response IEs"); wpa_printf(MSG_DEBUG, "WPS: Build Probe Response IEs");
@ -1373,22 +1363,20 @@ static int wps_set_ie(struct wps_registrar *reg)
(reg->dualband && wps_build_rf_bands(&reg->wps->dev, probe, 0)) || (reg->dualband && wps_build_rf_bands(&reg->wps->dev, probe, 0)) ||
wps_build_wfa_ext(probe, 0, auth_macs, count, 0) || wps_build_wfa_ext(probe, 0, auth_macs, count, 0) ||
wps_build_vendor_ext(&reg->wps->dev, probe) || wps_build_vendor_ext(&reg->wps->dev, probe) ||
wps_build_application_ext(&reg->wps->dev, probe)) { wps_build_application_ext(&reg->wps->dev, probe))
wpabuf_free(beacon); goto fail;
wpabuf_free(probe);
return -1;
}
beacon = wps_ie_encapsulate(beacon); beacon = wps_ie_encapsulate(beacon);
probe = wps_ie_encapsulate(probe); probe = wps_ie_encapsulate(probe);
if (!beacon || !probe) { if (!beacon || !probe)
goto fail;
return wps_cb_set_ie(reg, beacon, probe);
fail:
wpabuf_free(beacon); wpabuf_free(beacon);
wpabuf_free(probe); wpabuf_free(probe);
return -1; return -1;
}
return wps_cb_set_ie(reg, beacon, probe);
} }

View File

@ -113,3 +113,4 @@ CONFIG_DPP=y
CONFIG_DPP2=y CONFIG_DPP2=y
CONFIG_WEP=y CONFIG_WEP=y
CONFIG_PASN=y CONFIG_PASN=y
CONFIG_AIRTIME_POLICY=y

View File

@ -419,6 +419,12 @@ def dpp_qr_code(self, uri):
raise Exception("Failed to parse QR Code URI") raise Exception("Failed to parse QR Code URI")
return int(res) return int(res)
def dpp_nfc_uri(self, uri):
res = self.request("DPP_NFC_URI " + uri)
if "FAIL" in res:
raise Exception("Failed to parse NFC URI")
return int(res)
def dpp_bootstrap_gen(self, type="qrcode", chan=None, mac=None, info=None, def dpp_bootstrap_gen(self, type="qrcode", chan=None, mac=None, info=None,
curve=None, key=None): curve=None, key=None):
cmd = "DPP_BOOTSTRAP_GEN type=" + type cmd = "DPP_BOOTSTRAP_GEN type=" + type
@ -466,9 +472,13 @@ def dpp_listen(self, freq, netrole=None, qr=None, role=None):
def dpp_auth_init(self, peer=None, uri=None, conf=None, configurator=None, def dpp_auth_init(self, peer=None, uri=None, conf=None, configurator=None,
extra=None, own=None, role=None, neg_freq=None, extra=None, own=None, role=None, neg_freq=None,
ssid=None, passphrase=None, expect_fail=False): ssid=None, passphrase=None, expect_fail=False,
conn_status=False, nfc_uri=None):
cmd = "DPP_AUTH_INIT" cmd = "DPP_AUTH_INIT"
if peer is None: if peer is None:
if nfc_uri:
peer = self.dpp_nfc_uri(nfc_uri)
else:
peer = self.dpp_qr_code(uri) peer = self.dpp_qr_code(uri)
cmd += " peer=%d" % peer cmd += " peer=%d" % peer
if own is not None: if own is not None:
@ -487,6 +497,8 @@ def dpp_auth_init(self, peer=None, uri=None, conf=None, configurator=None,
cmd += " ssid=" + binascii.hexlify(ssid.encode()).decode() cmd += " ssid=" + binascii.hexlify(ssid.encode()).decode()
if passphrase: if passphrase:
cmd += " pass=" + binascii.hexlify(passphrase.encode()).decode() cmd += " pass=" + binascii.hexlify(passphrase.encode()).decode()
if conn_status:
cmd += " conn_status=1"
res = self.request(cmd) res = self.request(cmd)
if expect_fail: if expect_fail:
if "FAIL" not in res: if "FAIL" not in res:

View File

@ -881,6 +881,7 @@ def test_ap_wpa2_eap_sim_ext_anonymous(dev, apdev):
try: try:
run_ap_wpa2_eap_sim_ext_anonymous(dev, "anonymous@example.org") run_ap_wpa2_eap_sim_ext_anonymous(dev, "anonymous@example.org")
run_ap_wpa2_eap_sim_ext_anonymous(dev, "@example.org") run_ap_wpa2_eap_sim_ext_anonymous(dev, "@example.org")
run_ap_wpa2_eap_sim_ext_anonymous(dev, "example.org!anonymous@otherexample.org")
finally: finally:
dev[0].request("SET external_sim 0") dev[0].request("SET external_sim 0")

View File

@ -137,7 +137,7 @@ def run_roams(dev, apdev, hapd0, hapd1, ssid, passphrase, over_ds=False,
sae_password_id=None, sae_and_psk=False, pmksa_caching=False, sae_password_id=None, sae_and_psk=False, pmksa_caching=False,
roam_with_reassoc=False, also_non_ft=False, only_one_way=False, roam_with_reassoc=False, also_non_ft=False, only_one_way=False,
wait_before_roam=0, return_after_initial=False, ieee80211w="1", wait_before_roam=0, return_after_initial=False, ieee80211w="1",
sae_transition=False): sae_transition=False, beacon_prot=False):
logger.info("Connect to first AP") logger.info("Connect to first AP")
copts = {} copts = {}
@ -151,6 +151,8 @@ def run_roams(dev, apdev, hapd0, hapd1, ssid, passphrase, over_ds=False,
copts["group_mgmt"] = group_mgmt copts["group_mgmt"] = group_mgmt
if ocv: if ocv:
copts["ocv"] = ocv copts["ocv"] = ocv
if beacon_prot:
copts["beacon_prot"] = "1"
if eap: if eap:
if pmksa_caching: if pmksa_caching:
copts["ft_eap_pmksa_caching"] = "1" copts["ft_eap_pmksa_caching"] = "1"
@ -221,6 +223,10 @@ def run_roams(dev, apdev, hapd0, hapd1, ssid, passphrase, over_ds=False,
dev.scan_for_bss(ap2['bssid'], freq="2412") dev.scan_for_bss(ap2['bssid'], freq="2412")
for i in range(0, roams): for i in range(0, roams):
dev.dump_monitor()
hapd1ap.dump_monitor()
hapd2ap.dump_monitor()
# Roaming artificially fast can make data test fail because the key is # Roaming artificially fast can make data test fail because the key is
# set later. # set later.
time.sleep(0.01) time.sleep(0.01)
@ -239,11 +245,18 @@ def run_roams(dev, apdev, hapd0, hapd1, ssid, passphrase, over_ds=False,
raise Exception("Did not connect to correct AP") raise Exception("Did not connect to correct AP")
if (i == 0 or i == roams - 1) and test_connectivity: if (i == 0 or i == roams - 1) and test_connectivity:
hapd2ap.wait_sta() hapd2ap.wait_sta()
dev.dump_monitor()
hapd1ap.dump_monitor()
hapd2ap.dump_monitor()
if conndev: if conndev:
hwsim_utils.test_connectivity_iface(dev, hapd2ap, conndev) hwsim_utils.test_connectivity_iface(dev, hapd2ap, conndev)
else: else:
hwsim_utils.test_connectivity(dev, hapd2ap) hwsim_utils.test_connectivity(dev, hapd2ap)
dev.dump_monitor()
hapd1ap.dump_monitor()
hapd2ap.dump_monitor()
if only_one_way: if only_one_way:
return return
# Roaming artificially fast can make data test fail because the key is # Roaming artificially fast can make data test fail because the key is
@ -262,6 +275,9 @@ def run_roams(dev, apdev, hapd0, hapd1, ssid, passphrase, over_ds=False,
raise Exception("Did not connect to correct AP") raise Exception("Did not connect to correct AP")
if (i == 0 or i == roams - 1) and test_connectivity: if (i == 0 or i == roams - 1) and test_connectivity:
hapd1ap.wait_sta() hapd1ap.wait_sta()
dev.dump_monitor()
hapd1ap.dump_monitor()
hapd2ap.dump_monitor()
if conndev: if conndev:
hwsim_utils.test_connectivity_iface(dev, hapd1ap, conndev) hwsim_utils.test_connectivity_iface(dev, hapd1ap, conndev)
else: else:
@ -477,15 +493,23 @@ def test_ap_ft_pmf_required_over_ds(dev, apdev):
"""WPA2-PSK-FT AP with PMF required on STA (over DS)""" """WPA2-PSK-FT AP with PMF required on STA (over DS)"""
run_ap_ft_pmf(dev, apdev, "2", over_ds=True) run_ap_ft_pmf(dev, apdev, "2", over_ds=True)
def run_ap_ft_pmf(dev, apdev, ieee80211w, over_ds=False): def test_ap_ft_pmf_beacon_prot(dev, apdev):
"""WPA2-PSK-FT AP with PMF and beacon protection"""
run_ap_ft_pmf(dev, apdev, "1", beacon_prot=True)
def run_ap_ft_pmf(dev, apdev, ieee80211w, over_ds=False, beacon_prot=False):
ssid = "test-ft" ssid = "test-ft"
passphrase = "12345678" passphrase = "12345678"
params = ft_params1(ssid=ssid, passphrase=passphrase) params = ft_params1(ssid=ssid, passphrase=passphrase)
params["ieee80211w"] = "2" params["ieee80211w"] = "2"
if beacon_prot:
params["beacon_prot"] = "1"
hapd0 = hostapd.add_ap(apdev[0], params) hapd0 = hostapd.add_ap(apdev[0], params)
params = ft_params2(ssid=ssid, passphrase=passphrase) params = ft_params2(ssid=ssid, passphrase=passphrase)
params["ieee80211w"] = "2" params["ieee80211w"] = "2"
if beacon_prot:
params["beacon_prot"] = "1"
hapd1 = hostapd.add_ap(apdev[1], params) hapd1 = hostapd.add_ap(apdev[1], params)
Wlantest.setup(hapd0) Wlantest.setup(hapd0)
@ -494,7 +518,7 @@ def run_ap_ft_pmf(dev, apdev, ieee80211w, over_ds=False):
wt.add_passphrase(passphrase) wt.add_passphrase(passphrase)
run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase,
ieee80211w=ieee80211w, over_ds=over_ds) ieee80211w=ieee80211w, over_ds=over_ds, beacon_prot=beacon_prot)
def test_ap_ft_pmf_required_mismatch(dev, apdev): def test_ap_ft_pmf_required_mismatch(dev, apdev):
"""WPA2-PSK-FT AP with PMF required on STA but AP2 not enabling PMF""" """WPA2-PSK-FT AP with PMF required on STA but AP2 not enabling PMF"""

View File

@ -1370,13 +1370,15 @@ def test_ap_ht40_scan_broken_ap(dev, apdev):
hwsim_utils.test_connectivity(dev[1], hapd2) hwsim_utils.test_connectivity(dev[1], hapd2)
def run_op_class(dev, apdev, hw_mode, channel, country, ht_capab, sec_chan, def run_op_class(dev, apdev, hw_mode, channel, country, ht_capab, sec_chan,
freq, opclass): freq, opclass, use_op_class=False):
clear_scan_cache(apdev[0]) clear_scan_cache(apdev[0])
try: try:
params = {"ssid": "test-ht40", params = {"ssid": "test-ht40",
"hw_mode": hw_mode, "hw_mode": hw_mode,
"channel": channel, "channel": channel,
"ht_capab": ht_capab} "ht_capab": ht_capab}
if use_op_class:
params['op_class'] = str(opclass)
if country: if country:
params['country_code'] = country params['country_code'] = country
hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False) hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False)
@ -1397,6 +1399,7 @@ def run_op_class(dev, apdev, hw_mode, channel, country, ht_capab, sec_chan,
if rx_opclass != opclass: if rx_opclass != opclass:
raise Exception("Unexpected operating class: %d" % rx_opclass) raise Exception("Unexpected operating class: %d" % rx_opclass)
hapd.disable() hapd.disable()
hapd.dump_monitor()
dev[0].request("REMOVE_NETWORK all") dev[0].request("REMOVE_NETWORK all")
dev[0].request("ABORT_SCAN") dev[0].request("ABORT_SCAN")
dev[0].wait_disconnected() dev[0].wait_disconnected()
@ -1407,67 +1410,99 @@ def run_op_class(dev, apdev, hw_mode, channel, country, ht_capab, sec_chan,
def test_ap_ht_op_class_81(dev, apdev): def test_ap_ht_op_class_81(dev, apdev):
"""HT20 on operationg class 81""" """HT20 on operationg class 81"""
run_op_class(dev, apdev, "g", "1", None, "", "0", "2412", 81) for o in [False, True]:
run_op_class(dev, apdev, "g", "1", None, "", "0", "2412", 81,
use_op_class=o)
def test_ap_ht_op_class_83(dev, apdev): def test_ap_ht_op_class_83(dev, apdev):
"""HT40 on operationg class 83""" """HT40 on operationg class 83"""
run_op_class(dev, apdev, "g", "1", None, "[HT40+]", "1", "2412", 83) for o in [False, True]:
run_op_class(dev, apdev, "g", "1", None, "[HT40+]", "1", "2412", 83,
use_op_class=o)
def test_ap_ht_op_class_84(dev, apdev): def test_ap_ht_op_class_84(dev, apdev):
"""HT40 on operationg class 84""" """HT40 on operationg class 84"""
run_op_class(dev, apdev, "g", "11", None, "[HT40-]", "-1", "2462", 84) for o in [False, True]:
run_op_class(dev, apdev, "g", "11", None, "[HT40-]", "-1", "2462", 84,
use_op_class=o)
def test_ap_ht_op_class_115(dev, apdev): def test_ap_ht_op_class_115(dev, apdev):
"""HT20 on operationg class 115""" """HT20 on operationg class 115"""
run_op_class(dev, apdev, "a", "36", "FI", "", "0", "5180", 115) for o in [False, True]:
run_op_class(dev, apdev, "a", "36", "FI", "", "0", "5180", 115,
use_op_class=o)
def test_ap_ht_op_class_116(dev, apdev): def test_ap_ht_op_class_116(dev, apdev):
"""HT40 on operationg class 116""" """HT40 on operationg class 116"""
run_op_class(dev, apdev, "a", "36", "FI", "[HT40+]", "1", "5180", 116) for o in [False, True]:
run_op_class(dev, apdev, "a", "36", "FI", "[HT40+]", "1", "5180", 116,
use_op_class=o)
def test_ap_ht_op_class_117(dev, apdev): def test_ap_ht_op_class_117(dev, apdev):
"""HT40 on operationg class 117""" """HT40 on operationg class 117"""
run_op_class(dev, apdev, "a", "40", "FI", "[HT40-]", "-1", "5200", 117) for o in [False, True]:
run_op_class(dev, apdev, "a", "40", "FI", "[HT40-]", "-1", "5200", 117,
use_op_class=o)
def test_ap_ht_op_class_118(dev, apdev): def test_ap_ht_op_class_118(dev, apdev):
"""HT20 on operationg class 118""" """HT20 on operationg class 118"""
run_op_class(dev, apdev, "a", "60", "RS", "", "0", "5300", 118) for o in [False, True]:
run_op_class(dev, apdev, "a", "60", "PA", "", "0", "5300", 118,
use_op_class=o)
def test_ap_ht_op_class_119(dev, apdev): def test_ap_ht_op_class_119(dev, apdev):
"""HT40 on operationg class 119""" """HT40 on operationg class 119"""
run_op_class(dev, apdev, "a", "60", "RS", "[HT40+]", "1", "5300", 119) for o in [False, True]:
run_op_class(dev, apdev, "a", "60", "PA", "[HT40+]", "1", "5300", 119,
use_op_class=o)
def test_ap_ht_op_class_120(dev, apdev): def test_ap_ht_op_class_120(dev, apdev):
"""HT40 on operationg class 120""" """HT40 on operationg class 120"""
run_op_class(dev, apdev, "a", "64", "RS", "[HT40-]", "-1", "5320", 120) for o in [False, True]:
run_op_class(dev, apdev, "a", "64", "PA", "[HT40-]", "-1", "5320", 120,
use_op_class=o)
def test_ap_ht_op_class_121(dev, apdev): def test_ap_ht_op_class_121(dev, apdev):
"""HT20 on operationg class 121""" """HT20 on operationg class 121"""
run_op_class(dev, apdev, "a", "100", "ZA", "", "0", "5500", 121) for o in [False, True]:
run_op_class(dev, apdev, "a", "100", "ZA", "", "0", "5500", 121,
use_op_class=o)
def test_ap_ht_op_class_122(dev, apdev): def test_ap_ht_op_class_122(dev, apdev):
"""HT40 on operationg class 122""" """HT40 on operationg class 122"""
run_op_class(dev, apdev, "a", "100", "ZA", "[HT40+]", "1", "5500", 122) for o in [False, True]:
run_op_class(dev, apdev, "a", "100", "ZA", "[HT40+]", "1", "5500", 122,
use_op_class=o)
def test_ap_ht_op_class_123(dev, apdev): def test_ap_ht_op_class_123(dev, apdev):
"""HT40 on operationg class 123""" """HT40 on operationg class 123"""
run_op_class(dev, apdev, "a", "104", "ZA", "[HT40-]", "-1", "5520", 123) for o in [False, True]:
run_op_class(dev, apdev, "a", "104", "ZA", "[HT40-]", "-1", "5520", 123,
use_op_class=o)
def test_ap_ht_op_class_124(dev, apdev): def test_ap_ht_op_class_124(dev, apdev):
"""HT20 on operationg class 124""" """HT20 on operationg class 124"""
run_op_class(dev, apdev, "a", "149", "US", "", "0", "5745", 124) for o in [False, True]:
run_op_class(dev, apdev, "a", "149", "US", "", "0", "5745", 124,
use_op_class=o)
def test_ap_ht_op_class_125(dev, apdev): def test_ap_ht_op_class_125(dev, apdev):
"""HT20 on operationg class 125""" """HT20 on operationg class 125"""
run_op_class(dev, apdev, "a", "169", "NL", "", "0", "5845", 125) for o in [False, True]:
run_op_class(dev, apdev, "a", "169", "NL", "", "0", "5845", 125,
use_op_class=o)
def test_ap_ht_op_class_126(dev, apdev): def test_ap_ht_op_class_126(dev, apdev):
"""HT40 on operationg class 126""" """HT40 on operationg class 126"""
run_op_class(dev, apdev, "a", "149", "US", "[HT40+]", "1", "5745", 126) for o in [False, True]:
run_op_class(dev, apdev, "a", "149", "US", "[HT40+]", "1", "5745", 126,
use_op_class=o)
def test_ap_ht_op_class_127(dev, apdev): def test_ap_ht_op_class_127(dev, apdev):
"""HT40 on operationg class 127""" """HT40 on operationg class 127"""
run_op_class(dev, apdev, "a", "153", "US", "[HT40-]", "-1", "5765", 127) for o in [False, True]:
run_op_class(dev, apdev, "a", "153", "US", "[HT40-]", "-1", "5765", 127,
use_op_class=o)
def test_ap_ht40_plus_minus1(dev, apdev): def test_ap_ht40_plus_minus1(dev, apdev):
"""HT40 with both plus and minus allowed (1)""" """HT40 with both plus and minus allowed (1)"""

View File

@ -909,3 +909,64 @@ def test_ap_notify_mgmt_frames_disabled(dev, apdev):
ev = hapd.wait_event(["AP-MGMT-FRAME-RECEIVED"], timeout=0.1) ev = hapd.wait_event(["AP-MGMT-FRAME-RECEIVED"], timeout=0.1)
if ev is not None: if ev is not None:
raise Exception("Unexpected AP-MGMT-FRAME-RECEIVED") raise Exception("Unexpected AP-MGMT-FRAME-RECEIVED")
def test_ap_airtime_policy_static(dev, apdev):
"""Airtime policy - static"""
ssid = "test-wpa2-psk"
passphrase = 'qwertyuiop'
params = hostapd.wpa2_params(ssid=ssid, passphrase=passphrase)
params['airtime_mode'] = "1"
params['airtime_update_interval'] = "200"
params['airtime_sta_weight'] = dev[0].own_addr() + " 512"
hapd = hostapd.add_ap(apdev[0], params)
dev[0].connect(ssid, psk=passphrase, scan_freq="2412")
dev[1].connect(ssid, psk=passphrase, scan_freq="2412")
time.sleep(1)
def test_ap_airtime_policy_per_bss_dynamic(dev, apdev):
"""Airtime policy - per-BSS dynamic"""
ssid = "test-wpa2-psk"
passphrase = 'qwertyuiop'
params = hostapd.wpa2_params(ssid=ssid, passphrase=passphrase)
params['airtime_mode'] = "2"
params['airtime_update_interval'] = "200"
params['airtime_bss_weight'] = "2"
hapd = hostapd.add_ap(apdev[0], params)
dev[0].connect(ssid, psk=passphrase, scan_freq="2412")
dev[1].connect(ssid, psk=passphrase, scan_freq="2412")
time.sleep(1)
def test_ap_airtime_policy_per_bss_limit(dev, apdev):
"""Airtime policy - per-BSS limit"""
ssid = "test-wpa2-psk"
passphrase = 'qwertyuiop'
params = hostapd.wpa2_params(ssid=ssid, passphrase=passphrase)
params['airtime_mode'] = "3"
params['airtime_update_interval'] = "200"
params['airtime_bss_weight'] = "2"
params['airtime_bss_limit'] = "1"
hapd = hostapd.add_ap(apdev[0], params)
dev[0].connect(ssid, psk=passphrase, scan_freq="2412")
dev[1].connect(ssid, psk=passphrase, scan_freq="2412")
time.sleep(1)
hapd.set("force_backlog_bytes", "1")
time.sleep(1)
def test_ap_airtime_policy_per_bss_limit_invalid(dev, apdev):
"""Airtime policy - per-BSS limit (invalid)"""
ssid = "test-wpa2-psk"
passphrase = 'qwertyuiop'
params = hostapd.wpa2_params(ssid=ssid, passphrase=passphrase)
params['airtime_mode'] = "3"
params['airtime_update_interval'] = "0"
params['airtime_bss_weight'] = "2"
params['airtime_bss_limit'] = "1"
hapd = hostapd.add_ap(apdev[0], params, no_enable=True)
if "FAIL" not in hapd.request("ENABLE"):
raise Exception("Invalid airtime policy configuration accepted")
hapd.set("airtime_update_interval", "200")
hapd.enable()
hapd.set("airtime_update_interval", "0")
dev[0].connect(ssid, psk=passphrase, scan_freq="2412")
dev[1].connect(ssid, psk=passphrase, scan_freq="2412")
time.sleep(1)

View File

@ -500,6 +500,22 @@ def test_ap_wpa2_gtk_rekey_request(dev, apdev):
raise Exception("GTK rekey timed out") raise Exception("GTK rekey timed out")
hwsim_utils.test_connectivity(dev[0], hapd) hwsim_utils.test_connectivity(dev[0], hapd)
def test_ap_wpa2_gtk_rekey_failure(dev, apdev):
"""WPA2-PSK AP and GTK rekey failure"""
ssid = "test-wpa2-psk"
passphrase = 'qwertyuiop'
params = hostapd.wpa2_params(ssid=ssid, passphrase=passphrase)
hapd = hostapd.add_ap(apdev[0], params)
dev[0].connect(ssid, psk=passphrase, scan_freq="2412")
with fail_test(hapd, 1, "wpa_group_config_group_keys"):
if "OK" not in hapd.request("REKEY_GTK"):
raise Exception("REKEY_GTK failed")
wait_fail_trigger(hapd, "GET_FAIL")
ev = dev[0].wait_event(["WPA: Group rekeying completed"], timeout=2)
if ev is None:
raise Exception("GTK rekey timed out")
dev[0].wait_disconnected()
@remote_compatible @remote_compatible
def test_ap_wpa_gtk_rekey(dev, apdev): def test_ap_wpa_gtk_rekey(dev, apdev):
"""WPA-PSK/TKIP AP and GTK rekey enforced by AP""" """WPA-PSK/TKIP AP and GTK rekey enforced by AP"""

View File

@ -403,3 +403,35 @@ def _test_ap_track_taxonomy(dev, apdev):
raise Exception("Unexpected SIGNATURE prefix") raise Exception("Unexpected SIGNATURE prefix")
if "|assoc:" not in res: if "|assoc:" not in res:
raise Exception("Missing assoc info in SIGNATURE") raise Exception("Missing assoc info in SIGNATURE")
def test_ap_track_taxonomy_5g(dev, apdev):
"""AP tracking STA taxonomy (5 GHz)"""
try:
_test_ap_track_taxonomy_5g(dev, apdev)
finally:
subprocess.call(['iw', 'reg', 'set', '00'])
dev[0].flush_scan_cache()
def _test_ap_track_taxonomy_5g(dev, apdev):
params = {"ssid": "track",
"country_code": "US",
"hw_mode": "a",
"channel": "40",
"track_sta_max_num": "2"}
hapd = hostapd.add_ap(apdev[0], params)
bssid = apdev[0]['bssid']
dev[0].scan_for_bss(bssid, freq=5200, force_scan=True)
addr0 = dev[0].own_addr()
dev[0].connect("track", key_mgmt="NONE", scan_freq="5200")
res = hapd.request("SIGNATURE " + addr0)
logger.info("sta0: " + res)
if not res.startswith("wifi4|probe:"):
raise Exception("Unexpected SIGNATURE prefix")
if "|assoc:" not in res:
raise Exception("Missing assoc info in SIGNATURE")
if ",htcap:" not in res:
raise Exception("Missing HT info in SIGNATURE")
if ",vhtcap:" not in res:
raise Exception("Missing VHT info in SIGNATURE")

View File

@ -44,10 +44,12 @@
from utils import * from utils import *
from test_ap_eap import int_eap_server_params from test_ap_eap import int_eap_server_params
def wps_start_ap(apdev, ssid="test-wps-conf"): def wps_start_ap(apdev, ssid="test-wps-conf", extra_cred=None):
params = {"ssid": ssid, "eap_server": "1", "wps_state": "2", params = {"ssid": ssid, "eap_server": "1", "wps_state": "2",
"wpa_passphrase": "12345678", "wpa": "2", "wpa_passphrase": "12345678", "wpa": "2",
"wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP"} "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP"}
if extra_cred:
params['extra_cred'] = extra_cred
return hostapd.add_ap(apdev, params) return hostapd.add_ap(apdev, params)
@remote_compatible @remote_compatible
@ -1067,6 +1069,43 @@ def test_ap_wps_pbc_overlap_2sta(dev, apdev):
dev[0].flush_scan_cache() dev[0].flush_scan_cache()
dev[1].flush_scan_cache() dev[1].flush_scan_cache()
def test_ap_wps_pbc_session_workaround(dev, apdev):
"""WPS PBC session overlap workaround"""
ssid = "test-wps-pbc-overlap"
hapd = hostapd.add_ap(apdev[0],
{"ssid": ssid, "eap_server": "1", "wps_state": "2",
"wpa_passphrase": "12345678", "wpa": "2",
"wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP"})
bssid = hapd.own_addr()
hapd.request("WPS_PBC")
dev[0].scan_for_bss(bssid, freq="2412")
dev[0].request("WPS_PBC " + bssid)
dev[0].wait_connected(timeout=30)
dev[0].request("REMOVE_NETWORK all")
dev[0].wait_disconnected(timeout=30)
dev[0].dump_monitor()
# Trigger AP/Registrar to ignore PBC activation immediately after
# successfully completed provisioning
dev[0].request("WPS_PBC " + bssid)
ev = dev[0].wait_event(["CTRL-EVENT-SCAN-RESULTS"], timeout=10)
if ev is None:
raise Exception("No scan results reported")
dev[0].request("WPS_CANCEL")
dev[0].dump_monitor()
# Verify that PBC session overlap does not prevent connection
hapd.request("WPS_PBC")
dev[1].scan_for_bss(bssid, freq="2412")
dev[1].request("WPS_PBC " + bssid)
dev[1].wait_connected()
dev[1].request("REMOVE_NETWORK all")
dev[1].wait_disconnected()
hapd.request("DISABLE")
dev[0].flush_scan_cache()
dev[1].flush_scan_cache()
@remote_compatible @remote_compatible
def test_ap_wps_cancel(dev, apdev): def test_ap_wps_cancel(dev, apdev):
"""WPS AP cancelling enabled config method""" """WPS AP cancelling enabled config method"""
@ -4358,10 +4397,12 @@ def wps_er_stop(dev, sock, server, on_alloc_fail=False):
raise Exception("No WPS-ER-AP-REMOVE event on max-age timeout") raise Exception("No WPS-ER-AP-REMOVE event on max-age timeout")
dev.request("WPS_ER_STOP") dev.request("WPS_ER_STOP")
def run_wps_er_proto_test(dev, handler, no_event_url=False, location_url=None): def run_wps_er_proto_test(dev, handler, no_event_url=False, location_url=None,
max_age=1):
try: try:
uuid = '27ea801a-9e5c-4e73-bd82-f89cbcd10d7e' uuid = '27ea801a-9e5c-4e73-bd82-f89cbcd10d7e'
server, sock = wps_er_start(dev, handler, location_url=location_url) server, sock = wps_er_start(dev, handler, location_url=location_url,
max_age=max_age)
global wps_event_url global wps_event_url
wps_event_url = None wps_event_url = None
server.handle_request() server.handle_request()
@ -5105,6 +5146,15 @@ def handle_upnp_info(self):
run_wps_er_proto_test(dev[0], WPSAPHTTPServer_req_as_resp, run_wps_er_proto_test(dev[0], WPSAPHTTPServer_req_as_resp,
no_event_url=True) no_event_url=True)
def test_ap_wps_er_http_client_timeout(dev, apdev):
"""WPS ER and HTTP client timeout"""
class WPSAPHTTPServer_timeout(WPSAPHTTPServer):
def handle_upnp_info(self):
time.sleep(31)
self.wfile.write(b"GET / HTTP/1.1\r\n\r\n")
run_wps_er_proto_test(dev[0], WPSAPHTTPServer_timeout,
no_event_url=True, max_age=60)
def test_ap_wps_init_oom(dev, apdev): def test_ap_wps_init_oom(dev, apdev):
"""wps_init OOM cases""" """wps_init OOM cases"""
ssid = "test-wps" ssid = "test-wps"
@ -10464,3 +10514,55 @@ def run_ap_wps_ap_timeout(dev, apdev, cmd):
logger.info("BSS after timeout: " + str(bss)) logger.info("BSS after timeout: " + str(bss))
if bss['ie'].endswith("0106ffffffffffff"): if bss['ie'].endswith("0106ffffffffffff"):
raise Exception("Authorized MAC not removed") raise Exception("Authorized MAC not removed")
def test_ap_wps_er_unsubscribe_errors(dev, apdev):
"""WPS ER and UNSUBSCRIBE errors"""
start_wps_ap(apdev[0])
tests = [(1, "http_client_url_parse;wps_er_ap_unsubscribe"),
(1, "wpabuf_alloc;wps_er_ap_unsubscribe"),
(1, "http_client_addr;wps_er_ap_unsubscribe")]
try:
for count, func in tests:
start_wps_er(dev[0])
with alloc_fail(dev[0], count, func):
dev[0].request("WPS_ER_STOP")
dev[0].request("REMOVE_NETWORK all")
dev[0].wait_disconnected()
dev[0].dump_monitor()
finally:
dev[0].request("WPS_ER_STOP")
def start_wps_ap(apdev):
ssid = "wps-er-ap-config"
ap_pin = "12345670"
ap_uuid = "27ea801a-9e5c-4e73-bd82-f89cbcd10d7e"
params = {"ssid": ssid, "eap_server": "1", "wps_state": "2",
"wpa_passphrase": "12345678", "wpa": "2",
"wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP",
"device_name": "Wireless AP", "manufacturer": "Company",
"model_name": "WAP", "model_number": "123",
"serial_number": "12345", "device_type": "6-0050F204-1",
"os_version": "01020300",
"config_methods": "label push_button",
"ap_pin": ap_pin, "uuid": ap_uuid, "upnp_iface": "lo"}
hostapd.add_ap(apdev, params)
def start_wps_er(dev):
ssid = "wps-er-ap-config"
dev.connect(ssid, psk="12345678", scan_freq="2412")
dev.request("WPS_ER_START ifname=lo")
ev = dev.wait_event(["WPS-ER-AP-ADD"], timeout=15)
if ev is None:
raise Exception("AP discovery timed out")
def test_ap_wps_registrar_init_errors(dev, apdev):
"""WPS Registrar init errors"""
hapd = wps_start_ap(apdev[0], extra_cred="wps-mixed-cred")
hapd.disable()
tests = [(1, "wps_registrar_init"),
(1, "wpabuf_alloc_copy;wps_registrar_init"),
(1, "wps_set_ie;wps_registrar_init")]
for count, func in tests:
with alloc_fail(hapd, count, func):
if "FAIL" not in hapd.request("ENABLE"):
raise Exception("ENABLE succeeded unexpectedly")

View File

@ -2581,6 +2581,14 @@ def test_dpp_pkex_hostapd_errors(dev, apdev):
def test_dpp_hostapd_configurator(dev, apdev): def test_dpp_hostapd_configurator(dev, apdev):
"""DPP with hostapd as configurator/initiator""" """DPP with hostapd as configurator/initiator"""
run_dpp_hostapd_configurator(dev, apdev)
def test_dpp_hostapd_configurator_enrollee_v1(dev, apdev):
"""DPP with hostapd as configurator/initiator with v1 enrollee"""
dev[0].set("dpp_version_override", "1")
run_dpp_hostapd_configurator(dev, apdev)
def run_dpp_hostapd_configurator(dev, apdev):
check_dpp_capab(dev[0]) check_dpp_capab(dev[0])
hapd = hostapd.add_ap(apdev[0], {"ssid": "unconfigured", hapd = hostapd.add_ap(apdev[0], {"ssid": "unconfigured",
"channel": "1"}) "channel": "1"})
@ -2640,6 +2648,340 @@ def test_dpp_hostapd_configurator_fragmentation(dev, apdev):
wait_auth_success(dev[0], hapd, configurator=hapd, enrollee=dev[0], wait_auth_success(dev[0], hapd, configurator=hapd, enrollee=dev[0],
stop_responder=True) stop_responder=True)
def test_dpp_hostapd_enrollee_fragmentation(dev, apdev):
"""DPP and hostapd as Enrollee with GAS fragmentation"""
check_dpp_capab(dev[0])
hapd = hostapd.add_ap(apdev[0], {"ssid": "unconfigured",
"channel": "6"})
check_dpp_capab(hapd)
conf_id = dev[0].dpp_configurator_add()
id0 = dev[0].dpp_bootstrap_gen(chan="81/6", mac=True)
uri0 = dev[0].request("DPP_BOOTSTRAP_GET_URI %d" % id0)
conf = '{"wi-fi_tech":"infra", "discovery":{"ssid":"test"},"cred":{"akm":"psk","pass":"secret passphrase"}}' + 3000*' '
dev[0].set("dpp_config_obj_override", conf)
dev[0].set("dpp_configurator_params",
" conf=ap-dpp configurator=%d" % conf_id)
dev[0].dpp_listen(2437, role="configurator")
hapd.dpp_auth_init(uri=uri0, role="enrollee")
wait_auth_success(dev[0], hapd, configurator=dev[0], enrollee=hapd,
stop_responder=True)
def test_dpp_hostapd_enrollee_gas_timeout(dev, apdev):
"""DPP and hostapd as Enrollee with GAS timeout"""
check_dpp_capab(dev[0])
hapd = hostapd.add_ap(apdev[0], {"ssid": "unconfigured",
"channel": "6"})
check_dpp_capab(hapd)
conf_id = dev[0].dpp_configurator_add()
id0 = dev[0].dpp_bootstrap_gen(chan="81/6", mac=True)
uri0 = dev[0].request("DPP_BOOTSTRAP_GET_URI %d" % id0)
conf = '{"wi-fi_tech":"infra", "discovery":{"ssid":"test"},"cred":{"akm":"psk","pass":"secret passphrase"}}' + 3000*' '
dev[0].set("dpp_config_obj_override", conf)
dev[0].set("dpp_configurator_params",
"conf=ap-dpp configurator=%d" % conf_id)
dev[0].set("ext_mgmt_frame_handling", "1")
dev[0].dpp_listen(2437, role="configurator")
hapd.dpp_auth_init(uri=uri0, role="enrollee")
process_dpp_frames(dev[0])
ev = hapd.wait_event(["GAS-QUERY-DONE"], timeout=10)
if "result=TIMEOUT" not in ev:
raise Exception("GAS timeout not reported")
def test_dpp_hostapd_enrollee_gas_timeout_comeback(dev, apdev):
"""DPP and hostapd as Enrollee with GAS timeout during comeback"""
check_dpp_capab(dev[0])
hapd = hostapd.add_ap(apdev[0], {"ssid": "unconfigured",
"channel": "6"})
check_dpp_capab(hapd)
conf_id = dev[0].dpp_configurator_add()
id0 = dev[0].dpp_bootstrap_gen(chan="81/6", mac=True)
uri0 = dev[0].request("DPP_BOOTSTRAP_GET_URI %d" % id0)
conf = '{"wi-fi_tech":"infra", "discovery":{"ssid":"test"},"cred":{"akm":"psk","pass":"secret passphrase"}}' + 3000*' '
dev[0].set("dpp_config_obj_override", conf)
dev[0].set("dpp_configurator_params",
"conf=ap-dpp configurator=%d" % conf_id)
dev[0].set("ext_mgmt_frame_handling", "1")
dev[0].dpp_listen(2437, role="configurator")
hapd.dpp_auth_init(uri=uri0, role="enrollee")
process_dpp_frames(dev[0], count=4)
ev = hapd.wait_event(["GAS-QUERY-DONE"], timeout=10)
if "result=TIMEOUT" not in ev:
raise Exception("GAS timeout not reported")
def process_dpp_frames(dev, count=3):
for i in range(count):
msg = dev.mgmt_rx()
cmd = "MGMT_RX_PROCESS freq={} datarate={} ssi_signal={} frame={}".format(msg['freq'], msg['datarate'], msg['ssi_signal'], binascii.hexlify(msg['frame']).decode())
if "OK" not in dev.request(cmd):
raise Exception("MGMT_RX_PROCESS failed")
def test_dpp_hostapd_enrollee_gas_errors(dev, apdev):
"""DPP and hostapd as Enrollee with GAS query local errors"""
check_dpp_capab(dev[0])
hapd = hostapd.add_ap(apdev[0], {"ssid": "unconfigured",
"channel": "6"})
check_dpp_capab(hapd)
conf_id = dev[0].dpp_configurator_add()
id0 = dev[0].dpp_bootstrap_gen(chan="81/6", mac=True)
uri0 = dev[0].request("DPP_BOOTSTRAP_GET_URI %d" % id0)
dev[0].set("dpp_configurator_params",
"conf=ap-dpp configurator=%d" % conf_id)
dev[0].set("ext_mgmt_frame_handling", "1")
# GAS without comeback
tests = [(1, "gas_query_append;gas_query_rx_initial", 3, True),
(1, "gas_query_rx_initial", 3, True),
(1, "gas_query_tx_initial_req", 2, True),
(1, "gas_query_ap_req", 2, False)]
for count, func, frame_count, wait_ev in tests:
dev[0].request("DPP_STOP_LISTEN")
dev[0].dpp_listen(2437, role="configurator")
dev[0].dump_monitor()
hapd.dump_monitor()
with alloc_fail(hapd, count, func):
hapd.dpp_auth_init(uri=uri0, role="enrollee")
process_dpp_frames(dev[0], count=frame_count)
if wait_ev:
ev = hapd.wait_event(["GAS-QUERY-DONE"], timeout=10)
if not ev or "result=INTERNAL_ERROR" not in ev:
raise Exception("Unexpect GAS query result: " + str(ev))
# GAS with comeback
conf = '{"wi-fi_tech":"infra", "discovery":{"ssid":"test"},"cred":{"akm":"psk","pass":"secret passphrase"}}' + 3000*' '
dev[0].set("dpp_config_obj_override", conf)
tests = [(1, "gas_query_append;gas_query_rx_comeback", 4),
(1, "wpabuf_alloc;gas_query_tx_comeback_req", 3),
(1, "hostapd_drv_send_action;gas_query_tx_comeback_req", 3)]
for count, func, frame_count in tests:
dev[0].request("DPP_STOP_LISTEN")
dev[0].dpp_listen(2437, role="configurator")
dev[0].dump_monitor()
hapd.dump_monitor()
with alloc_fail(hapd, count, func):
hapd.dpp_auth_init(uri=uri0, role="enrollee")
process_dpp_frames(dev[0], count=frame_count)
ev = hapd.wait_event(["GAS-QUERY-DONE"], timeout=10)
if not ev or "result=INTERNAL_ERROR" not in ev:
raise Exception("Unexpect GAS query result: " + str(ev))
def test_dpp_hostapd_enrollee_gas_proto(dev, apdev):
"""DPP and hostapd as Enrollee with GAS query protocol testing"""
check_dpp_capab(dev[0])
hapd = hostapd.add_ap(apdev[0], {"ssid": "unconfigured",
"channel": "6"})
check_dpp_capab(hapd)
bssid = hapd.own_addr()
conf_id = dev[0].dpp_configurator_add()
id0 = dev[0].dpp_bootstrap_gen(chan="81/6", mac=True)
uri0 = dev[0].request("DPP_BOOTSTRAP_GET_URI %d" % id0)
dev[0].set("dpp_configurator_params",
"conf=ap-dpp configurator=%d" % conf_id)
conf = '{"wi-fi_tech":"infra", "discovery":{"ssid":"test"},"cred":{"akm":"psk","pass":"secret passphrase"}}' + 3000*' '
dev[0].set("dpp_config_obj_override", conf)
dev[0].set("ext_mgmt_frame_handling", "1")
dev[0].dpp_listen(2437, role="configurator")
hapd.dpp_auth_init(uri=uri0, role="enrollee")
process_dpp_frames(dev[0], count=3)
msg = dev[0].mgmt_rx()
payload = msg['payload']
dialog_token, = struct.unpack('B', payload[2:3])
hdr = struct.pack('<BBBHBH', 4, 13, dialog_token, 0, 0x80, 0)
# GAS: Advertisement Protocol changed between initial and comeback response from 02:00:00:00:00:00
adv_proto = "6c087fdd05506f9a1a02"
action = binascii.hexlify(hdr).decode() + adv_proto + "0300" + "001001"
cmd = "MGMT_TX %s %s freq=2437 wait_time=100 action=%s" % (bssid, bssid, action)
dev[0].request(cmd)
ev = hapd.wait_event(["GAS-QUERY-DONE"], timeout=10)
if not ev or "result=PEER_ERROR" not in ev:
raise Exception("Unexpect GAS query result: " + str(ev))
dev[0].request("DPP_STOP_LISTEN")
hapd.dump_monitor()
dev[0].dump_monitor()
dev[0].dpp_listen(2437, role="configurator")
hapd.dpp_auth_init(uri=uri0, role="enrollee")
process_dpp_frames(dev[0], count=3)
msg = dev[0].mgmt_rx()
payload = msg['payload']
dialog_token, = struct.unpack('B', payload[2:3])
# Another comeback delay
hdr = struct.pack('<BBBHBH', 4, 13, dialog_token, 0, 0x80, 1)
adv_proto = "6c087fdd05506f9a1a01"
action = binascii.hexlify(hdr).decode() + adv_proto + "0300" + "001001"
cmd = "MGMT_TX %s %s freq=2437 wait_time=100 action=%s" % (bssid, bssid, action)
dev[0].request(cmd)
msg = dev[0].mgmt_rx()
hdr = struct.pack('<BBBHBH', 4, 13, dialog_token, 0, 0x81, 1)
# GAS: Invalid comeback response with non-zero frag_id and comeback_delay from 02:00:00:00:00:00
action = binascii.hexlify(hdr).decode() + adv_proto + "0300" + "001001"
cmd = "MGMT_TX %s %s freq=2437 wait_time=100 action=%s" % (bssid, bssid, action)
dev[0].request(cmd)
ev = hapd.wait_event(["GAS-QUERY-DONE"], timeout=10)
if not ev or "result=PEER_ERROR" not in ev:
raise Exception("Unexpect GAS query result: " + str(ev))
dev[0].request("DPP_STOP_LISTEN")
hapd.dump_monitor()
dev[0].dump_monitor()
dev[0].dpp_listen(2437, role="configurator")
hapd.dpp_auth_init(uri=uri0, role="enrollee")
process_dpp_frames(dev[0], count=3)
msg = dev[0].mgmt_rx()
payload = msg['payload']
dialog_token, = struct.unpack('B', payload[2:3])
# Valid comeback response
hdr = struct.pack('<BBBHBH', 4, 13, dialog_token, 0, 0x80, 0)
action = binascii.hexlify(hdr).decode() + adv_proto + "0300" + "001001"
cmd = "MGMT_TX %s %s freq=2437 wait_time=100 action=%s" % (bssid, bssid, action)
dev[0].request(cmd)
msg = dev[0].mgmt_rx()
# GAS: Drop frame as possible retry of previous fragment
hdr = struct.pack('<BBBHBH', 4, 13, dialog_token, 0, 0x80, 0)
action = binascii.hexlify(hdr).decode() + adv_proto + "0300" + "001001"
cmd = "MGMT_TX %s %s freq=2437 wait_time=100 action=%s" % (bssid, bssid, action)
dev[0].request(cmd)
# GAS: Unexpected frag_id in response from 02:00:00:00:00:00
hdr = struct.pack('<BBBHBH', 4, 13, dialog_token, 0, 0x82, 0)
action = binascii.hexlify(hdr).decode() + adv_proto + "0300" + "001001"
cmd = "MGMT_TX %s %s freq=2437 wait_time=100 action=%s" % (bssid, bssid, action)
dev[0].request(cmd)
ev = hapd.wait_event(["GAS-QUERY-DONE"], timeout=10)
if not ev or "result=PEER_ERROR" not in ev:
raise Exception("Unexpect GAS query result: " + str(ev))
dev[0].request("DPP_STOP_LISTEN")
hapd.dump_monitor()
dev[0].dump_monitor()
dev[0].dpp_listen(2437, role="configurator")
hapd.dpp_auth_init(uri=uri0, role="enrollee")
process_dpp_frames(dev[0], count=3)
msg = dev[0].mgmt_rx()
payload = msg['payload']
dialog_token, = struct.unpack('B', payload[2:3])
# GAS: Unexpected initial response from 02:00:00:00:00:00 dialog token 3 when waiting for comeback response
hdr = struct.pack('<BBBHBH', 4, 11, dialog_token, 0, 0x80, 0)
action = binascii.hexlify(hdr).decode() + adv_proto + "0300" + "001001"
cmd = "MGMT_TX %s %s freq=2437 wait_time=100 action=%s" % (bssid, bssid, action)
dev[0].request(cmd)
# GAS: Allow non-zero status for outstanding comeback response
hdr = struct.pack('<BBBHBH', 4, 13, dialog_token, 95, 0x80, 0)
# GAS: Ignore 1 octets of extra data after Query Response from 02:00:00:00:00:00
action = binascii.hexlify(hdr).decode() + adv_proto + "0300" + "001001" + "ff"
cmd = "MGMT_TX %s %s freq=2437 wait_time=100 action=%s" % (bssid, bssid, action)
dev[0].request(cmd)
# GAS: No pending query found for 02:00:00:00:00:00 dialog token 4
hdr = struct.pack('<BBBHBH', 4, 13, (dialog_token + 1) % 256, 0, 0x80, 0)
action = binascii.hexlify(hdr).decode() + adv_proto + "0300" + "001001"
cmd = "MGMT_TX %s %s freq=2437 wait_time=100 action=%s" % (bssid, bssid, action)
dev[0].request(cmd)
# GAS: Truncated Query Response in response from 02:00:00:00:00:00
hdr = struct.pack('<BBBHBH', 4, 13, dialog_token, 0, 0x81, 0)
action = binascii.hexlify(hdr).decode() + adv_proto + "0300" + "0010"
cmd = "MGMT_TX %s %s freq=2437 wait_time=100 action=%s" % (bssid, bssid, action)
dev[0].request(cmd)
# GAS: No room for GAS Response Length
hdr = struct.pack('<BBBHBH', 4, 13, dialog_token, 0, 0x81, 0)
action = binascii.hexlify(hdr).decode() + adv_proto + "03"
cmd = "MGMT_TX %s %s freq=2437 wait_time=100 action=%s" % (bssid, bssid, action)
dev[0].request(cmd)
# GAS: Unexpected Advertisement Protocol element ID 0 in response from 02:00:00:00:00:00
hdr = struct.pack('<BBBHBH', 4, 13, dialog_token, 0, 0x81, 0)
adv_proto_broken = "0000"
action = binascii.hexlify(hdr).decode() + adv_proto_broken + "0300" + "001001"
cmd = "MGMT_TX %s %s freq=2437 wait_time=100 action=%s" % (bssid, bssid, action)
dev[0].request(cmd)
# GAS: No room for Advertisement Protocol element in the response from 02:00:00:00:00:00
hdr = struct.pack('<BBBHBH', 4, 13, dialog_token, 0, 0x81, 0)
adv_proto_broken = "00ff"
action = binascii.hexlify(hdr).decode() + adv_proto_broken + "0300" + "001001"
cmd = "MGMT_TX %s %s freq=2437 wait_time=100 action=%s" % (bssid, bssid, action)
dev[0].request(cmd)
# No room for Comeback Delay
hdr = struct.pack('<BBBHBB', 4, 13, dialog_token, 0, 0x81, 0)
action = binascii.hexlify(hdr).decode()
cmd = "MGMT_TX %s %s freq=2437 wait_time=100 action=%s" % (bssid, bssid, action)
dev[0].request(cmd)
# No room for frag_id
hdr = struct.pack('<BBBH', 4, 13, dialog_token, 0)
action = binascii.hexlify(hdr).decode()
cmd = "MGMT_TX %s %s freq=2437 wait_time=100 action=%s" % (bssid, bssid, action)
dev[0].request(cmd)
# GAS: Query to 02:00:00:00:00:00 dialog token 3 failed - status code 1
hdr = struct.pack('<BBBHBH', 4, 13, dialog_token, 1, 0x81, 0)
action = binascii.hexlify(hdr).decode() + adv_proto + "0300" + "001001"
cmd = "MGMT_TX %s %s freq=2437 wait_time=100 action=%s" % (bssid, bssid, action)
dev[0].request(cmd)
ev = hapd.wait_event(["GAS-QUERY-DONE"], timeout=10)
if not ev or "result=FAILURE" not in ev:
raise Exception("Unexpect GAS query result: " + str(ev))
dev[0].request("DPP_STOP_LISTEN")
hapd.dump_monitor()
dev[0].dump_monitor()
dev[0].dpp_listen(2437, role="configurator")
hapd.dpp_auth_init(uri=uri0, role="enrollee")
process_dpp_frames(dev[0], count=2)
msg = dev[0].mgmt_rx()
payload = msg['payload']
dialog_token, = struct.unpack('B', payload[2:3])
# Unexpected comeback delay
hdr = struct.pack('<BBBHBH', 4, 13, dialog_token, 0, 0x80, 0)
adv_proto = "6c087fdd05506f9a1a01"
action = binascii.hexlify(hdr).decode() + adv_proto + "0300" + "001001"
cmd = "MGMT_TX %s %s freq=2437 wait_time=100 action=%s" % (bssid, bssid, action)
dev[0].request(cmd)
# GAS: Query to 02:00:00:00:00:00 dialog token 3 failed - status code 1
hdr = struct.pack('<BBBHBH', 4, 11, dialog_token, 1, 0x80, 0)
action = binascii.hexlify(hdr).decode() + adv_proto + "0300" + "001001"
cmd = "MGMT_TX %s %s freq=2437 wait_time=100 action=%s" % (bssid, bssid, action)
dev[0].request(cmd)
ev = hapd.wait_event(["GAS-QUERY-DONE"], timeout=10)
if not ev or "result=FAILURE" not in ev:
raise Exception("Unexpect GAS query result: " + str(ev))
dev[0].request("DPP_STOP_LISTEN")
hapd.dump_monitor()
dev[0].dump_monitor()
def test_dpp_hostapd_enrollee_gas_tx_status_errors(dev, apdev):
"""DPP and hostapd as Enrollee with GAS TX status errors"""
check_dpp_capab(dev[0])
hapd = hostapd.add_ap(apdev[0], {"ssid": "unconfigured",
"channel": "6"})
check_dpp_capab(hapd)
conf_id = dev[0].dpp_configurator_add()
id0 = dev[0].dpp_bootstrap_gen(chan="81/6", mac=True)
uri0 = dev[0].request("DPP_BOOTSTRAP_GET_URI %d" % id0)
conf = '{"wi-fi_tech":"infra", "discovery":{"ssid":"test"},"cred":{"akm":"psk","pass":"secret passphrase"}}' + 3000*' '
dev[0].set("dpp_config_obj_override", conf)
dev[0].set("dpp_configurator_params",
"conf=ap-dpp configurator=%d" % conf_id)
dev[0].set("ext_mgmt_frame_handling", "1")
dev[0].dpp_listen(2437, role="configurator")
hapd.dpp_auth_init(uri=uri0, role="enrollee")
process_dpp_frames(dev[0], count=3)
hapd.set("ext_mgmt_frame_handling", "1")
# GAS: TX status for unexpected destination
frame = "d0003a01" + "222222222222"
frame += hapd.own_addr().replace(':', '') + "ffffffffffff"
frame += "5000" + "040a"
hapd.request("MGMT_TX_STATUS_PROCESS stype=13 ok=1 buf=" + frame)
# GAS: No ACK to GAS request
frame = "d0003a01" + dev[0].own_addr().replace(':', '')
frame += hapd.own_addr().replace(':', '') + "ffffffffffff"
frame += "5000" + "040a"
hapd.request("MGMT_TX_STATUS_PROCESS stype=13 ok=0 buf=" + frame)
ev = hapd.wait_event(["GAS-QUERY-DONE"], timeout=10)
if "result=TIMEOUT" not in ev:
raise Exception("GAS timeout not reported")
# GAS: Unexpected TX status: dst=02:00:00:00:00:00 ok=1 - no query in progress
hapd.request("MGMT_TX_STATUS_PROCESS stype=13 ok=1 buf=" + frame)
hapd.set("ext_mgmt_frame_handling", "0")
def test_dpp_hostapd_configurator_override_objects(dev, apdev): def test_dpp_hostapd_configurator_override_objects(dev, apdev):
"""DPP with hostapd as configurator and override objects""" """DPP with hostapd as configurator and override objects"""
check_dpp_capab(dev[0]) check_dpp_capab(dev[0])
@ -5303,6 +5645,49 @@ def run_dpp_conn_status(dev, apdev, result=0, assoc_reject=False):
if result == 10 and "channel_list=" not in ev: if result == 10 and "channel_list=" not in ev:
raise Exception("Channel list not reported for no-AP") raise Exception("Channel list not reported for no-AP")
def test_dpp_conn_status_success_hostapd_configurator(dev, apdev):
"""DPP connection status - success with hostapd as Configurator"""
try:
run_dpp_conn_status_hostapd_configurator(dev, apdev)
finally:
dev[0].set("dpp_config_processing", "0", allow_fail=True)
def run_dpp_conn_status_hostapd_configurator(dev, apdev):
check_dpp_capab(dev[0])
hapd = hostapd.add_ap(apdev[0], {"ssid": "unconfigured",
"channel": "1"})
check_dpp_capab(hapd)
conf_id = hapd.dpp_configurator_add()
cmd = "DPP_CONFIGURATOR_SIGN conf=ap-dpp configurator=%d" % conf_id
res = hapd.request(cmd)
if "FAIL" in res:
raise Exception("Failed to generate own configuration")
update_hapd_config(hapd)
id0 = dev[0].dpp_bootstrap_gen(chan="81/1", mac=True)
uri0 = dev[0].request("DPP_BOOTSTRAP_GET_URI %d" % id0)
id1 = hapd.dpp_qr_code(uri0)
res = hapd.request("DPP_BOOTSTRAP_INFO %d" % id1)
if "FAIL" in res:
raise Exception("DPP_BOOTSTRAP_INFO failed")
if "type=QRCODE" not in res:
raise Exception("DPP_BOOTSTRAP_INFO did not report correct type")
if "mac_addr=" + dev[0].own_addr() not in res:
raise Exception("DPP_BOOTSTRAP_INFO did not report correct mac_addr")
dev[0].set("dpp_config_processing", "2")
dev[0].dpp_listen(2412)
hapd.dpp_auth_init(peer=id1, configurator=conf_id, conf="sta-dpp",
conn_status=True)
res = wait_auth_success(dev[0], hapd, configurator=hapd, enrollee=dev[0])
if 'wait_conn_status' not in res:
raise Exception("Configurator did not request connection status")
ev = hapd.wait_event(["DPP-CONN-STATUS-RESULT"], timeout=20)
if ev is None:
raise Exception("No connection status reported")
if "result=0" not in ev:
raise Exception("Unexpected connection status: " + ev)
def test_dpp_mud_url(dev, apdev): def test_dpp_mud_url(dev, apdev):
"""DPP MUD URL""" """DPP MUD URL"""
check_dpp_capab(dev[0]) check_dpp_capab(dev[0])
@ -5408,6 +5793,24 @@ def test_dpp_nfc_uri_hostapd(dev, apdev):
dev[0].dpp_auth_init(nfc_uri=uri, configurator=conf_id, conf="ap-dpp") dev[0].dpp_auth_init(nfc_uri=uri, configurator=conf_id, conf="ap-dpp")
wait_auth_success(hapd, dev[0], configurator=dev[0], enrollee=hapd) wait_auth_success(hapd, dev[0], configurator=dev[0], enrollee=hapd)
def test_dpp_nfc_uri_hostapd_tag_read(dev, apdev):
"""DPP bootstrapping via NFC URI record (hostapd reading tag)"""
check_dpp_capab(dev[0])
hapd = hostapd.add_ap(apdev[0], {"ssid": "unconfigured"})
check_dpp_capab(hapd)
id = dev[0].dpp_bootstrap_gen(type="nfc-uri", chan="81/1", mac=True)
uri = dev[0].request("DPP_BOOTSTRAP_GET_URI %d" % id)
info = dev[0].request("DPP_BOOTSTRAP_INFO %d" % id)
conf_id = dev[0].dpp_configurator_add()
dev[0].set("dpp_configurator_params",
"conf=ap-dpp configurator=%d" % conf_id)
dev[0].dpp_listen(2412)
hapd.dpp_auth_init(nfc_uri=uri, role="enrollee")
wait_auth_success(dev[0], hapd, configurator=dev[0], enrollee=hapd)
def test_dpp_nfc_negotiated_handover(dev, apdev): def test_dpp_nfc_negotiated_handover(dev, apdev):
"""DPP bootstrapping via NFC negotiated handover""" """DPP bootstrapping via NFC negotiated handover"""
run_dpp_nfc_negotiated_handover(dev) run_dpp_nfc_negotiated_handover(dev)
@ -5471,6 +5874,40 @@ def run_dpp_nfc_negotiated_handover(dev, curve0=None, curve1=None,
conf=conf) conf=conf)
wait_auth_success(dev[1], dev[0], configurator=dev[0], enrollee=dev[1]) wait_auth_success(dev[1], dev[0], configurator=dev[0], enrollee=dev[1])
def test_dpp_nfc_errors_hostapd(dev, apdev):
"""DPP NFC operation failures in hostapd"""
check_dpp_capab(dev[0])
check_dpp_capab(dev[1])
id0 = dev[0].dpp_bootstrap_gen(type="nfc-uri", chan="81/11", mac=True,
curve="secp384r1")
uri0 = dev[0].request("DPP_BOOTSTRAP_GET_URI %d" % id0)
hapd = hostapd.add_ap(apdev[0], {"ssid": "unconfigured",
"channel": "6"})
check_dpp_capab(hapd)
id_h = hapd.dpp_bootstrap_gen(type="nfc-uri", chan="81/6", mac=True)
uri_h = hapd.request("DPP_BOOTSTRAP_GET_URI %d" % id_h)
tests = ["",
"own=123456789",
"own=%d" % id_h,
"own=%d uri=%s" % (id_h, "foo")]
for t in tests:
if "FAIL" not in hapd.request("DPP_NFC_HANDOVER_REQ " + t):
raise Exception("Invalid DPP_NFC_HANDOVER_REQ accepted")
if "FAIL" not in hapd.request("DPP_NFC_HANDOVER_SEL " + t):
raise Exception("Invalid DPP_NFC_HANDOVER_SEL accepted")
# DPP: Peer (NFC Handover Selector) used different curve
if "FAIL" not in hapd.request("DPP_NFC_HANDOVER_SEL own=%d uri=%s" % (id_h, uri0)):
raise Exception("Invalid DPP_NFC_HANDOVER_SEL accepted")
# DPP: No common channel found
if "FAIL" not in hapd.request("DPP_NFC_HANDOVER_REQ own=%d uri=%s" % (id_h, uri0)):
raise Exception("DPP_NFC_HANDOVER_REQ with local error accepted")
def test_dpp_with_p2p_device(dev, apdev): def test_dpp_with_p2p_device(dev, apdev):
"""DPP exchange when driver uses a separate P2P Device interface""" """DPP exchange when driver uses a separate P2P Device interface"""
check_dpp_capab(dev[0]) check_dpp_capab(dev[0])
@ -5648,6 +6085,74 @@ def test_dpp_chirp_ap(dev, apdev):
timeout=20) timeout=20)
update_hapd_config(hapd) update_hapd_config(hapd)
@long_duration_test
def test_dpp_chirp_ap_5g(dev, apdev):
"""DPP chirp by an AP on 5 GHz"""
check_dpp_capab(dev[0], min_ver=2)
try:
hapd = None
hapd2 = None
params = {"ssid": "unconfigured",
"country_code": "US",
"hw_mode": "a",
"channel": "40",
"dpp_configurator_connectivity": "1"}
hapd2 = hostapd.add_ap(apdev[1], params)
check_dpp_capab(hapd2, min_ver=2)
params = {"ssid": "unconfigured",
"country_code": "US",
"hw_mode": "a",
"channel": "36",
"start_disabled": "1"}
hapd = hostapd.add_ap(apdev[0], params)
check_dpp_capab(hapd, min_ver=2)
id_h = hapd.dpp_bootstrap_gen(chan="81/1", mac=True)
uri = hapd.request("DPP_BOOTSTRAP_GET_URI %d" % id_h)
# First, check chirping iteration and timeout
if "OK" not in hapd.request("DPP_CHIRP own=%d iter=2" % id_h):
raise Exception("DPP_CHIRP failed")
chan1 = 0
chan6 = 0
chan40 = 0
chan149 = 0
for i in range(30):
ev = hapd.wait_event(["DPP-CHIRP-STOPPED", "DPP-TX "], timeout=60)
if ev is None:
raise Exception("DPP chirp stop not reported")
if "DPP-CHIRP-STOPPED" in ev:
break
if "type=13" not in ev:
continue
freq = int(ev.split(' ')[2].split('=')[1])
if freq == 2412:
chan1 += 1
elif freq == 2437:
chan6 += 1
elif freq == 5200:
chan40 += 1
elif freq == 5745:
chan149 += 1
if not chan1 or not chan6 or not chan40 or not chan149:
raise Exception("Chirp not sent on all channels")
# Then, check successful chirping
conf_id = dev[0].dpp_configurator_add()
idc = dev[0].dpp_qr_code(uri)
dev[0].dpp_bootstrap_set(idc, conf="ap-dpp", configurator=conf_id)
dev[0].dpp_listen(5200)
if "OK" not in hapd.request("DPP_CHIRP own=%d iter=5" % id_h):
raise Exception("DPP_CHIRP failed")
wait_auth_success(hapd, dev[0], configurator=dev[0], enrollee=hapd,
timeout=20)
update_hapd_config(hapd)
finally:
clear_regdom(hapd, dev)
def test_dpp_chirp_ap_errors(dev, apdev): def test_dpp_chirp_ap_errors(dev, apdev):
"""DPP chirp errors in hostapd""" """DPP chirp errors in hostapd"""
hapd = hostapd.add_ap(apdev[0], {"ssid": "unconfigured", hapd = hostapd.add_ap(apdev[0], {"ssid": "unconfigured",
@ -5779,6 +6284,25 @@ def test_dpp_pfs_ap_0_sta_ver1(dev, apdev):
hapd = start_dpp_pfs_ap(apdev[0], 0) hapd = start_dpp_pfs_ap(apdev[0], 0)
run_dpp_pfs_sta(dev[0], 0, pfs_expected=False) run_dpp_pfs_sta(dev[0], 0, pfs_expected=False)
def test_dpp_pfs_errors(dev, apdev):
"""DPP PFS error cases"""
check_dpp_capab(dev[0], min_ver=2)
hapd = start_dpp_pfs_ap(apdev[0], 1)
tests = [(1, "dpp_pfs_init"),
(1, "crypto_ecdh_init;dpp_pfs_init"),
(1, "wpabuf_alloc;dpp_pfs_init")]
for count, func in tests:
with alloc_fail(dev[0], count, func):
dev[0].connect("dpp", key_mgmt="DPP", scan_freq="2412",
ieee80211w="2", dpp_pfs="1",
dpp_csign=params1_csign,
dpp_connector=params1_sta_connector,
dpp_netaccesskey=params1_sta_netaccesskey)
dev[0].request("REMOVE_NETWORK all")
dev[0].wait_disconnected()
dev[0].dump_monitor()
hapd.dump_monitor()
def test_dpp_reconfig_connector(dev, apdev): def test_dpp_reconfig_connector(dev, apdev):
"""DPP reconfiguration connector""" """DPP reconfiguration connector"""
try: try:

View File

@ -2869,10 +2869,10 @@ def test_eap_proto_eke_errors(dev, apdev):
(1, "os_get_random;eap_eke_dhcomp", None), (1, "os_get_random;eap_eke_dhcomp", None),
(1, "aes_128_cbc_encrypt;eap_eke_dhcomp", None), (1, "aes_128_cbc_encrypt;eap_eke_dhcomp", None),
(1, "aes_128_cbc_decrypt;eap_eke_shared_secret", None), (1, "aes_128_cbc_decrypt;eap_eke_shared_secret", None),
(1, "eap_eke_prf;eap_eke_shared_secret", None), (1, "hmac_sha256_vector;eap_eke_shared_secret", None),
(1, "eap_eke_prfplus;eap_eke_derive_ke_ki", None), (1, "eap_eke_prf_hmac_sha256;eap_eke_derive_ke_ki", None),
(1, "eap_eke_prfplus;eap_eke_derive_ka", None), (1, "eap_eke_prf_hmac_sha256;eap_eke_derive_ka", None),
(1, "eap_eke_prfplus;eap_eke_derive_msk", None), (1, "eap_eke_prf_hmac_sha256;eap_eke_derive_msk", None),
(1, "os_get_random;eap_eke_prot", None), (1, "os_get_random;eap_eke_prot", None),
(1, "aes_128_cbc_decrypt;eap_eke_decrypt_prot", None), (1, "aes_128_cbc_decrypt;eap_eke_decrypt_prot", None),
(1, "eap_eke_derive_key;eap_eke_process_commit", None), (1, "eap_eke_derive_key;eap_eke_process_commit", None),

View File

@ -2358,3 +2358,54 @@ def test_fils_discovery_frame(dev, apdev, params):
eap="PSK", identity="psk.user@example.com", eap="PSK", identity="psk.user@example.com",
password_hex="0123456789abcdef0123456789abcdef", password_hex="0123456789abcdef0123456789abcdef",
erp="1", scan_freq="2412") erp="1", scan_freq="2412")
def test_fils_offload_to_driver(dev, apdev, params):
"""FILS offload to driver"""
check_fils_capa(dev[0])
check_erp_capa(dev[0])
run_fils_offload_to_driver(dev[0], apdev, params)
def test_fils_offload_to_driver2(dev, apdev, params):
"""FILS offload to driver"""
wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
wpas.interface_add("wlan5", drv_params="force_connect_cmd=1")
run_fils_offload_to_driver(wpas, apdev, params)
def run_fils_offload_to_driver(dev, apdev, params):
start_erp_as(msk_dump=os.path.join(params['logdir'], "msk.lst"))
bssid = apdev[0]['bssid']
params = hostapd.wpa2_eap_params(ssid="fils")
params['wpa_key_mgmt'] = "FILS-SHA256"
params['auth_server_port'] = "18128"
params['erp_send_reauth_start'] = '1'
params['erp_domain'] = 'example.com'
params['fils_realm'] = 'example.com'
params['disable_pmksa_caching'] = '1'
hapd = hostapd.add_ap(apdev[0]['ifname'], params)
dev.request("ERP_FLUSH")
id = dev.connect("fils", key_mgmt="FILS-SHA256",
eap="PSK", identity="psk.user@example.com",
password_hex="0123456789abcdef0123456789abcdef",
erp="1", scan_freq="2412")
p = "freq=2412 authorized=1 fils_erp_next_seq_num=4"
if "OK" not in dev.request("DRIVER_EVENT ASSOC " + p):
raise Exception("DRIVER_EVENT ASSOC did not succeed")
dev.wait_connected()
dev.request("DISCONNECT")
dev.wait_disconnected()
dev.dump_monitor()
dev.select_network(id, freq=2412)
dev.wait_connected()
dev.dump_monitor()
# This does not really work properly with SME-in-wpa_supplicant case
p = "freq=2412 authorized=1 fils_erp_next_seq_num=4"
if "OK" not in dev.request("DRIVER_EVENT ASSOC " + p):
raise Exception("DRIVER_EVENT ASSOC did not succeed")
dev.wait_connected()

View File

@ -24,7 +24,7 @@ def test_he_open(dev, apdev):
"he_mu_edca_ac_be_ecwmax": "15"} "he_mu_edca_ac_be_ecwmax": "15"}
hapd = hostapd.add_ap(apdev[0], params) hapd = hostapd.add_ap(apdev[0], params)
if hapd.get_status_field("ieee80211ax") != "1": if hapd.get_status_field("ieee80211ax") != "1":
raise Exception("STATUS did not indicate ieee80211ac=1") raise Exception("STATUS did not indicate ieee80211ax=1")
dev[0].connect("he", key_mgmt="NONE", scan_freq="2412") dev[0].connect("he", key_mgmt="NONE", scan_freq="2412")
sta = hapd.get_sta(dev[0].own_addr()) sta = hapd.get_sta(dev[0].own_addr())
if "[HE]" not in sta['flags']: if "[HE]" not in sta['flags']:
@ -94,7 +94,25 @@ def test_he_params(dev, apdev):
"he_oper_centr_freq_seg1_idx": "0"} "he_oper_centr_freq_seg1_idx": "0"}
hapd = hostapd.add_ap(apdev[0], params) hapd = hostapd.add_ap(apdev[0], params)
if hapd.get_status_field("ieee80211ax") != "1": if hapd.get_status_field("ieee80211ax") != "1":
raise Exception("STATUS did not indicate ieee80211ac=1") raise Exception("STATUS did not indicate ieee80211ax=1")
dev[0].connect("he", key_mgmt="NONE", scan_freq="2412")
def test_he_spr_params(dev, apdev):
"""HE AP spatial reuse parameters"""
params = {"ssid": "he",
"ieee80211ax": "1",
"he_spr_sr_control": "12",
"he_spr_non_srg_obss_pd_max_offset": "1",
"he_spr_srg_obss_pd_min_offset": "2",
"he_spr_srg_obss_pd_max_offset": "3",
"he_spr_srg_bss_colors": "1 2 10 63",
"he_spr_srg_partial_bssid": "0 1 3 63",
"he_oper_chwidth": "0",
"he_oper_centr_freq_seg0_idx": "1",
"he_oper_centr_freq_seg1_idx": "0"}
hapd = hostapd.add_ap(apdev[0], params)
if hapd.get_status_field("ieee80211ax") != "1":
raise Exception("STATUS did not indicate ieee80211ax=1")
dev[0].connect("he", key_mgmt="NONE", scan_freq="2412") dev[0].connect("he", key_mgmt="NONE", scan_freq="2412")
def he_supported(): def he_supported():

View File

@ -245,6 +245,23 @@ def test_ieee8021x_held(dev, apdev):
dev[0].request("SET EAPOL::maxStart 3") dev[0].request("SET EAPOL::maxStart 3")
dev[0].request("SET EAPOL::heldPeriod 60") dev[0].request("SET EAPOL::heldPeriod 60")
def test_ieee8021x_force_unauth(dev, apdev):
"""IEEE 802.1X and FORCE_UNAUTH state"""
params = hostapd.radius_params()
params["ssid"] = "ieee8021x-open"
params["ieee8021x"] = "1"
hapd = hostapd.add_ap(apdev[0], params)
bssid = apdev[0]['bssid']
dev[0].connect("ieee8021x-open", key_mgmt="IEEE8021X", eapol_flags="0",
eap="PSK", identity="psk.user@example.com",
password_hex="0123456789abcdef0123456789abcdef",
scan_freq="2412")
dev[0].request("SET EAPOL::portControl ForceUnauthorized")
pae = dev[0].get_status_field('Supplicant PAE state')
dev[0].wait_disconnected()
dev[0].request("SET EAPOL::portControl Auto")
def send_eapol_key(dev, bssid, signkey, frame_start, frame_end): def send_eapol_key(dev, bssid, signkey, frame_start, frame_end):
zero_sign = "00000000000000000000000000000000" zero_sign = "00000000000000000000000000000000"
frame = frame_start + zero_sign + frame_end frame = frame_start + zero_sign + frame_end

View File

@ -543,15 +543,32 @@ def test_mbo_without_pmf(dev, apdev):
def test_mbo_without_pmf_workaround(dev, apdev): def test_mbo_without_pmf_workaround(dev, apdev):
"""MBO and WPA2 without PMF on misbehaving AP""" """MBO and WPA2 without PMF on misbehaving AP"""
ssid = "test-wnm-mbo" ssid = "test-wnm-mbo"
params = {'ssid': ssid, "wpa": '2', params0 = {'ssid': ssid, "wpa": '2',
"wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP", "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP",
"wpa_passphrase": "12345678", "wpa_passphrase": "12345678",
"vendor_elements": "dd07506f9a16010100"} "vendor_elements": "dd07506f9a16010100"}
hapd = hostapd.add_ap(apdev[0], params) params1 = {'ssid': ssid, "mbo": '1', "wpa": '2',
"wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP",
"wpa_passphrase": "12345678", "ieee80211w": "1"}
hapd0 = hostapd.add_ap(apdev[0], params0)
dev[0].connect(ssid, psk="12345678", key_mgmt="WPA-PSK", dev[0].connect(ssid, psk="12345678", key_mgmt="WPA-PSK",
proto="WPA2", ieee80211w="1", scan_freq="2412") proto="WPA2", ieee80211w="1", scan_freq="2412")
hapd.wait_sta() hapd0.wait_sta()
sta = hapd.get_sta(dev[0].own_addr()) sta = hapd0.get_sta(dev[0].own_addr())
ext_capab = bytearray(binascii.unhexlify(sta['ext_capab']))
if ext_capab[2] & 0x08:
raise Exception("STA did not disable BSS Transition capability")
hapd1 = hostapd.add_ap(apdev[1], params1)
dev[0].scan_for_bss(hapd1.own_addr(), 2412, force_scan=True)
dev[0].roam(hapd1.own_addr())
hapd1.wait_sta()
sta = hapd1.get_sta(dev[0].own_addr())
ext_capab = bytearray(binascii.unhexlify(sta['ext_capab']))
if not ext_capab[2] & 0x08:
raise Exception("STA disabled BSS Transition capability")
dev[0].roam(hapd0.own_addr())
hapd0.wait_sta()
sta = hapd0.get_sta(dev[0].own_addr())
ext_capab = bytearray(binascii.unhexlify(sta['ext_capab'])) ext_capab = bytearray(binascii.unhexlify(sta['ext_capab']))
if ext_capab[2] & 0x08: if ext_capab[2] & 0x08:
raise Exception("STA did not disable BSS Transition capability") raise Exception("STA did not disable BSS Transition capability")

231
tests/hwsim/test_mscs.py Normal file
View File

@ -0,0 +1,231 @@
# Test cases for MSCS
# Copyright (c) 2021, Jouni Malinen <j@w1.fi>
#
# This software may be distributed under the terms of the BSD license.
# See README for more details.
import struct
import time
import hostapd
from utils import *
def register_mcsc_req(hapd):
type = 0x00d0
match = "1304"
if "OK" not in hapd.request("REGISTER_FRAME %04x %s" % (type, match)):
raise Exception("Could not register frame reception for Robust AV Streaming")
def handle_mscs_req(hapd, wrong_dialog=False, status_code=0):
msg = hapd.mgmt_rx()
if msg['subtype'] != 13:
logger.info("RX:" + str(msg))
raise Exception("Received unexpected Management frame")
categ, act, dialog_token = struct.unpack('BBB', msg['payload'][0:3])
if categ != 19 or act != 4:
logger.info("RX:" + str(msg))
raise Exception("Received unexpected Action frame")
if wrong_dialog:
dialog_token = (dialog_token + 1) % 256
msg['da'] = msg['sa']
msg['sa'] = hapd.own_addr()
msg['payload'] = struct.pack('<BBBH', 19, 5, dialog_token, status_code)
hapd.mgmt_tx(msg)
ev = hapd.wait_event(["MGMT-TX-STATUS"], timeout=5)
if ev is None or "stype=13 ok=1" not in ev:
raise Exception("No TX status reported")
def wait_mscs_result(dev, expect_status=0):
ev = dev.wait_event(["CTRL-EVENT-MSCS-RESULT"], timeout=1)
if ev is None:
raise Exception("No MSCS result reported")
if "status_code=%d" % expect_status not in ev:
raise Exception("Unexpected MSCS result: " + ev)
def test_mscs_invalid_params(dev, apdev):
"""MSCS command invalid parameters"""
tests = ["",
"add Xp_bitmap=F0 up_limit=7 stream_timeout=12345 frame_classifier=045F",
"add up_bitmap=F0 Xp_limit=7 stream_timeout=12345 frame_classifier=045F",
"add up_bitmap=F0 up_limit=7 Xtream_timeout=12345 frame_classifier=045F",
"add up_bitmap=F0 up_limit=7 stream_timeout=12345 Xrame_classifier=045F",
"add up_bitmap=X0 up_limit=7 stream_timeout=12345 frame_classifier=045F",
"add up_bitmap=F0 up_limit=7 stream_timeout=0 frame_classifier=045F",
"add up_bitmap=F0 up_limit=7 stream_timeout=12345 frame_classifier=X45F",
"change "]
for t in tests:
if "FAIL" not in dev[0].request("MSCS " + t):
raise Exception("Invalid MSCS parameters accepted: " + t)
def test_mscs_without_ap_support(dev, apdev):
"""MSCS without AP support"""
try:
run_mscs_without_ap_support(dev, apdev)
finally:
dev[0].request("MSCS remove")
def run_mscs_without_ap_support(dev, apdev):
params = {"ssid": "mscs",
"ext_capa_mask": 10*"00" + "20"}
hapd = hostapd.add_ap(apdev[0], params)
cmd = "MSCS add up_bitmap=F0 up_limit=7 stream_timeout=12345 frame_classifier=045F"
if "OK" not in dev[0].request(cmd):
raise Exception("Failed to configure MSCS")
dev[0].connect("mscs", key_mgmt="NONE", scan_freq="2412")
cmd = "MSCS change up_bitmap=F0 up_limit=7 stream_timeout=12345 frame_classifier=045F"
if "FAIL" not in dev[0].request(cmd):
raise Exception("MSCS change accepted unexpectedly")
cmd = "MSCS add up_bitmap=F0 up_limit=7 stream_timeout=12345 frame_classifier=045F"
if "FAIL" not in dev[0].request(cmd):
raise Exception("MSCS add accepted unexpectedly")
def test_mscs_post_assoc(dev, apdev):
"""MSCS configuration post-association"""
try:
run_mscs_post_assoc(dev, apdev)
finally:
dev[0].request("MSCS remove")
def run_mscs_post_assoc(dev, apdev):
params = {"ssid": "mscs",
"ext_capa": 10*"00" + "20"}
hapd = hostapd.add_ap(apdev[0], params)
register_mcsc_req(hapd)
dev[0].connect("mscs", key_mgmt="NONE", scan_freq="2412")
hapd.dump_monitor()
hapd.set("ext_mgmt_frame_handling", "1")
cmd = "MSCS change up_bitmap=F0 up_limit=7 stream_timeout=12345 frame_classifier=045F"
if "FAIL" not in dev[0].request(cmd):
raise Exception("MSCS change accepted unexpectedly")
cmd = "MSCS add up_bitmap=F0 up_limit=7 stream_timeout=12345 frame_classifier=045F"
if "OK" not in dev[0].request(cmd):
raise Exception("MSCS add failed")
handle_mscs_req(hapd)
wait_mscs_result(dev[0])
cmd = "MSCS change up_bitmap=F0 up_limit=7 stream_timeout=12345 frame_classifier=045F"
if "OK" not in dev[0].request(cmd):
raise Exception("MSCS change failed")
handle_mscs_req(hapd)
wait_mscs_result(dev[0])
cmd = "MSCS change up_bitmap=F0 up_limit=7 stream_timeout=12345 frame_classifier=045F"
if "OK" not in dev[0].request(cmd):
raise Exception("MSCS change failed")
handle_mscs_req(hapd, status_code=23456)
wait_mscs_result(dev[0], expect_status=23456)
def test_mscs_pre_assoc(dev, apdev):
"""MSCS configuration pre-association"""
try:
run_mscs_pre_assoc(dev, apdev)
finally:
dev[0].request("MSCS remove")
def run_mscs_pre_assoc(dev, apdev):
params = {"ssid": "mscs",
"ext_capa": 10*"00" + "20",
"assocresp_elements": "ff0c5800000000000000" + "01020000"}
hapd = hostapd.add_ap(apdev[0], params)
register_mcsc_req(hapd)
cmd = "MSCS add up_bitmap=F0 up_limit=7 stream_timeout=12345 frame_classifier=045F"
if "OK" not in dev[0].request(cmd):
raise Exception("MSCS add failed")
dev[0].connect("mscs", key_mgmt="NONE", scan_freq="2412",
wait_connect=False)
wait_mscs_result(dev[0])
dev[0].wait_connected()
hapd.set("ext_mgmt_frame_handling", "1")
cmd = "MSCS change up_bitmap=F0 up_limit=7 stream_timeout=12345 frame_classifier=045F"
if "OK" not in dev[0].request(cmd):
raise Exception("MSCS change failed")
handle_mscs_req(hapd)
wait_mscs_result(dev[0])
cmd = "MSCS change up_bitmap=F0 up_limit=7 stream_timeout=12345 frame_classifier=045F"
if "OK" not in dev[0].request(cmd):
raise Exception("MSCS change failed")
handle_mscs_req(hapd, wrong_dialog=True)
ev = dev[0].wait_event(["CTRL-EVENT-MSCS-RESULT"], timeout=1)
if ev is not None:
raise Exception("Unexpected MSCS result reported")
def test_mscs_assoc_failure(dev, apdev):
"""MSCS configuration failure during association exchange"""
try:
run_mscs_assoc_failure(dev, apdev)
finally:
dev[0].request("MSCS remove")
def run_mscs_assoc_failure(dev, apdev):
params = {"ssid": "mscs",
"ext_capa": 10*"00" + "20",
"assocresp_elements": "ff0c5800000000000000" + "01020001"}
hapd = hostapd.add_ap(apdev[0], params)
register_mcsc_req(hapd)
cmd = "MSCS add up_bitmap=F0 up_limit=7 stream_timeout=12345 frame_classifier=045F"
if "OK" not in dev[0].request(cmd):
raise Exception("MSCS add failed")
dev[0].connect("mscs", key_mgmt="NONE", scan_freq="2412",
wait_connect=False)
wait_mscs_result(dev[0], expect_status=256)
dev[0].wait_connected()
dev[0].request("REMOVE_NETWORK all")
dev[0].wait_disconnected()
hapd.dump_monitor()
# No MSCS Status subelement
hapd.set("assocresp_elements", "ff085800000000000000")
dev[0].connect("mscs", key_mgmt="NONE", scan_freq="2412",
wait_connect=False)
ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED", "CTRL-EVENT-MSCS-RESULT"],
timeout=10)
if ev is None:
raise Exception("No connection event")
if "CTRL-EVENT-MSCS-RESULT" in ev:
raise Exception("Unexpected MSCS result")
def test_mscs_local_errors(dev, apdev):
"""MSCS configuration local errors"""
try:
run_mscs_local_errors(dev, apdev)
finally:
dev[0].request("MSCS remove")
def run_mscs_local_errors(dev, apdev):
params = {"ssid": "mscs",
"ext_capa": 10*"00" + "20"}
hapd = hostapd.add_ap(apdev[0], params)
register_mcsc_req(hapd)
dev[0].connect("mscs", key_mgmt="NONE", scan_freq="2412")
hapd.dump_monitor()
hapd.set("ext_mgmt_frame_handling", "1")
for count in range(1, 3):
with alloc_fail(dev[0], count, "wpas_send_mscs_req"):
cmd = "MSCS add up_bitmap=F0 up_limit=7 stream_timeout=12345 frame_classifier=045F"
if "FAIL" not in dev[0].request(cmd):
raise Exception("MSCS add succeeded in error case")

View File

@ -225,6 +225,8 @@ def run_multi_ap_wps(dev, apdev, params, params_backhaul=None, add_apdev=False,
dev[0].cmd_execute(['iw', wpas_apdev['ifname'], 'del']) dev[0].cmd_execute(['iw', wpas_apdev['ifname'], 'del'])
raise raise
return hapd
def test_multi_ap_wps_shared(dev, apdev): def test_multi_ap_wps_shared(dev, apdev):
"""WPS on shared fronthaul/backhaul AP""" """WPS on shared fronthaul/backhaul AP"""
ssid = "multi-ap-wps" ssid = "multi-ap-wps"
@ -233,7 +235,15 @@ def test_multi_ap_wps_shared(dev, apdev):
params.update({"multi_ap": "3", params.update({"multi_ap": "3",
"multi_ap_backhaul_ssid": '"%s"' % ssid, "multi_ap_backhaul_ssid": '"%s"' % ssid,
"multi_ap_backhaul_wpa_passphrase": passphrase}) "multi_ap_backhaul_wpa_passphrase": passphrase})
run_multi_ap_wps(dev, apdev, params) hapd = run_multi_ap_wps(dev, apdev, params)
# Verify WPS parameter update with Multi-AP
if "OK" not in hapd.request("RELOAD"):
raise Exception("hostapd RELOAD failed")
dev[0].wait_disconnected()
dev[0].request("REMOVE_NETWORK all")
hapd.request("WPS_PBC")
dev[0].request("WPS_PBC multi_ap=1")
dev[0].wait_connected(timeout=20)
def test_multi_ap_wps_shared_csa(dev, apdev): def test_multi_ap_wps_shared_csa(dev, apdev):
"""WPS on shared fronthaul/backhaul AP, run CSA""" """WPS on shared fronthaul/backhaul AP, run CSA"""

View File

@ -982,12 +982,22 @@ def check_ocv_failure(dev, frame_txt, frame, addr):
def test_wpa2_ocv_ap_override_eapol_m3(dev, apdev): def test_wpa2_ocv_ap_override_eapol_m3(dev, apdev):
"""OCV on 2.4 GHz and AP override EAPOL-Key msg 3/4""" """OCV on 2.4 GHz and AP override EAPOL-Key msg 3/4"""
run_wpa2_ocv_ap_override_eapol_m3(dev, apdev)
def test_wpa2_ocv_ap_override_eapol_m3_post_enable(dev, apdev):
"""OCV on 2.4 GHz and AP override EAPOL-Key msg 3/4 (post enable)"""
run_wpa2_ocv_ap_override_eapol_m3(dev, apdev, True)
def run_wpa2_ocv_ap_override_eapol_m3(dev, apdev, post_enable=False):
params = {"channel": "1", params = {"channel": "1",
"ieee80211w": "2", "ieee80211w": "2",
"ocv": "1", "ocv": "1"}
"oci_freq_override_eapol_m3": "2462"} if not post_enable:
params["oci_freq_override_eapol_m3"] = "2462"
hapd, ssid, passphrase = ocv_setup_ap(apdev[0], params) hapd, ssid, passphrase = ocv_setup_ap(apdev[0], params)
bssid = hapd.own_addr() bssid = hapd.own_addr()
if post_enable:
hapd.set("oci_freq_override_eapol_m3", "2462")
dev[0].connect(ssid, psk=passphrase, scan_freq="2412", ocv="1", dev[0].connect(ssid, psk=passphrase, scan_freq="2412", ocv="1",
ieee80211w="2", wait_connect=False) ieee80211w="2", wait_connect=False)
@ -999,15 +1009,25 @@ def test_wpa2_ocv_ap_override_eapol_m3(dev, apdev):
def test_wpa2_ocv_ap_override_eapol_g1(dev, apdev): def test_wpa2_ocv_ap_override_eapol_g1(dev, apdev):
"""OCV on 2.4 GHz and AP override EAPOL-Key group msg 1/2""" """OCV on 2.4 GHz and AP override EAPOL-Key group msg 1/2"""
run_wpa2_ocv_ap_override_eapol_g1(dev, apdev)
def test_wpa2_ocv_ap_override_eapol_g1_post_enable(dev, apdev):
"""OCV on 2.4 GHz and AP override EAPOL-Key group msg 1/2 (post enable)"""
run_wpa2_ocv_ap_override_eapol_g1(dev, apdev, True)
def run_wpa2_ocv_ap_override_eapol_g1(dev, apdev, post_enable=False):
params = {"channel": "1", params = {"channel": "1",
"ieee80211w": "2", "ieee80211w": "2",
"ocv": "1", "ocv": "1"}
"oci_freq_override_eapol_g1": "2462"} if not post_enable:
params["oci_freq_override_eapol_g1"] = "2462"
hapd, ssid, passphrase = ocv_setup_ap(apdev[0], params) hapd, ssid, passphrase = ocv_setup_ap(apdev[0], params)
bssid = hapd.own_addr() bssid = hapd.own_addr()
dev[0].connect(ssid, psk=passphrase, scan_freq="2412", ocv="1", dev[0].connect(ssid, psk=passphrase, scan_freq="2412", ocv="1",
ieee80211w="2") ieee80211w="2")
if post_enable:
hapd.set("oci_freq_override_eapol_g1", "2462")
if "OK" not in hapd.request("REKEY_GTK"): if "OK" not in hapd.request("REKEY_GTK"):
raise Exception("REKEY_GTK failed") raise Exception("REKEY_GTK failed")
check_ocv_failure(dev[0], "EAPOL-Key group msg 1/2", "eapol-key-g1", bssid) check_ocv_failure(dev[0], "EAPOL-Key group msg 1/2", "eapol-key-g1", bssid)
@ -1044,6 +1064,13 @@ def test_wpa2_ocv_ap_override_saquery_resp(dev, apdev):
def test_wpa2_ocv_ap_override_fils_assoc(dev, apdev, params): def test_wpa2_ocv_ap_override_fils_assoc(dev, apdev, params):
"""OCV on 2.4 GHz and AP override FILS association""" """OCV on 2.4 GHz and AP override FILS association"""
run_wpa2_ocv_ap_override_fils_assoc(dev, apdev, params)
def test_wpa2_ocv_ap_override_fils_assoc_post_enable(dev, apdev, params):
"""OCV on 2.4 GHz and AP override FILS association (post enable)"""
run_wpa2_ocv_ap_override_fils_assoc(dev, apdev, params, True)
def run_wpa2_ocv_ap_override_fils_assoc(dev, apdev, params, post_enable=False):
check_fils_capa(dev[0]) check_fils_capa(dev[0])
check_erp_capa(dev[0]) check_erp_capa(dev[0])
@ -1060,6 +1087,7 @@ def test_wpa2_ocv_ap_override_fils_assoc(dev, apdev, params):
params['wpa_group_rekey'] = '1' params['wpa_group_rekey'] = '1'
params["ieee80211w"] = "2" params["ieee80211w"] = "2"
params["ocv"] = "1" params["ocv"] = "1"
if not post_enable:
params["oci_freq_override_fils_assoc"] = "2462" params["oci_freq_override_fils_assoc"] = "2462"
try: try:
hapd = hostapd.add_ap(apdev[0], params) hapd = hostapd.add_ap(apdev[0], params)
@ -1068,6 +1096,8 @@ def test_wpa2_ocv_ap_override_fils_assoc(dev, apdev, params):
raise HwsimSkip("OCV not supported") raise HwsimSkip("OCV not supported")
raise raise
bssid = hapd.own_addr() bssid = hapd.own_addr()
if post_enable:
hapd.set("oci_freq_override_fils_assoc", "2462")
dev[0].request("ERP_FLUSH") dev[0].request("ERP_FLUSH")
id = dev[0].connect(ssid, key_mgmt="FILS-SHA256", id = dev[0].connect(ssid, key_mgmt="FILS-SHA256",
eap="PSK", identity="psk.user@example.com", eap="PSK", identity="psk.user@example.com",
@ -1085,12 +1115,20 @@ def test_wpa2_ocv_ap_override_fils_assoc(dev, apdev, params):
def test_wpa2_ocv_ap_override_ft_assoc(dev, apdev): def test_wpa2_ocv_ap_override_ft_assoc(dev, apdev):
"""OCV on 2.4 GHz and AP override FT reassociation""" """OCV on 2.4 GHz and AP override FT reassociation"""
run_wpa2_ocv_ap_override_ft_assoc(dev, apdev)
def test_wpa2_ocv_ap_override_ft_assoc_post_enable(dev, apdev):
"""OCV on 2.4 GHz and AP override FT reassociation (post enable)"""
run_wpa2_ocv_ap_override_ft_assoc(dev, apdev, True)
def run_wpa2_ocv_ap_override_ft_assoc(dev, apdev, post_enable=False):
ssid = "test-wpa2-ocv" ssid = "test-wpa2-ocv"
passphrase = "qwertyuiop" passphrase = "qwertyuiop"
params = ft_params1(ssid=ssid, passphrase=passphrase) params = ft_params1(ssid=ssid, passphrase=passphrase)
params["ieee80211w"] = "2" params["ieee80211w"] = "2"
params["ocv"] = "1" params["ocv"] = "1"
params["oci_freq_override_fils_assoc"] = "2462" if not post_enable:
params["oci_freq_override_ft_assoc"] = "2462"
try: try:
hapd0 = hostapd.add_ap(apdev[0], params) hapd0 = hostapd.add_ap(apdev[0], params)
except Exception as e: except Exception as e:
@ -1100,9 +1138,14 @@ def test_wpa2_ocv_ap_override_ft_assoc(dev, apdev):
params = ft_params2(ssid=ssid, passphrase=passphrase) params = ft_params2(ssid=ssid, passphrase=passphrase)
params["ieee80211w"] = "2" params["ieee80211w"] = "2"
params["ocv"] = "1" params["ocv"] = "1"
if not post_enable:
params["oci_freq_override_ft_assoc"] = "2462" params["oci_freq_override_ft_assoc"] = "2462"
hapd1 = hostapd.add_ap(apdev[1], params) hapd1 = hostapd.add_ap(apdev[1], params)
if post_enable:
hapd0.set("oci_freq_override_ft_assoc", "2462")
hapd1.set("oci_freq_override_ft_assoc", "2462")
dev[0].connect(ssid, key_mgmt="FT-PSK", psk=passphrase, dev[0].connect(ssid, key_mgmt="FT-PSK", psk=passphrase,
scan_freq="2412", ocv="1", ieee80211w="2") scan_freq="2412", ocv="1", ieee80211w="2")

View File

@ -818,3 +818,54 @@ def test_p2p_group_cli_invalid(dev, apdev):
ev = dev[i].wait_global_event(["P2P-DEVICE-FOUND"], timeout=5) ev = dev[i].wait_global_event(["P2P-DEVICE-FOUND"], timeout=5)
if not ev: if not ev:
raise Exception("P2P device not found") raise Exception("P2P device not found")
def test_discovery_max_peers(dev):
"""P2P device discovery and maximum peer limit exceeded"""
dev[0].p2p_listen()
dev[0].request("SET ext_mgmt_frame_handling 1")
probereq1 = "40000000ffffffffffff"
probereq2 = "ffffffffffff000000074449524543542d01080c1218243048606c0301012d1afe131bffff000000000000000000000100000000000000000000ff16230178c812400000bfce0000000000000000fafffaffdd730050f204104a000110103a00010110080002314810470010572cf82fc95756539b16b5cfb298abf1105400080000000000000000103c0001031002000200001009000200001012000200001021000120102300012010240001201011000844657669636520421049000900372a000120030101dd11506f9a0902020025000605005858045106"
# Fill the P2P peer table with max+1 entries based on Probe Request frames
# to verify correct behavior on# removing the oldest entry when running out
# of room.
for i in range(101):
addr = "0202020202%02x" % i
probereq = probereq1 + addr + probereq2
if "OK" not in dev[0].request("MGMT_RX_PROCESS freq=2412 datarate=60 ssi_signal=-30 frame=" + probereq):
raise Exception("MGMT_RX_PROCESS failed")
res = dev[0].global_request("P2P_PEER FIRST")
addr = res.splitlines()[0]
peers = [addr]
limit = 200
while limit > 0:
res = dev[0].global_request("P2P_PEER NEXT-" + addr)
addr = res.splitlines()[0]
if addr == "FAIL":
break
peers.append(addr)
limit -= 1
logger.info("Peers: " + str(peers))
if len(peers) != 100:
raise Exception("Unexpected number of peer entries")
oldest = "02:02:02:02:02:00"
if oldest in peers:
raise Exception("Oldest entry is still present")
for i in range(101):
addr = "02:02:02:02:02:%02x" % i
if addr == oldest:
continue
if addr not in peers:
raise Exception("Peer missing from table: " + addr)
# Provision Discovery Request from the oldest peer (SA) using internally
# different P2P Device Address as a regression test for incorrect processing
# for this corner case.
dst = dev[0].own_addr().replace(':', '')
src = peers[99].replace(':', '')
devaddr = "0202020202ff"
pdreq = "d0004000" + dst + src + dst + "d0000409506f9a090701dd29506f9a0902020025000d1d00" + devaddr + "1108000000000000000000101100084465766963652041dd0a0050f204100800020008"
if "OK" not in dev[0].request("MGMT_RX_PROCESS freq=2412 datarate=60 ssi_signal=-30 frame=" + pdreq):
raise Exception("MGMT_RX_PROCESS failed")

View File

@ -13,6 +13,7 @@
import socket import socket
import struct import struct
import subprocess import subprocess
import re
import hwsim_utils import hwsim_utils
import hostapd import hostapd
@ -231,9 +232,12 @@ def test_pasn_sae_pmksa_cache(dev, apdev):
params = hostapd.wpa2_params(ssid="test-sae", params = hostapd.wpa2_params(ssid="test-sae",
passphrase="12345678") passphrase="12345678")
params['wpa_key_mgmt'] = 'SAE PASN' params['wpa_key_mgmt'] = 'SAE PASN'
params['sae_pwe'] = "2"
hapd = start_pasn_ap(apdev[0], params) hapd = start_pasn_ap(apdev[0], params)
try:
dev[0].set("sae_groups", "19") dev[0].set("sae_groups", "19")
dev[0].set("sae_pwe", "2")
dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", scan_freq="2412") dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", scan_freq="2412")
hapd.wait_sta() hapd.wait_sta()
@ -243,6 +247,8 @@ def test_pasn_sae_pmksa_cache(dev, apdev):
dev[0].wait_disconnected() dev[0].wait_disconnected()
check_pasn_akmp_cipher(dev[0], hapd, "SAE", "CCMP") check_pasn_akmp_cipher(dev[0], hapd, "SAE", "CCMP")
finally:
dev[0].set("sae_pwe", "0")
def check_pasn_fils_pmksa_cache(dev, apdev, params, key_mgmt): def check_pasn_fils_pmksa_cache(dev, apdev, params, key_mgmt):
check_fils_capa(dev[0]) check_fils_capa(dev[0])
@ -298,16 +304,19 @@ def test_pasn_sae_kdk(dev, apdev):
params = hostapd.wpa2_params(ssid="test-sae", params = hostapd.wpa2_params(ssid="test-sae",
passphrase="12345678") passphrase="12345678")
params['wpa_key_mgmt'] = 'SAE PASN' params['wpa_key_mgmt'] = 'SAE PASN'
params['sae_pwe'] = "2"
params['force_kdk_derivation'] = "1" params['force_kdk_derivation'] = "1"
hapd = start_pasn_ap(apdev[0], params) hapd = start_pasn_ap(apdev[0], params)
dev[0].set("force_kdk_derivation", "1") dev[0].set("force_kdk_derivation", "1")
dev[0].set("sae_pwe", "2")
dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
scan_freq="2412") scan_freq="2412")
check_pasn_ptk(dev[0], hapd, "CCMP", clear_keys=False) check_pasn_ptk(dev[0], hapd, "CCMP", clear_keys=False)
finally: finally:
dev[0].set("force_kdk_derivation", "0") dev[0].set("force_kdk_derivation", "0")
dev[0].set("sae_pwe", "0")
def check_pasn_fils_kdk(dev, apdev, params, key_mgmt): def check_pasn_fils_kdk(dev, apdev, params, key_mgmt):
@ -383,10 +392,13 @@ def test_pasn_sae(dev, apdev):
params = hostapd.wpa2_params(ssid="test-pasn-sae", params = hostapd.wpa2_params(ssid="test-pasn-sae",
passphrase="12345678") passphrase="12345678")
params['wpa_key_mgmt'] = 'SAE PASN' params['wpa_key_mgmt'] = 'SAE PASN'
params['sae_pwe'] = "2"
hapd = start_pasn_ap(apdev[0], params) hapd = start_pasn_ap(apdev[0], params)
dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", scan_freq="2412", try:
only_add_network=True) dev[0].set("sae_pwe", "2")
dev[0].connect("test-pasn-sae", psk="12345678", key_mgmt="SAE",
scan_freq="2412", only_add_network=True)
# first test with a valid PSK # first test with a valid PSK
check_pasn_akmp_cipher(dev[0], hapd, "SAE", "CCMP", nid="0") check_pasn_akmp_cipher(dev[0], hapd, "SAE", "CCMP", nid="0")
@ -400,6 +412,8 @@ def test_pasn_sae(dev, apdev):
dev[0].set_network_quoted(0, "psk", "12345678787") dev[0].set_network_quoted(0, "psk", "12345678787")
check_pasn_akmp_cipher(dev[0], hapd, "SAE", "CCMP", status=1, nid="0") check_pasn_akmp_cipher(dev[0], hapd, "SAE", "CCMP", status=1, nid="0")
finally:
dev[0].set("sae_pwe", "0")
@remote_compatible @remote_compatible
def test_pasn_sae_while_connected_same_channel(dev, apdev): def test_pasn_sae_while_connected_same_channel(dev, apdev):
@ -411,18 +425,23 @@ def test_pasn_sae_while_connected_same_channel(dev, apdev):
passphrase="12345678") passphrase="12345678")
hapd = hostapd.add_ap(apdev[0], params) hapd = hostapd.add_ap(apdev[0], params)
try:
dev[0].set("sae_pwe", "2")
dev[0].connect("test-pasn-wpa2-psk", psk="12345678", scan_freq="2412") dev[0].connect("test-pasn-wpa2-psk", psk="12345678", scan_freq="2412")
params = hostapd.wpa2_params(ssid="test-pasn-sae", params = hostapd.wpa2_params(ssid="test-pasn-sae",
passphrase="12345678") passphrase="12345678")
params['wpa_key_mgmt'] = 'SAE PASN' params['wpa_key_mgmt'] = 'SAE PASN'
params['sae_pwe'] = "2"
hapd = start_pasn_ap(apdev[1], params) hapd = start_pasn_ap(apdev[1], params)
dev[0].connect("test-pasn-sae", psk="12345678", key_mgmt="SAE", dev[0].connect("test-pasn-sae", psk="12345678", key_mgmt="SAE",
scan_freq="2412", only_add_network=True) scan_freq="2412", only_add_network=True)
check_pasn_akmp_cipher(dev[0], hapd, "SAE", "CCMP", nid="1") check_pasn_akmp_cipher(dev[0], hapd, "SAE", "CCMP", nid="1")
finally:
dev[0].set("sae_pwe", "0")
@remote_compatible @remote_compatible
def test_pasn_sae_while_connected_diff_channel(dev, apdev): def test_pasn_sae_while_connected_diff_channel(dev, apdev):
@ -442,18 +461,23 @@ def test_pasn_sae_while_connected_diff_channel(dev, apdev):
params['channel'] = "6" params['channel'] = "6"
hapd = hostapd.add_ap(apdev[0], params) hapd = hostapd.add_ap(apdev[0], params)
try:
wpas.set("sae_pwe", "2")
wpas.connect("test-pasn-wpa2-psk", psk="12345678", scan_freq="2437") wpas.connect("test-pasn-wpa2-psk", psk="12345678", scan_freq="2437")
params = hostapd.wpa2_params(ssid="test-pasn-sae", params = hostapd.wpa2_params(ssid="test-pasn-sae",
passphrase="12345678") passphrase="12345678")
params['wpa_key_mgmt'] = 'SAE PASN' params['wpa_key_mgmt'] = 'SAE PASN'
params['sae_pwe'] = "2"
hapd = start_pasn_ap(apdev[1], params) hapd = start_pasn_ap(apdev[1], params)
wpas.connect("test-pasn-sae", psk="12345678", key_mgmt="SAE", wpas.connect("test-pasn-sae", psk="12345678", key_mgmt="SAE",
scan_freq="2412", only_add_network=True) scan_freq="2412", only_add_network=True)
check_pasn_akmp_cipher(wpas, hapd, "SAE", "CCMP", nid="1") check_pasn_akmp_cipher(wpas, hapd, "SAE", "CCMP", nid="1")
finally:
wpas.set("sae_pwe", "0")
def pasn_fils_setup(wpas, apdev, params, key_mgmt): def pasn_fils_setup(wpas, apdev, params, key_mgmt):
check_fils_capa(wpas) check_fils_capa(wpas)
@ -681,3 +705,146 @@ def test_pasn_ap_mic_error(dev, apdev):
check_pasn_akmp_cipher(dev[0], hapd1, "PASN", "CCMP", status=1) check_pasn_akmp_cipher(dev[0], hapd1, "PASN", "CCMP", status=1)
check_pasn_akmp_cipher(dev[0], hapd0, "PASN", "CCMP") check_pasn_akmp_cipher(dev[0], hapd0, "PASN", "CCMP")
@remote_compatible
def test_pasn_comeback(dev, apdev, params):
"""PASN authentication with comeback flow"""
check_pasn_capab(dev[0])
params = pasn_ap_params("PASN", "CCMP", "19")
params['sae_anti_clogging_threshold'] = '0'
hapd = hostapd.add_ap(apdev[0], params)
bssid = hapd.own_addr()
dev[0].scan(type="ONLY", freq=2412)
cmd = "PASN_START bssid=%s akmp=PASN cipher=CCMP group=19" % bssid
resp = dev[0].request(cmd)
if "OK" not in resp:
raise Exception("Failed to start PASN authentication")
ev = dev[0].wait_event(["PASN-AUTH-STATUS"], 3)
if not ev:
raise Exception("PASN: PASN-AUTH-STATUS not seen")
if bssid + " akmp=PASN, status=30 comeback_after=" not in ev:
raise Exception("PASN: unexpected status")
comeback = re.split("comeback=", ev)[1]
cmd = "PASN_START bssid=%s akmp=PASN cipher=CCMP group=19 comeback=%s" % \
(bssid, comeback)
resp = dev[0].request(cmd)
if "OK" not in resp:
raise Exception("Failed to start PASN authentication")
ev = dev[0].wait_event(["PASN-AUTH-STATUS"], 3)
if not ev:
raise Exception("PASN: PASN-AUTH-STATUS not seen")
if bssid + " akmp=PASN, status=0" not in ev:
raise Exception("PASN: unexpected status with comeback token")
check_pasn_ptk(dev[0], hapd, "CCMP")
@remote_compatible
def test_pasn_comeback_after_0(dev, apdev, params):
"""PASN authentication with comeback flow with comeback after set to 0"""
check_pasn_capab(dev[0])
params = pasn_ap_params("PASN", "CCMP", "19")
params['anti_clogging_threshold'] = '0'
params['pasn_comeback_after'] = '0'
hapd = start_pasn_ap(apdev[0], params)
check_pasn_akmp_cipher(dev[0], hapd, "PASN", "CCMP")
@remote_compatible
def test_pasn_comeback_after_0_sae(dev, apdev):
"""PASN authentication with SAE, with comeback flow where comeback after is set to 0"""
check_pasn_capab(dev[0])
check_sae_capab(dev[0])
params = hostapd.wpa2_params(ssid="test-pasn-sae",
passphrase="12345678")
params['wpa_key_mgmt'] = 'SAE PASN'
params['anti_clogging_threshold'] = '0'
params['pasn_comeback_after'] = '0'
params['sae_pwe'] = "2"
hapd = start_pasn_ap(apdev[0], params)
try:
dev[0].set("sae_pwe", "2")
dev[0].connect("test-pasn-sae", psk="12345678", key_mgmt="SAE",
scan_freq="2412", only_add_network=True)
# first test with a valid PSK
check_pasn_akmp_cipher(dev[0], hapd, "SAE", "CCMP", nid="0")
# And now with PMKSA caching
check_pasn_akmp_cipher(dev[0], hapd, "SAE", "CCMP")
# And now with a wrong passphrase
if "FAIL" in dev[0].request("PMKSA_FLUSH"):
raise Exception("PMKSA_FLUSH failed")
dev[0].set_network_quoted(0, "psk", "12345678787")
check_pasn_akmp_cipher(dev[0], hapd, "SAE", "CCMP", status=1, nid="0")
finally:
dev[0].set("sae_pwe", "0")
@remote_compatible
def test_pasn_comeback_multi(dev, apdev):
"""PASN authentication with SAE, with multiple stations with comeback"""
check_pasn_capab(dev[0])
check_sae_capab(dev[0])
params = hostapd.wpa2_params(ssid="test-pasn-sae",
passphrase="12345678")
params['wpa_key_mgmt'] = 'SAE PASN'
params['anti_clogging_threshold'] = '1'
params['pasn_comeback_after'] = '0'
hapd = start_pasn_ap(apdev[0], params)
bssid = hapd.own_addr()
id = {}
for i in range(0, 2):
dev[i].flush_scan_cache()
dev[i].scan(type="ONLY", freq=2412)
id[i] = dev[i].connect("test-pasn-sae", psk="12345678", key_mgmt="SAE",
scan_freq="2412", only_add_network=True)
for i in range(0, 2):
cmd = "PASN_START bssid=%s akmp=PASN cipher=CCMP group=19, nid=%s" % (bssid, id[i])
resp = dev[i].request(cmd)
if "OK" not in resp:
raise Exception("Failed to start pasn authentication")
for i in range(0, 2):
ev = dev[i].wait_event(["PASN-AUTH-STATUS"], 3)
if not ev:
raise Exception("PASN: PASN-AUTH-STATUS not seen")
if bssid + " akmp=PASN, status=0" not in ev:
raise Exception("PASN: unexpected status")
check_pasn_ptk(dev[i], hapd, "CCMP")
def test_pasn_kdk_derivation(dev, apdev):
"""PASN authentication with forced KDK derivation"""
check_pasn_capab(dev[0])
params = pasn_ap_params("PASN", "CCMP", "19")
hapd0 = start_pasn_ap(apdev[0], params)
params['force_kdk_derivation'] = "1"
hapd1 = start_pasn_ap(apdev[1], params)
try:
check_pasn_akmp_cipher(dev[0], hapd0, "PASN", "CCMP")
dev[0].set("force_kdk_derivation", "1")
check_pasn_akmp_cipher(dev[0], hapd1, "PASN", "CCMP")
finally:
dev[0].set("force_kdk_derivation", "0")

View File

@ -1251,3 +1251,17 @@ def test_rsn_preauth_local_errors(dev, apdev):
raise Exception("ENABLE failed") raise Exception("ENABLE failed")
sock.send(_bssid + foreign + proto + struct.pack('>BBH', 2, 1, 0)) sock.send(_bssid + foreign + proto + struct.pack('>BBH', 2, 1, 0))
sock.send(_bssid + foreign2 + proto + struct.pack('>BBH', 2, 1, 0)) sock.send(_bssid + foreign2 + proto + struct.pack('>BBH', 2, 1, 0))
def test_pmksa_cache_add_failure(dev, apdev):
"""PMKSA cache add failure"""
params = hostapd.wpa2_eap_params(ssid="test-pmksa-cache")
hostapd.add_ap(apdev[0], params)
bssid = apdev[0]['bssid']
with alloc_fail(dev[0], 1, "pmksa_cache_add"):
dev[0].connect("test-pmksa-cache", proto="RSN", key_mgmt="WPA-EAP",
eap="GPSK", identity="gpsk user",
password="abcdefghijklmnop0123456789abcdef",
scan_freq="2412")
pmksa = dev[0].get_pmksa(bssid)
if pmksa is None:
raise Exception("No PMKSA cache entry created")

View File

@ -212,6 +212,20 @@ def test_rrm_neighbor_db(dev, apdev):
if apdev[0]['bssid'] not in res: if apdev[0]['bssid'] not in res:
raise Exception("Own BSS not visible in SHOW_NEIGHBOR output") raise Exception("Own BSS not visible in SHOW_NEIGHBOR output")
def test_rrm_neighbor_db_failures(dev, apdev):
"""hostapd ctrl_iface SET_NEIGHBOR failures"""
params = {"ssid": "test", "rrm_neighbor_report": "1"}
hapd = hostapd.add_ap(apdev[0]['ifname'], params)
cmd = "SET_NEIGHBOR 00:11:22:33:44:55 ssid=\"test1\" nr=" + nr + " lci=" + lci + " civic=" + civic
tests = [(1, "hostapd_neighbor_add"),
(1, "wpabuf_dup;hostapd_neighbor_set"),
(2, "wpabuf_dup;hostapd_neighbor_set"),
(3, "wpabuf_dup;hostapd_neighbor_set")]
for count, func in tests:
with alloc_fail(hapd, count, func):
if "FAIL" not in hapd.request(cmd):
raise Exception("Set neighbor succeeded")
def test_rrm_neighbor_db_disabled(dev, apdev): def test_rrm_neighbor_db_disabled(dev, apdev):
"""hostapd ctrl_iface SHOW_NEIGHBOR while neighbor report disabled""" """hostapd ctrl_iface SHOW_NEIGHBOR while neighbor report disabled"""
params = {"ssid": "test"} params = {"ssid": "test"}

View File

@ -37,7 +37,8 @@ def start_wnm_ap(apdev, bss_transition=True, time_adv=False, ssid=None,
wnm_sleep_mode=False, wnm_sleep_mode_no_keys=False, rsn=False, wnm_sleep_mode=False, wnm_sleep_mode_no_keys=False, rsn=False,
ocv=False, ap_max_inactivity=0, coloc_intf_reporting=False, ocv=False, ap_max_inactivity=0, coloc_intf_reporting=False,
hw_mode=None, channel=None, country_code=None, country3=None, hw_mode=None, channel=None, country_code=None, country3=None,
pmf=True, passphrase=None, ht=True, vht=False, mbo=False): pmf=True, passphrase=None, ht=True, vht=False, mbo=False,
beacon_prot=False):
if rsn: if rsn:
if not ssid: if not ssid:
ssid = "test-wnm-rsn" ssid = "test-wnm-rsn"
@ -47,6 +48,8 @@ def start_wnm_ap(apdev, bss_transition=True, time_adv=False, ssid=None,
if pmf: if pmf:
params["wpa_key_mgmt"] = "WPA-PSK-SHA256" params["wpa_key_mgmt"] = "WPA-PSK-SHA256"
params["ieee80211w"] = "2" params["ieee80211w"] = "2"
if beacon_prot:
params["beacon_prot"] = "1"
else: else:
params = {"ssid": "test-wnm"} params = {"ssid": "test-wnm"}
if bss_transition: if bss_transition:
@ -195,7 +198,8 @@ def test_wnm_ess_disassoc_imminent_pmf(dev, apdev):
if ev is None: if ev is None:
raise Exception("Timeout while waiting for re-connection scan") raise Exception("Timeout while waiting for re-connection scan")
def check_wnm_sleep_mode_enter_exit(hapd, dev, interval=None, tfs_req=None): def check_wnm_sleep_mode_enter_exit(hapd, dev, interval=None, tfs_req=None,
rekey=False):
addr = dev.p2p_interface_addr() addr = dev.p2p_interface_addr()
sta = hapd.get_sta(addr) sta = hapd.get_sta(addr)
if "[WNM_SLEEP_MODE]" in sta['flags']: if "[WNM_SLEEP_MODE]" in sta['flags']:
@ -219,6 +223,14 @@ def check_wnm_sleep_mode_enter_exit(hapd, dev, interval=None, tfs_req=None):
if not ok: if not ok:
raise Exception("Station failed to enter WNM-Sleep Mode") raise Exception("Station failed to enter WNM-Sleep Mode")
if rekey:
time.sleep(0.1)
if "OK" not in hapd.request("REKEY_GTK"):
raise Exception("REKEY_GTK failed")
ev = dev.wait_event(["WPA: Group rekeying completed"], timeout=0.1)
if ev is not None:
raise Exception("Unexpected report of GTK rekey during WNM-Sleep Mode")
logger.info("Waking up from WNM Sleep Mode") logger.info("Waking up from WNM Sleep Mode")
ok = False ok = False
dev.request("WNM_SLEEP exit") dev.request("WNM_SLEEP exit")
@ -231,6 +243,14 @@ def check_wnm_sleep_mode_enter_exit(hapd, dev, interval=None, tfs_req=None):
if not ok: if not ok:
raise Exception("Station failed to exit WNM-Sleep Mode") raise Exception("Station failed to exit WNM-Sleep Mode")
if rekey:
time.sleep(0.1)
if "OK" not in hapd.request("REKEY_GTK"):
raise Exception("REKEY_GTK failed")
ev = dev.wait_event(["WPA: Group rekeying completed"], timeout=2)
if ev is None:
raise Exception("GTK rekey timed out")
@remote_compatible @remote_compatible
def test_wnm_sleep_mode_open(dev, apdev): def test_wnm_sleep_mode_open(dev, apdev):
"""WNM Sleep Mode - open""" """WNM Sleep Mode - open"""
@ -303,6 +323,19 @@ def test_wnm_sleep_mode_rsn_pmf(dev, apdev):
raise Exception("No connection event received from hostapd") raise Exception("No connection event received from hostapd")
check_wnm_sleep_mode_enter_exit(hapd, dev[0]) check_wnm_sleep_mode_enter_exit(hapd, dev[0])
def test_wnm_sleep_mode_rsn_beacon_prot(dev, apdev):
"""WNM Sleep Mode - RSN with PMF and beacon protection"""
hapd = start_wnm_ap(apdev[0], rsn=True, wnm_sleep_mode=True, time_adv=True,
beacon_prot=True)
dev[0].connect("test-wnm-rsn", psk="12345678", ieee80211w="2",
beacon_prot="1",
key_mgmt="WPA-PSK-SHA256", proto="WPA2", scan_freq="2412")
ev = hapd.wait_event(["AP-STA-CONNECTED"], timeout=5)
if ev is None:
raise Exception("No connection event received from hostapd")
check_wnm_sleep_mode_enter_exit(hapd, dev[0])
check_wnm_sleep_mode_enter_exit(hapd, dev[0], rekey=True)
@remote_compatible @remote_compatible
def test_wnm_sleep_mode_rsn_ocv(dev, apdev): def test_wnm_sleep_mode_rsn_ocv(dev, apdev):
"""WNM Sleep Mode - RSN with OCV""" """WNM Sleep Mode - RSN with OCV"""

View File

@ -1402,6 +1402,8 @@ def test_wpas_ctrl_driver_event(dev, apdev):
"""wpa_supplicant ctrl_iface DRIVER_EVENT""" """wpa_supplicant ctrl_iface DRIVER_EVENT"""
if "FAIL" not in dev[0].request("DRIVER_EVENT foo"): if "FAIL" not in dev[0].request("DRIVER_EVENT foo"):
raise Exception("Invalid DRIVER_EVENT accepted") raise Exception("Invalid DRIVER_EVENT accepted")
if "OK" not in dev[0].request("DRIVER_EVENT ASSOC reassoc=1 req_ies=0000 resp_ies=0000 resp_frame=0000 beacon_ies=0000 freq=2412 wmm::info_bitmap=0 wmm::uapsd_queues=0 addr=02:02:02:02:02:02 authorized=0 key_replay_ctr=00 ptk_kck=00 ptk_kek=00 subnet_status=0 fils_erp_next_seq_num=0 fils_pmk=00 fils_pmkid=" + 16*"00"):
raise Exception("DRIVER_EVENT ASSOC did not succeed")
@remote_compatible @remote_compatible
def test_wpas_ctrl_eapol_rx(dev, apdev): def test_wpas_ctrl_eapol_rx(dev, apdev):
@ -2147,3 +2149,11 @@ def test_wpas_ctrl_get_pref_freq_list_override(dev):
dev[0].set("get_pref_freq_list_override", "") dev[0].set("get_pref_freq_list_override", "")
res = dev[0].request("GET_PREF_FREQ_LIST STATION").strip() res = dev[0].request("GET_PREF_FREQ_LIST STATION").strip()
logger.info("STATION (without override): " + res) logger.info("STATION (without override): " + res)
def test_wpas_ctrl_interface_add_driver_init_failure(dev, apdev):
"""wpa_supplicant INTERFACE_ADD and driver init failing"""
for i in range(1000):
res = dev[0].global_request("INTERFACE_ADD FOO")
if "FAIL" not in res:
raise Exception("Unexpected result: " + res)
dev[0].dump_monitor()

View File

@ -15,11 +15,16 @@ mount sysfs -t sysfs /sys
# needed for tracing # needed for tracing
mount debugfs -t debugfs /sys/kernel/debug mount debugfs -t debugfs /sys/kernel/debug
mkdir /tmp/wireshark-share
mount --bind /usr/share/wireshark /tmp/wireshark-share
mount tmpfs -t tmpfs /usr/share/wireshark
# for inside telnet # for inside telnet
mkdir /dev/pts mkdir /dev/pts
mount devpts -t devpts /dev/pts mount devpts -t devpts /dev/pts
export PATH=/usr/sbin:$PATH export PATH=/usr/sbin:$PATH
export HOME=/tmp
# reboot on any sort of crash # reboot on any sort of crash
sysctl kernel.panic_on_oops=1 sysctl kernel.panic_on_oops=1

View File

@ -512,6 +512,19 @@ static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s,
} else if (os_strcasecmp(cmd, "EAPOL::maxStart") == 0) { } else if (os_strcasecmp(cmd, "EAPOL::maxStart") == 0) {
eapol_sm_configure(wpa_s->eapol, eapol_sm_configure(wpa_s->eapol,
-1, -1, -1, atoi(value)); -1, -1, -1, atoi(value));
#ifdef CONFIG_TESTING_OPTIONS
} else if (os_strcasecmp(cmd, "EAPOL::portControl") == 0) {
if (os_strcmp(value, "Auto") == 0)
eapol_sm_notify_portControl(wpa_s->eapol, Auto);
else if (os_strcmp(value, "ForceUnauthorized") == 0)
eapol_sm_notify_portControl(wpa_s->eapol,
ForceUnauthorized);
else if (os_strcmp(value, "ForceAuthorized") == 0)
eapol_sm_notify_portControl(wpa_s->eapol,
ForceAuthorized);
else
ret = -1;
#endif /* CONFIG_TESTING_OPTIONS */
} else if (os_strcasecmp(cmd, "dot11RSNAConfigPMKLifetime") == 0) { } else if (os_strcasecmp(cmd, "dot11RSNAConfigPMKLifetime") == 0) {
if (wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME, if (wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
atoi(value))) { atoi(value))) {
@ -2999,20 +3012,18 @@ static int wpa_supplicant_ctrl_iface_scan_result(
ie2, 2 + ie2[1]); ie2, 2 + ie2[1]);
} }
rsnxe = wpa_bss_get_ie(bss, WLAN_EID_RSNX); rsnxe = wpa_bss_get_ie(bss, WLAN_EID_RSNX);
if (rsnxe && rsnxe[1] >= 1) { if (ieee802_11_rsnx_capab(rsnxe, WLAN_RSNX_CAPAB_SAE_H2E)) {
if (rsnxe[2] & BIT(WLAN_RSNX_CAPAB_SAE_H2E)) {
ret = os_snprintf(pos, end - pos, "[SAE-H2E]"); ret = os_snprintf(pos, end - pos, "[SAE-H2E]");
if (os_snprintf_error(end - pos, ret)) if (os_snprintf_error(end - pos, ret))
return -1; return -1;
pos += ret; pos += ret;
} }
if (rsnxe[2] & BIT(WLAN_RSNX_CAPAB_SAE_PK)) { if (ieee802_11_rsnx_capab(rsnxe, WLAN_RSNX_CAPAB_SAE_PK)) {
ret = os_snprintf(pos, end - pos, "[SAE-PK]"); ret = os_snprintf(pos, end - pos, "[SAE-PK]");
if (os_snprintf_error(end - pos, ret)) if (os_snprintf_error(end - pos, ret))
return -1; return -1;
pos += ret; pos += ret;
} }
}
osen_ie = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE); osen_ie = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE);
if (osen_ie) if (osen_ie)
pos = wpa_supplicant_ie_txt(pos, end, "OSEN", pos = wpa_supplicant_ie_txt(pos, end, "OSEN",
@ -5099,20 +5110,18 @@ static int print_bss_info(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
mesh ? "RSN" : "WPA2", ie2, mesh ? "RSN" : "WPA2", ie2,
2 + ie2[1]); 2 + ie2[1]);
rsnxe = wpa_bss_get_ie(bss, WLAN_EID_RSNX); rsnxe = wpa_bss_get_ie(bss, WLAN_EID_RSNX);
if (rsnxe && rsnxe[1] >= 1) { if (ieee802_11_rsnx_capab(rsnxe, WLAN_RSNX_CAPAB_SAE_H2E)) {
if (rsnxe[2] & BIT(WLAN_RSNX_CAPAB_SAE_H2E)) {
ret = os_snprintf(pos, end - pos, "[SAE-H2E]"); ret = os_snprintf(pos, end - pos, "[SAE-H2E]");
if (os_snprintf_error(end - pos, ret)) if (os_snprintf_error(end - pos, ret))
return -1; return -1;
pos += ret; pos += ret;
} }
if (rsnxe[2] & BIT(WLAN_RSNX_CAPAB_SAE_PK)) { if (ieee802_11_rsnx_capab(rsnxe, WLAN_RSNX_CAPAB_SAE_PK)) {
ret = os_snprintf(pos, end - pos, "[SAE-PK]"); ret = os_snprintf(pos, end - pos, "[SAE-PK]");
if (os_snprintf_error(end - pos, ret)) if (os_snprintf_error(end - pos, ret))
return -1; return -1;
pos += ret; pos += ret;
} }
}
osen_ie = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE); osen_ie = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE);
if (osen_ie) if (osen_ie)
pos = wpa_supplicant_ie_txt(pos, end, "OSEN", pos = wpa_supplicant_ie_txt(pos, end, "OSEN",
@ -9300,6 +9309,132 @@ static int wpas_ctrl_iface_driver_scan_res(struct wpa_supplicant *wpa_s,
} }
static int wpas_ctrl_iface_driver_event_assoc(struct wpa_supplicant *wpa_s,
char *param)
{
union wpa_event_data event;
struct assoc_info *ai;
char *ctx = NULL;
int ret = -1;
struct wpabuf *req_ies = NULL;
struct wpabuf *resp_ies = NULL;
struct wpabuf *resp_frame = NULL;
struct wpabuf *beacon_ies = NULL;
struct wpabuf *key_replay_ctr = NULL;
struct wpabuf *ptk_kck = NULL;
struct wpabuf *ptk_kek = NULL;
struct wpabuf *fils_pmk = NULL;
char *str, *pos;
u8 addr[ETH_ALEN];
u8 fils_pmkid[PMKID_LEN];
os_memset(&event, 0, sizeof(event));
ai = &event.assoc_info;
while ((str = str_token(param, " ", &ctx))) {
pos = os_strchr(str, '=');
if (!pos)
goto fail;
*pos++ = '\0';
if (os_strcmp(str, "reassoc") == 0) {
ai->reassoc = atoi(pos);
} else if (os_strcmp(str, "req_ies") == 0) {
wpabuf_free(req_ies);
req_ies = wpabuf_parse_bin(pos);
if (!req_ies)
goto fail;
ai->req_ies = wpabuf_head(req_ies);
ai->req_ies_len = wpabuf_len(req_ies);
} else if (os_strcmp(str, "resp_ies") == 0) {
wpabuf_free(resp_ies);
resp_ies = wpabuf_parse_bin(pos);
if (!resp_ies)
goto fail;
ai->resp_ies = wpabuf_head(resp_ies);
ai->resp_ies_len = wpabuf_len(resp_ies);
} else if (os_strcmp(str, "resp_frame") == 0) {
wpabuf_free(resp_frame);
resp_frame = wpabuf_parse_bin(pos);
if (!resp_frame)
goto fail;
ai->resp_frame = wpabuf_head(resp_frame);
ai->resp_frame_len = wpabuf_len(resp_frame);
} else if (os_strcmp(str, "beacon_ies") == 0) {
wpabuf_free(beacon_ies);
beacon_ies = wpabuf_parse_bin(pos);
if (!beacon_ies)
goto fail;
ai->beacon_ies = wpabuf_head(beacon_ies);
ai->beacon_ies_len = wpabuf_len(beacon_ies);
} else if (os_strcmp(str, "freq") == 0) {
ai->freq = atoi(pos);
} else if (os_strcmp(str, "wmm::info_bitmap") == 0) {
ai->wmm_params.info_bitmap = atoi(pos);
} else if (os_strcmp(str, "wmm::uapsd_queues") == 0) {
ai->wmm_params.uapsd_queues = atoi(pos);
} else if (os_strcmp(str, "addr") == 0) {
if (hwaddr_aton(pos, addr))
goto fail;
ai->addr = addr;
} else if (os_strcmp(str, "authorized") == 0) {
ai->authorized = atoi(pos);
} else if (os_strcmp(str, "key_replay_ctr") == 0) {
wpabuf_free(key_replay_ctr);
key_replay_ctr = wpabuf_parse_bin(pos);
if (!key_replay_ctr)
goto fail;
ai->key_replay_ctr = wpabuf_head(key_replay_ctr);
ai->key_replay_ctr_len = wpabuf_len(key_replay_ctr);
} else if (os_strcmp(str, "ptk_kck") == 0) {
wpabuf_free(ptk_kck);
ptk_kck = wpabuf_parse_bin(pos);
if (!ptk_kck)
goto fail;
ai->ptk_kck = wpabuf_head(ptk_kck);
ai->ptk_kck_len = wpabuf_len(ptk_kck);
} else if (os_strcmp(str, "ptk_kek") == 0) {
wpabuf_free(ptk_kek);
ptk_kek = wpabuf_parse_bin(pos);
if (!ptk_kek)
goto fail;
ai->ptk_kek = wpabuf_head(ptk_kek);
ai->ptk_kek_len = wpabuf_len(ptk_kek);
} else if (os_strcmp(str, "subnet_status") == 0) {
ai->subnet_status = atoi(pos);
} else if (os_strcmp(str, "fils_erp_next_seq_num") == 0) {
ai->fils_erp_next_seq_num = atoi(pos);
} else if (os_strcmp(str, "fils_pmk") == 0) {
wpabuf_free(fils_pmk);
fils_pmk = wpabuf_parse_bin(pos);
if (!fils_pmk)
goto fail;
ai->fils_pmk = wpabuf_head(fils_pmk);
ai->fils_pmk_len = wpabuf_len(fils_pmk);
} else if (os_strcmp(str, "fils_pmkid") == 0) {
if (hexstr2bin(pos, fils_pmkid, PMKID_LEN) < 0)
goto fail;
ai->fils_pmkid = fils_pmkid;
} else {
goto fail;
}
}
wpa_supplicant_event(wpa_s, EVENT_ASSOC, &event);
ret = 0;
fail:
wpabuf_free(req_ies);
wpabuf_free(resp_ies);
wpabuf_free(resp_frame);
wpabuf_free(beacon_ies);
wpabuf_free(key_replay_ctr);
wpabuf_free(ptk_kck);
wpabuf_free(ptk_kek);
wpabuf_free(fils_pmk);
return ret;
}
static int wpas_ctrl_iface_driver_event(struct wpa_supplicant *wpa_s, char *cmd) static int wpas_ctrl_iface_driver_event(struct wpa_supplicant *wpa_s, char *cmd)
{ {
char *pos, *param; char *pos, *param;
@ -9332,6 +9467,8 @@ static int wpas_ctrl_iface_driver_event(struct wpa_supplicant *wpa_s, char *cmd)
return 0; return 0;
} else if (os_strcmp(cmd, "SCAN_RES") == 0) { } else if (os_strcmp(cmd, "SCAN_RES") == 0) {
return wpas_ctrl_iface_driver_scan_res(wpa_s, param); return wpas_ctrl_iface_driver_scan_res(wpa_s, param);
} else if (os_strcmp(cmd, "ASSOC") == 0) {
return wpas_ctrl_iface_driver_event_assoc(wpa_s, param);
} else { } else {
wpa_dbg(wpa_s, MSG_DEBUG, "Testing - unknown driver event: %s", wpa_dbg(wpa_s, MSG_DEBUG, "Testing - unknown driver event: %s",
cmd); cmd);
@ -10598,15 +10735,18 @@ static int wpas_ctrl_iface_pasn_start(struct wpa_supplicant *wpa_s, char *cmd)
u8 bssid[ETH_ALEN]; u8 bssid[ETH_ALEN];
int akmp = -1, cipher = -1, got_bssid = 0; int akmp = -1, cipher = -1, got_bssid = 0;
u16 group = 0xFFFF; u16 group = 0xFFFF;
int id = 0; u8 *comeback = NULL;
size_t comeback_len = 0;
int id = 0, ret = -1;
/* /*
* Entry format: bssid=<BSSID> akmp=<AKMP> cipher=<CIPHER> group=<group> * Entry format: bssid=<BSSID> akmp=<AKMP> cipher=<CIPHER> group=<group>
* [comeback=<hexdump>]
*/ */
while ((token = str_token(cmd, " ", &context))) { while ((token = str_token(cmd, " ", &context))) {
if (os_strncmp(token, "bssid=", 6) == 0) { if (os_strncmp(token, "bssid=", 6) == 0) {
if (hwaddr_aton(token + 6, bssid)) if (hwaddr_aton(token + 6, bssid))
return -1; goto out;
got_bssid = 1; got_bssid = 1;
} else if (os_strcmp(token, "akmp=PASN") == 0) { } else if (os_strcmp(token, "akmp=PASN") == 0) {
akmp = WPA_KEY_MGMT_PASN; akmp = WPA_KEY_MGMT_PASN;
@ -10640,20 +10780,34 @@ static int wpas_ctrl_iface_pasn_start(struct wpa_supplicant *wpa_s, char *cmd)
group = atoi(token + 6); group = atoi(token + 6);
} else if (os_strncmp(token, "nid=", 4) == 0) { } else if (os_strncmp(token, "nid=", 4) == 0) {
id = atoi(token + 4); id = atoi(token + 4);
} else if (os_strncmp(token, "comeback=", 9) == 0) {
comeback_len = os_strlen(token + 9);
if (comeback || !comeback_len || comeback_len % 2)
goto out;
comeback_len /= 2;
comeback = os_malloc(comeback_len);
if (!comeback ||
hexstr2bin(token + 9, comeback, comeback_len))
goto out;
} else { } else {
wpa_printf(MSG_DEBUG, wpa_printf(MSG_DEBUG,
"CTRL: PASN Invalid parameter: '%s'", "CTRL: PASN Invalid parameter: '%s'",
token); token);
return -1; goto out;
} }
} }
if (!got_bssid || akmp == -1 || cipher == -1 || group == 0xFFFF) { if (!got_bssid || akmp == -1 || cipher == -1 || group == 0xFFFF) {
wpa_printf(MSG_DEBUG,"CTRL: PASN missing parameter"); wpa_printf(MSG_DEBUG,"CTRL: PASN missing parameter");
return -1; goto out;
} }
return wpas_pasn_auth_start(wpa_s, bssid, akmp, cipher, group, id); ret = wpas_pasn_auth_start(wpa_s, bssid, akmp, cipher, group, id,
comeback, comeback_len);
out:
os_free(comeback);
return ret;
} }

View File

@ -70,14 +70,17 @@ wpa_supplicant_ctrl_iface_init(struct wpa_supplicant *wpa_s);
/** /**
* wpa_supplicant_ctrl_iface_deinit - Deinitialize control interface * wpa_supplicant_ctrl_iface_deinit - Deinitialize control interface
* @wpa_s: Pointer to wpa_supplicant data
* @priv: Pointer to private data from wpa_supplicant_ctrl_iface_init() * @priv: Pointer to private data from wpa_supplicant_ctrl_iface_init()
* *
* Deinitialize the control interface that was initialized with * Deinitialize the control interface that was initialized with
* wpa_supplicant_ctrl_iface_init(). * wpa_supplicant_ctrl_iface_init() and any data related to the wpa_s instance.
* @priv may be %NULL if the control interface has not yet been initialized.
* *
* Required to be implemented in each control interface backend. * Required to be implemented in each control interface backend.
*/ */
void wpa_supplicant_ctrl_iface_deinit(struct ctrl_iface_priv *priv); void wpa_supplicant_ctrl_iface_deinit(struct wpa_supplicant *wpa_s,
struct ctrl_iface_priv *priv);
/** /**
* wpa_supplicant_ctrl_iface_wait - Wait for ctrl_iface monitor * wpa_supplicant_ctrl_iface_wait - Wait for ctrl_iface monitor
@ -128,7 +131,8 @@ wpa_supplicant_ctrl_iface_init(struct wpa_supplicant *wpa_s)
} }
static inline void static inline void
wpa_supplicant_ctrl_iface_deinit(struct ctrl_iface_priv *priv) wpa_supplicant_ctrl_iface_deinit(struct wpa_supplicant *wpa_s,
struct ctrl_iface_priv *priv)
{ {
} }

View File

@ -462,8 +462,11 @@ wpa_supplicant_ctrl_iface_init(struct wpa_supplicant *wpa_s)
} }
void wpa_supplicant_ctrl_iface_deinit(struct ctrl_iface_priv *priv) void wpa_supplicant_ctrl_iface_deinit(struct wpa_supplicant *wpa_s,
struct ctrl_iface_priv *priv)
{ {
if (!priv)
return;
while (priv->ctrl_dst) while (priv->ctrl_dst)
ctrl_close_pipe(priv->ctrl_dst); ctrl_close_pipe(priv->ctrl_dst);
if (priv->sec_attr_set) if (priv->sec_attr_set)

View File

@ -490,8 +490,12 @@ wpa_supplicant_ctrl_iface_init(struct wpa_supplicant *wpa_s)
} }
void wpa_supplicant_ctrl_iface_deinit(struct ctrl_iface_priv *priv) void wpa_supplicant_ctrl_iface_deinit(struct wpa_supplicant *wpa_s,
struct ctrl_iface_priv *priv)
{ {
if (!priv)
return;
if (priv->sock > -1) { if (priv->sock > -1) {
eloop_unregister_read_sock(priv->sock); eloop_unregister_read_sock(priv->sock);
if (priv->ctrl_dst) { if (priv->ctrl_dst) {

View File

@ -800,12 +800,52 @@ static int wpas_ctrl_iface_reinit(struct wpa_supplicant *wpa_s,
} }
void wpa_supplicant_ctrl_iface_deinit(struct ctrl_iface_priv *priv) static void
wpas_global_ctrl_iface_flush_queued_msg(struct wpa_global *global,
struct wpa_supplicant *wpa_s)
{
struct ctrl_iface_global_priv *gpriv;
struct ctrl_iface_msg *msg, *prev_msg;
unsigned int count = 0;
if (!global || !global->ctrl_iface)
return;
gpriv = global->ctrl_iface;
dl_list_for_each_safe(msg, prev_msg, &gpriv->msg_queue,
struct ctrl_iface_msg, list) {
if (msg->wpa_s == wpa_s) {
count++;
dl_list_del(&msg->list);
os_free(msg);
}
}
if (count) {
wpa_printf(MSG_DEBUG,
"CTRL: Dropped %u pending message(s) for interface that is being removed",
count);
}
}
void wpa_supplicant_ctrl_iface_deinit(struct wpa_supplicant *wpa_s,
struct ctrl_iface_priv *priv)
{ {
struct wpa_ctrl_dst *dst, *prev; struct wpa_ctrl_dst *dst, *prev;
struct ctrl_iface_msg *msg, *prev_msg; struct ctrl_iface_msg *msg, *prev_msg;
struct ctrl_iface_global_priv *gpriv; struct ctrl_iface_global_priv *gpriv;
if (!priv) {
/* Control interface has not yet been initialized, so there is
* nothing to deinitialize here. However, there might be a
* pending message for this interface, so get rid of any such
* entry before completing interface removal. */
wpas_global_ctrl_iface_flush_queued_msg(wpa_s->global, wpa_s);
eloop_cancel_timeout(wpas_ctrl_msg_queue_timeout, wpa_s, NULL);
return;
}
if (priv->sock > -1) { if (priv->sock > -1) {
char *fname; char *fname;
char *buf, *dir = NULL; char *buf, *dir = NULL;
@ -877,6 +917,7 @@ void wpa_supplicant_ctrl_iface_deinit(struct ctrl_iface_priv *priv)
} }
} }
} }
wpas_global_ctrl_iface_flush_queued_msg(wpa_s->global, wpa_s);
eloop_cancel_timeout(wpas_ctrl_msg_queue_timeout, priv->wpa_s, NULL); eloop_cancel_timeout(wpas_ctrl_msg_queue_timeout, priv->wpa_s, NULL);
os_free(priv); os_free(priv);
} }

View File

@ -674,10 +674,8 @@ static void test_eapol_clean(struct eapol_test_data *e,
os_free(e->radius_conf); os_free(e->radius_conf);
e->radius_conf = NULL; e->radius_conf = NULL;
scard_deinit(wpa_s->scard); scard_deinit(wpa_s->scard);
if (wpa_s->ctrl_iface) { wpa_supplicant_ctrl_iface_deinit(wpa_s, wpa_s->ctrl_iface);
wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface);
wpa_s->ctrl_iface = NULL; wpa_s->ctrl_iface = NULL;
}
ext_password_deinit(wpa_s->ext_pw); ext_password_deinit(wpa_s->ext_pw);
wpa_s->ext_pw = NULL; wpa_s->ext_pw = NULL;

View File

@ -1102,14 +1102,11 @@ static bool sae_pk_acceptable_bss_with_pk(struct wpa_supplicant *wpa_s,
dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) { dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
int count; int count;
const u8 *ie; const u8 *ie;
u8 rsnxe_capa = 0;
if (bss == orig_bss) if (bss == orig_bss)
continue; continue;
ie = wpa_bss_get_ie(bss, WLAN_EID_RSNX); ie = wpa_bss_get_ie(bss, WLAN_EID_RSNX);
if (ie && ie[1] >= 1) if (!(ieee802_11_rsnx_capab(ie, WLAN_RSNX_CAPAB_SAE_PK)))
rsnxe_capa = ie[2];
if (!(rsnxe_capa & BIT(WLAN_RSNX_CAPAB_SAE_PK)))
continue; continue;
/* TODO: Could be more thorough in checking what kind of /* TODO: Could be more thorough in checking what kind of
@ -4405,6 +4402,8 @@ static void wpa_supplicant_event_assoc_auth(struct wpa_supplicant *wpa_s,
wpa_supplicant_event_port_authorized(wpa_s); wpa_supplicant_event_port_authorized(wpa_s);
wpa_s->last_eapol_matches_bssid = 1;
wpa_sm_set_rx_replay_ctr(wpa_s->wpa, data->assoc_info.key_replay_ctr); wpa_sm_set_rx_replay_ctr(wpa_s->wpa, data->assoc_info.key_replay_ctr);
wpa_sm_set_ptk_kck_kek(wpa_s->wpa, data->assoc_info.ptk_kck, wpa_sm_set_ptk_kck_kek(wpa_s->wpa, data->assoc_info.ptk_kck,
data->assoc_info.ptk_kck_len, data->assoc_info.ptk_kck_len,

View File

@ -344,7 +344,6 @@ static int mesh_rsn_build_sae_commit(struct wpa_supplicant *wpa_s,
} }
return sae_prepare_commit(wpa_s->own_addr, sta->addr, return sae_prepare_commit(wpa_s->own_addr, sta->addr,
(u8 *) password, os_strlen(password), (u8 *) password, os_strlen(password),
ssid->sae_password_id,
sta->sae); sta->sae);
} }

View File

@ -33,9 +33,18 @@ struct wpa_pasn_auth_work {
int cipher; int cipher;
u16 group; u16 group;
int network_id; int network_id;
struct wpabuf *comeback;
}; };
static void wpas_pasn_free_auth_work(struct wpa_pasn_auth_work *awork)
{
wpabuf_free(awork->comeback);
awork->comeback = NULL;
os_free(awork);
}
static void wpas_pasn_auth_work_timeout(void *eloop_ctx, void *timeout_ctx) static void wpas_pasn_auth_work_timeout(void *eloop_ctx, void *timeout_ctx)
{ {
struct wpa_supplicant *wpa_s = eloop_ctx; struct wpa_supplicant *wpa_s = eloop_ctx;
@ -56,8 +65,30 @@ static void wpas_pasn_cancel_auth_work(struct wpa_supplicant *wpa_s)
static void wpas_pasn_auth_status(struct wpa_supplicant *wpa_s, const u8 *bssid, static void wpas_pasn_auth_status(struct wpa_supplicant *wpa_s, const u8 *bssid,
int akmp, int cipher, u8 status) int akmp, int cipher, u8 status,
struct wpabuf *comeback,
u16 comeback_after)
{ {
if (comeback) {
size_t comeback_len = wpabuf_len(comeback);
size_t buflen = comeback_len * 2 + 1;
char *comeback_txt = os_malloc(buflen);
if (comeback_txt) {
wpa_snprintf_hex(comeback_txt, buflen,
wpabuf_head(comeback), comeback_len);
wpa_msg(wpa_s, MSG_INFO, PASN_AUTH_STATUS MACSTR
" akmp=%s, status=%u comeback_after=%u comeback=%s",
MAC2STR(bssid),
wpa_key_mgmt_txt(akmp, WPA_PROTO_RSN),
status, comeback_after, comeback_txt);
os_free(comeback_txt);
return;
}
}
wpa_msg(wpa_s, MSG_INFO, wpa_msg(wpa_s, MSG_INFO,
PASN_AUTH_STATUS MACSTR " akmp=%s, status=%u", PASN_AUTH_STATUS MACSTR " akmp=%s, status=%u",
MAC2STR(bssid), wpa_key_mgmt_txt(akmp, WPA_PROTO_RSN), MAC2STR(bssid), wpa_key_mgmt_txt(akmp, WPA_PROTO_RSN),
@ -71,30 +102,17 @@ static struct wpabuf * wpas_pasn_wd_sae_commit(struct wpa_supplicant *wpa_s)
{ {
struct wpas_pasn *pasn = &wpa_s->pasn; struct wpas_pasn *pasn = &wpa_s->pasn;
struct wpabuf *buf = NULL; struct wpabuf *buf = NULL;
const char *password = NULL;
int ret; int ret;
if (pasn->ssid) {
password = pasn->ssid->sae_password;
if (!password)
password = pasn->ssid->passphrase;
}
if (!password) {
wpa_printf(MSG_DEBUG, "PASN: SAE without a password");
return NULL;
}
ret = sae_set_group(&pasn->sae, pasn->group); ret = sae_set_group(&pasn->sae, pasn->group);
if (ret) { if (ret) {
wpa_printf(MSG_DEBUG, "PASN: Failed to set SAE group"); wpa_printf(MSG_DEBUG, "PASN: Failed to set SAE group");
return NULL; return NULL;
} }
/* TODO: SAE H2E */ ret = sae_prepare_commit_pt(&pasn->sae, pasn->ssid->pt,
ret = sae_prepare_commit(wpa_s->own_addr, pasn->bssid, wpa_s->own_addr, pasn->bssid,
(const u8 *) password, os_strlen(password), 0, NULL, NULL);
&pasn->sae);
if (ret) { if (ret) {
wpa_printf(MSG_DEBUG, "PASN: Failed to prepare SAE commit"); wpa_printf(MSG_DEBUG, "PASN: Failed to prepare SAE commit");
return NULL; return NULL;
@ -109,7 +127,7 @@ static struct wpabuf * wpas_pasn_wd_sae_commit(struct wpa_supplicant *wpa_s)
wpabuf_put_le16(buf, WLAN_AUTH_SAE); wpabuf_put_le16(buf, WLAN_AUTH_SAE);
wpabuf_put_le16(buf, 1); wpabuf_put_le16(buf, 1);
wpabuf_put_le16(buf, WLAN_STATUS_SUCCESS); wpabuf_put_le16(buf, WLAN_STATUS_SAE_HASH_TO_ELEMENT);
sae_write_commit(&pasn->sae, buf, NULL, 0); sae_write_commit(&pasn->sae, buf, NULL, 0);
pasn->sae.state = SAE_COMMITTED; pasn->sae.state = SAE_COMMITTED;
@ -155,14 +173,14 @@ static int wpas_pasn_wd_sae_rx(struct wpa_supplicant *wpa_s, struct wpabuf *wd)
wpa_printf(MSG_DEBUG, "PASN: SAE: commit: alg=%u, seq=%u, status=%u", wpa_printf(MSG_DEBUG, "PASN: SAE: commit: alg=%u, seq=%u, status=%u",
alg, seq, status); alg, seq, status);
/* TODO: SAE H2E */ if (alg != WLAN_AUTH_SAE || seq != 1 ||
if (alg != WLAN_AUTH_SAE || seq != 1 || status != WLAN_STATUS_SUCCESS) { status != WLAN_STATUS_SAE_HASH_TO_ELEMENT) {
wpa_printf(MSG_DEBUG, "PASN: SAE: dropping peer commit"); wpa_printf(MSG_DEBUG, "PASN: SAE: dropping peer commit");
return -1; return -1;
} }
res = sae_parse_commit(&pasn->sae, data + 6, len - 6, NULL, 0, groups, res = sae_parse_commit(&pasn->sae, data + 6, len - 6, NULL, 0, groups,
0); 1);
if (res != WLAN_STATUS_SUCCESS) { if (res != WLAN_STATUS_SUCCESS) {
wpa_printf(MSG_DEBUG, "PASN: SAE failed parsing commit"); wpa_printf(MSG_DEBUG, "PASN: SAE failed parsing commit");
return -1; return -1;
@ -240,6 +258,31 @@ static struct wpabuf * wpas_pasn_wd_sae_confirm(struct wpa_supplicant *wpa_s)
return buf; return buf;
} }
static int wpas_pasn_sae_setup_pt(struct wpa_supplicant *wpa_s,
struct wpa_ssid *ssid, int group)
{
const char *password = ssid->sae_password;
int groups[2] = { group, 0 };
if (!password)
password = ssid->passphrase;
if (!password) {
wpa_printf(MSG_DEBUG, "PASN: SAE without a password");
return -1;
}
if (ssid->pt)
return 0; /* PT already derived */
ssid->pt = sae_derive_pt(groups, ssid->ssid, ssid->ssid_len,
(const u8 *) password, os_strlen(password),
ssid->sae_password_id);
return ssid->pt ? 0 : -1;
}
#endif /* CONFIG_SAE */ #endif /* CONFIG_SAE */
@ -612,7 +655,8 @@ static u8 wpas_pasn_get_wrapped_data_format(struct wpas_pasn *pasn)
} }
static struct wpabuf * wpas_pasn_build_auth_1(struct wpa_supplicant *wpa_s) static struct wpabuf * wpas_pasn_build_auth_1(struct wpa_supplicant *wpa_s,
const struct wpabuf *comeback)
{ {
struct wpas_pasn *pasn = &wpa_s->pasn; struct wpas_pasn *pasn = &wpa_s->pasn;
struct wpabuf *buf, *pubkey = NULL, *wrapped_data_buf = NULL; struct wpabuf *buf, *pubkey = NULL, *wrapped_data_buf = NULL;
@ -680,14 +724,14 @@ static struct wpabuf * wpas_pasn_build_auth_1(struct wpa_supplicant *wpa_s)
wrapped_data = WPA_PASN_WRAPPED_DATA_NO; wrapped_data = WPA_PASN_WRAPPED_DATA_NO;
wpa_pasn_add_parameter_ie(buf, pasn->group, wrapped_data, wpa_pasn_add_parameter_ie(buf, pasn->group, wrapped_data,
pubkey, true, NULL, -1); pubkey, true, comeback, -1);
if (wpa_pasn_add_wrapped_data(buf, wrapped_data_buf) < 0) if (wpa_pasn_add_wrapped_data(buf, wrapped_data_buf) < 0)
goto fail; goto fail;
/* Add own RNSXE */ /* Add own RNSXE */
/* TODO: How to handle protected TWT and SAE H2E? */
capab = 0; capab = 0;
capab |= BIT(WLAN_RSNX_CAPAB_SAE_H2E);
if (wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_SEC_LTF) if (wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_SEC_LTF)
capab |= BIT(WLAN_RSNX_CAPAB_SECURE_LTF); capab |= BIT(WLAN_RSNX_CAPAB_SECURE_LTF);
if (wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_SEC_RTT) if (wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_SEC_RTT)
@ -828,6 +872,10 @@ static void wpas_pasn_reset(struct wpa_supplicant *wpa_s)
wpabuf_free(pasn->beacon_rsne_rsnxe); wpabuf_free(pasn->beacon_rsne_rsnxe);
pasn->beacon_rsne_rsnxe = NULL; pasn->beacon_rsne_rsnxe = NULL;
wpabuf_free(pasn->comeback);
pasn->comeback = NULL;
pasn->comeback_after = 0;
#ifdef CONFIG_SAE #ifdef CONFIG_SAE
sae_clear_data(&pasn->sae); sae_clear_data(&pasn->sae);
#endif /* CONFIG_SAE */ #endif /* CONFIG_SAE */
@ -946,7 +994,7 @@ static int wpas_pasn_start(struct wpa_supplicant *wpa_s, const u8 *bssid,
int akmp, int cipher, u16 group, int freq, int akmp, int cipher, u16 group, int freq,
const u8 *beacon_rsne, u8 beacon_rsne_len, const u8 *beacon_rsne, u8 beacon_rsne_len,
const u8 *beacon_rsnxe, u8 beacon_rsnxe_len, const u8 *beacon_rsnxe, u8 beacon_rsnxe_len,
int network_id) int network_id, struct wpabuf *comeback)
{ {
struct wpas_pasn *pasn = &wpa_s->pasn; struct wpas_pasn *pasn = &wpa_s->pasn;
struct wpa_ssid *ssid = NULL; struct wpa_ssid *ssid = NULL;
@ -972,6 +1020,20 @@ static int wpas_pasn_start(struct wpa_supplicant *wpa_s, const u8 *bssid,
"PASN: No network profile found for SAE"); "PASN: No network profile found for SAE");
return -1; return -1;
} }
if (!ieee802_11_rsnx_capab(beacon_rsnxe,
WLAN_RSNX_CAPAB_SAE_H2E)) {
wpa_printf(MSG_DEBUG,
"PASN: AP does not support SAE H2E");
return -1;
}
if (wpas_pasn_sae_setup_pt(wpa_s, ssid, group) < 0) {
wpa_printf(MSG_DEBUG,
"PASN: Failed to derive PT");
return -1;
}
pasn->sae.state = SAE_NOTHING; pasn->sae.state = SAE_NOTHING;
pasn->sae.send_confirm = 0; pasn->sae.send_confirm = 0;
pasn->ssid = ssid; pasn->ssid = ssid;
@ -1016,6 +1078,15 @@ static int wpas_pasn_start(struct wpa_supplicant *wpa_s, const u8 *bssid,
pasn->cipher = cipher; pasn->cipher = cipher;
pasn->group = group; pasn->group = group;
pasn->freq = freq; pasn->freq = freq;
if (wpa_s->conf->force_kdk_derivation ||
(wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_SEC_LTF &&
ieee802_11_rsnx_capab(beacon_rsnxe, WLAN_RSNX_CAPAB_SECURE_LTF)))
pasn->kdk_len = WPA_KDK_MAX_LEN;
else
pasn->kdk_len = 0;
wpa_printf(MSG_DEBUG, "PASN: kdk_len=%zu", pasn->kdk_len);
os_memcpy(pasn->bssid, bssid, ETH_ALEN); os_memcpy(pasn->bssid, bssid, ETH_ALEN);
wpa_printf(MSG_DEBUG, wpa_printf(MSG_DEBUG,
@ -1023,7 +1094,7 @@ static int wpas_pasn_start(struct wpa_supplicant *wpa_s, const u8 *bssid,
MAC2STR(pasn->bssid), pasn->akmp, pasn->cipher, MAC2STR(pasn->bssid), pasn->akmp, pasn->cipher,
pasn->group); pasn->group);
frame = wpas_pasn_build_auth_1(wpa_s); frame = wpas_pasn_build_auth_1(wpa_s, comeback);
if (!frame) { if (!frame) {
wpa_printf(MSG_DEBUG, "PASN: Failed building 1st auth frame"); wpa_printf(MSG_DEBUG, "PASN: Failed building 1st auth frame");
goto fail; goto fail;
@ -1105,7 +1176,8 @@ static void wpas_pasn_auth_start_cb(struct wpa_radio_work *work, int deinit)
wpa_s, NULL); wpa_s, NULL);
wpa_s->pasn_auth_work = NULL; wpa_s->pasn_auth_work = NULL;
} }
os_free(awork);
wpas_pasn_free_auth_work(awork);
return; return;
} }
@ -1132,24 +1204,29 @@ static void wpas_pasn_auth_start_cb(struct wpa_radio_work *work, int deinit)
ret = wpas_pasn_start(wpa_s, awork->bssid, awork->akmp, awork->cipher, ret = wpas_pasn_start(wpa_s, awork->bssid, awork->akmp, awork->cipher,
awork->group, bss->freq, rsne, *(rsne + 1) + 2, awork->group, bss->freq, rsne, *(rsne + 1) + 2,
rsnxe, rsnxe ? *(rsnxe + 1) + 2 : 0, rsnxe, rsnxe ? *(rsnxe + 1) + 2 : 0,
awork->network_id); awork->network_id, awork->comeback);
if (ret) { if (ret) {
wpa_printf(MSG_DEBUG, wpa_printf(MSG_DEBUG,
"PASN: Failed to start PASN authentication"); "PASN: Failed to start PASN authentication");
goto fail; goto fail;
} }
/* comeback token is no longer needed at this stage */
wpabuf_free(awork->comeback);
awork->comeback = NULL;
wpa_s->pasn_auth_work = work; wpa_s->pasn_auth_work = work;
return; return;
fail: fail:
os_free(awork); wpas_pasn_free_auth_work(awork);
work->ctx = NULL; work->ctx = NULL;
radio_work_done(work); radio_work_done(work);
} }
int wpas_pasn_auth_start(struct wpa_supplicant *wpa_s, const u8 *bssid, int wpas_pasn_auth_start(struct wpa_supplicant *wpa_s, const u8 *bssid,
int akmp, int cipher, u16 group, int network_id) int akmp, int cipher, u16 group, int network_id,
const u8 *comeback, size_t comeback_len)
{ {
struct wpa_pasn_auth_work *awork; struct wpa_pasn_auth_work *awork;
struct wpa_bss *bss; struct wpa_bss *bss;
@ -1195,9 +1272,17 @@ int wpas_pasn_auth_start(struct wpa_supplicant *wpa_s, const u8 *bssid,
awork->group = group; awork->group = group;
awork->network_id = network_id; awork->network_id = network_id;
if (comeback && comeback_len) {
awork->comeback = wpabuf_alloc_copy(comeback, comeback_len);
if (!awork->comeback) {
wpas_pasn_free_auth_work(awork);
return -1;
}
}
if (radio_add_work(wpa_s, bss->freq, "pasn-start-auth", 1, if (radio_add_work(wpa_s, bss->freq, "pasn-start-auth", 1,
wpas_pasn_auth_start_cb, awork) < 0) { wpas_pasn_auth_start_cb, awork) < 0) {
os_free(awork); wpas_pasn_free_auth_work(awork);
return -1; return -1;
} }
@ -1216,12 +1301,33 @@ void wpas_pasn_auth_stop(struct wpa_supplicant *wpa_s)
wpa_printf(MSG_DEBUG, "PASN: Stopping authentication"); wpa_printf(MSG_DEBUG, "PASN: Stopping authentication");
wpas_pasn_auth_status(wpa_s, pasn->bssid, pasn->akmp, pasn->cipher, wpas_pasn_auth_status(wpa_s, pasn->bssid, pasn->akmp, pasn->cipher,
pasn->status); pasn->status, pasn->comeback,
pasn->comeback_after);
wpas_pasn_reset(wpa_s); wpas_pasn_reset(wpa_s);
} }
static int wpas_pasn_immediate_retry(struct wpa_supplicant *wpa_s,
struct wpas_pasn *pasn,
struct wpa_pasn_params_data *params)
{
int akmp = pasn->akmp;
int cipher = pasn->cipher;
u16 group = pasn->group;
u8 bssid[ETH_ALEN];
int network_id = pasn->ssid ? pasn->ssid->id : 0;
wpa_printf(MSG_DEBUG, "PASN: Immediate retry");
os_memcpy(bssid, pasn->bssid, ETH_ALEN);
wpas_pasn_reset(wpa_s);
return wpas_pasn_auth_start(wpa_s, bssid, akmp, cipher, group,
network_id,
params->comeback, params->comeback_len);
}
int wpas_pasn_auth_rx(struct wpa_supplicant *wpa_s, int wpas_pasn_auth_rx(struct wpa_supplicant *wpa_s,
const struct ieee80211_mgmt *mgmt, size_t len) const struct ieee80211_mgmt *mgmt, size_t len)
{ {
@ -1315,10 +1421,26 @@ int wpas_pasn_auth_rx(struct wpa_supplicant *wpa_s,
goto fail; goto fail;
} }
/* TODO: handle comeback flow */
if (status == WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY) { if (status == WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY) {
wpa_printf(MSG_DEBUG, wpa_printf(MSG_DEBUG,
"PASN: Authentication temporarily rejected"); "PASN: Authentication temporarily rejected");
if (pasn_params.comeback && pasn_params.comeback_len) {
wpa_printf(MSG_DEBUG,
"PASN: Comeback token available. After=%u",
pasn_params.after);
if (!pasn_params.after)
return wpas_pasn_immediate_retry(wpa_s, pasn,
&pasn_params);
pasn->comeback = wpabuf_alloc_copy(
pasn_params.comeback, pasn_params.comeback_len);
if (pasn->comeback)
pasn->comeback_after = pasn_params.after;
}
pasn->status = status;
goto fail; goto fail;
} }
@ -1393,7 +1515,7 @@ int wpas_pasn_auth_rx(struct wpa_supplicant *wpa_s,
wpa_s->own_addr, pasn->bssid, wpa_s->own_addr, pasn->bssid,
wpabuf_head(secret), wpabuf_len(secret), wpabuf_head(secret), wpabuf_len(secret),
&pasn->ptk, pasn->akmp, pasn->cipher, &pasn->ptk, pasn->akmp, pasn->cipher,
WPA_KDK_MAX_LEN); pasn->kdk_len);
if (ret) { if (ret) {
wpa_printf(MSG_DEBUG, "PASN: Failed to derive PTK"); wpa_printf(MSG_DEBUG, "PASN: Failed to derive PTK");
goto fail; goto fail;
@ -1456,7 +1578,11 @@ int wpas_pasn_auth_rx(struct wpa_supplicant *wpa_s,
* the frame and terminate the authentication exchange. However, better * the frame and terminate the authentication exchange. However, better
* reply to the AP with an error status. * reply to the AP with an error status.
*/ */
if (status == WLAN_STATUS_SUCCESS)
pasn->status = WLAN_STATUS_UNSPECIFIED_FAILURE; pasn->status = WLAN_STATUS_UNSPECIFIED_FAILURE;
else
pasn->status = status;
wpas_pasn_auth_stop(wpa_s); wpas_pasn_auth_stop(wpa_s);
return -1; return -1;
} }

View File

@ -193,10 +193,8 @@ static void test_eapol_clean(struct wpa_supplicant *wpa_s)
pmksa_candidate_free(wpa_s->wpa); pmksa_candidate_free(wpa_s->wpa);
wpa_sm_deinit(wpa_s->wpa); wpa_sm_deinit(wpa_s->wpa);
scard_deinit(wpa_s->scard); scard_deinit(wpa_s->scard);
if (wpa_s->ctrl_iface) { wpa_supplicant_ctrl_iface_deinit(wpa_s, wpa_s->ctrl_iface);
wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface);
wpa_s->ctrl_iface = NULL; wpa_s->ctrl_iface = NULL;
}
wpa_config_free(wpa_s->conf); wpa_config_free(wpa_s->conf);
} }

View File

@ -118,7 +118,7 @@ void wpas_handle_robust_av_recv_action(struct wpa_supplicant *wpa_s,
return; return;
} }
status_code = *buf; status_code = WPA_GET_LE16(buf);
wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_MSCS_RESULT "bssid=" MACSTR wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_MSCS_RESULT "bssid=" MACSTR
" status_code=%u", MAC2STR(src), status_code); " status_code=%u", MAC2STR(src), status_code);
wpa_s->mscs_setup_done = status_code == WLAN_STATUS_SUCCESS; wpa_s->mscs_setup_done = status_code == WLAN_STATUS_SUCCESS;

View File

@ -186,7 +186,6 @@ static struct wpabuf * sme_auth_build_sae_commit(struct wpa_supplicant *wpa_s,
if (!use_pt && if (!use_pt &&
sae_prepare_commit(wpa_s->own_addr, bssid, sae_prepare_commit(wpa_s->own_addr, bssid,
(u8 *) password, os_strlen(password), (u8 *) password, os_strlen(password),
ssid->sae_password_id,
&wpa_s->sme.sae) < 0) { &wpa_s->sme.sae) < 0) {
wpa_printf(MSG_DEBUG, "SAE: Could not pick PWE"); wpa_printf(MSG_DEBUG, "SAE: Could not pick PWE");
return NULL; return NULL;

View File

@ -1158,8 +1158,8 @@ int wpa_supplicant_reload_configuration(struct wpa_supplicant *wpa_s)
os_strcmp(conf->ctrl_interface, os_strcmp(conf->ctrl_interface,
wpa_s->conf->ctrl_interface) != 0); wpa_s->conf->ctrl_interface) != 0);
if (reconf_ctrl && wpa_s->ctrl_iface) { if (reconf_ctrl) {
wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface); wpa_supplicant_ctrl_iface_deinit(wpa_s, wpa_s->ctrl_iface);
wpa_s->ctrl_iface = NULL; wpa_s->ctrl_iface = NULL;
} }
@ -6748,10 +6748,8 @@ static void wpa_supplicant_deinit_iface(struct wpa_supplicant *wpa_s,
if (terminate) if (terminate)
wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TERMINATING); wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TERMINATING);
if (wpa_s->ctrl_iface) { wpa_supplicant_ctrl_iface_deinit(wpa_s, wpa_s->ctrl_iface);
wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface);
wpa_s->ctrl_iface = NULL; wpa_s->ctrl_iface = NULL;
}
#ifdef CONFIG_MESH #ifdef CONFIG_MESH
if (wpa_s->ifmsh) { if (wpa_s->ifmsh) {

View File

@ -539,6 +539,7 @@ struct wpas_pasn {
int cipher; int cipher;
u16 group; u16 group;
int freq; int freq;
size_t kdk_len;
u8 trans_seq; u8 trans_seq;
u8 status; u8 status;
@ -554,6 +555,9 @@ struct wpas_pasn {
struct wpa_ptk ptk; struct wpa_ptk ptk;
struct crypto_ecdh *ecdh; struct crypto_ecdh *ecdh;
struct wpabuf *comeback;
u16 comeback_after;
#ifdef CONFIG_SAE #ifdef CONFIG_SAE
struct sae_data sae; struct sae_data sae;
#endif /* CONFIG_SAE */ #endif /* CONFIG_SAE */
@ -1730,7 +1734,8 @@ void wpas_handle_assoc_resp_mscs(struct wpa_supplicant *wpa_s, const u8 *bssid,
int wpas_pasn_auth_start(struct wpa_supplicant *wpa_s, int wpas_pasn_auth_start(struct wpa_supplicant *wpa_s,
const u8 *bssid, int akmp, int cipher, const u8 *bssid, int akmp, int cipher,
u16 group, int network_id); u16 group, int network_id,
const u8 *comeback, size_t comeback_len);
void wpas_pasn_auth_stop(struct wpa_supplicant *wpa_s); void wpas_pasn_auth_stop(struct wpa_supplicant *wpa_s);
int wpas_pasn_auth_tx_status(struct wpa_supplicant *wpa_s, int wpas_pasn_auth_tx_status(struct wpa_supplicant *wpa_s,
const u8 *data, size_t data_len, u8 acked); const u8 *data, size_t data_len, u8 acked);