}
+static void p2p_validate_dira(struct p2p_data *p2p, struct p2p_device *dev,
+ const u8 *dira, u16 dira_len)
+{
+ if (p2p->cfg->validate_dira)
+ p2p->cfg->validate_dira(p2p->cfg->cb_ctx,
+ dev->info.p2p_device_addr,
+ dira, dira_len);
+}
+
+
struct wpabuf * p2p_usd_elems(struct p2p_data *p2p)
{
struct wpabuf *buf;
if (!ether_addr_equal(peer_addr, p2p_dev_addr))
os_memcpy(dev->interface_addr, peer_addr, ETH_ALEN);
+ if (msg.dira && msg.dira_len)
+ p2p_validate_dira(p2p, dev, msg.dira, msg.dira_len);
+
p2p_dbg(p2p, "Updated device entry based on USD frame: " MACSTR
" dev_capab=0x%x group_capab=0x%x listen_freq=%d",
MAC2STR(dev->info.p2p_device_addr), dev->info.dev_capab,
return ret;
}
+
+void p2p_pasn_pmksa_set_pmk(struct p2p_data *p2p, const u8 *src, const u8 *dst,
+ const u8 *pmk, size_t pmk_len, const u8 *pmkid)
+{
+ pasn_initiator_pmksa_cache_add(p2p->initiator_pmksa, src, dst, pmk,
+ pmk_len, pmkid);
+ pasn_responder_pmksa_cache_add(p2p->responder_pmksa, src, dst, pmk,
+ pmk_len, pmkid);
+}
+
#endif /* CONFIG_PASN */
void (*bootstrap_completed)(void *ctx, const u8 *addr,
enum p2p_status_code status, int freq);
+ /**
+ * validate_dira - Indicate reception of DIRA to be validated against a
+ * 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
+ *
+ * This function can be used to validate DIRA and configure PMK of a
+ * paired/persistent peer from configuration. The handler function is
+ * expected to call p2p_pasn_pmksa_set_pmk() to set the PMK/PMKID in
+ * case a matching entry is found.
+ */
+ void (*validate_dira)(void *ctx, const u8 *peer_addr,
+ const u8 *dira, size_t dira_len);
+
/**
* pasn_send_mgmt - Function handler to transmit a Management frame
* @ctx: Callback context from cb_ctx
int p2p_pasn_auth_tx_status(struct p2p_data *p2p, const u8 *data,
size_t data_len, bool acked, bool verify);
int p2p_config_sae_password(struct p2p_data *p2p, const char *pw);
+void p2p_pasn_pmksa_set_pmk(struct p2p_data *p2p, const u8 *src, const u8 *dst,
+ const u8 *pmk, size_t pmk_len, const u8 *pmkid);
#endif /* P2P_H */
}
+static void wpas_validate_dira(void *ctx, const u8 *peer_addr,
+ const u8 *dira, size_t dira_len)
+{
+ struct wpa_supplicant *wpa_s = ctx;
+ int ret;
+ u8 tag[DEVICE_MAX_HASH_LEN];
+ struct wpa_dev_ik *ik;
+ const u8 *addr[3];
+ 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;
+ }
+
+ if (dira_len < 1 + DEVICE_IDENTITY_NONCE_LEN + DEVICE_IDENTITY_TAG_LEN)
+ {
+ wpa_printf(MSG_INFO, "P2P2: Truncated DIRA (length %zu)",
+ dira_len);
+ return;
+ }
+
+ addr[0] = (const u8 *) label;
+ len[0] = DIR_STR_LEN;
+ addr[1] = peer_addr;
+ len[1] = ETH_ALEN;
+ addr[2] = &dira[1];
+ len[2] = DEVICE_IDENTITY_NONCE_LEN;
+
+ for (ik = wpa_s->conf->identity; ik; ik = ik->next) {
+ if (wpabuf_len(ik->dik) != DEVICE_IDENTITY_KEY_LEN ||
+ ik->dik_cipher != DIRA_CIPHER_VERSION_128)
+ continue;
+
+ ret = hmac_sha256_vector(wpabuf_head(ik->dik),
+ DEVICE_IDENTITY_KEY_LEN,
+ 3, addr, len, tag);
+ if (ret < 0) {
+ wpa_printf(MSG_ERROR,
+ "P2P2: Failed to derive DIRA Tag");
+ return;
+ }
+
+ if (os_memcmp(tag, &dira[1 + DEVICE_IDENTITY_NONCE_LEN],
+ DEVICE_IDENTITY_TAG_LEN) == 0) {
+ wpa_printf(MSG_DEBUG, "P2P2: DIRA Tag matched");
+ break;
+ }
+ }
+
+ if (!ik)
+ return;
+
+#ifdef CONFIG_PASN
+ p2p_pasn_pmksa_set_pmk(wpa_s->global->p2p, wpa_s->global->p2p_dev_addr,
+ peer_addr,
+ wpabuf_head(ik->pmk), wpabuf_len(ik->pmk),
+ wpabuf_head(ik->pmkid));
+#endif /* CONFIG_PASN */
+}
+
+
#ifdef CONFIG_PASN
static int wpas_p2p_initiate_pasn_verify(struct wpa_supplicant *wpa_s,
p2p.register_bootstrap_comeback = wpas_p2p_register_bootstrap_comeback;
p2p.bootstrap_req_rx = wpas_bootstrap_req_rx;
p2p.bootstrap_completed = wpas_bootstrap_completed;
+ p2p.validate_dira = wpas_validate_dira;
#ifdef CONFIG_PASN
p2p.pasn_send_mgmt = wpas_p2p_pasn_send_mgmt;
p2p.prepare_data_element = wpas_p2p_prepare_data_element;