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 <quic_jouni@quicinc.com>
This commit is contained in:
Jouni Malinen 2022-07-21 20:30:07 +03:00 committed by Jouni Malinen
parent 6929564467
commit e9137950fa
5 changed files with 52 additions and 0 deletions

View file

@ -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,

View file

@ -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);

View file

@ -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);
}

View file

@ -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;

View file

@ -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,