From: Vinay Gannevaram Date: Sun, 19 Jan 2025 17:57:27 +0000 (+0530) Subject: P2P2: Control interface command to validate DIRA info X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=9f7dc9c307ffb63a9fd615e55e0c11b78e9103b7;p=thirdparty%2Fhostap.git P2P2: Control interface command to validate DIRA info 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 --- diff --git a/src/p2p/p2p.c b/src/p2p/p2p.c index 7775aa788..767b1543a 100644 --- a/src/p2p/p2p.c +++ b/src/p2p/p2p.c @@ -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; } diff --git a/src/p2p/p2p.h b/src/p2p/p2p.h index 066064e13..bcf317ba6 100644 --- a/src/p2p/p2p.h +++ b/src/p2p/p2p.h @@ -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 diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index 90e98ce6a..eda2ecd5e 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -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[] = { diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c index ee12c8a6d..0f8ea11f4 100644 --- a/wpa_supplicant/p2p_supplicant.c +++ b/wpa_supplicant/p2p_supplicant.c @@ -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); diff --git a/wpa_supplicant/p2p_supplicant.h b/wpa_supplicant/p2p_supplicant.h index 32af1af03..501172450 100644 --- a/wpa_supplicant/p2p_supplicant.h +++ b/wpa_supplicant/p2p_supplicant.h @@ -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 */