}
+static void restore_tk(void *ctx1, void *ctx2)
+{
+ struct hostapd_data *hapd = ctx1;
+ struct sta_info *sta = ctx2;
+
+ wpa_printf(MSG_INFO, "TESTING: Restore TK for " MACSTR,
+ MAC2STR(sta->addr));
+ /* This does not really restore the TSC properly, so this will result
+ * in replay protection issues for now since there is no clean way of
+ * preventing encryption of a single EAPOL frame. */
+ hostapd_drv_set_key(hapd->conf->iface, hapd, sta->last_tk_alg,
+ sta->addr, sta->last_tk_key_idx, 1, NULL, 0,
+ sta->last_tk, sta->last_tk_len);
+}
+
+
static int hostapd_ctrl_resend_m1(struct hostapd_data *hapd, const char *cmd)
{
struct sta_info *sta;
u8 addr[ETH_ALEN];
+ int plain = os_strstr(cmd, "plaintext") != NULL;
if (hwaddr_aton(cmd, addr))
return -1;
if (!sta || !sta->wpa_sm)
return -1;
+ if (plain && sta->last_tk_alg == WPA_ALG_NONE)
+ plain = 0; /* no need for special processing */
+ if (plain) {
+ wpa_printf(MSG_INFO, "TESTING: Clear TK for " MACSTR,
+ MAC2STR(sta->addr));
+ hostapd_drv_set_key(hapd->conf->iface, hapd, WPA_ALG_NONE,
+ sta->addr, sta->last_tk_key_idx, 0, NULL, 0,
+ NULL, 0);
+ }
+
wpa_printf(MSG_INFO, "TESTING: Send M1 to " MACSTR, MAC2STR(sta->addr));
return wpa_auth_resend_m1(sta->wpa_sm,
- os_strstr(cmd, "change-anonce") != NULL);
+ os_strstr(cmd, "change-anonce") != NULL,
+ plain ? restore_tk : NULL, hapd, sta);
}
{
struct sta_info *sta;
u8 addr[ETH_ALEN];
+ int plain = os_strstr(cmd, "plaintext") != NULL;
if (hwaddr_aton(cmd, addr))
return -1;
if (!sta || !sta->wpa_sm)
return -1;
+ if (plain && sta->last_tk_alg == WPA_ALG_NONE)
+ plain = 0; /* no need for special processing */
+ if (plain) {
+ wpa_printf(MSG_INFO, "TESTING: Clear TK for " MACSTR,
+ MAC2STR(sta->addr));
+ hostapd_drv_set_key(hapd->conf->iface, hapd, WPA_ALG_NONE,
+ sta->addr, sta->last_tk_key_idx, 0, NULL, 0,
+ NULL, 0);
+ }
+
wpa_printf(MSG_INFO, "TESTING: Send M3 to " MACSTR, MAC2STR(sta->addr));
- return wpa_auth_resend_m3(sta->wpa_sm);
+ return wpa_auth_resend_m3(sta->wpa_sm,
+ plain ? restore_tk : NULL, hapd, sta);
}
{
struct sta_info *sta;
u8 addr[ETH_ALEN];
+ int plain = os_strstr(cmd, "plaintext") != NULL;
if (hwaddr_aton(cmd, addr))
return -1;
if (!sta || !sta->wpa_sm)
return -1;
+ if (plain && sta->last_tk_alg == WPA_ALG_NONE)
+ plain = 0; /* no need for special processing */
+ if (plain) {
+ wpa_printf(MSG_INFO, "TESTING: Clear TK for " MACSTR,
+ MAC2STR(sta->addr));
+ hostapd_drv_set_key(hapd->conf->iface, hapd, WPA_ALG_NONE,
+ sta->addr, sta->last_tk_key_idx, 0, NULL, 0,
+ NULL, 0);
+ }
+
wpa_printf(MSG_INFO,
"TESTING: Send group M1 for the same GTK and zero RSC to "
MACSTR, MAC2STR(sta->addr));
- return wpa_auth_resend_group_m1(sta->wpa_sm);
+ return wpa_auth_resend_group_m1(sta->wpa_sm,
+ plain ? restore_tk : NULL, hapd, sta);
}
#endif /* CONFIG_TESTING_OPTIONS */
(timeout_ms % 1000) * 1000,
wpa_send_eapol_timeout, wpa_auth, sm);
}
+
+#ifdef CONFIG_TESTING_OPTIONS
+ if (sm->eapol_status_cb) {
+ sm->eapol_status_cb(sm->eapol_status_cb_ctx1,
+ sm->eapol_status_cb_ctx2);
+ sm->eapol_status_cb = NULL;
+ }
+#endif /* CONFIG_TESTING_OPTIONS */
}
#if CONFIG_TESTING_OPTIONS
-int wpa_auth_resend_m1(struct wpa_state_machine *sm, int change_anonce)
+int wpa_auth_resend_m1(struct wpa_state_machine *sm, int change_anonce,
+ void (*cb)(void *ctx1, void *ctx2),
+ void *ctx1, void *ctx2)
{
const u8 *anonce = sm->ANonce;
u8 anonce_buf[WPA_NONCE_LEN];
}
-int wpa_auth_resend_m3(struct wpa_state_machine *sm)
+int wpa_auth_resend_m3(struct wpa_state_machine *sm,
+ void (*cb)(void *ctx1, void *ctx2),
+ void *ctx1, void *ctx2)
{
u8 rsc[WPA_KEY_RSC_LEN], *_rsc, *gtk, *kde, *pos, *opos;
size_t gtk_len, kde_len;
}
-int wpa_auth_resend_group_m1(struct wpa_state_machine *sm)
+int wpa_auth_resend_group_m1(struct wpa_state_machine *sm,
+ void (*cb)(void *ctx1, void *ctx2),
+ void *ctx1, void *ctx2)
{
u8 rsc[WPA_KEY_RSC_LEN];
struct wpa_group *gsm = sm->group;
kde_len = gsm->GTK_len;
}
+ sm->eapol_status_cb = cb;
+ sm->eapol_status_cb_ctx1 = ctx1;
+ sm->eapol_status_cb_ctx2 = ctx2;
+
wpa_send_eapol(sm->wpa_auth, sm,
WPA_KEY_INFO_SECURE |
(wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len) ?
u8 *pos, size_t max_len,
const u8 *req_ies, size_t req_ies_len);
-int wpa_auth_resend_m1(struct wpa_state_machine *sm, int change_anonce);
-int wpa_auth_resend_m3(struct wpa_state_machine *sm);
-int wpa_auth_resend_group_m1(struct wpa_state_machine *sm);
+int wpa_auth_resend_m1(struct wpa_state_machine *sm, int change_anonce,
+ void (*cb)(void *ctx1, void *ctx2),
+ void *ctx1, void *ctx2);
+int wpa_auth_resend_m3(struct wpa_state_machine *sm,
+ void (*cb)(void *ctx1, void *ctx2),
+ void *ctx1, void *ctx2);
+int wpa_auth_resend_group_m1(struct wpa_state_machine *sm,
+ void (*cb)(void *ctx1, void *ctx2),
+ void *ctx1, void *ctx2);
#endif /* WPA_AUTH_H */