Snap for 7482982 from eaaf04ea4ffcfebfba5a187e27a77d2d8a3c8057 to sc-release

Change-Id: I9fb2a40834cbf090f65833c5b96f1d3b783f7257
diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c
index 64a6ccb..ede782c 100644
--- a/src/rsn_supp/wpa.c
+++ b/src/rsn_supp/wpa.c
@@ -32,7 +32,8 @@
 #include "pmksa_cache.h"
 #include "wpa_i.h"
 #include "wpa_ie.h"
-
+#include "wpa_supplicant_i.h"
+#include "driver_i.h"
 
 static const u8 null_rsc[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
 
@@ -3877,6 +3878,32 @@
 			"WPA: Failed to set PMK to the driver");
 	}
 }
+
+void wpa_sm_notify_brcm_ft_reassoc(struct wpa_sm *sm, const u8 *bssid)
+{
+	u8 buf[256];
+	struct wpa_supplicant *wpa_s = sm->ctx->ctx;
+
+	wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
+		"WPA: BRCM FT Reassociation event - clear replay counter");
+	os_memcpy(sm->bssid, bssid, ETH_ALEN);
+	os_memset(sm->rx_replay_counter, 0, WPA_REPLAY_COUNTER_LEN);
+	sm->rx_replay_counter_set = 0;
+
+	if (wpa_drv_driver_cmd(wpa_s, "GET_FTKEY", (char *)buf, sizeof(buf)) < 0) {
+		wpa_msg(sm->ctx->msg_ctx, MSG_ERROR,
+			"WPA: Failed to get FT KEY information");
+		wpa_supplicant_deauthenticate(
+			wpa_s, WLAN_REASON_DEAUTH_LEAVING);
+
+	} else {
+		/* update kck and kek */
+		os_memcpy(sm->ptk.kck, buf, 16);
+		os_memcpy(sm->ptk.kek, buf + 16, 16);
+		wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
+			"WPA: Updated KCK and KEK after FT reassoc");
+	}
+}
 #endif /* CONFIG_DRIVER_NL80211_BRCM */
 
 #ifdef CONFIG_WNM
diff --git a/src/rsn_supp/wpa.h b/src/rsn_supp/wpa.h
index 541ef5a..95c58f6 100644
--- a/src/rsn_supp/wpa.h
+++ b/src/rsn_supp/wpa.h
@@ -208,6 +208,7 @@
 
 #ifdef CONFIG_DRIVER_NL80211_BRCM
 void wpa_sm_install_pmk(struct wpa_sm *sm);
+void wpa_sm_notify_brcm_ft_reassoc(struct wpa_sm *sm, const u8 *bssid);
 #endif /* CONFIG_DRIVER_NL80211_BRCM */
 
 void wpa_sm_set_rx_replay_ctr(struct wpa_sm *sm, const u8 *rx_replay_counter);
@@ -434,7 +435,9 @@
 				 size_t ies_len, const u8 *src_addr);
 int wpa_ft_start_over_ds(struct wpa_sm *sm, const u8 *target_ap,
 			 const u8 *mdie);
-
+#ifdef CONFIG_DRIVER_NL80211_BRCM
+int wpa_ft_is_ft_protocol(struct wpa_sm *sm);
+#endif /* CONFIG_DRIVER_NL80211_BRCM */
 #ifdef CONFIG_PASN
 
 int wpa_pasn_ft_derive_pmk_r1(struct wpa_sm *sm, int akmp, const u8 *r1kh_id,
@@ -474,6 +477,13 @@
 	return 0;
 }
 
+#ifdef CONFIG_DRIVER_NL80211_BRCM
+static inline int wpa_ft_is_ft_protocol(struct wpa_sm *sm)
+{
+	return 0;
+}
+#endif /* CONFIG_DRIVER_NL80211_BRCM */
+
 static inline void wpa_reset_ft_completed(struct wpa_sm *sm)
 {
 }
diff --git a/src/rsn_supp/wpa_ft.c b/src/rsn_supp/wpa_ft.c
index c517c41..caad760 100644
--- a/src/rsn_supp/wpa_ft.c
+++ b/src/rsn_supp/wpa_ft.c
@@ -743,6 +743,18 @@
 	return sm->ft_completed;
 }
 
+#ifdef CONFIG_DRIVER_NL80211_BRCM
+int wpa_ft_is_ft_protocol(struct wpa_sm *sm)
+{
+	if (sm == NULL)
+		return 0;
+
+	if (!wpa_key_mgmt_ft(sm->key_mgmt))
+		return 0;
+
+	return sm->ft_protocol;
+}
+#endif /* CONFIG_DRIVER_NL80211_BRCM */
 
 void wpa_reset_ft_completed(struct wpa_sm *sm)
 {
diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c
index 9c4f9f5..01bbde6 100644
--- a/wpa_supplicant/events.c
+++ b/wpa_supplicant/events.c
@@ -2929,7 +2929,10 @@
 	}
 #endif /* CONFIG_SME */
 #ifdef CONFIG_DRIVER_NL80211_BRCM
-	if ((wpa_s->key_mgmt == WPA_KEY_MGMT_FT_SAE) &&
+	if (((wpa_s->key_mgmt == WPA_KEY_MGMT_FT_PSK) ||
+		(wpa_s->key_mgmt == WPA_KEY_MGMT_FT_IEEE8021X) ||
+		(wpa_s->key_mgmt == WPA_KEY_MGMT_FT_SAE) ||
+		(wpa_s->key_mgmt == WPA_KEY_MGMT_FT_IEEE8021X_SHA384)) &&
 		wpa_ft_is_completed(wpa_s->wpa)) {
 		return 0;
 	}
@@ -3119,7 +3122,7 @@
 		/* Check for FT reassociation is done by the driver */
 #ifdef CONFIG_IEEE80211R
 		int use_sha384 = wpa_key_mgmt_sha384(wpa_s->wpa->key_mgmt);
-		if ((wpa_s->key_mgmt == WPA_KEY_MGMT_FT_SAE) && (wpa_s->key_mgmt == ie.key_mgmt)) {
+		if (wpa_key_mgmt_ft(wpa_s->key_mgmt) && (wpa_s->key_mgmt == ie.key_mgmt)) {
 			if (wpa_ft_parse_ies(data->assoc_info.resp_ies,
 				data->assoc_info.resp_ies_len, &parse, use_sha384) < 0) {
 				wpa_printf(MSG_DEBUG, "Failed to parse FT IEs");
@@ -3293,7 +3296,20 @@
 		 */
 		eapol_sm_notify_portValid(wpa_s->eapol, true);
 	}
-
+#ifdef CONFIG_DRIVER_NL80211_BRCM
+	if (ft_completed && wpa_key_mgmt_ft(wpa_s->key_mgmt)) {
+		if (wpa_drv_get_bssid(wpa_s, bssid) < 0) {
+			wpa_dbg(wpa_s, MSG_ERROR, "Failed to get BSSID, key_mgmt: 0x%0x",
+				wpa_s->key_mgmt);
+			wpa_supplicant_deauthenticate(
+				wpa_s, WLAN_REASON_DEAUTH_LEAVING);
+			return;
+		}
+		os_memcpy(wpa_s->bssid, bssid, ETH_ALEN);
+		wpa_s->assoc_freq = data->assoc_info.freq;
+		wpa_sm_notify_brcm_ft_reassoc(wpa_s->wpa, bssid);
+	}
+#endif /* CONFIG_DRIVER_NL80211_BRCM */
 	wpa_s->last_eapol_matches_bssid = 0;
 
 #ifdef CONFIG_TESTING_OPTIONS
diff --git a/wpa_supplicant/hidl/1.4/p2p_iface.cpp b/wpa_supplicant/hidl/1.4/p2p_iface.cpp
index db8f3a4..cabcccb 100644
--- a/wpa_supplicant/hidl/1.4/p2p_iface.cpp
+++ b/wpa_supplicant/hidl/1.4/p2p_iface.cpp
@@ -26,7 +26,12 @@
 }
 
 #define P2P_MAX_JOIN_SCAN_ATTEMPTS 3
-#define P2P_JOIN_SCAN_INTERVAL_USECS 1000000
+// Wait time before triggering the single channel scan to discover Auto GO.
+// Use a shorter wait time when the given frequency is GO operating frequency.
+// The idea is to quickly finish scans and return the status to application.
+#define P2P_JOIN_SINGLE_CHANNEL_SCAN_INTERVAL_USECS 200000
+// Wait time before triggering the multiple channel scan to discover Auto GO.
+#define P2P_JOIN_MULTIPLE_CHANNEL_SCAN_INTERVAL_USECS 1000000
 
 namespace {
 const char kConfigMethodStrPbc[] = "pbc";
@@ -180,6 +185,19 @@
 	return 0;
 }
 
+/**
+ * getP2pJoinScanInterval - Get the delay in triggering the scan to discover
+ * Auto GO.
+ */
+static int getP2pJoinScanIntervalUsecs(int freq)
+{
+	if (freq == 5 || freq == 2 || freq == 0) {
+		return P2P_JOIN_MULTIPLE_CHANNEL_SCAN_INTERVAL_USECS;
+	} else {
+		return P2P_JOIN_SINGLE_CHANNEL_SCAN_INTERVAL_USECS;
+	}
+}
+
 /*
  * isAnyEtherAddr - match any ether address
  *
@@ -1795,7 +1813,7 @@
 		}
 	};
 
-	pending_scan_res_join_callback = [wpa_s, ssid, passphrase, peer_address, this]() {
+	pending_scan_res_join_callback = [wpa_s, ssid, passphrase, peer_address, freq, this]() {
 		if (wpa_s->global->p2p == NULL || wpa_s->global->p2p_disabled) {
 			return;
 		}
@@ -1820,7 +1838,7 @@
 		eloop_cancel_timeout(joinScanWrapper, wpa_s, NULL);
 		if (wpa_s->p2p_join_scan_count < P2P_MAX_JOIN_SCAN_ATTEMPTS) {
 			wpa_printf(MSG_DEBUG, "P2P: Try join again later.");
-			eloop_register_timeout(0, P2P_JOIN_SCAN_INTERVAL_USECS,
+			eloop_register_timeout(0, getP2pJoinScanIntervalUsecs(freq),
 			    joinScanWrapper, wpa_s, this);
 			return;
 		}
diff --git a/wpa_supplicant/wpas_glue.c b/wpa_supplicant/wpas_glue.c
index b1c606f..95dad95 100644
--- a/wpa_supplicant/wpas_glue.c
+++ b/wpa_supplicant/wpas_glue.c
@@ -308,9 +308,19 @@
 		ieee802_1x_notify_create_actor(wpa_s, wpa_s->last_eapol_src);
 	}
 
-	if (result != EAPOL_SUPP_RESULT_SUCCESS ||
-	    !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_8021X))
+#ifdef CONFIG_DRIVER_NL80211_BRCM                                                            
+	if (result != EAPOL_SUPP_RESULT_SUCCESS)                          
+#else                                                                     
+	if (result != EAPOL_SUPP_RESULT_SUCCESS ||                        
+		!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_8021X))  
+#endif /* CONFIG_DRIVER_NL80211_BRCM */                                                      
+		return;                                                   
+
+#ifdef CONFIG_DRIVER_NL80211_BRCM
+	if (wpa_ft_is_ft_protocol(wpa_s->wpa)) {
 		return;
+	}
+#endif /* CONFIG_DRIVER_NL80211_BRCM */
 
 	if (!wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt))
 		return;