[PATCH 03/13] P2P: Allow P2P IE to be added into NAN SDFs
Shivani Baranwal
quic_shivbara at quicinc.com
Mon Jul 8 02:32:19 PDT 2024
Extend the NAN Subscribe and Publish methods to allow p2p=1 to be
specified to include P2P attributes in a P2P IE to be added into the NAN
Element Container attribute.
Signed-off-by: Shivani Baranwal <quic_shivbara at quicinc.com>
diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c
index 92df81c6c..2fb5f6960 100644
--- a/hostapd/ctrl_iface.c
+++ b/hostapd/ctrl_iface.c
@@ -3690,6 +3690,7 @@ static int hostapd_ctrl_nan_publish(struct hostapd_data *hapd, char *cmd,
struct wpabuf *ssi = NULL;
int ret = -1;
enum nan_service_protocol_type srv_proto_type = 0;
+ bool p2p = false;
os_memset(¶ms, 0, sizeof(params));
/* USD shall use both solicited and unsolicited transmissions */
@@ -3723,6 +3724,11 @@ static int hostapd_ctrl_nan_publish(struct hostapd_data *hapd, char *cmd,
continue;
}
+ if (os_strcmp(token, "p2p=1") == 0) {
+ p2p = true;
+ continue;
+ }
+
if (os_strcmp(token, "solicited=0") == 0) {
params.solicited = false;
continue;
@@ -3744,7 +3750,7 @@ static int hostapd_ctrl_nan_publish(struct hostapd_data *hapd, char *cmd,
}
publish_id = hostapd_nan_usd_publish(hapd, service_name, srv_proto_type,
- ssi, ¶ms);
+ ssi, ¶ms, p2p);
if (publish_id > 0)
ret = os_snprintf(buf, buflen, "%d", publish_id);
fail:
@@ -3827,6 +3833,7 @@ static int hostapd_ctrl_nan_subscribe(struct hostapd_data *hapd, char *cmd,
struct wpabuf *ssi = NULL;
int ret = -1;
enum nan_service_protocol_type srv_proto_type = 0;
+ bool p2p = false;
os_memset(¶ms, 0, sizeof(params));
@@ -3860,6 +3867,11 @@ static int hostapd_ctrl_nan_subscribe(struct hostapd_data *hapd, char *cmd,
continue;
}
+ if (os_strcmp(token, "p2p=1") == 0) {
+ p2p = true;
+ continue;
+ }
+
wpa_printf(MSG_INFO,
"CTRL: Invalid NAN_SUBSCRIBE parameter: %s",
token);
@@ -3868,7 +3880,7 @@ static int hostapd_ctrl_nan_subscribe(struct hostapd_data *hapd, char *cmd,
subscribe_id = hostapd_nan_usd_subscribe(hapd, service_name,
srv_proto_type, ssi,
- ¶ms);
+ ¶ms, p2p);
if (subscribe_id > 0)
ret = os_snprintf(buf, buflen, "%d", subscribe_id);
fail:
diff --git a/src/ap/nan_usd_ap.c b/src/ap/nan_usd_ap.c
index 70c6139fd..570abfce0 100644
--- a/src/ap/nan_usd_ap.c
+++ b/src/ap/nan_usd_ap.c
@@ -192,7 +192,7 @@ void hostapd_nan_usd_flush(struct hostapd_data *hapd)
int hostapd_nan_usd_publish(struct hostapd_data *hapd, const char *service_name,
enum nan_service_protocol_type srv_proto_type,
const struct wpabuf *ssi,
- struct nan_publish_params *params)
+ struct nan_publish_params *params, bool p2p)
{
int publish_id;
struct wpabuf *elems = NULL;
@@ -201,7 +201,7 @@ int hostapd_nan_usd_publish(struct hostapd_data *hapd, const char *service_name,
return -1;
publish_id = nan_de_publish(hapd->nan_de, service_name, srv_proto_type,
- ssi, elems, params);
+ ssi, elems, params, p2p);
wpabuf_free(elems);
return publish_id;
}
@@ -231,7 +231,7 @@ int hostapd_nan_usd_subscribe(struct hostapd_data *hapd,
const char *service_name,
enum nan_service_protocol_type srv_proto_type,
const struct wpabuf *ssi,
- struct nan_subscribe_params *params)
+ struct nan_subscribe_params *params, bool p2p)
{
int subscribe_id;
struct wpabuf *elems = NULL;
@@ -240,7 +240,7 @@ int hostapd_nan_usd_subscribe(struct hostapd_data *hapd,
return -1;
subscribe_id = nan_de_subscribe(hapd->nan_de, service_name,
- srv_proto_type, ssi, elems, params);
+ srv_proto_type, ssi, elems, params, p2p);
wpabuf_free(elems);
return subscribe_id;
}
diff --git a/src/ap/nan_usd_ap.h b/src/ap/nan_usd_ap.h
index 58ff5fc48..0571643c6 100644
--- a/src/ap/nan_usd_ap.h
+++ b/src/ap/nan_usd_ap.h
@@ -21,7 +21,7 @@ void hostapd_nan_usd_flush(struct hostapd_data *hapd);
int hostapd_nan_usd_publish(struct hostapd_data *hapd, const char *service_name,
enum nan_service_protocol_type srv_proto_type,
const struct wpabuf *ssi,
- struct nan_publish_params *params);
+ struct nan_publish_params *params, bool p2p);
void hostapd_nan_usd_cancel_publish(struct hostapd_data *hapd, int publish_id);
int hostapd_nan_usd_update_publish(struct hostapd_data *hapd, int publish_id,
const struct wpabuf *ssi);
@@ -29,7 +29,7 @@ int hostapd_nan_usd_subscribe(struct hostapd_data *hapd,
const char *service_name,
enum nan_service_protocol_type srv_proto_type,
const struct wpabuf *ssi,
- struct nan_subscribe_params *params);
+ struct nan_subscribe_params *params, bool p2p);
void hostapd_nan_usd_cancel_subscribe(struct hostapd_data *hapd,
int subscribe_id);
int hostapd_nan_usd_transmit(struct hostapd_data *hapd, int handle,
diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h
index 0fe631026..578ea73a1 100644
--- a/src/common/ieee802_11_defs.h
+++ b/src/common/ieee802_11_defs.h
@@ -1425,6 +1425,7 @@ struct ieee80211_ampe_ie {
#define WPS_IE_VENDOR_TYPE 0x0050f204
#define OUI_WFA 0x506f9a
#define P2P_IE_VENDOR_TYPE 0x506f9a09
+#define P2P2_IE_VENDOR_TYPE 0x506f9a28
#define WFD_IE_VENDOR_TYPE 0x506f9a0a
#define WFD_OUI_TYPE 10
#define HS20_IE_VENDOR_TYPE 0x506f9a10
@@ -1740,6 +1741,12 @@ enum p2p_attr_id {
P2P_ATTR_SESSION_ID = 26,
P2P_ATTR_FEATURE_CAPABILITY = 27,
P2P_ATTR_PERSISTENT_GROUP = 28,
+ P2P_ATTR_CAPABILITY_EXTENSION = 29,
+ P2P_ATTR_DEVICE_IDENTITY_KEY = 31,
+ P2P_ATTR_DEVICE_IDENTITY_RESOLUTION = 32,
+ P2P_ATTR_PAIRING_AND_BOOTSTRAPPING = 33,
+ P2P_ATTR_PASSWORD = 34,
+ P2P_ATTR_ACTION_FRAME_WRAPPER = 35,
P2P_ATTR_VENDOR_SPECIFIC = 221
};
@@ -1764,6 +1771,18 @@ enum p2p_attr_id {
#define P2P_GROUP_CAPAB_GROUP_FORMATION BIT(6)
#define P2P_GROUP_CAPAB_IP_ADDR_ALLOCATION BIT(7)
+/* P2P Capability Extension attribute - Capability info */
+#define P2P_PCEA_LEN_MASK (BIT(0) | BIT(1) | BIT(2) | BIT(3))
+#define P2P_PCEA_6GHZ BIT(4)
+#define P2P_PCEA_REG_INFO BIT(5)
+#define P2P_PCEA_DFS_OWNER BIT(6)
+#define P2P_PCEA_CLI_REQ_CS BIT(7)
+#define P2P_PCEA_PAIRING_CAPABLE BIT(8)
+#define P2P_PCEA_PAIRING_SETUP_ENABLE BIT(9)
+#define P2P_PCEA_PMK_CACHING BIT(10)
+#define P2P_PCEA_PASN_TYPE BIT(11)
+#define P2P_PCEA_TWT_POWER_MGMT BIT(12)
+
/* P2PS Coordination Protocol Transport Bitmap */
#define P2PS_FEATURE_CAPAB_UDP_TRANSPORT BIT(0)
#define P2PS_FEATURE_CAPAB_MAC_TRANSPORT BIT(1)
diff --git a/src/common/nan_de.c b/src/common/nan_de.c
index ecc73c5fd..7017311b6 100644
--- a/src/common/nan_de.c
+++ b/src/common/nan_de.c
@@ -58,6 +58,7 @@ struct nan_de_service {
struct os_reltime next_publish_state;
struct os_reltime next_publish_chan;
unsigned int next_publish_duration;
+ bool is_p2p;
};
struct nan_de {
@@ -1215,7 +1216,7 @@ const u8 * nan_de_get_service_id(struct nan_de *de, int id)
int nan_de_publish(struct nan_de *de, const char *service_name,
enum nan_service_protocol_type srv_proto_type,
const struct wpabuf *ssi, const struct wpabuf *elems,
- struct nan_publish_params *params)
+ struct nan_publish_params *params, bool p2p)
{
int publish_id;
struct nan_de_service *srv;
@@ -1271,6 +1272,7 @@ int nan_de_publish(struct nan_de *de, const char *service_name,
wpa_printf(MSG_DEBUG, "NAN: Assigned new publish handle %d for %s",
publish_id, service_name);
srv->id = publish_id;
+ srv->is_p2p = p2p;
nan_de_add_srv(de, srv);
nan_de_run_timer(de);
return publish_id;
@@ -1322,7 +1324,7 @@ int nan_de_update_publish(struct nan_de *de, int publish_id,
int nan_de_subscribe(struct nan_de *de, const char *service_name,
enum nan_service_protocol_type srv_proto_type,
const struct wpabuf *ssi, const struct wpabuf *elems,
- struct nan_subscribe_params *params)
+ struct nan_subscribe_params *params, bool p2p)
{
int subscribe_id;
struct nan_de_service *srv;
@@ -1362,6 +1364,7 @@ int nan_de_subscribe(struct nan_de *de, const char *service_name,
wpa_printf(MSG_DEBUG, "NAN: Assigned new subscribe handle %d for %s",
subscribe_id, service_name);
srv->id = subscribe_id;
+ srv->is_p2p = p2p;
nan_de_add_srv(de, srv);
nan_de_run_timer(de);
return subscribe_id;
diff --git a/src/common/nan_de.h b/src/common/nan_de.h
index ae77cf399..bdac284b4 100644
--- a/src/common/nan_de.h
+++ b/src/common/nan_de.h
@@ -106,7 +106,7 @@ struct nan_publish_params {
int nan_de_publish(struct nan_de *de, const char *service_name,
enum nan_service_protocol_type srv_proto_type,
const struct wpabuf *ssi, const struct wpabuf *elems,
- struct nan_publish_params *params);
+ struct nan_publish_params *params, bool p2p);
void nan_de_cancel_publish(struct nan_de *de, int publish_id);
@@ -133,7 +133,7 @@ struct nan_subscribe_params {
int nan_de_subscribe(struct nan_de *de, const char *service_name,
enum nan_service_protocol_type srv_proto_type,
const struct wpabuf *ssi, const struct wpabuf *elems,
- struct nan_subscribe_params *params);
+ struct nan_subscribe_params *params, bool p2p);
void nan_de_cancel_subscribe(struct nan_de *de, int subscribe_id);
diff --git a/src/p2p/p2p.c b/src/p2p/p2p.c
index 8e0fc35df..a2d09624d 100644
--- a/src/p2p/p2p.c
+++ b/src/p2p/p2p.c
@@ -16,6 +16,7 @@
#include "common/wpa_ctrl.h"
#include "crypto/sha256.h"
#include "crypto/crypto.h"
+#include "crypto/random.h"
#include "wps/wps_i.h"
#include "p2p_i.h"
#include "p2p.h"
@@ -2967,6 +2968,37 @@ bool is_p2p_6ghz_disabled(struct p2p_data *p2p)
return false;
}
+int p2p_pairing_info_init(struct p2p_data *p2p)
+{
+ struct p2p_pairing_info *pairing_info;
+
+ if (!p2p) {
+ p2p_dbg(p2p, "P2P data NULL");
+ return -1;
+ }
+
+ pairing_info = os_zalloc(sizeof(struct p2p_pairing_info));
+ if (!pairing_info)
+ return -1;
+
+ pairing_info->enable_pairing_setup =
+ p2p->cfg->pairing_config.enable_pairing_setup;
+ pairing_info->enable_pairing_cache =
+ p2p->cfg->pairing_config.enable_pairing_cache;
+ pairing_info->supported_bootstrap =
+ p2p->cfg->pairing_config.bootstrap_methods;
+
+ /* TODO: Add support to fetch DIK from p2p_supplicant.conf
+ * DIK should be same across device reboots
+ */
+ pairing_info->dev_ik.cipher_version = DIRA_CIPHER_VERSION_128;
+ pairing_info->dev_ik.dik_len = DEVICE_IDENTITY_KEY_LEN;
+ random_get_bytes(pairing_info->dev_ik.dik_data,
+ pairing_info->dev_ik.dik_len);
+ p2p->pairing_info = pairing_info;
+
+ return 0;
+}
struct p2p_data * p2p_init(const struct p2p_config *cfg)
{
@@ -3023,6 +3055,7 @@ struct p2p_data * p2p_init(const struct p2p_config *cfg)
p2p->go_timeout = 100;
p2p->client_timeout = 20;
p2p->num_p2p_sd_queries = 0;
+ p2p_pairing_info_init(p2p);
p2p_dbg(p2p, "initialized");
p2p_channels_dump(p2p, "channels", &p2p->cfg->channels);
@@ -3031,6 +3064,10 @@ struct p2p_data * p2p_init(const struct p2p_config *cfg)
return p2p;
}
+void p2p_pairing_info_deinit(struct p2p_data *p2p)
+{
+ os_free(p2p->pairing_info);
+}
void p2p_deinit(struct p2p_data *p2p)
{
@@ -3066,6 +3103,7 @@ void p2p_deinit(struct p2p_data *p2p)
p2p_remove_wps_vendor_extensions(p2p);
os_free(p2p->no_go_freq.range);
p2p_service_flush_asp(p2p);
+ p2p_pairing_info_deinit(p2p);
os_free(p2p);
}
@@ -5688,3 +5726,52 @@ void set_p2p_allow_6ghz(struct p2p_data *p2p, bool value)
{
p2p->allow_6ghz = value;
}
+
+
+struct wpabuf * p2p_usd_elems(struct p2p_data *p2p)
+{
+ struct wpabuf *buf;
+ u8 *len;
+ u8 group_capab;
+
+ buf = wpabuf_alloc(1000);
+ if (!buf)
+ return NULL;
+
+ len = p2p_buf_add_ie_hdr(buf);
+
+ /* P2P Capability attribute */
+ group_capab = 0;
+ if (p2p->num_groups) {
+ group_capab |= P2P_GROUP_CAPAB_GROUP_OWNER;
+ if ((p2p->dev_capab & P2P_DEV_CAPAB_CONCURRENT_OPER) &&
+ (p2p->dev_capab & P2P_DEV_CAPAB_INFRA_MANAGED) &&
+ p2p->cross_connect)
+ group_capab |= P2P_GROUP_CAPAB_CROSS_CONN;
+ }
+ if (p2p->cfg->p2p_intra_bss)
+ group_capab |= P2P_GROUP_CAPAB_INTRA_BSS_DIST;
+ p2p_buf_add_capability(buf, p2p->dev_capab &
+ ~P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY,
+ group_capab);
+
+ /* P2P Device Info attribute */
+ p2p_buf_add_device_info(buf, p2p, NULL);
+
+ p2p_buf_update_ie_hdr(buf, len);
+
+ len = p2p_buf_add_p2p2_ie_hdr(buf);
+ /* P2P Capability Extension attribute */
+ p2p_buf_add_pcea(buf, p2p);
+
+ /* P2P Pairing Bootstrapping Method attribute */
+ p2p_buf_add_pbma(buf, p2p->cfg->pairing_config.bootstrap_methods, NULL,
+ 0, 0);
+
+ /* P2P Device Identity Resolution attribute */
+ p2p_buf_add_dira(buf, p2p);
+
+ p2p_buf_update_p2p2_ie_hdr(buf, len);
+
+ return buf;
+}
diff --git a/src/p2p/p2p.h b/src/p2p/p2p.h
index 27bdac3bf..67124e3c9 100644
--- a/src/p2p/p2p.h
+++ b/src/p2p/p2p.h
@@ -320,6 +320,42 @@ enum p2p_scan_type {
#define P2P_MAX_WPS_VENDOR_EXT 10
+/**
+ * struct p2p_pairing_config - P2P pairing config.
+ */
+struct p2p_pairing_config {
+ /**
+ * Pairing capable
+ */
+ u8 pairing_capable;
+
+ /**
+ * Enable P2P pairing setup
+ */
+ u32 enable_pairing_setup;
+
+ /**
+ * Enable pairing cache to allow verification
+ */
+ u32 enable_pairing_cache;
+
+ /**
+ * Enable P2P pairing verification with cached NIK/NPK
+ */
+ u32 enable_pairing_verification;
+
+ /**
+ * P2P bootstrapping methods supported
+ */
+ u16 bootstrap_methods;
+
+ /**
+ * The set of supported PASN type
+ */
+ u8 pasn_type;
+};
+
+
/**
* struct p2p_peer_info - P2P peer information
*/
@@ -589,6 +625,31 @@ struct p2p_config {
*/
unsigned int passphrase_len;
+ /**
+ * p2p_pairing_config - P2P Pairing configuration
+ */
+ struct p2p_pairing_config pairing_config;
+
+ /**
+ * p2p_6ghz_enable - 6GHz enable for P2P operations
+ */
+ bool p2p_6ghz_enable;
+
+ /**
+ * reg_info - regulatory info encoding for operation in 6 GHz band
+ */
+ u8 reg_info;
+
+ /**
+ * dfs_owner - Enable p2p GO to act as DFS Owner
+ */
+ bool dfs_owner;
+
+ /**
+ * twt_power_mgmt - Enable TWT based power mgmt for P2P
+ */
+ bool twt_power_mgmt;
+
/**
* cb_ctx - Context to use with callback functions
*/
@@ -2429,5 +2490,6 @@ bool is_p2p_allow_6ghz(struct p2p_data *p2p);
void set_p2p_allow_6ghz(struct p2p_data *p2p, bool value);
int p2p_remove_6ghz_channels(struct weighted_pcl *pref_freq_list, int size);
int p2p_channel_to_freq(int op_class, int channel);
+struct wpabuf * p2p_usd_elems(struct p2p_data *p2p);
#endif /* P2P_H */
diff --git a/src/p2p/p2p_build.c b/src/p2p/p2p_build.c
index e4f40fe8f..641f9dd47 100644
--- a/src/p2p/p2p_build.c
+++ b/src/p2p/p2p_build.c
@@ -12,10 +12,11 @@
#include "common/ieee802_11_defs.h"
#include "common/ieee802_11_common.h"
#include "common/qca-vendor.h"
+#include "crypto/random.h"
+#include "crypto/sha256.h"
#include "wps/wps_i.h"
#include "p2p_i.h"
-
void p2p_buf_add_action_hdr(struct wpabuf *buf, u8 subtype, u8 dialog_token)
{
wpabuf_put_u8(buf, WLAN_ACTION_VENDOR_SPECIFIC);
@@ -59,6 +60,24 @@ void p2p_buf_update_ie_hdr(struct wpabuf *buf, u8 *len)
*len = (u8 *) wpabuf_put(buf, 0) - len - 1;
}
+u8 * p2p_buf_add_p2p2_ie_hdr(struct wpabuf *buf)
+{
+ u8 *len;
+
+ /* P2P2 IE header */
+ wpabuf_put_u8(buf, WLAN_EID_VENDOR_SPECIFIC);
+ len = wpabuf_put(buf, 1); /* IE length to be filled */
+ wpabuf_put_be32(buf, P2P2_IE_VENDOR_TYPE);
+ wpa_printf(MSG_DEBUG, "P2P: * P2P2 IE header");
+ return len;
+}
+
+
+void p2p_buf_update_p2p2_ie_hdr(struct wpabuf *buf, u8 *len)
+{
+ /* Update P2P2 IE Length */
+ *len = (u8 *) wpabuf_put(buf, 0) - len - 1;
+}
void p2p_buf_add_capability(struct wpabuf *buf, u8 dev_capab, u8 group_capab)
{
@@ -709,6 +728,167 @@ void p2p_buf_add_persistent_group_info(struct wpabuf *buf, const u8 *dev_addr,
}
+void p2p_buf_add_pcea(struct wpabuf *buf, struct p2p_data *p2p)
+{
+ u8 *len;
+ u16 capability_info = 0;
+
+ /* P2P Capability Extension */
+ wpabuf_put_u8(buf, P2P_ATTR_CAPABILITY_EXTENSION);
+ /* Length to be filled */
+ len = wpabuf_put(buf, 2);
+
+ if (p2p->cfg->p2p_6ghz_enable)
+ capability_info |= P2P_PCEA_6GHZ;
+
+ if (p2p->cfg->reg_info)
+ capability_info |= P2P_PCEA_REG_INFO;
+
+ if (p2p->cfg->dfs_owner)
+ capability_info |= P2P_PCEA_DFS_OWNER;
+
+ if (p2p->cfg->pairing_config.pairing_capable)
+ capability_info |= P2P_PCEA_PAIRING_CAPABLE;
+
+ if (p2p->cfg->pairing_config.enable_pairing_setup)
+ capability_info |= P2P_PCEA_PAIRING_SETUP_ENABLE;
+
+ if (p2p->cfg->pairing_config.enable_pairing_cache)
+ capability_info |= P2P_PCEA_PMK_CACHING;
+
+ if (p2p->cfg->pairing_config.pasn_type)
+ capability_info |= P2P_PCEA_PASN_TYPE;
+
+ if (p2p->cfg->twt_power_mgmt)
+ capability_info |= P2P_PCEA_TWT_POWER_MGMT;
+
+ /* Field length is (n-1), n in octets */
+ capability_info |= (2 - 1) & P2P_PCEA_LEN_MASK;
+ wpabuf_put_le16(buf, capability_info);
+
+ if (capability_info & P2P_PCEA_REG_INFO)
+ wpabuf_put_u8(buf, p2p->cfg->reg_info);
+
+ if (capability_info & P2P_PCEA_PASN_TYPE)
+ wpabuf_put_u8(buf, p2p->cfg->pairing_config.pasn_type);
+
+ /* Update attribute length */
+ WPA_PUT_LE16(len, (u8 *) wpabuf_put(buf, 0) - len - 2);
+
+ wpa_printf(MSG_DEBUG, "P2P: * Capability Extension info=0x%x",
+ capability_info);
+}
+
+void p2p_buf_add_pbma(struct wpabuf *buf, u16 bootstrap, const u8 *cookie,
+ size_t cookie_len, int comeback_after)
+{
+ u8 *len;
+
+ if (!bootstrap)
+ return;
+
+ /* P2P Pairing and Bootstrapping methods */
+ wpabuf_put_u8(buf, P2P_ATTR_PAIRING_AND_BOOTSTRAPPING);
+ /* Length to be filled */
+ len = wpabuf_put(buf, 2);
+
+ if (cookie && cookie_len) {
+ if (comeback_after)
+ wpabuf_put_le16(buf, comeback_after);
+ wpabuf_put_u8(buf, cookie_len);
+ wpabuf_put_data(buf, cookie, cookie_len);
+ }
+ wpabuf_put_le16(buf, bootstrap);
+
+ /* Update attribute length */
+ WPA_PUT_LE16(len, (u8 *) wpabuf_put(buf, 0) - len - 2);
+
+ wpa_printf(MSG_DEBUG, "P2P: * Bootstrapping method=0x%x",
+ bootstrap);
+}
+
+static int p2p_derive_nonce_tag(struct p2p_data *p2p)
+{
+ int ret;
+ u8 dira_nonce[DEVICE_IDENTITY_NONCE_LEN];
+ u8 dira_tag[DEVICE_MAX_HASH_LEN];
+ u8 data[DIR_STR_LEN + DEVICE_IDENTITY_NONCE_LEN + ETH_ALEN];
+ struct p2p_id_key *dev_ik;
+
+ dev_ik = &p2p->pairing_info->dev_ik;
+
+ if (dev_ik->cipher_version != DIRA_CIPHER_VERSION_128) {
+ wpa_printf(MSG_ERROR, "Unsupported DIRA Cipher version = %d",
+ dev_ik->cipher_version);
+ return -1;
+ }
+
+ if (dev_ik->dik_len != DEVICE_IDENTITY_KEY_LEN) {
+ wpa_printf(MSG_ERROR, "Invalid DIK length = %ld",
+ dev_ik->dik_len);
+ return -1;
+ }
+
+ if (dev_ik->dira_nonce_len && dev_ik->dira_tag_len)
+ return 0;
+
+ os_memset(data, 0, sizeof(data));
+ os_memset(dira_tag, 0, sizeof(dira_tag));
+
+ ret = random_get_bytes(dira_nonce, DEVICE_IDENTITY_NONCE_LEN);
+ if (ret < 0) {
+ wpa_printf(MSG_ERROR, "Get DIRA nonce Failed, err = %d", ret);
+ return -1;
+ }
+
+ os_memcpy(data, "DIR", DIR_STR_LEN);
+ os_memcpy(&data[DIR_STR_LEN], p2p->cfg->dev_addr, ETH_ALEN);
+ os_memcpy(&data[DIR_STR_LEN + ETH_ALEN], dira_nonce,
+ DEVICE_IDENTITY_NONCE_LEN);
+
+ ret = hmac_sha256(dev_ik->dik_data, DEVICE_IDENTITY_KEY_LEN, data,
+ sizeof(data), dira_tag);
+ if (ret < 0) {
+ wpa_printf(MSG_ERROR, "Could not derive DIRA tag, err = %d", ret);
+ return -1;
+ }
+
+ dev_ik->dira_nonce_len = DEVICE_IDENTITY_NONCE_LEN;
+ os_memcpy(dev_ik->dira_nonce, dira_nonce, DEVICE_IDENTITY_NONCE_LEN);
+ dev_ik->dira_tag_len = DEVICE_IDENTITY_TAG_LEN;
+ os_memcpy(dev_ik->dira_tag, dira_tag, DEVICE_IDENTITY_TAG_LEN);
+ return 0;
+}
+
+void p2p_buf_add_dira(struct wpabuf *buf, struct p2p_data *p2p)
+{
+ u8 *len;
+ struct p2p_id_key *dev_ik;
+
+ if (!p2p->cfg->pairing_config.pairing_capable ||
+ !p2p->cfg->pairing_config.enable_pairing_cache ||
+ !p2p->cfg->pairing_config.enable_pairing_verification)
+ return;
+
+ if (p2p_derive_nonce_tag(p2p))
+ return;
+
+ dev_ik = &p2p->pairing_info->dev_ik;
+ /* P2P DIRA */
+ wpabuf_put_u8(buf, P2P_ATTR_DEVICE_IDENTITY_RESOLUTION);
+ /* Length to be filled */
+ len = wpabuf_put(buf, 2);
+
+ wpabuf_put_u8(buf, dev_ik->cipher_version);
+ wpabuf_put_data(buf, dev_ik->dira_nonce, dev_ik->dira_nonce_len);
+ wpabuf_put_data(buf, dev_ik->dira_tag, dev_ik->dira_tag_len);
+
+ /* Update attribute length */
+ WPA_PUT_LE16(len, (u8 *)wpabuf_put(buf, 0) - len - 2);
+
+ wpa_printf(MSG_DEBUG, "P2P: * Added DIRA");
+}
+
static int p2p_add_wps_string(struct wpabuf *buf, enum wps_attribute attr,
const char *val)
{
diff --git a/src/p2p/p2p_i.h b/src/p2p/p2p_i.h
index 0a487e031..0e24e51ab 100644
--- a/src/p2p/p2p_i.h
+++ b/src/p2p/p2p_i.h
@@ -14,6 +14,11 @@
#include "p2p.h"
#define P2P_GO_NEG_CNF_MAX_RETRY_COUNT 1
+#define DEVICE_IDENTITY_KEY_LEN 16
+#define DEVICE_IDENTITY_TAG_LEN 8
+#define DEVICE_IDENTITY_NONCE_LEN 8
+#define DEVICE_MAX_HASH_LEN 32
+#define DIR_STR_LEN 3
/*
* A threshold (in seconds) to prefer a direct Probe Response frame from a P2P
@@ -160,6 +165,44 @@ struct p2p_sd_query {
struct wpabuf *tlvs;
};
+/* DIRA Cipher versions */
+#define DIRA_CIPHER_VERSION_128 0
+
+/* This is p2p device identity key params */
+struct p2p_id_key {
+ /* AKMP used for DevIK derviation */
+ int akmp;
+ /* cipher version type */
+ int cipher_version;
+ /* DevIK expiration time in seconds */
+ u32 expiration;
+ /* buffer to hold the DevIK */
+ u8 dik_data[DEVICE_IDENTITY_KEY_LEN];
+ /* length of DevIK */
+ size_t dik_len;
+ /* nonce used in DIRA attribute */
+ u8 dira_nonce[DEVICE_IDENTITY_NONCE_LEN];
+ /* length of nonce */
+ size_t dira_nonce_len;
+ /* tag computed for nonce using NIK */
+ u8 dira_tag[DEVICE_IDENTITY_TAG_LEN];
+ /* length of tag */
+ size_t dira_tag_len;
+};
+
+struct p2p_pairing_info {
+ /* P2P device own address */
+ u8 own_addr[ETH_ALEN];
+ /* device capability to enable pairing setup */
+ u32 enable_pairing_setup;
+ /* device capability to enable pairing cache */
+ u32 enable_pairing_cache;
+ /* device supported bootstrapping */
+ u16 supported_bootstrap;
+ /* p2p device identity key info */
+ struct p2p_id_key dev_ik;
+};
+
/**
* struct p2p_data - P2P module data (internal to P2P module)
*/
@@ -554,6 +597,8 @@ struct p2p_data {
bool p2p_6ghz_capable;
bool include_6ghz;
bool allow_6ghz;
+
+ struct p2p_pairing_info *pairing_info;
};
/**
@@ -748,11 +793,13 @@ void p2p_buf_add_action_hdr(struct wpabuf *buf, u8 subtype, u8 dialog_token);
void p2p_buf_add_public_action_hdr(struct wpabuf *buf, u8 subtype,
u8 dialog_token);
u8 * p2p_buf_add_ie_hdr(struct wpabuf *buf);
+u8 * p2p_buf_add_p2p2_ie_hdr(struct wpabuf *buf);
void p2p_buf_add_status(struct wpabuf *buf, u8 status);
void p2p_buf_add_device_info(struct wpabuf *buf, struct p2p_data *p2p,
struct p2p_device *peer);
void p2p_buf_add_device_id(struct wpabuf *buf, const u8 *dev_addr);
void p2p_buf_update_ie_hdr(struct wpabuf *buf, u8 *len);
+void p2p_buf_update_p2p2_ie_hdr(struct wpabuf *buf, u8 *len);
void p2p_buf_add_capability(struct wpabuf *buf, u8 dev_capab, u8 group_capab);
void p2p_buf_add_go_intent(struct wpabuf *buf, u8 go_intent);
void p2p_buf_add_listen_channel(struct wpabuf *buf, const char *country,
@@ -788,6 +835,10 @@ void p2p_buf_add_feature_capability(struct wpabuf *buf, u16 len,
const u8 *mask);
void p2p_buf_add_persistent_group_info(struct wpabuf *buf, const u8 *dev_addr,
const u8 *ssid, size_t ssid_len);
+void p2p_buf_add_pcea(struct wpabuf *buf, struct p2p_data *p2p);
+void p2p_buf_add_pbma(struct wpabuf *buf, u16 bootstrap, const u8 *cookie,
+ size_t cookie_len, int comeback_after);
+void p2p_buf_add_dira(struct wpabuf *buf, struct p2p_data *p2p);
int p2p_build_wps_ie(struct p2p_data *p2p, struct wpabuf *buf, int pw_id,
int all_attr);
void p2p_buf_add_pref_channel_list(struct wpabuf *buf,
diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c
index 74d61132e..03434c5ef 100644
--- a/wpa_supplicant/ctrl_iface.c
+++ b/wpa_supplicant/ctrl_iface.c
@@ -12193,6 +12193,7 @@ static int wpas_ctrl_nan_publish(struct wpa_supplicant *wpa_s, char *cmd,
int ret = -1;
enum nan_service_protocol_type srv_proto_type = 0;
int *freq_list = NULL;
+ bool p2p = false;
os_memset(¶ms, 0, sizeof(params));
/* USD shall use both solicited and unsolicited transmissions */
@@ -12253,6 +12254,11 @@ static int wpas_ctrl_nan_publish(struct wpa_supplicant *wpa_s, char *cmd,
continue;
}
+ if (os_strcmp(token, "p2p=1") == 0) {
+ p2p = true;
+ continue;
+ }
+
if (os_strcmp(token, "solicited=0") == 0) {
params.solicited = false;
continue;
@@ -12274,7 +12280,7 @@ static int wpas_ctrl_nan_publish(struct wpa_supplicant *wpa_s, char *cmd,
}
publish_id = wpas_nan_usd_publish(wpa_s, service_name, srv_proto_type,
- ssi, ¶ms);
+ ssi, ¶ms, p2p);
if (publish_id > 0)
ret = os_snprintf(buf, buflen, "%d", publish_id);
fail:
@@ -12358,6 +12364,7 @@ static int wpas_ctrl_nan_subscribe(struct wpa_supplicant *wpa_s, char *cmd,
struct wpabuf *ssi = NULL;
int ret = -1;
enum nan_service_protocol_type srv_proto_type = 0;
+ bool p2p = false;
os_memset(¶ms, 0, sizeof(params));
params.freq = NAN_USD_DEFAULT_FREQ;
@@ -12397,6 +12404,11 @@ static int wpas_ctrl_nan_subscribe(struct wpa_supplicant *wpa_s, char *cmd,
continue;
}
+ if (os_strcmp(token, "p2p=1") == 0) {
+ p2p = true;
+ continue;
+ }
+
wpa_printf(MSG_INFO,
"CTRL: Invalid NAN_SUBSCRIBE parameter: %s",
token);
@@ -12405,7 +12417,7 @@ static int wpas_ctrl_nan_subscribe(struct wpa_supplicant *wpa_s, char *cmd,
subscribe_id = wpas_nan_usd_subscribe(wpa_s, service_name,
srv_proto_type, ssi,
- ¶ms);
+ ¶ms, p2p);
if (subscribe_id > 0)
ret = os_snprintf(buf, buflen, "%d", subscribe_id);
fail:
diff --git a/wpa_supplicant/nan_usd.c b/wpa_supplicant/nan_usd.c
index 3fea540b9..0b329499f 100644
--- a/wpa_supplicant/nan_usd.c
+++ b/wpa_supplicant/nan_usd.c
@@ -13,6 +13,7 @@
#include "wpa_supplicant_i.h"
#include "offchannel.h"
#include "driver_i.h"
+#include "p2p_supplicant.h"
#include "nan_usd.h"
@@ -386,7 +387,7 @@ void wpas_nan_usd_flush(struct wpa_supplicant *wpa_s)
int wpas_nan_usd_publish(struct wpa_supplicant *wpa_s, const char *service_name,
enum nan_service_protocol_type srv_proto_type,
const struct wpabuf *ssi,
- struct nan_publish_params *params)
+ struct nan_publish_params *params, bool p2p)
{
int publish_id;
struct wpabuf *elems = NULL;
@@ -394,8 +395,11 @@ int wpas_nan_usd_publish(struct wpa_supplicant *wpa_s, const char *service_name,
if (!wpa_s->nan_de)
return -1;
+ if (p2p)
+ elems = wpas_p2p_usd_elems(wpa_s);
+
publish_id = nan_de_publish(wpa_s->nan_de, service_name, srv_proto_type,
- ssi, elems, params);
+ ssi, elems, params, p2p);
if (publish_id <= 0)
goto fail;
if ((wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_NAN_OFFLOAD) &&
@@ -443,7 +447,7 @@ int wpas_nan_usd_subscribe(struct wpa_supplicant *wpa_s,
const char *service_name,
enum nan_service_protocol_type srv_proto_type,
const struct wpabuf *ssi,
- struct nan_subscribe_params *params)
+ struct nan_subscribe_params *params, bool p2p)
{
int subscribe_id;
struct wpabuf *elems = NULL;
@@ -451,8 +455,12 @@ int wpas_nan_usd_subscribe(struct wpa_supplicant *wpa_s,
if (!wpa_s->nan_de)
return -1;
+ if (p2p)
+ elems = wpas_p2p_usd_elems(wpa_s);
+
subscribe_id = nan_de_subscribe(wpa_s->nan_de, service_name,
- srv_proto_type, ssi, elems, params);
+ srv_proto_type, ssi, elems, params,
+ p2p);
if (subscribe_id <= 0)
goto fail;
if ((wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_NAN_OFFLOAD) &&
diff --git a/wpa_supplicant/nan_usd.h b/wpa_supplicant/nan_usd.h
index 149ac9e60..ecb4973c4 100644
--- a/wpa_supplicant/nan_usd.h
+++ b/wpa_supplicant/nan_usd.h
@@ -21,7 +21,7 @@ void wpas_nan_usd_flush(struct wpa_supplicant *wpa_s);
int wpas_nan_usd_publish(struct wpa_supplicant *wpa_s, const char *service_name,
enum nan_service_protocol_type srv_proto_type,
const struct wpabuf *ssi,
- struct nan_publish_params *params);
+ struct nan_publish_params *params, bool p2p);
void wpas_nan_usd_cancel_publish(struct wpa_supplicant *wpa_s, int publish_id);
int wpas_nan_usd_update_publish(struct wpa_supplicant *wpa_s, int publish_id,
const struct wpabuf *ssi);
@@ -29,7 +29,7 @@ int wpas_nan_usd_subscribe(struct wpa_supplicant *wpa_s,
const char *service_name,
enum nan_service_protocol_type srv_proto_type,
const struct wpabuf *ssi,
- struct nan_subscribe_params *params);
+ struct nan_subscribe_params *params, bool p2p);
void wpas_nan_usd_cancel_subscribe(struct wpa_supplicant *wpa_s,
int subscribe_id);
int wpas_nan_usd_transmit(struct wpa_supplicant *wpa_s, int handle,
diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c
index 70025f1e4..2df2d108b 100644
--- a/wpa_supplicant/p2p_supplicant.c
+++ b/wpa_supplicant/p2p_supplicant.c
@@ -10242,3 +10242,13 @@ int wpas_p2p_lo_stop(struct wpa_supplicant *wpa_s)
wpa_s->p2p_lo_started = 0;
return ret;
}
+
+
+struct wpabuf * wpas_p2p_usd_elems(struct wpa_supplicant *wpa_s)
+{
+ struct p2p_data *p2p = wpa_s->global->p2p;
+
+ if (wpa_s->global->p2p_disabled || !p2p)
+ return NULL;
+ return p2p_usd_elems(p2p);
+}
diff --git a/wpa_supplicant/p2p_supplicant.h b/wpa_supplicant/p2p_supplicant.h
index d71f7701c..441e063d9 100644
--- a/wpa_supplicant/p2p_supplicant.h
+++ b/wpa_supplicant/p2p_supplicant.h
@@ -225,6 +225,7 @@ int wpas_p2p_lo_start(struct wpa_supplicant *wpa_s, unsigned int freq,
unsigned int count);
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);
#else /* CONFIG_P2P */
@@ -351,6 +352,11 @@ static inline int wpas_p2p_group_remove(struct wpa_supplicant *wpa_s,
return 0;
}
+static inline struct wpabuf * wpas_p2p_usd_elems(struct wpa_supplicant *wpa_s)
+{
+ return NULL;
+}
+
#endif /* CONFIG_P2P */
#endif /* P2P_SUPPLICANT_H */
--
2.34.1
More information about the Hostap
mailing list