Cumulative patch from commit b4342ca4d8f21af51d4923ca15910d3211bfdc7e

b4342ca P2P: Use p2p_init_wpa_s for P2P command redirection over D-Bus
96512a0 P2P: Fix D-Bus PresenceRequest to use group interface
b740401 P2P: Fix wpas_remove_persistent_peer() to use P2P mgmt interface
1e0a029 P2P: Fix wpas_p2p_add_persistent_group_client() to use P2P mgmt interface
86b91c8 P2P: Fix wpas_p2p_set_own_freq_preference() to use P2P mgmt interface
4367749 P2P: Use the P2P Device management interface in wpas_p2p_remove_client()
7b642dc P2P: Add D-Bus FindStopped to notify P2P-FIND-STOPPED event
d63f141 P2P: Advertize cross connection to WLAN AP on a non-P2P interface
ca24117 EAP-EKE: Add Session-Id
7f2f3a6 Increase DH key size in the hostapd.conf example
567098e ACS: Scan only channels specified in the channel list
c7dafdf WPS: Fix build without CONFIG_WPS=y

Change-Id: I7bcd69f71b239e7f907eccdb925bd954e72d8758
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf
index 5c6b28d..390c753 100644
--- a/hostapd/hostapd.conf
+++ b/hostapd/hostapd.conf
@@ -790,7 +790,7 @@
 # is in DSA parameters format, it will be automatically converted into DH
 # params. This parameter is required if anonymous EAP-FAST is used.
 # You can generate DH parameters file with OpenSSL, e.g.,
-# "openssl dhparam -out /etc/hostapd.dh.pem 1024"
+# "openssl dhparam -out /etc/hostapd.dh.pem 2048"
 #dh_file=/etc/hostapd.dh.pem
 
 # OpenSSL cipher string
diff --git a/src/ap/acs.c b/src/ap/acs.c
index 652d020..03d797f 100644
--- a/src/ap/acs.c
+++ b/src/ap/acs.c
@@ -894,6 +894,9 @@
 		if (chan->flag & HOSTAPD_CHAN_DISABLED)
 			continue;
 
+		if (!is_in_chanlist(iface, chan))
+			continue;
+
 		*freq++ = chan->freq;
 	}
 	*freq = 0;
diff --git a/src/eap_peer/eap_eke.c b/src/eap_peer/eap_eke.c
index 987af83..dfbda56 100644
--- a/src/eap_peer/eap_eke.c
+++ b/src/eap_peer/eap_eke.c
@@ -744,6 +744,29 @@
 }
 
 
+static u8 * eap_eke_get_session_id(struct eap_sm *sm, void *priv, size_t *len)
+{
+	struct eap_eke_data *data = priv;
+	u8 *sid;
+	size_t sid_len;
+
+	if (data->state != SUCCESS)
+		return NULL;
+
+	sid_len = 1 + 2 * data->sess.nonce_len;
+	sid = os_malloc(sid_len);
+	if (sid == NULL)
+		return NULL;
+	sid[0] = EAP_TYPE_EKE;
+	os_memcpy(sid + 1, data->nonce_p, data->sess.nonce_len);
+	os_memcpy(sid + 1 + data->sess.nonce_len, data->nonce_s,
+		  data->sess.nonce_len);
+	*len = sid_len;
+
+	return sid;
+}
+
+
 int eap_peer_eke_register(void)
 {
 	struct eap_method *eap;
@@ -760,6 +783,7 @@
 	eap->isKeyAvailable = eap_eke_isKeyAvailable;
 	eap->getKey = eap_eke_getKey;
 	eap->get_emsk = eap_eke_get_emsk;
+	eap->getSessionId = eap_eke_get_session_id;
 
 	ret = eap_peer_method_register(eap);
 	if (ret)
diff --git a/src/eap_server/eap_server_eke.c b/src/eap_server/eap_server_eke.c
index 966f511..ba82be9 100644
--- a/src/eap_server/eap_server_eke.c
+++ b/src/eap_server/eap_server_eke.c
@@ -766,6 +766,29 @@
 }
 
 
+static u8 * eap_eke_get_session_id(struct eap_sm *sm, void *priv, size_t *len)
+{
+	struct eap_eke_data *data = priv;
+	u8 *sid;
+	size_t sid_len;
+
+	if (data->state != SUCCESS)
+		return NULL;
+
+	sid_len = 1 + 2 * data->sess.nonce_len;
+	sid = os_malloc(sid_len);
+	if (sid == NULL)
+		return NULL;
+	sid[0] = EAP_TYPE_EKE;
+	os_memcpy(sid + 1, data->nonce_p, data->sess.nonce_len);
+	os_memcpy(sid + 1 + data->sess.nonce_len, data->nonce_s,
+		  data->sess.nonce_len);
+	*len = sid_len;
+
+	return sid;
+}
+
+
 int eap_server_eke_register(void)
 {
 	struct eap_method *eap;
@@ -785,6 +808,7 @@
 	eap->getKey = eap_eke_getKey;
 	eap->isSuccess = eap_eke_isSuccess;
 	eap->get_emsk = eap_eke_get_emsk;
+	eap->getSessionId = eap_eke_get_session_id;
 
 	ret = eap_server_method_register(eap);
 	if (ret)
diff --git a/wpa_supplicant/dbus/dbus_new.c b/wpa_supplicant/dbus/dbus_new.c
index 89a562c..840d105 100644
--- a/wpa_supplicant/dbus/dbus_new.c
+++ b/wpa_supplicant/dbus/dbus_new.c
@@ -3039,6 +3039,11 @@
 		  END_ARGS
 	  }
 	},
+	{ "FindStopped", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
+	  {
+		  END_ARGS
+	  }
+	},
 	{ "ProvisionDiscoveryRequestDisplayPin", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
 	  {
 		  { "peer_object", "o", ARG_OUT },
@@ -3530,6 +3535,35 @@
 }
 
 
+/**
+ * wpas_dbus_signal_p2p_find_stopped - Send P2P Find stopped signal
+ * @wpa_s: %wpa_supplicant network interface data
+ *
+ * Notify listeners about P2P Find stopped
+ */
+void wpas_dbus_signal_p2p_find_stopped(struct wpa_supplicant *wpa_s)
+{
+	struct wpas_dbus_priv *iface;
+	DBusMessage *msg;
+
+	iface = wpa_s->global->dbus;
+
+	/* Do nothing if the control interface is not turned on */
+	if (iface == NULL || !wpa_s->dbus_new_path)
+		return;
+
+	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
+				      WPAS_DBUS_NEW_IFACE_P2PDEVICE,
+				      "FindStopped");
+	if (msg == NULL)
+		return;
+
+	dbus_connection_send(iface->con, msg, NULL);
+
+	dbus_message_unref(msg);
+}
+
+
 void wpas_dbus_signal_peer_groups_changed(struct wpa_supplicant *wpa_s,
 					  const u8 *dev_addr)
 {
diff --git a/wpa_supplicant/dbus/dbus_new.h b/wpa_supplicant/dbus/dbus_new.h
index d162d2b..31db8d4 100644
--- a/wpa_supplicant/dbus/dbus_new.h
+++ b/wpa_supplicant/dbus/dbus_new.h
@@ -168,6 +168,7 @@
 void wpas_dbus_signal_debug_show_keys_changed(struct wpa_global *global);
 
 int wpas_dbus_register_peer(struct wpa_supplicant *wpa_s, const u8 *dev_addr);
+void wpas_dbus_signal_p2p_find_stopped(struct wpa_supplicant *wpa_s);
 void wpas_dbus_signal_peer_device_found(struct wpa_supplicant *wpa_s,
 					   const u8 *dev_addr);
 int wpas_dbus_unregister_peer(struct wpa_supplicant *wpa_s,
@@ -460,6 +461,11 @@
 }
 
 static inline void
+wpas_dbus_signal_p2p_find_stopped(struct wpa_supplicant *wpa_s)
+{
+}
+
+static inline void
 wpas_dbus_signal_peer_device_found(struct wpa_supplicant *wpa_s,
 				   const u8 *dev_addr)
 {
diff --git a/wpa_supplicant/dbus/dbus_new_handlers_p2p.c b/wpa_supplicant/dbus/dbus_new_handlers_p2p.c
index 32f0a35..9419ba8 100644
--- a/wpa_supplicant/dbus/dbus_new_handlers_p2p.c
+++ b/wpa_supplicant/dbus/dbus_new_handlers_p2p.c
@@ -127,8 +127,7 @@
 		wpa_dbus_dict_entry_clear(&entry);
 	}
 
-	if (wpa_s->p2p_dev)
-		wpa_s = wpa_s->p2p_dev;
+	wpa_s = wpa_s->global->p2p_init_wpa_s;
 
 	wpas_p2p_find(wpa_s, timeout, type, num_req_dev_types, req_dev_types,
 		      NULL, 0, 0, NULL, 0);
@@ -147,10 +146,7 @@
 DBusMessage * wpas_dbus_handler_p2p_stop_find(DBusMessage *message,
 					      struct wpa_supplicant *wpa_s)
 {
-	if (wpa_s->p2p_dev)
-		wpa_s = wpa_s->p2p_dev;
-
-	wpas_p2p_stop_find(wpa_s);
+	wpas_p2p_stop_find(wpa_s->global->p2p_init_wpa_s);
 	return NULL;
 }
 
@@ -168,8 +164,7 @@
 	if (parse_peer_object_path(peer_object_path, peer_addr) < 0)
 		return wpas_dbus_error_invalid_args(message, NULL);
 
-	if (wpa_s->p2p_dev)
-		wpa_s = wpa_s->p2p_dev;
+	wpa_s = wpa_s->global->p2p_init_wpa_s;
 
 	if (wpas_p2p_reject(wpa_s, peer_addr) < 0)
 		return wpas_dbus_error_unknown_error(message,
@@ -188,8 +183,7 @@
 				   DBUS_TYPE_INVALID))
 		return wpas_dbus_error_no_memory(message);
 
-	if (wpa_s->p2p_dev)
-		wpa_s = wpa_s->p2p_dev;
+	wpa_s = wpa_s->global->p2p_init_wpa_s;
 
 	if (wpas_p2p_listen(wpa_s, (unsigned int) timeout)) {
 		return dbus_message_new_error(message,
@@ -230,8 +224,7 @@
 		wpa_dbus_dict_entry_clear(&entry);
 	}
 
-	if (wpa_s->p2p_dev)
-		wpa_s = wpa_s->p2p_dev;
+	wpa_s = wpa_s->global->p2p_init_wpa_s;
 
 	if (wpas_p2p_ext_listen(wpa_s, period, interval))
 		return wpas_dbus_error_unknown_error(
@@ -282,9 +275,6 @@
 		wpa_dbus_dict_entry_clear(&entry);
 	}
 
-	if (wpa_s->p2p_dev)
-		wpa_s = wpa_s->p2p_dev;
-
 	if (wpas_p2p_presence_req(wpa_s, dur1, int1, dur2, int2) < 0)
 		return wpas_dbus_error_unknown_error(message,
 				"Failed to invoke presence request.");
@@ -339,8 +329,7 @@
 		wpa_dbus_dict_entry_clear(&entry);
 	}
 
-	if (wpa_s->p2p_dev)
-		wpa_s = wpa_s->p2p_dev;
+	wpa_s = wpa_s->global->p2p_init_wpa_s;
 
 	if (pg_object_path != NULL) {
 		char *net_id_str;
@@ -435,8 +424,7 @@
 	if (!wpa_dbus_p2p_check_enabled(wpa_s, message, &reply, NULL))
 		return reply;
 
-	if (wpa_s->p2p_dev)
-		wpa_s = wpa_s->p2p_dev;
+	wpa_s = wpa_s->global->p2p_init_wpa_s;
 
 	os_memset(wpa_s->p2p_auth_invite, 0, ETH_ALEN);
 	wpa_s->force_long_sd = 0;
@@ -532,8 +520,7 @@
 	if ((!pin || !pin[0]) && wps_method == WPS_PIN_KEYPAD)
 		goto inv_args;
 
-	if (wpa_s->p2p_dev)
-		wpa_s = wpa_s->p2p_dev;
+	wpa_s = wpa_s->global->p2p_init_wpa_s;
 
 	new_pin = wpas_p2p_connect(wpa_s, addr, pin, wps_method,
 				   persistent_group, 0, join, authorize_only,
@@ -635,8 +622,7 @@
 	    !p2p_peer_known(wpa_s->global->p2p, peer_addr))
 		goto err;
 
-	if (wpa_s->p2p_dev)
-		wpa_s = wpa_s->p2p_dev;
+	wpa_s = wpa_s->global->p2p_init_wpa_s;
 
 	if (persistent) {
 		char *net_id_str;
@@ -728,8 +714,7 @@
 	    os_strcmp(config_method, "pushbutton"))
 		return wpas_dbus_error_invalid_args(message, NULL);
 
-	if (wpa_s->p2p_dev)
-		wpa_s = wpa_s->p2p_dev;
+	wpa_s = wpa_s->global->p2p_init_wpa_s;
 
 	if (wpas_p2p_prov_disc(wpa_s, peer_addr, config_method,
 			       WPAS_P2P_PD_FOR_GO_NEG, NULL) < 0)
@@ -760,8 +745,7 @@
 	if (!wpa_dbus_p2p_check_enabled(wpa_s, NULL, NULL, error))
 		return FALSE;
 
-	if (wpa_s->p2p_dev)
-		wpa_s = wpa_s->p2p_dev;
+	wpa_s = wpa_s->global->p2p_init_wpa_s;
 
 	if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
 					      "a{sv}", &variant_iter) ||
@@ -866,8 +850,7 @@
 	if (!wpa_dbus_p2p_check_enabled(wpa_s, NULL, NULL, error))
 		return FALSE;
 
-	if (wpa_s->p2p_dev)
-		wpa_s = wpa_s->p2p_dev;
+	wpa_s = wpa_s->global->p2p_init_wpa_s;
 
 	dbus_message_iter_recurse(iter, &variant_iter);
 	if (!wpa_dbus_dict_open_read(&variant_iter, &iter_dict, error))
@@ -1586,8 +1569,7 @@
 	os_memset(&data, 0, sizeof(data));
 
 	wpa_s = peer_args->wpa_s;
-	if (wpa_s->p2p_dev)
-		wpa_s = wpa_s->p2p_dev;
+	wpa_s = wpa_s->global->p2p_init_wpa_s;
 
 	wpa_s_go = wpas_get_p2p_client_iface(wpa_s, info->p2p_device_addr);
 	if (wpa_s_go) {
@@ -1644,8 +1626,7 @@
 	unsigned int i = 0, num = 0;
 	dbus_bool_t success = FALSE;
 
-	if (wpa_s->p2p_dev)
-		wpa_s = wpa_s->p2p_dev;
+	wpa_s = wpa_s->global->p2p_init_wpa_s;
 	if (!wpa_s->parent->dbus_new_path)
 		return FALSE;
 
@@ -1759,8 +1740,7 @@
 
 	dbus_message_iter_init(message, &iter);
 
-	if (wpa_s->p2p_dev)
-		wpa_s = wpa_s->p2p_dev;
+	wpa_s = wpa_s->global->p2p_init_wpa_s;
 	if (wpa_s->parent->dbus_new_path)
 		ssid = wpa_config_add_network(wpa_s->conf);
 	if (ssid == NULL) {
@@ -1842,8 +1822,7 @@
 	dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &op,
 			      DBUS_TYPE_INVALID);
 
-	if (wpa_s->p2p_dev)
-		wpa_s = wpa_s->p2p_dev;
+	wpa_s = wpa_s->global->p2p_init_wpa_s;
 
 	/*
 	 * Extract the network ID and ensure the network is actually a child of
@@ -1919,8 +1898,8 @@
 	struct wpa_ssid *ssid, *next;
 	struct wpa_config *config;
 
-	if (wpa_s->p2p_dev)
-		wpa_s = wpa_s->p2p_dev;
+	wpa_s = wpa_s->global->p2p_init_wpa_s;
+
 	config = wpa_s->conf;
 	ssid = config->ssid;
 	while (ssid) {
diff --git a/wpa_supplicant/notify.c b/wpa_supplicant/notify.c
index 184a95c..4df9d90 100644
--- a/wpa_supplicant/notify.c
+++ b/wpa_supplicant/notify.c
@@ -520,6 +520,13 @@
 
 #ifdef CONFIG_P2P
 
+void wpas_notify_p2p_find_stopped(struct wpa_supplicant *wpa_s)
+{
+	/* Notify P2P find has stopped */
+	wpas_dbus_signal_p2p_find_stopped(wpa_s);
+}
+
+
 void wpas_notify_p2p_device_found(struct wpa_supplicant *wpa_s,
 				  const u8 *dev_addr, int new_device)
 {
diff --git a/wpa_supplicant/notify.h b/wpa_supplicant/notify.h
index b268332..1025ca8 100644
--- a/wpa_supplicant/notify.h
+++ b/wpa_supplicant/notify.h
@@ -84,6 +84,7 @@
 void wpas_notify_sta_authorized(struct wpa_supplicant *wpa_s,
 				const u8 *mac_addr, int authorized,
 				const u8 *p2p_dev_addr);
+void wpas_notify_p2p_find_stopped(struct wpa_supplicant *wpa_s);
 void wpas_notify_p2p_device_found(struct wpa_supplicant *wpa_s,
 				  const u8 *dev_addr, int new_device);
 void wpas_notify_p2p_device_lost(struct wpa_supplicant *wpa_s,
diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c
index def959f..23ab10d 100644
--- a/wpa_supplicant/p2p_supplicant.c
+++ b/wpa_supplicant/p2p_supplicant.c
@@ -191,7 +191,11 @@
 {
 	if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
 		return;
-	if (wpa_s->parent->conf->p2p_ignore_shared_freq &&
+
+	/* Use the wpa_s used to control the P2P Device operation */
+	wpa_s = wpa_s->global->p2p_init_wpa_s;
+
+	if (wpa_s->conf->p2p_ignore_shared_freq &&
 	    freq > 0 && wpa_s->num_multichan_concurrent > 1 &&
 	    wpas_p2p_num_unused_channels(wpa_s) > 0) {
 		wpa_printf(MSG_DEBUG, "P2P: Ignore own channel preference %d MHz due to p2p_ignore_shared_freq=1 configuration",
@@ -1109,13 +1113,14 @@
 	u8 *n;
 	size_t i;
 	int found = 0;
+	struct wpa_supplicant *p2p_wpa_s = wpa_s->global->p2p_init_wpa_s;
 
 	ssid = wpa_s->current_ssid;
 	if (ssid == NULL || ssid->mode != WPAS_MODE_P2P_GO ||
 	    !ssid->p2p_persistent_group)
 		return;
 
-	for (s = wpa_s->parent->conf->ssid; s; s = s->next) {
+	for (s = p2p_wpa_s->conf->ssid; s; s = s->next) {
 		if (s->disabled != 2 || s->mode != WPAS_MODE_P2P_GO)
 			continue;
 
@@ -1174,8 +1179,8 @@
 			  0xff, ETH_ALEN);
 	}
 
-	if (wpa_s->parent->conf->update_config &&
-	    wpa_config_write(wpa_s->parent->confname, wpa_s->parent->conf))
+	if (p2p_wpa_s->conf->update_config &&
+	    wpa_config_write(p2p_wpa_s->confname, p2p_wpa_s->conf))
 		wpa_printf(MSG_DEBUG, "P2P: Failed to update configuration");
 }
 
@@ -2248,6 +2253,7 @@
 {
 	struct wpa_supplicant *wpa_s = ctx;
 	wpa_msg_global(wpa_s, MSG_INFO, P2P_EVENT_FIND_STOPPED);
+	wpas_notify_p2p_find_stopped(wpa_s);
 }
 
 
@@ -2825,6 +2831,7 @@
 					const u8 *peer, int inv)
 {
 	size_t i;
+	struct wpa_supplicant *p2p_wpa_s = wpa_s->global->p2p_init_wpa_s;
 
 	if (ssid == NULL)
 		return;
@@ -2854,8 +2861,8 @@
 		   ssid->p2p_client_list + (i + 1) * 2 * ETH_ALEN,
 		   (ssid->num_p2p_clients - i - 1) * 2 * ETH_ALEN);
 	ssid->num_p2p_clients--;
-	if (wpa_s->parent->conf->update_config &&
-	    wpa_config_write(wpa_s->parent->confname, wpa_s->parent->conf))
+	if (p2p_wpa_s->conf->update_config &&
+	    wpa_config_write(p2p_wpa_s->confname, p2p_wpa_s->conf))
 		wpa_printf(MSG_DEBUG, "P2P: Failed to update configuration");
 }
 
@@ -3453,7 +3460,6 @@
 		wpa_printf(MSG_DEBUG, "P2P: Failed to add P2P Device interface");
 		return -1;
 	}
-	wpa_s->p2p_dev = p2pdev_wpa_s;
 
 	wpa_s->pending_interface_name[0] = '\0';
 	return 0;
@@ -5950,7 +5956,11 @@
 
 	if (wpa_s->global->p2p_disabled)
 		return -1;
-	if (wpa_s->conf->p2p_disabled)
+	/*
+	 * Advertize mandatory cross connection capability even on
+	 * p2p_disabled=1 interface when associating with a P2P Manager WLAN AP.
+	 */
+	if (wpa_s->conf->p2p_disabled && p2p_group)
 		return -1;
 	if (wpa_s->global->p2p == NULL)
 		return -1;
@@ -7304,16 +7314,17 @@
 {
 	struct wpa_ssid *s;
 	struct wpa_supplicant *w;
+	struct wpa_supplicant *p2p_wpa_s = wpa_s->global->p2p_init_wpa_s;
 
 	wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Remove client " MACSTR, MAC2STR(peer));
 
 	/* Remove from any persistent group */
-	for (s = wpa_s->parent->conf->ssid; s; s = s->next) {
+	for (s = p2p_wpa_s->conf->ssid; s; s = s->next) {
 		if (s->disabled != 2 || s->mode != WPAS_MODE_P2P_GO)
 			continue;
 		if (!iface_addr)
-			wpas_remove_persistent_peer(wpa_s, s, peer, 0);
-		wpas_p2p_remove_psk(wpa_s->parent, s, peer, iface_addr);
+			wpas_remove_persistent_peer(p2p_wpa_s, s, peer, 0);
+		wpas_p2p_remove_psk(p2p_wpa_s, s, peer, iface_addr);
 	}
 
 	/* Remove from any operating group */
diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index 06a1696..874eb48 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -3086,6 +3086,7 @@
 			timeout = 70;
 		}
 
+#ifdef CONFIG_WPS
 		if (wpa_s->current_ssid && wpa_s->current_bss &&
 		    (wpa_s->current_ssid->key_mgmt & WPA_KEY_MGMT_WPS) &&
 		    eap_is_wps_pin_enrollee(&wpa_s->current_ssid->eap)) {
@@ -3103,6 +3104,7 @@
 				timeout = 10;
 			wpabuf_free(wps_ie);
 		}
+#endif /* CONFIG_WPS */
 
 		wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
 	}
diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h
index 364ba19..ffda53d 100644
--- a/wpa_supplicant/wpa_supplicant_i.h
+++ b/wpa_supplicant/wpa_supplicant_i.h
@@ -738,7 +738,6 @@
 	int p2p_mgmt;
 
 #ifdef CONFIG_P2P
-	struct wpa_supplicant *p2p_dev;
 	struct p2p_go_neg_results *go_params;
 	int create_p2p_iface;
 	u8 pending_interface_addr[ETH_ALEN];