[PATCH 09/12] MLD STA: Add support for validating MLO KDEs for 4WHS EAPOL frames
Veerendranath Jakkam
quic_vjakkam at quicinc.com
Wed Aug 24 22:53:08 PDT 2022
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 at quicinc.com>
---
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
More information about the Hostap
mailing list