[PATCH 09/34] PR: API to derive and add DIRA in USD PR IE
Peddolla Harshavardhan Reddy
peddolla at qti.qualcomm.com
Thu Jun 19 08:37:02 PDT 2025
Add changes to derive the Device Identity Resolution Attribute
(DIRA) and add it to the Proximity Ranging Information Element
(PR IE). The DIRA attribute is used to resolve the identity of a
device even when MAC randomization causes the peer device's
MAC address to change. The DIRA attribute includes fields such as
the cipher version, a nonce, and a tag.
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 47d0efdb3..02c1f82ea 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)
{
@@ -325,6 +385,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;
@@ -332,6 +412,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)
@@ -350,6 +431,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 9a1fd6b5b..87b744d4c 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
/**
* PR_MAX_OP_CLASSES - Maximum number of operating classes
@@ -281,6 +288,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