From patchwork Mon Aug 5 09:33:14 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Shivani Baranwal X-Patchwork-Id: 1969087 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (2048-bit key; secure) header.d=lists.infradead.org header.i=@lists.infradead.org header.a=rsa-sha256 header.s=bombadil.20210309 header.b=ep/B8IpB; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=quicinc.com header.i=@quicinc.com header.a=rsa-sha256 header.s=qcppdkim1 header.b=aZ+l9yFg; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=none (no SPF record) smtp.mailfrom=lists.infradead.org (client-ip=2607:7c80:54:3::133; helo=bombadil.infradead.org; envelope-from=hostap-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; receiver=patchwork.ozlabs.org) Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2607:7c80:54:3::133]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4WczzZ0wX7z1yZl for ; Tue, 6 Aug 2024 00:56:42 +1000 (AEST) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-ID:Date:Subject:CC:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=RvA0WnqxT9qyMf4NPDwESHwKkkCeI9ZTmzAMPxJ87GU=; b=ep/B8IpBwNZstT 3b7ZZ/bTo2CXD/tqBCiI6gA4zNvejEGfIGMPGGZx0d0/0wiDQxGVWyNNaqW0l6tU51X6CmtXLtGbU 613PZdTKjyBug1ZtaH3V9nDZwWdVy3k0+TbdEx8tvqdcXg9qeVIB5YkfoOthitWDSq/6h3e5A4tnr 6PgfTjpnZeDgdGTR3PutWQcetDW98fpwVNNz2osbXtef5EIKL9LlfatWb1YaoyM+wkvOgniSXkIjK vLn2RDQnvuAhFsEigyz0U/KYky3xKcZJ/Gmx/xv9wbs3NdyuOAN985+XnyX8MFxwFjzcBUfDNFvBn 5ZdM4VzRDh1cf/SdlqiA==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.97.1 #2 (Red Hat Linux)) id 1saz80-0000000GDcP-23AA; Mon, 05 Aug 2024 14:56:04 +0000 Received: from mx0a-0031df01.pphosted.com ([205.220.168.131]) by bombadil.infradead.org with esmtps (Exim 4.97.1 #2 (Red Hat Linux)) id 1sau6v-0000000FIrL-0QhZ for hostap@lists.infradead.org; Mon, 05 Aug 2024 09:35:01 +0000 Received: from pps.filterd (m0279863.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id 4752VW51019108 for ; Mon, 5 Aug 2024 09:34:36 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; h= cc:content-type:date:from:in-reply-to:message-id:mime-version :references:subject:to; s=qcppdkim1; bh=p8T3JnjSwxWn1bhnlG0jnqcm o7nT/kmM2dspeOBS8bA=; b=aZ+l9yFgaUq6/yBlLUPekFJ40ACytQ5J6jZxQOw9 rjcWULcmvNUQayrIp5HeykGKoAE2a6+zfm4jd5/4ZjSHgdgCaDikhvS3a1iTR7ZJ Fi1eaIkL0BPrr0qWfSfwDk3rN6kn2TTLyLDNVnLxYIllUE2Vgptxibr8Xk3WcdL3 cLsgrobCQrFX/uukSrWHbDuu24weztjuOYX//6/pWO+ZJzQVK2Ux7oA+awZdNGaj ywV2GeC/gzgLiV3Xjuk1ybTCnsKUZ/UI56qzZKEXPlvlfLHLm6PrcupwTirJ5QuD f1jigXyE42ZCSRj8rQnsBAWh0FIVVK9Q2Xd4UHYIh8oAUg== Received: from nalasppmta03.qualcomm.com (Global_NAT1.qualcomm.com [129.46.96.20]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 40scs2uef9-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT) for ; Mon, 05 Aug 2024 09:34:35 +0000 (GMT) Received: from nalasex01a.na.qualcomm.com (nalasex01a.na.qualcomm.com [10.47.209.196]) by NALASPPMTA03.qualcomm.com (8.17.1.19/8.17.1.19) with ESMTPS id 4759YZ8r028855 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT) for ; Mon, 5 Aug 2024 09:34:35 GMT Received: from hu-shivbara-hyd.qualcomm.com (10.80.80.8) by nalasex01a.na.qualcomm.com (10.47.209.196) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.9; Mon, 5 Aug 2024 02:34:33 -0700 From: Shivani Baranwal To: CC: Subject: [PATCH v3 16/25] P2P: Add support for GO negotiation wrapped in PASN auth frame Date: Mon, 5 Aug 2024 15:03:14 +0530 Message-ID: <1722850403-8852-17-git-send-email-quic_shivbara@quicinc.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1722850403-8852-1-git-send-email-quic_shivbara@quicinc.com> References: <1722850403-8852-1-git-send-email-quic_shivbara@quicinc.com> MIME-Version: 1.0 X-Originating-IP: [10.80.80.8] X-ClientProxiedBy: nasanex01b.na.qualcomm.com (10.46.141.250) To nalasex01a.na.qualcomm.com (10.47.209.196) X-QCInternal: smtphost X-Proofpoint-Virus-Version: vendor=nai engine=6200 definitions=5800 signatures=585085 X-Proofpoint-ORIG-GUID: fgbxU2YjLyJIM3M4VfDwW9fYj1X2rg2D X-Proofpoint-GUID: fgbxU2YjLyJIM3M4VfDwW9fYj1X2rg2D X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1039,Hydra:6.0.680,FMLib:17.12.28.16 definitions=2024-08-04_14,2024-08-02_01,2024-05-17_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 mlxscore=0 bulkscore=0 suspectscore=0 adultscore=0 spamscore=0 priorityscore=1501 impostorscore=0 lowpriorityscore=0 mlxlogscore=999 phishscore=0 malwarescore=0 clxscore=1015 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.19.0-2407110000 definitions=main-2408050067 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20240805_023437_926964_B0C77361 X-CRM114-Status: GOOD ( 26.36 ) X-Spam-Score: -2.1 (--) X-Spam-Report: Spam detection software, running on the system "bombadil.infradead.org", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: Add P2P2 support for GO negotiation wrapped in PASN authentication frames as a action wrapper attribute. Signed-off-by: Shivani Baranwal --- src/ap/ieee802_11.c | 16 +- src/common/ieee802_11_common.c | 4 + src/common/ieee802_11_common.h | 2 + src/common/ieee802_11_defs.h | 2 + [...] Content analysis details: (-2.1 points, 5.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- 0.0 RCVD_IN_VALIDITY_SAFE_BLOCKED RBL: ADMINISTRATOR NOTICE: The query to Validity was blocked. See https://knowledge.validity.com/hc/en-us/articles/20961730681243 for more information. [205.220.168.131 listed in sa-accredit.habeas.com] 0.0 RCVD_IN_VALIDITY_CERTIFIED_BLOCKED RBL: ADMINISTRATOR NOTICE: The query to Validity was blocked. See https://knowledge.validity.com/hc/en-us/articles/20961730681243 for more information. [205.220.168.131 listed in sa-trusted.bondedsender.org] 0.0 RCVD_IN_VALIDITY_RPBL_BLOCKED RBL: ADMINISTRATOR NOTICE: The query to Validity was blocked. See https://knowledge.validity.com/hc/en-us/articles/20961730681243 for more information. [205.220.168.131 listed in bl.score.senderscore.com] -0.0 SPF_PASS SPF: sender matches SPF record 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from envelope-from domain -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] X-Mailman-Approved-At: Mon, 05 Aug 2024 07:55:43 -0700 X-BeenThere: hostap@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "Hostap" Errors-To: hostap-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org Add P2P2 support for GO negotiation wrapped in PASN authentication frames as a action wrapper attribute. Signed-off-by: Shivani Baranwal --- src/ap/ieee802_11.c | 16 +- src/common/ieee802_11_common.c | 4 + src/common/ieee802_11_common.h | 2 + src/common/ieee802_11_defs.h | 2 + src/p2p/p2p.c | 808 +++++++++++++++++++++++++++++++++++++- src/p2p/p2p.h | 85 ++++ src/p2p/p2p_go_neg.c | 4 +- src/p2p/p2p_i.h | 27 ++ src/p2p/p2p_parse.c | 20 + src/p2p/p2p_pd.c | 6 + src/pasn/pasn_common.h | 7 + src/pasn/pasn_initiator.c | 50 ++- src/pasn/pasn_responder.c | 20 +- wpa_supplicant/events.c | 56 ++- wpa_supplicant/p2p_supplicant.c | 161 +++++++- wpa_supplicant/p2p_supplicant.h | 11 +- wpa_supplicant/pasn_supplicant.c | 5 + wpa_supplicant/wpa_supplicant_i.h | 5 + 18 files changed, 1260 insertions(+), 29 deletions(-) diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c index 38fcba5..3c5a8dd 100644 --- a/src/ap/ieee802_11.c +++ b/src/ap/ieee802_11.c @@ -2487,6 +2487,10 @@ static void pasn_fils_auth_resp(struct hostapd_data *hapd, fils->erp_resp = erp_resp; ret = handle_auth_pasn_resp(sta->pasn, hapd->own_addr, sta->addr, NULL, WLAN_STATUS_SUCCESS); + if (sta->pasn->frame) { + wpabuf_free(sta->pasn->frame); + sta->pasn->frame = NULL; + } fils->erp_resp = NULL; if (ret) { @@ -2800,6 +2804,8 @@ static void handle_auth_pasn(struct hostapd_data *hapd, struct sta_info *sta, const struct ieee80211_mgmt *mgmt, size_t len, u16 trans_seq, u16 status) { + int ret; + if (hapd->conf->wpa != WPA_PROTO_RSN) { wpa_printf(MSG_INFO, "PASN: RSN is not configured"); return; @@ -2831,9 +2837,15 @@ static void handle_auth_pasn(struct hostapd_data *hapd, struct sta_info *sta, hapd_initialize_pasn(hapd, sta); hapd_pasn_update_params(hapd, sta, mgmt, len); - if (handle_auth_pasn_1(sta->pasn, hapd->own_addr, - sta->addr, mgmt, len) < 0) + ret = handle_auth_pasn_1(sta->pasn, hapd->own_addr, sta->addr, + mgmt, len); + if (sta->pasn->frame) { + wpabuf_free(sta->pasn->frame); + sta->pasn->frame = NULL; + } + if (ret < 0) ap_free_sta(hapd, sta); + } else if (trans_seq == 3) { if (!sta->pasn) { wpa_printf(MSG_DEBUG, diff --git a/src/common/ieee802_11_common.c b/src/common/ieee802_11_common.c index 2d4540b..b16564d 100644 --- a/src/common/ieee802_11_common.c +++ b/src/common/ieee802_11_common.c @@ -413,6 +413,10 @@ static int ieee802_11_parse_extension(const u8 *pos, size_t elen, elems->mbssid_known_bss = pos; elems->mbssid_known_bss_len = elen; break; + case WLAN_EID_EXT_PASN_ENCRYPTED_ELEMENT: + elems->pasn_encrypted_ie = pos; + elems->pasn_encrypted_ie_len = elen; + break; default: if (show_errors) { wpa_printf(MSG_MSGDUMP, diff --git a/src/common/ieee802_11_common.h b/src/common/ieee802_11_common.h index e4321b5..7ca99f3 100644 --- a/src/common/ieee802_11_common.h +++ b/src/common/ieee802_11_common.h @@ -66,6 +66,7 @@ struct ieee802_11_elems { const u8 *vendor_vht; const u8 *p2p; const u8 *p2p2_ie; + const u8 *pasn_encrypted_ie; const u8 *wfd; const u8 *link_id; const u8 *interworking; @@ -141,6 +142,7 @@ struct ieee802_11_elems { u8 vendor_vht_len; u8 p2p_len; u8 p2p2_ie_len; + u8 pasn_encrypted_ie_len; u8 wfd_len; u8 interworking_len; u8 qos_map_set_len; diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h index 0e88797..db1033a 100644 --- a/src/common/ieee802_11_defs.h +++ b/src/common/ieee802_11_defs.h @@ -524,6 +524,7 @@ #define WLAN_EID_EXT_MULTI_LINK_TRAFFIC_INDICATION 110 #define WLAN_EID_EXT_QOS_CHARACTERISTICS 113 #define WLAN_EID_EXT_AKM_SUITE_SELECTOR 114 +#define WLAN_EID_EXT_PASN_ENCRYPTED_ELEMENT 140 /* Extended Capabilities field */ #define WLAN_EXT_CAPAB_20_40_COEX 0 @@ -616,6 +617,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 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 01490e2..6e2a97c 100644 --- a/src/p2p/p2p.c +++ b/src/p2p/p2p.c @@ -15,10 +15,14 @@ #include "common/ieee802_11_common.h" #include "common/wpa_ctrl.h" #include "crypto/sha256.h" +#include "crypto/sha384.h" #include "crypto/crypto.h" #include "wps/wps_i.h" #include "p2p_i.h" #include "p2p.h" +#include "common/sae.h" +#include "pasn/pasn_common.h" +#include "crypto/aes_wrap.h" static void p2p_state_timeout(void *eloop_ctx, void *timeout_ctx); @@ -242,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 +968,14 @@ static void p2p_device_free(struct p2p_data *p2p, struct p2p_device *dev) dev->bootstrap_params = NULL; } +#ifdef CONFIG_PASN + if (dev->pasn) { + wpa_pasn_reset(dev->pasn); + pasn_data_deinit(dev->pasn); + dev->pasn = NULL; + } +#endif /* CONFIG_PASN */ + wpabuf_free(dev->info.wfd_subelems); wpabuf_free(dev->info.vendor_elems); wpabuf_free(dev->go_neg_conf); @@ -1861,8 +1878,13 @@ void p2p_go_complete(struct p2p_data *p2p, struct p2p_device *peer) os_memset(&res, 0, sizeof(res)); res.role_go = go; + + if (is_zero_ether_addr(peer->interface_addr)) + os_memcpy(peer->interface_addr, peer->intended_addr, ETH_ALEN); + os_memcpy(res.peer_device_addr, peer->info.p2p_device_addr, ETH_ALEN); - os_memcpy(res.peer_interface_addr, peer->intended_addr, ETH_ALEN); + os_memcpy(res.peer_interface_addr, peer->interface_addr, ETH_ALEN); + res.wps_method = peer->wps_method; if (peer->flags & P2P_DEV_PREFER_PERSISTENT_GROUP) { if (peer->flags & P2P_DEV_PREFER_PERSISTENT_RECONN) @@ -1911,6 +1933,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); } @@ -3012,7 +3039,18 @@ int p2p_pairing_info_init(struct p2p_data *p2p) os_memcpy(pairing_info->dev_ik.dik_data, p2p->cfg->pairing_config.dik_data, p2p->cfg->pairing_config.dik_len); + + if (!p2p->cfg->dev_password_len) { + p2p->cfg->dev_password_len = 10; + p2p_random(p2p->cfg->dev_password, p2p->cfg->dev_password_len); + p2p->cfg->dev_password[p2p->cfg->dev_password_len] = '\0'; + } + p2p->pairing_info = pairing_info; +#ifdef CONFIG_PASN + p2p->initiator_pmksa = pasn_initiator_pmksa_cache_init(); + p2p->responder_pmksa = pasn_responder_pmksa_cache_init(); +#endif /* CONFIG_PASN */ return 0; } @@ -3086,6 +3124,10 @@ struct p2p_data * p2p_init(const struct p2p_config *cfg) void p2p_pairing_info_deinit(struct p2p_data *p2p) { +#ifdef CONFIG_PASN + pasn_initiator_pmksa_cache_deinit(p2p->initiator_pmksa); + pasn_responder_pmksa_cache_deinit(p2p->responder_pmksa); +#endif /* CONFIG_PASN */ os_free(p2p->pairing_info); } @@ -4975,8 +5017,11 @@ int p2p_get_interface_addr(struct p2p_data *p2p, const u8 *dev_addr, u8 *iface_addr) { struct p2p_device *dev = p2p_get_device(p2p, dev_addr); - if (dev == NULL || is_zero_ether_addr(dev->interface_addr)) + if (dev == NULL || is_zero_ether_addr(dev->interface_addr)) { + wpa_printf(MSG_DEBUG, "P2P: Failed to get interface addr from dev addr " + MACSTR, MAC2STR(dev_addr)); return -1; + } os_memcpy(iface_addr, dev->interface_addr, ETH_ALEN); return 0; } @@ -4986,8 +5031,11 @@ int p2p_get_dev_addr(struct p2p_data *p2p, const u8 *iface_addr, u8 *dev_addr) { struct p2p_device *dev = p2p_get_device_interface(p2p, iface_addr); - if (dev == NULL) + if (!dev) { + wpa_printf(MSG_DEBUG, "P2P: Failed to get device addr from iface addr " + MACSTR, MAC2STR(iface_addr)); return -1; + } os_memcpy(dev_addr, dev->info.p2p_device_addr, ETH_ALEN); return 0; } @@ -5862,3 +5910,757 @@ void p2p_process_usd_elems(struct p2p_data *p2p, const u8 *ies, u16 ies_len, p2p_parse_free(&msg); } + +#ifdef CONFIG_PASN +int p2p_prepare_pasn_extra_ie(struct p2p_data *p2p, struct wpabuf *extra_ies, + struct wpabuf *frame) +{ + struct wpabuf *buf, *buf2; + + buf = wpabuf_alloc(1500); + if (!buf) { + p2p_dbg(p2p, "Mem alloc failed for buf"); + return -1; + } + + /* P2P Capability Extension attribute */ + p2p_buf_add_pcea(buf, p2p); + + if (frame) { + p2p_dbg(p2p, "P2P: Added Action frame wrapper"); + wpabuf_put_u8(buf, P2P_ATTR_ACTION_FRAME_WRAPPER); + wpabuf_put_le16(buf, wpabuf_len(frame)); + wpabuf_put_buf(buf, frame); + } + + buf2 = p2p_encaps_p2p_vendor_ie(p2p, buf, P2P2_IE_VENDOR_TYPE); + wpabuf_free(buf); + + wpabuf_put_buf(extra_ies, buf2); + wpabuf_free(buf2); + + return 0; +} + +struct wpabuf *p2p_pairing_generate_rsnxe(int akmp) +{ + u32 capab; + size_t flen = 0; + struct wpabuf *buf; + + capab = BIT(WLAN_RSNX_CAPAB_KEK); + + if (akmp == WPA_KEY_MGMT_SAE) + capab |= BIT(WLAN_RSNX_CAPAB_SAE_H2E); + + while (capab >> flen * 8) + flen++; + + buf = wpabuf_alloc(2 + flen); + if (!buf) { + wpa_printf(MSG_ERROR, "Memory allocation failed"); + return NULL; + } + + if (wpabuf_tailroom(buf) < 2 + flen) { + wpa_printf(MSG_ERROR, "wpabuf tail room small"); + wpabuf_free(buf); + return NULL; + } + capab |= flen - 1; /* bit 0-3 = Field length (n - 1) */ + + wpa_printf(MSG_DEBUG, "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; +} + +/* sae password id to derive pt */ +#define P2P_PAIRING_SSID "516F9A020000" + +void p2p_pairing_set_password(struct pasn_data *pasn, const char *passphrase, + u32 len) +{ + const u8 *pairing_ssid; + size_t pairing_ssid_len; + + if (!passphrase) { + wpa_printf(MSG_ERROR, "p2p pairing password NULL"); + return; + } + + pairing_ssid = (const u8 *)(P2P_PAIRING_SSID); + pairing_ssid_len = strlen(P2P_PAIRING_SSID); + pasn->pt = sae_derive_pt(pasn->pasn_groups, pairing_ssid, + pairing_ssid_len, (const u8 *)passphrase, len, + NULL); + /* Set passpharse for Pairing Responder to validate PASN auth1 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(); + + pasn = dev->pasn; + + os_memcpy(pasn->own_addr, p2p->cfg->dev_addr, ETH_ALEN); + os_memcpy(pasn->peer_addr, addr, ETH_ALEN); + + if (dev->role == P2P_ROLE_PAIRING_INITIATOR) + memcpy(pasn->bssid, pasn->peer_addr, ETH_ALEN); + else + memcpy(pasn->bssid, 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 = WPA_KEK_256; + pasn->pasn_groups = p2p->cfg->pairing_config.pasn_groups; + } else { + pasn->group = 19; + pasn->cipher = WPA_CIPHER_CCMP; + pasn->kek_len = WPA_KEK_128; + } + + if (dev->password_len) { + pasn->akmp = WPA_KEY_MGMT_SAE; + p2p_pairing_set_password(pasn, dev->password, + dev->password_len); + 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(pasn->akmp); + if (rsnxe) { + pasn->rsnxe_ie = os_zalloc(wpabuf_len(rsnxe)); + if (!pasn->rsnxe_ie) { + p2p_dbg(p2p, "Mem alloc failed for pasn rsnxe ie"); + wpabuf_free(rsnxe); + return; + } + os_memcpy((u8 *)pasn->rsnxe_ie, wpabuf_head_u8(rsnxe), + wpabuf_len(rsnxe)); + pasn->rsnxe_ie_len = wpabuf_len(rsnxe); + wpabuf_free(rsnxe); + } + + if (dev->role == P2P_ROLE_PAIRING_INITIATOR) + pasn->pmksa = p2p->initiator_pmksa; + else + pasn->pmksa = p2p->responder_pmksa; + + pasn->cb_ctx = p2p->cfg->cb_ctx; + pasn->send_mgmt = p2p->cfg->pasn_send_mgmt; + pasn->update_extra_ies = p2p->cfg->pasn_update_extra_ies; + pasn->parse_encrypted_data = p2p->cfg->pasn_parse_encrypted_data; + + 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; + int ret = 0; + + 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); + + /* FIXME: Added to resolve listen freq issue resulting in GO Neg no + * common channel failure + */ + p2p->cfg->reg_class = p2p->op_reg_class; + p2p->cfg->channel = p2p->op_channel; + + 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); + 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 Auth */ + 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, "p2p pasn start failed"); + ret = -1; + } +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_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 auth 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[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 Auth %d", + trans_seq); + p2p_parse_free(&msg); + return -1; + } + } + + if (trans_seq == 1) { + if (data && data[0] == P2P_INVITATION_REQ) { + p2p_process_invitation_req(p2p, mgmt->sa, data + 1, + 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, true); + 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, + data_len - 1, freq, true); + if (!p2p->go_neg_resp) + p2p_dbg(p2p, "No GO Neg Response found"); + dev->pasn->action_frame_wrapper = p2p->go_neg_resp; + } else { + p2p_dbg(p2p, "Invalid action frame wrapper in Auth1"); + } + } else if (trans_seq == 2) { + if (data && data[0] == P2P_INVITATION_RESP) { + p2p_process_invitation_resp(p2p, mgmt->sa, data + 1, + data_len - 1); + dev->pasn->action_frame_wrapper = NULL; + } else if (data && data[0] == P2P_GO_NEG_RESP) { + p2p_process_go_neg_resp(p2p, mgmt->sa, data + 1, + data_len - 1, freq, true); + if (!p2p->go_neg_conf) + p2p_dbg(p2p, "No GO Neg confirm found"); + dev->pasn->action_frame_wrapper = p2p->go_neg_conf; + /* FIXME: If go neg resp is with failure status, + how go_neg_failed is indicated to host */ + } else { + p2p_dbg(p2p, "Invalid action frame wrapper in Auth2"); + } + } else if (trans_seq == 3) { + if (data && 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 void p2p_pasn_add_encrypted_element(struct p2p_data *p2p, + struct p2p_device *dev, + struct wpabuf *buf) +{ + int ret; + struct pasn_data *pasn; + struct wpabuf *p2p2_ie; + u8 *len, *dika_len, *p2p2_ie_len; + u8 *pos, *key_data, *encrypted_data; + u16 key_data_len, pad_len = 0; + + if (!p2p || !dev || !dev->pasn) + return; + + pasn = dev->pasn; + + if (dev->req_bootstrap_method != P2P_PBMA_OPPORTUNISTIC && + !p2p->pairing_info->enable_pairing_cache) + return; + + p2p2_ie = wpabuf_alloc(100); + if (!p2p2_ie) { + p2p_dbg(p2p, "Mem alloc failed for p2p2 IE"); + return; + } + + 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, DIRA_CIPHER_VERSION_128); + 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); + } + + if (dev->req_bootstrap_method == P2P_PBMA_OPPORTUNISTIC && + p2p->cfg->dev_password_len) { + wpabuf_put_u8(p2p2_ie, P2P_ATTR_PASSWORD); + wpabuf_put_le16(p2p2_ie, p2p->cfg->dev_password_len); + wpabuf_put_data(p2p2_ie, p2p->cfg->dev_password, + p2p->cfg->dev_password_len); + } + + p2p_buf_update_p2p2_ie_hdr(p2p2_ie, p2p2_ie_len); + + key_data = (u8 *)wpabuf_head(p2p2_ie); + key_data_len = wpabuf_len(p2p2_ie); + + pad_len = key_data_len % 8; + + if (pad_len) { + pad_len = 8 - pad_len; + pos = key_data + key_data_len; + *pos++ = 0xdd; + } + key_data_len += pad_len + 8; + + encrypted_data = os_malloc(key_data_len); + if (!encrypted_data) { + p2p_dbg(p2p, "P2P PASN: Mem alloc failed for encrypted data"); + wpabuf_free(p2p2_ie); + return; + } + ret = aes_wrap(pasn->ptk.kek, pasn->ptk.kek_len, + (key_data_len - 8) / 8, key_data, encrypted_data); + if (ret) { + p2p_dbg(p2p, "P2P PASN: AES upwrap failed, ret=%d", ret); + goto out; + } + + wpabuf_put_u8(buf, WLAN_EID_EXTENSION); + len = wpabuf_put(buf, 1); + + wpabuf_put_u8(buf, WLAN_EID_EXT_PASN_ENCRYPTED_ELEMENT); + + wpabuf_put_data(buf, encrypted_data, key_data_len); + *len = (u8 *)wpabuf_put(buf, 0) - len - 1; + +out: + os_free(encrypted_data); + wpabuf_free(p2p2_ie); +} + + +int p2p_pasn_update_extra_ies(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, (u8 *)peer_addr); + if (!dev || !dev->pasn) { + p2p_dbg(p2p, "P2P PASN: Peer not found" MACSTR, + MAC2STR(peer_addr)); + return -1; + } + pasn = dev->pasn; + + extra_ies = wpabuf_alloc(1500); + if (!extra_ies) { + p2p_dbg(p2p, "Mem alloc failed for extra ies"); + goto out; + } + + if (p2p_prepare_pasn_extra_ie(p2p, extra_ies, + pasn->action_frame_wrapper)) { + p2p_dbg(p2p, "prepare pasn extra ies failed"); + goto out; + } + + p2p_pasn_add_encrypted_element(p2p, dev, extra_ies); + + pasn->extra_ies = os_zalloc(wpabuf_len(extra_ies)); + if (!pasn->extra_ies) { + p2p_dbg(p2p, "Mem alloc failed for pasn extra ies"); + 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); + ret = 0; + +out: + wpabuf_free(extra_ies); + wpabuf_free(pasn->action_frame_wrapper); + pasn->action_frame_wrapper = NULL; + + return ret; +} + + +int p2p_pasn_parse_encrypted_data(struct p2p_data *p2p, const u8 *data, + size_t len) +{ + int ret = -1; + u8 attr_id; + u8 *buf, *pos; + u16 rem_len, attr_len; + struct p2p_device *dev; + struct pasn_data *pasn; + struct ieee802_11_elems elems; + const struct ieee80211_mgmt *mgmt = + (const struct ieee80211_mgmt *) data; + + if (!p2p) + return -1; + + dev = p2p_get_device(p2p, (u8 *)mgmt->sa); + if (!dev || !dev->pasn) { + p2p_dbg(p2p, "P2P PASN: Peer not found" MACSTR, + MAC2STR(mgmt->sa)); + return -1; + } + + if (ieee802_11_parse_elems(mgmt->u.auth.variable, + len - offsetof(struct ieee80211_mgmt, + u.auth.variable), + &elems, 0) == ParseFailed) { + p2p_dbg(p2p, "P2P PASN: Failed parsing Authentication frame"); + return -1; + } + + if (!elems.pasn_encrypted_ie || !elems.pasn_encrypted_ie_len) { + p2p_dbg(p2p, "P2P PASN: No encrypted IEs"); + return 0; + } + + pasn = dev->pasn; + rem_len = elems.pasn_encrypted_ie_len; + + buf = os_zalloc(rem_len); + if (!buf) { + p2p_dbg(p2p, "Mem alloc failed for buf"); + return -1; + } + + ret = aes_unwrap(pasn->ptk.kek, pasn->ptk.kek_len, (rem_len - 8) / 8, + elems.pasn_encrypted_ie, buf); + if (ret) { + p2p_dbg(p2p, "P2P PASN: AES unwrap failed, ret=%d", ret); + goto done; + } + + pos = buf; + if (pos[0] != WLAN_EID_VENDOR_SPECIFIC || + WPA_GET_BE32(&pos[2]) != P2P2_IE_VENDOR_TYPE) { + p2p_dbg(p2p, "P2P PASN: P2P2 IE not present"); + goto done; + } + + pos += 6; + rem_len -= 6; + + while (rem_len > 2) { + attr_id = *pos++; + attr_len = WPA_GET_LE16(pos); + + pos += 2; + rem_len -= 3; + switch (attr_id) { + case P2P_ATTR_DEVICE_IDENTITY_KEY: + if (rem_len < 13) { + p2p_dbg(p2p, "P2P PASN: Invalid rem len %d", rem_len); + goto done; + } + dev->info.dik_cipher_version = *pos++; + rem_len--; + if (dev->info.dik_cipher_version == 0) { + memcpy(dev->info.dik_data, pos, 16); + dev->info.dik_len = 16; + pos += 16; + rem_len -= 16; + } else { + p2p_dbg(p2p, "P2P PASN: Invalid cipher"); + goto done; + } + dev->info.dik_lifetime = WPA_GET_BE32(pos); + pos += 4; + rem_len -= 4; + break; + case P2P_ATTR_PASSWORD: + if (rem_len < 1) { + p2p_dbg(p2p, "P2P PASN: Invalid rem len %d", rem_len); + goto done; + } + dev->info.password_len = attr_len; + memset(dev->info.password, 0, + sizeof(dev->info.password)); + memcpy(dev->info.password, pos, attr_len); + break; + default: + p2p_dbg(p2p, "Invalid Attr ID: %d", attr_id); + break; + } + } + ret = 0; +done: + os_free(buf); + return ret; +} + +int p2p_pasn_auth_tx_status(struct p2p_data *p2p, const u8 *data, + size_t data_len, u8 acked) +{ + int ret = 0; + struct p2p_device *dev; + struct pasn_data *pasn; + const struct ieee80211_mgmt *mgmt = + (const struct ieee80211_mgmt *) data; + + if (!p2p) + return -1; + + dev = p2p_get_device(p2p, (u8 *)mgmt->da); + if (!dev || !dev->pasn) { + p2p_dbg(p2p, "P2P PASN: Peer not found" MACSTR, + MAC2STR(mgmt->da)); + return -1; + } + + pasn = dev->pasn; + + ret = wpa_pasn_auth_tx_status(pasn, data, data_len, acked); + if (ret != 1 && acked == 0 && pasn->frame) { + return pasn->send_mgmt(pasn->cb_ctx, wpabuf_head(pasn->frame), + wpabuf_len(pasn->frame), 0, pasn->freq, + 1000); + } else if (pasn->frame) { + wpabuf_free(pasn->frame); + pasn->frame = NULL; + } + + if (ret != 1) + return ret; + + if (dev == p2p->go_neg_peer) + p2p_go_complete(p2p, dev); + + return 0; +} + +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; + 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, "P2P PASN Responder: Not our frame"); + 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, "P2P PASN: Authentication rejected - status=%u", + status_code); + return -1; + } + + if (auth_alg != WLAN_AUTH_PASN || auth_transaction == 2) { + p2p_dbg(p2p, "P2P PASN Responder: Not PASN frame " + " or Unexpected auth frame, auth_alg = %d", + auth_alg); + return -1; + } + if (auth_transaction == 1) { + if (p2p_pasn_handle_action_wrapper(p2p, dev, mgmt, len, freq, + auth_transaction)) { + p2p_dbg(p2p, "P2P PASN Responder: Handle Auth1 action wrapper failed"); + return -1; + } + if (handle_auth_pasn_1(pasn, p2p->cfg->dev_addr, mgmt->sa, mgmt, + len) < 0) { + p2p_dbg(p2p, "P2P PASN Responder: Handle Auth1 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, "P2P PASN Responder: Handle PASN Auth3 failed"); + return -1; + } + if (p2p_pasn_handle_action_wrapper(p2p, dev, mgmt, len, freq, + auth_transaction)) { + p2p_dbg(p2p, "P2P PASN Responder: Handle Auth3 action wrapper failed"); + memset(dev->info.dik_data, 0, + sizeof(dev->info.dik_data)); + memset(dev->info.password, 0, + sizeof(dev->info.password)); + dev->info.password_len = 0; + 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) +{ + 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, (u8 *)mgmt->sa); + if (!dev) { + p2p_dbg(p2p, "P2P PASN: Peer not found" MACSTR, + MAC2STR(mgmt->sa)); + return -1; + } + + if (!dev->pasn) { + p2p_dbg(p2p, "P2P PASN: uninitialized"); + return -1; + } + + pasn = dev->pasn; + + if (pasn->frame) { + wpabuf_free(pasn->frame); + pasn->frame = NULL; + } + + pasn_register_callbacks(pasn, p2p->cfg->cb_ctx, + p2p->cfg->pasn_send_mgmt, 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, "P2P PASN Initiator: Handle Auth2 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, "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 diff --git a/src/p2p/p2p.h b/src/p2p/p2p.h index c9bc12f..1b1c19f 100644 --- a/src/p2p/p2p.h +++ b/src/p2p/p2p.h @@ -372,6 +372,11 @@ struct p2p_pairing_config { /* length of DevIK */ size_t dik_len; + + /** + * The set of supported PASN groups + */ + int pasn_groups[4]; }; @@ -479,6 +484,36 @@ struct p2p_peer_info { * p2p_pairing_config - P2P Pairing configuration */ struct p2p_pairing_config pairing_config; + + /** + * cipher version for Device Identity key generation + */ + u8 dik_cipher_version; + + /** + * Device Identity key which is unique for a device + */ + u8 dik_data[DEVICE_IDENTITY_KEY_MAX_LEN]; + + /** + * Device Identity key length + */ + u16 dik_len; + + /** + * Device Identity key lifetime + */ + u32 dik_lifetime; + + /** + * password used during group formation post opportunistic pasn auth + */ + char password[100]; + + /** + * password length. Non zero if valid + */ + u16 password_len; }; enum p2p_prov_disc_status { @@ -658,6 +693,16 @@ struct p2p_config { unsigned int passphrase_len; /** + * password used during group formation post opportunistic pasn auth + */ + char dev_password[100]; + + /** + * password length. Non zero if valid + */ + u16 dev_password_len; + + /** * p2p_pairing_config - P2P Pairing configuration */ struct p2p_pairing_config pairing_config; @@ -1269,6 +1314,38 @@ struct p2p_config { */ void (*bootstrap_completed)(void *ctx, const u8 *addr, int status, int freq); + + /** + * pasn_send_mgmt - Function handler to transmit a Management frame + * @ctx: Callback context from cb_ctx + * @data : Frame to transmit + * @data_len: Length of frame to transmit + * @noack : No ack flag + * @freq: Frequency in MHz for the channel on which to transmit + * @wait: How many milliseconds to wait for a response frame + * Returns: 0 on success, -1 on failure + */ + int (*pasn_send_mgmt)(void *ctx, const u8 *data, size_t data_len, + int noack, unsigned int freq, unsigned int wait); + + /** + * pasn_update_extra_ies - Function handler to update protocol specific + * IEs in pasn auth frames + * @ctx: Callback context from cb_ctx + * @peer_addr : peer mac address + * Returns: 0 on success, -1 on failure + */ + int (*pasn_update_extra_ies)(void *ctx, const u8 *peer_addr); + + /** + * pasn_parse_encrypted_data - Function handler to parse encrypted data + * with KEK received in pasn auth frames + * @ctx: Callback context from cb_ctx + * @data : data to be decrypted + * @len: length of encrypted data + * Returns: 0 on success, -1 on failure + */ + int (*pasn_parse_encrypted_data)(void *ctx, const u8 *data, size_t len); }; @@ -2571,4 +2648,12 @@ 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_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); #endif /* P2P_H */ diff --git a/src/p2p/p2p_go_neg.c b/src/p2p/p2p_go_neg.c index 5798018..1f6923d 100644 --- a/src/p2p/p2p_go_neg.c +++ b/src/p2p/p2p_go_neg.c @@ -135,8 +135,8 @@ static const char * p2p_wps_method_str(enum p2p_wps_method wps_method) } -static struct wpabuf * p2p_build_go_neg_req(struct p2p_data *p2p, - struct p2p_device *peer) +struct wpabuf * p2p_build_go_neg_req(struct p2p_data *p2p, + struct p2p_device *peer) { u8 group_capab; size_t extra = 0; diff --git a/src/p2p/p2p_i.h b/src/p2p/p2p_i.h index d7a5dc1..e0d2ee0 100644 --- a/src/p2p/p2p_i.h +++ b/src/p2p/p2p_i.h @@ -37,6 +37,13 @@ enum p2p_go_state { }; +/* 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 params */ @@ -188,6 +195,12 @@ struct p2p_device { * password length. Non zero if valid */ u16 password_len; + + /* pasn data structure */ + struct pasn_data *pasn; + + /* device role */ + enum p2p_role role; }; struct p2p_sd_query { @@ -630,6 +643,10 @@ struct p2p_data { bool allow_6ghz; struct p2p_pairing_info *pairing_info; + /*p2p pairing initiator pmksa cache list */ + struct rsn_pmksa_cache *initiator_pmksa; + /* p2p pairing responder pmksa cache list */ + struct rsn_pmksa_cache *responder_pmksa; /** * go_neg_resp - GO Negotiation Response frame */ @@ -761,6 +778,12 @@ struct p2p_message { const u8 *pbma_info; size_t pbma_info_len; + + const u8 *action_frame_wrapper; + size_t action_frame_wrapper_len; + + const u8 *dira; + size_t dira_len; }; @@ -919,6 +942,8 @@ void p2p_rx_gas_comeback_resp(struct p2p_data *p2p, const u8 *sa, int p2p_start_sd(struct p2p_data *p2p, struct p2p_device *dev); /* p2p_go_neg.c */ +struct wpabuf * p2p_build_go_neg_req(struct p2p_data *p2p, + struct p2p_device *peer); int p2p_peer_channels_check(struct p2p_data *p2p, struct p2p_channels *own, struct p2p_device *dev, const u8 *channel_list, size_t channel_list_len); @@ -1021,6 +1046,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_parse.c b/src/p2p/p2p_parse.c index a70e180..de2a43f 100644 --- a/src/p2p/p2p_parse.c +++ b/src/p2p/p2p_parse.c @@ -437,6 +437,26 @@ static int p2p_parse_attribute(u8 id, const u8 *data, u16 len, msg->pbma_info_len = len; wpa_printf(MSG_DEBUG, "P2P: * PBMA (length=%u)", len); break; + case P2P_ATTR_ACTION_FRAME_WRAPPER: + if (len < 2) { + wpa_printf(MSG_DEBUG, "P2P: Too short Action frame (length %d)", + len); + return -1; + } + msg->action_frame_wrapper = data; + msg->action_frame_wrapper_len = len; + wpa_printf(MSG_DEBUG, "P2P: * Action frame wrapper (length=%u)", len); + break; + case P2P_ATTR_DEVICE_IDENTITY_RESOLUTION: + if (len < 2) { + wpa_printf(MSG_DEBUG, "P2P: Too short DIRA (length %d)", + len); + return -1; + } + msg->dira = data; + msg->dira_len = len; + wpa_printf(MSG_DEBUG, "P2P: * DIRA (length=%u)", len); + break; default: wpa_printf(MSG_DEBUG, "P2P: Skipped unknown attribute %d " "(length %d)", id, len); diff --git a/src/p2p/p2p_pd.c b/src/p2p/p2p_pd.c index 56022ff..f1856d2 100644 --- a/src/p2p/p2p_pd.c +++ b/src/p2p/p2p_pd.c @@ -824,6 +824,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 diff --git a/src/pasn/pasn_common.h b/src/pasn/pasn_common.h index e3ff746..8eb3bce 100644 --- a/src/pasn/pasn_common.h +++ b/src/pasn/pasn_common.h @@ -55,6 +55,7 @@ struct pasn_data { int rsn_pairwise; u16 rsnxe_capab; const u8 *rsnxe_ie; + size_t rsnxe_ie_len; bool custom_pmkid_valid; u8 custom_pmkid[PMKID_LEN]; @@ -130,6 +131,8 @@ struct pasn_data { struct os_reltime last_comeback_key_update; u16 comeback_idx; u16 *comeback_pending_idx; + struct wpabuf *action_frame_wrapper; + struct wpabuf *frame; /** * send_mgmt - Function handler to transmit a Management frame @@ -151,6 +154,10 @@ struct pasn_data { */ int (*validate_custom_pmkid)(void *ctx, const u8 *addr, const u8 *pmkid); + + int (*update_extra_ies)(void *ctx, const u8 *peer_addr); + + int (*parse_encrypted_data)(void *ctx, const u8 *data, size_t len); }; /* Initiator */ diff --git a/src/pasn/pasn_initiator.c b/src/pasn/pasn_initiator.c index dbcc91a..9d97895 100644 --- a/src/pasn/pasn_initiator.c +++ b/src/pasn/pasn_initiator.c @@ -646,7 +646,10 @@ static struct wpabuf * wpas_pasn_build_auth_1(struct pasn_data *pasn, if (wpa_pasn_add_wrapped_data(buf, wrapped_data_buf) < 0) goto fail; - wpa_pasn_add_rsnxe(buf, pasn->rsnxe_capab); + if (pasn->rsnxe_ie) + wpabuf_put_data(buf, pasn->rsnxe_ie, pasn->rsnxe_ie_len); + else + wpa_pasn_add_rsnxe(buf, pasn->rsnxe_capab); wpa_pasn_add_extra_ies(buf, pasn->extra_ies, pasn->extra_ies_len); @@ -675,11 +678,13 @@ fail: } -static struct wpabuf * wpas_pasn_build_auth_3(struct pasn_data *pasn) +static struct wpabuf * wpas_pasn_build_auth_3(struct pasn_data *pasn, + const u8 *mgmt, size_t len) { struct wpabuf *buf, *wrapped_data_buf = NULL; u8 mic[WPA_PASN_MAX_MIC_LEN]; - u8 mic_len, data_len; + u8 mic_len; + size_t data_len; const u8 *data; u8 *ptr; u8 wrapped_data; @@ -713,6 +718,11 @@ static struct wpabuf * wpas_pasn_build_auth_3(struct pasn_data *pasn) wpabuf_free(wrapped_data_buf); wrapped_data_buf = NULL; + if (pasn->update_extra_ies && pasn->cb_ctx) + pasn->update_extra_ies(pasn->cb_ctx, pasn->peer_addr); + + wpa_pasn_add_extra_ies(buf, pasn->extra_ies, pasn->extra_ies_len); + /* Add the MIC */ mic_len = pasn_mic_len(pasn->akmp, pasn->cipher); wpabuf_put_u8(buf, WLAN_EID_MIC); @@ -806,13 +816,25 @@ void wpa_pasn_reset(struct pasn_data *pasn) pasn->derive_kdk = false; pasn->rsn_ie = NULL; pasn->rsn_ie_len = 0; - pasn->rsnxe_ie = NULL; pasn->custom_pmkid_valid = false; + if (pasn->rsnxe_ie) { + os_free((u8 *)pasn->rsnxe_ie); + pasn->rsnxe_ie = NULL; + pasn->rsnxe_ie_len = 0; + } if (pasn->extra_ies) { os_free((u8 *) pasn->extra_ies); pasn->extra_ies = NULL; } + if (pasn->action_frame_wrapper) { + wpabuf_free(pasn->action_frame_wrapper); + pasn->action_frame_wrapper = NULL; + } + if (pasn->frame) { + wpabuf_free(pasn->frame); + pasn->frame = NULL; + } } @@ -982,17 +1004,21 @@ static int wpas_pasn_send_auth_1(struct pasn_data *pasn, const u8 *own_addr, wpa_printf(MSG_DEBUG, "PASN: Failed building 1st auth frame"); goto fail; } + if (pasn->frame) { + wpabuf_free(pasn->frame); + pasn->frame = NULL; + } ret = pasn->send_mgmt(pasn->cb_ctx, wpabuf_head(frame), wpabuf_len(frame), 0, pasn->freq, 1000); - wpabuf_free(frame); if (ret) { wpa_printf(MSG_DEBUG, "PASN: Failed sending 1st auth frame"); + wpabuf_free(frame); goto fail; } - + pasn->frame = frame; return 0; fail: @@ -1382,21 +1408,29 @@ int wpa_pasn_auth_rx(struct pasn_data *pasn, const u8 *data, size_t len, wpa_printf(MSG_DEBUG, "PASN: Success verifying Authentication frame"); - frame = wpas_pasn_build_auth_3(pasn); + if (pasn->parse_encrypted_data && pasn->cb_ctx) + pasn->parse_encrypted_data(pasn->cb_ctx, data, len); + + frame = wpas_pasn_build_auth_3(pasn, data, len); if (!frame) { wpa_printf(MSG_DEBUG, "PASN: Failed building 3rd auth frame"); goto fail; } + if (pasn->frame) { + wpabuf_free(pasn->frame); + pasn->frame = NULL; + } ret = pasn->send_mgmt(pasn->cb_ctx, wpabuf_head(frame), wpabuf_len(frame), 0, pasn->freq, 100); - wpabuf_free(frame); if (ret) { wpa_printf(MSG_DEBUG, "PASN: Failed sending 3st auth frame"); + wpabuf_free(frame); goto fail; } + pasn->frame = frame; wpa_printf(MSG_DEBUG, "PASN: Success sending last frame. Store PTK"); pasn->status = WLAN_STATUS_SUCCESS; diff --git a/src/pasn/pasn_responder.c b/src/pasn/pasn_responder.c index c75ba87..e5216a0 100644 --- a/src/pasn/pasn_responder.c +++ b/src/pasn/pasn_responder.c @@ -473,7 +473,7 @@ static void handle_auth_pasn_comeback(struct pasn_data *pasn, "PASN: comeback: STA=" MACSTR, MAC2STR(peer_addr)); ret = pasn->send_mgmt(pasn->cb_ctx, wpabuf_head_u8(buf), - wpabuf_len(buf), 0, 0, 0); + wpabuf_len(buf), 0, pasn->freq, 0); if (ret) wpa_printf(MSG_INFO, "PASN: Failed to send comeback frame 2"); @@ -561,6 +561,9 @@ int handle_auth_pasn_resp(struct pasn_data *pasn, const u8 *own_addr, if (rsnxe_ie) wpabuf_put_data(buf, rsnxe_ie, 2 + rsnxe_ie[1]); + if (pasn->update_extra_ies && pasn->cb_ctx) + pasn->update_extra_ies(pasn->cb_ctx, peer_addr); + wpa_pasn_add_extra_ies(buf, pasn->extra_ies, pasn->extra_ies_len); /* Add the mic */ @@ -636,14 +639,20 @@ done: wpa_printf(MSG_DEBUG, "PASN: Building frame 2: success; resp STA=" MACSTR, MAC2STR(peer_addr)); + if (pasn->frame) { + wpabuf_free(pasn->frame); + pasn->frame = NULL; + } ret = pasn->send_mgmt(pasn->cb_ctx, wpabuf_head_u8(buf), - wpabuf_len(buf), 0, 0, 0); - if (ret) + wpabuf_len(buf), 0, pasn->freq, 0); + if (ret) { wpa_printf(MSG_INFO, "send_auth_reply: Send failed"); + goto fail; + } wpabuf_free(rsn_buf); - wpabuf_free(buf); + pasn->frame = buf; return ret; fail: wpabuf_free(wrapped_data_buf); @@ -1079,6 +1088,9 @@ int handle_auth_pasn_3(struct pasn_data *pasn, const u8 *own_addr, wpabuf_free(wrapped_data); } + if (pasn->parse_encrypted_data && pasn->cb_ctx) + pasn->parse_encrypted_data(pasn->cb_ctx, (const u8 *) mgmt, len); + wpa_printf(MSG_INFO, "PASN: Success handling transaction == 3. Store PTK"); return 0; diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c index 46e7cf1..1c7992e 100644 --- a/wpa_supplicant/events.c +++ b/wpa_supplicant/events.c @@ -6093,6 +6093,37 @@ static void wpas_link_reconfig(struct wpa_supplicant *wpa_s) } +#ifdef CONFIG_PASN +int wpas_pasn_auth(struct wpa_supplicant *wpa_s, + const struct ieee80211_mgmt *mgmt, size_t len, int freq) +{ + int ret = 0; + struct ieee802_11_elems elems; + + if (len < 24) { + wpa_printf(MSG_DEBUG, "nl80211: Too short management frame"); + return -2; + } + + if (ieee802_11_parse_elems(mgmt->u.auth.variable, + len - offsetof(struct ieee80211_mgmt, + u.auth.variable), + &elems, 1) == ParseFailed) { + wpa_printf(MSG_DEBUG, + "PASN: Failed parsing Authentication frame"); + return -2; + } + + if (!elems.p2p2_ie || !elems.p2p2_ie_len) + ret = wpas_pasn_auth_rx(wpa_s, mgmt, len); + else + ret = wpas_p2p_pasn_auth_rx(wpa_s, mgmt, len, freq); + + return ret; +} +#endif /* CONFIG_PASN */ + + void wpa_supplicant_event(void *ctx, enum wpa_event_type event, union wpa_event_data *data) { @@ -6323,11 +6354,22 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event, #endif /* CONFIG_WNM */ #ifdef CONFIG_PASN if (data->tx_status.type == WLAN_FC_TYPE_MGMT && - data->tx_status.stype == WLAN_FC_STYPE_AUTH && - wpas_pasn_auth_tx_status(wpa_s, data->tx_status.data, - data->tx_status.data_len, - data->tx_status.ack) == 0) - break; + data->tx_status.stype == WLAN_FC_STYPE_AUTH) { + if (!wpa_s->pasn_auth_work && + wpa_s->p2p_pasn_auth_work) { + if (wpas_p2p_pasn_auth_tx_status(wpa_s, + data->tx_status.data, + data->tx_status.data_len, + data->tx_status.ack) == 0) + break; + } else { + if (wpas_pasn_auth_tx_status(wpa_s, + data->tx_status.data, + data->tx_status.data_len, + data->tx_status.ack) == 0) + break; + } + } #endif /* CONFIG_PASN */ #ifdef CONFIG_AP if (wpa_s->ap_iface == NULL) { @@ -6599,8 +6641,8 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event, } #ifdef CONFIG_PASN if (stype == WLAN_FC_STYPE_AUTH && - wpas_pasn_auth_rx(wpa_s, mgmt, - data->rx_mgmt.frame_len) != -2) + wpas_pasn_auth(wpa_s, mgmt, data->rx_mgmt.frame_len, + data->rx_mgmt.freq) != -2) break; #endif /* CONFIG_PASN */ diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c index 6e7cf8f..0cffb99 100644 --- a/wpa_supplicant/p2p_supplicant.c +++ b/wpa_supplicant/p2p_supplicant.c @@ -40,6 +40,7 @@ #include "crypto/random.h" + /* * How many times to try to scan to find the GO before giving up on join * request. @@ -165,7 +166,10 @@ wpas_p2p_consider_moving_gos(struct wpa_supplicant *wpa_s, static void wpas_p2p_reconsider_moving_go(void *eloop_ctx, void *timeout_ctx); static int wpas_p2p_disallowed_freq(struct wpa_global *global, unsigned int freq); - +#ifdef CONFIG_PASN +static int wpas_p2p_initiate_pasn_auth(struct wpa_supplicant *wpa_s, + const u8 *peer_addr, int freq); +#endif /* CONFIG_PASN */ static int wpas_get_6ghz_he_chwidth_capab(struct hostapd_hw_modes *mode) { @@ -1717,6 +1721,29 @@ static void wpas_send_action_done(void *ctx) offchannel_send_action_done(wpa_s); } +#ifdef CONFIG_PASN +struct wpa_p2p_pasn_auth_work { + u8 peer_addr[ETH_ALEN]; + bool verify; + int freq; +}; + + +static void wpas_p2p_pasn_free_auth_work(struct wpa_p2p_pasn_auth_work *awork) +{ + os_free(awork); +} + + +static void wpas_p2p_pasn_cancel_auth_work(struct wpa_supplicant *wpa_s) +{ + wpa_printf(MSG_DEBUG, "P2P PASN: Cancel p2p-pasn-start-auth work"); + + /* Remove pending/started work */ + radio_remove_works(wpa_s, "p2p-pasn-start-auth", 0); +} +#endif /* CONFIG_PASN */ + static int wpas_copy_go_neg_results(struct wpa_supplicant *wpa_s, struct p2p_go_neg_results *params) @@ -2392,6 +2419,12 @@ static void wpas_p2p_group_formation_timeout(void *eloop_ctx, void *timeout_ctx) { struct wpa_supplicant *wpa_s = eloop_ctx; +#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 */ wpa_printf(MSG_DEBUG, "P2P: Group Formation timed out"); wpas_p2p_group_formation_failed(wpa_s, 0); } @@ -2456,6 +2489,12 @@ static void wpas_go_neg_completed(void *ctx, struct p2p_go_neg_results *res) wpa_s->off_channel_freq = 0; wpa_s->roc_waiting_drv_freq = 0; } +#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 (res->status) { wpa_msg_global(wpa_s, MSG_INFO, @@ -4888,8 +4927,109 @@ static void wpas_bootstrap_completed(void *ctx, const u8 *addr, int status, if (status) return; +#ifdef CONFIG_PASN + wpas_p2p_initiate_pasn_auth(wpa_s, addr, freq); +#endif /* CONFIG_PASN */ +} + +#ifdef CONFIG_PASN +static void wpas_p2p_pasn_auth_start_cb(struct wpa_radio_work *work, int deinit) +{ + 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; + + if (deinit) { + if (!work->started) { + eloop_cancel_timeout(wpas_p2p_group_formation_timeout, + wpa_s->p2pdev, NULL); + } + os_free(awork); + return; + } + + if (!is_zero_ether_addr(awork->peer_addr)) + peer_addr = awork->peer_addr; + if (p2p_initiate_pasn_auth(p2p, peer_addr, awork->freq)) { + wpa_printf(MSG_DEBUG, + "P2P PASN: Failed to start PASN authentication"); + goto fail; + } + eloop_cancel_timeout(wpas_p2p_group_formation_timeout, + wpa_s->p2pdev, NULL); + eloop_register_timeout(P2P_MAX_INITIAL_CONN_WAIT, 0, + wpas_p2p_group_formation_timeout, + wpa_s->p2pdev, NULL); + wpa_s->p2p_pasn_auth_work = work; + return; +fail: + wpas_p2p_pasn_free_auth_work(awork); + work->ctx = NULL; + radio_work_done(work); } +static int wpas_p2p_initiate_pasn_auth(struct wpa_supplicant *wpa_s, + const u8 *peer_addr, int freq) +{ + struct wpa_p2p_pasn_auth_work *awork; + + wpas_p2p_pasn_cancel_auth_work(wpa_s); + wpa_s->p2p_pasn_auth_work = NULL; + + awork = os_zalloc(sizeof(*awork)); + if (!awork) + return -1; + + awork->freq = freq; + os_memcpy(awork->peer_addr, peer_addr, ETH_ALEN); + + 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_pasn_send_mlme(void *ctx, const u8 *data, size_t data_len, + int noack, unsigned int freq, + unsigned int wait) +{ + struct wpa_supplicant *wpa_s = ctx; + + return wpa_drv_send_mlme(wpa_s, data, data_len, noack, freq, wait); +} + + +static int wpas_p2p_pasn_update_extra_ies(void *ctx, const u8 *peer_addr) +{ + struct wpa_supplicant *wpa_s = ctx; + struct p2p_data *p2p = wpa_s->global->p2p; + + return p2p_pasn_update_extra_ies(p2p, peer_addr); +} + + +static int wpas_p2p_pasn_parse_encrypted_data(void *ctx, const u8 *data, + size_t len) +{ + struct wpa_supplicant *wpa_s = ctx; + struct p2p_data *p2p = wpa_s->global->p2p; + + return p2p_pasn_parse_encrypted_data(p2p, data, len); +} + +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; + + return p2p_pasn_auth_tx_status(p2p, data, data_len, acked); +} +#endif int wpas_p2p_mac_setup(struct wpa_supplicant *wpa_s) { @@ -5013,7 +5153,11 @@ int wpas_p2p_init(struct wpa_global *global, struct wpa_supplicant *wpa_s) p2p.register_bootstrap_comeback = wpas_p2p_register_bootstrap_comeback; p2p.bootstrap_req_rx = wpas_bootstrap_req_rx; p2p.bootstrap_completed = wpas_bootstrap_completed; - +#ifdef CONFIG_PASN + p2p.pasn_send_mgmt = wpas_p2p_pasn_send_mlme; + p2p.pasn_update_extra_ies = wpas_p2p_pasn_update_extra_ies; + p2p.pasn_parse_encrypted_data = wpas_p2p_pasn_parse_encrypted_data; +#endif /* CONFIG_PASN */ os_memcpy(wpa_s->global->p2p_dev_addr, wpa_s->own_addr, ETH_ALEN); os_memcpy(p2p.dev_addr, wpa_s->global->p2p_dev_addr, ETH_ALEN); p2p.dev_name = wpa_s->conf->device_name; @@ -10383,3 +10527,16 @@ void wpas_p2p_process_usd_elems(struct wpa_supplicant *wpa_s, const u8 *buf, return; p2p_process_usd_elems(p2p, buf, buf_len, peer_addr, freq); } + +#ifdef CONFIG_PASN +int wpas_p2p_pasn_auth_rx(struct wpa_supplicant *wpa_s, + const struct ieee80211_mgmt *mgmt, size_t len, + int freq) +{ + struct p2p_data *p2p = wpa_s->global->p2p; + + if (wpa_s->global->p2p_disabled || !p2p) + return -2; + return p2p_pasn_auth_rx(p2p, mgmt, len, freq); +} +#endif /* CONFIG_PASN */ diff --git a/wpa_supplicant/p2p_supplicant.h b/wpa_supplicant/p2p_supplicant.h index a2cb78d..5612d83 100644 --- a/wpa_supplicant/p2p_supplicant.h +++ b/wpa_supplicant/p2p_supplicant.h @@ -227,7 +227,9 @@ int wpas_p2p_lo_start(struct wpa_supplicant *wpa_s, unsigned int freq, int wpas_p2p_lo_stop(struct wpa_supplicant *wpa_s); int wpas_p2p_mac_setup(struct wpa_supplicant *wpa_s); struct wpabuf * wpas_p2p_usd_elems(struct wpa_supplicant *wpa_s); - +int wpas_p2p_pasn_auth_rx(struct wpa_supplicant *wpa_s, + const struct ieee80211_mgmt *mgmt, size_t len, + int freq); #else /* CONFIG_P2P */ static inline int @@ -358,6 +360,13 @@ static inline struct wpabuf * wpas_p2p_usd_elems(struct wpa_supplicant *wpa_s) return NULL; } +static inline int +wpas_p2p_pasn_auth_rx(struct wpa_supplicant *wpa_s, + const struct ieee80211_mgmt *mgmt, size_t len, int freq) +{ + return 0; +} + #endif /* CONFIG_P2P */ #endif /* P2P_SUPPLICANT_H */ diff --git a/wpa_supplicant/pasn_supplicant.c b/wpa_supplicant/pasn_supplicant.c index 89edad4..f4a3bb2 100644 --- a/wpa_supplicant/pasn_supplicant.c +++ b/wpa_supplicant/pasn_supplicant.c @@ -806,6 +806,11 @@ int wpas_pasn_auth_rx(struct wpa_supplicant *wpa_s, if (!wpa_s->pasn_auth_work) return -2; + if (pasn->frame) { + wpabuf_free(pasn->frame); + pasn->frame = NULL; + } + pasn_register_callbacks(pasn, wpa_s, wpas_pasn_send_mlme, NULL); ret = wpa_pasn_auth_rx(pasn, (const u8 *) mgmt, len, &pasn_data); if (ret == 0) { diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h index 35f541f..51da6ff 100644 --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -1593,6 +1593,9 @@ struct wpa_supplicant { struct wpa_radio_work *pasn_auth_work; unsigned int pasn_count; struct pasn_auth *pasn_params; +#ifdef CONFIG_P2P + struct wpa_radio_work *p2p_pasn_auth_work; +#endif /* CONFIG_P2P */ #endif /* CONFIG_PASN */ bool is_6ghz_enabled; @@ -2028,5 +2031,7 @@ int wpas_get_owe_trans_network(const u8 *owe_ie, const u8 **bssid, void wpas_p2p_process_usd_elems(struct wpa_supplicant *wpa_s, const u8 *buf, u16 buf_len, const u8 *peer_addr, unsigned int freq); +int wpas_p2p_pasn_auth_tx_status(struct wpa_supplicant *wpa_s, const u8 *data, + size_t data_len, u8 acked); #endif /* WPA_SUPPLICANT_I_H */