From e9137950fa8d4cf695c467b52210214980e4bbf6 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Thu, 21 Jul 2022 20:30:07 +0300 Subject: [PATCH] DPP: Recognize own PKEX Exchange Request if it ends up being received It is possible for a Controller to receive a copy of its own PKEX Exchange Request in the case where the Controller is initiating a PKEX exchange through a Relay. The Configurator role in the device would have a matching PKEX code in that case and the device might reply as a PKEX responder which would result in going through the exchange with the Controller device itself. That is clearly not desired, so recognize this special case by checking whether the Encrypted Key attribute value matches a pending locally generated one when processing a received PKEX Exchange Request. Signed-off-by: Jouni Malinen --- src/ap/dpp_hostapd.c | 9 +++++++++ src/common/dpp.h | 3 +++ src/common/dpp_pkex.c | 3 +++ src/common/dpp_tcp.c | 29 +++++++++++++++++++++++++++++ wpa_supplicant/dpp_supplicant.c | 8 ++++++++ 5 files changed, 52 insertions(+) diff --git a/src/ap/dpp_hostapd.c b/src/ap/dpp_hostapd.c index d85a38df8..ed4625dde 100644 --- a/src/ap/dpp_hostapd.c +++ b/src/ap/dpp_hostapd.c @@ -2132,6 +2132,15 @@ hostapd_dpp_rx_pkex_exchange_req(struct hostapd_data *hapd, const u8 *src, goto try_relay; } +#ifdef CONFIG_DPP2 + if (dpp_controller_is_own_pkex_req(hapd->iface->interfaces->dpp, + buf, len)) { + wpa_printf(MSG_DEBUG, + "DPP: PKEX Exchange Request is from local Controller - ignore request"); + return; + } +#endif /* CONFIG_DPP2 */ + if (hapd->dpp_pkex) { /* TODO: Support parallel operations */ wpa_printf(MSG_DEBUG, diff --git a/src/common/dpp.h b/src/common/dpp.h index da9a33b5e..08febd94f 100644 --- a/src/common/dpp.h +++ b/src/common/dpp.h @@ -222,6 +222,7 @@ struct dpp_pkex { unsigned int exch_req_tries; unsigned int freq; u8 peer_version; + struct wpabuf *enc_key; }; enum dpp_akm { @@ -605,6 +606,8 @@ int dpp_notify_new_qr_code(struct dpp_authentication *auth, void dpp_controller_pkex_add(struct dpp_global *dpp, struct dpp_bootstrap_info *bi, const char *code, const char *identifier); +bool dpp_controller_is_own_pkex_req(struct dpp_global *dpp, + const u8 *buf, size_t len); struct dpp_configuration * dpp_configuration_alloc(const char *type); int dpp_akm_psk(enum dpp_akm akm); int dpp_akm_sae(enum dpp_akm akm); diff --git a/src/common/dpp_pkex.c b/src/common/dpp_pkex.c index c4713a4fe..ff650cf0e 100644 --- a/src/common/dpp_pkex.c +++ b/src/common/dpp_pkex.c @@ -145,6 +145,8 @@ skip_finite_cyclic_group: My = wpabuf_put(msg, curve->prime_len); if (crypto_ec_point_to_bin(ec, M, Mx, My)) goto fail; + wpabuf_free(pkex->enc_key); + pkex->enc_key = wpabuf_alloc_copy(Mx, 2 * curve->prime_len); os_memcpy(pkex->Mx, Mx, curve->prime_len); @@ -1379,5 +1381,6 @@ void dpp_pkex_free(struct dpp_pkex *pkex) crypto_ec_key_deinit(pkex->peer_bootstrap_key); wpabuf_free(pkex->exchange_req); wpabuf_free(pkex->exchange_resp); + wpabuf_free(pkex->enc_key); os_free(pkex); } diff --git a/src/common/dpp_tcp.c b/src/common/dpp_tcp.c index 5cd732907..fc5dfb973 100644 --- a/src/common/dpp_tcp.c +++ b/src/common/dpp_tcp.c @@ -2264,6 +2264,35 @@ void dpp_controller_pkex_add(struct dpp_global *dpp, } +bool dpp_controller_is_own_pkex_req(struct dpp_global *dpp, + const u8 *buf, size_t len) +{ + struct dpp_connection *conn; + const u8 *attr_key = NULL; + u16 attr_key_len = 0; + + dl_list_for_each(conn, &dpp->tcp_init, struct dpp_connection, list) { + if (!conn->pkex || !conn->pkex->enc_key) + continue; + + if (!attr_key) { + attr_key = dpp_get_attr(buf, len, + DPP_ATTR_ENCRYPTED_KEY, + &attr_key_len); + if (!attr_key) + return false; + } + + if (attr_key_len == wpabuf_len(conn->pkex->enc_key) && + os_memcmp(attr_key, wpabuf_head(conn->pkex->enc_key), + attr_key_len) == 0) + return true; + } + + return false; +} + + void dpp_tcp_init_flush(struct dpp_global *dpp) { struct dpp_connection *conn, *tmp; diff --git a/wpa_supplicant/dpp_supplicant.c b/wpa_supplicant/dpp_supplicant.c index 4b2e91a3a..64eb5ea63 100644 --- a/wpa_supplicant/dpp_supplicant.c +++ b/wpa_supplicant/dpp_supplicant.c @@ -2976,6 +2976,14 @@ wpas_dpp_rx_pkex_exchange_req(struct wpa_supplicant *wpa_s, const u8 *src, return; } +#ifdef CONFIG_DPP2 + if (dpp_controller_is_own_pkex_req(wpa_s->dpp, buf, len)) { + wpa_printf(MSG_DEBUG, + "DPP: PKEX Exchange Request is from local Controller - ignore request"); + return; + } +#endif /* CONFIG_DPP2 */ + if (wpa_s->dpp_pkex) { /* TODO: Support parallel operations */ wpa_printf(MSG_DEBUG,