Signed-off-by: Shivani Baranwal <quic_shivbara@xxxxxxxxxxx> --- src/p2p/p2p.c | 124 +++++++++++++++++++- src/p2p/p2p.h | 18 ++- src/p2p/p2p_i.h | 16 ++- src/p2p/p2p_invitation.c | 100 ++++++++++++++-- wpa_supplicant/ctrl_iface.c | 12 +- wpa_supplicant/dbus/dbus_new_handlers_p2p.c | 8 +- wpa_supplicant/p2p_supplicant.c | 175 +++++++++++++++++++++++++--- wpa_supplicant/p2p_supplicant.h | 6 +- 8 files changed, 415 insertions(+), 44 deletions(-) diff --git a/src/p2p/p2p.c b/src/p2p/p2p.c index 8f3d76e..702c90a 100644 --- a/src/p2p/p2p.c +++ b/src/p2p/p2p.c @@ -3996,7 +3996,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); @@ -4296,7 +4296,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); } @@ -6206,6 +6206,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, true); + 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)) { + 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) { @@ -6370,7 +6481,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); @@ -6631,7 +6743,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; @@ -6664,7 +6776,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 65e2e0d..4759947 100644 --- a/src/p2p/p2p.h +++ b/src/p2p/p2p.h @@ -1127,7 +1127,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 @@ -1148,7 +1149,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 @@ -1693,12 +1695,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 @@ -2675,12 +2679,18 @@ void p2p_set_comeback_after(struct p2p_data *p2p, int comeback_after); void p2p_set_reg_info(struct p2p_data *p2p, u8 val); void p2p_set_twt_power_mgmt(struct p2p_data *p2p, int 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); 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 440ed1f..7ff2c97 100644 --- a/src/p2p/p2p_i.h +++ b/src/p2p/p2p_i.h @@ -201,6 +201,16 @@ struct p2p_device { /* device role */ enum p2p_role role; + + /** + * 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 { @@ -979,6 +989,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, @@ -990,7 +1003,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..19785d4 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,18 +577,70 @@ 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; + if (msg.group_bssid) + 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); +} + + +#ifdef CONFIG_PASN +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; } - +#endif /* CONFIG_PASN */ int p2p_invite_send(struct p2p_data *p2p, struct p2p_device *dev, const u8 *go_dev_addr, int dev_pw_id) @@ -649,8 +710,19 @@ 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 && 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 d976914..daa8bef 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -7073,6 +7073,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="); @@ -7129,9 +7130,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); } @@ -7186,6 +7189,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); @@ -7196,11 +7202,13 @@ 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, freq, 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 65bd478..aad4c5b 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 71aaeba..0befcdd 100644 --- a/wpa_supplicant/p2p_supplicant.c +++ b/wpa_supplicant/p2p_supplicant.c @@ -39,7 +39,8 @@ #include "wifi_display.h" #include "crypto/random.h" - +#include "ap/ieee802_11.h" +#include "ap/wpa_auth.h" /* * How many times to try to scan to find the GO before giving up on join @@ -1736,13 +1737,22 @@ static void wpas_send_action_done(void *ctx) #ifdef CONFIG_PASN 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); } @@ -3522,7 +3532,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; @@ -3562,7 +3573,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, @@ -3680,12 +3691,20 @@ 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; +#ifdef CONFIG_PASN + if (wpa_s->p2p_pasn_auth_work) { + wpas_p2p_pasn_cancel_auth_work(wpa_s); + wpa_s->p2p_pasn_auth_work = NULL; + } +#endif /* CONFIG_PASN */ + if (bssid) { wpa_msg_global(wpa_s, MSG_INFO, P2P_EVENT_INVITATION_RESULT "status=%d " MACSTR, @@ -3793,7 +3812,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); } @@ -4859,7 +4878,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); @@ -4982,7 +5002,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)); @@ -5075,10 +5096,13 @@ static void wpas_bootstrap_completed(void *ctx, const u8 *addr, int status, #ifdef CONFIG_PASN 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) { @@ -5091,7 +5115,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; @@ -5109,6 +5148,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) { @@ -5166,8 +5258,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; - return p2p_pasn_auth_tx_status(p2p, data, data_len, acked); + awork = wpa_s->p2p_pasn_auth_work->ctx; + + return p2p_pasn_auth_tx_status(p2p, data, data_len, acked, + awork->verify); } #endif @@ -6897,6 +6993,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)); @@ -7339,7 +7436,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; @@ -7397,6 +7495,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; @@ -7444,7 +7556,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; @@ -7513,7 +7626,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; } @@ -7540,6 +7654,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; @@ -8077,7 +8200,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; @@ -8103,6 +8226,7 @@ int wpas_p2p_invite(struct wpa_supplicant *wpa_s, const u8 *peer_addr, wpa_s->p2p_go_max_oper_chwidth = max_chwidth; wpa_s->p2p_go_vht_center_freq2 = vht_center_freq2; wpa_s->p2p_go_edmg = !!edmg; + wpa_s->p2p2 = p2p2; if (ssid->mode == WPAS_MODE_P2P_GO) { role = P2P_INVITE_ROLE_GO; if (peer_addr == NULL) { @@ -8125,7 +8249,8 @@ int wpas_p2p_invite(struct wpa_supplicant *wpa_s, const u8 *peer_addr, bssid = wpa_s->own_addr; } else { role = P2P_INVITE_ROLE_CLIENT; - peer_addr = ssid->bssid; + if (!wpa_s->p2p2) + peer_addr = ssid->bssid; } wpa_s->pending_invite_ssid_id = ssid->id; @@ -8156,9 +8281,23 @@ int wpas_p2p_invite(struct wpa_supplicant *wpa_s, const u8 *peer_addr, */ wpas_p2p_stop_find_oper(wpa_s); +#ifdef CONFIG_PASN + 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; + } +#endif /* CONFIG_PASN */ + 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); } @@ -8242,7 +8381,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); } @@ -9743,7 +9882,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 _______________________________________________ Hostap mailing list Hostap@xxxxxxxxxxxxxxxxxxx http://lists.infradead.org/mailman/listinfo/hostap