diff --git a/src/ap/drv_callbacks.c b/src/ap/drv_callbacks.c index 290d354a0..ec5abf166 100644 --- a/src/ap/drv_callbacks.c +++ b/src/ap/drv_callbacks.c @@ -459,8 +459,8 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr, if (hapd->conf->sae_pwe == 2 && sta->auth_alg == WLAN_AUTH_SAE && sta->sae && !sta->sae->h2e && - elems.rsnxe && elems.rsnxe_len >= 1 && - (elems.rsnxe[0] & BIT(WLAN_RSNX_CAPAB_SAE_H2E))) { + ieee802_11_rsnx_capab_len(elems.rsnxe, elems.rsnxe_len, + WLAN_RSNX_CAPAB_SAE_H2E)) { wpa_printf(MSG_INFO, "SAE: " MACSTR " indicates support for SAE H2E, but did not use it", MAC2STR(sta->addr)); diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c index 7b96ba07d..b404e84af 100644 --- a/src/ap/ieee802_11.c +++ b/src/ap/ieee802_11.c @@ -3153,8 +3153,8 @@ static void handle_auth_pasn_1(struct hostapd_data *hapd, struct sta_info *sta, if (hapd->conf->force_kdk_derivation || ((hapd->iface->drv_flags2 & WPA_DRIVER_FLAGS2_SEC_LTF) && - elems.rsnxe && elems.rsnxe_len >= 2 && - (WPA_GET_LE16(elems.rsnxe) & BIT(WLAN_RSNX_CAPAB_SECURE_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; @@ -4693,8 +4693,8 @@ static int check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta, if (hapd->conf->sae_pwe == 2 && sta->auth_alg == WLAN_AUTH_SAE && sta->sae && !sta->sae->h2e && - elems.rsnxe && elems.rsnxe_len >= 1 && - (elems.rsnxe[0] & BIT(WLAN_RSNX_CAPAB_SAE_H2E))) { + ieee802_11_rsnx_capab_len(elems.rsnxe, elems.rsnxe_len, + WLAN_RSNX_CAPAB_SAE_H2E)) { wpa_printf(MSG_INFO, "SAE: " MACSTR " indicates support for SAE H2E, but did not use it", MAC2STR(sta->addr)); diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c index ef0595c57..59cd46aa4 100644 --- a/src/ap/wpa_auth.c +++ b/src/ap/wpa_auth.c @@ -2283,8 +2283,7 @@ static int wpa_derive_ptk(struct wpa_state_machine *sm, const u8 *snonce, if (sm->wpa_auth->conf.force_kdk_derivation || (sm->wpa_auth->conf.secure_ltf && - sm->rsnxe && sm->rsnxe_len >= 4 && - sm->rsnxe[3] & BIT(WLAN_RSNX_CAPAB_SECURE_LTF - 8))) + ieee802_11_rsnx_capab(sm->rsnxe, WLAN_RSNX_CAPAB_SECURE_LTF))) kdk_len = WPA_KDK_MAX_LEN; else kdk_len = 0; @@ -2338,8 +2337,7 @@ int fils_auth_pmk_to_ptk(struct wpa_state_machine *sm, const u8 *pmk, if (sm->wpa_auth->conf.force_kdk_derivation || (sm->wpa_auth->conf.secure_ltf && - sm->rsnxe && sm->rsnxe_len >= 4 && - sm->rsnxe[3] & BIT(WLAN_RSNX_CAPAB_SECURE_LTF - 8))) + ieee802_11_rsnx_capab(sm->rsnxe, WLAN_RSNX_CAPAB_SECURE_LTF))) kdk_len = WPA_KDK_MAX_LEN; else kdk_len = 0; diff --git a/src/ap/wpa_auth_ft.c b/src/ap/wpa_auth_ft.c index 32b745651..e80086b93 100644 --- a/src/ap/wpa_auth_ft.c +++ b/src/ap/wpa_auth_ft.c @@ -3198,8 +3198,7 @@ pmk_r1_derived: if (sm->wpa_auth->conf.force_kdk_derivation || (sm->wpa_auth->conf.secure_ltf && - sm->rsnxe && sm->rsnxe_len >= 4 && - sm->rsnxe[3] & BIT(WLAN_RSNX_CAPAB_SECURE_LTF - 8))) + ieee802_11_rsnx_capab(sm->rsnxe, WLAN_RSNX_CAPAB_SECURE_LTF))) kdk_len = WPA_KDK_MAX_LEN; else kdk_len = 0; diff --git a/src/common/ieee802_11_common.c b/src/common/ieee802_11_common.c index 5b80db6d3..96681843e 100644 --- a/src/common/ieee802_11_common.c +++ b/src/common/ieee802_11_common.c @@ -2403,6 +2403,35 @@ int ieee802_11_ext_capab(const u8 *ie, unsigned int capab) } +bool ieee802_11_rsnx_capab_len(const u8 *rsnxe, size_t rsnxe_len, + unsigned int capab) +{ + const u8 *end; + size_t flen, i; + u32 capabs = 0; + + if (!rsnxe || rsnxe_len == 0) + return false; + end = rsnxe + rsnxe_len; + flen = (rsnxe[0] & 0x0f) + 1; + if (rsnxe + flen > end) + return false; + if (flen > 4) + flen = 4; + for (i = 0; i < flen; i++) + capabs |= rsnxe[i] << (8 * i); + + return capabs & BIT(capab); +} + + +bool ieee802_11_rsnx_capab(const u8 *rsnxe, unsigned int capab) +{ + return ieee802_11_rsnx_capab_len(rsnxe ? rsnxe + 2 : NULL, + rsnxe ? rsnxe[1] : 0, capab); +} + + void hostapd_encode_edmg_chan(int edmg_enable, u8 edmg_channel, int primary_channel, struct ieee80211_edmg_config *edmg) diff --git a/src/common/ieee802_11_common.h b/src/common/ieee802_11_common.h index 8a16f1666..fe2b1bca6 100644 --- a/src/common/ieee802_11_common.h +++ b/src/common/ieee802_11_common.h @@ -269,6 +269,9 @@ int ieee802_11_parse_candidate_list(const char *pos, u8 *nei_rep, size_t nei_rep_len); int ieee802_11_ext_capab(const u8 *ie, unsigned int capab); +bool ieee802_11_rsnx_capab_len(const u8 *rsnxe, size_t rsnxe_len, + unsigned int capab); +bool ieee802_11_rsnx_capab(const u8 *rsnxe, unsigned int capab); int op_class_to_bandwidth(u8 op_class); int op_class_to_ch_width(u8 op_class); diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c index 672d66428..78e2380b1 100644 --- a/src/rsn_supp/wpa.c +++ b/src/rsn_supp/wpa.c @@ -609,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; @@ -4376,8 +4376,8 @@ int fils_process_auth(struct wpa_sm *sm, const u8 *bssid, const u8 *data, } if (sm->force_kdk_derivation || - (sm->secure_ltf && sm->ap_rsnxe && sm->ap_rsnxe_len >= 4 && - sm->ap_rsnxe[3] & BIT(WLAN_RSNX_CAPAB_SECURE_LTF - 8))) + (sm->secure_ltf && + ieee802_11_rsnx_capab(sm->ap_rsnxe, WLAN_RSNX_CAPAB_SECURE_LTF))) kdk_len = WPA_KDK_MAX_LEN; else kdk_len = 0; diff --git a/src/rsn_supp/wpa_ft.c b/src/rsn_supp/wpa_ft.c index fce6e77e7..2669da9b3 100644 --- a/src/rsn_supp/wpa_ft.c +++ b/src/rsn_supp/wpa_ft.c @@ -69,8 +69,8 @@ int wpa_derive_ptk_ft(struct wpa_sm *sm, const unsigned char *src_addr, wpa_ft_pasn_store_r1kh(sm, src_addr); if (sm->force_kdk_derivation || - (sm->secure_ltf && sm->ap_rsnxe && sm->ap_rsnxe_len >= 4 && - sm->ap_rsnxe[3] & BIT(WLAN_RSNX_CAPAB_SECURE_LTF - 8))) + (sm->secure_ltf && + ieee802_11_rsnx_capab(sm->ap_rsnxe, WLAN_RSNX_CAPAB_SECURE_LTF))) kdk_len = WPA_KDK_MAX_LEN; else kdk_len = 0; @@ -672,8 +672,8 @@ int wpa_ft_process_response(struct wpa_sm *sm, const u8 *ies, size_t ies_len, wpa_ft_pasn_store_r1kh(sm, bssid); if (sm->force_kdk_derivation || - (sm->secure_ltf && sm->ap_rsnxe && sm->ap_rsnxe_len >= 4 && - sm->ap_rsnxe[3] & BIT(WLAN_RSNX_CAPAB_SECURE_LTF - 8))) + (sm->secure_ltf && + ieee802_11_rsnx_capab(sm->ap_rsnxe, WLAN_RSNX_CAPAB_SECURE_LTF))) kdk_len = WPA_KDK_MAX_LEN; else kdk_len = 0; diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index 062c64ee4..bf83e4168 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -3012,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) @@ -5112,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) diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c index 717a5eefb..b3c07f926 100644 --- a/wpa_supplicant/events.c +++ b/wpa_supplicant/events.c @@ -1102,14 +1102,11 @@ static bool sae_pk_acceptable_bss_with_pk(struct wpa_supplicant *wpa_s, dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) { int count; const u8 *ie; - u8 rsnxe_capa = 0; if (bss == orig_bss) continue; ie = wpa_bss_get_ie(bss, WLAN_EID_RSNX); - if (ie && ie[1] >= 1) - rsnxe_capa = ie[2]; - if (!(rsnxe_capa & BIT(WLAN_RSNX_CAPAB_SAE_PK))) + if (!(ieee802_11_rsnx_capab(ie, WLAN_RSNX_CAPAB_SAE_PK))) continue; /* TODO: Could be more thorough in checking what kind of diff --git a/wpa_supplicant/pasn_supplicant.c b/wpa_supplicant/pasn_supplicant.c index edb550800..baf4c2643 100644 --- a/wpa_supplicant/pasn_supplicant.c +++ b/wpa_supplicant/pasn_supplicant.c @@ -1021,8 +1021,8 @@ static int wpas_pasn_start(struct wpa_supplicant *wpa_s, const u8 *bssid, return -1; } - if (beacon_rsnxe_len < 3 || - !(beacon_rsnxe[2] & BIT(WLAN_RSNX_CAPAB_SAE_H2E))) { + 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; @@ -1081,9 +1081,7 @@ static int wpas_pasn_start(struct wpa_supplicant *wpa_s, const u8 *bssid, if (wpa_s->conf->force_kdk_derivation || (wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_SEC_LTF && - beacon_rsnxe && beacon_rsnxe_len >= 4 && - (WPA_GET_LE16(beacon_rsnxe + 2) & - BIT(WLAN_RSNX_CAPAB_SECURE_LTF)))) + ieee802_11_rsnx_capab(beacon_rsnxe, WLAN_RSNX_CAPAB_SECURE_LTF))) pasn->kdk_len = WPA_KDK_MAX_LEN; else pasn->kdk_len = 0;