FT: Do not allow multiple Reassociation Response frames

The driver is expected to not report a second association event without
the station having explicitly request a new association. As such, this
case should not be reachable. However, since reconfiguring the same
pairwise or group keys to the driver could result in nonce reuse issues,
be extra careful here and do an additional state check to avoid this
even if the local driver ends up somehow accepting an unexpected
Reassociation Response frame.

Bug: 65245581
Test: WiFi Integration Suite
Change-Id: Ic951a6fc87a742f7811b44ea0d93e6dae515c9ee
Merged-In: Ic951a6fc87a742f7811b44ea0d93e6dae515c9ee
Signed-off-by: Jouni Malinen <j@w1.fi>
Signed-off-by: Glen Kuhne <kuh@google.com>
(cherry picked from commit e01e480a81f4ed818d3e7690261e2199227bc0e4)
diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c
index 0d2b0aa..1221e67 100644
--- a/src/rsn_supp/wpa.c
+++ b/src/rsn_supp/wpa.c
@@ -2419,7 +2419,9 @@
 #ifdef CONFIG_TDLS
 	wpa_tdls_disassoc(sm);
 #endif /* CONFIG_TDLS */
-
+#ifdef CONFIG_IEEE80211R
+	sm->ft_reassoc_completed = 0;
+#endif /* CONFIG_IEEE80211R */
 	/* Keys are not needed in the WPA state machine anymore */
 	wpa_sm_drop_sa(sm);
 
diff --git a/src/rsn_supp/wpa_ft.c b/src/rsn_supp/wpa_ft.c
index 205793e..d45bb45 100644
--- a/src/rsn_supp/wpa_ft.c
+++ b/src/rsn_supp/wpa_ft.c
@@ -153,6 +153,7 @@
 	u16 capab;
 
 	sm->ft_completed = 0;
+	sm->ft_reassoc_completed = 0;
 
 	buf_len = 2 + sizeof(struct rsn_mdie) + 2 + sizeof(struct rsn_ftie) +
 		2 + sm->r0kh_id_len + ric_ies_len + 100;
@@ -681,6 +682,11 @@
 		return -1;
 	}
 
+	if (sm->ft_reassoc_completed) {
+		wpa_printf(MSG_DEBUG, "FT: Reassociation has already been completed for this FT protocol instance - ignore unexpected retransmission");
+		return 0;
+	}
+
 	if (wpa_ft_parse_ies(ies, ies_len, &parse) < 0) {
 		wpa_printf(MSG_DEBUG, "FT: Failed to parse IEs");
 		return -1;
@@ -781,6 +787,8 @@
 		return -1;
 	}
 
+	sm->ft_reassoc_completed = 1;
+
 	if (wpa_ft_process_gtk_subelem(sm, parse.gtk, parse.gtk_len) < 0)
 		return -1;
 
diff --git a/src/rsn_supp/wpa_i.h b/src/rsn_supp/wpa_i.h
index 2d32e46..a653802 100644
--- a/src/rsn_supp/wpa_i.h
+++ b/src/rsn_supp/wpa_i.h
@@ -126,6 +126,7 @@
 	size_t r0kh_id_len;
 	u8 r1kh_id[FT_R1KH_ID_LEN];
 	int ft_completed;
+	int ft_reassoc_completed;
 	int over_the_ds_in_progress;
 	u8 target_ap[ETH_ALEN]; /* over-the-DS target AP */
 	int set_ptk_after_assoc;