diff mbox series

[v2,01/14] PASN: Support PASN with SAE key derivation

Message ID 20201216110105.8380-2-ilan.peer@intel.com
State Accepted
Headers show
Series Support PASN with SAE, FILS and FT | expand

Commit Message

Peer, Ilan Dec. 16, 2020, 11 a.m. UTC
Signed-off-by: Ilan Peer <ilan.peer@intel.com>
---
 src/rsn_supp/wpa.c                |  11 ++
 src/rsn_supp/wpa.h                |   2 +
 wpa_supplicant/ctrl_iface.c       |   6 +-
 wpa_supplicant/pasn_supplicant.c  | 242 +++++++++++++++++++++++++++++-
 wpa_supplicant/wpa_cli.c          |   2 +-
 wpa_supplicant/wpa_supplicant_i.h |   9 +-
 6 files changed, 261 insertions(+), 11 deletions(-)

Comments

Jouni Malinen Jan. 21, 2021, 1:40 p.m. UTC | #1
On Wed, Dec 16, 2020 at 01:00:52PM +0200, Ilan Peer wrote:
> diff --git a/wpa_supplicant/pasn_supplicant.c b/wpa_supplicant/pasn_supplicant.c
> +static struct wpabuf *wpas_pasn_wd_sae_commit(struct wpa_supplicant *wpa_s)

> +	ret = sae_prepare_commit(wpa_s->own_addr, pasn->bssid,
> +				 (u8 *)password,
> +				 os_strlen(password), 0,
> +				 &pasn->sae);

> +	wpabuf_put_le16(buf, WLAN_AUTH_SAE);
> +	wpabuf_put_le16(buf, 1);
> +	wpabuf_put_le16(buf, WLAN_STATUS_SUCCESS);

This seems to be hardcoded to support SAE only with the old
hunting-and-pecking mechanism and not allow H2E to be used.. I'd hope
that all new use cases for SAE would use H2E from the beginning. Is
there any particular reason for this implementation or need for PASN to
work with the old design for deriving pwe?
Peer, Ilan Jan. 21, 2021, 1:57 p.m. UTC | #2
Hi,

> -----Original Message-----
> From: Jouni Malinen <j@w1.fi>
> Sent: Thursday, January 21, 2021 15:41
> To: Peer, Ilan <ilan.peer@intel.com>
> Cc: hostap@lists.infradead.org
> Subject: Re: [PATCH v2 01/14] PASN: Support PASN with SAE key derivation
> 
> On Wed, Dec 16, 2020 at 01:00:52PM +0200, Ilan Peer wrote:
> > diff --git a/wpa_supplicant/pasn_supplicant.c
> > b/wpa_supplicant/pasn_supplicant.c
> > +static struct wpabuf *wpas_pasn_wd_sae_commit(struct wpa_supplicant
> > +*wpa_s)
> 
> > +	ret = sae_prepare_commit(wpa_s->own_addr, pasn->bssid,
> > +				 (u8 *)password,
> > +				 os_strlen(password), 0,
> > +				 &pasn->sae);
> 
> > +	wpabuf_put_le16(buf, WLAN_AUTH_SAE);
> > +	wpabuf_put_le16(buf, 1);
> > +	wpabuf_put_le16(buf, WLAN_STATUS_SUCCESS);
> 
> This seems to be hardcoded to support SAE only with the old hunting-and-
> pecking mechanism and not allow H2E to be used.. I'd hope that all new use
> cases for SAE would use H2E from the beginning. Is there any particular
> reason for this implementation or need for PASN to work with the old design
> for deriving pwe?

No. The main reason is that the original implementation was done before H2E was introduced.
I never got to the point that I modified the implementation to use H2E when possible.

Regards,

Ilan.
diff mbox series

Patch

diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c
index 2ae7eae37b..a18a8fa7f9 100644
--- a/src/rsn_supp/wpa.c
+++ b/src/rsn_supp/wpa.c
@@ -5194,3 +5194,14 @@  void wpa_sm_set_dpp_z(struct wpa_sm *sm, const struct wpabuf *z)
 	}
 }
 #endif /* CONFIG_DPP2 */
+
+
+#ifdef CONFIG_PASN
+void wpa_pasn_pmksa_cache_add(struct wpa_sm *sm, const u8 *pmk, size_t pmk_len,
+			      const u8 *pmkid, const u8 *bssid, int key_mgmt)
+{
+	sm->cur_pmksa = pmksa_cache_add(sm->pmksa, pmk, pmk_len, pmkid, NULL, 0,
+					bssid, sm->own_addr, NULL,
+					key_mgmt, 0);
+}
+#endif /* CONFIG_PASN */
diff --git a/src/rsn_supp/wpa.h b/src/rsn_supp/wpa.h
index a2a230d820..cb268648a7 100644
--- a/src/rsn_supp/wpa.h
+++ b/src/rsn_supp/wpa.h
@@ -523,5 +523,7 @@  int owe_process_assoc_resp(struct wpa_sm *sm, const u8 *bssid,
 void wpa_sm_set_reset_fils_completed(struct wpa_sm *sm, int set);
 void wpa_sm_set_fils_cache_id(struct wpa_sm *sm, const u8 *fils_cache_id);
 void wpa_sm_set_dpp_z(struct wpa_sm *sm, const struct wpabuf *z);
+void wpa_pasn_pmksa_cache_add(struct wpa_sm *sm, const u8 *pmk, size_t pmk_len,
+			      const u8 *pmkid, const u8 *bssid, int key_mgmt);
 
 #endif /* WPA_H */
diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c
index e2c1437ee0..fe167f13ac 100644
--- a/wpa_supplicant/ctrl_iface.c
+++ b/wpa_supplicant/ctrl_iface.c
@@ -10464,6 +10464,7 @@  static int wpas_ctrl_iface_pasn_start(struct wpa_supplicant *wpa_s, char *cmd)
 	u8 bssid[ETH_ALEN];
 	int akmp = -1, cipher = -1, got_bssid = 0;
 	u16 group = 0xFFFF;
+	int id = 0;
 
 	/*
 	 * Entry format: bssid=<BSSID> akmp=<AKMP> cipher=<CIPHER> group=<group>
@@ -10503,6 +10504,8 @@  static int wpas_ctrl_iface_pasn_start(struct wpa_supplicant *wpa_s, char *cmd)
 			cipher = WPA_CIPHER_GCMP;
 		} else if (os_strncmp(token, "group=", 6) == 0) {
 			group = atoi(token + 6);
+		} else if (os_strncmp(token, "nid=", 4) == 0) {
+			id = atoi(token + 4);
 		} else {
 			wpa_printf(MSG_DEBUG,
 				   "CTRL: PASN Invalid parameter: '%s'",
@@ -10516,7 +10519,8 @@  static int wpas_ctrl_iface_pasn_start(struct wpa_supplicant *wpa_s, char *cmd)
 		return -1;
 	}
 
-	return wpas_pasn_auth_start(wpa_s, bssid, akmp, cipher, group);
+	return wpas_pasn_auth_start(wpa_s, bssid, akmp, cipher, group,
+				    id);
 }
 #endif /* CONFIG_PASN */
 
diff --git a/wpa_supplicant/pasn_supplicant.c b/wpa_supplicant/pasn_supplicant.c
index 652fee0c7f..971d43e115 100644
--- a/wpa_supplicant/pasn_supplicant.c
+++ b/wpa_supplicant/pasn_supplicant.c
@@ -21,6 +21,7 @@ 
 #include "driver_i.h"
 #include "bss.h"
 #include "common/ptksa_cache.h"
+#include "config.h"
 
 static const int dot11RSNAConfigPMKLifetime = 43200;
 
@@ -29,6 +30,7 @@  struct wpa_pasn_auth_work {
 	int akmp;
 	int cipher;
 	u16 group;
+	int network_id;
 };
 
 
@@ -61,14 +63,202 @@  static void wpas_pasn_auth_status(struct wpa_supplicant *wpa_s, const u8 *bssid,
 		status);
 }
 
+#ifdef CONFIG_SAE
+
+static struct wpabuf *wpas_pasn_wd_sae_commit(struct wpa_supplicant *wpa_s)
+{
+	struct wpas_pasn *pasn = &wpa_s->pasn;
+	struct wpabuf *buf = NULL;
+	const char *password = NULL;
+	int ret;
+
+	if (pasn->ssid) {
+		password = pasn->ssid->sae_password;
+		if (!password)
+			password = pasn->ssid->passphrase;
+	}
+
+	if (!password) {
+		wpa_printf(MSG_DEBUG, "PASN: SAE without a password");
+		return NULL;
+	}
+
+	ret = sae_set_group(&pasn->sae, pasn->group);
+	if (ret) {
+		wpa_printf(MSG_DEBUG, "PASN: Failed to set SAE group");
+		return NULL;
+	}
 
-static struct wpabuf *wpas_pasn_get_wrapped_data(struct wpas_pasn *pasn)
+	ret = sae_prepare_commit(wpa_s->own_addr, pasn->bssid,
+				 (u8 *)password,
+				 os_strlen(password), 0,
+				 &pasn->sae);
+	if (ret) {
+		wpa_printf(MSG_DEBUG, "PASN: Failed to prepare SAE commit");
+		return NULL;
+	}
+
+	/* Need to add the entire authentication frame body */
+	buf = wpabuf_alloc(6 + SAE_COMMIT_MAX_LEN);
+	if (!buf) {
+		wpa_printf(MSG_DEBUG, "PASN: Failed to allocate SAE buffer");
+		return NULL;
+	}
+
+	wpabuf_put_le16(buf, WLAN_AUTH_SAE);
+	wpabuf_put_le16(buf, 1);
+	wpabuf_put_le16(buf, WLAN_STATUS_SUCCESS);
+
+	sae_write_commit(&pasn->sae, buf, NULL, 0);
+	pasn->sae.state = SAE_COMMITTED;
+
+	return buf;
+}
+
+
+static int wpas_pasn_wd_sae_rx(struct wpa_supplicant *wpa_s,
+			       struct wpabuf *wd)
 {
+	struct wpas_pasn *pasn = &wpa_s->pasn;
+	const u8 *data;
+	size_t buf_len;
+	u16 len, res, alg, seq, status;
+	int groups[] = { pasn->group, 0 };
+	int ret;
+
+	if (!wd)
+		return -1;
+
+	data = wpabuf_head_u8(wd);
+	buf_len = wpabuf_len(wd);
+
+	/* first handle the commit message */
+	if (buf_len < 2) {
+		wpa_printf(MSG_DEBUG, "PASN: SAE buffer too short (commit)");
+		return -1;
+	}
+
+	len = WPA_GET_LE16(data);
+	if (len < 6 || buf_len - 2 < len) {
+		wpa_printf(MSG_DEBUG, "PASN: SAE buffer too short for commit");
+		return -1;
+	}
+
+	buf_len -= 2;
+	data += 2;
+
+	alg = WPA_GET_LE16(data);
+	seq = WPA_GET_LE16(data + 2);
+	status = WPA_GET_LE16(data + 4);
+
+	wpa_printf(MSG_DEBUG, "PASN: SAE: commit: alg=%u, seq=%u, status=%u",
+		   alg, seq, status);
+
+	if (alg != WLAN_AUTH_SAE || seq != 1 || status != WLAN_STATUS_SUCCESS) {
+		wpa_printf(MSG_DEBUG, "PASN: SAE: dropping peer commit");
+		return -1;
+	}
+
+	res = sae_parse_commit(&pasn->sae, data + 6, len - 6, NULL, 0, groups,
+			       0);
+	if (res != WLAN_STATUS_SUCCESS) {
+		wpa_printf(MSG_DEBUG, "PASN: SAE failed parsing commit");
+		return -1;
+	}
+
+	/* process the commit message and derive the PMK */
+	ret = sae_process_commit(&pasn->sae);
+	if (ret) {
+		wpa_printf(MSG_DEBUG, "SAE: Failed to process peer commit");
+		return -1;
+	}
+
+	buf_len -= len;
+	data += len;
+
+	/* Handle the confirm message */
+	if (buf_len < 2) {
+		wpa_printf(MSG_DEBUG, "PASN: SAE buffer too short (confirm)");
+		return -1;
+	}
+
+	len = WPA_GET_LE16(data);
+	if (len < 6 || buf_len - 2 < len) {
+		wpa_printf(MSG_DEBUG, "PASN: SAE buffer too short for confirm");
+		return -1;
+	}
+
+	buf_len -= 2;
+	data += 2;
+
+	alg = WPA_GET_LE16(data);
+	seq = WPA_GET_LE16(data + 2);
+	status = WPA_GET_LE16(data + 4);
+
+	wpa_printf(MSG_DEBUG, "PASN: SAE: confirm: alg=%u, seq=%u, status=%u",
+		   alg, seq, status);
+
+	if (alg != WLAN_AUTH_SAE || seq != 2 || status != WLAN_STATUS_SUCCESS) {
+		wpa_printf(MSG_DEBUG, "PASN: SAE: dropping peer confirm");
+		return -1;
+	}
+
+	res = sae_check_confirm(&pasn->sae, data + 6, len - 6);
+	if (res != WLAN_STATUS_SUCCESS) {
+		wpa_printf(MSG_DEBUG, "PASN: SAE failed checking confirm");
+		return -1;
+	}
+
+	wpa_printf(MSG_DEBUG, "PASN: SAE completed successfully");
+	pasn->sae.state = SAE_ACCEPTED;
+
+	return 0;
+}
+
+
+static struct wpabuf *wpas_pasn_wd_sae_confirm(struct wpa_supplicant *wpa_s)
+{
+	struct wpas_pasn *pasn = &wpa_s->pasn;
+	struct wpabuf *buf = NULL;
+
+	/* Need to add the entire authentication frame body */
+	buf = wpabuf_alloc(6 + SAE_CONFIRM_MAX_LEN);
+	if (!buf) {
+		wpa_printf(MSG_DEBUG, "PASN: Failed to allocate SAE buffer");
+		return NULL;
+	}
+
+	wpabuf_put_le16(buf, WLAN_AUTH_SAE);
+	wpabuf_put_le16(buf, 2);
+	wpabuf_put_le16(buf, WLAN_STATUS_SUCCESS);
+
+	sae_write_confirm(&pasn->sae, buf);
+	pasn->sae.state = SAE_CONFIRMED;
+
+	return buf;
+}
+
+#endif /* CONFIG_SAE */
+
+static struct wpabuf *wpas_pasn_get_wrapped_data(struct wpa_supplicant *wpa_s)
+{
+	struct wpas_pasn *pasn = &wpa_s->pasn;
+
+	if (pasn->using_pmksa)
+		return NULL;
+
 	switch (pasn->akmp) {
 	case WPA_KEY_MGMT_PASN:
 		/* no wrapped data */
 		return NULL;
 	case WPA_KEY_MGMT_SAE:
+#ifdef CONFIG_SAE
+		if (pasn->trans_seq == 0)
+			return wpas_pasn_wd_sae_commit(wpa_s);
+		else if (pasn->trans_seq == 2)
+			return wpas_pasn_wd_sae_confirm(wpa_s);
+#endif /* CONFIG_SAE */
+		/* fall through */
 	case WPA_KEY_MGMT_FILS_SHA256:
 	case WPA_KEY_MGMT_FILS_SHA384:
 	case WPA_KEY_MGMT_FT_PSK:
@@ -85,6 +275,9 @@  static struct wpabuf *wpas_pasn_get_wrapped_data(struct wpas_pasn *pasn)
 
 static u8 wpas_pasn_get_wrapped_data_format(struct wpas_pasn *pasn)
 {
+	if (pasn->using_pmksa)
+		return WPA_PASN_NO_WRAPPED_DATA;
+
 	/* Note: valid AKMP is expected to already be validated */
 	switch (pasn->akmp) {
 	case WPA_KEY_MGMT_SAE:
@@ -144,7 +337,7 @@  static struct wpabuf *wpas_pasn_build_auth_1(struct wpa_supplicant *wpa_s)
 		 * Note: even when PMKSA is available, also add wrapped data as
 		 * it is possible that the PMKID is no longer valid at the AP.
 		 */
-		wrapped_data_buf = wpas_pasn_get_wrapped_data(pasn);
+		wrapped_data_buf = wpas_pasn_get_wrapped_data(wpa_s);
 	} else {
 		pmksa = NULL;
 	}
@@ -152,7 +345,6 @@  static struct wpabuf *wpas_pasn_build_auth_1(struct wpa_supplicant *wpa_s)
 	wpa_pasn_add_rsne(buf, pmksa ? pmksa->pmkid : NULL,
 			  pasn->akmp, pasn->cipher);
 
-
 	if (!wrapped_data_buf)
 		wrapped_data = WPA_PASN_NO_WRAPPED_DATA;
 
@@ -212,7 +404,7 @@  static struct wpabuf *wpas_pasn_build_auth_3(struct wpa_supplicant *wpa_s)
 				   wpa_s->own_addr, pasn->bssid,
 				   pasn->trans_seq + 1, WLAN_STATUS_SUCCESS);
 
-	wrapped_data_buf = wpas_pasn_get_wrapped_data(pasn);
+	wrapped_data_buf = wpas_pasn_get_wrapped_data(wpa_s);
 
 	if (!wrapped_data_buf)
 		wrapped_data = WPA_PASN_NO_WRAPPED_DATA;
@@ -276,6 +468,7 @@  static void wpas_pasn_reset(struct wpa_supplicant *wpa_s)
 	pasn->group = 0;
 	pasn->trans_seq = 0;
 	pasn->pmk_len = 0;
+	pasn->using_pmksa = 0;
 
 	os_memset(pasn->pmk, 0, sizeof(pasn->pmk));
 	os_memset(&pasn->ptk, 0, sizeof(pasn->ptk));
@@ -284,6 +477,9 @@  static void wpas_pasn_reset(struct wpa_supplicant *wpa_s)
 	wpabuf_free(pasn->beacon_rsne);
 	pasn->beacon_rsne = NULL;
 
+#ifdef CONFIG_SAE
+	sae_clear_data(&pasn->sae);
+#endif /* CONFIG_SAE */
 	pasn->status = WLAN_STATUS_UNSPECIFIED_FAILURE;
 }
 
@@ -295,6 +491,7 @@  static int wpas_pasn_set_pmk(struct wpa_supplicant *wpa_s,
 {
 	static const u8 pasn_default_pmk[] = {'P', 'M', 'K', 'z'};
 	struct wpas_pasn *pasn = &wpa_s->pasn;
+	int ret;
 
 	os_memset(pasn->pmk, 0, sizeof(pasn->pmk));
 	pasn->pmk_len = 0;
@@ -318,11 +515,32 @@  static int wpas_pasn_set_pmk(struct wpa_supplicant *wpa_s,
 
 			pasn->pmk_len = pmksa->pmk_len;
 			os_memcpy(pasn->pmk, pmksa->pmk, pmksa->pmk_len);
-
+			pasn->using_pmksa = 1;
 			return 0;
 		}
 	}
 
+#ifdef CONFIG_SAE
+	if (pasn->akmp == WPA_KEY_MGMT_SAE) {
+		ret = wpas_pasn_wd_sae_rx(wpa_s, wrapped_data);
+		if (ret) {
+			wpa_printf(MSG_DEBUG,
+				   "PASN: failed processing SAE wrapped data");
+			pasn->status = WLAN_STATUS_UNSPECIFIED_FAILURE;
+			return -1;
+		}
+
+		wpa_printf(MSG_DEBUG, "PASN: success deriving PMK with SAE");
+		pasn->pmk_len = PMK_LEN;
+		os_memcpy(pasn->pmk, pasn->sae.pmk, PMK_LEN);
+
+		wpa_pasn_pmksa_cache_add(wpa_s->wpa, pasn->pmk,
+					 pasn->pmk_len, pasn->sae.pmkid,
+					 pasn->bssid, pasn->akmp);
+		return 0;
+	}
+#endif /* CONFIG_SAE */
+
 	/* TODO: derive PMK based on wrapped data */
 	wpa_printf(MSG_DEBUG, "PASN: missing implementation to derive PMK");
 	pasn->status = WLAN_STATUS_UNSPECIFIED_FAILURE;
@@ -332,9 +550,11 @@  static int wpas_pasn_set_pmk(struct wpa_supplicant *wpa_s,
 
 static int wpas_pasn_start(struct wpa_supplicant *wpa_s, const u8 *bssid,
 			   int akmp, int cipher, u16 group, int freq,
-			   const u8 *beacon_rsne, u8 beacon_rsne_len)
+			   const u8 *beacon_rsne, u8 beacon_rsne_len,
+			   int network_id)
 {
 	struct wpas_pasn *pasn = &wpa_s->pasn;
+	struct wpa_ssid *ssid;
 	struct wpabuf *frame;
 	int ret;
 
@@ -345,11 +565,16 @@  static int wpas_pasn_start(struct wpa_supplicant *wpa_s, const u8 *bssid,
 		return -1;
 	}
 
+	ssid = wpa_config_get_network(wpa_s->conf, network_id);
+
 	switch (akmp) {
 	case WPA_KEY_MGMT_PASN:
 		break;
 #ifdef CONFIG_SAE
 	case WPA_KEY_MGMT_SAE:
+		pasn->sae.state = SAE_NOTHING;
+		pasn->sae.send_confirm = 0;
+		pasn->ssid = ssid;
 		break;
 #endif /* CONFIG_SAE */
 #ifdef CONFIG_FILS
@@ -503,7 +728,7 @@  static void wpas_pasn_auth_start_cb(struct wpa_radio_work *work, int deinit)
 
 	ret = wpas_pasn_start(wpa_s, awork->bssid, awork->akmp, awork->cipher,
 			      awork->group, bss->freq,
-			      rsne, *(rsne + 1) + 2);
+			      rsne, *(rsne + 1) + 2, awork->network_id);
 	if (ret) {
 		wpa_printf(MSG_DEBUG,
 			   "PASN: Failed to start PASN authentication");
@@ -521,7 +746,7 @@  fail:
 
 int wpas_pasn_auth_start(struct wpa_supplicant *wpa_s,
 			 const u8 *bssid, int akmp, int cipher,
-			 u16 group)
+			 u16 group, int network_id)
 {
 	struct wpa_pasn_auth_work *awork;
 	struct wpa_bss *bss;
@@ -566,6 +791,7 @@  int wpas_pasn_auth_start(struct wpa_supplicant *wpa_s,
 	awork->akmp = akmp;
 	awork->cipher = cipher;
 	awork->group = group;
+	awork->network_id = network_id;
 
 	if (radio_add_work(wpa_s, bss->freq, "pasn-start-auth", 1,
 			   wpas_pasn_auth_start_cb, awork) < 0) {
diff --git a/wpa_supplicant/wpa_cli.c b/wpa_supplicant/wpa_cli.c
index 70f2e9f01a..a478a1ff75 100644
--- a/wpa_supplicant/wpa_cli.c
+++ b/wpa_supplicant/wpa_cli.c
@@ -3858,7 +3858,7 @@  static const struct wpa_cli_cmd wpa_cli_commands[] = {
 	{ "pasn_auth_start", wpa_cli_cmd_pasn_auth_start, NULL,
 	  cli_cmd_flag_none,
 	  "bssid=<BSSID> akmp=<WPA key mgmt> cipher=<WPA cipher> group=<group> "
-          "= Start PASN authentication" },
+          "nid=<network id> = Start PASN authentication" },
 	{ "pasn_auth_stop", wpa_cli_cmd_pasn_auth_stop, NULL,
 	  cli_cmd_flag_none,
 	  "= Stop PASN authentication" },
diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h
index 510a6c2c9a..13587f790f 100644
--- a/wpa_supplicant/wpa_supplicant_i.h
+++ b/wpa_supplicant/wpa_supplicant_i.h
@@ -532,12 +532,19 @@  struct wpas_pasn {
 	u8 bssid[ETH_ALEN];
 	u8 pmk_len;
 	u8 pmk[PMK_LEN_MAX];
+	u8 using_pmksa;
 
 	u8 hash[SHA384_MAC_LEN];
 
 	struct wpabuf *beacon_rsne;
 	struct wpa_ptk ptk;
 	struct crypto_ecdh *ecdh;
+
+#ifdef CONFIG_SAE
+	struct sae_data sae;
+#endif /* CONFIG_SAE */
+
+	const struct wpa_ssid *ssid;
 };
 
 #endif /* CONFIG_PASN */
@@ -1679,7 +1686,7 @@  int wpa_is_fils_sk_pfs_supported(struct wpa_supplicant *wpa_s);
 void wpas_clear_driver_signal_override(struct wpa_supplicant *wpa_s);
 int wpas_pasn_auth_start(struct wpa_supplicant *wpa_s,
 			 const u8 *bssid, int akmp, int cipher,
-			 u16 group);
+			 u16 group, int network_id);
 void wpas_pasn_auth_stop(struct wpa_supplicant *wpa_s);
 int wpas_pasn_auth_tx_status(struct wpa_supplicant *wpa_s,
 			     const u8 *data, size_t data_len, u8 acked);