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;
}
* 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
* 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
}
+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)
{
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) {
"STA-FIRST",
#endif /* CONFIG_AP */
"P2P_GET_DIRA",
+ "P2P_VALIDATE_DIRA",
NULL
};
static const char * prefix[] = {
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;
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) {
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;
}
}
+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);
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 */