]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
PR: Validate DIRA from USD PR element
authorPeddolla Harshavardhan Reddy <peddolla@qti.qualcomm.com>
Sat, 26 Apr 2025 19:57:52 +0000 (01:27 +0530)
committerJouni Malinen <j@w1.fi>
Fri, 17 Oct 2025 10:22:51 +0000 (13:22 +0300)
Parse and validate the Proximity Ranging Device Identity Resolution
Attribute (PR DIRA). Compare the received Tag against a Tag derived
using each DIK in the list stored in the global Proximity Ranging
context. If the tags match, the device identity is confirmed and any
data associated with the matching DIK is retrieved for later use.

Signed-off-by: Peddolla Harshavardhan Reddy <peddolla@qti.qualcomm.com>
src/common/proximity_ranging.c

index 334c59dad328386faa4c0f63922490ff7fde77db..28475e624833da3349a0343e9c1802fd6a11cb1c 100644 (file)
@@ -364,6 +364,75 @@ static int pr_derive_dira(struct pr_data *pr, struct pr_dira *dira)
 }
 
 
+static int pr_validate_dira(struct pr_data *pr, struct pr_device *dev,
+                           const u8 *dira, u16 dira_len)
+{
+       int ret;
+       size_t len[3];
+       const u8 *addr[3];
+       struct pr_dev_ik *dev_ik;
+       u8 tag[DEVICE_MAX_HASH_LEN];
+       const char *label = "DIR";
+       const u8 *dira_nonce, *dira_tag;
+
+       if (dira_len < 1 + DEVICE_IDENTITY_NONCE_LEN + DEVICE_IDENTITY_TAG_LEN)
+       {
+               wpa_printf(MSG_DEBUG, "PR: Truncated DIRA (length %u)",
+                          dira_len);
+               return -1;
+       }
+
+       /* Cipher Version */
+       if (dira[0] != DIRA_CIPHER_VERSION_128) {
+               wpa_printf(MSG_DEBUG, "PR: Unsupported DIRA cipher version %d",
+                          dira[0]);
+               return -1;
+       }
+
+       /* Nonce */
+       dira_nonce = &dira[1];
+
+       /* Tag */
+       dira_tag = &dira[1 + DEVICE_IDENTITY_NONCE_LEN];
+
+       /* Tag = Truncate-64(HMAC-SHA-256(DevIK, "DIR" || Device Address ||
+        *                                Nonce)) */
+       addr[0] = (const u8 *) label;
+       len[0] = DIR_STR_LEN;
+       addr[1] = dev->pr_device_addr;
+       len[1] = ETH_ALEN;
+       addr[2] = dira_nonce;
+       len[2] = DEVICE_IDENTITY_NONCE_LEN;
+
+       dl_list_for_each(dev_ik, &pr->dev_iks, struct pr_dev_ik, list) {
+               ret = hmac_sha256_vector(dev_ik->dik, DEVICE_IDENTITY_KEY_LEN,
+                                        3, addr, len, tag);
+               if (ret < 0) {
+                       wpa_printf(MSG_INFO,
+                                  "PR: Failed to derive DIRA Tag");
+                       return -1;
+               }
+
+               if (os_memcmp(tag, dira_tag, DEVICE_IDENTITY_TAG_LEN) == 0) {
+                       wpa_printf(MSG_DEBUG, "PR: DIRA Tag matched");
+                       if (dev_ik->password_valid) {
+                               os_strlcpy(dev->password, dev_ik->password,
+                                          sizeof(dev->password));
+                               dev->password_valid = true;
+                       }
+                       if (dev_ik->pmk_valid) {
+                               os_memcpy(dev->pmk, dev_ik->pmk,
+                                         WPA_PASN_PMK_LEN);
+                               dev->pmk_valid = true;
+                       }
+                       return 0;
+               }
+       }
+
+       return -1;
+}
+
+
 static void pr_buf_add_channel_list(struct wpabuf *buf, const char *country,
                                    const struct pr_channels *chan)
 {
@@ -955,5 +1024,8 @@ void pr_process_usd_elems(struct pr_data *pr, const u8 *ies, u16 ies_len,
                                            &dev->ntb_caps,
                                            dev->pr_caps.secure_he_ltf);
 
+       if (msg.dira && msg.dira_len)
+               pr_validate_dira(pr, dev, msg.dira, msg.dira_len);
+
        pr_parse_free(&msg);
 }