[PATCH v2 35/44] WPA_AUTH: MLO: Validate MLO KDEs in 4th message of 4-way handshake

Andrei Otcheretianski andrei.otcheretianski at intel.com
Mon May 22 12:34:03 PDT 2023


From: Ilan Peer <ilan.peer at intel.com>

Signed-off-by: Ilan Peer <ilan.peer at intel.com>
Signed-off-by: Andrei Otcheretianski <andrei.otcheretianski at intel.com>
---
 src/ap/wpa_auth.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 67 insertions(+), 1 deletion(-)

diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c
index 81fb1aee35..3c9a2568bf 100644
--- a/src/ap/wpa_auth.c
+++ b/src/ap/wpa_auth.c
@@ -1080,9 +1080,15 @@ void wpa_receive(struct wpa_authenticator *wpa_auth,
 	const u8 *key_data;
 	size_t keyhdrlen, mic_len;
 	u8 *mic;
+	u8 is_mld = 0;
 
 	if (!wpa_auth || !wpa_auth->conf.wpa || !sm)
 		return;
+
+#ifdef CONFIG_IEEE80211BE
+	is_mld = (sm->mld_assoc_link_id >= 0);
+#endif /* CONFIG_IEEE80211BE */
+
 	wpa_hexdump(MSG_MSGDUMP, "WPA: RX EAPOL data", data, data_len);
 
 	mic_len = wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len);
@@ -1160,7 +1166,8 @@ void wpa_receive(struct wpa_authenticator *wpa_auth,
 		msgtxt = "2/2 Group";
 	} else if (key_data_length == 0 ||
 		   (mic_len == 0 && (key_info & WPA_KEY_INFO_ENCR_KEY_DATA) &&
-		    key_data_length == AES_BLOCK_SIZE)) {
+		    key_data_length == AES_BLOCK_SIZE) ||
+		   (is_mld && (key_info & WPA_KEY_INFO_SECURE))) {
 		msg = PAIRWISE_4;
 		msgtxt = "4/4 Pairwise";
 	} else {
@@ -4324,11 +4331,70 @@ done:
 	os_free(wpa_ie_buf2);
 }
 
+static int wpa_auth_validate_ml_kdes_m4(struct wpa_state_machine *sm)
+{
+#ifdef CONFIG_IEEE80211BE
+	struct ieee802_1x_hdr *hdr;
+	struct wpa_eapol_key *key;
+	struct wpa_eapol_ie_parse kde;
+	const u8 *key_data, *mic;
+	u16 key_data_length;
+	size_t mic_len;
+
+	if (sm->mld_assoc_link_id < 0)
+		return 0;
+
+	/*
+	 * Note: last_rx_eapol_key length fields have already been validated in
+	 * wpa_receive().
+	 */
+	mic_len = wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len);
+
+	hdr = (struct ieee802_1x_hdr *)sm->last_rx_eapol_key;
+	key = (struct wpa_eapol_key *)((void *)(hdr + 1));
+	mic = (u8 *)(key + 1);
+	key_data = mic + mic_len + 2;
+	key_data_length = WPA_GET_BE16(mic + mic_len);
+	if (key_data_length > sm->last_rx_eapol_key_len - sizeof(*hdr) -
+	    sizeof(*key) - mic_len - 2)
+		return -1;
+
+	if (wpa_parse_kde_ies(key_data, key_data_length, &kde) < 0) {
+		wpa_auth_vlogger(sm->wpa_auth, wpa_auth_get_spa(sm),
+				 LOGGER_INFO,
+				 "received EAPOL-Key msg 4/4 with invalid Key Data contents");
+		return -1;
+	}
+
+	/* MLD MAC address must be the same */
+	if (!kde.mac_addr ||
+	    os_memcmp(kde.mac_addr, sm->peer_mld_addr, ETH_ALEN)) {
+		wpa_printf(MSG_DEBUG,
+			   "WPA_AUTH: MLD: invalid MLD address in msg 4/4");
+		return -1;
+	}
+
+	wpa_printf(MSG_DEBUG,
+		   "WPA_AUTH: MLD: MLD address in message 4/4: " MACSTR,
+		   MAC2STR(kde.mac_addr));
+
+#endif /* CONFIG_IEEE80211BE */
+
+	return 0;
+}
+
 
 SM_STATE(WPA_PTK, PTKINITDONE)
 {
 	SM_ENTRY_MA(WPA_PTK, PTKINITDONE, wpa_ptk);
 	sm->EAPOLKeyReceived = false;
+
+	if (wpa_auth_validate_ml_kdes_m4(sm) < 0) {
+		wpa_sta_disconnect(sm->wpa_auth, sm->addr,
+				   WLAN_REASON_PREV_AUTH_NOT_VALID);
+		return;
+	}
+
 	if (sm->Pair) {
 		enum wpa_alg alg = wpa_cipher_to_alg(sm->pairwise);
 		int klen = wpa_cipher_key_len(sm->pairwise);
-- 
2.38.1




More information about the Hostap mailing list