diff --git a/src/common/dpp.c b/src/common/dpp.c index 99f6da3b2..5a9021922 100644 --- a/src/common/dpp.c +++ b/src/common/dpp.c @@ -1541,6 +1541,9 @@ static struct wpabuf * dpp_auth_build_resp(struct dpp_authentication *auth, size_t len[2], siv_len, attr_len; u8 *attr_start, *attr_end, *pos; + auth->waiting_auth_conf = 1; + auth->auth_resp_tries = 0; + /* Build DPP Authentication Response frame attributes */ attr_len = 4 + 1 + 2 * (4 + SHA256_MAC_LEN) + 4 + (pr ? wpabuf_len(pr) : 0) + 4 + sizeof(wrapped_data); @@ -1551,7 +1554,6 @@ static struct wpabuf * dpp_auth_build_resp(struct dpp_authentication *auth, msg = dpp_alloc_msg(DPP_PA_AUTHENTICATION_RESP, attr_len); if (!msg) return NULL; - wpabuf_free(auth->resp_msg); attr_start = wpabuf_put(msg, 0); @@ -2497,6 +2499,7 @@ static int dpp_auth_build_resp_ok(struct dpp_authentication *auth) auth->k2); if (!msg) goto fail; + wpabuf_free(auth->resp_msg); auth->resp_msg = msg; ret = 0; fail: @@ -2542,6 +2545,7 @@ static int dpp_auth_build_resp_status(struct dpp_authentication *auth, NULL, i_nonce, NULL, 0, auth->k1); if (!msg) return -1; + wpabuf_free(auth->resp_msg); auth->resp_msg = msg; return 0; } @@ -3454,6 +3458,8 @@ int dpp_auth_conf_rx(struct dpp_authentication *auth, const u8 *hdr, size_t unwrapped_len = 0; u8 i_auth2[DPP_MAX_HASH_LEN]; + auth->waiting_auth_conf = 0; + wrapped_data = dpp_get_attr(attr_start, attr_len, DPP_ATTR_WRAPPED_DATA, &wrapped_data_len); if (!wrapped_data || wrapped_data_len < AES_BLOCK_SIZE) { diff --git a/src/common/dpp.h b/src/common/dpp.h index 161ffb942..6c2805838 100644 --- a/src/common/dpp.h +++ b/src/common/dpp.h @@ -183,6 +183,8 @@ struct dpp_authentication { u8 ke[DPP_MAX_HASH_LEN]; int initiator; int waiting_auth_resp; + int waiting_auth_conf; + unsigned int auth_resp_tries; u8 allowed_roles; int configurator; int remove_on_tx_status; diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index c2c423587..f756bcae6 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -611,6 +611,10 @@ static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s, wpa_s->dpp_init_retry_time = atoi(value); } else if (os_strcasecmp(cmd, "dpp_resp_wait_time") == 0) { wpa_s->dpp_resp_wait_time = atoi(value); + } else if (os_strcasecmp(cmd, "dpp_resp_max_tries") == 0) { + wpa_s->dpp_resp_max_tries = atoi(value); + } else if (os_strcasecmp(cmd, "dpp_resp_retry_time") == 0) { + wpa_s->dpp_resp_retry_time = atoi(value); #endif /* CONFIG_DPP */ #ifdef CONFIG_TESTING_OPTIONS } else if (os_strcasecmp(cmd, "ext_mgmt_frame_handling") == 0) { @@ -7755,6 +7759,8 @@ static void wpa_supplicant_ctrl_iface_flush(struct wpa_supplicant *wpa_s) wpa_s->dpp_init_max_tries = 0; wpa_s->dpp_init_retry_time = 0; wpa_s->dpp_resp_wait_time = 0; + wpa_s->dpp_resp_max_tries = 0; + wpa_s->dpp_resp_retry_time = 0; #endif /* CONFIG_DPP */ #ifdef CONFIG_TDLS diff --git a/wpa_supplicant/dpp_supplicant.c b/wpa_supplicant/dpp_supplicant.c index 2f7a9940a..e34f68dbd 100644 --- a/wpa_supplicant/dpp_supplicant.c +++ b/wpa_supplicant/dpp_supplicant.c @@ -300,6 +300,63 @@ int wpas_dpp_bootstrap_info(struct wpa_supplicant *wpa_s, int id, } +static void wpas_dpp_auth_resp_retry_timeout(void *eloop_ctx, void *timeout_ctx) +{ + struct wpa_supplicant *wpa_s = eloop_ctx; + struct dpp_authentication *auth = wpa_s->dpp_auth; + + if (!auth || !auth->resp_msg) + return; + + wpa_printf(MSG_DEBUG, + "DPP: Retry Authentication Response after timeout"); + wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR + " freq=%u type=%d", + MAC2STR(auth->peer_mac_addr), auth->curr_freq, + DPP_PA_AUTHENTICATION_RESP); + offchannel_send_action(wpa_s, auth->curr_freq, auth->peer_mac_addr, + wpa_s->own_addr, broadcast, + wpabuf_head(auth->resp_msg), + wpabuf_len(auth->resp_msg), + 500, wpas_dpp_tx_status, 0); +} + + +static void wpas_dpp_auth_resp_retry(struct wpa_supplicant *wpa_s) +{ + struct dpp_authentication *auth = wpa_s->dpp_auth; + unsigned int wait_time, max_tries; + + if (!auth || !auth->resp_msg) + return; + + if (wpa_s->dpp_resp_max_tries) + max_tries = wpa_s->dpp_resp_max_tries; + else + max_tries = 5; + auth->auth_resp_tries++; + if (auth->auth_resp_tries >= max_tries) { + wpa_printf(MSG_INFO, "DPP: No confirm received from initiator - stopping exchange"); + offchannel_send_action_done(wpa_s); + dpp_auth_deinit(wpa_s->dpp_auth); + wpa_s->dpp_auth = NULL; + return; + } + + if (wpa_s->dpp_resp_retry_time) + wait_time = wpa_s->dpp_resp_retry_time; + else + wait_time = 10000; + wpa_printf(MSG_DEBUG, + "DPP: Schedule retransmission of Authentication Response frame in %u ms", + wait_time); + eloop_cancel_timeout(wpas_dpp_auth_resp_retry_timeout, wpa_s, NULL); + eloop_register_timeout(wait_time / 1000, + (wait_time % 1000) * 1000, + wpas_dpp_auth_resp_retry_timeout, wpa_s, NULL); +} + + static void wpas_dpp_tx_status(struct wpa_supplicant *wpa_s, unsigned int freq, const u8 *dst, const u8 *src, const u8 *bssid, @@ -328,6 +385,8 @@ static void wpas_dpp_tx_status(struct wpa_supplicant *wpa_s, "DPP: Terminate authentication exchange due to an earlier error"); eloop_cancel_timeout(wpas_dpp_init_timeout, wpa_s, NULL); eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL); + eloop_cancel_timeout(wpas_dpp_auth_resp_retry_timeout, wpa_s, + NULL); offchannel_send_action_done(wpa_s); dpp_auth_deinit(wpa_s->dpp_auth); wpa_s->dpp_auth = NULL; @@ -348,6 +407,10 @@ static void wpas_dpp_tx_status(struct wpa_supplicant *wpa_s, wpas_dpp_auth_init_next(wpa_s); return; } + if (auth->waiting_auth_conf) { + wpas_dpp_auth_resp_retry(wpa_s); + return; + } } if (!wpa_s->dpp_auth_ok_on_ack && wpa_s->dpp_auth->neg_freq > 0 && @@ -685,6 +748,8 @@ int wpas_dpp_auth_init(struct wpa_supplicant *wpa_s, const char *cmd) if (wpa_s->dpp_auth) { eloop_cancel_timeout(wpas_dpp_init_timeout, wpa_s, NULL); eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL); + eloop_cancel_timeout(wpas_dpp_auth_resp_retry_timeout, wpa_s, + NULL); offchannel_send_action_done(wpa_s); dpp_auth_deinit(wpa_s->dpp_auth); } @@ -1856,6 +1921,7 @@ wpas_dpp_gas_status_handler(void *ctx, struct wpabuf *resp, int ok) wpa_printf(MSG_DEBUG, "DPP: Configuration exchange completed (ok=%d)", ok); eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL); + eloop_cancel_timeout(wpas_dpp_auth_resp_retry_timeout, wpa_s, NULL); offchannel_send_action_done(wpa_s); wpas_dpp_listen_stop(wpa_s); if (ok) @@ -2244,6 +2310,7 @@ void wpas_dpp_deinit(struct wpa_supplicant *wpa_s) return; eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL); eloop_cancel_timeout(wpas_dpp_init_timeout, wpa_s, NULL); + eloop_cancel_timeout(wpas_dpp_auth_resp_retry_timeout, wpa_s, NULL); offchannel_send_action_done(wpa_s); wpas_dpp_listen_stop(wpa_s); dpp_bootstrap_del(wpa_s, 0); diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h index 65454edf7..099c8d085 100644 --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -1203,6 +1203,8 @@ struct wpa_supplicant { unsigned int dpp_init_max_tries; unsigned int dpp_init_retry_time; unsigned int dpp_resp_wait_time; + unsigned int dpp_resp_max_tries; + unsigned int dpp_resp_retry_time; #ifdef CONFIG_TESTING_OPTIONS char *dpp_config_obj_override; char *dpp_discovery_override;