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

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

View File

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

View File

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

View File

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

View File

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

View File

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

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

View File

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

View File

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

View File

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

View File

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

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 *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)
len = hapd->iface->extended_capa_len;
if (len == 0)
return eid;
*pos++ = WLAN_EID_EXT_CAPAB;
*pos++ = len;
@ -525,6 +465,11 @@ u8 * hostapd_eid_ext_capab(struct hostapd_data *hapd, u8 *eid)
*pos &= ~hapd->iface->extended_capa_mask[i];
*pos |= hapd->iface->extended_capa[i];
}
if (i < EXT_CAPA_MAX_LEN) {
*pos &= ~hapd->conf->ext_capa_mask[i];
*pos |= hapd->conf->ext_capa[i];
}
}
while (len > 0 && eid[1 + len] == 0) {

View File

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

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

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 ||
(sm->wpa_auth->conf.secure_ltf &&
sm->rsnxe && sm->rsnxe_len >= 4 &&
sm->rsnxe[3] & BIT(WLAN_RSNX_CAPAB_SECURE_LTF - 8)))
ieee802_11_rsnx_capab(sm->rsnxe, WLAN_RSNX_CAPAB_SECURE_LTF)))
kdk_len = WPA_KDK_MAX_LEN;
else
kdk_len = 0;

View File

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

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,
int primary_channel,
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);
int ieee802_11_ext_capab(const u8 *ie, unsigned int capab);
bool ieee802_11_rsnx_capab_len(const u8 *rsnxe, size_t rsnxe_len,
unsigned int capab);
bool ieee802_11_rsnx_capab(const u8 *rsnxe, unsigned int capab);
int op_class_to_bandwidth(u8 op_class);
int op_class_to_ch_width(u8 op_class);

View File

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

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

View File

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

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,
u8 wrapped_data_format,
struct wpabuf *pubkey, bool compressed,
struct wpabuf *comeback, int after)
const struct wpabuf *pubkey, bool compressed,
const struct wpabuf *comeback, int after)
{
struct pasn_parameter_ie *params;

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,
u8 wrapped_data_format,
struct wpabuf *pubkey, bool compressed,
struct wpabuf *comeback, int after);
const struct wpabuf *pubkey, bool compressed,
const struct wpabuf *comeback, int after);
int wpa_pasn_add_wrapped_data(struct wpabuf *buf,
struct wpabuf *wrapped_data_buf);

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)
{
if (pkey->type != EVP_PKEY_EC)
return NULL;
return pkey->pkey.ec;
}
#endif /* CONFIG_ECC */
#endif /* OpenSSL version < 1.1.0 */

View File

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

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

View File

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

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)
{
static const char *anonymous_id_prefix = "anonymous@";
const u8 *decorated;
size_t anonymous_id_len = os_strlen(anonymous_id_prefix);
if (id_len > anonymous_id_len &&
@ -1226,5 +1241,14 @@ int eap_sim_anonymous_username(const u8 *id, size_t id_len)
if (id_len > 1 && id[0] == '@')
return 1; /* '@realm' */
/* RFC 7542 decorated username, for example:
* homerealm.example.org!anonymous@otherrealm.example.net */
decorated = get_last_char(id, id_len, '!');
if (decorated) {
decorated++;
return eap_sim_anonymous_username(decorated,
id + id_len - decorated);
}
return 0;
}

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

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

View File

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

View File

@ -113,3 +113,4 @@ CONFIG_DPP=y
CONFIG_DPP2=y
CONFIG_WEP=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")
return int(res)
def dpp_nfc_uri(self, uri):
res = self.request("DPP_NFC_URI " + uri)
if "FAIL" in res:
raise Exception("Failed to parse NFC URI")
return int(res)
def dpp_bootstrap_gen(self, type="qrcode", chan=None, mac=None, info=None,
curve=None, key=None):
cmd = "DPP_BOOTSTRAP_GEN type=" + type
@ -466,10 +472,14 @@ def dpp_listen(self, freq, netrole=None, qr=None, role=None):
def dpp_auth_init(self, peer=None, uri=None, conf=None, configurator=None,
extra=None, own=None, role=None, neg_freq=None,
ssid=None, passphrase=None, expect_fail=False):
ssid=None, passphrase=None, expect_fail=False,
conn_status=False, nfc_uri=None):
cmd = "DPP_AUTH_INIT"
if peer is None:
peer = self.dpp_qr_code(uri)
if nfc_uri:
peer = self.dpp_nfc_uri(nfc_uri)
else:
peer = self.dpp_qr_code(uri)
cmd += " peer=%d" % peer
if own is not None:
cmd += " own=%d" % own
@ -487,6 +497,8 @@ def dpp_auth_init(self, peer=None, uri=None, conf=None, configurator=None,
cmd += " ssid=" + binascii.hexlify(ssid.encode()).decode()
if passphrase:
cmd += " pass=" + binascii.hexlify(passphrase.encode()).decode()
if conn_status:
cmd += " conn_status=1"
res = self.request(cmd)
if expect_fail:
if "FAIL" not in res:

View File

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

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

View File

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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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

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

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

View File

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

View File

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

View File

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

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

View File

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

View File

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

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) {
eapol_sm_configure(wpa_s->eapol,
-1, -1, -1, atoi(value));
#ifdef CONFIG_TESTING_OPTIONS
} else if (os_strcasecmp(cmd, "EAPOL::portControl") == 0) {
if (os_strcmp(value, "Auto") == 0)
eapol_sm_notify_portControl(wpa_s->eapol, Auto);
else if (os_strcmp(value, "ForceUnauthorized") == 0)
eapol_sm_notify_portControl(wpa_s->eapol,
ForceUnauthorized);
else if (os_strcmp(value, "ForceAuthorized") == 0)
eapol_sm_notify_portControl(wpa_s->eapol,
ForceAuthorized);
else
ret = -1;
#endif /* CONFIG_TESTING_OPTIONS */
} else if (os_strcasecmp(cmd, "dot11RSNAConfigPMKLifetime") == 0) {
if (wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
atoi(value))) {
@ -2999,19 +3012,17 @@ static int wpa_supplicant_ctrl_iface_scan_result(
ie2, 2 + ie2[1]);
}
rsnxe = wpa_bss_get_ie(bss, WLAN_EID_RSNX);
if (rsnxe && rsnxe[1] >= 1) {
if (rsnxe[2] & BIT(WLAN_RSNX_CAPAB_SAE_H2E)) {
ret = os_snprintf(pos, end - pos, "[SAE-H2E]");
if (os_snprintf_error(end - pos, ret))
return -1;
pos += ret;
}
if (rsnxe[2] & BIT(WLAN_RSNX_CAPAB_SAE_PK)) {
ret = os_snprintf(pos, end - pos, "[SAE-PK]");
if (os_snprintf_error(end - pos, ret))
return -1;
pos += ret;
}
if (ieee802_11_rsnx_capab(rsnxe, WLAN_RSNX_CAPAB_SAE_H2E)) {
ret = os_snprintf(pos, end - pos, "[SAE-H2E]");
if (os_snprintf_error(end - pos, ret))
return -1;
pos += ret;
}
if (ieee802_11_rsnx_capab(rsnxe, WLAN_RSNX_CAPAB_SAE_PK)) {
ret = os_snprintf(pos, end - pos, "[SAE-PK]");
if (os_snprintf_error(end - pos, ret))
return -1;
pos += ret;
}
osen_ie = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE);
if (osen_ie)
@ -5099,19 +5110,17 @@ static int print_bss_info(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
mesh ? "RSN" : "WPA2", ie2,
2 + ie2[1]);
rsnxe = wpa_bss_get_ie(bss, WLAN_EID_RSNX);
if (rsnxe && rsnxe[1] >= 1) {
if (rsnxe[2] & BIT(WLAN_RSNX_CAPAB_SAE_H2E)) {
ret = os_snprintf(pos, end - pos, "[SAE-H2E]");
if (os_snprintf_error(end - pos, ret))
return -1;
pos += ret;
}
if (rsnxe[2] & BIT(WLAN_RSNX_CAPAB_SAE_PK)) {
ret = os_snprintf(pos, end - pos, "[SAE-PK]");
if (os_snprintf_error(end - pos, ret))
return -1;
pos += ret;
}
if (ieee802_11_rsnx_capab(rsnxe, WLAN_RSNX_CAPAB_SAE_H2E)) {
ret = os_snprintf(pos, end - pos, "[SAE-H2E]");
if (os_snprintf_error(end - pos, ret))
return -1;
pos += ret;
}
if (ieee802_11_rsnx_capab(rsnxe, WLAN_RSNX_CAPAB_SAE_PK)) {
ret = os_snprintf(pos, end - pos, "[SAE-PK]");
if (os_snprintf_error(end - pos, ret))
return -1;
pos += ret;
}
osen_ie = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE);
if (osen_ie)
@ -9300,6 +9309,132 @@ 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)
{
char *pos, *param;
@ -9332,6 +9467,8 @@ static int wpas_ctrl_iface_driver_event(struct wpa_supplicant *wpa_s, char *cmd)
return 0;
} else if (os_strcmp(cmd, "SCAN_RES") == 0) {
return wpas_ctrl_iface_driver_scan_res(wpa_s, param);
} else if (os_strcmp(cmd, "ASSOC") == 0) {
return wpas_ctrl_iface_driver_event_assoc(wpa_s, param);
} else {
wpa_dbg(wpa_s, MSG_DEBUG, "Testing - unknown driver event: %s",
cmd);
@ -10598,15 +10735,18 @@ static int wpas_ctrl_iface_pasn_start(struct wpa_supplicant *wpa_s, char *cmd)
u8 bssid[ETH_ALEN];
int akmp = -1, cipher = -1, got_bssid = 0;
u16 group = 0xFFFF;
int id = 0;
u8 *comeback = NULL;
size_t comeback_len = 0;
int id = 0, ret = -1;
/*
* Entry format: bssid=<BSSID> akmp=<AKMP> cipher=<CIPHER> group=<group>
* [comeback=<hexdump>]
*/
while ((token = str_token(cmd, " ", &context))) {
if (os_strncmp(token, "bssid=", 6) == 0) {
if (hwaddr_aton(token + 6, bssid))
return -1;
goto out;
got_bssid = 1;
} else if (os_strcmp(token, "akmp=PASN") == 0) {
akmp = WPA_KEY_MGMT_PASN;
@ -10640,20 +10780,34 @@ static int wpas_ctrl_iface_pasn_start(struct wpa_supplicant *wpa_s, char *cmd)
group = atoi(token + 6);
} else if (os_strncmp(token, "nid=", 4) == 0) {
id = atoi(token + 4);
} else if (os_strncmp(token, "comeback=", 9) == 0) {
comeback_len = os_strlen(token + 9);
if (comeback || !comeback_len || comeback_len % 2)
goto out;
comeback_len /= 2;
comeback = os_malloc(comeback_len);
if (!comeback ||
hexstr2bin(token + 9, comeback, comeback_len))
goto out;
} else {
wpa_printf(MSG_DEBUG,
"CTRL: PASN Invalid parameter: '%s'",
token);
return -1;
goto out;
}
}
if (!got_bssid || akmp == -1 || cipher == -1 || group == 0xFFFF) {
wpa_printf(MSG_DEBUG,"CTRL: PASN missing parameter");
return -1;
goto out;
}
return wpas_pasn_auth_start(wpa_s, bssid, akmp, cipher, group, id);
ret = wpas_pasn_auth_start(wpa_s, bssid, akmp, cipher, group, id,
comeback, comeback_len);
out:
os_free(comeback);
return ret;
}

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

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)
ctrl_close_pipe(priv->ctrl_dst);
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) {
eloop_unregister_read_sock(priv->sock);
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 ctrl_iface_msg *msg, *prev_msg;
struct ctrl_iface_global_priv *gpriv;
if (!priv) {
/* Control interface has not yet been initialized, so there is
* nothing to deinitialize here. However, there might be a
* pending message for this interface, so get rid of any such
* entry before completing interface removal. */
wpas_global_ctrl_iface_flush_queued_msg(wpa_s->global, wpa_s);
eloop_cancel_timeout(wpas_ctrl_msg_queue_timeout, wpa_s, NULL);
return;
}
if (priv->sock > -1) {
char *fname;
char *buf, *dir = NULL;
@ -877,6 +917,7 @@ 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);
os_free(priv);
}

View File

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

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

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,
(u8 *) password, os_strlen(password),
ssid->sae_password_id,
sta->sae);
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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