Validate new KDEs defined for MLO connection in EAPOL 1/4 and 3/4 and reject the Four-Way handshake frames if any of the new KDE data is not matching expected key data. Signed-off-by: Veerendranath Jakkam <quic_vjakkam@xxxxxxxxxxx> --- src/rsn_supp/wpa.c | 147 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 147 insertions(+) diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c index 96adc4817..9a4e0ebee 100644 --- a/src/rsn_supp/wpa.c +++ b/src/rsn_supp/wpa.c @@ -785,6 +785,14 @@ static void wpa_supplicant_process_1_of_4(struct wpa_sm *sm, } } + if (sm->valid_links && + (!ie.mac_addr || ie.mac_addr_len < ETH_ALEN || + os_memcmp(ie.mac_addr, sm->ap_mld_addr, ETH_ALEN))) { + wpa_printf(MSG_INFO, + "RSN MLO: Discard EAPOL-Key msg 1/4 with invalid MAC address KDE"); + return; + } + res = wpa_supplicant_get_pmk(sm, src_addr, ie.pmkid); if (res == -2) { wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "RSN: Do not reply to " @@ -2092,6 +2100,131 @@ int wpa_supplicant_send_4_of_4(struct wpa_sm *sm, const unsigned char *dst, } +static int wpa_supplicant_validate_link_kde(struct wpa_sm *sm, + u8 link_id, + const u8 *link_kde, + size_t link_kde_len) +{ + struct wpa_mlo_link_hdr *link_kde_hdr; + size_t rsn_ie_len = 0, rsnxe_len = 0; + const u8 *rsn_ie = NULL, *rsnxe = NULL; + + if (!link_kde || link_kde_len < sizeof(*link_kde_hdr)) { + wpa_msg(sm->ctx->msg_ctx, MSG_INFO, + "WPA MLO: Invalid link KDE for link ID %d", + link_id); + return -1; + } + + link_kde_hdr = (struct wpa_mlo_link_hdr *) link_kde; + + if (os_memcmp(sm->links[link_id].bssid, link_kde_hdr->mac, ETH_ALEN)) { + wpa_msg(sm->ctx->msg_ctx, MSG_INFO, + "WPA MLO: Link MAC address not matching with assoc response"); + return -1; + } + + if (link_kde_hdr->rsne_present) { + rsn_ie = link_kde + sizeof(*link_kde_hdr); + if (link_kde_len < (sizeof(*link_kde_hdr) + 2) || + link_kde_len < (sizeof(*link_kde_hdr) + 2 + rsn_ie[1])) + return -1; + + rsn_ie_len = rsn_ie[1] + 2; + } + + if (link_kde_hdr->rsnxe_present) { + rsnxe = link_kde + sizeof(*link_kde_hdr) + rsn_ie_len; + if (link_kde_len < (sizeof(*link_kde_hdr) + rsn_ie_len + 2) || + link_kde_len < (sizeof(*link_kde_hdr) + rsn_ie_len + 2 + + rsnxe[1])) + return -1; + + rsnxe_len = rsnxe[1] + 2; + } + + if (sm->links[link_id].ap_rsn_ie == NULL) { + wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, + "WPA MLO: No RSN IE AP link ID %u known. " + "Trying to get from scan results", link_id); + if (wpa_sm_get_link_beacon_ie(sm, link_id) < 0) { + wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, + "WPA MLO: Could not find AP from " + "the scan results"); + return -1; + } + wpa_msg(sm->ctx->msg_ctx, MSG_DEBUG, + "WPA MLO: Found the current AP from updated scan results"); + } + + if (rsn_ie == NULL && sm->links[link_id].ap_rsn_ie) { + wpa_msg(sm->ctx->msg_ctx, MSG_INFO, + "WPA MLO: IE in 3/4 msg does not match with IE in Beacon/ProbeResp (no IE?) for link ID %u", + link_id); + return -1; + } + + if (rsn_ie && sm->links[link_id].ap_rsn_ie && + wpa_compare_rsn_ie(wpa_key_mgmt_ft(sm->key_mgmt), + sm->links[link_id].ap_rsn_ie, + sm->links[link_id].ap_rsn_ie_len, + rsn_ie, rsn_ie_len)) { + wpa_msg(sm->ctx->msg_ctx, MSG_INFO, + "WPA MLO: IE in 3/4 msg does not match with IE in Beacon/ProbeResp for link ID %u", + link_id); + wpa_hexdump(MSG_INFO, "RSNE in Beacon/ProbeResp", + sm->links[link_id].ap_rsnxe, + sm->links[link_id].ap_rsnxe_len); + wpa_hexdump(MSG_INFO, "RSNE in EAPOL-Key msg 3/4", + rsn_ie, rsn_ie_len); + return -1; + } + + if ((sm->links[link_id].ap_rsnxe && !rsnxe) || + (!sm->links[link_id].ap_rsnxe && rsnxe) || + (sm->links[link_id].ap_rsnxe && rsnxe && + (sm->links[link_id].ap_rsnxe_len != rsnxe_len || + os_memcmp(sm->links[link_id].ap_rsnxe, rsnxe, + sm->links[link_id].ap_rsnxe_len) != 0))) { + wpa_msg(sm->ctx->msg_ctx, MSG_INFO, + "WPA MLO: RSNXE mismatch between Beacon/ProbeResp and EAPOL-Key msg 3/4 for link ID %u", + link_id); + wpa_hexdump(MSG_INFO, "RSNXE in Beacon/ProbeResp", + sm->links[link_id].ap_rsnxe, + sm->links[link_id].ap_rsnxe_len); + wpa_hexdump(MSG_INFO, "RSNXE in EAPOL-Key msg 3/4", + rsnxe, rsnxe_len); + wpa_sm_deauthenticate(sm, WLAN_REASON_IE_IN_4WAY_DIFFERS); + return -1; + } + + return 0; +} + + +static int wpa_validate_mlo_kdes(struct wpa_sm *sm, + u8 link_id, struct wpa_eapol_ie_parse *ie) +{ + if (ie->mlo_igtk[link_id] && + sm->mgmt_group_cipher != WPA_CIPHER_GTK_NOT_USED && + wpa_cipher_valid_mgmt_group(sm->mgmt_group_cipher) && + ie->mlo_igtk_len[link_id] != sizeof(struct wpa_mlo_igtk_hdr) + + (unsigned int) wpa_cipher_key_len(sm->mgmt_group_cipher)) { + wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, + "WPA MLO: Invalid IGTK KDE length %lu for link ID %u", + (unsigned long) ie->mlo_igtk_len, link_id); + return -1; + } + + if (wpa_supplicant_validate_link_kde(sm, link_id, + ie->mlo_link[link_id], + ie->mlo_link_len[link_id])) + return -1; + + return 0; +} + + static void wpa_supplicant_process_mlo_3_of_4(struct wpa_sm *sm, const struct wpa_eapol_key *key, u16 ver, const u8 *key_data, @@ -2099,6 +2232,7 @@ static void wpa_supplicant_process_mlo_3_of_4(struct wpa_sm *sm, { u16 key_info, keylen; struct wpa_eapol_ie_parse ie; + int i; wpa_sm_set_state(sm, WPA_4WAY_HANDSHAKE); wpa_dbg(sm->ctx->msg_ctx, MSG_INFO, "WPA MLO: RX message 3 of 4-Way " @@ -2121,6 +2255,19 @@ static void wpa_supplicant_process_mlo_3_of_4(struct wpa_sm *sm, goto failed; } + if (!ie.mac_addr || ie.mac_addr_len < ETH_ALEN || + os_memcmp(ie.mac_addr, sm->ap_mld_addr, ETH_ALEN)) { + wpa_printf(MSG_DEBUG, "RSN MLO: Invalid MAC address KDE"); + goto failed; + } + + for (i = 0; i < MAX_NUM_MLD_LINKS; i++) { + if (!(sm->valid_links & BIT(i))) + continue; + + if (wpa_validate_mlo_kdes(sm, i, &ie)) + goto failed; + } #ifdef CONFIG_IEEE80211R if (wpa_key_mgmt_ft(sm->key_mgmt) && -- 2.25.1 _______________________________________________ Hostap mailing list Hostap@xxxxxxxxxxxxxxxxxxx http://lists.infradead.org/mailman/listinfo/hostap