Annotation of /trunk/wpa_supplicant/patches/0001-hostapd-Avoid-key-reinstallation-in-FT-handshake.patch
Parent Directory | Revision Log
Revision 2999 -
(hide annotations)
(download)
Tue Oct 17 10:55:21 2017 UTC (6 years, 11 months ago) by niro
File size: 6218 byte(s)
Tue Oct 17 10:55:21 2017 UTC (6 years, 11 months ago) by niro
File size: 6218 byte(s)
-krackattack patches
1 | niro | 2999 | From cf4cab804c7afd5c45505528a8d16e46163243a2 Mon Sep 17 00:00:00 2001 |
2 | From: Mathy Vanhoef <Mathy.Vanhoef@cs.kuleuven.be> | ||
3 | Date: Fri, 14 Jul 2017 15:15:35 +0200 | ||
4 | Subject: [PATCH 1/8] hostapd: Avoid key reinstallation in FT handshake | ||
5 | |||
6 | Do not reinstall TK to the driver during Reassociation Response frame | ||
7 | processing if the first attempt of setting the TK succeeded. This avoids | ||
8 | issues related to clearing the TX/RX PN that could result in reusing | ||
9 | same PN values for transmitted frames (e.g., due to CCM nonce reuse and | ||
10 | also hitting replay protection on the receiver) and accepting replayed | ||
11 | frames on RX side. | ||
12 | |||
13 | This issue was introduced by the commit | ||
14 | 0e84c25434e6a1f283c7b4e62e483729085b78d2 ('FT: Fix PTK configuration in | ||
15 | authenticator') which allowed wpa_ft_install_ptk() to be called multiple | ||
16 | times with the same PTK. While the second configuration attempt is | ||
17 | needed with some drivers, it must be done only if the first attempt | ||
18 | failed. | ||
19 | |||
20 | Signed-off-by: Mathy Vanhoef <Mathy.Vanhoef@cs.kuleuven.be> | ||
21 | --- | ||
22 | src/ap/ieee802_11.c | 16 +++++++++++++--- | ||
23 | src/ap/wpa_auth.c | 11 +++++++++++ | ||
24 | src/ap/wpa_auth.h | 3 ++- | ||
25 | src/ap/wpa_auth_ft.c | 10 ++++++++++ | ||
26 | src/ap/wpa_auth_i.h | 1 + | ||
27 | 5 files changed, 37 insertions(+), 4 deletions(-) | ||
28 | |||
29 | diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c | ||
30 | index 4e04169..333035f 100644 | ||
31 | --- a/src/ap/ieee802_11.c | ||
32 | +++ b/src/ap/ieee802_11.c | ||
33 | @@ -1841,6 +1841,7 @@ static int add_associated_sta(struct hostapd_data *hapd, | ||
34 | { | ||
35 | struct ieee80211_ht_capabilities ht_cap; | ||
36 | struct ieee80211_vht_capabilities vht_cap; | ||
37 | + int set = 1; | ||
38 | |||
39 | /* | ||
40 | * Remove the STA entry to ensure the STA PS state gets cleared and | ||
41 | @@ -1848,9 +1849,18 @@ static int add_associated_sta(struct hostapd_data *hapd, | ||
42 | * FT-over-the-DS, where a station re-associates back to the same AP but | ||
43 | * skips the authentication flow, or if working with a driver that | ||
44 | * does not support full AP client state. | ||
45 | + * | ||
46 | + * Skip this if the STA has already completed FT reassociation and the | ||
47 | + * TK has been configured since the TX/RX PN must not be reset to 0 for | ||
48 | + * the same key. | ||
49 | */ | ||
50 | - if (!sta->added_unassoc) | ||
51 | + if (!sta->added_unassoc && | ||
52 | + (!(sta->flags & WLAN_STA_AUTHORIZED) || | ||
53 | + !wpa_auth_sta_ft_tk_already_set(sta->wpa_sm))) { | ||
54 | hostapd_drv_sta_remove(hapd, sta->addr); | ||
55 | + wpa_auth_sm_event(sta->wpa_sm, WPA_DRV_STA_REMOVED); | ||
56 | + set = 0; | ||
57 | + } | ||
58 | |||
59 | #ifdef CONFIG_IEEE80211N | ||
60 | if (sta->flags & WLAN_STA_HT) | ||
61 | @@ -1873,11 +1883,11 @@ static int add_associated_sta(struct hostapd_data *hapd, | ||
62 | sta->flags & WLAN_STA_VHT ? &vht_cap : NULL, | ||
63 | sta->flags | WLAN_STA_ASSOC, sta->qosinfo, | ||
64 | sta->vht_opmode, sta->p2p_ie ? 1 : 0, | ||
65 | - sta->added_unassoc)) { | ||
66 | + set)) { | ||
67 | hostapd_logger(hapd, sta->addr, | ||
68 | HOSTAPD_MODULE_IEEE80211, HOSTAPD_LEVEL_NOTICE, | ||
69 | "Could not %s STA to kernel driver", | ||
70 | - sta->added_unassoc ? "set" : "add"); | ||
71 | + set ? "set" : "add"); | ||
72 | |||
73 | if (sta->added_unassoc) { | ||
74 | hostapd_drv_sta_remove(hapd, sta->addr); | ||
75 | diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c | ||
76 | index 3587086..707971d 100644 | ||
77 | --- a/src/ap/wpa_auth.c | ||
78 | +++ b/src/ap/wpa_auth.c | ||
79 | @@ -1745,6 +1745,9 @@ int wpa_auth_sm_event(struct wpa_state_machine *sm, enum wpa_event event) | ||
80 | #else /* CONFIG_IEEE80211R */ | ||
81 | break; | ||
82 | #endif /* CONFIG_IEEE80211R */ | ||
83 | + case WPA_DRV_STA_REMOVED: | ||
84 | + sm->tk_already_set = FALSE; | ||
85 | + return 0; | ||
86 | } | ||
87 | |||
88 | #ifdef CONFIG_IEEE80211R | ||
89 | @@ -3250,6 +3253,14 @@ int wpa_auth_sta_wpa_version(struct wpa_state_machine *sm) | ||
90 | } | ||
91 | |||
92 | |||
93 | +int wpa_auth_sta_ft_tk_already_set(struct wpa_state_machine *sm) | ||
94 | +{ | ||
95 | + if (!sm || !wpa_key_mgmt_ft(sm->wpa_key_mgmt)) | ||
96 | + return 0; | ||
97 | + return sm->tk_already_set; | ||
98 | +} | ||
99 | + | ||
100 | + | ||
101 | int wpa_auth_sta_clear_pmksa(struct wpa_state_machine *sm, | ||
102 | struct rsn_pmksa_cache_entry *entry) | ||
103 | { | ||
104 | diff --git a/src/ap/wpa_auth.h b/src/ap/wpa_auth.h | ||
105 | index 0de8d97..97461b0 100644 | ||
106 | --- a/src/ap/wpa_auth.h | ||
107 | +++ b/src/ap/wpa_auth.h | ||
108 | @@ -267,7 +267,7 @@ void wpa_receive(struct wpa_authenticator *wpa_auth, | ||
109 | u8 *data, size_t data_len); | ||
110 | enum wpa_event { | ||
111 | WPA_AUTH, WPA_ASSOC, WPA_DISASSOC, WPA_DEAUTH, WPA_REAUTH, | ||
112 | - WPA_REAUTH_EAPOL, WPA_ASSOC_FT | ||
113 | + WPA_REAUTH_EAPOL, WPA_ASSOC_FT, WPA_DRV_STA_REMOVED | ||
114 | }; | ||
115 | void wpa_remove_ptk(struct wpa_state_machine *sm); | ||
116 | int wpa_auth_sm_event(struct wpa_state_machine *sm, enum wpa_event event); | ||
117 | @@ -280,6 +280,7 @@ int wpa_auth_pairwise_set(struct wpa_state_machine *sm); | ||
118 | int wpa_auth_get_pairwise(struct wpa_state_machine *sm); | ||
119 | int wpa_auth_sta_key_mgmt(struct wpa_state_machine *sm); | ||
120 | int wpa_auth_sta_wpa_version(struct wpa_state_machine *sm); | ||
121 | +int wpa_auth_sta_ft_tk_already_set(struct wpa_state_machine *sm); | ||
122 | int wpa_auth_sta_clear_pmksa(struct wpa_state_machine *sm, | ||
123 | struct rsn_pmksa_cache_entry *entry); | ||
124 | struct rsn_pmksa_cache_entry * | ||
125 | diff --git a/src/ap/wpa_auth_ft.c b/src/ap/wpa_auth_ft.c | ||
126 | index 42242a5..e63b99a 100644 | ||
127 | --- a/src/ap/wpa_auth_ft.c | ||
128 | +++ b/src/ap/wpa_auth_ft.c | ||
129 | @@ -780,6 +780,14 @@ void wpa_ft_install_ptk(struct wpa_state_machine *sm) | ||
130 | return; | ||
131 | } | ||
132 | |||
133 | + if (sm->tk_already_set) { | ||
134 | + /* Must avoid TK reconfiguration to prevent clearing of TX/RX | ||
135 | + * PN in the driver */ | ||
136 | + wpa_printf(MSG_DEBUG, | ||
137 | + "FT: Do not re-install same PTK to the driver"); | ||
138 | + return; | ||
139 | + } | ||
140 | + | ||
141 | /* FIX: add STA entry to kernel/driver here? The set_key will fail | ||
142 | * most likely without this.. At the moment, STA entry is added only | ||
143 | * after association has been completed. This function will be called | ||
144 | @@ -792,6 +800,7 @@ void wpa_ft_install_ptk(struct wpa_state_machine *sm) | ||
145 | |||
146 | /* FIX: MLME-SetProtection.Request(TA, Tx_Rx) */ | ||
147 | sm->pairwise_set = TRUE; | ||
148 | + sm->tk_already_set = TRUE; | ||
149 | } | ||
150 | |||
151 | |||
152 | @@ -898,6 +907,7 @@ static int wpa_ft_process_auth_req(struct wpa_state_machine *sm, | ||
153 | |||
154 | sm->pairwise = pairwise; | ||
155 | sm->PTK_valid = TRUE; | ||
156 | + sm->tk_already_set = FALSE; | ||
157 | wpa_ft_install_ptk(sm); | ||
158 | |||
159 | buflen = 2 + sizeof(struct rsn_mdie) + 2 + sizeof(struct rsn_ftie) + | ||
160 | diff --git a/src/ap/wpa_auth_i.h b/src/ap/wpa_auth_i.h | ||
161 | index 72b7eb3..7fd8f05 100644 | ||
162 | --- a/src/ap/wpa_auth_i.h | ||
163 | +++ b/src/ap/wpa_auth_i.h | ||
164 | @@ -65,6 +65,7 @@ struct wpa_state_machine { | ||
165 | struct wpa_ptk PTK; | ||
166 | Boolean PTK_valid; | ||
167 | Boolean pairwise_set; | ||
168 | + Boolean tk_already_set; | ||
169 | int keycount; | ||
170 | Boolean Pair; | ||
171 | struct wpa_key_replay_counter { | ||
172 | -- | ||
173 | 2.7.4 | ||
174 |