[PATCH v3 22/25] P2P: Add support to validate DIRA and configure PMK
Shivani Baranwal
quic_shivbara at quicinc.com
Mon Aug 5 02:33:20 PDT 2024
When DIRA is matched, configure PMK for pairing verification of
previously paired peer.
---
src/ap/wpa_auth.c | 18 +++++++++++++
src/ap/wpa_auth.h | 3 +++
src/p2p/p2p.c | 39 +++++++++++++++++++++++++++
src/p2p/p2p.h | 19 ++++++++++++++
src/rsn_supp/wpa.c | 17 ++++++++++++
src/rsn_supp/wpa.h | 2 ++
wpa_supplicant/p2p_supplicant.c | 58 +++++++++++++++++++++++++++++++++++++++++
7 files changed, 156 insertions(+)
diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c
index 93f157d..20c809a 100644
--- a/src/ap/wpa_auth.c
+++ b/src/ap/wpa_auth.c
@@ -6557,6 +6557,24 @@ wpa_auth_pmksa_get(struct wpa_authenticator *wpa_auth, const u8 *sta_addr,
return pmksa_cache_auth_get(wpa_auth->pmksa, sta_addr, pmkid);
}
+int wpa_auth_pmksa_get_pmk(struct wpa_authenticator *wpa_auth,
+ const u8 *sta_addr, u8 **pmk, u16 *pmk_len,
+ u8 **pmkid)
+{
+ struct rsn_pmksa_cache_entry *pmksa;
+
+ pmksa = wpa_auth_pmksa_get(wpa_auth, sta_addr, NULL);
+ if (!pmksa) {
+ wpa_printf(MSG_DEBUG, "P2P: Failed to get PMKSA for " MACSTR,
+ MAC2STR(sta_addr));
+ return -1;
+ }
+
+ *pmk = pmksa->pmk;
+ *pmk_len = pmksa->pmk_len;
+ *pmkid = pmksa->pmkid;
+ return 0;
+}
void wpa_auth_pmksa_set_to_sm(struct rsn_pmksa_cache_entry *pmksa,
struct wpa_state_machine *sm,
diff --git a/src/ap/wpa_auth.h b/src/ap/wpa_auth.h
index b22c419..0d621a0 100644
--- a/src/ap/wpa_auth.h
+++ b/src/ap/wpa_auth.h
@@ -528,6 +528,9 @@ wpa_auth_get_pmksa_cache(struct wpa_authenticator *wpa_auth);
struct rsn_pmksa_cache_entry *
wpa_auth_pmksa_get(struct wpa_authenticator *wpa_auth, const u8 *sta_addr,
const u8 *pmkid);
+int wpa_auth_pmksa_get_pmk(struct wpa_authenticator *wpa_auth,
+ const u8 *sta_addr, u8 **pmk, u16 *pmk_len,
+ u8 **pmkid);
struct rsn_pmksa_cache_entry *
wpa_auth_pmksa_get_fils_cache_id(struct wpa_authenticator *wpa_auth,
const u8 *sta_addr, const u8 *pmkid);
diff --git a/src/p2p/p2p.c b/src/p2p/p2p.c
index 216abf4..2c81ec5 100644
--- a/src/p2p/p2p.c
+++ b/src/p2p/p2p.c
@@ -5177,6 +5177,24 @@ int p2p_get_dev_addr(struct p2p_data *p2p, const u8 *iface_addr,
}
+int p2p_get_dev_identity_key(struct p2p_data *p2p, const u8 *dev_addr,
+ u8 **dik_data, u16 *dik_len, u8 *cipher)
+{
+ struct p2p_device *dev = p2p_get_device(p2p, dev_addr);
+ if (!dev) {
+ wpa_printf(MSG_DEBUG, "P2P: Failed to get device identity key for dev "
+ MACSTR, MAC2STR(dev_addr));
+ return -1;
+ }
+
+ *dik_data = dev->info.dik_data;
+ *dik_len = dev->info.dik_len;
+ *cipher = dev->info.dik_cipher_version;
+
+ return 0;
+}
+
+
void p2p_set_peer_filter(struct p2p_data *p2p, const u8 *addr)
{
os_memcpy(p2p->peer_filter, addr, ETH_ALEN);
@@ -5931,6 +5949,14 @@ void set_p2p_allow_6ghz(struct p2p_data *p2p, bool value)
p2p->allow_6ghz = value;
}
+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, p2p->cfg->dev_addr,
+ dev->info.p2p_device_addr, dira,
+ dira_len);
+}
struct wpabuf * p2p_usd_elems(struct p2p_data *p2p)
{
@@ -6035,6 +6061,9 @@ void p2p_process_usd_elems(struct p2p_data *p2p, const u8 *ies, u16 ies_len,
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,
@@ -6913,4 +6942,14 @@ int p2p_pasn_auth_rx(struct p2p_data *p2p, const struct ieee80211_mgmt *mgmt,
}
return ret;
}
+
+
+void p2p_pasn_pmksa_set_pmk(struct p2p_data *p2p, const u8 *src, const u8 *dst,
+ u8 *pmk, u16 pmk_len, 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
diff --git a/src/p2p/p2p.h b/src/p2p/p2p.h
index 9962b69..6024370 100644
--- a/src/p2p/p2p.h
+++ b/src/p2p/p2p.h
@@ -1337,6 +1337,21 @@ struct p2p_config {
int freq);
/**
+ * validate_dira - Function handler to validate dira against list of
+ * device identity keys available
+ * @ctx: Callback context from cb_ctx
+ * @own_addr: p2p device own address
+ * @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 vaildate DIRA and configure PMK of
+ * paired/persistent peer from conf file.
+ */
+ void (*validate_dira)(void *ctx, const u8 *own_addr, const u8 *peer_addr,
+ const u8 *dira, u16 dira_len);
+
+ /**
* pasn_send_mgmt - Function handler to transmit a Management frame
* @ctx: Callback context from cb_ctx
* @data : Frame to transmit
@@ -2293,6 +2308,8 @@ int p2p_get_interface_addr(struct p2p_data *p2p, const u8 *dev_addr,
u8 *iface_addr);
int p2p_get_dev_addr(struct p2p_data *p2p, const u8 *iface_addr,
u8 *dev_addr);
+int p2p_get_dev_identity_key(struct p2p_data *p2p, const u8 *dev_addr,
+ u8 **dik_data, u16 *dik_len, u8 *cipher);
void p2p_set_peer_filter(struct p2p_data *p2p, const u8 *addr);
@@ -2697,4 +2714,6 @@ int p2p_pasn_parse_encrypted_data(struct p2p_data *p2p, const u8 *data,
size_t len);
int p2p_pasn_auth_tx_status(struct p2p_data *p2p, const u8 *data,
size_t data_len, u8 acked, bool verify);
+void p2p_pasn_pmksa_set_pmk(struct p2p_data *p2p, const u8 *src, const u8 *dst,
+ u8 *pmk, u16 pmk_len, u8 *pmkid);
#endif /* P2P_H */
diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c
index 52a4c74..3aa660d 100644
--- a/src/rsn_supp/wpa.c
+++ b/src/rsn_supp/wpa.c
@@ -5547,6 +5547,23 @@ struct rsn_pmksa_cache_entry * wpa_sm_pmksa_cache_get(struct wpa_sm *sm,
akmp);
}
+int wpa_sm_pmksa_get_pmk(struct wpa_sm *sm, const u8 *aa, u8 **pmk,
+ u16 *pmk_len, u8 **pmkid)
+{
+ struct rsn_pmksa_cache_entry *pmksa;
+
+ pmksa = wpa_sm_pmksa_cache_get(sm, aa, NULL, NULL, 0);
+ if (!pmksa) {
+ wpa_printf(MSG_DEBUG, "P2P: Failed to get PMKSA for " MACSTR,
+ MAC2STR(aa));
+ return -1;
+ }
+
+ *pmk = pmksa->pmk;
+ *pmk_len = pmksa->pmk_len;
+ *pmkid = pmksa->pmkid;
+ return 0;
+}
void wpa_sm_pmksa_cache_remove(struct wpa_sm *sm,
struct rsn_pmksa_cache_entry *entry)
diff --git a/src/rsn_supp/wpa.h b/src/rsn_supp/wpa.h
index d85dd9a..2d9ed50 100644
--- a/src/rsn_supp/wpa.h
+++ b/src/rsn_supp/wpa.h
@@ -254,6 +254,8 @@ struct rsn_pmksa_cache_entry * wpa_sm_pmksa_cache_get(struct wpa_sm *sm,
const u8 *pmkid,
const void *network_ctx,
int akmp);
+int wpa_sm_pmksa_get_pmk(struct wpa_sm *sm, const u8 *aa, u8 **pmk,
+ u16 *pmk_len, u8 **pmkid);
void wpa_sm_pmksa_cache_remove(struct wpa_sm *sm,
struct rsn_pmksa_cache_entry *entry);
bool wpa_sm_has_ft_keys(struct wpa_sm *sm, const u8 *md);
diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c
index 0aeb9c6..903aa42 100644
--- a/wpa_supplicant/p2p_supplicant.c
+++ b/wpa_supplicant/p2p_supplicant.c
@@ -5152,6 +5152,63 @@ static void wpas_bootstrap_completed(void *ctx, const u8 *addr, int status,
#endif /* CONFIG_PASN */
}
+void wpas_validate_dira(void *ctx, const u8 *own_addr, const u8 *peer_addr,
+ const u8 *dira, u16 dira_len)
+{
+ int ret;
+ u8 pmk[PMK_LEN_MAX];
+ u8 pmkid[PMKID_LEN];
+ u8 tag[DEVICE_MAX_HASH_LEN];
+ u8 dik[DEVICE_IDENTITY_KEY_LEN];
+ struct wpa_dev_ik *ik = NULL;
+ struct wpa_supplicant *wpa_s = ctx;
+ u8 data[DIR_STR_LEN + DEVICE_IDENTITY_NONCE_LEN + ETH_ALEN];
+
+ if (dira[0] != DIRA_CIPHER_VERSION_128) {
+ wpa_printf(MSG_ERROR,
+ "DIRA cipher version unsupported, (%d)", dira[0]);
+ return;
+ }
+
+ os_memset(tag, 0, sizeof(tag));
+ os_memset(data, 0, sizeof(data));
+ os_memcpy(data, "DIR", DIR_STR_LEN);
+ os_memcpy(&data[DIR_STR_LEN], peer_addr, ETH_ALEN);
+ os_memcpy(&data[DIR_STR_LEN + ETH_ALEN], &dira[1],
+ DEVICE_IDENTITY_NONCE_LEN);
+
+ for (ik = wpa_s->conf->identity; ik; ik = ik->next) {
+ if (ik->dik_len != DEVICE_IDENTITY_KEY_LEN ||
+ ik->dik_cipher != DIRA_CIPHER_VERSION_128)
+ continue;
+
+ hexstr2bin(ik->dik_data, dik, DEVICE_IDENTITY_KEY_LEN);
+ ret = hmac_sha256(dik, DEVICE_IDENTITY_KEY_LEN, data,
+ sizeof(data), tag);
+ if (ret < 0) {
+ wpa_printf(MSG_ERROR, "DIRA Tag derivation failed");
+ return;
+ }
+
+ if (os_memcmp(tag, &dira[1 + DEVICE_IDENTITY_NONCE_LEN],
+ DEVICE_IDENTITY_TAG_LEN) == 0) {
+ wpa_printf(MSG_DEBUG, "DIRA Tag Matched");
+ break;
+ }
+ }
+
+ if (!ik)
+ return;
+
+ hexstr2bin(ik->pmk, pmk, ik->pmk_len);
+ hexstr2bin(ik->pmkid, pmkid, PMKID_LEN);
+
+#ifdef CONFIG_PASN
+ p2p_pasn_pmksa_set_pmk(wpa_s->global->p2p, own_addr, peer_addr, pmk,
+ ik->pmk_len, pmkid);
+#endif /* CONFIG_PASN */
+}
+
#ifdef CONFIG_PASN
static void wpas_p2p_pasn_auth_start_cb(struct wpa_radio_work *work, int deinit)
{
@@ -5449,6 +5506,7 @@ int wpas_p2p_init(struct wpa_global *global, 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_mlme;
p2p.pasn_update_extra_ies = wpas_p2p_pasn_update_extra_ies;
--
2.7.4
More information about the Hostap
mailing list