From 043dedee83a7ded7a0df2c8a18fcaa22eb84148b Mon Sep 17 00:00:00 2001 From: Michal Kazior Date: Tue, 11 May 2021 10:56:17 +0000 Subject: [PATCH] DPP: Expose enrollee pubkey hash for identification 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 --- src/ap/ctrl_iface_ap.c | 13 +++++++++++++ src/ap/dpp_hostapd.c | 14 ++++++++------ src/ap/pmksa_cache_auth.c | 1 + src/ap/pmksa_cache_auth.h | 2 ++ src/ap/sta_info.c | 31 +++++++++++++++++++++++++++---- src/ap/sta_info.h | 2 ++ src/ap/wpa_auth.c | 31 +++++++++++++++++++++++++++++++ src/ap/wpa_auth.h | 4 ++++ src/common/dpp.c | 19 ++++++++++++++++--- src/common/dpp.h | 3 ++- src/common/dpp_crypto.c | 21 +++++++++++++++++++++ wpa_supplicant/dpp_supplicant.c | 4 ++-- 12 files changed, 129 insertions(+), 16 deletions(-) diff --git a/src/ap/ctrl_iface_ap.c b/src/ap/ctrl_iface_ap.c index 0df232772..a02917c5f 100644 --- a/src/ap/ctrl_iface_ap.c +++ b/src/ap/ctrl_iface_ap.c @@ -218,6 +218,7 @@ static int hostapd_ctrl_iface_sta_mib(struct hostapd_data *hapd, { int len, res, ret, i; const char *keyid; + const u8 *dpp_pkhash; if (!sta) return 0; @@ -386,6 +387,18 @@ 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="); + if (!os_snprintf_error(buflen - len, ret)) + len += ret; + len += wpa_snprintf_hex(buf + len, buflen - len, dpp_pkhash, + SHA256_MAC_LEN); + ret = os_snprintf(buf + len, buflen - len, "\n"); + 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 00b571eea..3c515f268 100644 --- a/src/ap/dpp_hostapd.c +++ b/src/ap/dpp_hostapd.c @@ -2051,6 +2051,7 @@ static void hostapd_dpp_rx_peer_disc_req(struct hostapd_data *hapd, os_time_t expire; int expiration; enum dpp_status_error res; + u8 pkhash[SHA256_MAC_LEN]; os_memset(&intro, 0, sizeof(intro)); @@ -2087,7 +2088,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, pkhash); if (res == 255) { wpa_printf(MSG_INFO, "DPP: Network Introduction protocol resulted in internal failure (peer " @@ -2132,9 +2133,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"); goto done; } @@ -2792,6 +2793,7 @@ hostapd_dpp_rx_priv_peer_intro_update(struct hostapd_data *hapd, const u8 *src, os_time_t expire; int expiration; enum dpp_status_error res; + u8 pkhash[SHA256_MAC_LEN]; os_memset(&intro, 0, sizeof(intro)); @@ -2869,7 +2871,7 @@ hostapd_dpp_rx_priv_peer_intro_update(struct hostapd_data *hapd, const u8 *src, 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); if (res == 255) { wpa_printf(MSG_INFO, "DPP: Network Introduction protocol resulted in internal failure (peer " @@ -2903,9 +2905,9 @@ hostapd_dpp_rx_priv_peer_intro_update(struct hostapd_data *hapd, const u8 *src, 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"); goto done; } diff --git a/src/ap/pmksa_cache_auth.c b/src/ap/pmksa_cache_auth.c index b67b8522e..32d291d1c 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..e3cee4a4b 100644 --- a/src/ap/pmksa_cache_auth.h +++ b/src/ap/pmksa_cache_auth.h @@ -23,6 +23,8 @@ struct rsn_pmksa_cache_entry { int akmp; /* WPA_KEY_MGMT_* */ u8 spa[ETH_ALEN]; + u8 *dpp_pkhash; /* SHA256_MAC_LEN octet hash value of DPP Connector + * public key */ u8 *identity; size_t identity_len; struct wpabuf *cui; diff --git a/src/ap/sta_info.c b/src/ap/sta_info.c index c54192612..63f514c9e 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 u8 * 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 u8 *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,27 @@ 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) { + const char *prefix = " dpp_pkhash="; + size_t plen = os_strlen(prefix); + + os_strlcpy(dpp_pkhash_buf, prefix, + sizeof(dpp_pkhash_buf)); + wpa_snprintf_hex(&dpp_pkhash_buf[plen], + sizeof(dpp_pkhash_buf) - plen, + dpp_pkhash, SHA256_MAC_LEN); + } + + 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 6911bc5fb..b59b7584b 100644 --- a/src/ap/sta_info.h +++ b/src/ap/sta_info.h @@ -354,6 +354,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 u8 * 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 3d0f6ff6b..e3dfd8a6a 100644 --- a/src/ap/wpa_auth.c +++ b/src/ap/wpa_auth.c @@ -4856,6 +4856,14 @@ const u8 * wpa_auth_get_pmk(struct wpa_state_machine *sm, int *len) } +const u8 * wpa_auth_get_dpp_pkhash(struct wpa_state_machine *sm) +{ + if (!sm || !sm->pmksa) + return NULL; + return sm->pmksa->dpp_pkhash; +} + + int wpa_auth_sta_key_mgmt(struct wpa_state_machine *sm) { if (!sm) @@ -5018,6 +5026,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 u8 *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 (3)", 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_memdup(dpp_pkhash, SHA256_MAC_LEN); + + 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 5f51c434c..b6737a32e 100644 --- a/src/ap/wpa_auth.h +++ b/src/ap/wpa_auth.h @@ -410,6 +410,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 u8 * 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); @@ -435,6 +436,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 u8 *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 6e5f11008..e12522bdb 100644 --- a/src/common/dpp.c +++ b/src/common/dpp.c @@ -4141,7 +4141,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, u8 *peer_key_hash) { struct json_token *root = NULL, *netkey, *token; struct json_token *own_root = NULL; @@ -4264,6 +4264,9 @@ dpp_peer_intro(struct dpp_introduction *intro, const char *own_connector, } #endif /* CONFIG_DPP3 */ + if (peer_key_hash) + dpp_get_pubkey_hash(intro->peer_key, peer_key_hash); + ret = DPP_STATUS_OK; fail: if (ret != DPP_STATUS_OK) @@ -5036,8 +5039,18 @@ 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); + u8 hash[SHA256_MAC_LEN]; + char hex[SHA256_MAC_LEN * 2 + 1]; + + if (auth->peer_protocol_key) { + dpp_get_pubkey_hash(auth->peer_protocol_key, hash); + wpa_snprintf_hex(hex, sizeof(hex), hash, sizeof(hash)); + } else { + hex[0] = '\0'; + } + 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 0def82356..0f843da6a 100644 --- a/src/common/dpp.h +++ b/src/common/dpp.h @@ -669,7 +669,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, u8 *peer_key_hash); void dpp_peer_intro_deinit(struct dpp_introduction *intro); int dpp_get_connector_version(const char *connector); struct dpp_pkex * dpp_pkex_init(void *msg_ctx, struct dpp_bootstrap_info *bi, @@ -853,6 +853,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(struct crypto_ec_key *key, u8 *hash); #endif /* CONFIG_DPP */ #endif /* DPP_H */ diff --git a/src/common/dpp_crypto.c b/src/common/dpp_crypto.c index 09d4d8cf0..f17f95a2c 100644 --- a/src/common/dpp_crypto.c +++ b/src/common/dpp_crypto.c @@ -246,6 +246,27 @@ struct crypto_ec_key * dpp_set_pubkey_point(struct crypto_ec_key *group_key, } +int dpp_get_pubkey_hash(struct crypto_ec_key *key, u8 *hash) +{ + struct wpabuf *uncomp; + const u8 *addr[1]; + size_t len[1]; + int res; + + if (!key) + return -1; + + uncomp = crypto_ec_key_get_pubkey_point(key, 1); + if (!uncomp) + return -1; + addr[0] = wpabuf_head(uncomp); + len[0] = wpabuf_len(uncomp); + res = sha256_vector(1, addr, len, hash); + wpabuf_free(uncomp); + return res; +} + + struct crypto_ec_key * dpp_gen_keypair(const struct dpp_curve_params *curve) { struct crypto_ec_key *key; diff --git a/wpa_supplicant/dpp_supplicant.c b/wpa_supplicant/dpp_supplicant.c index f8dd9c155..afadd789f 100644 --- a/wpa_supplicant/dpp_supplicant.c +++ b/wpa_supplicant/dpp_supplicant.c @@ -2677,7 +2677,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"); @@ -3830,7 +3830,7 @@ wpas_dpp_rx_priv_peer_intro_notify(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");