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 <j@w1.fi>
This commit is contained in:
Jouni Malinen 2021-04-10 12:43:38 +03:00
parent 663e190b72
commit d675d3b15b
11 changed files with 75 additions and 55 deletions

View file

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

View file

@ -3153,8 +3153,8 @@ static void handle_auth_pasn_1(struct hostapd_data *hapd, struct sta_info *sta,
if (hapd->conf->force_kdk_derivation || if (hapd->conf->force_kdk_derivation ||
((hapd->iface->drv_flags2 & WPA_DRIVER_FLAGS2_SEC_LTF) && ((hapd->iface->drv_flags2 & WPA_DRIVER_FLAGS2_SEC_LTF) &&
elems.rsnxe && elems.rsnxe_len >= 2 && ieee802_11_rsnx_capab_len(elems.rsnxe, elems.rsnxe_len,
(WPA_GET_LE16(elems.rsnxe) & BIT(WLAN_RSNX_CAPAB_SECURE_LTF)))) WLAN_RSNX_CAPAB_SECURE_LTF)))
sta->pasn->kdk_len = WPA_KDK_MAX_LEN; sta->pasn->kdk_len = WPA_KDK_MAX_LEN;
else else
sta->pasn->kdk_len = 0; 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 && if (hapd->conf->sae_pwe == 2 &&
sta->auth_alg == WLAN_AUTH_SAE && sta->auth_alg == WLAN_AUTH_SAE &&
sta->sae && !sta->sae->h2e && sta->sae && !sta->sae->h2e &&
elems.rsnxe && elems.rsnxe_len >= 1 && ieee802_11_rsnx_capab_len(elems.rsnxe, elems.rsnxe_len,
(elems.rsnxe[0] & BIT(WLAN_RSNX_CAPAB_SAE_H2E))) { WLAN_RSNX_CAPAB_SAE_H2E)) {
wpa_printf(MSG_INFO, "SAE: " MACSTR wpa_printf(MSG_INFO, "SAE: " MACSTR
" indicates support for SAE H2E, but did not use it", " indicates support for SAE H2E, but did not use it",
MAC2STR(sta->addr)); MAC2STR(sta->addr));

View file

@ -2283,8 +2283,7 @@ static int wpa_derive_ptk(struct wpa_state_machine *sm, const u8 *snonce,
if (sm->wpa_auth->conf.force_kdk_derivation || if (sm->wpa_auth->conf.force_kdk_derivation ||
(sm->wpa_auth->conf.secure_ltf && (sm->wpa_auth->conf.secure_ltf &&
sm->rsnxe && sm->rsnxe_len >= 4 && ieee802_11_rsnx_capab(sm->rsnxe, WLAN_RSNX_CAPAB_SECURE_LTF)))
sm->rsnxe[3] & BIT(WLAN_RSNX_CAPAB_SECURE_LTF - 8)))
kdk_len = WPA_KDK_MAX_LEN; kdk_len = WPA_KDK_MAX_LEN;
else else
kdk_len = 0; kdk_len = 0;
@ -2338,8 +2337,7 @@ int fils_auth_pmk_to_ptk(struct wpa_state_machine *sm, const u8 *pmk,
if (sm->wpa_auth->conf.force_kdk_derivation || if (sm->wpa_auth->conf.force_kdk_derivation ||
(sm->wpa_auth->conf.secure_ltf && (sm->wpa_auth->conf.secure_ltf &&
sm->rsnxe && sm->rsnxe_len >= 4 && ieee802_11_rsnx_capab(sm->rsnxe, WLAN_RSNX_CAPAB_SECURE_LTF)))
sm->rsnxe[3] & BIT(WLAN_RSNX_CAPAB_SECURE_LTF - 8)))
kdk_len = WPA_KDK_MAX_LEN; kdk_len = WPA_KDK_MAX_LEN;
else else
kdk_len = 0; kdk_len = 0;

View file

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

View file

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

View file

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

View file

@ -609,8 +609,8 @@ static int wpa_derive_ptk(struct wpa_sm *sm, const unsigned char *src_addr,
#endif /* CONFIG_OWE */ #endif /* CONFIG_OWE */
if (sm->force_kdk_derivation || if (sm->force_kdk_derivation ||
(sm->secure_ltf && sm->ap_rsnxe && sm->ap_rsnxe_len >= 4 && (sm->secure_ltf &&
sm->ap_rsnxe[3] & BIT(WLAN_RSNX_CAPAB_SECURE_LTF - 8))) ieee802_11_rsnx_capab(sm->ap_rsnxe, WLAN_RSNX_CAPAB_SECURE_LTF)))
kdk_len = WPA_KDK_MAX_LEN; kdk_len = WPA_KDK_MAX_LEN;
else else
kdk_len = 0; kdk_len = 0;
@ -4376,8 +4376,8 @@ int fils_process_auth(struct wpa_sm *sm, const u8 *bssid, const u8 *data,
} }
if (sm->force_kdk_derivation || if (sm->force_kdk_derivation ||
(sm->secure_ltf && sm->ap_rsnxe && sm->ap_rsnxe_len >= 4 && (sm->secure_ltf &&
sm->ap_rsnxe[3] & BIT(WLAN_RSNX_CAPAB_SECURE_LTF - 8))) ieee802_11_rsnx_capab(sm->ap_rsnxe, WLAN_RSNX_CAPAB_SECURE_LTF)))
kdk_len = WPA_KDK_MAX_LEN; kdk_len = WPA_KDK_MAX_LEN;
else else
kdk_len = 0; kdk_len = 0;

View file

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

View file

@ -3012,19 +3012,17 @@ static int wpa_supplicant_ctrl_iface_scan_result(
ie2, 2 + ie2[1]); ie2, 2 + ie2[1]);
} }
rsnxe = wpa_bss_get_ie(bss, WLAN_EID_RSNX); rsnxe = wpa_bss_get_ie(bss, WLAN_EID_RSNX);
if (rsnxe && rsnxe[1] >= 1) { if (ieee802_11_rsnx_capab(rsnxe, WLAN_RSNX_CAPAB_SAE_H2E)) {
if (rsnxe[2] & BIT(WLAN_RSNX_CAPAB_SAE_H2E)) { ret = os_snprintf(pos, end - pos, "[SAE-H2E]");
ret = os_snprintf(pos, end - pos, "[SAE-H2E]"); if (os_snprintf_error(end - pos, ret))
if (os_snprintf_error(end - pos, ret)) return -1;
return -1; pos += ret;
pos += ret; }
} if (ieee802_11_rsnx_capab(rsnxe, WLAN_RSNX_CAPAB_SAE_PK)) {
if (rsnxe[2] & BIT(WLAN_RSNX_CAPAB_SAE_PK)) { ret = os_snprintf(pos, end - pos, "[SAE-PK]");
ret = os_snprintf(pos, end - pos, "[SAE-PK]"); if (os_snprintf_error(end - pos, ret))
if (os_snprintf_error(end - pos, ret)) return -1;
return -1; pos += ret;
pos += ret;
}
} }
osen_ie = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE); osen_ie = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE);
if (osen_ie) if (osen_ie)
@ -5112,19 +5110,17 @@ static int print_bss_info(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
mesh ? "RSN" : "WPA2", ie2, mesh ? "RSN" : "WPA2", ie2,
2 + ie2[1]); 2 + ie2[1]);
rsnxe = wpa_bss_get_ie(bss, WLAN_EID_RSNX); rsnxe = wpa_bss_get_ie(bss, WLAN_EID_RSNX);
if (rsnxe && rsnxe[1] >= 1) { if (ieee802_11_rsnx_capab(rsnxe, WLAN_RSNX_CAPAB_SAE_H2E)) {
if (rsnxe[2] & BIT(WLAN_RSNX_CAPAB_SAE_H2E)) { ret = os_snprintf(pos, end - pos, "[SAE-H2E]");
ret = os_snprintf(pos, end - pos, "[SAE-H2E]"); if (os_snprintf_error(end - pos, ret))
if (os_snprintf_error(end - pos, ret)) return -1;
return -1; pos += ret;
pos += ret; }
} if (ieee802_11_rsnx_capab(rsnxe, WLAN_RSNX_CAPAB_SAE_PK)) {
if (rsnxe[2] & BIT(WLAN_RSNX_CAPAB_SAE_PK)) { ret = os_snprintf(pos, end - pos, "[SAE-PK]");
ret = os_snprintf(pos, end - pos, "[SAE-PK]"); if (os_snprintf_error(end - pos, ret))
if (os_snprintf_error(end - pos, ret)) return -1;
return -1; pos += ret;
pos += ret;
}
} }
osen_ie = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE); osen_ie = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE);
if (osen_ie) if (osen_ie)

View file

@ -1102,14 +1102,11 @@ static bool sae_pk_acceptable_bss_with_pk(struct wpa_supplicant *wpa_s,
dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) { dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
int count; int count;
const u8 *ie; const u8 *ie;
u8 rsnxe_capa = 0;
if (bss == orig_bss) if (bss == orig_bss)
continue; continue;
ie = wpa_bss_get_ie(bss, WLAN_EID_RSNX); ie = wpa_bss_get_ie(bss, WLAN_EID_RSNX);
if (ie && ie[1] >= 1) if (!(ieee802_11_rsnx_capab(ie, WLAN_RSNX_CAPAB_SAE_PK)))
rsnxe_capa = ie[2];
if (!(rsnxe_capa & BIT(WLAN_RSNX_CAPAB_SAE_PK)))
continue; continue;
/* TODO: Could be more thorough in checking what kind of /* TODO: Could be more thorough in checking what kind of

View file

@ -1021,8 +1021,8 @@ static int wpas_pasn_start(struct wpa_supplicant *wpa_s, const u8 *bssid,
return -1; return -1;
} }
if (beacon_rsnxe_len < 3 || if (!ieee802_11_rsnx_capab(beacon_rsnxe,
!(beacon_rsnxe[2] & BIT(WLAN_RSNX_CAPAB_SAE_H2E))) { WLAN_RSNX_CAPAB_SAE_H2E)) {
wpa_printf(MSG_DEBUG, wpa_printf(MSG_DEBUG,
"PASN: AP does not support SAE H2E"); "PASN: AP does not support SAE H2E");
return -1; 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 || if (wpa_s->conf->force_kdk_derivation ||
(wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_SEC_LTF && (wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_SEC_LTF &&
beacon_rsnxe && beacon_rsnxe_len >= 4 && ieee802_11_rsnx_capab(beacon_rsnxe, WLAN_RSNX_CAPAB_SECURE_LTF)))
(WPA_GET_LE16(beacon_rsnxe + 2) &
BIT(WLAN_RSNX_CAPAB_SECURE_LTF))))
pasn->kdk_len = WPA_KDK_MAX_LEN; pasn->kdk_len = WPA_KDK_MAX_LEN;
else else
pasn->kdk_len = 0; pasn->kdk_len = 0;