]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
P2P2: Control interface command to validate DIRA info
authorVinay Gannevaram <quic_vganneva@quicinc.com>
Sun, 19 Jan 2025 17:57:27 +0000 (23:27 +0530)
committerJouni Malinen <j@w1.fi>
Fri, 24 Jan 2025 21:00:11 +0000 (23:00 +0200)
Add a control interface command P2P_VALIDATE_DIRA to validate DIRA for
all the available Device Identity keys in the config file. Upper layer
components can use this to validate DIRA obtained from a peer in BLE
frames during BLE Assisted P2P R2 discovery.

Signed-off-by: Vinay Gannevaram <quic_vganneva@quicinc.com>
src/p2p/p2p.c
src/p2p/p2p.h
wpa_supplicant/ctrl_iface.c
wpa_supplicant/p2p_supplicant.c
wpa_supplicant/p2p_supplicant.h

index 7775aa788d7ab47e3f25783c2e7073ba4e238b79..767b1543a483412b28fc013c14515e35e34008e9 100644 (file)
@@ -6045,10 +6045,27 @@ static int p2p_derive_nonce_tag(struct p2p_data *p2p)
 static int p2p_validate_dira(struct p2p_data *p2p, struct p2p_device *dev,
                             const u8 *dira, u16 dira_len)
 {
-       if (p2p->cfg->validate_dira)
+       if (dira_len < 1 || dira[0] != DIRA_CIPHER_VERSION_128) {
+               p2p_dbg(p2p, "Unsupported DIRA cipher version %d",
+                       dira[0]);
+               return 0;
+       }
+
+       if (dira_len < 1 + DEVICE_IDENTITY_NONCE_LEN + DEVICE_IDENTITY_TAG_LEN)
+       {
+               p2p_dbg(p2p, "Truncated DIRA (length %u)", dira_len);
+               return 0;
+       }
+
+       if (p2p->cfg->validate_dira) {
+               const u8 *nonce = &dira[1];;
+               const u8 *tag = &dira[1 + DEVICE_IDENTITY_NONCE_LEN];
+
                return p2p->cfg->validate_dira(p2p->cfg->cb_ctx,
                                               dev->info.p2p_device_addr,
-                                              dira, dira_len);
+                                              nonce, tag);
+       }
+
        return 0;
 }
 
index 066064e1389b6d2ea9fadf501b01383eb1c5a69a..bcf317ba6817bb63daa43da688cd3161928e35ab 100644 (file)
@@ -1370,8 +1370,8 @@ struct p2p_config {
         *      list of available device identity keys
         * @ctx: Callback context from cb_ctx
         * @peer_addr: P2P Device address of the peer
-        * @dira: DIRA attribute present in the USD frames
-        * @dira_len: Length of DIRA
+        * @dira_nonce: DIRA Nonce
+        * @dira_tag: DIRA Tag
         * Returns: Identity block ID on success, 0 on failure
         *
         * This function can be used to validate DIRA and configure PMK of a
@@ -1380,7 +1380,7 @@ struct p2p_config {
         * case a matching entry is found.
         */
        int (*validate_dira)(void *ctx, const u8 *peer_addr,
-                            const u8 *dira, size_t dira_len);
+                            const u8 *dira_nonce, const u8 *dira_tag);
 
        /**
         * pasn_send_mgmt - Function handler to transmit a Management frame
index 90e98ce6ad37329ff3ee9e783701f001bcb5f466..eda2ecd5e125027c38611f1af9134d9af31bc90c 100644 (file)
@@ -6626,6 +6626,38 @@ static int p2p_get_passphrase(struct wpa_supplicant *wpa_s, char *buf,
 }
 
 
+static int p2p_ctrl_validate_dira(struct wpa_supplicant *wpa_s, char *cmd)
+{
+       char *pos, *pos2;
+       u8 addr[ETH_ALEN];
+       u8 nonce[DEVICE_IDENTITY_NONCE_LEN];
+       u8 tag[DEVICE_IDENTITY_TAG_LEN];
+
+       if (hwaddr_aton(cmd, addr))
+               return -1;
+
+       pos = cmd + 17;
+       if (*pos != ' ')
+               return -1;
+
+       pos2 = os_strstr(pos, "nonce=");
+       if (pos2) {
+               pos2 += 6;
+               if (hexstr2bin(pos2, nonce, sizeof(nonce)) < 0)
+                       return -1;
+       }
+
+       pos2 = os_strstr(pos, "tag=");
+       if (pos2) {
+               pos2 += 4;
+               if (hexstr2bin(pos2, tag, sizeof(tag)) < 0)
+                       return -1;
+       }
+
+       return wpas_p2p_validate_dira(wpa_s, addr, 0, nonce, tag);
+}
+
+
 static int p2p_ctrl_serv_disc_req(struct wpa_supplicant *wpa_s, char *cmd,
                                  char *buf, size_t buflen)
 {
@@ -13036,6 +13068,9 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
                reply_len = p2p_get_passphrase(wpa_s, reply, reply_size);
        } else if (os_strcmp(buf, "P2P_GET_DIRA") == 0) {
                reply_len = wpas_p2p_get_dira(wpa_s, reply, reply_size);
+       } else if (os_strncmp(buf, "P2P_VALIDATE_DIRA ", 18) == 0) {
+               if (p2p_ctrl_validate_dira(wpa_s, buf + 18) < 0)
+                       reply_len = -1;
 #ifdef CONFIG_PASN
 #ifdef CONFIG_TESTING_OPTIONS
        } else if (os_strcmp(buf, "P2P_GET_PASNPTK") == 0) {
@@ -14141,6 +14176,7 @@ static char * wpas_global_ctrl_iface_redir_p2p(struct wpa_global *global,
                "STA-FIRST",
 #endif /* CONFIG_AP */
                "P2P_GET_DIRA",
+               "P2P_VALIDATE_DIRA",
                NULL
        };
        static const char * prefix[] = {
index ee12c8a6d89136495ddcde335f7ab36a8cae6b7f..0f8ea11f4a64c7c5fcb70b1368d136cbd3db7209 100644 (file)
@@ -5439,7 +5439,7 @@ static void wpas_bootstrap_completed(void *ctx, const u8 *addr,
 
 
 static int wpas_validate_dira(void *ctx, const u8 *peer_addr,
-                             const u8 *dira, size_t dira_len)
+                             const u8 *dira_nonce, const u8 *dira_tag)
 {
        struct wpa_supplicant *wpa_s = ctx;
        int ret;
@@ -5449,24 +5449,11 @@ static int wpas_validate_dira(void *ctx, const u8 *peer_addr,
        size_t len[3];
        const char *label = "DIR";
 
-       if (dira_len < 1 || dira[0] != DIRA_CIPHER_VERSION_128) {
-               wpa_printf(MSG_ERROR,
-                          "P2P2: Unsupported DIRA cipher version %d", dira[0]);
-               return 0;
-       }
-
-       if (dira_len < 1 + DEVICE_IDENTITY_NONCE_LEN + DEVICE_IDENTITY_TAG_LEN)
-       {
-               wpa_printf(MSG_INFO, "P2P2: Truncated DIRA (length %zu)",
-                          dira_len);
-               return 0;
-       }
-
        addr[0] = (const u8 *) label;
        len[0] = DIR_STR_LEN;
        addr[1] = peer_addr;
        len[1] = ETH_ALEN;
-       addr[2] = &dira[1];
+       addr[2] = dira_nonce;
        len[2] = DEVICE_IDENTITY_NONCE_LEN;
 
        for (ik = wpa_s->conf->identity; ik; ik = ik->next) {
@@ -5483,8 +5470,7 @@ static int wpas_validate_dira(void *ctx, const u8 *peer_addr,
                        return 0;
                }
 
-               if (os_memcmp(tag, &dira[1 + DEVICE_IDENTITY_NONCE_LEN],
-                             DEVICE_IDENTITY_TAG_LEN) == 0) {
+               if (os_memcmp(tag, dira_tag, DEVICE_IDENTITY_TAG_LEN) == 0) {
                        wpa_printf(MSG_DEBUG, "P2P2: DIRA Tag matched");
                        break;
                }
@@ -11442,6 +11428,22 @@ int wpas_p2p_get_dira(struct wpa_supplicant *wpa_s, char *buf, size_t buf_len)
 }
 
 
+int wpas_p2p_validate_dira(struct wpa_supplicant *wpa_s, const u8 *addr,
+                          u8 cipher, const u8 *nonce, const u8 *tag)
+{
+       if (cipher != DIRA_CIPHER_VERSION_128) {
+               wpa_printf(MSG_INFO, "P2P2: Unsupported DIRA cipher version %d",
+                          cipher);
+               return -1;
+       }
+
+       if (wpas_validate_dira(wpa_s, addr, nonce, tag) > 0)
+               return 0;
+
+       return -1;
+}
+
+
 void wpas_p2p_update_dev_addr(struct wpa_supplicant *wpa_s)
 {
        os_memcpy(wpa_s->global->p2p_dev_addr, wpa_s->own_addr, ETH_ALEN);
index 32af1af03f25012faf5f1f53af7819b0c045b73e..5011724501b6a27c573131ef65e37d4af06fc633 100644 (file)
@@ -245,6 +245,8 @@ int wpas_p2p_pasn_auth_rx(struct wpa_supplicant *wpa_s,
 int wpas_p2p_get_pasn_ptk(struct wpa_supplicant *wpa_s, const u8 **ptk,
                          size_t *ptk_len);
 int wpas_p2p_get_dira(struct wpa_supplicant *wpa_s, char *buf, size_t buf_len);
+int wpas_p2p_validate_dira(struct wpa_supplicant *wpa_s, const u8 *addr,
+                          u8 cipher, const u8 *nonce, const u8 *tag);
 
 #else /* CONFIG_P2P */