Merge ~morphis/snappy-hwe-snaps/+git/wifi-ap:hostapd-2.6-krack-fixes into ~snappy-hwe-team/snappy-hwe-snaps/+git/wifi-ap:hostapd/2.6

Proposed by Simon Fels
Status: Merged
Approved by: Alfonso Sanchez-Beato
Approved revision: 71a9967679a174551b38312a41b7bf448a1cdbc2
Merged at revision: 0125bab503042e0f984c9dc961837fa0bc58bb3a
Proposed branch: ~morphis/snappy-hwe-snaps/+git/wifi-ap:hostapd-2.6-krack-fixes
Merge into: ~snappy-hwe-team/snappy-hwe-snaps/+git/wifi-ap:hostapd/2.6
Diff against target: 659 lines (+225/-61)
10 files modified
src/ap/ieee802_11.c (+13/-3)
src/ap/wpa_auth.c (+32/-3)
src/ap/wpa_auth.h (+2/-1)
src/ap/wpa_auth_ft.c (+10/-0)
src/ap/wpa_auth_i.h (+1/-0)
src/common/wpa_common.h (+12/-0)
src/rsn_supp/tdls.c (+36/-2)
src/rsn_supp/wpa.c (+104/-51)
src/rsn_supp/wpa_ft.c (+8/-0)
src/rsn_supp/wpa_i.h (+7/-1)
Reviewer Review Type Date Requested Status
System Enablement Bot continuous-integration Approve
Roberto Mier Escandon (community) Approve
Oliver Grawert Approve
Alfonso Sanchez-Beato Approve
Review via email: mp+332311@code.launchpad.net

Description of the change

Apply CVE fixes for Krack attack

See https://w1.fi/security/2017-1/wpa-packet-number-reuse-with-replayed-messages.txt for details on the different CVEs this fixes.

All patches are taken from upstream except rebased-v2.6-0007-WNM-Ignore-WNM-Sleep-Mode-Response-without-pending-r.patch as it only applies for wpa-supplicant which we don't ship in our tree here.

To post a comment you must log in.
Revision history for this message
Alfonso Sanchez-Beato (alfonsosanchezbeato) wrote :

LGTM

review: Approve
Revision history for this message
Oliver Grawert (ogra) wrote :

looks fine

review: Approve
Revision history for this message
Roberto Mier Escandon (rmescandon) wrote :

lgtm, but I would like more people to take a look, just in case

review: Approve
Revision history for this message
System Enablement Bot (system-enablement-ci-bot) wrote :
review: Approve (continuous-integration)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c
2index 4e04169..333035f 100644
3--- a/src/ap/ieee802_11.c
4+++ b/src/ap/ieee802_11.c
5@@ -1841,6 +1841,7 @@ static int add_associated_sta(struct hostapd_data *hapd,
6 {
7 struct ieee80211_ht_capabilities ht_cap;
8 struct ieee80211_vht_capabilities vht_cap;
9+ int set = 1;
10
11 /*
12 * Remove the STA entry to ensure the STA PS state gets cleared and
13@@ -1848,9 +1849,18 @@ static int add_associated_sta(struct hostapd_data *hapd,
14 * FT-over-the-DS, where a station re-associates back to the same AP but
15 * skips the authentication flow, or if working with a driver that
16 * does not support full AP client state.
17+ *
18+ * Skip this if the STA has already completed FT reassociation and the
19+ * TK has been configured since the TX/RX PN must not be reset to 0 for
20+ * the same key.
21 */
22- if (!sta->added_unassoc)
23+ if (!sta->added_unassoc &&
24+ (!(sta->flags & WLAN_STA_AUTHORIZED) ||
25+ !wpa_auth_sta_ft_tk_already_set(sta->wpa_sm))) {
26 hostapd_drv_sta_remove(hapd, sta->addr);
27+ wpa_auth_sm_event(sta->wpa_sm, WPA_DRV_STA_REMOVED);
28+ set = 0;
29+ }
30
31 #ifdef CONFIG_IEEE80211N
32 if (sta->flags & WLAN_STA_HT)
33@@ -1873,11 +1883,11 @@ static int add_associated_sta(struct hostapd_data *hapd,
34 sta->flags & WLAN_STA_VHT ? &vht_cap : NULL,
35 sta->flags | WLAN_STA_ASSOC, sta->qosinfo,
36 sta->vht_opmode, sta->p2p_ie ? 1 : 0,
37- sta->added_unassoc)) {
38+ set)) {
39 hostapd_logger(hapd, sta->addr,
40 HOSTAPD_MODULE_IEEE80211, HOSTAPD_LEVEL_NOTICE,
41 "Could not %s STA to kernel driver",
42- sta->added_unassoc ? "set" : "add");
43+ set ? "set" : "add");
44
45 if (sta->added_unassoc) {
46 hostapd_drv_sta_remove(hapd, sta->addr);
47diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c
48index 3587086..bf10cc1 100644
49--- a/src/ap/wpa_auth.c
50+++ b/src/ap/wpa_auth.c
51@@ -1745,6 +1745,9 @@ int wpa_auth_sm_event(struct wpa_state_machine *sm, enum wpa_event event)
52 #else /* CONFIG_IEEE80211R */
53 break;
54 #endif /* CONFIG_IEEE80211R */
55+ case WPA_DRV_STA_REMOVED:
56+ sm->tk_already_set = FALSE;
57+ return 0;
58 }
59
60 #ifdef CONFIG_IEEE80211R
61@@ -1898,6 +1901,21 @@ SM_STATE(WPA_PTK, AUTHENTICATION2)
62 }
63
64
65+static int wpa_auth_sm_ptk_update(struct wpa_state_machine *sm)
66+{
67+ if (random_get_bytes(sm->ANonce, WPA_NONCE_LEN)) {
68+ wpa_printf(MSG_ERROR,
69+ "WPA: Failed to get random data for ANonce");
70+ sm->Disconnect = TRUE;
71+ return -1;
72+ }
73+ wpa_hexdump(MSG_DEBUG, "WPA: Assign new ANonce", sm->ANonce,
74+ WPA_NONCE_LEN);
75+ sm->TimeoutCtr = 0;
76+ return 0;
77+}
78+
79+
80 SM_STATE(WPA_PTK, INITPMK)
81 {
82 u8 msk[2 * PMK_LEN];
83@@ -2455,9 +2473,12 @@ SM_STEP(WPA_PTK)
84 SM_ENTER(WPA_PTK, AUTHENTICATION);
85 else if (sm->ReAuthenticationRequest)
86 SM_ENTER(WPA_PTK, AUTHENTICATION2);
87- else if (sm->PTKRequest)
88- SM_ENTER(WPA_PTK, PTKSTART);
89- else switch (sm->wpa_ptk_state) {
90+ else if (sm->PTKRequest) {
91+ if (wpa_auth_sm_ptk_update(sm) < 0)
92+ SM_ENTER(WPA_PTK, DISCONNECTED);
93+ else
94+ SM_ENTER(WPA_PTK, PTKSTART);
95+ } else switch (sm->wpa_ptk_state) {
96 case WPA_PTK_INITIALIZE:
97 break;
98 case WPA_PTK_DISCONNECT:
99@@ -3250,6 +3271,14 @@ int wpa_auth_sta_wpa_version(struct wpa_state_machine *sm)
100 }
101
102
103+int wpa_auth_sta_ft_tk_already_set(struct wpa_state_machine *sm)
104+{
105+ if (!sm || !wpa_key_mgmt_ft(sm->wpa_key_mgmt))
106+ return 0;
107+ return sm->tk_already_set;
108+}
109+
110+
111 int wpa_auth_sta_clear_pmksa(struct wpa_state_machine *sm,
112 struct rsn_pmksa_cache_entry *entry)
113 {
114diff --git a/src/ap/wpa_auth.h b/src/ap/wpa_auth.h
115index 0de8d97..97461b0 100644
116--- a/src/ap/wpa_auth.h
117+++ b/src/ap/wpa_auth.h
118@@ -267,7 +267,7 @@ void wpa_receive(struct wpa_authenticator *wpa_auth,
119 u8 *data, size_t data_len);
120 enum wpa_event {
121 WPA_AUTH, WPA_ASSOC, WPA_DISASSOC, WPA_DEAUTH, WPA_REAUTH,
122- WPA_REAUTH_EAPOL, WPA_ASSOC_FT
123+ WPA_REAUTH_EAPOL, WPA_ASSOC_FT, WPA_DRV_STA_REMOVED
124 };
125 void wpa_remove_ptk(struct wpa_state_machine *sm);
126 int wpa_auth_sm_event(struct wpa_state_machine *sm, enum wpa_event event);
127@@ -280,6 +280,7 @@ int wpa_auth_pairwise_set(struct wpa_state_machine *sm);
128 int wpa_auth_get_pairwise(struct wpa_state_machine *sm);
129 int wpa_auth_sta_key_mgmt(struct wpa_state_machine *sm);
130 int wpa_auth_sta_wpa_version(struct wpa_state_machine *sm);
131+int wpa_auth_sta_ft_tk_already_set(struct wpa_state_machine *sm);
132 int wpa_auth_sta_clear_pmksa(struct wpa_state_machine *sm,
133 struct rsn_pmksa_cache_entry *entry);
134 struct rsn_pmksa_cache_entry *
135diff --git a/src/ap/wpa_auth_ft.c b/src/ap/wpa_auth_ft.c
136index 42242a5..e63b99a 100644
137--- a/src/ap/wpa_auth_ft.c
138+++ b/src/ap/wpa_auth_ft.c
139@@ -780,6 +780,14 @@ void wpa_ft_install_ptk(struct wpa_state_machine *sm)
140 return;
141 }
142
143+ if (sm->tk_already_set) {
144+ /* Must avoid TK reconfiguration to prevent clearing of TX/RX
145+ * PN in the driver */
146+ wpa_printf(MSG_DEBUG,
147+ "FT: Do not re-install same PTK to the driver");
148+ return;
149+ }
150+
151 /* FIX: add STA entry to kernel/driver here? The set_key will fail
152 * most likely without this.. At the moment, STA entry is added only
153 * after association has been completed. This function will be called
154@@ -792,6 +800,7 @@ void wpa_ft_install_ptk(struct wpa_state_machine *sm)
155
156 /* FIX: MLME-SetProtection.Request(TA, Tx_Rx) */
157 sm->pairwise_set = TRUE;
158+ sm->tk_already_set = TRUE;
159 }
160
161
162@@ -898,6 +907,7 @@ static int wpa_ft_process_auth_req(struct wpa_state_machine *sm,
163
164 sm->pairwise = pairwise;
165 sm->PTK_valid = TRUE;
166+ sm->tk_already_set = FALSE;
167 wpa_ft_install_ptk(sm);
168
169 buflen = 2 + sizeof(struct rsn_mdie) + 2 + sizeof(struct rsn_ftie) +
170diff --git a/src/ap/wpa_auth_i.h b/src/ap/wpa_auth_i.h
171index 72b7eb3..7fd8f05 100644
172--- a/src/ap/wpa_auth_i.h
173+++ b/src/ap/wpa_auth_i.h
174@@ -65,6 +65,7 @@ struct wpa_state_machine {
175 struct wpa_ptk PTK;
176 Boolean PTK_valid;
177 Boolean pairwise_set;
178+ Boolean tk_already_set;
179 int keycount;
180 Boolean Pair;
181 struct wpa_key_replay_counter {
182diff --git a/src/common/wpa_common.h b/src/common/wpa_common.h
183index af1d0f0..1021ccb 100644
184--- a/src/common/wpa_common.h
185+++ b/src/common/wpa_common.h
186@@ -215,8 +215,20 @@ struct wpa_ptk {
187 size_t kck_len;
188 size_t kek_len;
189 size_t tk_len;
190+ int installed; /* 1 if key has already been installed to driver */
191 };
192
193+struct wpa_gtk {
194+ u8 gtk[WPA_GTK_MAX_LEN];
195+ size_t gtk_len;
196+};
197+
198+#ifdef CONFIG_IEEE80211W
199+struct wpa_igtk {
200+ u8 igtk[WPA_IGTK_MAX_LEN];
201+ size_t igtk_len;
202+};
203+#endif /* CONFIG_IEEE80211W */
204
205 /* WPA IE version 1
206 * 00-50-f2:1 (OUI:OUI type)
207diff --git a/src/rsn_supp/tdls.c b/src/rsn_supp/tdls.c
208index e424168..9eb9738 100644
209--- a/src/rsn_supp/tdls.c
210+++ b/src/rsn_supp/tdls.c
211@@ -112,6 +112,7 @@ struct wpa_tdls_peer {
212 u8 tk[16]; /* TPK-TK; assuming only CCMP will be used */
213 } tpk;
214 int tpk_set;
215+ int tk_set; /* TPK-TK configured to the driver */
216 int tpk_success;
217 int tpk_in_progress;
218
219@@ -192,6 +193,20 @@ static int wpa_tdls_set_key(struct wpa_sm *sm, struct wpa_tdls_peer *peer)
220 u8 rsc[6];
221 enum wpa_alg alg;
222
223+ if (peer->tk_set) {
224+ /*
225+ * This same TPK-TK has already been configured to the driver
226+ * and this new configuration attempt (likely due to an
227+ * unexpected retransmitted frame) would result in clearing
228+ * the TX/RX sequence number which can break security, so must
229+ * not allow that to happen.
230+ */
231+ wpa_printf(MSG_INFO, "TDLS: TPK-TK for the peer " MACSTR
232+ " has already been configured to the driver - do not reconfigure",
233+ MAC2STR(peer->addr));
234+ return -1;
235+ }
236+
237 os_memset(rsc, 0, 6);
238
239 switch (peer->cipher) {
240@@ -209,12 +224,15 @@ static int wpa_tdls_set_key(struct wpa_sm *sm, struct wpa_tdls_peer *peer)
241 return -1;
242 }
243
244+ wpa_printf(MSG_DEBUG, "TDLS: Configure pairwise key for peer " MACSTR,
245+ MAC2STR(peer->addr));
246 if (wpa_sm_set_key(sm, alg, peer->addr, -1, 1,
247 rsc, sizeof(rsc), peer->tpk.tk, key_len) < 0) {
248 wpa_printf(MSG_WARNING, "TDLS: Failed to set TPK to the "
249 "driver");
250 return -1;
251 }
252+ peer->tk_set = 1;
253 return 0;
254 }
255
256@@ -696,7 +714,7 @@ static void wpa_tdls_peer_clear(struct wpa_sm *sm, struct wpa_tdls_peer *peer)
257 peer->cipher = 0;
258 peer->qos_info = 0;
259 peer->wmm_capable = 0;
260- peer->tpk_set = peer->tpk_success = 0;
261+ peer->tk_set = peer->tpk_set = peer->tpk_success = 0;
262 peer->chan_switch_enabled = 0;
263 os_memset(&peer->tpk, 0, sizeof(peer->tpk));
264 os_memset(peer->inonce, 0, WPA_NONCE_LEN);
265@@ -1159,6 +1177,7 @@ skip_rsnie:
266 wpa_tdls_peer_free(sm, peer);
267 return -1;
268 }
269+ peer->tk_set = 0; /* A new nonce results in a new TK */
270 wpa_hexdump(MSG_DEBUG, "TDLS: Initiator Nonce for TPK handshake",
271 peer->inonce, WPA_NONCE_LEN);
272 os_memcpy(ftie->Snonce, peer->inonce, WPA_NONCE_LEN);
273@@ -1751,6 +1770,19 @@ static int wpa_tdls_addset_peer(struct wpa_sm *sm, struct wpa_tdls_peer *peer,
274 }
275
276
277+static int tdls_nonce_set(const u8 *nonce)
278+{
279+ int i;
280+
281+ for (i = 0; i < WPA_NONCE_LEN; i++) {
282+ if (nonce[i])
283+ return 1;
284+ }
285+
286+ return 0;
287+}
288+
289+
290 static int wpa_tdls_process_tpk_m1(struct wpa_sm *sm, const u8 *src_addr,
291 const u8 *buf, size_t len)
292 {
293@@ -2004,7 +2036,8 @@ skip_rsn:
294 peer->rsnie_i_len = kde.rsn_ie_len;
295 peer->cipher = cipher;
296
297- if (os_memcmp(peer->inonce, ftie->Snonce, WPA_NONCE_LEN) != 0) {
298+ if (os_memcmp(peer->inonce, ftie->Snonce, WPA_NONCE_LEN) != 0 ||
299+ !tdls_nonce_set(peer->inonce)) {
300 /*
301 * There is no point in updating the RNonce for every obtained
302 * TPK M1 frame (e.g., retransmission due to timeout) with the
303@@ -2020,6 +2053,7 @@ skip_rsn:
304 "TDLS: Failed to get random data for responder nonce");
305 goto error;
306 }
307+ peer->tk_set = 0; /* A new nonce results in a new TK */
308 }
309
310 #if 0
311diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c
312index 3c47879..2a53c6f 100644
313--- a/src/rsn_supp/wpa.c
314+++ b/src/rsn_supp/wpa.c
315@@ -510,7 +510,6 @@ static void wpa_supplicant_process_1_of_4(struct wpa_sm *sm,
316 os_memset(buf, 0, sizeof(buf));
317 }
318 sm->tptk_set = 1;
319- sm->tk_to_set = 1;
320
321 kde = sm->assoc_wpa_ie;
322 kde_len = sm->assoc_wpa_ie_len;
323@@ -615,7 +614,7 @@ static int wpa_supplicant_install_ptk(struct wpa_sm *sm,
324 enum wpa_alg alg;
325 const u8 *key_rsc;
326
327- if (!sm->tk_to_set) {
328+ if (sm->ptk.installed) {
329 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
330 "WPA: Do not re-install same PTK to the driver");
331 return 0;
332@@ -659,7 +658,7 @@ static int wpa_supplicant_install_ptk(struct wpa_sm *sm,
333
334 /* TK is not needed anymore in supplicant */
335 os_memset(sm->ptk.tk, 0, WPA_TK_MAX_LEN);
336- sm->tk_to_set = 0;
337+ sm->ptk.installed = 1;
338
339 if (sm->wpa_ptk_rekey) {
340 eloop_cancel_timeout(wpa_sm_rekey_ptk, sm, NULL);
341@@ -709,11 +708,23 @@ struct wpa_gtk_data {
342
343 static int wpa_supplicant_install_gtk(struct wpa_sm *sm,
344 const struct wpa_gtk_data *gd,
345- const u8 *key_rsc)
346+ const u8 *key_rsc, int wnm_sleep)
347 {
348 const u8 *_gtk = gd->gtk;
349 u8 gtk_buf[32];
350
351+ /* Detect possible key reinstallation */
352+ if ((sm->gtk.gtk_len == (size_t) gd->gtk_len &&
353+ os_memcmp(sm->gtk.gtk, gd->gtk, sm->gtk.gtk_len) == 0) ||
354+ (sm->gtk_wnm_sleep.gtk_len == (size_t) gd->gtk_len &&
355+ os_memcmp(sm->gtk_wnm_sleep.gtk, gd->gtk,
356+ sm->gtk_wnm_sleep.gtk_len) == 0)) {
357+ wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
358+ "WPA: Not reinstalling already in-use GTK to the driver (keyidx=%d tx=%d len=%d)",
359+ gd->keyidx, gd->tx, gd->gtk_len);
360+ return 0;
361+ }
362+
363 wpa_hexdump_key(MSG_DEBUG, "WPA: Group Key", gd->gtk, gd->gtk_len);
364 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
365 "WPA: Installing GTK to the driver (keyidx=%d tx=%d len=%d)",
366@@ -748,6 +759,15 @@ static int wpa_supplicant_install_gtk(struct wpa_sm *sm,
367 }
368 os_memset(gtk_buf, 0, sizeof(gtk_buf));
369
370+ if (wnm_sleep) {
371+ sm->gtk_wnm_sleep.gtk_len = gd->gtk_len;
372+ os_memcpy(sm->gtk_wnm_sleep.gtk, gd->gtk,
373+ sm->gtk_wnm_sleep.gtk_len);
374+ } else {
375+ sm->gtk.gtk_len = gd->gtk_len;
376+ os_memcpy(sm->gtk.gtk, gd->gtk, sm->gtk.gtk_len);
377+ }
378+
379 return 0;
380 }
381
382@@ -840,7 +860,7 @@ static int wpa_supplicant_pairwise_gtk(struct wpa_sm *sm,
383 (wpa_supplicant_check_group_cipher(sm, sm->group_cipher,
384 gtk_len, gtk_len,
385 &gd.key_rsc_len, &gd.alg) ||
386- wpa_supplicant_install_gtk(sm, &gd, key_rsc))) {
387+ wpa_supplicant_install_gtk(sm, &gd, key_rsc, 0))) {
388 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
389 "RSN: Failed to install GTK");
390 os_memset(&gd, 0, sizeof(gd));
391@@ -854,6 +874,58 @@ static int wpa_supplicant_pairwise_gtk(struct wpa_sm *sm,
392 }
393
394
395+#ifdef CONFIG_IEEE80211W
396+static int wpa_supplicant_install_igtk(struct wpa_sm *sm,
397+ const struct wpa_igtk_kde *igtk,
398+ int wnm_sleep)
399+{
400+ size_t len = wpa_cipher_key_len(sm->mgmt_group_cipher);
401+ u16 keyidx = WPA_GET_LE16(igtk->keyid);
402+
403+ /* Detect possible key reinstallation */
404+ if ((sm->igtk.igtk_len == len &&
405+ os_memcmp(sm->igtk.igtk, igtk->igtk, sm->igtk.igtk_len) == 0) ||
406+ (sm->igtk_wnm_sleep.igtk_len == len &&
407+ os_memcmp(sm->igtk_wnm_sleep.igtk, igtk->igtk,
408+ sm->igtk_wnm_sleep.igtk_len) == 0)) {
409+ wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
410+ "WPA: Not reinstalling already in-use IGTK to the driver (keyidx=%d)",
411+ keyidx);
412+ return 0;
413+ }
414+
415+ wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
416+ "WPA: IGTK keyid %d pn %02x%02x%02x%02x%02x%02x",
417+ keyidx, MAC2STR(igtk->pn));
418+ wpa_hexdump_key(MSG_DEBUG, "WPA: IGTK", igtk->igtk, len);
419+ if (keyidx > 4095) {
420+ wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
421+ "WPA: Invalid IGTK KeyID %d", keyidx);
422+ return -1;
423+ }
424+ if (wpa_sm_set_key(sm, wpa_cipher_to_alg(sm->mgmt_group_cipher),
425+ broadcast_ether_addr,
426+ keyidx, 0, igtk->pn, sizeof(igtk->pn),
427+ igtk->igtk, len) < 0) {
428+ wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
429+ "WPA: Failed to configure IGTK to the driver");
430+ return -1;
431+ }
432+
433+ if (wnm_sleep) {
434+ sm->igtk_wnm_sleep.igtk_len = len;
435+ os_memcpy(sm->igtk_wnm_sleep.igtk, igtk->igtk,
436+ sm->igtk_wnm_sleep.igtk_len);
437+ } else {
438+ sm->igtk.igtk_len = len;
439+ os_memcpy(sm->igtk.igtk, igtk->igtk, sm->igtk.igtk_len);
440+ }
441+
442+ return 0;
443+}
444+#endif /* CONFIG_IEEE80211W */
445+
446+
447 static int ieee80211w_set_keys(struct wpa_sm *sm,
448 struct wpa_eapol_ie_parse *ie)
449 {
450@@ -864,30 +936,14 @@ static int ieee80211w_set_keys(struct wpa_sm *sm,
451 if (ie->igtk) {
452 size_t len;
453 const struct wpa_igtk_kde *igtk;
454- u16 keyidx;
455+
456 len = wpa_cipher_key_len(sm->mgmt_group_cipher);
457 if (ie->igtk_len != WPA_IGTK_KDE_PREFIX_LEN + len)
458 return -1;
459+
460 igtk = (const struct wpa_igtk_kde *) ie->igtk;
461- keyidx = WPA_GET_LE16(igtk->keyid);
462- wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: IGTK keyid %d "
463- "pn %02x%02x%02x%02x%02x%02x",
464- keyidx, MAC2STR(igtk->pn));
465- wpa_hexdump_key(MSG_DEBUG, "WPA: IGTK",
466- igtk->igtk, len);
467- if (keyidx > 4095) {
468- wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
469- "WPA: Invalid IGTK KeyID %d", keyidx);
470- return -1;
471- }
472- if (wpa_sm_set_key(sm, wpa_cipher_to_alg(sm->mgmt_group_cipher),
473- broadcast_ether_addr,
474- keyidx, 0, igtk->pn, sizeof(igtk->pn),
475- igtk->igtk, len) < 0) {
476- wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
477- "WPA: Failed to configure IGTK to the driver");
478+ if (wpa_supplicant_install_igtk(sm, igtk, 0) < 0)
479 return -1;
480- }
481 }
482
483 return 0;
484@@ -1536,7 +1592,7 @@ static void wpa_supplicant_process_1_of_2(struct wpa_sm *sm,
485 if (wpa_supplicant_rsc_relaxation(sm, key->key_rsc))
486 key_rsc = null_rsc;
487
488- if (wpa_supplicant_install_gtk(sm, &gd, key_rsc) ||
489+ if (wpa_supplicant_install_gtk(sm, &gd, key_rsc, 0) ||
490 wpa_supplicant_send_2_of_2(sm, key, ver, key_info) < 0)
491 goto failed;
492 os_memset(&gd, 0, sizeof(gd));
493@@ -2307,7 +2363,7 @@ void wpa_sm_deinit(struct wpa_sm *sm)
494 */
495 void wpa_sm_notify_assoc(struct wpa_sm *sm, const u8 *bssid)
496 {
497- int clear_ptk = 1;
498+ int clear_keys = 1;
499
500 if (sm == NULL)
501 return;
502@@ -2333,11 +2389,11 @@ void wpa_sm_notify_assoc(struct wpa_sm *sm, const u8 *bssid)
503 /* Prepare for the next transition */
504 wpa_ft_prepare_auth_request(sm, NULL);
505
506- clear_ptk = 0;
507+ clear_keys = 0;
508 }
509 #endif /* CONFIG_IEEE80211R */
510
511- if (clear_ptk) {
512+ if (clear_keys) {
513 /*
514 * IEEE 802.11, 8.4.10: Delete PTK SA on (re)association if
515 * this is not part of a Fast BSS Transition.
516@@ -2347,6 +2403,12 @@ void wpa_sm_notify_assoc(struct wpa_sm *sm, const u8 *bssid)
517 os_memset(&sm->ptk, 0, sizeof(sm->ptk));
518 sm->tptk_set = 0;
519 os_memset(&sm->tptk, 0, sizeof(sm->tptk));
520+ os_memset(&sm->gtk, 0, sizeof(sm->gtk));
521+ os_memset(&sm->gtk_wnm_sleep, 0, sizeof(sm->gtk_wnm_sleep));
522+#ifdef CONFIG_IEEE80211W
523+ os_memset(&sm->igtk, 0, sizeof(sm->igtk));
524+ os_memset(&sm->igtk_wnm_sleep, 0, sizeof(sm->igtk_wnm_sleep));
525+#endif /* CONFIG_IEEE80211W */
526 }
527
528 #ifdef CONFIG_TDLS
529@@ -2378,6 +2440,9 @@ void wpa_sm_notify_disassoc(struct wpa_sm *sm)
530 #ifdef CONFIG_TDLS
531 wpa_tdls_disassoc(sm);
532 #endif /* CONFIG_TDLS */
533+#ifdef CONFIG_IEEE80211R
534+ sm->ft_reassoc_completed = 0;
535+#endif /* CONFIG_IEEE80211R */
536
537 /* Keys are not needed in the WPA state machine anymore */
538 wpa_sm_drop_sa(sm);
539@@ -2877,6 +2942,12 @@ void wpa_sm_drop_sa(struct wpa_sm *sm)
540 os_memset(sm->pmk, 0, sizeof(sm->pmk));
541 os_memset(&sm->ptk, 0, sizeof(sm->ptk));
542 os_memset(&sm->tptk, 0, sizeof(sm->tptk));
543+ os_memset(&sm->gtk, 0, sizeof(sm->gtk));
544+ os_memset(&sm->gtk_wnm_sleep, 0, sizeof(sm->gtk_wnm_sleep));
545+#ifdef CONFIG_IEEE80211W
546+ os_memset(&sm->igtk, 0, sizeof(sm->igtk));
547+ os_memset(&sm->igtk_wnm_sleep, 0, sizeof(sm->igtk_wnm_sleep));
548+#endif /* CONFIG_IEEE80211W */
549 #ifdef CONFIG_IEEE80211R
550 os_memset(sm->xxkey, 0, sizeof(sm->xxkey));
551 os_memset(sm->pmk_r0, 0, sizeof(sm->pmk_r0));
552@@ -2940,7 +3011,7 @@ int wpa_wnmsleep_install_key(struct wpa_sm *sm, u8 subelem_id, u8 *buf)
553
554 wpa_hexdump_key(MSG_DEBUG, "Install GTK (WNM SLEEP)",
555 gd.gtk, gd.gtk_len);
556- if (wpa_supplicant_install_gtk(sm, &gd, key_rsc)) {
557+ if (wpa_supplicant_install_gtk(sm, &gd, key_rsc, 1)) {
558 os_memset(&gd, 0, sizeof(gd));
559 wpa_printf(MSG_DEBUG, "Failed to install the GTK in "
560 "WNM mode");
561@@ -2949,29 +3020,11 @@ int wpa_wnmsleep_install_key(struct wpa_sm *sm, u8 subelem_id, u8 *buf)
562 os_memset(&gd, 0, sizeof(gd));
563 #ifdef CONFIG_IEEE80211W
564 } else if (subelem_id == WNM_SLEEP_SUBELEM_IGTK) {
565- struct wpa_igtk_kde igd;
566- u16 keyidx;
567-
568- os_memset(&igd, 0, sizeof(igd));
569- keylen = wpa_cipher_key_len(sm->mgmt_group_cipher);
570- os_memcpy(igd.keyid, buf + 2, 2);
571- os_memcpy(igd.pn, buf + 4, 6);
572-
573- keyidx = WPA_GET_LE16(igd.keyid);
574- os_memcpy(igd.igtk, buf + 10, keylen);
575-
576- wpa_hexdump_key(MSG_DEBUG, "Install IGTK (WNM SLEEP)",
577- igd.igtk, keylen);
578- if (wpa_sm_set_key(sm, wpa_cipher_to_alg(sm->mgmt_group_cipher),
579- broadcast_ether_addr,
580- keyidx, 0, igd.pn, sizeof(igd.pn),
581- igd.igtk, keylen) < 0) {
582- wpa_printf(MSG_DEBUG, "Failed to install the IGTK in "
583- "WNM mode");
584- os_memset(&igd, 0, sizeof(igd));
585+ const struct wpa_igtk_kde *igtk;
586+
587+ igtk = (const struct wpa_igtk_kde *) (buf + 2);
588+ if (wpa_supplicant_install_igtk(sm, igtk, 1) < 0)
589 return -1;
590- }
591- os_memset(&igd, 0, sizeof(igd));
592 #endif /* CONFIG_IEEE80211W */
593 } else {
594 wpa_printf(MSG_DEBUG, "Unknown element id");
595diff --git a/src/rsn_supp/wpa_ft.c b/src/rsn_supp/wpa_ft.c
596index 205793e..d45bb45 100644
597--- a/src/rsn_supp/wpa_ft.c
598+++ b/src/rsn_supp/wpa_ft.c
599@@ -153,6 +153,7 @@ static u8 * wpa_ft_gen_req_ies(struct wpa_sm *sm, size_t *len,
600 u16 capab;
601
602 sm->ft_completed = 0;
603+ sm->ft_reassoc_completed = 0;
604
605 buf_len = 2 + sizeof(struct rsn_mdie) + 2 + sizeof(struct rsn_ftie) +
606 2 + sm->r0kh_id_len + ric_ies_len + 100;
607@@ -681,6 +682,11 @@ int wpa_ft_validate_reassoc_resp(struct wpa_sm *sm, const u8 *ies,
608 return -1;
609 }
610
611+ if (sm->ft_reassoc_completed) {
612+ wpa_printf(MSG_DEBUG, "FT: Reassociation has already been completed for this FT protocol instance - ignore unexpected retransmission");
613+ return 0;
614+ }
615+
616 if (wpa_ft_parse_ies(ies, ies_len, &parse) < 0) {
617 wpa_printf(MSG_DEBUG, "FT: Failed to parse IEs");
618 return -1;
619@@ -781,6 +787,8 @@ int wpa_ft_validate_reassoc_resp(struct wpa_sm *sm, const u8 *ies,
620 return -1;
621 }
622
623+ sm->ft_reassoc_completed = 1;
624+
625 if (wpa_ft_process_gtk_subelem(sm, parse.gtk, parse.gtk_len) < 0)
626 return -1;
627
628diff --git a/src/rsn_supp/wpa_i.h b/src/rsn_supp/wpa_i.h
629index f653ba6..56f88dc 100644
630--- a/src/rsn_supp/wpa_i.h
631+++ b/src/rsn_supp/wpa_i.h
632@@ -24,13 +24,18 @@ struct wpa_sm {
633 struct wpa_ptk ptk, tptk;
634 int ptk_set, tptk_set;
635 unsigned int msg_3_of_4_ok:1;
636- unsigned int tk_to_set:1;
637 u8 snonce[WPA_NONCE_LEN];
638 u8 anonce[WPA_NONCE_LEN]; /* ANonce from the last 1/4 msg */
639 int renew_snonce;
640 u8 rx_replay_counter[WPA_REPLAY_COUNTER_LEN];
641 int rx_replay_counter_set;
642 u8 request_counter[WPA_REPLAY_COUNTER_LEN];
643+ struct wpa_gtk gtk;
644+ struct wpa_gtk gtk_wnm_sleep;
645+#ifdef CONFIG_IEEE80211W
646+ struct wpa_igtk igtk;
647+ struct wpa_igtk igtk_wnm_sleep;
648+#endif /* CONFIG_IEEE80211W */
649
650 struct eapol_sm *eapol; /* EAPOL state machine from upper level code */
651
652@@ -123,6 +128,7 @@ struct wpa_sm {
653 size_t r0kh_id_len;
654 u8 r1kh_id[FT_R1KH_ID_LEN];
655 int ft_completed;
656+ int ft_reassoc_completed;
657 int over_the_ds_in_progress;
658 u8 target_ap[ETH_ALEN]; /* over-the-DS target AP */
659 int set_ptk_after_assoc;

Subscribers

People subscribed via source and target branches

to all changes: