@@ -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;
}
@@ -1588,6 +1588,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));
@@ -1632,7 +1634,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 "
@@ -1655,9 +1657,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), "hostap");
+
+ 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;
}
@@ -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);
@@ -23,6 +23,7 @@ struct rsn_pmksa_cache_entry {
int akmp; /* WPA_KEY_MGMT_* */
u8 spa[ETH_ALEN];
+ u8 *dpp_pkhash;
u8 *identity;
size_t identity_len;
struct wpabuf *cui;
@@ -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);
@@ -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);
@@ -4683,6 +4683,16 @@ 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)
+ 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 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 (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)
{
@@ -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 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);
@@ -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 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,
@@ -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;
@@ -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,
@@ -1408,6 +1408,7 @@ dpp_auth_resp_rx(struct dpp_authentication *auth, const u8 *hdr,
EVP_PKEY *pr;
size_t secret_len;
const u8 *addr[2];
+ u8 hex[SHA256_MAC_LEN*2 + 1];
size_t len[2];
u8 *unwrapped = NULL, *unwrapped2 = NULL;
size_t unwrapped_len = 0, unwrapped2_len = 0;
@@ -1563,6 +1564,10 @@ dpp_auth_resp_rx(struct dpp_authentication *auth, const u8 *hdr,
}
dpp_debug_print_key("Peer (Responder) Protocol Key", pr);
+ os_memset(hex, 0, sizeof(hex));
+ dpp_get_pubkey_hash(pr, hex, sizeof(hex), "hostap");
+ wpa_msg(auth->msg_ctx, MSG_INFO, DPP_EVENT_AUTH_PK_HASH "%s", hex);
+
if (dpp_ecdh(auth->own_protocol_key, pr, auth->Nx, &secret_len) < 0) {
dpp_auth_fail(auth, "Failed to derive ECDH shared secret");
goto fail;
@@ -520,6 +520,44 @@ EVP_PKEY * dpp_set_pubkey_point(EVP_PKEY *group_key, const u8 *buf, size_t len)
}
+int dpp_get_pubkey_hash(EVP_PKEY *key, u8 *hexstr, size_t len, const char *salt)
+{
+ unsigned char *der = NULL;
+ const u8 *args[2];
+ size_t lens[2];
+ char 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;
+
+ if (!salt)
+ salt = "";
+
+ der_len = i2d_EC_PUBKEY(eckey, &der);
+ if (der_len > 0) {
+ args[0] = salt;
+ lens[0] = strlen(salt);
+ args[1] = der;
+ lens[1] = der_len;
+
+ if (sha256_vector(2, 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;
@@ -81,6 +81,7 @@ EVP_PKEY * dpp_set_pubkey_point_group(const EC_GROUP *group,
const u8 *buf_x, const u8 *buf_y,
size_t len);
EVP_PKEY * dpp_set_pubkey_point(EVP_PKEY *group_key, const u8 *buf, size_t len);
+int dpp_get_pubkey_hash(EVP_PKEY *key, u8 *hexstr, size_t len, const char *salt);
int dpp_bn2bin_pad(const BIGNUM *bn, u8 *pos, size_t len);
int dpp_hkdf_expand(size_t hash_len, const u8 *secret, size_t secret_len,
const char *label, u8 *out, size_t outlen);
@@ -173,6 +173,7 @@ extern "C" {
#define DPP_EVENT_RESPONSE_PENDING "DPP-RESPONSE-PENDING "
#define DPP_EVENT_SCAN_PEER_QR_CODE "DPP-SCAN-PEER-QR-CODE "
#define DPP_EVENT_AUTH_DIRECTION "DPP-AUTH-DIRECTION "
+#define DPP_EVENT_AUTH_PK_HASH "DPP-AUTH-PK-HASH "
#define DPP_EVENT_CONF_RECEIVED "DPP-CONF-RECEIVED "
#define DPP_EVENT_CONF_SENT "DPP-CONF-SENT "
#define DPP_EVENT_CONF_FAILED "DPP-CONF-FAILED "
@@ -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");