[PATCH v2 14/14] P2P: Add support to get PASN PTK
Shivani Baranwal
quic_shivbara at quicinc.com
Thu Jul 18 21:40:06 PDT 2024
Signed-off-by: Shivani Baranwal <quic_shivbara at quicinc.com>
---
src/common/wpa_common.c | 2 ++
src/common/wpa_common.h | 1 +
src/p2p/p2p.c | 53 ++++++++++++++++++++++++++++++++++++++---
src/p2p/p2p.h | 8 +++++++
src/p2p/p2p_i.h | 4 ++++
wpa_supplicant/ctrl_iface.c | 21 ++++++++++++++++
wpa_supplicant/p2p_supplicant.c | 11 +++++++++
wpa_supplicant/p2p_supplicant.h | 8 +++++++
8 files changed, 105 insertions(+), 3 deletions(-)
diff --git a/src/common/wpa_common.c b/src/common/wpa_common.c
index b7438ce..8d15410 100644
--- a/src/common/wpa_common.c
+++ b/src/common/wpa_common.c
@@ -582,6 +582,7 @@ int wpa_pmk_to_ptk(const u8 *pmk, size_t pmk_len, const char *label,
ptk->kek2_len = 0;
ptk->kck2_len = 0;
+ ptk->ptk_len = ptk_len;
os_memset(tmp, 0, sizeof(tmp));
os_memset(data, 0, data_len);
return 0;
@@ -1553,6 +1554,7 @@ int pasn_pmk_to_ptk(const u8 *pmk, size_t pmk_len,
ptk->kdk, ptk->kdk_len);
}
+ ptk->ptk_len = ptk_len;
forced_memzero(tmp, sizeof(tmp));
ret = 0;
err:
diff --git a/src/common/wpa_common.h b/src/common/wpa_common.h
index 249f1d1..fcd56e1 100644
--- a/src/common/wpa_common.h
+++ b/src/common/wpa_common.h
@@ -268,6 +268,7 @@ struct wpa_ptk {
size_t kck2_len;
size_t kek2_len;
size_t kdk_len;
+ size_t ptk_len;
size_t ltf_keyseed_len;
int installed; /* 1 if key has already been installed to driver */
};
diff --git a/src/p2p/p2p.c b/src/p2p/p2p.c
index 946cccd..62988b0 100644
--- a/src/p2p/p2p.c
+++ b/src/p2p/p2p.c
@@ -3101,6 +3101,11 @@ void p2p_remove_wlan_ap_info(struct p2p_data *p2p, u8 val)
p2p->cfg->remove_wlan_ap_info = val;
}
+void p2p_set_store_pasn_ptk(struct p2p_data *p2p, u8 val)
+{
+ p2p->cfg->store_pasn_ptk = val;
+}
+
struct ieee80211_dfs_ap_info_list * p2p_dfs_get_ap_info(struct p2p_data *p2p,
const u8 *bssid)
@@ -6883,6 +6888,7 @@ int p2p_handle_pasn_auth(struct p2p_data *p2p, struct p2p_device *dev,
p2p_dbg(p2p, "P2P PASN Responder: Handle PASN Auth3 failed");
return -1;
}
+ p2p_pasn_store_ptk(p2p, &pasn->ptk);
if (p2p_pasn_handle_action_wrapper(p2p, dev, mgmt, len, freq,
auth_transaction)) {
p2p_dbg(p2p, "P2P PASN Responder: Handle Auth3 action wrapper failed");
@@ -6938,15 +6944,56 @@ int p2p_pasn_auth_rx(struct p2p_data *p2p, const struct ieee80211_mgmt *mgmt,
return -1;
}
ret = wpa_pasn_auth_rx(pasn, (const u8 *)mgmt, len, &pasn_data);
- forced_memzero(pasn_get_ptk(pasn), sizeof(pasn->ptk));
-
if (ret < 0) {
p2p_dbg(p2p, "P2P PASN: wpa_pasn_auth_rx failed");
dev->role = P2P_ROLE_IDLE;
}
-
+ p2p_pasn_store_ptk(p2p, &pasn->ptk);
+ forced_memzero(pasn_get_ptk(pasn), sizeof(pasn->ptk));
} else {
ret = p2p_handle_pasn_auth(p2p, dev, mgmt, len, freq);
}
return ret;
}
+
+void p2p_pasn_store_ptk(struct p2p_data *p2p, struct wpa_ptk *ptk)
+{
+ u8 *pos;
+
+ if (!p2p->cfg->store_pasn_ptk)
+ return;
+
+ if (ptk->ptk_len > sizeof(p2p->pasn_ptk)) {
+ p2p_dbg(p2p, "P2P PASN PTK exceeds: (len=%ld)", ptk->ptk_len);
+ return;
+ }
+
+ pos = p2p->pasn_ptk;
+ p2p->pasn_ptk_len = ptk->ptk_len;
+ if (ptk->kck_len) {
+ os_memcpy(pos, ptk->kck, ptk->kck_len);
+ pos += ptk->kck_len;
+ }
+ if (ptk->kek_len) {
+ os_memcpy(pos, ptk->kek, ptk->kek_len);
+ pos += ptk->kek_len;
+ }
+ if (ptk->tk_len) {
+ os_memcpy(pos, ptk->tk, ptk->tk_len);
+ pos += ptk->tk_len;
+ }
+ if (ptk->kdk_len) {
+ os_memcpy(pos, ptk->kdk, ptk->kdk_len);
+ pos += ptk->kdk_len;
+ }
+}
+
+int p2p_pasn_get_ptk(struct p2p_data *p2p, const u8 **buf, size_t *buf_len)
+{
+ if (!p2p || !p2p->cfg->store_pasn_ptk || !p2p->pasn_ptk_len)
+ return -1;
+
+ *buf_len = p2p->pasn_ptk_len;
+ *buf = p2p->pasn_ptk;
+ return 0;
+}
diff --git a/src/p2p/p2p.h b/src/p2p/p2p.h
index 4ada7a2..9678f95 100644
--- a/src/p2p/p2p.h
+++ b/src/p2p/p2p.h
@@ -722,6 +722,11 @@ struct p2p_config {
void *cb_ctx;
/**
+ * store pasn ptk, Used for certification mode
+ */
+ bool store_pasn_ptk;
+
+ /**
* debug_print - Debug print
* @ctx: Callback context from cb_ctx
* @level: Debug verbosity level (MSG_*)
@@ -2665,4 +2670,7 @@ bool is_p2p_dfs_owner(struct p2p_data *p2p);
void p2p_remove_wlan_ap_info(struct p2p_data *p2p, u8 val);
void p2p_update_dfs_ap_info(struct p2p_data *p2p, const u8 *bssid, int freq,
int flag);
+void p2p_set_store_pasn_ptk(struct p2p_data *p2p, u8 val);
+void p2p_pasn_store_ptk(struct p2p_data *p2p, struct wpa_ptk *ptk);
+int p2p_pasn_get_ptk(struct p2p_data *p2p, const u8 **buf, size_t *buf_len);
#endif /* P2P_H */
diff --git a/src/p2p/p2p_i.h b/src/p2p/p2p_i.h
index 2309dc8..99dcb76 100644
--- a/src/p2p/p2p_i.h
+++ b/src/p2p/p2p_i.h
@@ -702,6 +702,10 @@ struct p2p_data {
/* list of dfs APs */
struct ieee80211_dfs_ap_info_list *dfs_ap_list;
size_t num_dfs_ap;
+
+ /* pasn ptk of recent handshake when store_pasn_ptk enabled */
+ u8 pasn_ptk[128];
+ size_t pasn_ptk_len;
};
/**
diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c
index 76ba48b..236d9dd 100644
--- a/wpa_supplicant/ctrl_iface.c
+++ b/wpa_supplicant/ctrl_iface.c
@@ -7753,6 +7753,11 @@ static int p2p_ctrl_set(struct wpa_supplicant *wpa_s, char *cmd)
return 0;
}
+ if (os_strcmp(cmd, "store_pasn_ptk") == 0) {
+ p2p_set_store_pasn_ptk(wpa_s->global->p2p, atoi(param));
+ return 0;
+ }
+
wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown P2P_SET field value '%s'",
cmd);
@@ -10910,6 +10915,20 @@ static void wpas_ctrl_iface_pmksa_flush(struct wpa_supplicant *wpa_s)
#endif /* CONFIG_AP */
}
+#ifdef CONFIG_PASN
+
+static int p2p_ctrl_get_pasn_ptk(struct wpa_supplicant *wpa_s, char *buf,
+ size_t buflen)
+{
+ const u8 *ptk;
+ size_t ptk_len;
+
+ if (wpas_p2p_get_pasn_ptk(wpa_s, &ptk, &ptk_len))
+ return -1;
+ return wpa_snprintf_hex(buf, buflen, ptk, ptk_len);
+}
+
+#endif // CONFIG_PASN
#ifdef CONFIG_PMKSA_CACHE_EXTERNAL
@@ -12923,6 +12942,8 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
reply_len = -1;
} else if (os_strcmp(buf, "P2P_GET_PASSPHRASE") == 0) {
reply_len = p2p_get_passphrase(wpa_s, reply, reply_size);
+ } else if (os_strcmp(buf, "P2P_GET_PASNPTK") == 0) {
+ reply_len = p2p_ctrl_get_pasn_ptk(wpa_s, reply, reply_size);
} else if (os_strncmp(buf, "P2P_SERV_DISC_REQ ", 18) == 0) {
reply_len = p2p_ctrl_serv_disc_req(wpa_s, buf + 18, reply,
reply_size);
diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c
index d55a439..0d296bb 100644
--- a/wpa_supplicant/p2p_supplicant.c
+++ b/wpa_supplicant/p2p_supplicant.c
@@ -10918,3 +10918,14 @@ void wpas_p2p_update_dfs_ap_info_list(struct wpa_supplicant *wpa_s,
}
}
}
+
+
+int wpas_p2p_get_pasn_ptk(struct wpa_supplicant *wpa_s, const u8 **ptk,
+ size_t *ptk_len)
+{
+ struct p2p_data *p2p = wpa_s->global->p2p;
+
+ if (wpa_s->global->p2p_disabled || !p2p)
+ return -2;
+ return p2p_pasn_get_ptk(p2p, ptk, ptk_len);
+}
diff --git a/wpa_supplicant/p2p_supplicant.h b/wpa_supplicant/p2p_supplicant.h
index 9156e5a..1ae983e 100644
--- a/wpa_supplicant/p2p_supplicant.h
+++ b/wpa_supplicant/p2p_supplicant.h
@@ -235,6 +235,8 @@ int wpas_p2p_pasn_auth_rx(struct wpa_supplicant *wpa_s,
int freq);
void wpas_p2p_update_dfs_ap_info_list(struct wpa_supplicant *wpa_s,
struct wpa_scan_results *scan_res);
+int wpas_p2p_get_pasn_ptk(struct wpa_supplicant *wpa_s, const u8 **ptk,
+ size_t *ptk_len);
#else /* CONFIG_P2P */
static inline int
@@ -377,6 +379,12 @@ wpas_p2p_update_dfs_ap_info_list(struct wpa_supplicant *wpa_s,
struct wpa_scan_results *scan_res)
{
}
+
+static inline int wpas_p2p_get_pasn_ptk(struct wpa_supplicant *wpa_s,
+ const u8 **ptk, size_t *ptk_len)
+{
+ return 0;
+}
#endif /* CONFIG_P2P */
#endif /* P2P_SUPPLICANT_H */
--
2.7.4
More information about the Hostap
mailing list