Merge "[wpa_supplicant] Cherry-pick security fixes (April 29, 2019)" into qt-dev
diff --git a/wpa_supplicant/hidl/1.2/p2p_iface.cpp b/wpa_supplicant/hidl/1.2/p2p_iface.cpp
index 7acb0d3..7dddee9 100644
--- a/wpa_supplicant/hidl/1.2/p2p_iface.cpp
+++ b/wpa_supplicant/hidl/1.2/p2p_iface.cpp
@@ -265,7 +265,11 @@
 				return -1;
 			}
 
-			params.freqs = (int *) os_malloc(sizeof(int) * 2);
+			/*
+			 * Allocate memory for frequency array, allocate one extra
+			 * slot for the zero-terminator.
+			 */
+			params.freqs = (int *) os_calloc(2, sizeof(int));
 			if (params.freqs) {
 				params.freqs[0] = freq;
 			} else {
diff --git a/wpa_supplicant/hidl/1.2/sta_network.cpp b/wpa_supplicant/hidl/1.2/sta_network.cpp
index 1354055..9f4e9d2 100644
--- a/wpa_supplicant/hidl/1.2/sta_network.cpp
+++ b/wpa_supplicant/hidl/1.2/sta_network.cpp
@@ -875,6 +875,7 @@
 	if (key_mgmt_mask & ~kAllowedKeyMgmtMask) {
 		return {SupplicantStatusCode::FAILURE_ARGS_INVALID, ""};
 	}
+	setFastTransitionKeyMgmt(key_mgmt_mask);
 	wpa_ssid->key_mgmt = key_mgmt_mask;
 	wpa_printf(MSG_MSGDUMP, "key_mgmt: 0x%x", wpa_ssid->key_mgmt);
 	resetInternalStateAfterParamsUpdate();
@@ -1320,8 +1321,10 @@
 std::pair<SupplicantStatus, uint32_t> StaNetwork::getKeyMgmtInternal()
 {
 	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
-	return {{SupplicantStatusCode::SUCCESS, ""},
-		wpa_ssid->key_mgmt & kAllowedKeyMgmtMask};
+	uint32_t key_mgmt_mask = wpa_ssid->key_mgmt & kAllowedKeyMgmtMask;
+
+	resetFastTransitionKeyMgmt(key_mgmt_mask);
+	return {{SupplicantStatusCode::SUCCESS, ""}, key_mgmt_mask};
 }
 
 std::pair<SupplicantStatus, uint32_t> StaNetwork::getProtoInternal()
@@ -2120,6 +2123,44 @@
 	resetInternalStateAfterParamsUpdate();
 	return 0;
 }
+
+/**
+ * Helper function to set the fast transition bits in the key management
+ * bitmask, to allow FT support when possible.
+ */
+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;
+	}
+
+	if (key_mgmt_mask & WPA_KEY_MGMT_IEEE8021X) {
+		key_mgmt_mask |= WPA_KEY_MGMT_FT_IEEE8021X;
+	}
+}
+
+/**
+ * Helper function to reset the fast transition bits in the key management
+ * bitmask.
+ */
+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;
+	}
+
+	if (key_mgmt_mask & WPA_KEY_MGMT_IEEE8021X) {
+		key_mgmt_mask &= ~WPA_KEY_MGMT_FT_IEEE8021X;
+	}
+}
 }  // namespace implementation
 }  // namespace V1_2
 }  // namespace supplicant
diff --git a/wpa_supplicant/hidl/1.2/sta_network.h b/wpa_supplicant/hidl/1.2/sta_network.h
index a235257..16d065e 100644
--- a/wpa_supplicant/hidl/1.2/sta_network.h
+++ b/wpa_supplicant/hidl/1.2/sta_network.h
@@ -363,6 +363,8 @@
 	    const uint8_t* value, const size_t value_len,
 	    uint8_t** to_update_field, size_t* to_update_field_len,
 	    const char* hexdump_prefix);
+	void setFastTransitionKeyMgmt(uint32_t &key_mgmt_mask);
+	void resetFastTransitionKeyMgmt(uint32_t &key_mgmt_mask);
 
 	// Reference to the global wpa_struct. This is assumed to be valid
 	// for the lifetime of the process.
diff --git a/wpa_supplicant/notify.c b/wpa_supplicant/notify.c
index bd4b8ae..41dc334 100644
--- a/wpa_supplicant/notify.c
+++ b/wpa_supplicant/notify.c
@@ -60,30 +60,28 @@
 
 int wpas_notify_iface_added(struct wpa_supplicant *wpa_s)
 {
-	if (wpa_s->p2p_mgmt)
-		return 0;
+	if (!wpa_s->p2p_mgmt) {
+		if (wpas_dbus_register_interface(wpa_s))
+			return -1;
+	}
 
 	/* HIDL interface wants to keep track of the P2P mgmt iface. */
 	if (wpas_hidl_register_interface(wpa_s))
 		return -1;
 
-	if (wpas_dbus_register_interface(wpa_s))
-		return -1;
-
 	return 0;
 }
 
 
 void wpas_notify_iface_removed(struct wpa_supplicant *wpa_s)
 {
-	if (wpa_s->p2p_mgmt)
-		return;
+	if (!wpa_s->p2p_mgmt) {
+		/* unregister interface in new DBus ctrl iface */
+		wpas_dbus_unregister_interface(wpa_s);
+	}
 
 	/* HIDL interface wants to keep track of the P2P mgmt iface. */
 	wpas_hidl_unregister_interface(wpa_s);
-
-	/* unregister interface in new DBus ctrl iface */
-	wpas_dbus_unregister_interface(wpa_s);
 }