[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