1e5b75505Sopenharmony_ci/*
2e5b75505Sopenharmony_ci * hostapd / TKIP countermeasures
3e5b75505Sopenharmony_ci * Copyright (c) 2002-2012, Jouni Malinen <j@w1.fi>
4e5b75505Sopenharmony_ci *
5e5b75505Sopenharmony_ci * This software may be distributed under the terms of the BSD license.
6e5b75505Sopenharmony_ci * See README for more details.
7e5b75505Sopenharmony_ci */
8e5b75505Sopenharmony_ci
9e5b75505Sopenharmony_ci#include "utils/includes.h"
10e5b75505Sopenharmony_ci
11e5b75505Sopenharmony_ci#include "utils/common.h"
12e5b75505Sopenharmony_ci#include "utils/eloop.h"
13e5b75505Sopenharmony_ci#include "common/ieee802_11_defs.h"
14e5b75505Sopenharmony_ci#include "radius/radius.h"
15e5b75505Sopenharmony_ci#include "hostapd.h"
16e5b75505Sopenharmony_ci#include "sta_info.h"
17e5b75505Sopenharmony_ci#include "ap_mlme.h"
18e5b75505Sopenharmony_ci#include "wpa_auth.h"
19e5b75505Sopenharmony_ci#include "ap_drv_ops.h"
20e5b75505Sopenharmony_ci#include "tkip_countermeasures.h"
21e5b75505Sopenharmony_ci
22e5b75505Sopenharmony_ci
23e5b75505Sopenharmony_cistatic void ieee80211_tkip_countermeasures_stop(void *eloop_ctx,
24e5b75505Sopenharmony_ci						void *timeout_ctx)
25e5b75505Sopenharmony_ci{
26e5b75505Sopenharmony_ci	struct hostapd_data *hapd = eloop_ctx;
27e5b75505Sopenharmony_ci	hapd->tkip_countermeasures = 0;
28e5b75505Sopenharmony_ci	hostapd_drv_set_countermeasures(hapd, 0);
29e5b75505Sopenharmony_ci	hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211,
30e5b75505Sopenharmony_ci		       HOSTAPD_LEVEL_INFO, "TKIP countermeasures ended");
31e5b75505Sopenharmony_ci}
32e5b75505Sopenharmony_ci
33e5b75505Sopenharmony_ci
34e5b75505Sopenharmony_cistatic void ieee80211_tkip_countermeasures_start(struct hostapd_data *hapd)
35e5b75505Sopenharmony_ci{
36e5b75505Sopenharmony_ci	struct sta_info *sta;
37e5b75505Sopenharmony_ci
38e5b75505Sopenharmony_ci	hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211,
39e5b75505Sopenharmony_ci		       HOSTAPD_LEVEL_INFO, "TKIP countermeasures initiated");
40e5b75505Sopenharmony_ci
41e5b75505Sopenharmony_ci	wpa_auth_countermeasures_start(hapd->wpa_auth);
42e5b75505Sopenharmony_ci	hapd->tkip_countermeasures = 1;
43e5b75505Sopenharmony_ci	hostapd_drv_set_countermeasures(hapd, 1);
44e5b75505Sopenharmony_ci	wpa_gtk_rekey(hapd->wpa_auth);
45e5b75505Sopenharmony_ci	eloop_cancel_timeout(ieee80211_tkip_countermeasures_stop, hapd, NULL);
46e5b75505Sopenharmony_ci	eloop_register_timeout(60, 0, ieee80211_tkip_countermeasures_stop,
47e5b75505Sopenharmony_ci			       hapd, NULL);
48e5b75505Sopenharmony_ci	while ((sta = hapd->sta_list)) {
49e5b75505Sopenharmony_ci		sta->acct_terminate_cause =
50e5b75505Sopenharmony_ci			RADIUS_ACCT_TERMINATE_CAUSE_ADMIN_RESET;
51e5b75505Sopenharmony_ci		if (sta->flags & WLAN_STA_AUTH) {
52e5b75505Sopenharmony_ci			mlme_deauthenticate_indication(
53e5b75505Sopenharmony_ci				hapd, sta,
54e5b75505Sopenharmony_ci				WLAN_REASON_MICHAEL_MIC_FAILURE);
55e5b75505Sopenharmony_ci		}
56e5b75505Sopenharmony_ci		hostapd_drv_sta_deauth(hapd, sta->addr,
57e5b75505Sopenharmony_ci				       WLAN_REASON_MICHAEL_MIC_FAILURE);
58e5b75505Sopenharmony_ci		ap_free_sta(hapd, sta);
59e5b75505Sopenharmony_ci	}
60e5b75505Sopenharmony_ci}
61e5b75505Sopenharmony_ci
62e5b75505Sopenharmony_ci
63e5b75505Sopenharmony_civoid ieee80211_tkip_countermeasures_deinit(struct hostapd_data *hapd)
64e5b75505Sopenharmony_ci{
65e5b75505Sopenharmony_ci	eloop_cancel_timeout(ieee80211_tkip_countermeasures_stop, hapd, NULL);
66e5b75505Sopenharmony_ci}
67e5b75505Sopenharmony_ci
68e5b75505Sopenharmony_ci
69e5b75505Sopenharmony_ciint michael_mic_failure(struct hostapd_data *hapd, const u8 *addr, int local)
70e5b75505Sopenharmony_ci{
71e5b75505Sopenharmony_ci	struct os_reltime now;
72e5b75505Sopenharmony_ci	int ret = 0;
73e5b75505Sopenharmony_ci
74e5b75505Sopenharmony_ci	hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211,
75e5b75505Sopenharmony_ci		       HOSTAPD_LEVEL_INFO,
76e5b75505Sopenharmony_ci		       "Michael MIC failure detected in received frame%s",
77e5b75505Sopenharmony_ci		       local ? " (local)" : "");
78e5b75505Sopenharmony_ci
79e5b75505Sopenharmony_ci	if (addr && local) {
80e5b75505Sopenharmony_ci		struct sta_info *sta = ap_get_sta(hapd, addr);
81e5b75505Sopenharmony_ci		if (sta != NULL) {
82e5b75505Sopenharmony_ci			wpa_auth_sta_local_mic_failure_report(sta->wpa_sm);
83e5b75505Sopenharmony_ci			hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211,
84e5b75505Sopenharmony_ci				       HOSTAPD_LEVEL_INFO,
85e5b75505Sopenharmony_ci				       "Michael MIC failure detected in "
86e5b75505Sopenharmony_ci				       "received frame");
87e5b75505Sopenharmony_ci			mlme_michaelmicfailure_indication(hapd, addr);
88e5b75505Sopenharmony_ci		} else {
89e5b75505Sopenharmony_ci			wpa_printf(MSG_DEBUG,
90e5b75505Sopenharmony_ci				   "MLME-MICHAELMICFAILURE.indication "
91e5b75505Sopenharmony_ci				   "for not associated STA (" MACSTR
92e5b75505Sopenharmony_ci				   ") ignored", MAC2STR(addr));
93e5b75505Sopenharmony_ci			return ret;
94e5b75505Sopenharmony_ci		}
95e5b75505Sopenharmony_ci	}
96e5b75505Sopenharmony_ci
97e5b75505Sopenharmony_ci	os_get_reltime(&now);
98e5b75505Sopenharmony_ci	if (os_reltime_expired(&now, &hapd->michael_mic_failure, 60)) {
99e5b75505Sopenharmony_ci		hapd->michael_mic_failures = 1;
100e5b75505Sopenharmony_ci	} else {
101e5b75505Sopenharmony_ci		hapd->michael_mic_failures++;
102e5b75505Sopenharmony_ci		if (hapd->michael_mic_failures > 1) {
103e5b75505Sopenharmony_ci			ieee80211_tkip_countermeasures_start(hapd);
104e5b75505Sopenharmony_ci			ret = 1;
105e5b75505Sopenharmony_ci		}
106e5b75505Sopenharmony_ci	}
107e5b75505Sopenharmony_ci	hapd->michael_mic_failure = now;
108e5b75505Sopenharmony_ci
109e5b75505Sopenharmony_ci	return ret;
110e5b75505Sopenharmony_ci}
111