[PATCH v2 11/14] p2p: Add support for Invitation using pairing verification
Shivani Baranwal
quic_shivbara at quicinc.com
Thu Jul 18 21:40:03 PDT 2024
Signed-off-by: Shivani Baranwal <quic_shivbara at quicinc.com>
---
src/p2p/p2p.c | 125 ++++++++++++++++++++-
src/p2p/p2p.h | 18 ++-
src/p2p/p2p_i.h | 16 ++-
src/p2p/p2p_invitation.c | 100 +++++++++++++++--
wpa_supplicant/ctrl_iface.c | 11 +-
wpa_supplicant/dbus/dbus_new_handlers_p2p.c | 8 +-
wpa_supplicant/p2p_supplicant.c | 164 +++++++++++++++++++++++++---
wpa_supplicant/p2p_supplicant.h | 6 +-
8 files changed, 406 insertions(+), 42 deletions(-)
diff --git a/src/p2p/p2p.c b/src/p2p/p2p.c
index 6bcadf4..8a89e29 100644
--- a/src/p2p/p2p.c
+++ b/src/p2p/p2p.c
@@ -3955,7 +3955,7 @@ void p2p_send_action_cb(struct p2p_data *p2p, unsigned int freq, const u8 *dst,
p2p_invitation_req_cb(p2p, success);
break;
case P2P_PENDING_INVITATION_RESPONSE:
- p2p_invitation_resp_cb(p2p, success);
+ p2p_invitation_resp_cb(p2p, dst, success);
break;
case P2P_PENDING_DEV_DISC_REQUEST:
p2p_dev_disc_req_cb(p2p, success);
@@ -4255,7 +4255,7 @@ static void p2p_timeout_invite_listen(struct p2p_data *p2p)
p2p->cfg->invitation_result(
p2p->cfg->cb_ctx, -1, NULL, NULL,
p2p->invite_peer->info.p2p_device_addr,
- 0, 0);
+ 0, 0, NULL, NULL, 0);
}
p2p_set_state(p2p, P2P_IDLE);
}
@@ -6131,8 +6131,117 @@ void p2p_pasn_initialize(struct p2p_data *p2p, struct p2p_device *dev,
pasn->freq = freq;
}
+int get_listen_freq(struct p2p_data *p2p, const u8 *peer_addr)
+{
+ int freq;
+ struct p2p_device *dev;
+
+ if (!peer_addr) {
+ p2p_dbg(p2p, "peer address NULL");
+ return -1;
+ }
+
+ dev = p2p_get_device(p2p, peer_addr);
+ if (!dev) {
+ p2p_dbg(p2p, "Peer not known");
+ return -1;
+ }
+
+ freq = dev->listen_freq > 0 ? dev->listen_freq : dev->oper_freq;
+ if (freq <= 0)
+ freq = dev->oob_go_neg_freq;
+ if (freq <= 0) {
+ p2p_dbg(p2p, "No Listen/Operating frequency known for the peer "
+ MACSTR, MAC2STR(dev->info.p2p_device_addr));
+ return -1;
+ }
+ return freq;
+}
+
+int p2p_initiate_pasn_verify(struct p2p_data *p2p, const u8 *peer_addr,
+ int freq, enum p2p_invite_role role,
+ const u8 *bssid, const u8 *ssid, size_t ssid_len,
+ unsigned int force_freq, const u8 *go_dev_addr,
+ unsigned int pref_freq)
+{
+ struct pasn_data *pasn;
+ struct p2p_device *dev;
+ struct wpabuf *extra_ies, *req;
+ int ret = 0;
+
+ if (!peer_addr) {
+ p2p_dbg(p2p, "peer address NULL");
+ return -1;
+ }
+
+ dev = p2p_get_device(p2p, peer_addr);
+ if (!dev) {
+ p2p_dbg(p2p, "Peer not known");
+ return -1;
+ }
+
+ if (p2p_invite(p2p, peer_addr, role, bssid, ssid, ssid_len, force_freq,
+ go_dev_addr, 1, pref_freq, -1, 1)) {
+ p2p_dbg(p2p, "p2p_invite failed");
+ return -1;
+ }
+
+ dev->role = P2P_ROLE_PAIRING_INITIATOR;
+ p2p_pasn_initialize(p2p, dev, peer_addr, freq);
+ pasn = dev->pasn;
+
+ req = p2p_build_invitation_req(p2p, dev, go_dev_addr, -1);
+ if (!req)
+ return -1;
+ p2p_set_state(p2p, P2P_INVITE);
+ p2p->pending_action_state = P2P_PENDING_INVITATION_REQUEST;
+ p2p->invite_peer = dev;
+ dev->invitation_reqs++;
+ extra_ies = wpabuf_alloc(1500);
+ if (!extra_ies) {
+ wpabuf_free(req);
+ p2p_dbg(p2p, "Mem alloc failed for extra ies");
+ return -1;
+ }
+
+ if (p2p_prepare_pasn_extra_ie(p2p, extra_ies, req, true)) {
+ p2p_dbg(p2p, "prepare pasn extra ies failed");
+ ret = -1;
+ goto out;
+ }
+
+ pasn->extra_ies = os_zalloc(wpabuf_len(extra_ies));
+ if (!pasn->extra_ies) {
+ p2p_dbg(p2p, "Mem alloc failed for pasn extra ies");
+ ret = -1;
+ goto out;
+ }
+
+ os_memcpy((u8 *)pasn->extra_ies, wpabuf_head_u8(extra_ies),
+ wpabuf_len(extra_ies));
+ pasn->extra_ies_len = wpabuf_len(extra_ies);
+
+ /* Start PASN Verify */
+ if (wpa_pasn_verify(pasn, pasn->own_addr, pasn->peer_addr, pasn->bssid,
+ pasn->akmp, pasn->cipher, pasn->group, pasn->freq,
+ NULL, 0, NULL, 0, NULL)) {
+ p2p_dbg(p2p, "p2p pasn verify failed");
+ ret = -1;
+ } else {
+ dev->flags |= P2P_DEV_WAIT_INV_REQ_ACK;
+ }
+out:
+ if (pasn->extra_ies) {
+ os_free((u8 *)pasn->extra_ies);
+ pasn->extra_ies = NULL;
+ pasn->extra_ies_len = 0;
+ }
+ wpabuf_free(req);
+ wpabuf_free(extra_ies);
+ return ret;
+}
int p2p_initiate_pasn_auth(struct p2p_data *p2p, const u8 *addr, int freq)
{
@@ -6264,6 +6373,9 @@ int p2p_pasn_handle_action_wrapper(struct p2p_data *p2p,
data_len - 1, freq);
if (!p2p->invitation_resp)
p2p_dbg(p2p, "No Invitation Response found");
+
+ dev->role = P2P_ROLE_PAIRING_RESPONDER;
+ p2p_pasn_initialize(p2p, dev, mgmt->sa, freq);
dev->pasn->action_frame_wrapper = p2p->invitation_resp;
} else if (data && data[0] == P2P_GO_NEG_REQ) {
p2p_process_go_neg_req(p2p, mgmt->sa, data + 1,
@@ -6293,7 +6405,8 @@ int p2p_pasn_handle_action_wrapper(struct p2p_data *p2p,
p2p_handle_go_neg_conf(p2p, mgmt->sa, data + 1,
data_len - 1, true);
} else {
- p2p_invitation_resp_cb(p2p, P2P_SEND_ACTION_SUCCESS);
+ p2p_invitation_resp_cb(p2p, mgmt->sa,
+ P2P_SEND_ACTION_SUCCESS);
}
}
p2p_parse_free(&msg);
@@ -6554,7 +6667,7 @@ done:
}
int p2p_pasn_auth_tx_status(struct p2p_data *p2p, const u8 *data,
- size_t data_len, u8 acked)
+ size_t data_len, u8 acked, bool verify)
{
int ret = 0;
struct p2p_device *dev;
@@ -6587,7 +6700,9 @@ int p2p_pasn_auth_tx_status(struct p2p_data *p2p, const u8 *data,
if (ret != 1)
return ret;
- if (dev == p2p->go_neg_peer)
+ if (verify && dev == p2p->invite_peer)
+ p2p_start_invitation_connect(p2p, dev);
+ else if (dev == p2p->go_neg_peer)
p2p_go_complete(p2p, dev);
return 0;
diff --git a/src/p2p/p2p.h b/src/p2p/p2p.h
index 99668fa..89c99ca 100644
--- a/src/p2p/p2p.h
+++ b/src/p2p/p2p.h
@@ -1088,7 +1088,8 @@ struct p2p_config {
void (*invitation_received)(void *ctx, const u8 *sa, const u8 *bssid,
const u8 *ssid, size_t ssid_len,
const u8 *go_dev_addr, u8 status,
- int op_freq);
+ int op_freq, u8 *pmkid, u8 *pmk,
+ size_t pmk_len);
/**
* invitation_result - Callback on Invitation result
@@ -1109,7 +1110,8 @@ struct p2p_config {
*/
void (*invitation_result)(void *ctx, int status, const u8 *bssid,
const struct p2p_channels *channels,
- const u8 *addr, int freq, int peer_oper_freq);
+ const u8 *addr, int freq, int peer_oper_freq,
+ u8 *pmkid, u8 *pmk, size_t pmk_len);
/**
* go_connected - Check whether we are connected to a GO
@@ -1639,12 +1641,14 @@ enum p2p_invite_role {
* force_freq == 0)
* @dev_pw_id: Device Password ID from OOB Device Password (NFC) static handover
* case or -1 if not used
+ * @p2p2: Operating in p2p2 mode
* Returns: 0 on success, -1 on failure
*/
int p2p_invite(struct p2p_data *p2p, const u8 *peer, enum p2p_invite_role role,
const u8 *bssid, const u8 *ssid, size_t ssid_len,
unsigned int force_freq, const u8 *go_dev_addr,
- int persistent_group, unsigned int pref_freq, int dev_pw_id);
+ int persistent_group, unsigned int pref_freq, int dev_pw_id,
+ bool p2p2);
/**
* p2p_presence_req - Request GO presence
@@ -2620,7 +2624,13 @@ void p2p_set_pasn_type(struct p2p_data *p2p, u8 pasn_type);
void p2p_set_comeback_after(struct p2p_data *p2p, int comeback_after);
void p2p_set_reg_info(struct p2p_data *p2p, u8 val);
+int get_listen_freq(struct p2p_data *p2p, const u8 *peer_addr);
int p2p_initiate_pasn_auth(struct p2p_data *p2p, const u8 *addr, int freq);
+int p2p_initiate_pasn_verify(struct p2p_data *p2p, const u8 *peer_addr,
+ int freq, enum p2p_invite_role role,
+ const u8 *bssid, const u8 *ssid, size_t ssid_len,
+ unsigned int force_freq, const u8 *go_dev_addr,
+ unsigned int pref_freq);
int p2p_pasn_auth_rx(struct p2p_data *p2p, const struct ieee80211_mgmt *mgmt,
size_t len, int freq);
int p2p_pasn_update_extra_ies(struct p2p_data *p2p, const u8 *peer_addr,
@@ -2628,5 +2638,5 @@ int p2p_pasn_update_extra_ies(struct p2p_data *p2p, const u8 *peer_addr,
int p2p_pasn_parse_encrypted_data(struct p2p_data *p2p, const u8 *data,
size_t len);
int p2p_pasn_auth_tx_status(struct p2p_data *p2p, const u8 *data,
- size_t data_len, u8 acked);
+ size_t data_len, u8 acked, bool verify);
#endif /* P2P_H */
diff --git a/src/p2p/p2p_i.h b/src/p2p/p2p_i.h
index c15fc2a..6dce2d8 100644
--- a/src/p2p/p2p_i.h
+++ b/src/p2p/p2p_i.h
@@ -216,6 +216,16 @@ struct p2p_device {
* password length. Non zero if valid
*/
u16 dev_password_len;
+
+ /**
+ * Invitation params for P2P2
+ */
+ u8 inv_reject;
+ u8 inv_status;
+ int inv_freq;
+ int inv_peer_oper_freq;
+ u8 inv_bssid[ETH_ALEN];
+ struct p2p_channels *inv_channels;
};
struct p2p_sd_query {
@@ -996,6 +1006,9 @@ void p2p_process_pcea(struct p2p_data *p2p, struct p2p_message *msg,
struct p2p_device *dev);
/* p2p_invitation.c */
+struct wpabuf * p2p_build_invitation_req(struct p2p_data *p2p,
+ struct p2p_device *peer,
+ const u8 *go_dev_addr, int dev_pw_id);
void p2p_handle_invitation_req(struct p2p_data *p2p, const u8 *sa,
const u8 *data, size_t len, int rx_freq);
void p2p_handle_invitation_resp(struct p2p_data *p2p, const u8 *sa,
@@ -1007,7 +1020,8 @@ void p2p_process_invitation_resp(struct p2p_data *p2p, const u8 *sa,
int p2p_invite_send(struct p2p_data *p2p, struct p2p_device *dev,
const u8 *go_dev_addr, int dev_pw_id);
void p2p_invitation_req_cb(struct p2p_data *p2p, int success);
-void p2p_invitation_resp_cb(struct p2p_data *p2p, int success);
+void p2p_invitation_resp_cb(struct p2p_data *p2p, const u8 *dst, int success);
+void p2p_start_invitation_connect(struct p2p_data *p2p, struct p2p_device *dev);
/* p2p_dev_disc.c */
void p2p_process_dev_disc_req(struct p2p_data *p2p, const u8 *sa,
diff --git a/src/p2p/p2p_invitation.c b/src/p2p/p2p_invitation.c
index 8ade838..3478c03 100644
--- a/src/p2p/p2p_invitation.c
+++ b/src/p2p/p2p_invitation.c
@@ -13,12 +13,15 @@
#include "common/wpa_ctrl.h"
#include "p2p_i.h"
#include "p2p.h"
+#include "crypto/sha256.h"
+#include "crypto/sha384.h"
+#include "common/sae.h"
+#include "pasn/pasn_common.h"
-static struct wpabuf * p2p_build_invitation_req(struct p2p_data *p2p,
- struct p2p_device *peer,
- const u8 *go_dev_addr,
- int dev_pw_id)
+struct wpabuf * p2p_build_invitation_req(struct p2p_data *p2p,
+ struct p2p_device *peer,
+ const u8 *go_dev_addr, int dev_pw_id)
{
struct wpabuf *buf;
u8 *len;
@@ -100,7 +103,7 @@ static struct wpabuf * p2p_build_invitation_req(struct p2p_data *p2p,
if (p2p->vendor_elem && p2p->vendor_elem[VENDOR_ELEM_P2P_INV_REQ])
wpabuf_put_buf(buf, p2p->vendor_elem[VENDOR_ELEM_P2P_INV_REQ]);
- if (dev_pw_id >= 0) {
+ if (dev_pw_id >= 0 && !peer->p2p2) {
/* WSC IE in Invitation Request for NFC static handover */
p2p_build_wps_ie(p2p, buf, dev_pw_id, 0);
}
@@ -120,6 +123,7 @@ static struct wpabuf * p2p_build_invitation_resp(struct p2p_data *p2p,
u8 *len;
size_t extra = 0;
+ p2p_dbg(p2p, "Building Invitation Response ");
#ifdef CONFIG_WIFI_DISPLAY
struct wpabuf *wfd_ie = p2p->wfd_ie_invitation;
if (wfd_ie && group_bssid) {
@@ -453,6 +457,7 @@ void p2p_process_invitation_resp(struct p2p_data *p2p, const u8 *sa,
struct p2p_device *dev;
struct p2p_message msg;
struct p2p_channels intersection, *channels = NULL;
+ struct p2p_channels *p2p2_channels = NULL;
p2p_dbg(p2p, "Received Invitation Response from " MACSTR,
MAC2STR(sa));
@@ -532,14 +537,17 @@ void p2p_process_invitation_resp(struct p2p_data *p2p, const u8 *sa,
#endif /* CONFIG_P2P_STRICT */
/* Try to survive without peer channel list */
channels = &p2p->channels;
+ p2p2_channels = channels;
} else if (!msg.channel_list) {
/* Non-success cases are not required to include Channel List */
channels = &p2p->channels;
+ p2p2_channels = channels;
} else if (p2p_peer_channels_check(p2p, &p2p->channels, dev,
msg.channel_list,
msg.channel_list_len) < 0) {
p2p_dbg(p2p, "No common channels found");
p2p_parse_free(&msg);
+ dev->inv_reject = 1;
return;
} else {
p2p_channels_intersect(&p2p->channels, &dev->channels,
@@ -547,6 +555,7 @@ void p2p_process_invitation_resp(struct p2p_data *p2p, const u8 *sa,
channels = &intersection;
}
+
if (p2p->cfg->invitation_result) {
int peer_oper_freq = 0;
int freq = p2p_channel_to_freq(p2p->op_reg_class,
@@ -568,19 +577,68 @@ void p2p_process_invitation_resp(struct p2p_data *p2p, const u8 *sa,
*/
p2p_check_pref_chan(p2p, 0, dev, &msg);
+ if (dev->p2p2) {
+ dev->inv_freq = freq;
+ dev->inv_status = *msg.status;
+ dev->inv_channels = p2p2_channels;
+ dev->inv_peer_oper_freq = peer_oper_freq;
+ os_memcpy(dev->inv_bssid, msg.group_bssid, ETH_ALEN);
+ goto out;
+ }
+
p2p->cfg->invitation_result(p2p->cfg->cb_ctx, *msg.status,
msg.group_bssid, channels, sa,
- freq, peer_oper_freq);
+ freq, peer_oper_freq, NULL, NULL,
+ 0);
}
+ p2p_clear_timeout(p2p);
+ p2p_set_state(p2p, P2P_IDLE);
+ p2p->invite_peer = NULL;
+
+out:
p2p_parse_free(&msg);
+}
+
+
+void p2p_start_invitation_connect(struct p2p_data *p2p, struct p2p_device *dev)
+{
+ size_t pmk_len = 0;
+ u8 pmkid[PMKID_LEN];
+ u8 pmk[PMK_LEN_MAX];
+ struct p2p_channels intersection;
+
+ if (!p2p || !dev || dev->inv_reject || !dev->pasn)
+ return;
+
+ if (!dev->inv_channels) {
+ p2p_channels_intersect(&p2p->channels, &dev->channels,
+ &intersection);
+ dev->inv_channels = &intersection;
+ }
+
+ pasn_initiator_pmksa_cache_get(dev->pasn->pmksa, dev->pasn->peer_addr,
+ pmkid, pmk, &pmk_len);
+
+ wpa_pasn_reset(dev->pasn);
+ p2p_dbg(p2p, "P2P Invitation connect: msg status %d", dev->inv_status);
+ if (p2p->cfg->invitation_result)
+ p2p->cfg->invitation_result(p2p->cfg->cb_ctx, dev->inv_status,
+ dev->inv_bssid, dev->inv_channels,
+ dev->info.p2p_device_addr,
+ dev->inv_freq,
+ dev->inv_peer_oper_freq, pmkid,
+ pmk, pmk_len);
+
+ /* Reset pmk and pmkid from RAM */
+ memset(pmkid, 0, sizeof(pmkid));
+ memset(pmk, 0, sizeof(pmk));
p2p_clear_timeout(p2p);
p2p_set_state(p2p, P2P_IDLE);
p2p->invite_peer = NULL;
}
-
int p2p_invite_send(struct p2p_data *p2p, struct p2p_device *dev,
const u8 *go_dev_addr, int dev_pw_id)
{
@@ -649,8 +707,22 @@ void p2p_invitation_req_cb(struct p2p_data *p2p, int success)
}
-void p2p_invitation_resp_cb(struct p2p_data *p2p, int success)
+void p2p_invitation_resp_cb(struct p2p_data *p2p, const u8 *peer, int success)
{
+ size_t pmk_len = 0;
+ u8 pmkid[PMKID_LEN];
+ u8 pmk[PMK_LEN_MAX];
+ struct p2p_device *dev;
+
+ dev = p2p_get_device(p2p, peer);
+ if (!dev)
+ return;
+
+ if (dev->pasn)
+ pasn_responder_pmksa_cache_get(dev->pasn->pmksa,
+ dev->pasn->peer_addr, pmkid,
+ pmk, &pmk_len);
+
p2p_dbg(p2p, "Invitation Response TX callback: success=%d", success);
p2p->cfg->send_action_done(p2p->cfg->cb_ctx);
@@ -664,15 +736,20 @@ void p2p_invitation_resp_cb(struct p2p_data *p2p, int success)
p2p->inv_ssid, p2p->inv_ssid_len,
p2p->inv_go_dev_addr,
p2p->inv_status,
- p2p->inv_op_freq);
+ p2p->inv_op_freq, pmkid, pmk,
+ pmk_len);
}
+ /* Reset pmk and pmkid from RAM */
+ memset(pmkid, 0, sizeof(pmkid));
+ memset(pmk, 0, sizeof(pmk));
}
int p2p_invite(struct p2p_data *p2p, const u8 *peer, enum p2p_invite_role role,
const u8 *bssid, const u8 *ssid, size_t ssid_len,
unsigned int force_freq, const u8 *go_dev_addr,
- int persistent_group, unsigned int pref_freq, int dev_pw_id)
+ int persistent_group, unsigned int pref_freq, int dev_pw_id,
+ bool p2p2)
{
struct p2p_device *dev;
@@ -740,5 +817,8 @@ int p2p_invite(struct p2p_data *p2p, const u8 *peer, enum p2p_invite_role role,
os_memcpy(p2p->inv_ssid, ssid, ssid_len);
p2p->inv_ssid_len = ssid_len;
p2p->inv_persistent = persistent_group;
+ if (p2p2)
+ return 0;
+
return p2p_invite_send(p2p, dev, go_dev_addr, dev_pw_id);
}
diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c
index 2acabf2..4cfff25 100644
--- a/wpa_supplicant/ctrl_iface.c
+++ b/wpa_supplicant/ctrl_iface.c
@@ -7078,6 +7078,7 @@ static int p2p_ctrl_invite_persistent(struct wpa_supplicant *wpa_s, char *cmd)
int ht40, vht, he, max_oper_chwidth, chwidth = 0, freq2 = 0;
int edmg;
bool allow_6ghz;
+ bool p2p2;
id = atoi(cmd);
pos = os_strstr(cmd, " peer=");
@@ -7134,9 +7135,11 @@ static int p2p_ctrl_invite_persistent(struct wpa_supplicant *wpa_s, char *cmd)
if (allow_6ghz && chwidth == 40)
max_oper_chwidth = CONF_OPER_CHWIDTH_40MHZ_6GHZ;
+ p2p2 = os_strstr(cmd, "p2p2") != NULL;
+
return wpas_p2p_invite(wpa_s, _peer, ssid, NULL, freq, freq2, ht40, vht,
max_oper_chwidth, pref_freq, he, edmg,
- allow_6ghz);
+ allow_6ghz, p2p2);
}
@@ -7191,6 +7194,9 @@ static int p2p_ctrl_group_add_persistent(struct wpa_supplicant *wpa_s,
int he, int edmg, bool allow_6ghz,
const u8 *go_bssid)
{
+ size_t pmk_len = 0;
+ u8 pmkid[PMKID_LEN];
+ u8 pmk[PMK_LEN_MAX];
struct wpa_ssid *ssid;
ssid = wpa_config_get_network(wpa_s->conf, id);
@@ -7201,11 +7207,12 @@ static int p2p_ctrl_group_add_persistent(struct wpa_supplicant *wpa_s,
return -1;
}
+ /* FIXME Fetch pmk, pmkid from p2p_supplicant.conf */
return wpas_p2p_group_add_persistent(wpa_s, ssid, 0, freq, 0,
vht_center_freq2, ht40, vht,
vht_chwidth, he, edmg,
NULL, 0, 0, allow_6ghz, 0,
- go_bssid);
+ go_bssid, NULL, pmkid, pmk, pmk_len);
}
diff --git a/wpa_supplicant/dbus/dbus_new_handlers_p2p.c b/wpa_supplicant/dbus/dbus_new_handlers_p2p.c
index 0011cf0..76548d6 100644
--- a/wpa_supplicant/dbus/dbus_new_handlers_p2p.c
+++ b/wpa_supplicant/dbus/dbus_new_handlers_p2p.c
@@ -367,6 +367,9 @@ DBusMessage * wpas_dbus_handler_p2p_group_add(DBusMessage *message,
int he = wpa_s->conf->p2p_go_he;
int edmg = wpa_s->conf->p2p_go_edmg;
int max_oper_chwidth, chwidth = 0, freq2 = 0;
+ size_t pmk_len = 0;
+ u8 pmkid[PMKID_LEN];
+ u8 pmk[PMK_LEN_MAX];
dbus_message_iter_init(message, &iter);
@@ -477,7 +480,8 @@ DBusMessage * wpas_dbus_handler_p2p_group_add(DBusMessage *message,
freq2, ht40, vht,
max_oper_chwidth, he, edmg,
NULL, 0, 0, allow_6ghz,
- retry_limit, go_bssid)) {
+ retry_limit, go_bssid, NULL, pmkid,
+ pmk, pmk_len)) {
reply = wpas_dbus_error_unknown_error(
message,
"Failed to reinvoke a persistent group");
@@ -866,7 +870,7 @@ DBusMessage * wpas_dbus_handler_p2p_invite(DBusMessage *message,
goto err;
if (wpas_p2p_invite(wpa_s, peer_addr, ssid, NULL, 0, 0, 0, 0, 0,
- 0, 0, 0, false) < 0) {
+ 0, 0, 0, false, 0) < 0) {
reply = wpas_dbus_error_unknown_error(
message,
"Failed to reinvoke a persistent group");
diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c
index a1430be..2a21842 100644
--- a/wpa_supplicant/p2p_supplicant.c
+++ b/wpa_supplicant/p2p_supplicant.c
@@ -1731,13 +1731,22 @@ static void wpas_send_action_done(void *ctx)
struct wpa_p2p_pasn_auth_work {
u8 peer_addr[ETH_ALEN];
- bool verify;
int freq;
+ bool verify;
+ int force_freq;
+ int pref_freq;
+ enum p2p_invite_role role;
+ u8 *ssid;
+ size_t ssid_len;
+ u8 bssid[ETH_ALEN];
+ u8 go_dev_addr[ETH_ALEN];
};
static void wpas_p2p_pasn_free_auth_work(struct wpa_p2p_pasn_auth_work *awork)
{
+ if (awork->ssid)
+ os_free(awork->ssid);
os_free(awork);
}
@@ -3507,7 +3516,8 @@ accept_inv:
static void wpas_invitation_received(void *ctx, const u8 *sa, const u8 *bssid,
const u8 *ssid, size_t ssid_len,
const u8 *go_dev_addr, u8 status,
- int op_freq)
+ int op_freq, u8 *pmkid, u8 *pmk,
+ size_t pmk_len)
{
struct wpa_supplicant *wpa_s = ctx;
struct wpa_ssid *s;
@@ -3547,7 +3557,7 @@ static void wpas_invitation_received(void *ctx, const u8 *sa, const u8 *bssid,
wpa_s->conf->p2p_go_edmg, NULL,
go ? P2P_MAX_INITIAL_CONN_WAIT_GO_REINVOKE : 0,
1, is_p2p_allow_6ghz(wpa_s->global->p2p), 0,
- NULL);
+ bssid, sa, pmkid, pmk, pmk_len);
} else if (bssid) {
wpa_s->user_initiated_pd = 0;
wpa_msg_global(wpa_s, MSG_INFO,
@@ -3665,12 +3675,18 @@ static void wpas_remove_persistent_client(struct wpa_supplicant *wpa_s,
static void wpas_invitation_result(void *ctx, int status, const u8 *bssid,
const struct p2p_channels *channels,
const u8 *peer, int neg_freq,
- int peer_oper_freq)
+ int peer_oper_freq, u8 *pmkid, u8 *pmk,
+ size_t pmk_len)
{
struct wpa_supplicant *wpa_s = ctx;
struct wpa_ssid *ssid;
int freq;
+ if (wpa_s->p2p_pasn_auth_work) {
+ wpas_p2p_pasn_cancel_auth_work(wpa_s);
+ wpa_s->p2p_pasn_auth_work = NULL;
+ }
+
if (bssid) {
wpa_msg_global(wpa_s, MSG_INFO, P2P_EVENT_INVITATION_RESULT
"status=%d " MACSTR,
@@ -3778,7 +3794,7 @@ static void wpas_invitation_result(void *ctx, int status, const u8 *bssid,
P2P_MAX_INITIAL_CONN_WAIT_GO_REINVOKE :
0, 1,
is_p2p_allow_6ghz(wpa_s->global->p2p), 0,
- NULL);
+ bssid, peer, pmkid, pmk, pmk_len);
}
@@ -4844,7 +4860,8 @@ static void wpas_p2ps_prov_complete(void *ctx, u8 status, const u8 *dev,
persistent_go->mode ==
WPAS_MODE_P2P_GO ?
P2P_MAX_INITIAL_CONN_WAIT_GO_REINVOKE :
- 0, 0, false, 0, NULL);
+ 0, 0, false, 0, NULL, NULL, NULL, NULL,
+ 0);
} else if (response_done) {
wpas_p2p_group_add(wpa_s, 1, freq,
0, 0, 0, 0, 0, 0, false);
@@ -4967,7 +4984,8 @@ static int wpas_prov_disc_resp_cb(void *ctx)
NULL,
persistent_go->mode == WPAS_MODE_P2P_GO ?
P2P_MAX_INITIAL_CONN_WAIT_GO_REINVOKE : 0, 0,
- is_p2p_allow_6ghz(wpa_s->global->p2p), 0, NULL);
+ is_p2p_allow_6ghz(wpa_s->global->p2p), 0, NULL, NULL,
+ NULL, NULL, 0);
} else {
wpas_p2p_group_add(wpa_s, 1, freq, 0, 0, 0, 0, 0, 0,
is_p2p_allow_6ghz(wpa_s->global->p2p));
@@ -4990,10 +5008,13 @@ static int wpas_p2p_get_pref_freq_list(void *ctx, int go,
static void wpas_p2p_pasn_auth_start_cb(struct wpa_radio_work *work, int deinit)
{
+ int ret = 0;
struct wpa_supplicant *wpa_s = work->wpa_s;
struct wpa_p2p_pasn_auth_work *awork = work->ctx;
struct p2p_data *p2p = wpa_s->global->p2p;
const u8 *peer_addr = NULL;
+ const u8 *bssid = NULL;
+ const u8 *go_dev_addr = NULL;
if (deinit) {
if (!work->started) {
@@ -5006,7 +5027,22 @@ static void wpas_p2p_pasn_auth_start_cb(struct wpa_radio_work *work, int deinit)
if (!is_zero_ether_addr(awork->peer_addr))
peer_addr = awork->peer_addr;
- if (p2p_initiate_pasn_auth(p2p, peer_addr, awork->freq)) {
+ if (!is_zero_ether_addr(awork->bssid))
+ bssid = awork->bssid;
+ if (!is_zero_ether_addr(awork->go_dev_addr))
+ go_dev_addr = awork->go_dev_addr;
+
+
+ if (awork->verify)
+ ret = p2p_initiate_pasn_verify(p2p, peer_addr, awork->freq,
+ awork->role, bssid, awork->ssid,
+ awork->ssid_len,
+ awork->force_freq, go_dev_addr,
+ awork->pref_freq);
+ else
+ ret = p2p_initiate_pasn_auth(p2p, peer_addr, awork->freq);
+
+ if (ret) {
wpa_printf(MSG_DEBUG,
"P2P PASN: Failed to start PASN authentication");
goto fail;
@@ -5024,6 +5060,59 @@ fail:
radio_work_done(work);
}
+static int wpas_p2p_initiate_pasn_verify(struct wpa_supplicant *wpa_s,
+ const u8 *peer,
+ enum p2p_invite_role role,
+ const u8 *bssid, const u8 *ssid,
+ size_t ssid_len,
+ unsigned int force_freq,
+ const u8 *go_dev_addr,
+ unsigned int pref_freq)
+{
+ int freq;
+ struct wpa_p2p_pasn_auth_work *awork;
+
+ wpas_p2p_pasn_cancel_auth_work(wpa_s);
+ wpa_s->p2p_pasn_auth_work = NULL;
+
+ freq = get_listen_freq(wpa_s->global->p2p, peer);
+ if (freq == -1)
+ return -1;
+
+ awork = os_zalloc(sizeof(*awork));
+ if (!awork)
+ return -1;
+
+ awork->verify = 1;
+ awork->role = role;
+ awork->freq = freq;
+ awork->force_freq = force_freq;
+ awork->pref_freq = pref_freq;
+ os_memcpy(awork->peer_addr, peer, ETH_ALEN);
+ if (go_dev_addr)
+ os_memcpy(awork->go_dev_addr, go_dev_addr, ETH_ALEN);
+ if (bssid)
+ os_memcpy(awork->bssid, bssid, ETH_ALEN);
+ if (ssid_len) {
+ awork->ssid = os_zalloc(ssid_len);
+ if (!awork->ssid) {
+ os_free(awork);
+ return -1;
+ }
+ memcpy(awork->ssid, ssid, ssid_len);
+ awork->ssid_len = ssid_len;
+ }
+
+ if (radio_add_work(wpa_s, freq, "p2p-pasn-start-auth", 1,
+ wpas_p2p_pasn_auth_start_cb, awork) < 0) {
+ wpas_p2p_pasn_free_auth_work(awork);
+ return -1;
+ }
+
+ wpa_printf(MSG_DEBUG, "P2P PASN: Auth work successfully added");
+ return 0;
+}
+
static int wpas_p2p_initiate_pasn_auth(struct wpa_supplicant *wpa_s,
const u8 *peer_addr, int freq)
{
@@ -5150,8 +5239,12 @@ int wpas_p2p_pasn_auth_tx_status(struct wpa_supplicant *wpa_s, const u8 *data,
size_t data_len, u8 acked)
{
struct p2p_data *p2p = wpa_s->global->p2p;
+ struct wpa_p2p_pasn_auth_work *awork;
+
+ awork = wpa_s->p2p_pasn_auth_work->ctx;
- return p2p_pasn_auth_tx_status(p2p, data, data_len, acked);
+ return p2p_pasn_auth_tx_status(p2p, data, data_len, acked,
+ awork->verify);
}
int wpas_p2p_mac_setup(struct wpa_supplicant *wpa_s)
@@ -6851,6 +6944,7 @@ static int wpas_p2p_init_go_params(struct wpa_supplicant *wpa_s,
params->max_oper_chwidth = max_oper_chwidth;
params->vht_center_freq2 = vht_center_freq2;
params->edmg = edmg;
+ params->p2p2 = wpa_s->p2p2;
freqs = os_calloc(wpa_s->num_multichan_concurrent,
sizeof(struct wpa_used_freq_data));
@@ -7293,7 +7387,8 @@ int wpas_p2p_group_add(struct wpa_supplicant *wpa_s, int persistent_group,
static int wpas_start_p2p_client(struct wpa_supplicant *wpa_s,
struct wpa_ssid *params, int addr_allocated,
int freq, int force_scan, int retry_limit,
- const u8 *go_bssid)
+ const u8 *go_bssid, bool p2p2, u8 *pmkid,
+ u8 *pmk, size_t pmk_len)
{
struct wpa_ssid *ssid;
int other_iface_found = 0;
@@ -7351,6 +7446,20 @@ static int wpas_start_p2p_client(struct wpa_supplicant *wpa_s,
os_memcpy(ssid->bssid, go_bssid, ETH_ALEN);
}
+ if (p2p2) {
+ ssid->key_mgmt = WPA_KEY_MGMT_SAE;
+ ssid->auth_alg = WPA_AUTH_ALG_OPEN;
+ ssid->sae_password = "12345678";
+ wpa_s->conf->sae_pwe = SAE_PWE_HASH_TO_ELEMENT;
+ ssid->ieee80211w = MGMT_FRAME_PROTECTION_REQUIRED;
+ ssid->disabled = 0;
+
+ if (pmk && pmk_len && pmkid)
+ wpa_sm_set_pmk(wpa_s->wpa, pmk, pmk_len, pmkid,
+ ssid->bssid);
+ wpa_s->current_ssid = ssid;
+ }
+
wpa_s->show_group_started = 1;
wpa_s->p2p_in_invitation = 1;
wpa_s->p2p_retry_limit = retry_limit;
@@ -7398,7 +7507,8 @@ int wpas_p2p_group_add_persistent(struct wpa_supplicant *wpa_s,
const struct p2p_channels *channels,
int connection_timeout, int force_scan,
bool allow_6ghz, int retry_limit,
- const u8 *go_bssid)
+ const u8 *go_bssid, const u8 *dev_addr,
+ u8 *pmkid, u8 *pmk, size_t pmk_len)
{
struct p2p_go_neg_results params;
int go = 0, freq;
@@ -7467,7 +7577,8 @@ int wpas_p2p_group_add_persistent(struct wpa_supplicant *wpa_s,
}
return wpas_start_p2p_client(wpa_s, ssid, addr_allocated, freq,
- force_scan, retry_limit, go_bssid);
+ force_scan, retry_limit, go_bssid,
+ wpa_s->p2p2, pmkid, pmk, pmk_len);
} else {
return -1;
}
@@ -7494,6 +7605,15 @@ int wpas_p2p_group_add_persistent(struct wpa_supplicant *wpa_s,
params.ssid_len = ssid->ssid_len;
params.persistent_group = 1;
+ if (wpa_s->p2p2 && pmk_len && pmk && pmkid) {
+ memcpy(params.peer_device_addr, dev_addr, ETH_ALEN);
+ memcpy(params.pmkid, pmkid, PMKID_LEN);
+ memcpy(params.pmk, pmk, pmk_len);
+ params.pmk_len = pmk_len;
+ params.akmp = WPA_KEY_MGMT_SAE;
+ params.p2p2 = true;
+ }
+
wpa_s = wpas_p2p_get_group_iface(wpa_s, addr_allocated, 1);
if (wpa_s == NULL)
return -1;
@@ -8031,7 +8151,7 @@ int wpas_p2p_reject(struct wpa_supplicant *wpa_s, const u8 *addr)
int wpas_p2p_invite(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
struct wpa_ssid *ssid, const u8 *go_dev_addr, int freq,
int vht_center_freq2, int ht40, int vht, int max_chwidth,
- int pref_freq, int he, int edmg, bool allow_6ghz)
+ int pref_freq, int he, int edmg, bool allow_6ghz, bool p2p2)
{
enum p2p_invite_role role;
u8 *bssid = NULL;
@@ -8110,9 +8230,21 @@ int wpas_p2p_invite(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
*/
wpas_p2p_stop_find_oper(wpa_s);
+ if (p2p2) {
+ if (wpas_p2p_initiate_pasn_verify(wpa_s, peer_addr, role, bssid,
+ ssid->ssid, ssid->ssid_len,
+ force_freq, go_dev_addr,
+ pref_freq) < 0) {
+ if (wpa_s->create_p2p_iface)
+ wpas_p2p_remove_pending_group_interface(wpa_s);
+ return -1;
+ }
+ return 0;
+ }
+
return p2p_invite(wpa_s->global->p2p, peer_addr, role, bssid,
ssid->ssid, ssid->ssid_len, force_freq, go_dev_addr,
- 1, pref_freq, -1);
+ 1, pref_freq, -1, 0);
}
@@ -8196,7 +8328,7 @@ int wpas_p2p_invite_group(struct wpa_supplicant *wpa_s, const char *ifname,
return p2p_invite(wpa_s->global->p2p, peer_addr, role, bssid,
ssid->ssid, ssid->ssid_len, force_freq,
- go_dev_addr, persistent, pref_freq, -1);
+ go_dev_addr, persistent, pref_freq, -1, 0);
}
@@ -9697,7 +9829,7 @@ static int wpas_p2p_nfc_auth_join(struct wpa_supplicant *wpa_s,
P2P_INVITE_ROLE_ACTIVE_GO, wpa_s->own_addr,
ssid->ssid, ssid->ssid_len, ssid->frequency,
wpa_s->global->p2p_dev_addr, persistent, 0,
- wpa_s->p2pdev->p2p_oob_dev_pw_id);
+ wpa_s->p2pdev->p2p_oob_dev_pw_id, 0);
}
diff --git a/wpa_supplicant/p2p_supplicant.h b/wpa_supplicant/p2p_supplicant.h
index 5612d83..61d4281 100644
--- a/wpa_supplicant/p2p_supplicant.h
+++ b/wpa_supplicant/p2p_supplicant.h
@@ -54,7 +54,8 @@ int wpas_p2p_group_add_persistent(struct wpa_supplicant *wpa_s,
const struct p2p_channels *channels,
int connection_timeout, int force_scan,
bool allow_6ghz, int retry_limit,
- const u8 *go_bssid);
+ const u8 *go_bssid, const u8 *dev_addr,
+ u8 *pmkid, u8 *pmk, size_t pmk_len);
struct p2p_group * wpas_p2p_group_init(struct wpa_supplicant *wpa_s,
struct wpa_ssid *ssid);
enum wpas_p2p_prov_disc_use {
@@ -122,7 +123,8 @@ int wpas_p2p_reject(struct wpa_supplicant *wpa_s, const u8 *addr);
int wpas_p2p_invite(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
struct wpa_ssid *ssid, const u8 *go_dev_addr, int freq,
int vht_center_freq2, int ht40, int vht, int max_chwidth,
- int pref_freq, int he, int edmg, bool allow_6ghz);
+ int pref_freq, int he, int edmg, bool allow_6ghz,
+ bool p2p2);
int wpas_p2p_invite_group(struct wpa_supplicant *wpa_s, const char *ifname,
const u8 *peer_addr, const u8 *go_dev_addr,
bool allow_6ghz);
--
2.7.4
More information about the Hostap
mailing list