From: Michal Kazior <michal@xxxxxxxxx> 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@xxxxxxxxx> --- Notes: v3: - remove unnecessary empty newline in dpp_auth.c - fix memleak of peer_key after dpp_peer_intro() by making it hand over the pkhash instead of key (this also avoids openssl code in dpp_hostapd.c) - dont duplicate dpp_pkhash string if its 0 length so that NULL checks can actually skip some logic 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 | 8 ++++--- 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 | 15 ++++++++++--- src/common/dpp.h | 4 +++- src/common/dpp_crypto.c | 37 +++++++++++++++++++++++++++++++++ wpa_supplicant/dpp_supplicant.c | 2 +- 12 files changed, 127 insertions(+), 12 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 f0b4bc034..46b031003 100644 --- a/src/ap/dpp_hostapd.c +++ b/src/ap/dpp_hostapd.c @@ -1587,6 +1587,7 @@ static void hostapd_dpp_rx_peer_disc_req(struct hostapd_data *hapd, os_time_t expire; int expiration; enum dpp_status_error res; + char pkhash[SHA256_MAC_LEN*2 + 1]; wpa_printf(MSG_DEBUG, "DPP: Peer Discovery Request from " MACSTR, MAC2STR(src)); @@ -1631,7 +1632,8 @@ 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, + pkhash, sizeof(pkhash)); if (res == 255) { wpa_printf(MSG_INFO, "DPP: Network Introduction protocol resulted in internal failure (peer " @@ -1654,9 +1656,9 @@ 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, + 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, pkhash) < 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 27e72f9a0..254e4f39f 100644 --- a/src/ap/sta_info.h +++ b/src/ap/sta_info.h @@ -385,6 +385,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 59cd46aa4..f6575acdb 100644 --- a/src/ap/wpa_auth.c +++ b/src/ap/wpa_auth.c @@ -4681,6 +4681,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) @@ -4842,6 +4852,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 && os_strlen(dpp_pkhash) > 0) + 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 847e77c81..56c442d6d 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, + char *peer_key_hash, size_t peer_key_hash_len) { struct json_token *root = NULL, *netkey, *token; struct json_token *own_root = NULL; @@ -3770,6 +3771,9 @@ dpp_peer_intro(struct dpp_introduction *intro, const char *own_connector, goto fail; } + if (peer_key_hash) + dpp_get_pubkey_hash(peer_key, peer_key_hash, peer_key_hash_len); + ret = DPP_STATUS_OK; fail: if (ret != DPP_STATUS_OK) @@ -4393,8 +4397,13 @@ void dpp_global_deinit(struct dpp_global *dpp) 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); } diff --git a/src/common/dpp.h b/src/common/dpp.h index ba2ef53de..fffb7a37f 100644 --- a/src/common/dpp.h +++ b/src/common/dpp.h @@ -594,7 +594,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, + char *peer_key_hash, size_t peer_key_hash_len); struct dpp_pkex * dpp_pkex_init(void *msg_ctx, struct dpp_bootstrap_info *bi, const u8 *own_mac, const char *identifier, @@ -732,6 +733,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_crypto.c b/src/common/dpp_crypto.c index c75fc7871..c1e6c43ee 100644 --- a/src/common/dpp_crypto.c +++ b/src/common/dpp_crypto.c @@ -520,6 +520,43 @@ 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)); + os_memset(hexstr, 0, len); + + if (!key) + return -1; + + 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 289c60bc8..b0a11bc4d 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, 0); if (res != DPP_STATUS_OK) { wpa_printf(MSG_INFO, "DPP: Network Introduction protocol resulted in failure"); -- 2.27.0 _______________________________________________ Hostap mailing list Hostap@xxxxxxxxxxxxxxxxxxx http://lists.infradead.org/mailman/listinfo/hostap