[PATCHv2 2/3] DPP: expose enrollee pubkey hash for identification
Michal Kazior
kazikcz at gmail.com
Fri Apr 30 14:20:31 BST 2021
From: Michal Kazior <michal at plume.com>
Just like with WPA-PSK and keyids it may be
desired to identify connecting clients to provide
additional network filtering.
This does:
- extend DPP_EVENT_AUTH_SUCCESS to expose public
key hash of the peer so the system can pick it
up and use for identification later
- store public key hash in PMKSA from DPP Network
Intro for later use
- extend sta mib to print out the dpp_pkhash
from PMKSA if present
- extend AP_STA_CONNECTED to include the
dpp_pkhash from PMKSA if present
Signed-off-by: Michal Kazior <michal at plume.com>
---
Notes:
v2:
- fixed type warnings (char vs u8)
- dropped "hostap" salt for the pkhash
- dropped DPP_EVENT_AUTH_PK_HASH and reused
DPP_EVENT_AUTH_SUCCESS (as a result this fixed
some cases where PK_HASH wasn't signalled as
expected)
- adjusted commit log
src/ap/ctrl_iface_ap.c | 8 ++++++++
src/ap/dpp_hostapd.c | 10 +++++++---
src/ap/pmksa_cache_auth.c | 1 +
src/ap/pmksa_cache_auth.h | 1 +
src/ap/sta_info.c | 24 ++++++++++++++++++++----
src/ap/sta_info.h | 2 ++
src/ap/wpa_auth.c | 33 +++++++++++++++++++++++++++++++++
src/ap/wpa_auth.h | 4 ++++
src/common/dpp.c | 17 +++++++++++++----
src/common/dpp.h | 3 ++-
src/common/dpp_auth.c | 1 +
src/common/dpp_crypto.c | 33 +++++++++++++++++++++++++++++++++
wpa_supplicant/dpp_supplicant.c | 2 +-
13 files changed, 126 insertions(+), 13 deletions(-)
diff --git a/src/ap/ctrl_iface_ap.c b/src/ap/ctrl_iface_ap.c
index 28e40ba9c..e663a60cb 100644
--- a/src/ap/ctrl_iface_ap.c
+++ b/src/ap/ctrl_iface_ap.c
@@ -208,6 +208,7 @@ static int hostapd_ctrl_iface_sta_mib(struct hostapd_data *hapd,
{
int len, res, ret, i;
const char *keyid;
+ const char *dpp_pkhash;
if (!sta)
return 0;
@@ -377,6 +378,13 @@ static int hostapd_ctrl_iface_sta_mib(struct hostapd_data *hapd,
len += ret;
}
+ dpp_pkhash = ap_sta_wpa_get_dpp_pkhash(hapd, sta);
+ if (dpp_pkhash) {
+ ret = os_snprintf(buf + len, buflen - len, "dpp_pkhash=%s\n", dpp_pkhash);
+ if (!os_snprintf_error(buflen - len, ret))
+ len += ret;
+ }
+
return len;
}
diff --git a/src/ap/dpp_hostapd.c b/src/ap/dpp_hostapd.c
index 8d0068cb5..431d5a215 100644
--- a/src/ap/dpp_hostapd.c
+++ b/src/ap/dpp_hostapd.c
@@ -1587,6 +1587,8 @@ static void hostapd_dpp_rx_peer_disc_req(struct hostapd_data *hapd,
os_time_t expire;
int expiration;
enum dpp_status_error res;
+ EVP_PKEY *peer_key = NULL;
+ char hex[SHA256_MAC_LEN*2 + 1];
wpa_printf(MSG_DEBUG, "DPP: Peer Discovery Request from " MACSTR,
MAC2STR(src));
@@ -1631,7 +1633,7 @@ static void hostapd_dpp_rx_peer_disc_req(struct hostapd_data *hapd,
wpabuf_len(hapd->conf->dpp_netaccesskey),
wpabuf_head(hapd->conf->dpp_csign),
wpabuf_len(hapd->conf->dpp_csign),
- connector, connector_len, &expire);
+ connector, connector_len, &expire, &peer_key);
if (res == 255) {
wpa_printf(MSG_INFO,
"DPP: Network Introduction protocol resulted in internal failure (peer "
@@ -1654,9 +1656,11 @@ static void hostapd_dpp_rx_peer_disc_req(struct hostapd_data *hapd,
else
expiration = 0;
- if (wpa_auth_pmksa_add2(hapd->wpa_auth, src, intro.pmk, intro.pmk_len,
+ dpp_get_pubkey_hash(peer_key, hex, sizeof(hex));
+
+ if (wpa_auth_pmksa_add3(hapd->wpa_auth, src, intro.pmk, intro.pmk_len,
intro.pmkid, expiration,
- WPA_KEY_MGMT_DPP) < 0) {
+ WPA_KEY_MGMT_DPP, hex) < 0) {
wpa_printf(MSG_ERROR, "DPP: Failed to add PMKSA cache entry");
return;
}
diff --git a/src/ap/pmksa_cache_auth.c b/src/ap/pmksa_cache_auth.c
index fe5f81717..29d2b500a 100644
--- a/src/ap/pmksa_cache_auth.c
+++ b/src/ap/pmksa_cache_auth.c
@@ -40,6 +40,7 @@ static void _pmksa_cache_free_entry(struct rsn_pmksa_cache_entry *entry)
{
os_free(entry->vlan_desc);
os_free(entry->identity);
+ os_free(entry->dpp_pkhash);
wpabuf_free(entry->cui);
#ifndef CONFIG_NO_RADIUS
radius_free_class(&entry->radius_class);
diff --git a/src/ap/pmksa_cache_auth.h b/src/ap/pmksa_cache_auth.h
index 2ef217435..59e7e698f 100644
--- a/src/ap/pmksa_cache_auth.h
+++ b/src/ap/pmksa_cache_auth.h
@@ -23,6 +23,7 @@ struct rsn_pmksa_cache_entry {
int akmp; /* WPA_KEY_MGMT_* */
u8 spa[ETH_ALEN];
+ char *dpp_pkhash;
u8 *identity;
size_t identity_len;
struct wpabuf *cui;
diff --git a/src/ap/sta_info.c b/src/ap/sta_info.c
index ccd1ed931..9a80efd4d 100644
--- a/src/ap/sta_info.c
+++ b/src/ap/sta_info.c
@@ -1260,6 +1260,13 @@ const char * ap_sta_wpa_get_keyid(struct hostapd_data *hapd,
}
+const char * ap_sta_wpa_get_dpp_pkhash(struct hostapd_data *hapd,
+ struct sta_info *sta)
+{
+ return wpa_auth_get_dpp_pkhash(sta->wpa_sm);
+}
+
+
void ap_sta_set_authorized(struct hostapd_data *hapd, struct sta_info *sta,
int authorized)
{
@@ -1298,10 +1305,13 @@ void ap_sta_set_authorized(struct hostapd_data *hapd, struct sta_info *sta,
sta->addr, authorized, dev_addr);
if (authorized) {
+ const char *dpp_pkhash;
const char *keyid;
+ char dpp_pkhash_buf[100];
char keyid_buf[100];
char ip_addr[100];
+ dpp_pkhash_buf[0] = '\0';
keyid_buf[0] = '\0';
ip_addr[0] = '\0';
#ifdef CONFIG_P2P
@@ -1319,14 +1329,20 @@ void ap_sta_set_authorized(struct hostapd_data *hapd, struct sta_info *sta,
" keyid=%s", keyid);
}
- wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_CONNECTED "%s%s%s",
- buf, ip_addr, keyid_buf);
+ dpp_pkhash = ap_sta_wpa_get_dpp_pkhash(hapd, sta);
+ if (dpp_pkhash) {
+ os_snprintf(dpp_pkhash_buf, sizeof(dpp_pkhash_buf),
+ " dpp_pkhash=%s", dpp_pkhash);
+ }
+
+ wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_CONNECTED "%s%s%s%s",
+ buf, ip_addr, keyid_buf, dpp_pkhash_buf);
if (hapd->msg_ctx_parent &&
hapd->msg_ctx_parent != hapd->msg_ctx)
wpa_msg_no_global(hapd->msg_ctx_parent, MSG_INFO,
- AP_STA_CONNECTED "%s%s%s",
- buf, ip_addr, keyid_buf);
+ AP_STA_CONNECTED "%s%s%s%s",
+ buf, ip_addr, keyid_buf, dpp_pkhash_buf);
} else {
wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_DISCONNECTED "%s", buf);
diff --git a/src/ap/sta_info.h b/src/ap/sta_info.h
index efa48e7e3..7f9ef3cc4 100644
--- a/src/ap/sta_info.h
+++ b/src/ap/sta_info.h
@@ -384,6 +384,8 @@ void ap_sta_stop_sa_query(struct hostapd_data *hapd, struct sta_info *sta);
int ap_check_sa_query_timeout(struct hostapd_data *hapd, struct sta_info *sta);
const char * ap_sta_wpa_get_keyid(struct hostapd_data *hapd,
struct sta_info *sta);
+const char * ap_sta_wpa_get_dpp_pkhash(struct hostapd_data *hapd,
+ struct sta_info *sta);
void ap_sta_disconnect(struct hostapd_data *hapd, struct sta_info *sta,
const u8 *addr, u16 reason);
diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c
index ef0595c57..772cc3083 100644
--- a/src/ap/wpa_auth.c
+++ b/src/ap/wpa_auth.c
@@ -4683,6 +4683,16 @@ const u8 * wpa_auth_get_pmk(struct wpa_state_machine *sm, int *len)
}
+const char * wpa_auth_get_dpp_pkhash(struct wpa_state_machine *sm)
+{
+ if (!sm)
+ return NULL;
+ if (!sm->pmksa)
+ return NULL;
+ return sm->pmksa->dpp_pkhash;
+}
+
+
int wpa_auth_sta_key_mgmt(struct wpa_state_machine *sm)
{
if (!sm)
@@ -4844,6 +4854,29 @@ int wpa_auth_pmksa_add2(struct wpa_authenticator *wpa_auth, const u8 *addr,
}
+int wpa_auth_pmksa_add3(struct wpa_authenticator *wpa_auth, const u8 *addr,
+ const u8 *pmk, size_t pmk_len, const u8 *pmkid,
+ int session_timeout, int akmp, const char *dpp_pkhash)
+{
+ struct rsn_pmksa_cache_entry *entry;
+
+ if (wpa_auth->conf.disable_pmksa_caching)
+ return -1;
+
+ wpa_hexdump_key(MSG_DEBUG, "RSN: Cache PMK (2)", pmk, PMK_LEN);
+ entry = pmksa_cache_auth_add(wpa_auth->pmksa, pmk, pmk_len, pmkid,
+ NULL, 0, wpa_auth->addr, addr, session_timeout,
+ NULL, akmp);
+ if (!entry)
+ return -1;
+
+ if (dpp_pkhash)
+ entry->dpp_pkhash = os_strdup(dpp_pkhash);
+
+ return 0;
+}
+
+
void wpa_auth_pmksa_remove(struct wpa_authenticator *wpa_auth,
const u8 *sta_addr)
{
diff --git a/src/ap/wpa_auth.h b/src/ap/wpa_auth.h
index eaa2cafc8..7dc80fded 100644
--- a/src/ap/wpa_auth.h
+++ b/src/ap/wpa_auth.h
@@ -401,6 +401,7 @@ void wpa_auth_countermeasures_start(struct wpa_authenticator *wpa_auth);
int wpa_auth_pairwise_set(struct wpa_state_machine *sm);
int wpa_auth_get_pairwise(struct wpa_state_machine *sm);
const u8 * wpa_auth_get_pmk(struct wpa_state_machine *sm, int *len);
+const char * wpa_auth_get_dpp_pkhash(struct wpa_state_machine *sm);
int wpa_auth_sta_key_mgmt(struct wpa_state_machine *sm);
int wpa_auth_sta_wpa_version(struct wpa_state_machine *sm);
int wpa_auth_sta_ft_tk_already_set(struct wpa_state_machine *sm);
@@ -425,6 +426,9 @@ void wpa_auth_add_sae_pmkid(struct wpa_state_machine *sm, const u8 *pmkid);
int wpa_auth_pmksa_add2(struct wpa_authenticator *wpa_auth, const u8 *addr,
const u8 *pmk, size_t pmk_len, const u8 *pmkid,
int session_timeout, int akmp);
+int wpa_auth_pmksa_add3(struct wpa_authenticator *wpa_auth, const u8 *addr,
+ const u8 *pmk, size_t pmk_len, const u8 *pmkid,
+ int session_timeout, int akmp, const char *dpp_pkhash);
void wpa_auth_pmksa_remove(struct wpa_authenticator *wpa_auth,
const u8 *sta_addr);
int wpa_auth_pmksa_list(struct wpa_authenticator *wpa_auth, char *buf,
diff --git a/src/common/dpp.c b/src/common/dpp.c
index a8feb8090..e1edde449 100644
--- a/src/common/dpp.c
+++ b/src/common/dpp.c
@@ -3665,7 +3665,8 @@ dpp_peer_intro(struct dpp_introduction *intro, const char *own_connector,
const u8 *net_access_key, size_t net_access_key_len,
const u8 *csign_key, size_t csign_key_len,
const u8 *peer_connector, size_t peer_connector_len,
- os_time_t *expiry)
+ os_time_t *expiry,
+ EVP_PKEY **peer_key_out)
{
struct json_token *root = NULL, *netkey, *token;
struct json_token *own_root = NULL;
@@ -3778,7 +3779,10 @@ fail:
os_free(info.payload);
EVP_PKEY_free(own_key);
wpabuf_free(own_key_pub);
- EVP_PKEY_free(peer_key);
+ if (!peer_key_out)
+ EVP_PKEY_free(peer_key);
+ else
+ *peer_key_out = peer_key;
json_free(root);
json_free(own_root);
return ret;
@@ -4424,8 +4428,13 @@ void dpp_notify_chirp_received(void *msg_ctx, int id, const u8 *src,
void dpp_notify_auth_success(struct dpp_authentication *auth, int initiator)
{
- wpa_msg(auth->msg_ctx, MSG_INFO, DPP_EVENT_AUTH_SUCCESS "init=%d",
- initiator);
+ char hex[SHA256_MAC_LEN*2 + 1];
+
+ os_memset(hex, 0, sizeof(hex));
+ dpp_get_pubkey_hash(auth->peer_protocol_key, hex, sizeof(hex));
+
+ wpa_msg(auth->msg_ctx, MSG_INFO, DPP_EVENT_AUTH_SUCCESS "init=%d pkhash=%s",
+ initiator, hex);
}
#endif /* CONFIG_DPP2 */
diff --git a/src/common/dpp.h b/src/common/dpp.h
index 03052939e..f5fcebf37 100644
--- a/src/common/dpp.h
+++ b/src/common/dpp.h
@@ -594,7 +594,7 @@ dpp_peer_intro(struct dpp_introduction *intro, const char *own_connector,
const u8 *net_access_key, size_t net_access_key_len,
const u8 *csign_key, size_t csign_key_len,
const u8 *peer_connector, size_t peer_connector_len,
- os_time_t *expiry);
+ os_time_t *expiry, EVP_PKEY **peer_key_out);
struct dpp_pkex * dpp_pkex_init(void *msg_ctx, struct dpp_bootstrap_info *bi,
const u8 *own_mac,
const char *identifier,
@@ -731,6 +731,7 @@ struct dpp_reconfig_id * dpp_gen_reconfig_id(const u8 *csign_key,
size_t pp_key_len);
int dpp_update_reconfig_id(struct dpp_reconfig_id *id);
void dpp_free_reconfig_id(struct dpp_reconfig_id *id);
+int dpp_get_pubkey_hash(EVP_PKEY *key, char *hexstr, size_t len);
#endif /* CONFIG_DPP */
#endif /* DPP_H */
diff --git a/src/common/dpp_auth.c b/src/common/dpp_auth.c
index 0cabd647f..8f5e34c3e 100644
--- a/src/common/dpp_auth.c
+++ b/src/common/dpp_auth.c
@@ -780,6 +780,7 @@ dpp_auth_req_rx(struct dpp_global *dpp, void *msg_ctx, u8 dpp_allowed_roles,
}
dpp_debug_print_key("Peer (Initiator) Protocol Key", pi);
+
if (dpp_ecdh(own_bi->pubkey, pi, auth->Mx, &secret_len) < 0)
goto fail;
auth->secret_len = secret_len;
diff --git a/src/common/dpp_crypto.c b/src/common/dpp_crypto.c
index c75fc7871..e87b33435 100644
--- a/src/common/dpp_crypto.c
+++ b/src/common/dpp_crypto.c
@@ -520,6 +520,39 @@ EVP_PKEY * dpp_set_pubkey_point(EVP_PKEY *group_key, const u8 *buf, size_t len)
}
+int dpp_get_pubkey_hash(EVP_PKEY *key, char *hexstr, size_t len)
+{
+ unsigned char *der = NULL;
+ const u8 *args[1];
+ size_t lens[1];
+ u8 buf[SHA256_MAC_LEN];
+ EC_KEY *eckey;
+ int der_len;
+ int res = 0;
+
+ os_memset(buf, 0, sizeof(buf));
+
+ eckey = EVP_PKEY_get1_EC_KEY(key);
+ if (!eckey)
+ return -1;
+
+ der_len = i2d_EC_PUBKEY(eckey, &der);
+ if (der_len > 0) {
+ args[0] = der;
+ lens[0] = der_len;
+
+ if (sha256_vector(1, args, lens, buf) < 0)
+ res = -1;
+
+ }
+ OPENSSL_free(der);
+ EC_KEY_free(eckey);
+
+ wpa_snprintf_hex(hexstr, len, buf, sizeof(buf));
+ return res;
+}
+
+
EVP_PKEY * dpp_gen_keypair(const struct dpp_curve_params *curve)
{
EVP_PKEY_CTX *kctx = NULL;
diff --git a/wpa_supplicant/dpp_supplicant.c b/wpa_supplicant/dpp_supplicant.c
index 01a2b2e3f..f3d0a2c8d 100644
--- a/wpa_supplicant/dpp_supplicant.c
+++ b/wpa_supplicant/dpp_supplicant.c
@@ -2437,7 +2437,7 @@ static void wpas_dpp_rx_peer_disc_resp(struct wpa_supplicant *wpa_s,
ssid->dpp_netaccesskey_len,
ssid->dpp_csign,
ssid->dpp_csign_len,
- connector, connector_len, &expiry);
+ connector, connector_len, &expiry, NULL);
if (res != DPP_STATUS_OK) {
wpa_printf(MSG_INFO,
"DPP: Network Introduction protocol resulted in failure");
--
2.27.0
More information about the Hostap
mailing list