Merge tag 'android-security-10.0.0_r55' into int/10/fp2

Android Security 10.0.0 Release 55 (7269719)

* tag 'android-security-10.0.0_r55':
  P2P: Fix a corner case in peer addition based on PD Request

Change-Id: Ia1d2651b77b13f3f99287189df87c419908b035c
diff --git a/src/ap/drv_callbacks.c b/src/ap/drv_callbacks.c
index 952a3d5..e3844d9 100644
--- a/src/ap/drv_callbacks.c
+++ b/src/ap/drv_callbacks.c
@@ -131,6 +131,19 @@
 			   "hostapd_notif_assoc: Skip event with no address");
 		return -1;
 	}
+
+	if (is_multicast_ether_addr(addr) ||
+	    is_zero_ether_addr(addr) ||
+	    os_memcmp(addr, hapd->own_addr, ETH_ALEN) == 0) {
+		/* Do not process any frames with unexpected/invalid SA so that
+		 * we do not add any state for unexpected STA addresses or end
+		 * up sending out frames to unexpected destination. */
+		wpa_printf(MSG_DEBUG, "%s: Invalid SA=" MACSTR
+			   " in received indication - ignore this indication silently",
+			   __func__, MAC2STR(addr));
+		return 0;
+	}
+
 	random_add_randomness(addr, ETH_ALEN);
 
 	hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211,
diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c
index 5cd2562..36161c2 100644
--- a/src/ap/ieee802_11.c
+++ b/src/ap/ieee802_11.c
@@ -4461,6 +4461,18 @@
 	fc = le_to_host16(mgmt->frame_control);
 	stype = WLAN_FC_GET_STYPE(fc);
 
+	if (is_multicast_ether_addr(mgmt->sa) ||
+	    is_zero_ether_addr(mgmt->sa) ||
+	    os_memcmp(mgmt->sa, hapd->own_addr, ETH_ALEN) == 0) {
+		/* Do not process any frames with unexpected/invalid SA so that
+		 * we do not add any state for unexpected STA addresses or end
+		 * up sending out frames to unexpected destination. */
+		wpa_printf(MSG_DEBUG, "MGMT: Invalid SA=" MACSTR
+			   " in received frame - ignore this frame silently",
+			   MAC2STR(mgmt->sa));
+		return 0;
+	}
+
 	if (stype == WLAN_FC_STYPE_BEACON) {
 		handle_beacon(hapd, mgmt, len, fi);
 		return 1;
diff --git a/src/eap_common/eap_sim_common.c b/src/eap_common/eap_sim_common.c
index 6290c35..cfdd1bf 100644
--- a/src/eap_common/eap_sim_common.c
+++ b/src/eap_common/eap_sim_common.c
@@ -1203,3 +1203,19 @@
 		}
 	}
 }
+
+
+int eap_sim_anonymous_username(const u8 *id, size_t id_len)
+{
+	static const char *anonymous_id_prefix = "anonymous@";
+	size_t anonymous_id_len = os_strlen(anonymous_id_prefix);
+
+	if (id_len > anonymous_id_len &&
+	    os_memcmp(id, anonymous_id_prefix, anonymous_id_len) == 0)
+		return 1; /* 'anonymous@realm' */
+
+	if (id_len > 1 && id[0] == '@')
+		return 1; /* '@realm' */
+
+	return 0;
+}
diff --git a/src/eap_common/eap_sim_common.h b/src/eap_common/eap_sim_common.h
index daeb0e2..7142b94 100644
--- a/src/eap_common/eap_sim_common.h
+++ b/src/eap_common/eap_sim_common.h
@@ -226,5 +226,6 @@
 			     int attr_pad);
 
 void eap_sim_report_notification(void *msg_ctx, int notification, int aka);
+int eap_sim_anonymous_username(const u8 *id, size_t id_len);
 
 #endif /* EAP_SIM_COMMON_H */
diff --git a/src/eap_peer/eap_aka.c b/src/eap_peer/eap_aka.c
index a96a39f..ff88cf8 100644
--- a/src/eap_peer/eap_aka.c
+++ b/src/eap_peer/eap_aka.c
@@ -57,7 +57,6 @@
 	u16 last_kdf_attrs[EAP_AKA_PRIME_KDF_MAX];
 	size_t last_kdf_count;
 	int error_code;
-	int anonymous_flag;
 };
 
 
@@ -94,7 +93,6 @@
 	struct eap_aka_data *data;
 	const char *phase1 = eap_get_config_phase1(sm);
 	struct eap_peer_config *config = eap_get_config(sm);
-	static const char *anonymous_id_prefix = "anonymous@";
 
 	data = os_zalloc(sizeof(*data));
 	if (data == NULL)
@@ -109,7 +107,6 @@
 	data->prev_id = -1;
 
 	data->result_ind = phase1 && os_strstr(phase1, "result_ind=1") != NULL;
-	data->anonymous_flag = 0;
 
 	data->use_pseudonym = !sm->init_phase2;
 	if (config && config->anonymous_identity && data->use_pseudonym) {
@@ -118,13 +115,6 @@
 			os_memcpy(data->pseudonym, config->anonymous_identity,
 				  config->anonymous_identity_len);
 			data->pseudonym_len = config->anonymous_identity_len;
-			if (data->pseudonym_len > os_strlen(anonymous_id_prefix) &&
-					!os_memcmp(data->pseudonym, anonymous_id_prefix,
-					os_strlen(anonymous_id_prefix))) {
-				data->anonymous_flag = 1;
-				wpa_printf(MSG_DEBUG,
-					   "EAP-AKA: Setting anonymous@realm flag");
-			}
 		}
 	}
 
@@ -427,7 +417,6 @@
 		if (data->use_pseudonym)
 			eap_set_anon_id(sm, data->pseudonym,
 					data->pseudonym_len);
-		data->anonymous_flag = 0;
 	}
 
 	if (attr->next_reauth_id) {
@@ -633,15 +622,22 @@
 		identity_len = data->reauth_id_len;
 		data->reauth = 1;
 	} else if ((id_req == ANY_ID || id_req == FULLAUTH_ID) &&
-		   data->pseudonym && !data->anonymous_flag) {
+		   data->pseudonym &&
+		   !eap_sim_anonymous_username(data->pseudonym,
+					       data->pseudonym_len)) {
 		identity = data->pseudonym;
 		identity_len = data->pseudonym_len;
 		eap_aka_clear_identities(sm, data, CLEAR_REAUTH_ID);
 	} else if (id_req != NO_ID_REQ) {
 		identity = eap_get_config_identity(sm, &identity_len);
 		if (identity) {
-			eap_aka_clear_identities(sm, data, CLEAR_PSEUDONYM |
-						 CLEAR_REAUTH_ID);
+			int ids = CLEAR_PSEUDONYM | CLEAR_REAUTH_ID;
+
+			if (data->pseudonym &&
+			    eap_sim_anonymous_username(data->pseudonym,
+						       data->pseudonym_len))
+				ids &= ~CLEAR_PSEUDONYM;
+			eap_aka_clear_identities(sm, data, ids);
 		}
 	}
 	if (id_req != NO_ID_REQ)
@@ -1037,7 +1033,9 @@
 	if (data->last_eap_identity) {
 		identity = data->last_eap_identity;
 		identity_len = data->last_eap_identity_len;
-	} else if (data->pseudonym && !data->anonymous_flag) {
+	} else if (data->pseudonym &&
+		   !eap_sim_anonymous_username(data->pseudonym,
+					       data->pseudonym_len)) {
 		identity = data->pseudonym;
 		identity_len = data->pseudonym_len;
 	} else {
diff --git a/src/eap_peer/eap_sim.c b/src/eap_peer/eap_sim.c
index 6989aa8..b5811a8 100644
--- a/src/eap_peer/eap_sim.c
+++ b/src/eap_peer/eap_sim.c
@@ -48,7 +48,6 @@
 	int result_ind, use_result_ind;
 	int use_pseudonym;
 	int error_code;
-	int anonymous_flag;
 };
 
 
@@ -84,7 +83,6 @@
 {
 	struct eap_sim_data *data;
 	struct eap_peer_config *config = eap_get_config(sm);
-	static const char *anonymous_id_prefix = "anonymous@";
 
 	data = os_zalloc(sizeof(*data));
 	if (data == NULL)
@@ -99,7 +97,7 @@
 
 	/* Zero is a valid error code, so we need to initialize */
 	data->error_code = NO_EAP_METHOD_ERROR;
-	data->anonymous_flag = 0;
+
 	data->min_num_chal = 2;
 	if (config && config->phase1) {
 		char *pos = os_strstr(config->phase1, "sim_min_num_chal=");
@@ -129,14 +127,6 @@
 			os_memcpy(data->pseudonym, config->anonymous_identity,
 				  config->anonymous_identity_len);
 			data->pseudonym_len = config->anonymous_identity_len;
-			if (data->pseudonym_len > os_strlen(anonymous_id_prefix) &&
-					!os_memcmp(data->pseudonym, anonymous_id_prefix,
-					os_strlen(anonymous_id_prefix))) {
-				data->anonymous_flag = 1;
-				wpa_printf(MSG_DEBUG,
-					   "EAP-SIM: Setting anonymous@realm flag");
-			}
-
 		}
 	}
 
@@ -447,7 +437,6 @@
 		if (data->use_pseudonym)
 			eap_set_anon_id(sm, data->pseudonym,
 					data->pseudonym_len);
-		data->anonymous_flag = 0;
 	}
 
 	if (attr->next_reauth_id) {
@@ -503,15 +492,22 @@
 		identity_len = data->reauth_id_len;
 		data->reauth = 1;
 	} else if ((id_req == ANY_ID || id_req == FULLAUTH_ID) &&
-		   data->pseudonym && !data->anonymous_flag) {
+		   data->pseudonym &&
+		   !eap_sim_anonymous_username(data->pseudonym,
+					       data->pseudonym_len)) {
 		identity = data->pseudonym;
 		identity_len = data->pseudonym_len;
 		eap_sim_clear_identities(sm, data, CLEAR_REAUTH_ID);
 	} else if (id_req != NO_ID_REQ) {
 		identity = eap_get_config_identity(sm, &identity_len);
 		if (identity) {
-			eap_sim_clear_identities(sm, data, CLEAR_PSEUDONYM |
-						 CLEAR_REAUTH_ID);
+			int ids = CLEAR_PSEUDONYM | CLEAR_REAUTH_ID;
+
+			if (data->pseudonym &&
+			    eap_sim_anonymous_username(data->pseudonym,
+						       data->pseudonym_len))
+				ids &= ~CLEAR_PSEUDONYM;
+			eap_sim_clear_identities(sm, data, ids);
 		}
 	}
 	if (id_req != NO_ID_REQ)
@@ -779,7 +775,9 @@
 	if (data->last_eap_identity) {
 		identity = data->last_eap_identity;
 		identity_len = data->last_eap_identity_len;
-	} else if (data->pseudonym && !data->anonymous_flag) {
+	} else if (data->pseudonym &&
+		   !eap_sim_anonymous_username(data->pseudonym,
+					       data->pseudonym_len)) {
 		identity = data->pseudonym;
 		identity_len = data->pseudonym_len;
 	} else {
diff --git a/wpa_supplicant/hidl/1.2/p2p_iface.cpp b/wpa_supplicant/hidl/1.2/p2p_iface.cpp
index ada7ee6..fd9ce0d 100644
--- a/wpa_supplicant/hidl/1.2/p2p_iface.cpp
+++ b/wpa_supplicant/hidl/1.2/p2p_iface.cpp
@@ -225,6 +225,12 @@
 	size_t ielen;
 	unsigned int bands;
 
+	if (wpa_s->global->p2p == NULL || wpa_s->global->p2p_disabled) {
+		wpa_printf(MSG_ERROR,
+		    "P2P: P2P interface is gone, cancel join scan");
+		return -ENXIO;
+	}
+
 	os_memset(&params, 0, sizeof(params));
 	if (ssid.size() > 0) {
 		params.ssids[0].ssid = ssid.data();
@@ -1628,6 +1634,10 @@
 	int vht = wpa_s->conf->p2p_go_vht;
 	int ht40 = wpa_s->conf->p2p_go_ht40 || vht;
 
+	if (wpa_s->global->p2p == NULL || wpa_s->global->p2p_disabled) {
+		return {SupplicantStatusCode::FAILURE_IFACE_DISABLED, ""};
+	}
+
 	if (!isSsidValid(ssid)) {
 		return {SupplicantStatusCode::FAILURE_ARGS_INVALID, "SSID is invalid."};
 	}
@@ -1637,10 +1647,6 @@
 	}
 
 	if (!joinExistingGroup) {
-		if (wpa_s->global->p2p == NULL) {
-			return {SupplicantStatusCode::FAILURE_IFACE_DISABLED, ""};
-		}
-
 		struct p2p_data *p2p = wpa_s->global->p2p;
 		os_memcpy(p2p->ssid, ssid.data(), ssid.size());
 		p2p->ssid_len = ssid.size();
@@ -1685,6 +1691,9 @@
 
 	pending_join_scan_callback =
 	    [wpa_s, ssid, freq]() {
+		if (wpa_s->global->p2p == NULL || wpa_s->global->p2p_disabled) {
+			return;
+		}
 		int ret = joinScanReq(wpa_s, ssid, freq);
 		// for BUSY case, the scan might be occupied by WiFi.
 		// Do not give up immediately, but try again later.
@@ -1701,7 +1710,7 @@
 	};
 
 	pending_scan_res_join_callback = [wpa_s, ssid, passphrase, peer_address, this]() {
-		if (wpa_s->global->p2p_disabled) {
+		if (wpa_s->global->p2p == NULL || wpa_s->global->p2p_disabled) {
 			return;
 		}
 
diff --git a/wpa_supplicant/hidl/1.2/sta_network.cpp b/wpa_supplicant/hidl/1.2/sta_network.cpp
index 9f4e9d2..4d694f7 100644
--- a/wpa_supplicant/hidl/1.2/sta_network.cpp
+++ b/wpa_supplicant/hidl/1.2/sta_network.cpp
@@ -1011,8 +1011,9 @@
 SupplicantStatus StaNetwork::setRequirePmfInternal(bool enable)
 {
 	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
-	wpa_ssid->ieee80211w =
-	    enable ? MGMT_FRAME_PROTECTION_REQUIRED : NO_MGMT_FRAME_PROTECTION;
+	if (enable) {
+		wpa_ssid->ieee80211w = MGMT_FRAME_PROTECTION_REQUIRED;
+	}
 	resetInternalStateAfterParamsUpdate();
 	return {SupplicantStatusCode::SUCCESS, ""};
 }
@@ -2130,10 +2131,6 @@
  */
 void StaNetwork::setFastTransitionKeyMgmt(uint32_t &key_mgmt_mask)
 {
-	if (key_mgmt_mask & WPA_KEY_MGMT_SAE) {
-		key_mgmt_mask |= WPA_KEY_MGMT_FT_SAE;
-	}
-
 	if (key_mgmt_mask & WPA_KEY_MGMT_PSK) {
 		key_mgmt_mask |= WPA_KEY_MGMT_FT_PSK;
 	}
@@ -2149,10 +2146,6 @@
  */
 void StaNetwork::resetFastTransitionKeyMgmt(uint32_t &key_mgmt_mask)
 {
-	if (key_mgmt_mask & WPA_KEY_MGMT_SAE) {
-		key_mgmt_mask &= ~WPA_KEY_MGMT_FT_SAE;
-	}
-
 	if (key_mgmt_mask & WPA_KEY_MGMT_PSK) {
 		key_mgmt_mask &= ~WPA_KEY_MGMT_FT_PSK;
 	}
diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index be8efb4..5d4adf4 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -4333,6 +4333,7 @@
 	}
 
 	wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
+	wpas_wps_update_mac_addr(wpa_s);
 
 	return 0;
 }
diff --git a/wpa_supplicant/wps_supplicant.c b/wpa_supplicant/wps_supplicant.c
index 2950763..5da8154 100644
--- a/wpa_supplicant/wps_supplicant.c
+++ b/wpa_supplicant/wps_supplicant.c
@@ -2235,6 +2235,16 @@
 }
 
 
+void wpas_wps_update_mac_addr(struct wpa_supplicant *wpa_s)
+{
+	struct wps_context *wps;
+
+	wps = wpa_s->wps;
+	if (wps)
+		os_memcpy(wps->dev.mac_addr, wpa_s->own_addr, ETH_ALEN);
+}
+
+
 #ifdef CONFIG_WPS_NFC
 
 #ifdef CONFIG_WPS_ER
diff --git a/wpa_supplicant/wps_supplicant.h b/wpa_supplicant/wps_supplicant.h
index 3a99f2c..41b9298 100644
--- a/wpa_supplicant/wps_supplicant.h
+++ b/wpa_supplicant/wps_supplicant.h
@@ -62,6 +62,7 @@
 					     int ndef, const char *uuid);
 int wpas_wps_terminate_pending(struct wpa_supplicant *wpa_s);
 void wpas_wps_update_config(struct wpa_supplicant *wpa_s);
+void wpas_wps_update_mac_addr(struct wpa_supplicant *wpa_s);
 struct wpabuf * wpas_wps_network_config_token(struct wpa_supplicant *wpa_s,
 					  int ndef, struct wpa_ssid * ssid);
 struct wpabuf * wpas_wps_nfc_config_token(struct wpa_supplicant *wpa_s,
@@ -156,6 +157,10 @@
 	return 0;
 }
 
+static inline void wpas_wps_update_mac_addr(struct wpa_supplicant *wpa_s)
+{
+}
+
 #endif /* CONFIG_WPS */
 
 #endif /* WPS_SUPPLICANT_H */