From 3973300b8deda00a096f1c3f13a2147d5507ebd0 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Tue, 8 Aug 2023 13:32:32 +0300 Subject: [PATCH] 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 --- src/ap/wpa_auth_ft.c | 7 ++++--- src/common/wpa_common.c | 31 ++++++++++++++++++++++++++----- src/common/wpa_common.h | 2 +- src/rsn_supp/wpa.c | 2 +- src/rsn_supp/wpa_ft.c | 7 ++++--- wlantest/rx_mgmt.c | 14 ++++++++------ 6 files changed, 44 insertions(+), 19 deletions(-) diff --git a/src/ap/wpa_auth_ft.c b/src/ap/wpa_auth_ft.c index 2402ad922..8b91b822c 100644 --- a/src/ap/wpa_auth_ft.c +++ b/src/ap/wpa_auth_ft.c @@ -2805,7 +2805,7 @@ u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos, ric_start = pos; 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, parse.ric_len); 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", 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"); 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); - 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"); return WLAN_STATUS_UNSPECIFIED_FAILURE; } diff --git a/src/common/wpa_common.c b/src/common/wpa_common.c index dc77368df..88b6bbe15 100644 --- a/src/common/wpa_common.c +++ b/src/common/wpa_common.c @@ -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 key_mgmt) + int key_mgmt, bool reassoc_resp) { const u8 *end, *pos; 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; size_t fte_len = 0; bool is_fte = false; + struct ieee802_11_elems elems; os_memset(parse, 0, sizeof(*parse)); if (ies == NULL) 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; end = ies + ies_len; 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 * frame. */ - if (parse->rsn) - prot_ie_count--; + 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) + 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) prot_ie_count--; if (parse->ftie) prot_ie_count--; - if (parse->rsnxe) - prot_ie_count--; if (prot_ie_count < 0) { wpa_printf(MSG_DEBUG, "FT: Some required IEs not included in " "the protected IE count"); diff --git a/src/common/wpa_common.h b/src/common/wpa_common.h index 9e87b9a26..f503e9095 100644 --- a/src/common/wpa_common.h +++ b/src/common/wpa_common.h @@ -638,7 +638,7 @@ struct wpa_pasn_params_data { #define WPA_PASN_PUBKEY_UNCOMPRESSED 0x04 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 { const u8 *wpa_ie; diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c index 9c7c526fc..fcd8ede3b 100644 --- a/src/rsn_supp/wpa.c +++ b/src/rsn_supp/wpa.c @@ -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, - sm->key_mgmt) < 0) { + sm->key_mgmt, false) < 0) { wpa_printf(MSG_DEBUG, "FILS+FT: Failed to parse IEs"); goto fail; } diff --git a/src/rsn_supp/wpa_ft.c b/src/rsn_supp/wpa_ft.c index 497d91e6d..35fad9f1d 100644 --- a/src/rsn_supp/wpa_ft.c +++ b/src/rsn_supp/wpa_ft.c @@ -127,7 +127,7 @@ int wpa_sm_set_ft_params(struct wpa_sm *sm, const u8 *ies, size_t ies_len) 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; 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; } - 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"); return -1; } @@ -1033,7 +1034,7 @@ int wpa_ft_validate_reassoc_resp(struct wpa_sm *sm, const u8 *ies, 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"); return -1; } diff --git a/wlantest/rx_mgmt.c b/wlantest/rx_mgmt.c index ba98034bd..8f7d220b8 100644 --- a/wlantest/rx_mgmt.c +++ b/wlantest/rx_mgmt.c @@ -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, len - IEEE80211_HDRLEN - sizeof(mgmt->u.auth), - &parse, 0)) { + &parse, 0, false)) { add_note(wt, MSG_INFO, "Could not parse FT Authentication Response frame"); return; @@ -1111,7 +1111,7 @@ static void rx_mgmt_assoc_resp(struct wlantest *wt, const u8 *data, size_t len) 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) { os_memcpy(bss->r0kh_id, parse.r0kh_id, 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); - 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"); 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); - 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"); return; } @@ -2037,7 +2039,7 @@ static void rx_mgmt_action_ft_request(struct wlantest *wt, ies_len = len - (24 + 2 + 2 * ETH_ALEN); 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"); return; } @@ -2086,7 +2088,7 @@ static void rx_mgmt_action_ft_response(struct wlantest *wt, ies_len = len - (24 + 2 + 2 * ETH_ALEN); 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, "Could not parse FT Response frame body"); return;