DPP: Retransmit DPP Authentication Response frame if it is not ACKed
This extends wpa_supplicant DPP implementation to retransmit DPP Authentication Response frame every 10 seconds up to 5 times if the peer does not reply with DPP Authentication Confirm frame. Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
This commit is contained in:
parent
c1d3773967
commit
95b0104a34
5 changed files with 84 additions and 1 deletions
|
@ -1541,6 +1541,9 @@ static struct wpabuf * dpp_auth_build_resp(struct dpp_authentication *auth,
|
||||||
size_t len[2], siv_len, attr_len;
|
size_t len[2], siv_len, attr_len;
|
||||||
u8 *attr_start, *attr_end, *pos;
|
u8 *attr_start, *attr_end, *pos;
|
||||||
|
|
||||||
|
auth->waiting_auth_conf = 1;
|
||||||
|
auth->auth_resp_tries = 0;
|
||||||
|
|
||||||
/* Build DPP Authentication Response frame attributes */
|
/* Build DPP Authentication Response frame attributes */
|
||||||
attr_len = 4 + 1 + 2 * (4 + SHA256_MAC_LEN) +
|
attr_len = 4 + 1 + 2 * (4 + SHA256_MAC_LEN) +
|
||||||
4 + (pr ? wpabuf_len(pr) : 0) + 4 + sizeof(wrapped_data);
|
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);
|
msg = dpp_alloc_msg(DPP_PA_AUTHENTICATION_RESP, attr_len);
|
||||||
if (!msg)
|
if (!msg)
|
||||||
return NULL;
|
return NULL;
|
||||||
wpabuf_free(auth->resp_msg);
|
|
||||||
|
|
||||||
attr_start = wpabuf_put(msg, 0);
|
attr_start = wpabuf_put(msg, 0);
|
||||||
|
|
||||||
|
@ -2497,6 +2499,7 @@ static int dpp_auth_build_resp_ok(struct dpp_authentication *auth)
|
||||||
auth->k2);
|
auth->k2);
|
||||||
if (!msg)
|
if (!msg)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
wpabuf_free(auth->resp_msg);
|
||||||
auth->resp_msg = msg;
|
auth->resp_msg = msg;
|
||||||
ret = 0;
|
ret = 0;
|
||||||
fail:
|
fail:
|
||||||
|
@ -2542,6 +2545,7 @@ static int dpp_auth_build_resp_status(struct dpp_authentication *auth,
|
||||||
NULL, i_nonce, NULL, 0, auth->k1);
|
NULL, i_nonce, NULL, 0, auth->k1);
|
||||||
if (!msg)
|
if (!msg)
|
||||||
return -1;
|
return -1;
|
||||||
|
wpabuf_free(auth->resp_msg);
|
||||||
auth->resp_msg = msg;
|
auth->resp_msg = msg;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -3454,6 +3458,8 @@ int dpp_auth_conf_rx(struct dpp_authentication *auth, const u8 *hdr,
|
||||||
size_t unwrapped_len = 0;
|
size_t unwrapped_len = 0;
|
||||||
u8 i_auth2[DPP_MAX_HASH_LEN];
|
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 = dpp_get_attr(attr_start, attr_len, DPP_ATTR_WRAPPED_DATA,
|
||||||
&wrapped_data_len);
|
&wrapped_data_len);
|
||||||
if (!wrapped_data || wrapped_data_len < AES_BLOCK_SIZE) {
|
if (!wrapped_data || wrapped_data_len < AES_BLOCK_SIZE) {
|
||||||
|
|
|
@ -183,6 +183,8 @@ struct dpp_authentication {
|
||||||
u8 ke[DPP_MAX_HASH_LEN];
|
u8 ke[DPP_MAX_HASH_LEN];
|
||||||
int initiator;
|
int initiator;
|
||||||
int waiting_auth_resp;
|
int waiting_auth_resp;
|
||||||
|
int waiting_auth_conf;
|
||||||
|
unsigned int auth_resp_tries;
|
||||||
u8 allowed_roles;
|
u8 allowed_roles;
|
||||||
int configurator;
|
int configurator;
|
||||||
int remove_on_tx_status;
|
int remove_on_tx_status;
|
||||||
|
|
|
@ -611,6 +611,10 @@ static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s,
|
||||||
wpa_s->dpp_init_retry_time = atoi(value);
|
wpa_s->dpp_init_retry_time = atoi(value);
|
||||||
} else if (os_strcasecmp(cmd, "dpp_resp_wait_time") == 0) {
|
} else if (os_strcasecmp(cmd, "dpp_resp_wait_time") == 0) {
|
||||||
wpa_s->dpp_resp_wait_time = atoi(value);
|
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 */
|
#endif /* CONFIG_DPP */
|
||||||
#ifdef CONFIG_TESTING_OPTIONS
|
#ifdef CONFIG_TESTING_OPTIONS
|
||||||
} else if (os_strcasecmp(cmd, "ext_mgmt_frame_handling") == 0) {
|
} 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_max_tries = 0;
|
||||||
wpa_s->dpp_init_retry_time = 0;
|
wpa_s->dpp_init_retry_time = 0;
|
||||||
wpa_s->dpp_resp_wait_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 */
|
#endif /* CONFIG_DPP */
|
||||||
|
|
||||||
#ifdef CONFIG_TDLS
|
#ifdef CONFIG_TDLS
|
||||||
|
|
|
@ -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,
|
static void wpas_dpp_tx_status(struct wpa_supplicant *wpa_s,
|
||||||
unsigned int freq, const u8 *dst,
|
unsigned int freq, const u8 *dst,
|
||||||
const u8 *src, const u8 *bssid,
|
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");
|
"DPP: Terminate authentication exchange due to an earlier error");
|
||||||
eloop_cancel_timeout(wpas_dpp_init_timeout, wpa_s, NULL);
|
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_reply_wait_timeout, wpa_s, NULL);
|
||||||
|
eloop_cancel_timeout(wpas_dpp_auth_resp_retry_timeout, wpa_s,
|
||||||
|
NULL);
|
||||||
offchannel_send_action_done(wpa_s);
|
offchannel_send_action_done(wpa_s);
|
||||||
dpp_auth_deinit(wpa_s->dpp_auth);
|
dpp_auth_deinit(wpa_s->dpp_auth);
|
||||||
wpa_s->dpp_auth = NULL;
|
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);
|
wpas_dpp_auth_init_next(wpa_s);
|
||||||
return;
|
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 &&
|
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) {
|
if (wpa_s->dpp_auth) {
|
||||||
eloop_cancel_timeout(wpas_dpp_init_timeout, wpa_s, NULL);
|
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_reply_wait_timeout, wpa_s, NULL);
|
||||||
|
eloop_cancel_timeout(wpas_dpp_auth_resp_retry_timeout, wpa_s,
|
||||||
|
NULL);
|
||||||
offchannel_send_action_done(wpa_s);
|
offchannel_send_action_done(wpa_s);
|
||||||
dpp_auth_deinit(wpa_s->dpp_auth);
|
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)",
|
wpa_printf(MSG_DEBUG, "DPP: Configuration exchange completed (ok=%d)",
|
||||||
ok);
|
ok);
|
||||||
eloop_cancel_timeout(wpas_dpp_reply_wait_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);
|
offchannel_send_action_done(wpa_s);
|
||||||
wpas_dpp_listen_stop(wpa_s);
|
wpas_dpp_listen_stop(wpa_s);
|
||||||
if (ok)
|
if (ok)
|
||||||
|
@ -2244,6 +2310,7 @@ void wpas_dpp_deinit(struct wpa_supplicant *wpa_s)
|
||||||
return;
|
return;
|
||||||
eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL);
|
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_init_timeout, wpa_s, NULL);
|
||||||
|
eloop_cancel_timeout(wpas_dpp_auth_resp_retry_timeout, wpa_s, NULL);
|
||||||
offchannel_send_action_done(wpa_s);
|
offchannel_send_action_done(wpa_s);
|
||||||
wpas_dpp_listen_stop(wpa_s);
|
wpas_dpp_listen_stop(wpa_s);
|
||||||
dpp_bootstrap_del(wpa_s, 0);
|
dpp_bootstrap_del(wpa_s, 0);
|
||||||
|
|
|
@ -1203,6 +1203,8 @@ struct wpa_supplicant {
|
||||||
unsigned int dpp_init_max_tries;
|
unsigned int dpp_init_max_tries;
|
||||||
unsigned int dpp_init_retry_time;
|
unsigned int dpp_init_retry_time;
|
||||||
unsigned int dpp_resp_wait_time;
|
unsigned int dpp_resp_wait_time;
|
||||||
|
unsigned int dpp_resp_max_tries;
|
||||||
|
unsigned int dpp_resp_retry_time;
|
||||||
#ifdef CONFIG_TESTING_OPTIONS
|
#ifdef CONFIG_TESTING_OPTIONS
|
||||||
char *dpp_config_obj_override;
|
char *dpp_config_obj_override;
|
||||||
char *dpp_discovery_override;
|
char *dpp_discovery_override;
|
||||||
|
|
Loading…
Reference in a new issue