diff --git a/src/common/dpp.c b/src/common/dpp.c index 56abe507f..c71a6424f 100644 --- a/src/common/dpp.c +++ b/src/common/dpp.c @@ -2246,6 +2246,7 @@ static int dpp_channel_local_list(struct dpp_authentication *auth, static int dpp_prepare_channel_list(struct dpp_authentication *auth, + unsigned int neg_freq, struct hostapd_hw_modes *own_modes, u16 num_modes) { @@ -2253,6 +2254,14 @@ static int dpp_prepare_channel_list(struct dpp_authentication *auth, char freqs[DPP_BOOTSTRAP_MAX_FREQ * 6 + 10], *pos, *end; unsigned int i; + if (!own_modes) { + if (!neg_freq) + return -1; + auth->num_freq = 1; + auth->freq[0] = neg_freq; + return 0; + } + if (auth->peer_bi->num_freq > 0) res = dpp_channel_intersect(auth, own_modes, num_modes); else @@ -2392,7 +2401,7 @@ struct dpp_authentication * dpp_auth_init(struct dpp_global *dpp, void *msg_ctx, auth->curve = peer_bi->curve; if (dpp_autogen_bootstrap_key(auth) < 0 || - dpp_prepare_channel_list(auth, own_modes, num_modes) < 0) + dpp_prepare_channel_list(auth, neg_freq, own_modes, num_modes) < 0) goto fail; #ifdef CONFIG_TESTING_OPTIONS @@ -2488,6 +2497,8 @@ struct dpp_authentication * dpp_auth_init(struct dpp_global *dpp, void *msg_ctx, } #endif /* CONFIG_TESTING_OPTIONS */ + if (neg_freq && auth->num_freq == 1 && auth->freq[0] == neg_freq) + neg_freq = 0; auth->req_msg = dpp_auth_build_req(auth, pi, nonce_len, r_pubkey_hash, i_pubkey_hash, neg_freq); if (!auth->req_msg) @@ -10597,10 +10608,29 @@ void dpp_bootstrap_find_pair(struct dpp_global *dpp, const u8 *i_bootstrap, if (*own_bi && *peer_bi) break; } - } +#ifdef CONFIG_DPP2 +struct dpp_bootstrap_info * dpp_bootstrap_find_chirp(struct dpp_global *dpp, + const u8 *hash) +{ + struct dpp_bootstrap_info *bi; + + if (!dpp) + return NULL; + + dl_list_for_each(bi, &dpp->bootstrap, struct dpp_bootstrap_info, list) { + if (!bi->own && os_memcmp(bi->pubkey_hash_chirp, hash, + SHA256_MAC_LEN) == 0) + return bi; + } + + return NULL; +} +#endif /* CONFIG_DPP2 */ + + static int dpp_nfc_update_bi_channel(struct dpp_bootstrap_info *own_bi, struct dpp_bootstrap_info *peer_bi) { diff --git a/src/common/dpp.h b/src/common/dpp.h index 513918bb5..61be2184b 100644 --- a/src/common/dpp.h +++ b/src/common/dpp.h @@ -578,6 +578,8 @@ void dpp_bootstrap_find_pair(struct dpp_global *dpp, const u8 *i_bootstrap, const u8 *r_bootstrap, struct dpp_bootstrap_info **own_bi, struct dpp_bootstrap_info **peer_bi); +struct dpp_bootstrap_info * dpp_bootstrap_find_chirp(struct dpp_global *dpp, + const u8 *hash); int dpp_configurator_add(struct dpp_global *dpp, const char *cmd); int dpp_configurator_remove(struct dpp_global *dpp, const char *id); int dpp_configurator_get_key_id(struct dpp_global *dpp, unsigned int id, diff --git a/wpa_supplicant/dpp_supplicant.c b/wpa_supplicant/dpp_supplicant.c index c6d555662..45fd3a744 100644 --- a/wpa_supplicant/dpp_supplicant.c +++ b/wpa_supplicant/dpp_supplicant.c @@ -1694,6 +1694,67 @@ static void wpas_dpp_remove_bi(void *ctx, struct dpp_bootstrap_info *bi) wpas_dpp_chirp_stop(wpa_s); } + +static void +wpas_dpp_rx_presence_announcement(struct wpa_supplicant *wpa_s, const u8 *src, + const u8 *hdr, const u8 *buf, size_t len, + unsigned int freq) +{ + const u8 *r_bootstrap; + u16 r_bootstrap_len; + struct dpp_bootstrap_info *peer_bi; + struct dpp_authentication *auth; + + if (!wpa_s->dpp) + return; + + if (wpa_s->dpp_auth) { + wpa_printf(MSG_DEBUG, + "DPP: Ignore Presence Announcement during ongoing Authentication"); + return; + } + + wpa_printf(MSG_DEBUG, "DPP: Presence Announcement from " MACSTR, + MAC2STR(src)); + + r_bootstrap = dpp_get_attr(buf, len, DPP_ATTR_R_BOOTSTRAP_KEY_HASH, + &r_bootstrap_len); + if (!r_bootstrap || r_bootstrap_len != SHA256_MAC_LEN) { + wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL + "Missing or invalid required Responder Bootstrapping Key Hash attribute"); + return; + } + wpa_hexdump(MSG_MSGDUMP, "DPP: Responder Bootstrapping Key Hash", + r_bootstrap, r_bootstrap_len); + peer_bi = dpp_bootstrap_find_chirp(wpa_s->dpp, r_bootstrap); + if (!peer_bi) { + wpa_printf(MSG_DEBUG, + "DPP: No matching bootstrapping information found"); + return; + } + + auth = dpp_auth_init(wpa_s->dpp, wpa_s, peer_bi, NULL, + DPP_CAPAB_CONFIGURATOR, freq, NULL, 0); + if (!auth) + return; + wpas_dpp_set_testing_options(wpa_s, auth); + if (dpp_set_configurator(auth, wpa_s->dpp_configurator_params) < 0) { + dpp_auth_deinit(auth); + return; + } + + auth->neg_freq = freq; + + if (!is_zero_ether_addr(peer_bi->mac_addr)) + os_memcpy(auth->peer_mac_addr, peer_bi->mac_addr, ETH_ALEN); + + wpa_s->dpp_auth = auth; + if (wpas_dpp_auth_init_next(wpa_s) < 0) { + dpp_auth_deinit(wpa_s->dpp_auth); + wpa_s->dpp_auth = NULL; + } +} + #endif /* CONFIG_DPP2 */ @@ -2239,6 +2300,10 @@ void wpas_dpp_rx_action(struct wpa_supplicant *wpa_s, const u8 *src, case DPP_PA_CONNECTION_STATUS_RESULT: wpas_dpp_rx_conn_status_result(wpa_s, src, hdr, buf, len); break; + case DPP_PA_PRESENCE_ANNOUNCEMENT: + wpas_dpp_rx_presence_announcement(wpa_s, src, hdr, buf, len, + freq); + break; #endif /* CONFIG_DPP2 */ default: wpa_printf(MSG_DEBUG,