From patchwork Mon Aug 5 09:33:16 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Shivani Baranwal X-Patchwork-Id: 1969023 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=ckIFjWud; 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=Uwc420k5; 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 4WctQ36cfQz20Mt for ; Mon, 5 Aug 2024 20:45:47 +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=QTDGFlAmfdc/o/txen0teV9ONkZalvtozfbtQXiiXp4=; b=ckIFjWudFHqJkV ICE4E9TVY0QBJ36yTOLWcdjoG9zVFRF8VqudEe3C007g09NVHsOOSRhNfeEF+ZNEJTtRNOdCcIevH wGw9za5VcVZYzoaQAMWwG/SOjdxZpMONPDs8gg6JYDmW1jWQEB+Igo5gor086hyprpYKJQeZGwH5X Rgo3IP4w2WpnUFbxasR2wkfISA94wWqpbofiwQP/S5Yru8/SnHjP3f6cNdARZKncvYAf9I0lYTkdS zCXoWx+ITxwVoAgkKeE15lojDFgTvHQGxAl67FptgfDFAi8xKX8wOCvHHSs9MAxZ2dtcWIoWL85p5 tc/jRXr5XDbcJ4p5U7kg==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.97.1 #2 (Red Hat Linux)) id 1savDZ-0000000FZCN-1f53; Mon, 05 Aug 2024 10:45:33 +0000 Received: from mx0b-0031df01.pphosted.com ([205.220.180.131]) by bombadil.infradead.org with esmtps (Exim 4.97.1 #2 (Red Hat Linux)) id 1sau6z-0000000FIts-1hUI for hostap@lists.infradead.org; Mon, 05 Aug 2024 09:34:55 +0000 Received: from pps.filterd (m0279869.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id 4752VkDM011545 for ; Mon, 5 Aug 2024 09:34:40 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=fv40G1ETLrsQWXrlrGXVF0nH JOzWBr3VgWwXu/R3G0U=; b=Uwc420k5GmMUR702w7RJNXGjcZjRLGX8DoB+FIby jkftXXbzUHH07Lg5FN5HDZ0/d426mi3lomwKmGsYtTnyO3OuST9eTG38rjy3g1Pv +IpP7S9ummkhFPID6QERE68XyUBCtU30NxssVm/FHhGHiQBGJC9MwuBKt31iyMe4 stmH5TKt/LpST3gpzOd0IV3dH78uhsPQzDO7fFbgPultW4vzPgy4Ncy9RrhfHu+S Hizo7pQvs5y8b5W++7XAVsWrajgtCSXlcfEFEaWQeQCLpBKiVe5b2H17n4CA8k1k J7hvn6O6J4bC36giV168etK7DleEBucFtwiNt2qpy8W6Eg== Received: from nalasppmta01.qualcomm.com (Global_NAT1.qualcomm.com [129.46.96.20]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 40sbj6khrn-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT) for ; Mon, 05 Aug 2024 09:34:39 +0000 (GMT) Received: from nalasex01a.na.qualcomm.com (nalasex01a.na.qualcomm.com [10.47.209.196]) by NALASPPMTA01.qualcomm.com (8.17.1.19/8.17.1.19) with ESMTPS id 4759Yc9n022922 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT) for ; Mon, 5 Aug 2024 09:34:38 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:36 -0700 From: Shivani Baranwal To: CC: Subject: [PATCH v3 18/25] Add p2p2 support for group formation on successful negotiation Date: Mon, 5 Aug 2024 15:03:16 +0530 Message-ID: <1722850403-8852-19-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: WJYDrlTmN-BCWGc_uUEedUtSZubzO4R0 X-Proofpoint-GUID: WJYDrlTmN-BCWGc_uUEedUtSZubzO4R0 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 spamscore=0 suspectscore=0 priorityscore=1501 adultscore=0 mlxscore=0 lowpriorityscore=0 bulkscore=0 phishscore=0 mlxlogscore=999 clxscore=1015 malwarescore=0 impostorscore=0 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_023442_102668_0C21F060 X-CRM114-Status: GOOD ( 27.09 ) 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 support for Group formation and connection between p2p go and p2p client on successful go negotiation. Signed-off-by: Shivani Baranwal --- src/ap/ap_drv_ops.c | 23 +++++ src/ap/ap_drv_ops.h | 5 ++ src/ap/ieee802_11.c | 15 ++++ src/ap/ieee802_11.h | 2 + src/ap/wpa_auth_ie.c | [...] 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.180.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.180.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.180.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-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 support for Group formation and connection between p2p go and p2p client on successful go negotiation. Signed-off-by: Shivani Baranwal --- src/ap/ap_drv_ops.c | 23 +++++ src/ap/ap_drv_ops.h | 5 ++ src/ap/ieee802_11.c | 15 ++++ src/ap/ieee802_11.h | 2 + src/ap/wpa_auth_ie.c | 17 ++++ src/p2p/p2p.c | 59 +++++++++++-- src/p2p/p2p.h | 22 ++++- src/p2p/p2p_group.c | 50 ++++++++++- src/p2p/p2p_i.h | 2 + wpa_supplicant/p2p_supplicant.c | 180 +++++++++++++++++++++++++++++++++++----- 10 files changed, 346 insertions(+), 29 deletions(-) diff --git a/src/ap/ap_drv_ops.c b/src/ap/ap_drv_ops.c index c473491..e22efeb 100644 --- a/src/ap/ap_drv_ops.c +++ b/src/ap/ap_drv_ops.c @@ -1250,3 +1250,26 @@ int hostapd_drv_set_secure_ranging_ctx(struct hostapd_data *hapd, return hapd->driver->set_secure_ranging_ctx(hapd->drv_priv, ¶ms); } #endif /* CONFIG_PASN */ + +int hostapd_drv_add_pmkid(struct hostapd_data *hapd, + struct wpa_pmkid_params *params) +{ + if (!hapd->driver || !hapd->driver->add_pmkid || !hapd->drv_priv) + return 0; + return hapd->driver->add_pmkid(hapd->drv_priv, params); +} + +int hostapd_drv_remove_pmkid(struct hostapd_data *hapd, + struct wpa_pmkid_params *params) +{ + if (!hapd->driver || !hapd->driver->remove_pmkid || !hapd->drv_priv) + return 0; + return hapd->driver->remove_pmkid(hapd->drv_priv, params); +} + +int hostapd_drv_flush_pmkid(struct hostapd_data *hapd) +{ + if (!hapd->driver || !hapd->driver->flush_pmkid || !hapd->drv_priv) + return 0; + return hapd->driver->flush_pmkid(hapd->drv_priv); +} diff --git a/src/ap/ap_drv_ops.h b/src/ap/ap_drv_ops.h index d7e79c8..de7c4af 100644 --- a/src/ap/ap_drv_ops.h +++ b/src/ap/ap_drv_ops.h @@ -148,6 +148,11 @@ int hostapd_drv_set_secure_ranging_ctx(struct hostapd_data *hapd, u32 cipher, u8 key_len, const u8 *key, u8 ltf_keyseed_len, const u8 *ltf_keyseed, u32 action); +int hostapd_drv_add_pmkid(struct hostapd_data *hapd, + struct wpa_pmkid_params *params); +int hostapd_drv_remove_pmkid(struct hostapd_data *hapd, + struct wpa_pmkid_params *params); +int hostapd_drv_flush_pmkid(struct hostapd_data *hapd); #include "drivers/driver.h" diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c index 3c5a8dd..5973056 100644 --- a/src/ap/ieee802_11.c +++ b/src/ap/ieee802_11.c @@ -8295,4 +8295,19 @@ u8 * hostapd_eid_mbssid(struct hostapd_data *hapd, u8 *eid, u8 *end, return eid; } + +int hostapd_add_pmkid(struct hostapd_data *hapd, const u8 *bssid, const u8 *pmk, + size_t pmk_len, const u8 *pmkid, int akmp) +{ + struct wpa_pmkid_params params; + + os_memset(¶ms, 0, sizeof(params)); + params.bssid = bssid; + params.pmkid = pmkid; + params.pmk = pmk; + params.pmk_len = pmk_len; + + return hostapd_drv_add_pmkid(hapd, ¶ms); +} + #endif /* CONFIG_NATIVE_WINDOWS */ diff --git a/src/ap/ieee802_11.h b/src/ap/ieee802_11.h index dd4995f..b1a3edf 100644 --- a/src/ap/ieee802_11.h +++ b/src/ap/ieee802_11.h @@ -263,5 +263,7 @@ int hostapd_process_assoc_ml_info(struct hostapd_data *hapd, const u8 *ies, size_t ies_len, bool reassoc, int tx_link_status, bool offload); +int hostapd_add_pmkid(struct hostapd_data *hapd, const u8 *bssid, const u8 *pmk, + size_t pmk_len, const u8 *pmkid, int akmp); #endif /* IEEE802_11_H */ diff --git a/src/ap/wpa_auth_ie.c b/src/ap/wpa_auth_ie.c index 43d9c1d..bd1bd64 100644 --- a/src/ap/wpa_auth_ie.c +++ b/src/ap/wpa_auth_ie.c @@ -499,6 +499,9 @@ static u32 rsnxe_capab(struct wpa_auth_config *conf, int key_mgmt) #endif /* CONFIG_SAE_PK */ } + // FIXME: Should not set it by default + capab |= BIT(WLAN_RSNX_CAPAB_SAE_H2E); + if (conf->secure_ltf) capab |= BIT(WLAN_RSNX_CAPAB_SECURE_LTF); if (conf->secure_rtt) @@ -1251,6 +1254,20 @@ wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth, pmkid = sm->pmksa->pmkid; break; } + + if (!is_zero_ether_addr(sm->p2p_dev_addr)) { + wpa_hexdump(MSG_DEBUG, "RSN IE: P2P DEV PMKID", + &data.pmkid[i * PMKID_LEN], PMKID_LEN); + sm->pmksa = + pmksa_cache_auth_get(wpa_auth->pmksa, + sm->p2p_dev_addr, + &data.pmkid[i * PMKID_LEN]); + if (sm->pmksa) { + pmkid = sm->pmksa->pmkid; + break; + } + } + } for (i = 0; sm->pmksa == NULL && wpa_auth->conf.okc && i < data.num_pmkid; i++) { diff --git a/src/p2p/p2p.c b/src/p2p/p2p.c index ab3ccc1..8f3d76e 100644 --- a/src/p2p/p2p.c +++ b/src/p2p/p2p.c @@ -253,6 +253,7 @@ void p2p_go_neg_failed(struct p2p_data *p2p, int status) os_memset(&res, 0, sizeof(res)); res.status = status; + res.p2p2 = peer->p2p2; os_memcpy(res.peer_device_addr, peer->info.p2p_device_addr, ETH_ALEN); os_memcpy(res.peer_interface_addr, peer->intended_addr, ETH_ALEN); p2p->cfg->go_neg_completed(p2p->cfg->cb_ctx, &res); @@ -1072,7 +1073,8 @@ static void p2p_search(struct p2p_data *p2p) res = p2p->cfg->p2p_scan(p2p->cfg->cb_ctx, type, freq, p2p->num_req_dev_types, p2p->req_dev_types, - p2p->find_dev_id, pw_id, p2p->include_6ghz); + p2p->find_dev_id, pw_id, p2p->include_6ghz, + false); if (res < 0) { p2p_dbg(p2p, "Scan request schedule failed"); p2p_continue_find(p2p); @@ -1299,7 +1301,7 @@ int p2p_find(struct p2p_data *p2p, unsigned int timeout, p2p->num_req_dev_types, p2p->req_dev_types, dev_id, DEV_PW_DEFAULT, - p2p->include_6ghz); + p2p->include_6ghz, false); break; } /* fall through */ @@ -1307,13 +1309,15 @@ int p2p_find(struct p2p_data *p2p, unsigned int timeout, res = p2p->cfg->p2p_scan(p2p->cfg->cb_ctx, P2P_SCAN_FULL, 0, p2p->num_req_dev_types, p2p->req_dev_types, dev_id, - DEV_PW_DEFAULT, p2p->include_6ghz); + DEV_PW_DEFAULT, p2p->include_6ghz, + false); break; case P2P_FIND_ONLY_SOCIAL: res = p2p->cfg->p2p_scan(p2p->cfg->cb_ctx, P2P_SCAN_SOCIAL, 0, p2p->num_req_dev_types, p2p->req_dev_types, dev_id, - DEV_PW_DEFAULT, p2p->include_6ghz); + DEV_PW_DEFAULT, p2p->include_6ghz, + false); break; default: return -1; @@ -1861,6 +1865,16 @@ int p2p_go_params(struct p2p_data *p2p, struct p2p_go_neg_results *params) } p2p->ssid_set = 0; + params->cipher = WPA_CIPHER_CCMP; + if (p2p->cfg->pairing_config.pasn_type & 0xc) + params->cipher |= WPA_CIPHER_GCMP_256; + + if (params->p2p2) { + params->password_len = p2p->cfg->dev_password_len; + memcpy(params->password, p2p->cfg->dev_password, + p2p->cfg->dev_password_len); + } + p2p_random(params->passphrase, p2p->cfg->passphrase_len); params->passphrase[p2p->cfg->passphrase_len] = '\0'; return 0; @@ -1934,8 +1948,43 @@ void p2p_go_complete(struct p2p_data *p2p, struct p2p_device *peer) peer->go_neg_conf = NULL; #ifdef CONFIG_PASN - if (peer->p2p2 && peer->pasn) + if (peer->p2p2 && peer->pasn) { + res.p2p2 = peer->p2p2; + res.akmp = peer->pasn->akmp; + res.cipher = peer->pasn->cipher; + + if (res.akmp == WPA_KEY_MGMT_PASN) { + if (go) { + res.password_len = p2p->cfg->dev_password_len; + memcpy(res.password, p2p->cfg->dev_password, + res.password_len); + } else { + if (!peer->info.password_len) { + p2p_dbg(p2p, "Password Invalid for P2P2 group formation"); + return; + } + res.password_len = peer->info.password_len; + memcpy(res.password, peer->info.password, + res.password_len); + } + } else if (res.akmp == WPA_KEY_MGMT_SAE) { + res.password_len = peer->password_len; + memcpy(res.password, peer->password, res.password_len); + if (peer->role == P2P_ROLE_PAIRING_INITIATOR) { + pasn_initiator_pmksa_cache_get(peer->pasn->pmksa, + peer->pasn->peer_addr, + res.pmkid, res.pmk, + &res.pmk_len); + } else { + pasn_responder_pmksa_cache_get(peer->pasn->pmksa, + peer->pasn->peer_addr, + res.pmkid, res.pmk, + &res.pmk_len); + } + } + wpa_pasn_reset(peer->pasn); + } #endif /* CONFIG_PASN */ p2p_set_state(p2p, P2P_PROVISIONING); diff --git a/src/p2p/p2p.h b/src/p2p/p2p.h index db2052f..65e2e0d 100644 --- a/src/p2p/p2p.h +++ b/src/p2p/p2p.h @@ -11,6 +11,7 @@ #include "common/ieee802_11_defs.h" #include "wps/wps.h" +#include "common/wpa_common.h" #define DEVICE_IDENTITY_KEY_MAX_LEN 64 #define DEVICE_IDENTITY_KEY_LEN 16 @@ -181,6 +182,22 @@ struct p2p_go_neg_results { * peer_config_timeout - Peer configuration timeout (in 10 msec units) */ unsigned int peer_config_timeout; + + bool p2p2; + + int akmp; + + int cipher; + + u8 pmkid[PMKID_LEN]; + + u8 pmk[PMK_LEN_MAX]; + + size_t pmk_len; + + char password[100]; + + size_t password_len; }; struct p2ps_provision { @@ -779,7 +796,7 @@ struct p2p_config { int (*p2p_scan)(void *ctx, enum p2p_scan_type type, int freq, unsigned int num_req_dev_types, const u8 *req_dev_types, const u8 *dev_id, u16 pw_id, - bool include_6ghz); + bool include_6ghz, bool p2p2); /** * send_probe_resp - Transmit a Probe Response frame @@ -1993,6 +2010,7 @@ struct p2p_group_config { * p2p_group_init - Initialize P2P group * @p2p: P2P module context from p2p_init() * @config: P2P group configuration (will be freed by p2p_group_deinit()) + * @p2p2: parameter to indicate that the group formed using p2p2 * Returns: Pointer to private data or %NULL on failure * * This function is used to initialize per-group P2P module context. Currently, @@ -2000,7 +2018,7 @@ struct p2p_group_config { * create an instance of this per-group information. */ struct p2p_group * p2p_group_init(struct p2p_data *p2p, - struct p2p_group_config *config); + struct p2p_group_config *config, bool p2p2); /** * p2p_group_deinit - Deinitialize P2P group diff --git a/src/p2p/p2p_group.c b/src/p2p/p2p_group.c index c036f92..4822c28 100644 --- a/src/p2p/p2p_group.c +++ b/src/p2p/p2p_group.c @@ -40,11 +40,12 @@ struct p2p_group { int beacon_update; struct wpabuf *noa; struct wpabuf *wfd_ie; + bool p2p2; }; struct p2p_group * p2p_group_init(struct p2p_data *p2p, - struct p2p_group_config *config) + struct p2p_group_config *config, bool p2p2) { struct p2p_group *group, **groups; @@ -62,6 +63,7 @@ struct p2p_group * p2p_group_init(struct p2p_data *p2p, p2p->groups = groups; group->p2p = p2p; + group->p2p2 = p2p2; group->cfg = config; group->group_formation = 1; group->beacon_update = 1; @@ -205,11 +207,28 @@ static struct wpabuf * p2p_group_encaps_probe_resp(struct wpabuf *subelems) } +struct wpabuf * p2p_group_build_p2p2_ie(struct p2p_data *p2p, + struct wpabuf *p2p2_ie, int freq) +{ + u8 *len; + + wpabuf_put_u8(p2p2_ie, WLAN_EID_VENDOR_SPECIFIC); + len = wpabuf_put(p2p2_ie, 1); + wpabuf_put_be32(p2p2_ie, P2P2_IE_VENDOR_TYPE); + wpa_printf(MSG_DEBUG, "P2P: * P2P2 IE header"); + p2p_buf_add_pcea(p2p2_ie, p2p); + *len = (u8 *)wpabuf_put(p2p2_ie, 0) - len - 1; + + return p2p2_ie; +} + + static struct wpabuf * p2p_group_build_beacon_ie(struct p2p_group *group) { struct wpabuf *ie; u8 *len; size_t extra = 0; + struct wpabuf *p2p2_ie; #ifdef CONFIG_WIFI_DISPLAY if (group->p2p->wfd_ie_beacon) @@ -220,7 +239,7 @@ static struct wpabuf * p2p_group_build_beacon_ie(struct p2p_group *group) group->p2p->vendor_elem[VENDOR_ELEM_BEACON_P2P_GO]) extra += wpabuf_len(group->p2p->vendor_elem[VENDOR_ELEM_BEACON_P2P_GO]); - ie = wpabuf_alloc(257 + extra); + ie = wpabuf_alloc(500 + extra); if (ie == NULL) return NULL; @@ -240,6 +259,15 @@ static struct wpabuf * p2p_group_build_beacon_ie(struct p2p_group *group) p2p_group_add_noa(ie, group->noa); p2p_buf_update_ie_hdr(ie, len); + if (group->p2p2) { + p2p2_ie = wpabuf_alloc(255); + if (!p2p2_ie) + return NULL; + + p2p_group_build_p2p2_ie(group->p2p, p2p2_ie, group->cfg->freq); + ie = wpabuf_concat(p2p2_ie, ie); + } + return ie; } @@ -443,6 +471,7 @@ void p2p_group_buf_add_id(struct p2p_group *group, struct wpabuf *buf) static struct wpabuf * p2p_group_build_probe_resp_ie(struct p2p_group *group) { struct wpabuf *p2p_subelems, *ie; + struct wpabuf *p2p2_ie; p2p_subelems = wpabuf_alloc(500); if (p2p_subelems == NULL) @@ -474,7 +503,14 @@ static struct wpabuf * p2p_group_build_probe_resp_ie(struct p2p_group *group) ie = wpabuf_concat(wfd, ie); } #endif /* CONFIG_WIFI_DISPLAY */ + if (group->p2p2) { + p2p2_ie = wpabuf_alloc(255); + if (!p2p2_ie) + return NULL; + p2p_group_build_p2p2_ie(group->p2p, p2p2_ie, group->cfg->freq); + ie = wpabuf_concat(p2p2_ie, ie); + } return ie; } @@ -648,6 +684,7 @@ struct wpabuf * p2p_group_assoc_resp_ie(struct p2p_group *group, u8 status) struct wpabuf *resp; u8 *rlen; size_t extra = 0; + struct wpabuf *p2p2_ie; #ifdef CONFIG_WIFI_DISPLAY if (group->wfd_ie) @@ -683,6 +720,15 @@ struct wpabuf * p2p_group_assoc_resp_ie(struct p2p_group *group, u8 status) p2p_buf_add_status(resp, status); p2p_buf_update_ie_hdr(resp, rlen); + if (group->p2p2) { + p2p2_ie = wpabuf_alloc(255); + if (!p2p2_ie) + return NULL; + + p2p_group_build_p2p2_ie(group->p2p, p2p2_ie, group->cfg->freq); + resp = wpabuf_concat(p2p2_ie, resp); + } + return resp; } diff --git a/src/p2p/p2p_i.h b/src/p2p/p2p_i.h index e0d2ee0..440ed1f 100644 --- a/src/p2p/p2p_i.h +++ b/src/p2p/p2p_i.h @@ -926,6 +926,8 @@ void p2p_buf_add_pref_channel_list(struct wpabuf *buf, unsigned int size); struct wpabuf *p2p_encaps_p2p_vendor_ie(struct p2p_data *p2p, struct wpabuf *subelems, u32 ie_type); +struct wpabuf * p2p_group_build_p2p2_ie(struct p2p_data *p2p, + struct wpabuf *p2p2_ie, int freq); /* p2p_sd.c */ struct p2p_sd_query * p2p_pending_sd_req(struct p2p_data *p2p, diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c index 0cffb99..71aaeba 100644 --- a/wpa_supplicant/p2p_supplicant.c +++ b/wpa_supplicant/p2p_supplicant.c @@ -426,11 +426,11 @@ static int wpas_p2p_search_social_channel(struct wpa_supplicant *wpa_s, static int wpas_p2p_scan(void *ctx, enum p2p_scan_type type, int freq, unsigned int num_req_dev_types, const u8 *req_dev_types, const u8 *dev_id, u16 pw_id, - bool include_6ghz) + bool include_6ghz, bool p2p2) { struct wpa_supplicant *wpa_s = ctx; struct wpa_driver_scan_params *params = NULL; - struct wpabuf *wps_ie, *ies; + struct wpabuf *wps_ie = NULL, *ies; unsigned int num_channels = 0; int social_channels_freq[] = { 2412, 2437, 2462, 60480 }; size_t ielen; @@ -459,11 +459,16 @@ static int wpas_p2p_scan(void *ctx, enum p2p_scan_type type, int freq, params->ssids[0].ssid_len = P2P_WILDCARD_SSID_LEN; wpa_s->wps->dev.p2p = 1; - wps_ie = wps_build_probe_req_ie(pw_id, &wpa_s->wps->dev, - wpa_s->wps->uuid, WPS_REQ_ENROLLEE, - num_req_dev_types, req_dev_types); - if (wps_ie == NULL) - goto fail; + + if (!p2p2) { + wps_ie = wps_build_probe_req_ie(pw_id, &wpa_s->wps->dev, + wpa_s->wps->uuid, + WPS_REQ_ENROLLEE, + num_req_dev_types, + req_dev_types); + if (wps_ie == NULL) + goto fail; + } /* * In case 6 GHz channels are requested as part of the P2P scan, only @@ -514,13 +519,20 @@ static int wpas_p2p_scan(void *ctx, enum p2p_scan_type type, int freq, } ielen = p2p_scan_ie_buf_len(wpa_s->global->p2p); - ies = wpabuf_alloc(wpabuf_len(wps_ie) + ielen); - if (ies == NULL) { + + if (wps_ie) + ielen += wpabuf_len(wps_ie); + + ies = wpabuf_alloc(ielen); + if (!ies) { wpabuf_free(wps_ie); goto fail; } - wpabuf_put_buf(ies, wps_ie); - wpabuf_free(wps_ie); + + if (wps_ie) { + wpabuf_put_buf(ies, wps_ie); + wpabuf_free(wps_ie); + } bands = wpas_get_bands(wpa_s, params->freqs); p2p_scan_ie(wpa_s->global->p2p, ies, dev_id, bands); @@ -1757,6 +1769,80 @@ static int wpas_copy_go_neg_results(struct wpa_supplicant *wpa_s, return 0; } +static void wpas_start_gc(struct wpa_supplicant *wpa_s, + struct p2p_go_neg_results *res) +{ + struct wpa_ssid *ssid; + + if (!res->ssid_len) { + wpa_dbg(wpa_s, MSG_DEBUG, "P2P: SSID info not present"); + return; + } + + wpa_s->group_formation_reported = 0; + wpa_printf(MSG_DEBUG, "P2P: Start connect for peer " MACSTR + " dev_addr " MACSTR, + MAC2STR(res->peer_interface_addr), + MAC2STR(res->peer_device_addr)); + wpa_hexdump_ascii(MSG_DEBUG, "P2P: Start connect for SSID", + res->ssid, res->ssid_len); + wpa_supplicant_ap_deinit(wpa_s); + wpas_copy_go_neg_results(wpa_s, res); + + ssid = wpa_config_add_network(wpa_s->conf); + if (ssid == NULL) { + wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Could not add network for Client"); + return; + } + os_memset(wpa_s->go_dev_addr, 0, ETH_ALEN); + wpa_config_set_network_defaults(ssid); + ssid->temporary = 1; + ssid->p2p_group = 1; + + ssid->ssid = os_zalloc(res->ssid_len); + if (!ssid->ssid) + return; + + ssid->ssid_len = res->ssid_len; + os_memcpy(ssid->ssid, res->ssid, ssid->ssid_len); + + memcpy(ssid->bssid, res->peer_interface_addr, ETH_ALEN); + + if (res->akmp == WPA_KEY_MGMT_PASN) { + ssid->auth_alg = WPA_AUTH_ALG_SAE; + ssid->sae_password = os_strdup(res->password); + } else if (res->akmp == WPA_KEY_MGMT_SAE) { + ssid->auth_alg = WPA_AUTH_ALG_OPEN; + ssid->sae_password = os_strdup(res->password); + wpa_sm_set_pmk(wpa_s->wpa, res->pmk, res->pmk_len, + res->pmkid, res->peer_interface_addr); + } + + if (res->psk_set) { + os_memcpy(ssid->psk, res->psk, 32); + ssid->psk_set = 1; + } + ssid->proto = WPA_PROTO_RSN; + ssid->key_mgmt = WPA_KEY_MGMT_SAE; + ssid->pairwise_cipher = WPA_CIPHER_CCMP; + ssid->group_cipher = WPA_CIPHER_CCMP; + if (res->cipher) { + ssid->pairwise_cipher |= res->cipher; + } + ssid->sae_pwe = SAE_PWE_HASH_TO_ELEMENT; + wpa_s->conf->sae_pwe = SAE_PWE_HASH_TO_ELEMENT; + ssid->ieee80211w = MGMT_FRAME_PROTECTION_REQUIRED; + ssid->disabled = 0; + wpa_s->show_group_started = 1; + wpa_s->p2p_in_invitation = 1; + wpa_s->p2p_go_group_formation_completed = 0; + wpa_s->global->p2p_group_formation = wpa_s; + + wpa_s->current_ssid = ssid; + wpa_supplicant_update_scan_results(wpa_s, res->peer_interface_addr); + wpa_supplicant_select_network(wpa_s, ssid); +} + static void wpas_start_wps_enrollee(struct wpa_supplicant *wpa_s, struct p2p_go_neg_results *res) @@ -1892,6 +1978,9 @@ static void p2p_go_configured(void *ctx, void *data) struct wpa_supplicant *wpa_s = ctx; struct p2p_go_neg_results *params = data; struct wpa_ssid *ssid; + struct sta_info sta; + struct sae_data *sae; + struct hostapd_data *hapd; wpa_s->ap_configured_cb = NULL; wpa_s->ap_configured_cb_ctx = NULL; @@ -1901,6 +1990,26 @@ static void p2p_go_configured(void *ctx, void *data) "P2P: p2p_go_configured() called with wpa_s->go_params == NULL"); return; } + if (wpa_s->ap_iface && params->p2p2 && + params->akmp == WPA_KEY_MGMT_SAE) { + hapd = wpa_s->ap_iface->bss[0]; + memset(&sta, 0, sizeof(struct sta_info)); + memcpy(sta.addr, params->peer_device_addr, ETH_ALEN); + sae = os_zalloc(sizeof(struct sae_data)); + if (sae) { + sta.sae = sae; + memcpy(sta.sae->pmkid, params->pmkid, PMKID_LEN); + wpa_auth_pmksa_add_sae(hapd->wpa_auth, + params->peer_device_addr, + params->pmk, params->pmk_len, + params->pmkid, WPA_KEY_MGMT_SAE); + hostapd_add_pmkid(hapd, params->peer_device_addr, + params->pmk, params->pmk_len, + params->pmkid, WPA_KEY_MGMT_SAE); + memset(&sta, 0, sizeof(struct sta_info)); + os_free(sae); + } + } p2p_go_save_group_common_freqs(wpa_s, params); p2p_go_dump_common_freqs(wpa_s); @@ -1967,13 +2076,21 @@ static void p2p_go_configured(void *ctx, void *data) return; } - wpa_printf(MSG_DEBUG, "P2P: Setting up WPS for GO provisioning"); if (wpa_supplicant_ap_mac_addr_filter(wpa_s, params->peer_interface_addr)) { wpa_printf(MSG_DEBUG, "P2P: Failed to setup MAC address " "filtering"); return; } + + if (params->p2p2) { + wpas_group_formation_completed(wpa_s, 1, 0); + wpa_printf(MSG_DEBUG, "P2P2: Group formation completed, " + "First connection in progress"); + goto out; + } + + wpa_printf(MSG_DEBUG, "P2P: Setting up WPS for GO provisioning"); if (params->wps_method == WPS_PBC) { wpa_supplicant_ap_wps_pbc(wpa_s, params->peer_interface_addr, params->peer_device_addr); @@ -1994,6 +2111,7 @@ static void p2p_go_configured(void *ctx, void *data) } else if (wpa_s->p2p_pin[0]) wpa_supplicant_ap_wps_pin(wpa_s, params->peer_interface_addr, wpa_s->p2p_pin, NULL, 0, 0); +out: os_free(wpa_s->go_params); wpa_s->go_params = NULL; } @@ -2076,9 +2194,9 @@ int wpas_p2p_try_edmg_channel(struct wpa_supplicant *wpa_s, } -static void wpas_start_wps_go(struct wpa_supplicant *wpa_s, - struct p2p_go_neg_results *params, - int group_formation) +static void wpas_start_go(struct wpa_supplicant *wpa_s, + struct p2p_go_neg_results *params, + int group_formation, bool p2p2) { struct wpa_ssid *ssid; @@ -2173,6 +2291,21 @@ static void wpas_start_wps_go(struct wpa_supplicant *wpa_s, wpa_config_update_psk(ssid); ssid->ap_max_inactivity = wpa_s->p2pdev->conf->p2p_go_max_inactivity; + if (p2p2) { + if (params->akmp == WPA_KEY_MGMT_SAE) + ssid->auth_alg = WPA_AUTH_ALG_OPEN; + else + ssid->auth_alg |= WPA_AUTH_ALG_SAE; + + ssid->key_mgmt = WPA_KEY_MGMT_SAE; + ssid->sae_password = os_strdup(params->password); + ssid->ieee80211w = MGMT_FRAME_PROTECTION_REQUIRED; + wpa_s->conf->sae_pwe = SAE_PWE_HASH_TO_ELEMENT; + if (params->cipher) { + ssid->pairwise_cipher |= params->cipher; + } + } + wpa_s->ap_configured_cb = p2p_go_configured; wpa_s->ap_configured_cb_ctx = wpa_s; wpa_s->ap_configured_cb_data = wpa_s->go_params; @@ -2387,6 +2520,7 @@ wpas_p2p_init_group_interface(struct wpa_supplicant *wpa_s, int go) wpa_s->global->pending_group_iface_for_p2ps = 0; wpas_p2p_clone_config(group_wpa_s, wpa_s); + group_wpa_s->p2p2 = wpa_s->p2p2; if (wpa_s->conf->p2p_interface_random_mac_addr) { if (wpa_drv_set_mac_addr(group_wpa_s, @@ -2569,12 +2703,18 @@ static void wpas_go_neg_completed(void *ctx, struct p2p_go_neg_results *res) os_memcpy(group_wpa_s->p2p_pin, wpa_s->p2p_pin, sizeof(group_wpa_s->p2p_pin)); group_wpa_s->p2p_wps_method = wpa_s->p2p_wps_method; + group_wpa_s->p2p2 = res->p2p2; + group_wpa_s->p2p_bootstrap = wpa_s->p2p_bootstrap; } + if (res->role_go) { - wpas_start_wps_go(group_wpa_s, res, 1); + wpas_start_go(group_wpa_s, res, 1, res->p2p2); } else { os_get_reltime(&group_wpa_s->scan_min_time); - wpas_start_wps_enrollee(group_wpa_s, res); + if (res->p2p2) + wpas_start_gc(group_wpa_s, res); + else + wpas_start_wps_enrollee(group_wpa_s, res); } wpa_s->global->p2p_long_listen = 0; @@ -7190,7 +7330,7 @@ int wpas_p2p_group_add(struct wpa_supplicant *wpa_s, int persistent_group, return -1; if (freq > 0) wpa_s->p2p_go_no_pri_sec_switch = 1; - wpas_start_wps_go(wpa_s, ¶ms, 0); + wpas_start_go(wpa_s, ¶ms, 0, wpa_s->p2p2); return 0; } @@ -7407,7 +7547,7 @@ int wpas_p2p_group_add_persistent(struct wpa_supplicant *wpa_s, p2p_channels_to_freqs(channels, params.freq_list, P2P_MAX_CHANNELS); wpa_s->p2p_first_connection_timeout = connection_timeout; - wpas_start_wps_go(wpa_s, ¶ms, 0); + wpas_start_go(wpa_s, ¶ms, 0, wpa_s->p2p2); return 0; } @@ -7489,7 +7629,7 @@ struct p2p_group * wpas_p2p_group_init(struct wpa_supplicant *wpa_s, cfg->ip_addr_alloc = WPA_GET_BE32(wpa_s->p2pdev->conf->ip_addr_start) != 0; - group = p2p_group_init(wpa_s->global->p2p, cfg); + group = p2p_group_init(wpa_s->global->p2p, cfg, wpa_s->p2p2); if (group == NULL) os_free(cfg); if (ssid->mode != WPAS_MODE_P2P_GROUP_FORMATION)