key-replay-cve-multiple.patch 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943
  1. The WPA2 four-way handshake protocol is vulnerable to replay attacks which can
  2. result in unauthenticated clients gaining access to the network.
  3. Backport a number of patches from upstream to fix this.
  4. CVE: CVE-2017-13077
  5. CVE: CVE-2017-13078
  6. CVE: CVE-2017-13079
  7. CVE: CVE-2017-13080
  8. CVE: CVE-2017-13081
  9. CVE: CVE-2017-13082
  10. CVE: CVE-2017-13086
  11. CVE: CVE-2017-13087
  12. CVE: CVE-2017-13088
  13. Upstream-Status: Backport
  14. Signed-off-by: Ross Burton <ross.burton@intel.com>
  15. From 859e243137203d2389e20103a9947cf76082022e Mon Sep 17 00:00:00 2001
  16. From: Haiqing Bai <Haiqing.Bai@windriver.com>
  17. Date: Fri, 13 Oct 2017 09:37:06 +0800
  18. Subject: [PATCH 1/7] hostapd: Avoid key reinstallation in FT handshake
  19. Do not reinstall TK to the driver during Reassociation Response frame
  20. processing if the first attempt of setting the TK succeeded. This avoids
  21. issues related to clearing the TX/RX PN that could result in reusing
  22. same PN values for transmitted frames (e.g., due to CCM nonce reuse and
  23. also hitting replay protection on the receiver) and accepting replayed
  24. frames on RX side.
  25. This issue was introduced by the commit
  26. 0e84c25434e6a1f283c7b4e62e483729085b78d2 ('FT: Fix PTK configuration in
  27. authenticator') which allowed wpa_ft_install_ptk() to be called multiple
  28. times with the same PTK. While the second configuration attempt is
  29. needed with some drivers, it must be done only if the first attempt
  30. failed.
  31. Signed-off-by: Mathy Vanhoef <Mathy.Vanhoef@cs.kuleuven.be>
  32. Upstream-Status: Backport
  33. Signed-off-by: Haiqing Bai <Haiqing.Bai@windriver.com>
  34. ---
  35. src/ap/wpa_auth.c | 11 ++++++++++-
  36. src/ap/wpa_auth.h | 3 ++-
  37. src/ap/wpa_auth_ft.c | 10 ++++++++++
  38. src/ap/wpa_auth_i.h | 1 +
  39. 4 files changed, 23 insertions(+), 2 deletions(-)
  40. diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c
  41. index 9c5f609..0ebbdb5 100644
  42. --- a/src/ap/wpa_auth.c
  43. +++ b/src/ap/wpa_auth.c
  44. @@ -1715,6 +1715,9 @@ int wpa_auth_sm_event(struct wpa_state_machine *sm, wpa_event event)
  45. #else /* CONFIG_IEEE80211R */
  46. break;
  47. #endif /* CONFIG_IEEE80211R */
  48. + case WPA_DRV_STA_REMOVED:
  49. + sm->tk_already_set = FALSE;
  50. + return 0;
  51. }
  52. #ifdef CONFIG_IEEE80211R
  53. @@ -3168,7 +3171,13 @@ int wpa_auth_sta_wpa_version(struct wpa_state_machine *sm)
  54. return sm->wpa;
  55. }
  56. -
  57. +int wpa_auth_sta_ft_tk_already_set(struct wpa_state_machine *sm)
  58. +{
  59. + if (!sm || !wpa_key_mgmt_ft(sm->wpa_key_mgmt))
  60. + return 0;
  61. + return sm->tk_already_set;
  62. +}
  63. +
  64. int wpa_auth_sta_clear_pmksa(struct wpa_state_machine *sm,
  65. struct rsn_pmksa_cache_entry *entry)
  66. {
  67. diff --git a/src/ap/wpa_auth.h b/src/ap/wpa_auth.h
  68. index 2788e65..8dee180 100644
  69. --- a/src/ap/wpa_auth.h
  70. +++ b/src/ap/wpa_auth.h
  71. @@ -253,7 +253,7 @@ void wpa_receive(struct wpa_authenticator *wpa_auth,
  72. u8 *data, size_t data_len);
  73. typedef enum {
  74. WPA_AUTH, WPA_ASSOC, WPA_DISASSOC, WPA_DEAUTH, WPA_REAUTH,
  75. - WPA_REAUTH_EAPOL, WPA_ASSOC_FT
  76. + WPA_REAUTH_EAPOL, WPA_ASSOC_FT, WPA_DRV_STA_REMOVED
  77. } wpa_event;
  78. void wpa_remove_ptk(struct wpa_state_machine *sm);
  79. int wpa_auth_sm_event(struct wpa_state_machine *sm, wpa_event event);
  80. @@ -266,6 +266,7 @@ int wpa_auth_pairwise_set(struct wpa_state_machine *sm);
  81. int wpa_auth_get_pairwise(struct wpa_state_machine *sm);
  82. int wpa_auth_sta_key_mgmt(struct wpa_state_machine *sm);
  83. int wpa_auth_sta_wpa_version(struct wpa_state_machine *sm);
  84. +int wpa_auth_sta_ft_tk_already_set(struct wpa_state_machine *sm);
  85. int wpa_auth_sta_clear_pmksa(struct wpa_state_machine *sm,
  86. struct rsn_pmksa_cache_entry *entry);
  87. struct rsn_pmksa_cache_entry *
  88. diff --git a/src/ap/wpa_auth_ft.c b/src/ap/wpa_auth_ft.c
  89. index ef3249a..17e6039 100644
  90. --- a/src/ap/wpa_auth_ft.c
  91. +++ b/src/ap/wpa_auth_ft.c
  92. @@ -779,6 +779,14 @@ void wpa_ft_install_ptk(struct wpa_state_machine *sm)
  93. return;
  94. }
  95. + if (sm->tk_already_set) {
  96. + /* Must avoid TK reconfiguration to prevent clearing of TX/RX
  97. + * PN in the driver */
  98. + wpa_printf(MSG_DEBUG,
  99. + "FT: Do not re-install same PTK to the driver");
  100. + return;
  101. + }
  102. +
  103. /* FIX: add STA entry to kernel/driver here? The set_key will fail
  104. * most likely without this.. At the moment, STA entry is added only
  105. * after association has been completed. This function will be called
  106. @@ -791,6 +799,7 @@ void wpa_ft_install_ptk(struct wpa_state_machine *sm)
  107. /* FIX: MLME-SetProtection.Request(TA, Tx_Rx) */
  108. sm->pairwise_set = TRUE;
  109. + sm->tk_already_set = TRUE;
  110. }
  111. @@ -897,6 +906,7 @@ static int wpa_ft_process_auth_req(struct wpa_state_machine *sm,
  112. sm->pairwise = pairwise;
  113. sm->PTK_valid = TRUE;
  114. + sm->tk_already_set = FALSE;
  115. wpa_ft_install_ptk(sm);
  116. buflen = 2 + sizeof(struct rsn_mdie) + 2 + sizeof(struct rsn_ftie) +
  117. diff --git a/src/ap/wpa_auth_i.h b/src/ap/wpa_auth_i.h
  118. index 7b2cd3e..0f3d504 100644
  119. --- a/src/ap/wpa_auth_i.h
  120. +++ b/src/ap/wpa_auth_i.h
  121. @@ -64,6 +64,7 @@ struct wpa_state_machine {
  122. struct wpa_ptk PTK;
  123. Boolean PTK_valid;
  124. Boolean pairwise_set;
  125. + Boolean tk_already_set;
  126. int keycount;
  127. Boolean Pair;
  128. struct wpa_key_replay_counter {
  129. --
  130. 1.9.1
  131. From 0779537c11d18045d0f09ce3dd7f535bdb245de3 Mon Sep 17 00:00:00 2001
  132. From: Haiqing Bai <Haiqing.Bai@windriver.com>
  133. Date: Fri, 13 Oct 2017 10:00:48 +0800
  134. Subject: [PATCH 2/7] Prevent reinstallation of an already in-use group key
  135. Track the current GTK and IGTK that is in use and when receiving a
  136. (possibly retransmitted) Group Message 1 or WNM-Sleep Mode Response, do
  137. not install the given key if it is already in use. This prevents an
  138. attacker from trying to trick the client into resetting or lowering the
  139. sequence counter associated to the group key.
  140. Signed-off-by: Mathy Vanhoef <Mathy.Vanhoef@cs.kuleuven.be>
  141. Upstream-Status: Backport
  142. Signed-off-by: Haiqing Bai <Haiqing.Bai@windriver.com>
  143. ---
  144. src/common/wpa_common.h | 11 +++++
  145. src/rsn_supp/wpa.c | 118 +++++++++++++++++++++++++++++-------------------
  146. src/rsn_supp/wpa_i.h | 4 ++
  147. 3 files changed, 87 insertions(+), 46 deletions(-)
  148. diff --git a/src/common/wpa_common.h b/src/common/wpa_common.h
  149. index 091e317..66f9977 100644
  150. --- a/src/common/wpa_common.h
  151. +++ b/src/common/wpa_common.h
  152. @@ -224,6 +224,17 @@ struct wpa_ptk {
  153. size_t tk_len;
  154. };
  155. +struct wpa_gtk {
  156. + u8 gtk[WPA_GTK_MAX_LEN];
  157. + size_t gtk_len;
  158. +};
  159. +
  160. +#ifdef CONFIG_IEEE80211W
  161. +struct wpa_igtk {
  162. + u8 igtk[WPA_IGTK_MAX_LEN];
  163. + size_t igtk_len;
  164. +};
  165. +#endif /* CONFIG_IEEE80211W */
  166. /* WPA IE version 1
  167. * 00-50-f2:1 (OUI:OUI type)
  168. diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c
  169. index 8adeef4..2c4d9a4 100644
  170. --- a/src/rsn_supp/wpa.c
  171. +++ b/src/rsn_supp/wpa.c
  172. @@ -686,6 +686,15 @@ static int wpa_supplicant_install_gtk(struct wpa_sm *sm,
  173. const u8 *_gtk = gd->gtk;
  174. u8 gtk_buf[32];
  175. + /* Detect possible key reinstallation */
  176. + if (sm->gtk.gtk_len == (size_t) gd->gtk_len &&
  177. + os_memcmp(sm->gtk.gtk, gd->gtk, sm->gtk.gtk_len) == 0) {
  178. + wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
  179. + "WPA: Not reinstalling already in-use GTK to the driver (keyidx=%d tx=%d len=%d)",
  180. + gd->keyidx, gd->tx, gd->gtk_len);
  181. + return 0;
  182. + }
  183. +
  184. wpa_hexdump_key(MSG_DEBUG, "WPA: Group Key", gd->gtk, gd->gtk_len);
  185. wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
  186. "WPA: Installing GTK to the driver (keyidx=%d tx=%d len=%d)",
  187. @@ -720,6 +729,9 @@ static int wpa_supplicant_install_gtk(struct wpa_sm *sm,
  188. }
  189. os_memset(gtk_buf, 0, sizeof(gtk_buf));
  190. + sm->gtk.gtk_len = gd->gtk_len;
  191. + os_memcpy(sm->gtk.gtk, gd->gtk, sm->gtk.gtk_len);
  192. +
  193. return 0;
  194. }
  195. @@ -790,6 +802,46 @@ static int wpa_supplicant_pairwise_gtk(struct wpa_sm *sm,
  196. return 0;
  197. }
  198. +#ifdef CONFIG_IEEE80211W
  199. +static int wpa_supplicant_install_igtk(struct wpa_sm *sm,
  200. + const struct wpa_igtk_kde *igtk)
  201. +{
  202. + size_t len = wpa_cipher_key_len(sm->mgmt_group_cipher);
  203. + u16 keyidx = WPA_GET_LE16(igtk->keyid);
  204. +
  205. + /* Detect possible key reinstallation */
  206. + if (sm->igtk.igtk_len == len &&
  207. + os_memcmp(sm->igtk.igtk, igtk->igtk, sm->igtk.igtk_len) == 0) {
  208. + wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
  209. + "WPA: Not reinstalling already in-use IGTK to the driver (keyidx=%d)",
  210. + keyidx);
  211. + return 0;
  212. + }
  213. +
  214. + wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
  215. + "WPA: IGTK keyid %d pn %02x%02x%02x%02x%02x%02x",
  216. + keyidx, MAC2STR(igtk->pn));
  217. + wpa_hexdump_key(MSG_DEBUG, "WPA: IGTK", igtk->igtk, len);
  218. + if (keyidx > 4095) {
  219. + wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
  220. + "WPA: Invalid IGTK KeyID %d", keyidx);
  221. + return -1;
  222. + }
  223. + if (wpa_sm_set_key(sm, wpa_cipher_to_alg(sm->mgmt_group_cipher),
  224. + broadcast_ether_addr,
  225. + keyidx, 0, igtk->pn, sizeof(igtk->pn),
  226. + igtk->igtk, len) < 0) {
  227. + wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
  228. + "WPA: Failed to configure IGTK to the driver");
  229. + return -1;
  230. + }
  231. +
  232. + sm->igtk.igtk_len = len;
  233. + os_memcpy(sm->igtk.igtk, igtk->igtk, sm->igtk.igtk_len);
  234. +
  235. + return 0;
  236. +}
  237. +#endif /* CONFIG_IEEE80211W */
  238. static int ieee80211w_set_keys(struct wpa_sm *sm,
  239. struct wpa_eapol_ie_parse *ie)
  240. @@ -801,30 +853,14 @@ static int ieee80211w_set_keys(struct wpa_sm *sm,
  241. if (ie->igtk) {
  242. size_t len;
  243. const struct wpa_igtk_kde *igtk;
  244. - u16 keyidx;
  245. +
  246. len = wpa_cipher_key_len(sm->mgmt_group_cipher);
  247. if (ie->igtk_len != WPA_IGTK_KDE_PREFIX_LEN + len)
  248. return -1;
  249. +
  250. igtk = (const struct wpa_igtk_kde *) ie->igtk;
  251. - keyidx = WPA_GET_LE16(igtk->keyid);
  252. - wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: IGTK keyid %d "
  253. - "pn %02x%02x%02x%02x%02x%02x",
  254. - keyidx, MAC2STR(igtk->pn));
  255. - wpa_hexdump_key(MSG_DEBUG, "WPA: IGTK",
  256. - igtk->igtk, len);
  257. - if (keyidx > 4095) {
  258. - wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
  259. - "WPA: Invalid IGTK KeyID %d", keyidx);
  260. - return -1;
  261. - }
  262. - if (wpa_sm_set_key(sm, wpa_cipher_to_alg(sm->mgmt_group_cipher),
  263. - broadcast_ether_addr,
  264. - keyidx, 0, igtk->pn, sizeof(igtk->pn),
  265. - igtk->igtk, len) < 0) {
  266. - wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
  267. - "WPA: Failed to configure IGTK to the driver");
  268. - return -1;
  269. - }
  270. + if (wpa_supplicant_install_igtk(sm, igtk) < 0)
  271. + return -1;
  272. }
  273. return 0;
  274. @@ -2228,7 +2264,7 @@ void wpa_sm_deinit(struct wpa_sm *sm)
  275. */
  276. void wpa_sm_notify_assoc(struct wpa_sm *sm, const u8 *bssid)
  277. {
  278. - int clear_ptk = 1;
  279. + int clear_keys = 1;
  280. if (sm == NULL)
  281. return;
  282. @@ -2254,11 +2290,11 @@ void wpa_sm_notify_assoc(struct wpa_sm *sm, const u8 *bssid)
  283. /* Prepare for the next transition */
  284. wpa_ft_prepare_auth_request(sm, NULL);
  285. - clear_ptk = 0;
  286. + clear_keys = 0;
  287. }
  288. #endif /* CONFIG_IEEE80211R */
  289. - if (clear_ptk) {
  290. + if (clear_keys) {
  291. /*
  292. * IEEE 802.11, 8.4.10: Delete PTK SA on (re)association if
  293. * this is not part of a Fast BSS Transition.
  294. @@ -2268,6 +2304,10 @@ void wpa_sm_notify_assoc(struct wpa_sm *sm, const u8 *bssid)
  295. os_memset(&sm->ptk, 0, sizeof(sm->ptk));
  296. sm->tptk_set = 0;
  297. os_memset(&sm->tptk, 0, sizeof(sm->tptk));
  298. + os_memset(&sm->gtk, 0, sizeof(sm->gtk));
  299. +#ifdef CONFIG_IEEE80211W
  300. + os_memset(&sm->igtk, 0, sizeof(sm->igtk));
  301. +#endif /* CONFIG_IEEE80211W */
  302. }
  303. #ifdef CONFIG_TDLS
  304. @@ -2784,6 +2824,10 @@ void wpa_sm_drop_sa(struct wpa_sm *sm)
  305. os_memset(sm->pmk, 0, sizeof(sm->pmk));
  306. os_memset(&sm->ptk, 0, sizeof(sm->ptk));
  307. os_memset(&sm->tptk, 0, sizeof(sm->tptk));
  308. + os_memset(&sm->gtk, 0, sizeof(sm->gtk));
  309. +#ifdef CONFIG_IEEE80211W
  310. + os_memset(&sm->igtk, 0, sizeof(sm->igtk));
  311. +#endif /* CONFIG_IEEE80211W */
  312. #ifdef CONFIG_IEEE80211R
  313. os_memset(sm->xxkey, 0, sizeof(sm->xxkey));
  314. os_memset(sm->pmk_r0, 0, sizeof(sm->pmk_r0));
  315. @@ -2856,29 +2900,11 @@ int wpa_wnmsleep_install_key(struct wpa_sm *sm, u8 subelem_id, u8 *buf)
  316. os_memset(&gd, 0, sizeof(gd));
  317. #ifdef CONFIG_IEEE80211W
  318. } else if (subelem_id == WNM_SLEEP_SUBELEM_IGTK) {
  319. - struct wpa_igtk_kde igd;
  320. - u16 keyidx;
  321. -
  322. - os_memset(&igd, 0, sizeof(igd));
  323. - keylen = wpa_cipher_key_len(sm->mgmt_group_cipher);
  324. - os_memcpy(igd.keyid, buf + 2, 2);
  325. - os_memcpy(igd.pn, buf + 4, 6);
  326. -
  327. - keyidx = WPA_GET_LE16(igd.keyid);
  328. - os_memcpy(igd.igtk, buf + 10, keylen);
  329. -
  330. - wpa_hexdump_key(MSG_DEBUG, "Install IGTK (WNM SLEEP)",
  331. - igd.igtk, keylen);
  332. - if (wpa_sm_set_key(sm, wpa_cipher_to_alg(sm->mgmt_group_cipher),
  333. - broadcast_ether_addr,
  334. - keyidx, 0, igd.pn, sizeof(igd.pn),
  335. - igd.igtk, keylen) < 0) {
  336. - wpa_printf(MSG_DEBUG, "Failed to install the IGTK in "
  337. - "WNM mode");
  338. - os_memset(&igd, 0, sizeof(igd));
  339. - return -1;
  340. - }
  341. - os_memset(&igd, 0, sizeof(igd));
  342. + const struct wpa_igtk_kde *igtk;
  343. +
  344. + igtk = (const struct wpa_igtk_kde *) (buf + 2);
  345. + if (wpa_supplicant_install_igtk(sm, igtk) < 0)
  346. + return -1;
  347. #endif /* CONFIG_IEEE80211W */
  348. } else {
  349. wpa_printf(MSG_DEBUG, "Unknown element id");
  350. diff --git a/src/rsn_supp/wpa_i.h b/src/rsn_supp/wpa_i.h
  351. index 965a9c1..27b6123 100644
  352. --- a/src/rsn_supp/wpa_i.h
  353. +++ b/src/rsn_supp/wpa_i.h
  354. @@ -30,6 +30,10 @@ struct wpa_sm {
  355. u8 rx_replay_counter[WPA_REPLAY_COUNTER_LEN];
  356. int rx_replay_counter_set;
  357. u8 request_counter[WPA_REPLAY_COUNTER_LEN];
  358. + struct wpa_gtk gtk;
  359. +#ifdef CONFIG_IEEE80211W
  360. + struct wpa_igtk igtk;
  361. +#endif /* CONFIG_IEEE80211W */
  362. struct eapol_sm *eapol; /* EAPOL state machine from upper level code */
  363. --
  364. 1.9.1
  365. From 6e891ae64e9ec9edb17be8ca26dcf109e3250541 Mon Sep 17 00:00:00 2001
  366. From: Haiqing Bai <Haiqing.Bai@windriver.com>
  367. Date: Fri, 13 Oct 2017 10:24:29 +0800
  368. Subject: [PATCH 3/7] Extend protection of GTK/IGTK reinstallation of WNM-Sleep
  369. Mode cases
  370. This extends the protection to track last configured GTK/IGTK value
  371. separately from EAPOL-Key frames and WNM-Sleep Mode frames to cover a
  372. corner case where these two different mechanisms may get used when the
  373. GTK/IGTK has changed and tracking a single value is not sufficient to
  374. detect a possible key reconfiguration.
  375. Signed-off-by: Jouni Malinen <j@w1.fi>
  376. Upstream-Status: Backport
  377. Signed-off-by: Haiqing Bai <Haiqing.Bai@windriver.com>
  378. ---
  379. src/rsn_supp/wpa.c | 56 ++++++++++++++++++++++++++++++++++++----------------
  380. src/rsn_supp/wpa_i.h | 2 ++
  381. 2 files changed, 41 insertions(+), 17 deletions(-)
  382. diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c
  383. index 2c4d9a4..19cc78b 100644
  384. --- a/src/rsn_supp/wpa.c
  385. +++ b/src/rsn_supp/wpa.c
  386. @@ -681,14 +681,17 @@ struct wpa_gtk_data {
  387. static int wpa_supplicant_install_gtk(struct wpa_sm *sm,
  388. const struct wpa_gtk_data *gd,
  389. - const u8 *key_rsc)
  390. + const u8 *key_rsc, int wnm_sleep)
  391. {
  392. const u8 *_gtk = gd->gtk;
  393. u8 gtk_buf[32];
  394. /* Detect possible key reinstallation */
  395. - if (sm->gtk.gtk_len == (size_t) gd->gtk_len &&
  396. - os_memcmp(sm->gtk.gtk, gd->gtk, sm->gtk.gtk_len) == 0) {
  397. + if ((sm->gtk.gtk_len == (size_t) gd->gtk_len &&
  398. + os_memcmp(sm->gtk.gtk, gd->gtk, sm->gtk.gtk_len) == 0) ||
  399. + (sm->gtk_wnm_sleep.gtk_len == (size_t) gd->gtk_len &&
  400. + os_memcmp(sm->gtk_wnm_sleep.gtk, gd->gtk,
  401. + sm->gtk_wnm_sleep.gtk_len) == 0)) {
  402. wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
  403. "WPA: Not reinstalling already in-use GTK to the driver (keyidx=%d tx=%d len=%d)",
  404. gd->keyidx, gd->tx, gd->gtk_len);
  405. @@ -729,13 +732,18 @@ static int wpa_supplicant_install_gtk(struct wpa_sm *sm,
  406. }
  407. os_memset(gtk_buf, 0, sizeof(gtk_buf));
  408. - sm->gtk.gtk_len = gd->gtk_len;
  409. - os_memcpy(sm->gtk.gtk, gd->gtk, sm->gtk.gtk_len);
  410. + if (wnm_sleep) {
  411. + sm->gtk_wnm_sleep.gtk_len = gd->gtk_len;
  412. + os_memcpy(sm->gtk_wnm_sleep.gtk, gd->gtk,
  413. + sm->gtk_wnm_sleep.gtk_len);
  414. + } else {
  415. + sm->gtk.gtk_len = gd->gtk_len;
  416. + os_memcpy(sm->gtk.gtk, gd->gtk, sm->gtk.gtk_len);
  417. + }
  418. return 0;
  419. }
  420. -
  421. static int wpa_supplicant_gtk_tx_bit_workaround(const struct wpa_sm *sm,
  422. int tx)
  423. {
  424. @@ -789,7 +797,7 @@ static int wpa_supplicant_pairwise_gtk(struct wpa_sm *sm,
  425. (wpa_supplicant_check_group_cipher(sm, sm->group_cipher,
  426. gtk_len, gtk_len,
  427. &gd.key_rsc_len, &gd.alg) ||
  428. - wpa_supplicant_install_gtk(sm, &gd, key->key_rsc))) {
  429. + wpa_supplicant_install_gtk(sm, &gd, key->key_rsc, 0))) {
  430. wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
  431. "RSN: Failed to install GTK");
  432. os_memset(&gd, 0, sizeof(gd));
  433. @@ -804,14 +812,18 @@ static int wpa_supplicant_pairwise_gtk(struct wpa_sm *sm,
  434. #ifdef CONFIG_IEEE80211W
  435. static int wpa_supplicant_install_igtk(struct wpa_sm *sm,
  436. - const struct wpa_igtk_kde *igtk)
  437. + const struct wpa_igtk_kde *igtk,
  438. + int wnm_sleep)
  439. {
  440. size_t len = wpa_cipher_key_len(sm->mgmt_group_cipher);
  441. u16 keyidx = WPA_GET_LE16(igtk->keyid);
  442. /* Detect possible key reinstallation */
  443. - if (sm->igtk.igtk_len == len &&
  444. - os_memcmp(sm->igtk.igtk, igtk->igtk, sm->igtk.igtk_len) == 0) {
  445. + if ((sm->igtk.igtk_len == len &&
  446. + os_memcmp(sm->igtk.igtk, igtk->igtk, sm->igtk.igtk_len) == 0) ||
  447. + (sm->igtk_wnm_sleep.igtk_len == len &&
  448. + os_memcmp(sm->igtk_wnm_sleep.igtk, igtk->igtk,
  449. + sm->igtk_wnm_sleep.igtk_len) == 0)) {
  450. wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
  451. "WPA: Not reinstalling already in-use IGTK to the driver (keyidx=%d)",
  452. keyidx);
  453. @@ -836,9 +848,15 @@ static int wpa_supplicant_install_igtk(struct wpa_sm *sm,
  454. return -1;
  455. }
  456. - sm->igtk.igtk_len = len;
  457. - os_memcpy(sm->igtk.igtk, igtk->igtk, sm->igtk.igtk_len);
  458. -
  459. + if (wnm_sleep) {
  460. + sm->igtk_wnm_sleep.igtk_len = len;
  461. + os_memcpy(sm->igtk_wnm_sleep.igtk, igtk->igtk,
  462. + sm->igtk_wnm_sleep.igtk_len);
  463. + } else {
  464. + sm->igtk.igtk_len = len;
  465. + os_memcpy(sm->igtk.igtk, igtk->igtk, sm->igtk.igtk_len);
  466. + }
  467. +
  468. return 0;
  469. }
  470. #endif /* CONFIG_IEEE80211W */
  471. @@ -859,7 +877,7 @@ static int ieee80211w_set_keys(struct wpa_sm *sm,
  472. return -1;
  473. igtk = (const struct wpa_igtk_kde *) ie->igtk;
  474. - if (wpa_supplicant_install_igtk(sm, igtk) < 0)
  475. + if (wpa_supplicant_install_igtk(sm, igtk, 0) < 0)
  476. return -1;
  477. }
  478. @@ -1502,7 +1520,7 @@ static void wpa_supplicant_process_1_of_2(struct wpa_sm *sm,
  479. if (ret)
  480. goto failed;
  481. - if (wpa_supplicant_install_gtk(sm, &gd, key->key_rsc) ||
  482. + if (wpa_supplicant_install_gtk(sm, &gd, key->key_rsc, 0) ||
  483. wpa_supplicant_send_2_of_2(sm, key, ver, key_info))
  484. goto failed;
  485. os_memset(&gd, 0, sizeof(gd));
  486. @@ -2305,8 +2323,10 @@ void wpa_sm_notify_assoc(struct wpa_sm *sm, const u8 *bssid)
  487. sm->tptk_set = 0;
  488. os_memset(&sm->tptk, 0, sizeof(sm->tptk));
  489. os_memset(&sm->gtk, 0, sizeof(sm->gtk));
  490. + os_memset(&sm->gtk_wnm_sleep, 0, sizeof(sm->gtk_wnm_sleep));
  491. #ifdef CONFIG_IEEE80211W
  492. os_memset(&sm->igtk, 0, sizeof(sm->igtk));
  493. + os_memset(&sm->igtk_wnm_sleep, 0, sizeof(sm->igtk_wnm_sleep));
  494. #endif /* CONFIG_IEEE80211W */
  495. }
  496. @@ -2825,8 +2845,10 @@ void wpa_sm_drop_sa(struct wpa_sm *sm)
  497. os_memset(&sm->ptk, 0, sizeof(sm->ptk));
  498. os_memset(&sm->tptk, 0, sizeof(sm->tptk));
  499. os_memset(&sm->gtk, 0, sizeof(sm->gtk));
  500. + os_memset(&sm->gtk_wnm_sleep, 0, sizeof(sm->gtk_wnm_sleep));
  501. #ifdef CONFIG_IEEE80211W
  502. os_memset(&sm->igtk, 0, sizeof(sm->igtk));
  503. + os_memset(&sm->igtk_wnm_sleep, 0, sizeof(sm->igtk_wnm_sleep));
  504. #endif /* CONFIG_IEEE80211W */
  505. #ifdef CONFIG_IEEE80211R
  506. os_memset(sm->xxkey, 0, sizeof(sm->xxkey));
  507. @@ -2891,7 +2913,7 @@ int wpa_wnmsleep_install_key(struct wpa_sm *sm, u8 subelem_id, u8 *buf)
  508. wpa_hexdump_key(MSG_DEBUG, "Install GTK (WNM SLEEP)",
  509. gd.gtk, gd.gtk_len);
  510. - if (wpa_supplicant_install_gtk(sm, &gd, key_rsc)) {
  511. + if (wpa_supplicant_install_gtk(sm, &gd, key_rsc, 1)) {
  512. os_memset(&gd, 0, sizeof(gd));
  513. wpa_printf(MSG_DEBUG, "Failed to install the GTK in "
  514. "WNM mode");
  515. @@ -2903,7 +2925,7 @@ int wpa_wnmsleep_install_key(struct wpa_sm *sm, u8 subelem_id, u8 *buf)
  516. const struct wpa_igtk_kde *igtk;
  517. igtk = (const struct wpa_igtk_kde *) (buf + 2);
  518. - if (wpa_supplicant_install_igtk(sm, igtk) < 0)
  519. + if (wpa_supplicant_install_igtk(sm, igtk, 1) < 0)
  520. return -1;
  521. #endif /* CONFIG_IEEE80211W */
  522. } else {
  523. diff --git a/src/rsn_supp/wpa_i.h b/src/rsn_supp/wpa_i.h
  524. index 27b6123..51753ee 100644
  525. --- a/src/rsn_supp/wpa_i.h
  526. +++ b/src/rsn_supp/wpa_i.h
  527. @@ -31,8 +31,10 @@ struct wpa_sm {
  528. int rx_replay_counter_set;
  529. u8 request_counter[WPA_REPLAY_COUNTER_LEN];
  530. struct wpa_gtk gtk;
  531. + struct wpa_gtk gtk_wnm_sleep;
  532. #ifdef CONFIG_IEEE80211W
  533. struct wpa_igtk igtk;
  534. + struct wpa_igtk igtk_wnm_sleep;
  535. #endif /* CONFIG_IEEE80211W */
  536. struct eapol_sm *eapol; /* EAPOL state machine from upper level code */
  537. --
  538. 1.9.1
  539. From 20280c8155506da6f1fc46f4fb345bc1ddaf1684 Mon Sep 17 00:00:00 2001
  540. From: Haiqing Bai <Haiqing.Bai@windriver.com>
  541. Date: Fri, 13 Oct 2017 10:32:52 +0800
  542. Subject: [PATCH 4/7] Prevent installation of an all-zero TK
  543. Properly track whether a PTK has already been installed to the driver
  544. and the TK part cleared from memory. This prevents an attacker from
  545. trying to trick the client into installing an all-zero TK.
  546. Signed-off-by: Mathy Vanhoef <Mathy.Vanhoef@cs.kuleuven.be>
  547. Upstream-Status: Backport
  548. Signed-off-by: Haiqing Bai <Haiqing.Bai@windriver.com>
  549. ---
  550. src/common/wpa_common.h | 1 +
  551. src/rsn_supp/wpa.c | 7 +++++++
  552. 2 files changed, 8 insertions(+)
  553. diff --git a/src/common/wpa_common.h b/src/common/wpa_common.h
  554. index 66f9977..5632d37 100644
  555. --- a/src/common/wpa_common.h
  556. +++ b/src/common/wpa_common.h
  557. @@ -222,6 +222,7 @@ struct wpa_ptk {
  558. size_t kck_len;
  559. size_t kek_len;
  560. size_t tk_len;
  561. + int installed; /* 1 if key has already been installed to driver */
  562. };
  563. struct wpa_gtk {
  564. diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c
  565. index 19cc78b..97de8d3 100644
  566. --- a/src/rsn_supp/wpa.c
  567. +++ b/src/rsn_supp/wpa.c
  568. @@ -594,6 +594,12 @@ static int wpa_supplicant_install_ptk(struct wpa_sm *sm,
  569. const u8 *key_rsc;
  570. u8 null_rsc[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
  571. + if (sm->ptk.installed) {
  572. + wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
  573. + "WPA: Do not re-install same PTK to the driver");
  574. + return 0;
  575. + }
  576. +
  577. wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
  578. "WPA: Installing PTK to the driver");
  579. @@ -632,6 +638,7 @@ static int wpa_supplicant_install_ptk(struct wpa_sm *sm,
  580. /* TK is not needed anymore in supplicant */
  581. os_memset(sm->ptk.tk, 0, WPA_TK_MAX_LEN);
  582. + sm->ptk.installed = 1;
  583. if (sm->wpa_ptk_rekey) {
  584. eloop_cancel_timeout(wpa_sm_rekey_ptk, sm, NULL);
  585. --
  586. 1.9.1
  587. From 39c0043c282ea1901eb37c902f663c8ab019fc63 Mon Sep 17 00:00:00 2001
  588. From: Haiqing Bai <Haiqing.Bai@windriver.com>
  589. Date: Fri, 13 Oct 2017 10:40:31 +0800
  590. Subject: [PATCH 5/7] Fix PTK rekeying to generate a new ANonce
  591. The Authenticator state machine path for PTK rekeying ended up bypassing
  592. the AUTHENTICATION2 state where a new ANonce is generated when going
  593. directly to the PTKSTART state since there is no need to try to
  594. determine the PMK again in such a case. This is far from ideal since the
  595. new PTK would depend on a new nonce only from the supplicant.
  596. Fix this by generating a new ANonce when moving to the PTKSTART state
  597. for the purpose of starting new 4-way handshake to rekey PTK.
  598. Signed-off-by: Jouni Malinen <j@w1.fi>
  599. Upstream-Status: Backport
  600. Signed-off-by: Haiqing Bai <Haiqing.Bai@windriver.com>
  601. ---
  602. src/ap/wpa_auth.c | 22 +++++++++++++++++++---
  603. 1 file changed, 19 insertions(+), 3 deletions(-)
  604. diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c
  605. index 0ebbdb5..5084b74 100644
  606. --- a/src/ap/wpa_auth.c
  607. +++ b/src/ap/wpa_auth.c
  608. @@ -1858,6 +1858,19 @@ SM_STATE(WPA_PTK, AUTHENTICATION2)
  609. sm->TimeoutCtr = 0;
  610. }
  611. +static int wpa_auth_sm_ptk_update(struct wpa_state_machine *sm)
  612. +{
  613. + if (random_get_bytes(sm->ANonce, WPA_NONCE_LEN)) {
  614. + wpa_printf(MSG_ERROR,
  615. + "WPA: Failed to get random data for ANonce");
  616. + sm->Disconnect = TRUE;
  617. + return -1;
  618. + }
  619. + wpa_hexdump(MSG_DEBUG, "WPA: Assign new ANonce", sm->ANonce,
  620. + WPA_NONCE_LEN);
  621. + sm->TimeoutCtr = 0;
  622. + return 0;
  623. +}
  624. SM_STATE(WPA_PTK, INITPMK)
  625. {
  626. @@ -2377,9 +2390,12 @@ SM_STEP(WPA_PTK)
  627. SM_ENTER(WPA_PTK, AUTHENTICATION);
  628. else if (sm->ReAuthenticationRequest)
  629. SM_ENTER(WPA_PTK, AUTHENTICATION2);
  630. - else if (sm->PTKRequest)
  631. - SM_ENTER(WPA_PTK, PTKSTART);
  632. - else switch (sm->wpa_ptk_state) {
  633. + else if (sm->PTKRequest) {
  634. + if (wpa_auth_sm_ptk_update(sm) < 0)
  635. + SM_ENTER(WPA_PTK, DISCONNECTED);
  636. + else
  637. + SM_ENTER(WPA_PTK, PTKSTART);
  638. + } else switch (sm->wpa_ptk_state) {
  639. case WPA_PTK_INITIALIZE:
  640. break;
  641. case WPA_PTK_DISCONNECT:
  642. --
  643. 1.9.1
  644. From e1b4fa806a88ade798722fccf16ee07f6df1413a Mon Sep 17 00:00:00 2001
  645. From: Haiqing Bai <Haiqing.Bai@windriver.com>
  646. Date: Fri, 13 Oct 2017 10:55:03 +0800
  647. Subject: [PATCH 6/7] TDLS: Reject TPK-TK reconfiguration
  648. Do not try to reconfigure the same TPK-TK to the driver after it has
  649. been successfully configured. This is an explicit check to avoid issues
  650. related to resetting the TX/RX packet number. There was already a check
  651. for this for TPK M2 (retries of that message are ignored completely), so
  652. that behavior does not get modified.
  653. For TPK M3, the TPK-TK could have been reconfigured, but that was
  654. followed by immediate teardown of the link due to an issue in updating
  655. the STA entry. Furthermore, for TDLS with any real security (i.e.,
  656. ignoring open/WEP), the TPK message exchange is protected on the AP path
  657. and simple replay attacks are not feasible.
  658. As an additional corner case, make sure the local nonce gets updated if
  659. the peer uses a very unlikely "random nonce" of all zeros.
  660. Signed-off-by: Jouni Malinen <j@w1.fi>
  661. Upstream-Status: Backport
  662. Signed-off-by: Haiqing Bai <Haiqing.Bai@windriver.com>
  663. ---
  664. src/rsn_supp/tdls.c | 36 ++++++++++++++++++++++++++++++++++--
  665. 1 file changed, 34 insertions(+), 2 deletions(-)
  666. diff --git a/src/rsn_supp/tdls.c b/src/rsn_supp/tdls.c
  667. index c1d7749..8633b8f 100644
  668. --- a/src/rsn_supp/tdls.c
  669. +++ b/src/rsn_supp/tdls.c
  670. @@ -111,6 +111,7 @@ struct wpa_tdls_peer {
  671. u8 tk[16]; /* TPK-TK; assuming only CCMP will be used */
  672. } tpk;
  673. int tpk_set;
  674. + int tk_set; /* TPK-TK configured to the driver */
  675. int tpk_success;
  676. int tpk_in_progress;
  677. @@ -191,6 +192,20 @@ static int wpa_tdls_set_key(struct wpa_sm *sm, struct wpa_tdls_peer *peer)
  678. u8 rsc[6];
  679. enum wpa_alg alg;
  680. + if (peer->tk_set) {
  681. + /*
  682. + * This same TPK-TK has already been configured to the driver
  683. + * and this new configuration attempt (likely due to an
  684. + * unexpected retransmitted frame) would result in clearing
  685. + * the TX/RX sequence number which can break security, so must
  686. + * not allow that to happen.
  687. + */
  688. + wpa_printf(MSG_INFO, "TDLS: TPK-TK for the peer " MACSTR
  689. + " has already been configured to the driver - do not reconfigure",
  690. + MAC2STR(peer->addr));
  691. + return -1;
  692. + }
  693. +
  694. os_memset(rsc, 0, 6);
  695. switch (peer->cipher) {
  696. @@ -208,12 +223,15 @@ static int wpa_tdls_set_key(struct wpa_sm *sm, struct wpa_tdls_peer *peer)
  697. return -1;
  698. }
  699. + wpa_printf(MSG_DEBUG, "TDLS: Configure pairwise key for peer " MACSTR,
  700. + MAC2STR(peer->addr));
  701. if (wpa_sm_set_key(sm, alg, peer->addr, -1, 1,
  702. rsc, sizeof(rsc), peer->tpk.tk, key_len) < 0) {
  703. wpa_printf(MSG_WARNING, "TDLS: Failed to set TPK to the "
  704. "driver");
  705. return -1;
  706. }
  707. + peer->tk_set = 1;
  708. return 0;
  709. }
  710. @@ -689,7 +707,7 @@ static void wpa_tdls_peer_clear(struct wpa_sm *sm, struct wpa_tdls_peer *peer)
  711. peer->cipher = 0;
  712. peer->qos_info = 0;
  713. peer->wmm_capable = 0;
  714. - peer->tpk_set = peer->tpk_success = 0;
  715. + peer->tk_set = peer->tpk_set = peer->tpk_success = 0;
  716. peer->chan_switch_enabled = 0;
  717. os_memset(&peer->tpk, 0, sizeof(peer->tpk));
  718. os_memset(peer->inonce, 0, WPA_NONCE_LEN);
  719. @@ -1152,6 +1170,7 @@ skip_rsnie:
  720. wpa_tdls_peer_free(sm, peer);
  721. return -1;
  722. }
  723. + peer->tk_set = 0; /* A new nonce results in a new TK */
  724. wpa_hexdump(MSG_DEBUG, "TDLS: Initiator Nonce for TPK handshake",
  725. peer->inonce, WPA_NONCE_LEN);
  726. os_memcpy(ftie->Snonce, peer->inonce, WPA_NONCE_LEN);
  727. @@ -1747,6 +1766,17 @@ static int wpa_tdls_addset_peer(struct wpa_sm *sm, struct wpa_tdls_peer *peer,
  728. peer->supp_oper_classes_len);
  729. }
  730. +static int tdls_nonce_set(const u8 *nonce)
  731. +{
  732. + int i;
  733. +
  734. + for (i = 0; i < WPA_NONCE_LEN; i++) {
  735. + if (nonce[i])
  736. + return 1;
  737. + }
  738. +
  739. + return 0;
  740. +}
  741. static int wpa_tdls_process_tpk_m1(struct wpa_sm *sm, const u8 *src_addr,
  742. const u8 *buf, size_t len)
  743. @@ -2001,7 +2031,8 @@ skip_rsn:
  744. peer->rsnie_i_len = kde.rsn_ie_len;
  745. peer->cipher = cipher;
  746. - if (os_memcmp(peer->inonce, ftie->Snonce, WPA_NONCE_LEN) != 0) {
  747. + if (os_memcmp(peer->inonce, ftie->Snonce, WPA_NONCE_LEN) != 0 ||
  748. + !tdls_nonce_set(peer->inonce)) {
  749. /*
  750. * There is no point in updating the RNonce for every obtained
  751. * TPK M1 frame (e.g., retransmission due to timeout) with the
  752. @@ -2017,6 +2048,7 @@ skip_rsn:
  753. "TDLS: Failed to get random data for responder nonce");
  754. goto error;
  755. }
  756. + peer->tk_set = 0; /* A new nonce results in a new TK */
  757. }
  758. #if 0
  759. --
  760. 1.9.1
  761. From 6d966716df42d379c0aaa1b833f070b93a29aaec Mon Sep 17 00:00:00 2001
  762. From: Haiqing Bai <Haiqing.Bai@windriver.com>
  763. Date: Fri, 13 Oct 2017 11:07:21 +0800
  764. Subject: [PATCH 7/7] FT: Do not allow multiple Reassociation Response frames
  765. The driver is expected to not report a second association event without
  766. the station having explicitly request a new association. As such, this
  767. case should not be reachable. However, since reconfiguring the same
  768. pairwise or group keys to the driver could result in nonce reuse issues,
  769. be extra careful here and do an additional state check to avoid this
  770. even if the local driver ends up somehow accepting an unexpected
  771. Reassociation Response frame.
  772. Signed-off-by: Jouni Malinen <j@w1.fi>
  773. Upstream-Status: Backport
  774. Signed-off-by: Haiqing Bai <Haiqing.Bai@windriver.com>
  775. ---
  776. src/rsn_supp/wpa.c | 3 +++
  777. src/rsn_supp/wpa_ft.c | 8 ++++++++
  778. src/rsn_supp/wpa_i.h | 1 +
  779. 3 files changed, 12 insertions(+)
  780. diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c
  781. index 97de8d3..b9c1ab5 100644
  782. --- a/src/rsn_supp/wpa.c
  783. +++ b/src/rsn_supp/wpa.c
  784. @@ -2366,6 +2366,9 @@ void wpa_sm_notify_disassoc(struct wpa_sm *sm)
  785. #ifdef CONFIG_TDLS
  786. wpa_tdls_disassoc(sm);
  787. #endif /* CONFIG_TDLS */
  788. +#ifdef CONFIG_IEEE80211R
  789. + sm->ft_reassoc_completed = 0;
  790. +#endif /* CONFIG_IEEE80211R */
  791. /* Keys are not needed in the WPA state machine anymore */
  792. wpa_sm_drop_sa(sm);
  793. diff --git a/src/rsn_supp/wpa_ft.c b/src/rsn_supp/wpa_ft.c
  794. index 06dea05..e8834dd 100644
  795. --- a/src/rsn_supp/wpa_ft.c
  796. +++ b/src/rsn_supp/wpa_ft.c
  797. @@ -153,6 +153,7 @@ static u8 * wpa_ft_gen_req_ies(struct wpa_sm *sm, size_t *len,
  798. u16 capab;
  799. sm->ft_completed = 0;
  800. + sm->ft_reassoc_completed = 0;
  801. buf_len = 2 + sizeof(struct rsn_mdie) + 2 + sizeof(struct rsn_ftie) +
  802. 2 + sm->r0kh_id_len + ric_ies_len + 100;
  803. @@ -683,6 +684,11 @@ int wpa_ft_validate_reassoc_resp(struct wpa_sm *sm, const u8 *ies,
  804. return -1;
  805. }
  806. + if (sm->ft_reassoc_completed) {
  807. + wpa_printf(MSG_DEBUG, "FT: Reassociation has already been completed for this FT protocol instance - ignore unexpected retransmission");
  808. + return 0;
  809. + }
  810. +
  811. if (wpa_ft_parse_ies(ies, ies_len, &parse) < 0) {
  812. wpa_printf(MSG_DEBUG, "FT: Failed to parse IEs");
  813. return -1;
  814. @@ -783,6 +789,8 @@ int wpa_ft_validate_reassoc_resp(struct wpa_sm *sm, const u8 *ies,
  815. return -1;
  816. }
  817. + sm->ft_reassoc_completed = 1;
  818. +
  819. if (wpa_ft_process_gtk_subelem(sm, parse.gtk, parse.gtk_len) < 0)
  820. return -1;
  821. diff --git a/src/rsn_supp/wpa_i.h b/src/rsn_supp/wpa_i.h
  822. index 51753ee..85cc862 100644
  823. --- a/src/rsn_supp/wpa_i.h
  824. +++ b/src/rsn_supp/wpa_i.h
  825. @@ -127,6 +127,7 @@ struct wpa_sm {
  826. size_t r0kh_id_len;
  827. u8 r1kh_id[FT_R1KH_ID_LEN];
  828. int ft_completed;
  829. + int ft_reassoc_completed;
  830. int over_the_ds_in_progress;
  831. u8 target_ap[ETH_ALEN]; /* over-the-DS target AP */
  832. int set_ptk_after_assoc;
  833. --
  834. 1.9.1