From d675d3b15b407b18e26eb1ed54d3cbe22d473876 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 10 Apr 2021 12:43:38 +0300 Subject: [PATCH] Add helper functions for parsing RSNXE capabilities Simplify the implementation by using shared functions for parsing the capabilities instead of using various similar but not exactly identical checks throughout the implementation. Signed-off-by: Jouni Malinen --- src/ap/drv_callbacks.c | 4 +-- src/ap/ieee802_11.c | 8 +++--- src/ap/wpa_auth.c | 6 ++-- src/ap/wpa_auth_ft.c | 3 +- src/common/ieee802_11_common.c | 29 +++++++++++++++++++ src/common/ieee802_11_common.h | 3 ++ src/rsn_supp/wpa.c | 8 +++--- src/rsn_supp/wpa_ft.c | 8 +++--- wpa_supplicant/ctrl_iface.c | 48 +++++++++++++++----------------- wpa_supplicant/events.c | 5 +--- wpa_supplicant/pasn_supplicant.c | 8 ++---- 11 files changed, 75 insertions(+), 55 deletions(-) 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;