]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
DPP: Expose enrollee pubkey hash for identification
authorMichal Kazior <michal@plume.com>
Tue, 11 May 2021 10:56:17 +0000 (10:56 +0000)
committerJouni Malinen <j@w1.fi>
Tue, 29 Nov 2022 11:55:53 +0000 (13:55 +0200)
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@plume.com>
12 files changed:
src/ap/ctrl_iface_ap.c
src/ap/dpp_hostapd.c
src/ap/pmksa_cache_auth.c
src/ap/pmksa_cache_auth.h
src/ap/sta_info.c
src/ap/sta_info.h
src/ap/wpa_auth.c
src/ap/wpa_auth.h
src/common/dpp.c
src/common/dpp.h
src/common/dpp_crypto.c
wpa_supplicant/dpp_supplicant.c

index 0df2327725c5c331538522c3a9944c723b309f20..a02917c5f710a175081bc2de121b417ab430ef58 100644 (file)
@@ -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;
 }
 
index 00b571eea5eba68528d23e6244f17962afbf84f2..3c515f2688c20c7f9e027a7c85a4ff9d225e21b2 100644 (file)
@@ -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;
        }
index b67b8522e744fd404c73c833ebab41d672844102..32d291d1c0560f4eee274ed29d4a4374736093c2 100644 (file)
@@ -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);
index 2ef217435b11f7bdcbebfb31803184eafef0c20e..e3cee4a4b7909f5a8567191e629d7d93968aa22c 100644 (file)
@@ -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;
index c541926126608f0605f951bdded75f221e4fd6b1..63f514c9e8d3c0f3f0274f9e36c6ef067c6dd1e1 100644 (file)
@@ -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);
 
index 6911bc5fb719ed120adbed98a49a37bebd4b22d7..b59b7584b34af8ddd7892eb0b4efcb1eb2683d0a 100644 (file)
@@ -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);
 
index 3d0f6ff6b9f7876444af12a87d0f8eb2ec157e01..e3dfd8a6a99a7011e62daa206e9fe6ae0226ad4b 100644 (file)
@@ -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)
 {
index 5f51c434c38e180b50e17053620213e9d074b498..b6737a32ef64d928f3faa20d531a8a4a46fc3b8d 100644 (file)
@@ -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,
index 6e5f1100827be96ff5c72f916c8444727b610603..e12522bdbdd88734dc1abc05e2b243d17776c792 100644 (file)
@@ -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);
 }
 
 
index 0def823560a6c9ff5412e855159cabda246ab825..0f843da6a394fd449f2defd8a918f5a7897bab49 100644 (file)
@@ -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 */
index 09d4d8cf0ba3e25b45cc7814d48d7262427ceda8..f17f95a2ca34c4b38d782a693b2cb12e8b7664c4 100644 (file)
@@ -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;
index f8dd9c155dd4b25da5d5e77adcca1291e561731b..afadd789f73ab39c342adf5c4d7e843ea1d411c2 100644 (file)
@@ -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");