FTE protected element check for MLO Reassociation Response frame

The set of protected elements in the FTE in Reassociation Response frame
is different for MLO. Count RSNE and RSNXE separately for each link.
This implementation uses the number of links for which a GTK was
provided which does not fully match the standard ("requested link") and
a more accurate implementation is likely needed, but that will require
some more complexity and state information.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
This commit is contained in:
Jouni Malinen 2023-08-08 13:32:32 +03:00 committed by Jouni Malinen
parent 43b5f11d96
commit 3973300b8d
6 changed files with 44 additions and 19 deletions

View file

@ -2805,7 +2805,7 @@ u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos,
ric_start = pos; ric_start = pos;
if (wpa_ft_parse_ies(req_ies, req_ies_len, &parse, if (wpa_ft_parse_ies(req_ies, req_ies_len, &parse,
sm->wpa_key_mgmt) == 0 && parse.ric) { sm->wpa_key_mgmt, false) == 0 && parse.ric) {
pos = wpa_ft_process_ric(sm, pos, end, parse.ric, pos = wpa_ft_process_ric(sm, pos, end, parse.ric,
parse.ric_len); parse.ric_len);
if (auth_alg == WLAN_AUTH_FT) if (auth_alg == WLAN_AUTH_FT)
@ -3183,7 +3183,7 @@ static int wpa_ft_process_auth_req(struct wpa_state_machine *sm,
wpa_hexdump(MSG_DEBUG, "FT: Received authentication frame IEs", wpa_hexdump(MSG_DEBUG, "FT: Received authentication frame IEs",
ies, ies_len); ies, ies_len);
if (wpa_ft_parse_ies(ies, ies_len, &parse, 0)) { if (wpa_ft_parse_ies(ies, ies_len, &parse, 0, false)) {
wpa_printf(MSG_DEBUG, "FT: Failed to parse FT IEs"); wpa_printf(MSG_DEBUG, "FT: Failed to parse FT IEs");
return WLAN_STATUS_UNSPECIFIED_FAILURE; return WLAN_STATUS_UNSPECIFIED_FAILURE;
} }
@ -3481,7 +3481,8 @@ int wpa_ft_validate_reassoc(struct wpa_state_machine *sm, const u8 *ies,
wpa_hexdump(MSG_DEBUG, "FT: Reassoc Req IEs", ies, ies_len); wpa_hexdump(MSG_DEBUG, "FT: Reassoc Req IEs", ies, ies_len);
if (wpa_ft_parse_ies(ies, ies_len, &parse, sm->wpa_key_mgmt) < 0) { if (wpa_ft_parse_ies(ies, ies_len, &parse, sm->wpa_key_mgmt,
false) < 0) {
wpa_printf(MSG_DEBUG, "FT: Failed to parse FT IEs"); wpa_printf(MSG_DEBUG, "FT: Failed to parse FT IEs");
return WLAN_STATUS_UNSPECIFIED_FAILURE; return WLAN_STATUS_UNSPECIFIED_FAILURE;
} }

View file

@ -1198,7 +1198,7 @@ static int wpa_ft_parse_fte(int key_mgmt, const u8 *ie, size_t len,
int wpa_ft_parse_ies(const u8 *ies, size_t ies_len, struct wpa_ft_ies *parse, int wpa_ft_parse_ies(const u8 *ies, size_t ies_len, struct wpa_ft_ies *parse,
int key_mgmt) int key_mgmt, bool reassoc_resp)
{ {
const u8 *end, *pos; const u8 *end, *pos;
struct wpa_ie_data data; struct wpa_ie_data data;
@ -1207,11 +1207,17 @@ int wpa_ft_parse_ies(const u8 *ies, size_t ies_len, struct wpa_ft_ies *parse,
const u8 *fte = NULL; const u8 *fte = NULL;
size_t fte_len = 0; size_t fte_len = 0;
bool is_fte = false; bool is_fte = false;
struct ieee802_11_elems elems;
os_memset(parse, 0, sizeof(*parse)); os_memset(parse, 0, sizeof(*parse));
if (ies == NULL) if (ies == NULL)
return 0; return 0;
if (ieee802_11_parse_elems(ies, ies_len, &elems, 0) == ParseFailed) {
wpa_printf(MSG_DEBUG, "FT: Failed to parse elements");
return -1;
}
pos = ies; pos = ies;
end = ies + ies_len; end = ies + ies_len;
while (end - pos >= 2) { while (end - pos >= 2) {
@ -1328,14 +1334,29 @@ int wpa_ft_parse_ies(const u8 *ies, size_t ies_len, struct wpa_ft_ies *parse,
* Check that the protected IE count matches with IEs included in the * Check that the protected IE count matches with IEs included in the
* frame. * frame.
*/ */
if (reassoc_resp && elems.basic_mle) {
unsigned int link_id;
/* TODO: This count should be done based on all _requested_,
* not _accepted_ links. */
for (link_id = 0; link_id < MAX_NUM_MLO_LINKS; link_id++) {
if (parse->mlo_gtk[link_id]) {
if (parse->rsn) if (parse->rsn)
prot_ie_count--; prot_ie_count--;
if (parse->rsnxe)
prot_ie_count--;
}
}
} else {
if (parse->rsn)
prot_ie_count--;
if (parse->rsnxe)
prot_ie_count--;
}
if (parse->mdie) if (parse->mdie)
prot_ie_count--; prot_ie_count--;
if (parse->ftie) if (parse->ftie)
prot_ie_count--; prot_ie_count--;
if (parse->rsnxe)
prot_ie_count--;
if (prot_ie_count < 0) { if (prot_ie_count < 0) {
wpa_printf(MSG_DEBUG, "FT: Some required IEs not included in " wpa_printf(MSG_DEBUG, "FT: Some required IEs not included in "
"the protected IE count"); "the protected IE count");

View file

@ -638,7 +638,7 @@ struct wpa_pasn_params_data {
#define WPA_PASN_PUBKEY_UNCOMPRESSED 0x04 #define WPA_PASN_PUBKEY_UNCOMPRESSED 0x04
int wpa_ft_parse_ies(const u8 *ies, size_t ies_len, struct wpa_ft_ies *parse, int wpa_ft_parse_ies(const u8 *ies, size_t ies_len, struct wpa_ft_ies *parse,
int key_mgmt); int key_mgmt, bool reassoc_resp);
struct wpa_eapol_ie_parse { struct wpa_eapol_ie_parse {
const u8 *wpa_ie; const u8 *wpa_ie;

View file

@ -5458,7 +5458,7 @@ int fils_process_auth(struct wpa_sm *sm, const u8 *bssid, const u8 *data,
} }
if (wpa_ft_parse_ies(pos, end - pos, &parse, if (wpa_ft_parse_ies(pos, end - pos, &parse,
sm->key_mgmt) < 0) { sm->key_mgmt, false) < 0) {
wpa_printf(MSG_DEBUG, "FILS+FT: Failed to parse IEs"); wpa_printf(MSG_DEBUG, "FILS+FT: Failed to parse IEs");
goto fail; goto fail;
} }

View file

@ -127,7 +127,7 @@ int wpa_sm_set_ft_params(struct wpa_sm *sm, const u8 *ies, size_t ies_len)
return 0; return 0;
} }
if (wpa_ft_parse_ies(ies, ies_len, &ft, sm->key_mgmt) < 0) if (wpa_ft_parse_ies(ies, ies_len, &ft, sm->key_mgmt, false) < 0)
return -1; return -1;
if (ft.mdie_len < MOBILITY_DOMAIN_ID_LEN + 1) if (ft.mdie_len < MOBILITY_DOMAIN_ID_LEN + 1)
@ -615,7 +615,8 @@ int wpa_ft_process_response(struct wpa_sm *sm, const u8 *ies, size_t ies_len,
return -1; return -1;
} }
if (wpa_ft_parse_ies(ies, ies_len, &parse, sm->key_mgmt) < 0) { if (wpa_ft_parse_ies(ies, ies_len, &parse, sm->key_mgmt,
!ft_action) < 0) {
wpa_printf(MSG_DEBUG, "FT: Failed to parse IEs"); wpa_printf(MSG_DEBUG, "FT: Failed to parse IEs");
return -1; return -1;
} }
@ -1033,7 +1034,7 @@ int wpa_ft_validate_reassoc_resp(struct wpa_sm *sm, const u8 *ies,
return 0; return 0;
} }
if (wpa_ft_parse_ies(ies, ies_len, &parse, sm->key_mgmt) < 0) { if (wpa_ft_parse_ies(ies, ies_len, &parse, sm->key_mgmt, true) < 0) {
wpa_printf(MSG_DEBUG, "FT: Failed to parse IEs"); wpa_printf(MSG_DEBUG, "FT: Failed to parse IEs");
return -1; return -1;
} }

View file

@ -515,7 +515,7 @@ static void process_ft_auth(struct wlantest *wt, struct wlantest_bss *bss,
if (wpa_ft_parse_ies(mgmt->u.auth.variable, if (wpa_ft_parse_ies(mgmt->u.auth.variable,
len - IEEE80211_HDRLEN - sizeof(mgmt->u.auth), len - IEEE80211_HDRLEN - sizeof(mgmt->u.auth),
&parse, 0)) { &parse, 0, false)) {
add_note(wt, MSG_INFO, add_note(wt, MSG_INFO,
"Could not parse FT Authentication Response frame"); "Could not parse FT Authentication Response frame");
return; return;
@ -1111,7 +1111,7 @@ static void rx_mgmt_assoc_resp(struct wlantest *wt, const u8 *data, size_t len)
sta->state = STATE3; sta->state = STATE3;
} }
if (wpa_ft_parse_ies(ies, ies_len, &parse, 0) == 0) { if (wpa_ft_parse_ies(ies, ies_len, &parse, 0, false) == 0) {
if (parse.r0kh_id) { if (parse.r0kh_id) {
os_memcpy(bss->r0kh_id, parse.r0kh_id, os_memcpy(bss->r0kh_id, parse.r0kh_id,
parse.r0kh_id_len); parse.r0kh_id_len);
@ -1224,7 +1224,8 @@ static void rx_mgmt_reassoc_req(struct wlantest *wt, const u8 *data,
use_sha384 = wpa_key_mgmt_sha384(sta->key_mgmt); use_sha384 = wpa_key_mgmt_sha384(sta->key_mgmt);
if (wpa_ft_parse_ies(ie, ie_len, &parse, sta->key_mgmt) < 0) { if (wpa_ft_parse_ies(ie, ie_len, &parse, sta->key_mgmt,
false) < 0) {
add_note(wt, MSG_INFO, "FT: Failed to parse FT IEs"); add_note(wt, MSG_INFO, "FT: Failed to parse FT IEs");
return; return;
} }
@ -1722,7 +1723,8 @@ static void rx_mgmt_reassoc_resp(struct wlantest *wt, const u8 *data,
use_sha384 = wpa_key_mgmt_sha384(sta->key_mgmt); use_sha384 = wpa_key_mgmt_sha384(sta->key_mgmt);
if (wpa_ft_parse_ies(ies, ies_len, &parse, sta->key_mgmt) < 0) { if (wpa_ft_parse_ies(ies, ies_len, &parse, sta->key_mgmt,
true) < 0) {
add_note(wt, MSG_INFO, "FT: Failed to parse FT IEs"); add_note(wt, MSG_INFO, "FT: Failed to parse FT IEs");
return; return;
} }
@ -2037,7 +2039,7 @@ static void rx_mgmt_action_ft_request(struct wlantest *wt,
ies_len = len - (24 + 2 + 2 * ETH_ALEN); ies_len = len - (24 + 2 + 2 * ETH_ALEN);
wpa_hexdump(MSG_DEBUG, "FT Request frame body", ies, ies_len); wpa_hexdump(MSG_DEBUG, "FT Request frame body", ies, ies_len);
if (wpa_ft_parse_ies(ies, ies_len, &parse, 0)) { if (wpa_ft_parse_ies(ies, ies_len, &parse, 0, false)) {
add_note(wt, MSG_INFO, "Could not parse FT Request frame body"); add_note(wt, MSG_INFO, "Could not parse FT Request frame body");
return; return;
} }
@ -2086,7 +2088,7 @@ static void rx_mgmt_action_ft_response(struct wlantest *wt,
ies_len = len - (24 + 2 + 2 * ETH_ALEN); ies_len = len - (24 + 2 + 2 * ETH_ALEN);
wpa_hexdump(MSG_DEBUG, "FT Response frame body", ies, ies_len); wpa_hexdump(MSG_DEBUG, "FT Response frame body", ies, ies_len);
if (wpa_ft_parse_ies(ies, ies_len, &parse, 0)) { if (wpa_ft_parse_ies(ies, ies_len, &parse, 0, false)) {
add_note(wt, MSG_INFO, add_note(wt, MSG_INFO,
"Could not parse FT Response frame body"); "Could not parse FT Response frame body");
return; return;