diff mbox series

[v3,04/25] P2P: Add DIRA attributes to P2P2 IE of NAN SDFs

Message ID 1722850403-8852-5-git-send-email-quic_shivbara@quicinc.com
State Accepted
Headers show
Series Add support for P2P2 | expand

Commit Message

Shivani Baranwal Aug. 5, 2024, 9:33 a.m. UTC
Add DIRA attribute in P2P2 IE of NAN Subscribe and Publish frames
to enable support for Device identity of paired peers.

Signed-off-by: Shivani Baranwal <quic_shivbara@quicinc.com>
---
 src/p2p/p2p.c       | 10 ++++++
 src/p2p/p2p.h       | 18 +++++++++++
 src/p2p/p2p_build.c | 88 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/p2p/p2p_i.h     | 25 +++++++++++++++
 4 files changed, 141 insertions(+)
diff mbox series

Patch

diff --git a/src/p2p/p2p.c b/src/p2p/p2p.c
index 2f9482a..73fcb16 100644
--- a/src/p2p/p2p.c
+++ b/src/p2p/p2p.c
@@ -2987,6 +2987,13 @@  int p2p_pairing_info_init(struct p2p_data *p2p)
 	pairing_info->supported_bootstrap =
 				p2p->cfg->pairing_config.bootstrap_methods;
 
+	pairing_info->dev_ik.cipher_version =
+				p2p->cfg->pairing_config.dik_cipher;
+	pairing_info->dev_ik.dik_len =
+				p2p->cfg->pairing_config.dik_len;
+	os_memcpy(pairing_info->dev_ik.dik_data,
+		  p2p->cfg->pairing_config.dik_data,
+		  p2p->cfg->pairing_config.dik_len);
 	p2p->pairing_info = pairing_info;
 
 	return 0;
@@ -5760,6 +5767,9 @@  struct wpabuf * p2p_usd_elems(struct p2p_data *p2p)
 	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 700f839..b7d05e9 100644
--- a/src/p2p/p2p.h
+++ b/src/p2p/p2p.h
@@ -12,6 +12,16 @@ 
 #include "common/ieee802_11_defs.h"
 #include "wps/wps.h"
 
+#define DEVICE_IDENTITY_KEY_MAX_LEN 64
+#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
+
+/* DIRA Cipher versions */
+#define DIRA_CIPHER_VERSION_128 0
+
 struct weighted_pcl;
 
 /* P2P ASP Setup Capability */
@@ -354,6 +364,14 @@  struct p2p_pairing_config {
 	 */
 	u8 pasn_type;
 
+	/* cipher version type */
+	int dik_cipher;
+
+	/* buffer to hold the DevIK */
+	u8 dik_data[DEVICE_IDENTITY_KEY_MAX_LEN];
+
+	/* length of DevIK */
+	size_t dik_len;
 };
 
 
diff --git a/src/p2p/p2p_build.c b/src/p2p/p2p_build.c
index 4bdfb7e..347e8a1 100644
--- a/src/p2p/p2p_build.c
+++ b/src/p2p/p2p_build.c
@@ -12,6 +12,8 @@ 
 #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"
 
@@ -803,6 +805,92 @@  void p2p_buf_add_pbma(struct wpabuf *buf, u16 bootstrap, const u8 *cookie,
 		   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;
+	}
+
+	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, dev_ik->dik_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);
+
+	wpa_hexdump_key(MSG_DEBUG, "P2P: DIK", dev_ik->dik_data,
+			dev_ik->dik_len);
+	wpa_hexdump_key(MSG_DEBUG, "P2P: DIRA-NONCE", dev_ik->dira_nonce,
+			dev_ik->dira_nonce_len);
+	wpa_hexdump_key(MSG_DEBUG, "P2P: DIRA-TAG", dev_ik->dira_tag,
+			dev_ik->dira_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 381a02e..0879add 100644
--- a/src/p2p/p2p_i.h
+++ b/src/p2p/p2p_i.h
@@ -161,6 +161,28 @@  struct p2p_sd_query {
 };
 
 
+/* 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_MAX_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];
@@ -170,6 +192,8 @@  struct p2p_pairing_info {
 	u32 enable_pairing_cache;
 	/* device supported bootstrapping */
 	u16 supported_bootstrap;
+	/* p2p device identity key info */
+	struct p2p_id_key dev_ik;
 };
 
 /**
@@ -807,6 +831,7 @@  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);
 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,