From: Shivani Baranwal Date: Sun, 4 Aug 2024 21:13:59 +0000 (+0530) Subject: P2P2: Add support for GO Negotiation wrapped in PASN auth frame X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e147d24a0775c31c5231ce4ec416a0e0665644e7;p=thirdparty%2Fhostap.git P2P2: Add support for GO Negotiation wrapped in PASN auth frame Add P2P2 support for GO Negotiation wrapped in PASN authentication frames as an Action wrapper attribute. Signed-off-by: Shivani Baranwal --- diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h index d25e2b906..4b431b081 100644 --- a/src/common/ieee802_11_defs.h +++ b/src/common/ieee802_11_defs.h @@ -619,6 +619,7 @@ #define WLAN_RSNX_CAPAB_SECURE_RTT 9 #define WLAN_RSNX_CAPAB_URNM_MFPR_X20 10 #define WLAN_RSNX_CAPAB_URNM_MFPR 15 +#define WLAN_RSNX_CAPAB_KEK_IN_PASN 18 #define WLAN_RSNX_CAPAB_SSID_PROTECTION 21 /* Multiple BSSID element subelements */ diff --git a/src/p2p/p2p.c b/src/p2p/p2p.c index c5b4c05d6..3415e96dd 100644 --- a/src/p2p/p2p.c +++ b/src/p2p/p2p.c @@ -246,6 +246,11 @@ void p2p_go_neg_failed(struct p2p_data *p2p, int status) peer->go_neg_conf = NULL; p2p->go_neg_peer = NULL; +#ifdef CONFIG_PASN + if (peer->p2p2 && peer->pasn) + wpa_pasn_reset(peer->pasn); +#endif /* CONFIG_PASN */ + os_memset(&res, 0, sizeof(res)); res.status = status; os_memcpy(res.peer_device_addr, peer->info.p2p_device_addr, ETH_ALEN); @@ -959,6 +964,16 @@ static void p2p_device_free(struct p2p_data *p2p, struct p2p_device *dev) } os_free(dev->bootstrap_params); + + wpabuf_free(dev->action_frame_wrapper); + +#ifdef CONFIG_PASN + if (dev->pasn) { + wpa_pasn_reset(dev->pasn); + pasn_data_deinit(dev->pasn); + } +#endif /* CONFIG_PASN */ + wpabuf_free(dev->info.wfd_subelems); wpabuf_free(dev->info.vendor_elems); wpabuf_free(dev->go_neg_conf); @@ -1907,6 +1922,11 @@ void p2p_go_complete(struct p2p_data *p2p, struct p2p_device *peer) wpabuf_free(peer->go_neg_conf); peer->go_neg_conf = NULL; +#ifdef CONFIG_PASN + if (peer->p2p2 && peer->pasn) + wpa_pasn_reset(peer->pasn); +#endif /* CONFIG_PASN */ + p2p_set_state(p2p, P2P_PROVISIONING); p2p->cfg->go_neg_completed(p2p->cfg->cb_ctx, &res); } @@ -5949,9 +5969,585 @@ void p2p_process_usd_elems(struct p2p_data *p2p, const u8 *ies, u16 ies_len, #ifdef CONFIG_PASN + +static int p2p_prepare_pasn_extra_ie(struct p2p_data *p2p, + struct wpabuf *extra_ies, + const struct wpabuf *frame) +{ + struct wpabuf *buf, *buf2; + size_t len; + + len = 100; + if (frame) + len += wpabuf_len(frame); + buf = wpabuf_alloc(len); + if (!buf) + return -1; + + /* P2P Capability Extension attribute */ + p2p_buf_add_pcea(buf, p2p); + + if (frame) { + p2p_dbg(p2p, "Add Action frame wrapper for PASN"); + wpabuf_put_u8(buf, P2P_ATTR_ACTION_FRAME_WRAPPER); + wpabuf_put_le16(buf, wpabuf_len(frame)); + wpabuf_put_buf(buf, frame); + } + + buf2 = p2p_encaps_ie(buf, P2P2_IE_VENDOR_TYPE); + wpabuf_free(buf); + + if (wpabuf_tailroom(extra_ies) < wpabuf_len(buf2)) { + p2p_err(p2p, "Not enough room for P2P2 IE in PASN extra IEs"); + wpabuf_free(buf2); + return -1; + } + wpabuf_put_buf(extra_ies, buf2); + wpabuf_free(buf2); + + return 0; +} + + +static struct wpabuf * p2p_pairing_generate_rsnxe(struct p2p_data *p2p, + int akmp) +{ + u32 capab; + size_t flen = 0; + struct wpabuf *buf; + + capab = BIT(WLAN_RSNX_CAPAB_KEK_IN_PASN); + + if (wpa_key_mgmt_sae(akmp)) + capab |= BIT(WLAN_RSNX_CAPAB_SAE_H2E); + + while (capab >> flen * 8) + flen++; + + buf = wpabuf_alloc(2 + flen); + if (!buf) + return NULL; + + if (wpabuf_tailroom(buf) < 2 + flen) { + p2p_dbg(p2p, "wpabuf tail room too small"); + wpabuf_free(buf); + return NULL; + } + capab |= flen - 1; /* bit 0-3 = Field length (n - 1) */ + + p2p_dbg(p2p, "RSNXE capabilities: %04x", capab); + wpabuf_put_u8(buf, WLAN_EID_RSNX); + wpabuf_put_u8(buf, flen); + while (flen--) { + wpabuf_put_u8(buf, (capab & 0xff)); + capab = capab >> 8; + } + return buf; +} + + +/* SSID used for deriving SAE pt for pairing */ +#define P2P_PAIRING_SSID "516F9A020000" + +static void p2p_pairing_set_password(struct pasn_data *pasn, u8 pasn_type, + const char *passphrase) +{ + int pasn_groups[4] = { 0 }; + size_t len; + + if (!passphrase) + return; + + len = os_strlen(passphrase); + + if (pasn_type & 0xc && pasn_type & 0x3) { + pasn_groups[0] = 20; + pasn_groups[1] = 19; + } else if (pasn_type & 0xc) { + pasn_groups[0] = 20; + } else { + pasn_groups[0] = 19; + } + pasn->pt = sae_derive_pt(pasn_groups, (const u8 *) P2P_PAIRING_SSID, + os_strlen(P2P_PAIRING_SSID), + (const u8 *) passphrase, len, NULL); + /* Set passphrase for pairing responder to validate PASN auth 1 frame */ + pasn->password = passphrase; +} + + +void p2p_pasn_initialize(struct p2p_data *p2p, struct p2p_device *dev, + const u8 *addr, int freq, bool verify) +{ + struct pasn_data *pasn; + struct wpabuf *rsnxe; + + if (!p2p || !dev) + return; + + if (dev->pasn) { + wpa_pasn_reset(dev->pasn); + } else { + dev->pasn = pasn_data_init(); + if (!dev->pasn) + return; + } + + pasn = dev->pasn; + + os_memcpy(pasn->own_addr, p2p->cfg->dev_addr, ETH_ALEN); + os_memcpy(pasn->peer_addr, addr, ETH_ALEN); + + os_memcpy(pasn->bssid, dev->role == P2P_ROLE_PAIRING_INITIATOR ? + pasn->peer_addr : pasn->own_addr, ETH_ALEN); + + pasn->noauth = 1; + + if ((p2p->cfg->pairing_config.pasn_type & 0xc) && + (dev->info.pairing_config.pasn_type & 0xc)) { + pasn->group = 20; + pasn->cipher = WPA_CIPHER_GCMP_256; + pasn->kek_len = 32; + } else { + pasn->group = 19; + pasn->cipher = WPA_CIPHER_CCMP; + pasn->kek_len = 16; + } + + if (dev->password[0]) { + pasn->akmp = WPA_KEY_MGMT_SAE; + p2p_pairing_set_password(pasn, + p2p->cfg->pairing_config.pasn_type, + dev->password); + pasn->rsnxe_capab |= BIT(WLAN_RSNX_CAPAB_SAE_H2E); + } else if (verify) { + pasn->akmp = WPA_KEY_MGMT_SAE; + } else { + pasn->akmp = WPA_KEY_MGMT_PASN; + } + + pasn->rsn_pairwise = pasn->cipher; + pasn->wpa_key_mgmt = pasn->akmp; + + rsnxe = p2p_pairing_generate_rsnxe(p2p, pasn->akmp); + if (rsnxe) { + os_free(pasn->rsnxe_ie); + pasn->rsnxe_ie = os_memdup(wpabuf_head_u8(rsnxe), + wpabuf_len(rsnxe)); + if (!pasn->rsnxe_ie) { + wpabuf_free(rsnxe); + return; + } + wpabuf_free(rsnxe); + } + + if (dev->role == P2P_ROLE_PAIRING_INITIATOR) + pasn->pmksa = p2p->initiator_pmksa; + else + pasn->pmksa = p2p->responder_pmksa; + + pasn->freq = freq; +} + + +int p2p_initiate_pasn_auth(struct p2p_data *p2p, const u8 *addr, int freq) +{ + struct pasn_data *pasn; + struct p2p_device *dev; + struct wpabuf *extra_ies, *req; + u8 *ies = NULL; + int ret = 0; + size_t ies_len; + + if (!addr) { + p2p_dbg(p2p, "Peer address NULL"); + return -1; + } + + dev = p2p_get_device(p2p, addr); + if (!dev) { + p2p_dbg(p2p, "Peer not known"); + return -1; + } + + dev->role = P2P_ROLE_PAIRING_INITIATOR; + p2p_pasn_initialize(p2p, dev, addr, freq, false); + pasn = dev->pasn; + + pasn_initiator_pmksa_cache_remove(pasn->pmksa, (u8 *)addr); + + req = p2p_build_go_neg_req(p2p, dev); + if (!req) + return -1; + + p2p->go_neg_peer = dev; + dev->flags |= P2P_DEV_WAIT_GO_NEG_RESPONSE; + + extra_ies = wpabuf_alloc(1500); + if (!extra_ies) { + wpabuf_free(req); + return -1; + } + + if (p2p_prepare_pasn_extra_ie(p2p, extra_ies, req)) { + p2p_dbg(p2p, "Failed to prepare PASN extra elements"); + ret = -1; + goto out; + } + + ies_len = wpabuf_len(extra_ies); + ies = os_memdup(wpabuf_head_u8(extra_ies), ies_len); + if (!ies) { + ret = -1; + goto out; + } + + pasn->extra_ies = ies; + pasn->extra_ies_len = ies_len; + + /* Start PASN authentication */ + if (wpas_pasn_start(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, "Failed to start PASN"); + ret = -1; + } +out: + os_free(ies); + pasn->extra_ies = NULL; + pasn->extra_ies_len = 0; + wpabuf_free(req); + wpabuf_free(extra_ies); + return ret; +} + + +static int p2p_pasn_handle_action_wrapper(struct p2p_data *p2p, + struct p2p_device *dev, + const struct ieee80211_mgmt *mgmt, + size_t len, int freq, int trans_seq) +{ + const u8 *ies; + size_t ies_len; + size_t data_len = 0; + const u8 *data = NULL; + struct p2p_message msg; + + ies = mgmt->u.auth.variable; + ies_len = len - offsetof(struct ieee80211_mgmt, u.auth.variable); + + os_memset(&msg, 0, sizeof(msg)); + if (p2p_parse_ies(ies, ies_len, &msg)) { + p2p_dbg(p2p, + "Failed to parse P2P IE from PASN Authentication frame"); + p2p_parse_free(&msg); + return -1; + } + + if (msg.action_frame_wrapper && msg.action_frame_wrapper_len) { + data = msg.action_frame_wrapper; + data_len = msg.action_frame_wrapper_len; + if (data_len >= 2 && + data[0] == WLAN_ACTION_PUBLIC && + data[1] == WLAN_PA_VENDOR_SPECIFIC) { + data += 2; + data_len -= 2; + if (data_len < 4 || + WPA_GET_BE32(data) != P2P_IE_VENDOR_TYPE) { + p2p_parse_free(&msg); + return -1; + } + data += 4; + data_len -= 4; + } else { + p2p_dbg(p2p, + "Invalid category in Action frame wrapper in Authentication frame seq %d", + trans_seq); + p2p_parse_free(&msg); + return -1; + } + } + + if (trans_seq == 1) { + if (data && data_len >= 1 && data[0] == P2P_INVITATION_REQ) { + struct wpabuf *resp; + + resp = p2p_process_invitation_req(p2p, mgmt->sa, + data + 1, + data_len - 1, freq); + if (!resp) + p2p_dbg(p2p, "No Invitation Response found"); + + dev->role = P2P_ROLE_PAIRING_RESPONDER; + p2p_pasn_initialize(p2p, dev, mgmt->sa, freq, true); + wpabuf_free(dev->action_frame_wrapper); + dev->action_frame_wrapper = resp; + } else if (data && data_len >= 1 && data[0] == P2P_GO_NEG_REQ) { + struct wpabuf *resp; + + resp = p2p_process_go_neg_req(p2p, mgmt->sa, data + 1, + data_len - 1, freq, true); + if (!resp) + p2p_dbg(p2p, + "No GO Negotiation Response found"); + wpabuf_free(dev->action_frame_wrapper); + dev->action_frame_wrapper = resp; + } else { + p2p_dbg(p2p, "Invalid action frame wrapper in Auth1"); + } + } else if (trans_seq == 2) { + if (data && data_len >= 1 && data[0] == P2P_INVITATION_RESP) { + p2p_process_invitation_resp(p2p, mgmt->sa, data + 1, + data_len - 1); + wpabuf_free(dev->action_frame_wrapper); + dev->action_frame_wrapper = NULL; + } else if (data && data_len >= 1 && + data[0] == P2P_GO_NEG_RESP) { + struct wpabuf *conf; + + conf = p2p_process_go_neg_resp(p2p, mgmt->sa, data + 1, + data_len - 1, freq, + true); + if (!conf) + p2p_dbg(p2p, "No GO Negotiation Confirm found"); + wpabuf_free(dev->action_frame_wrapper); + dev->action_frame_wrapper = conf; + } else { + p2p_dbg(p2p, "Invalid action frame wrapper in Auth2"); + } + } else if (trans_seq == 3) { + if (data && data_len >= 1 && data[0] == P2P_GO_NEG_CONF) + 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_parse_free(&msg); + return 0; +} + + +static int p2p_pasn_add_encrypted_data(struct p2p_data *p2p, + struct p2p_device *dev, + struct wpabuf *buf) +{ + struct pasn_data *pasn; + struct wpabuf *p2p2_ie; + u8 *dika_len, *p2p2_ie_len; + int ret; + + if (!p2p || !dev || !dev->pasn) + return 0; + + pasn = dev->pasn; + + if (dev->req_bootstrap_method != P2P_PBMA_OPPORTUNISTIC && + !p2p->pairing_info->enable_pairing_cache) + return 0; + + p2p2_ie = wpabuf_alloc(100); + if (!p2p2_ie) + return -1; + + p2p2_ie_len = p2p_buf_add_p2p2_ie_hdr(p2p2_ie); + + if (p2p->pairing_info->enable_pairing_cache) { + wpabuf_put_u8(p2p2_ie, P2P_ATTR_DEVICE_IDENTITY_KEY); + dika_len = wpabuf_put(p2p2_ie, 2); + + wpabuf_put_u8(p2p2_ie, + p2p->pairing_info->dev_ik.cipher_version); + wpabuf_put_data(p2p2_ie, p2p->pairing_info->dev_ik.dik_data, + p2p->pairing_info->dev_ik.dik_len); + wpabuf_put_be32(p2p2_ie, p2p->pairing_info->dev_ik.expiration); + + WPA_PUT_LE16(dika_len, + (u8 *) wpabuf_put(p2p2_ie, 0) - dika_len - 2); + } + + p2p_buf_update_ie_hdr(p2p2_ie, p2p2_ie_len); + + ret = pasn_add_encrypted_data(pasn, buf, wpabuf_mhead_u8(p2p2_ie), + wpabuf_len(p2p2_ie)); + wpabuf_free(p2p2_ie); + return ret; +} + + +int p2p_prepare_data_element(struct p2p_data *p2p, const u8 *peer_addr) +{ + int ret = -1; + struct p2p_device *dev; + struct pasn_data *pasn; + struct wpabuf *extra_ies; + + if (!p2p) + return -1; + + dev = p2p_get_device(p2p, peer_addr); + if (!dev || !dev->pasn) { + p2p_dbg(p2p, "PASN: Peer not found " MACSTR, + MAC2STR(peer_addr)); + return -1; + } + pasn = dev->pasn; + + extra_ies = wpabuf_alloc(1500); + if (!extra_ies || + p2p_prepare_pasn_extra_ie(p2p, extra_ies, + dev->action_frame_wrapper)) { + p2p_dbg(p2p, "Failed to prepare PASN extra elements"); + goto out; + } + + if (p2p_pasn_add_encrypted_data(p2p, dev, extra_ies) < 0) + goto out; + + pasn->extra_ies = os_memdup(wpabuf_head_u8(extra_ies), + wpabuf_len(extra_ies)); + if (!pasn->extra_ies) + goto out; + pasn->extra_ies_len = wpabuf_len(extra_ies); + ret = 0; + +out: + wpabuf_free(extra_ies); + wpabuf_free(dev->action_frame_wrapper); + dev->action_frame_wrapper = NULL; + + return ret; +} + + +static int p2p_handle_pasn_auth(struct p2p_data *p2p, struct p2p_device *dev, + const struct ieee80211_mgmt *mgmt, size_t len, + int freq) +{ + struct pasn_data *pasn; + u8 pasn_type; + int pasn_groups[4] = { 0 }; + u16 auth_alg, auth_transaction, status_code; + + if (!p2p || !dev || !dev->pasn) + return -1; + + if (os_memcmp(mgmt->da, p2p->cfg->dev_addr, ETH_ALEN) != 0) { + p2p_dbg(p2p, "PASN Responder: Not our frame"); + return -1; + } + + if (len < offsetof(struct ieee80211_mgmt, u.auth.variable)) + return -1; + + pasn = dev->pasn; + auth_alg = le_to_host16(mgmt->u.auth.auth_alg); + status_code = le_to_host16(mgmt->u.auth.status_code); + + auth_transaction = le_to_host16(mgmt->u.auth.auth_transaction); + + if (status_code != WLAN_STATUS_SUCCESS && + status_code != WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY) { + p2p_dbg(p2p, "PASN: Authentication rejected - status=%u", + status_code); + return -1; + } + + if (auth_alg != WLAN_AUTH_PASN || auth_transaction == 2) { + p2p_dbg(p2p, + "PASN Responder: Not a PASN frame or unexpected Authentication frame, auth_alg=%d", + auth_alg); + return -1; + } + if (auth_transaction == 1) { + pasn_type = p2p->cfg->pairing_config.pasn_type; + if (pasn_type & 0xc && pasn_type & 0x3) { + pasn_groups[0] = 20; + pasn_groups[1] = 19; + } else if (pasn_type & 0xc) { + pasn_groups[0] = 20; + } else { + pasn_groups[0] = 19; + } + pasn->pasn_groups = pasn_groups; + + if (p2p_pasn_handle_action_wrapper(p2p, dev, mgmt, len, freq, + auth_transaction)) { + p2p_dbg(p2p, + "PASN Responder: Handle Auth 1 action wrapper failed"); + return -1; + } + if (handle_auth_pasn_1(pasn, p2p->cfg->dev_addr, mgmt->sa, mgmt, + len, false) < 0) { + p2p_dbg(p2p, + "PASN Responder: Handle Auth 1 failed"); + return -1; + } + } else if (auth_transaction == 3) { + if (handle_auth_pasn_3(pasn, p2p->cfg->dev_addr, mgmt->sa, mgmt, + len) < 0) { + p2p_dbg(p2p, + "PASN Responder: Handle Auth 3 failed"); + return -1; + } + if (p2p_pasn_handle_action_wrapper(p2p, dev, mgmt, len, freq, + auth_transaction)) { + p2p_dbg(p2p, + "PASN Responder: Handle Auth 3 action wrapper failed"); + return -1; + } + forced_memzero(pasn_get_ptk(pasn), sizeof(pasn->ptk)); + } + return 0; +} + + int p2p_pasn_auth_rx(struct p2p_data *p2p, const struct ieee80211_mgmt *mgmt, size_t len, int freq) { - return -1; /* TODO */ + int ret = 0; + u8 auth_transaction; + struct p2p_device *dev; + struct pasn_data *pasn; + struct wpa_pasn_params_data pasn_data; + + dev = p2p_get_device(p2p, mgmt->sa); + if (!dev) { + p2p_dbg(p2p, "PASN: Peer not found " MACSTR, + MAC2STR(mgmt->sa)); + return -1; + } + + if (!dev->pasn) { + p2p_dbg(p2p, "PASN: Uninitialized"); + return -1; + } + + pasn = dev->pasn; + + wpabuf_free(pasn->frame); + pasn->frame = NULL; + + auth_transaction = le_to_host16(mgmt->u.auth.auth_transaction); + + if (dev->role == P2P_ROLE_PAIRING_INITIATOR && auth_transaction == 2) { + if (p2p_pasn_handle_action_wrapper(p2p, dev, mgmt, len, freq, + auth_transaction)) { + p2p_dbg(p2p, + "PASN Initiator: Handle Auth 2 action wrapper failed"); + return -1; + } + ret = wpa_pasn_auth_rx(pasn, (const u8 *) mgmt, len, + &pasn_data); + forced_memzero(pasn_get_ptk(pasn), sizeof(pasn->ptk)); + + if (ret < 0) { + p2p_dbg(p2p, "PASN: wpa_pasn_auth_rx() failed"); + dev->role = P2P_ROLE_IDLE; + } + } else { + ret = p2p_handle_pasn_auth(p2p, dev, mgmt, len, freq); + } + return ret; } + #endif /* CONFIG_PASN */ diff --git a/src/p2p/p2p.h b/src/p2p/p2p.h index 56a8f9e5f..480515f16 100644 --- a/src/p2p/p2p.h +++ b/src/p2p/p2p.h @@ -2576,7 +2576,9 @@ int p2p_channel_to_freq(int op_class, int channel); struct wpabuf * p2p_usd_elems(struct p2p_data *p2p); void p2p_process_usd_elems(struct p2p_data *p2p, const u8 *ies, u16 ies_len, const u8 *peer_addr, unsigned int freq); +int p2p_initiate_pasn_auth(struct p2p_data *p2p, const u8 *addr, int freq); int p2p_pasn_auth_rx(struct p2p_data *p2p, const struct ieee80211_mgmt *mgmt, size_t len, int freq); +int p2p_prepare_data_element(struct p2p_data *p2p, const u8 *peer_addr); #endif /* P2P_H */ diff --git a/src/p2p/p2p_i.h b/src/p2p/p2p_i.h index 3bde27e9c..d7dfba825 100644 --- a/src/p2p/p2p_i.h +++ b/src/p2p/p2p_i.h @@ -36,6 +36,13 @@ enum p2p_go_state { REMOTE_GO }; +/* Enumeration for P2P device current role */ +enum p2p_role { + P2P_ROLE_IDLE = 0, + P2P_ROLE_PAIRING_INITIATOR, + P2P_ROLE_PAIRING_RESPONDER, +}; + /** * struct bootstrap_params - P2P Device bootstrap request parameters */ @@ -182,6 +189,13 @@ struct p2p_device { /* Password for P2P2 GO negotiation */ char password[100]; + + /* PASN data structure */ + struct pasn_data *pasn; + struct wpabuf *action_frame_wrapper; + + /* Device role */ + enum p2p_role role; }; struct p2p_sd_query { @@ -1012,6 +1026,8 @@ void p2p_pref_channel_filter(const struct p2p_channels *a, struct p2p_channels *res, bool go); void p2p_sd_query_cb(struct p2p_data *p2p, int success); +void p2p_pasn_initialize(struct p2p_data *p2p, struct p2p_device *dev, + const u8 *addr, int freq, bool verify); void p2p_dbg(struct p2p_data *p2p, const char *fmt, ...) PRINTF_FORMAT(2, 3); diff --git a/src/p2p/p2p_pd.c b/src/p2p/p2p_pd.c index fb2031310..7581fbfde 100644 --- a/src/p2p/p2p_pd.c +++ b/src/p2p/p2p_pd.c @@ -849,6 +849,12 @@ static void p2p_process_prov_disc_bootstrap_req(struct p2p_data *p2p, wpa_printf(MSG_ERROR, "Bootstrap received %d", bootstrap); + if (status == P2P_SC_SUCCESS) { + dev->role = P2P_ROLE_PAIRING_RESPONDER; +#ifdef CONFIG_PASN + p2p_pasn_initialize(p2p, dev, sa, rx_freq, false); +#endif /* CONFIG_PASN */ + } out: /* Send PD Bootstrapping Response for the PD Request */ resp = p2p_build_prov_disc_bootstrap_resp(p2p, dev, msg->dialog_token,