[RFC PATCH 09/34] API to derive and add DIRA in USD PR IE

Peddolla Harshavardhan Reddy peddolla at qti.qualcomm.com
Thu May 15 00:17:32 PDT 2025


Signed-off-by: Peddolla Harshavardhan Reddy <peddolla at qti.qualcomm.com>
---
 src/common/proximity_ranging.c | 85 ++++++++++++++++++++++++++++++++++
 src/common/proximity_ranging.h | 22 +++++++++
 2 files changed, 107 insertions(+)

diff --git a/src/common/proximity_ranging.c b/src/common/proximity_ranging.c
index 18701646b..33478bac3 100644
--- a/src/common/proximity_ranging.c
+++ b/src/common/proximity_ranging.c
@@ -14,6 +14,10 @@
 #include "common/qca-vendor.h"
 #include "wps/wps_i.h"
 #include "proximity_ranging.h"
+#include "crypto/sha256.h"
+#include "crypto/sha384.h"
+#include "crypto/crypto.h"
+
 
 static void pr_device_free(struct pr_data *pr, struct pr_device *dev)
 {
@@ -213,6 +217,62 @@ static void pr_get_ntb_capabilities(struct pr_data *pr,
 }
 
 
+static int pr_derive_dira(struct pr_data *pr, struct pr_dira *dira)
+{
+	u8 nonce[DEVICE_IDENTITY_NONCE_LEN];
+	u8 tag[DEVICE_MAX_HASH_LEN];
+	u8 data[DIR_STR_LEN + DEVICE_IDENTITY_NONCE_LEN + ETH_ALEN];
+
+	if (pr->cfg->dik_cipher != DIRA_CIPHER_VERSION_128) {
+		wpa_printf(MSG_ERROR,
+			   "PR: Unsupported DIRA Cipher version = %d",
+			   pr->cfg->dik_cipher);
+		return -1;
+	}
+
+	if (pr->cfg->dik_len != DEVICE_IDENTITY_KEY_LEN) {
+		wpa_printf(MSG_ERROR,
+			   "PR: Invalid DIK length = %zu", pr->cfg->dik_len);
+		return -1;
+	}
+
+	os_memset(data, 0, sizeof(data));
+
+	if (os_get_random(nonce, DEVICE_IDENTITY_NONCE_LEN) < 0) {
+		wpa_printf(MSG_ERROR, "PR: Failed to generate DIRA nonce");
+		return -1;
+	}
+
+	/* Tag = Truncate-64(HMAC-SHA-256(DevIK, "DIR" || PR Device Address ||
+	 *                                Nonce))
+	 */
+	os_memcpy(data, "DIR", DIR_STR_LEN);
+	os_memcpy(&data[DIR_STR_LEN], pr->cfg->dev_addr, ETH_ALEN);
+	os_memcpy(&data[DIR_STR_LEN + ETH_ALEN], nonce,
+		  DEVICE_IDENTITY_NONCE_LEN);
+
+	if (hmac_sha256(pr->cfg->dik_data, pr->cfg->dik_len, data, sizeof(data),
+			tag) < 0) {
+		wpa_printf(MSG_ERROR, "PR: Could not derive DIRA tag");
+		return -1;
+	}
+
+	os_memset(dira, 0, sizeof(struct pr_dira));
+	dira->cipher_version = pr->cfg->dik_cipher;
+	dira->nonce_len = DEVICE_IDENTITY_NONCE_LEN;
+	os_memcpy(dira->nonce, nonce, DEVICE_IDENTITY_NONCE_LEN);
+	dira->tag_len = DEVICE_IDENTITY_TAG_LEN;
+	os_memcpy(dira->tag, tag, DEVICE_IDENTITY_TAG_LEN);
+
+	wpa_hexdump_key(MSG_DEBUG, "PR: DIK", pr->cfg->dik_data,
+			pr->cfg->dik_len);
+	wpa_hexdump_key(MSG_DEBUG, "PR: DIRA-NONCE", dira->nonce,
+			dira->nonce_len);
+	wpa_hexdump_key(MSG_DEBUG, "PR: DIRA-TAG", dira->tag, dira->tag_len);
+	return 0;
+}
+
+
 static void pr_buf_add_channel_list(struct wpabuf *buf, const char *country,
 				    struct pr_channels *chan)
 {
@@ -327,6 +387,26 @@ static void pr_buf_add_ntb_capa_info(struct wpabuf *buf,
 }
 
 
+static void pr_buf_add_dira(struct wpabuf *buf, struct pr_dira *dira)
+{
+	u8 *len;
+
+	wpabuf_put_u8(buf, PR_ATTR_DEVICE_IDENTITY_RESOLUTION);
+
+	/* Length to be filled */
+	len = wpabuf_put(buf, 2);
+
+	wpabuf_put_u8(buf, dira->cipher_version);
+	wpabuf_put_data(buf, dira->nonce, dira->nonce_len);
+	wpabuf_put_data(buf, dira->tag, dira->tag_len);
+
+	/* Update attribute length */
+	WPA_PUT_LE16(len, (u8 *) wpabuf_put(buf, 0) - len - 2);
+
+	wpa_printf(MSG_DEBUG, "PR: * DIRA");
+}
+
+
 struct wpabuf * pr_prepare_usd_elems(struct pr_data *pr, const char *country)
 {
 	u32 ie_type;
@@ -334,6 +414,7 @@ struct wpabuf * pr_prepare_usd_elems(struct pr_data *pr, const char *country)
 	struct pr_capabilities pr_caps;
 	struct edca_capabilities edca_caps;
 	struct ntb_capabilities ntb_caps;
+	struct pr_dira dira;
 
 	buf = wpabuf_alloc(1000);
 	if (!buf)
@@ -352,6 +433,10 @@ struct wpabuf * pr_prepare_usd_elems(struct pr_data *pr, const char *country)
 		pr_buf_add_ntb_capa_info(buf, &ntb_caps);
 	}
 
+	/* PR Device Identity Resolution attribute */
+	if (!pr_derive_dira(pr, &dira))
+		pr_buf_add_dira(buf, &dira);
+
 	ie_type = (OUI_WFA << 8) | PR_OUI_TYPE;
 	buf2 = pr_encaps_ie(buf, ie_type);
 	wpabuf_free(buf);
diff --git a/src/common/proximity_ranging.h b/src/common/proximity_ranging.h
index d2847b62e..cbd7a7ef8 100644
--- a/src/common/proximity_ranging.h
+++ b/src/common/proximity_ranging.h
@@ -14,6 +14,13 @@
 #include "drivers/driver.h"
 
 #define DEVICE_IDENTITY_KEY_LEN 16
+#define DEVICE_IDENTITY_TAG_LEN 8
+#define DEVICE_IDENTITY_NONCE_LEN 8
+#define DIR_STR_LEN 3
+#define DEVICE_MAX_HASH_LEN 32
+
+/* DIRA Cipher versions */
+#define DIRA_CIPHER_VERSION_128 0
 
 /**
  * P2P_MAX_REG_CLASSES - Maximum number of regulatory classes
@@ -261,6 +268,21 @@ struct pr_data {
 	struct dl_list devices;
 };
 
+
+/* PR Device Identity Resolution Attribute parameters */
+struct pr_dira {
+	/* Cipher version type */
+	int cipher_version;
+	/* Nonce used in DIRA attribute */
+	u8 nonce[DEVICE_IDENTITY_NONCE_LEN];
+	/* Length of nonce */
+	size_t nonce_len;
+	/* Tag computed for nonce using NIK */
+	u8 tag[DEVICE_IDENTITY_TAG_LEN];
+	/* Length of tag in octets */
+	size_t tag_len;
+};
+
 struct pr_data * pr_init(const struct pr_config *cfg);
 void pr_deinit(struct pr_data *pr);
 struct wpabuf * pr_prepare_usd_elems(struct pr_data *pr, const char *country);
-- 
2.34.1




More information about the Hostap mailing list